Skip to content

Instantly share code, notes, and snippets.

@sheep0x
Created March 9, 2016 21:04
Show Gist options
  • Save sheep0x/0865c21559469aa46721 to your computer and use it in GitHub Desktop.
Save sheep0x/0865c21559469aa46721 to your computer and use it in GitHub Desktop.
/*
* 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