Created
March 9, 2016 21:04
-
-
Save sheep0x/0865c21559469aa46721 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* Hacker: Chen Ruichao <sheep0x@berkeley.edu> | |
* Date: 2016-02-02 -0800 | |
* | |
* Much of the code comes from Piazza, so maybe the copyright of this code | |
* belongs to them. In case parts of the hack can be attributed to me, you | |
* may assume the Apache License, Version 2.0. | |
* Disclaimer: I'm not a lawyer and what's written above is probably not | |
* legally effective. | |
*/ | |
// everything should have been based on http://piazza.com/js/splash/join.js?v=1313 (as of 2016-02-02 -0800) | |
// What this script does: quickly joins a whole bunch of Piazza forums. | |
// Instructions: | |
// - Log in on Piazza | |
// - Navigate to https://piazza.com/signup/berkeley | |
// - Copy-paste this big function into browser's console, then run it. | |
// Don't start until page is fully(?) loaded. | |
// Don't interrupt with mouse/keyboard. Not sure if it will be a problem. | |
function sheep0x_addWhateverAcceptibleClassWithEmulation() { | |
/* instead of finding a bunch of classes and drawing the auto-completion box every time, | |
* we "find" (almost) all classes at once, and then "auto-complete" one at a time. | |
*/ | |
var classes_to_add = sheep0x_filterClassSearch(); | |
/* | |
for (var i = 0; i < classes_to_add.length; i++) { | |
var c = classes_to_add[i]; | |
add_a_class(c); | |
} | |
*/ | |
// the function below does the same loop with some "sleep" between iterations. | |
(function () { | |
var i = 0; | |
singlethreaded_js_is_stupid(); | |
function singlethreaded_js_is_stupid() { | |
if (i >= classes_to_add.length) { return; } | |
console.log(i); | |
var c = classes_to_add[i]; | |
add_a_class(c); | |
i++; setTimeout(singlethreaded_js_is_stupid, 100); | |
} | |
})(); | |
function add_a_class(c) { | |
// emulation: clicking "Add Another Class" | |
// code from: $(document).ready() > $('.add_more a').click() | |
addClassSection(false); | |
$('#new-classes .class:last-child .autosuggest input[type="text"]').focus(); | |
// emulation: auto-complete (without typing anything) | |
// code from: $(document).on("keyup", ".autosuggest input", ) > else (none of Enter, Up, Down) | |
/* | |
* } else { | |
* filterClassSearch($(this)); | |
* return true; | |
* } | |
* | |
* "return true" is ignored because the only other bound event I found was Tab => go to next input box | |
*/ | |
//var sheep0x_fake_classResult =[c]; | |
classResult = [c]; // in order to counter the effect of "clearSearchStatus()", called when a class search is done | |
//buggy: var sheep0x_fake_this = $(".autosuggest input").first(); | |
var sheep0x_fake_this = $(".autosuggest input:visible").first(); // only a workaround. Don't know why :focus won't work. | |
sheep0x_fake_this.val(c.name); | |
sheep0x_autocomplete(sheep0x_fake_this/*, sheep0x_fake_classResult*/); | |
// emulation: pressing Down twice (selecting the first suggestion) | |
// code from: $(document).on("keyup", ".autosuggest input", ) > else if(keyCode === 40) | |
/* | |
// --> pressing once... | |
sheep0x_fake_this.closest('.autosuggest').find('ul.autosuggest-default li').addClass('keypress-selected'); | |
// --> pressing the second time... | |
var $selected = sheep0x_fake_this.closest('.autosuggest').find('li.keypress-selected'); | |
var $next = $selected.next('li'); | |
if($next.length === 1) { | |
$selected.removeClass('keypress-selected'); | |
$next.addClass('keypress-selected'); | |
} else if($selected.parent().is('.autosuggest-default')) { | |
$selected.removeClass('keypress-selected'); | |
sheep0x_fake_this.closest('.autosuggest').find('ul.autosuggest-results li').first().addClass('keypress-selected'); | |
} | |
*/ | |
/* | |
// "$selected" was modified so that we don't have to select a dummy suggestion before selecting the real one | |
var $selected = sheep0x_fake_this.closest('.autosuggest').find('ul.autosuggest-default li') | |
var $next = $selected.next('li'); | |
if($next.length === 1) { | |
$next.addClass('keypress-selected'); | |
} else if($selected.parent().is('.autosuggest-default')) { | |
sheep0x_fake_this.closest('.autosuggest').find('ul.autosuggest-results li').first().addClass('keypress-selected'); | |
} | |
*/ | |
sheep0x_fake_this.closest('.autosuggest').find('ul.autosuggest-results li').first().addClass('keypress-selected'); | |
// emulation: pressing Enter | |
// code from: $(document).on("keyup", ".autosuggest input", ) > if(keyCode === 13) | |
var $selected = sheep0x_fake_this.closest('.autosuggest').find('li.keypress-selected'); | |
$selected.click(); | |
// emulation: find the radio buttons of "Join as" and click "Student" | |
// Finding is hard-coded. The click() is emulated. | |
sheep0x_fake_this.closest(".container").find("input[type=radio].role_stud").click(); | |
// And we are done with this class. The loop goes on and we add all classes we want. | |
} | |
// emulation: click "Join Classes" | |
// Finding is hard-coded. The click() is emulated. | |
// May fail if some fields are empty. May be ignored if no classes are to be added. | |
/* | |
* Since I prefer to double check before committing the actions, I decided to click that button myself. | |
* $("#enroll_btn").click(); | |
*/ | |
// what this does: find all classes we may want to add | |
// emulation: first half of auto-completion (without typing anything) | |
// code from: function filterClassSearch(obj) | |
function sheep0x_filterClassSearch() { | |
classResult = []; // sheep0x: wat. global var? | |
for (var x = 0; x < allClasses.length; x++) { | |
var net = allClasses[x]; | |
var sheep0x_classAndTerm = net.cn + "_" + selectedTerm; | |
if (classHave[net.cn + "_" + selectedTerm]) { | |
console.log("classHave: Skipping " + sheep0x_classAndTerm); | |
continue; | |
} | |
var name = net.cn + ": " + net.n; | |
var toks = name.split(/\s/); | |
// sheep0x: I'd rather manually drop what I don't want to join | |
/* | |
// sheep0x: filter out some classes | |
var unwanted_regexps = [/TA/, /GSI/, /Staff/]; | |
var want = true; | |
for (var i = 0; i < unwanted_regexps.length && want; i++) { | |
for (var j = 0; j < toks.length && want; j++) { | |
if (toks[j].match(unwanted_regexps[i])) { | |
want = false; | |
} | |
} | |
} | |
if (!want) continue; // Todo: console.log | |
*/ | |
// sheep0x: We may remove this line to access more classes, but that's not worth the risk. If Piazza changes the code, I'll have to hack it again. | |
if (!net.terms || !net.terms[selectedTerm] || !profExists(net.terms[selectedTerm])) { | |
console.log("net.terms and profExists: Skipping " + sheep0x_classAndTerm); | |
continue; | |
} | |
var obj = {name:name, org:net, terms:net.terms}; | |
classResult.push(obj); | |
} | |
classResult = classResult.sort(function(a,b) { | |
if (a.name > b.name) return 1; | |
if (a.name < b.name) return -1; | |
return 0; | |
}); | |
return classResult; | |
} | |
// what this does: add 1 class to auto-completion results | |
// emulation: second half of auto-completion (without typing anything) | |
// code from: function filterClassSearch(obj) | |
function sheep0x_autocomplete(obj/*, classResult*/) { | |
var theStr = obj.val(); | |
var theClass = obj.closest('.class'); | |
// else { | |
var html = ""; | |
for (var i = 0; i < classResult.length; i++) { | |
var gray = ""; | |
var count = ""; | |
var cnt = 0; | |
var term = {} | |
if (classResult[i].terms && classResult[i].terms[selectedTerm]) term = classResult[i].terms[selectedTerm]; | |
if (term.cnt) | |
cnt = term.cnt; | |
//var prof = classResult[i].prof; | |
if (cnt != null) | |
if (cnt > 0 && profExists(term)) | |
count = cnt + " Enrolled"; | |
html += '<li onclick="return addClass(' + i + ',this)">'; | |
html += '<div class="autosuggest-count">' + count +'</div>'; | |
html += '<span class="autosuggest-class-name' + gray + '">' + classResult[i].name + '</span>'; | |
html += '</li>'; | |
} | |
if (classResult.length == 0) { | |
$('.class.active .autosuggest-default').addClass('highlighted'); | |
} else { | |
$('.class.active .autosuggest-default').removeClass('highlighted'); | |
} | |
theClass.find('.autosuggest-results').html(html); | |
theClass.find('.autosuggest-box').show(); | |
theClass.find('.autosuggest-input').text(theStr); | |
// } | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment