NOTICE: By continued use of this site you understand and agree to the binding Terms of Service and Privacy Policy.
// ==UserScript== // @name RedditRaffle // @namespace redditraffle // @include http://www.reddit.com/r/*/comments/* // @version 1.4 // @grant GM_xmlhttpRequest // @grant GM_addStyle // ==/UserScript== var link, url, winner_count, author_exclude, keyword_included, keyword_excluded, karma_link, karma_comment, age = 0., total_comments, comments = [], more = [], more_lock = false, parse_lock = false, names = [], chosen = [], userinfo, query_timeout, connection_count = 0; function render_results() { progress.innerHTML = "Rendering:"; var html = []; html.push("<!doctype html><meta charset=\"utf-8\" /><title>Raffle results</title>" + "<style>table{overflow:hidden;border:1px solid #d3d3d3;background:#fefefe;" + "width:70%;margin:5% auto 0;-moz-border-radius:5px;-webkit-border-radius:5px;" + "border-radius:5px;-moz-box-shadow: 0 0 4px rgba(0, 0, 0, 0.2);" + "-webkit-box-shadow: 0 0 4px rgba(0, 0, 0, 0.2);}th,td{text-align:center;}" + "th{padding:14px 22px;text-shadow: 1px 1px 1px #fff;background:#e8eaeb;}" + "td{border-top:1px solid #e0e0e0;border-right:1px solid #e0e0e0;}" + "tr:nth-child(odd) td{background:#f6f6f6;}td:last-child{border-right:none;" + "text-align:left;padding:8px 18px;}</style><table><tr><th>No.</th><th>User</th>" + "<th>Comment</th></tr>"); var winner_length = Math.min(winner_count, chosen.length); for(var i = 0; i < winner_length; i++) { html.push("<tr><td>" + (i + 1) + ".</td><td><a href=\"http://www.reddit.com/user/" + chosen[i].author + "\">" + chosen[i].author + "</a></td><td>"); html.push(chosen[i].body_html.replace(/</g,'<').replace(/>/g,'>').replace(/&/g,'&')); html.push("<br /><a href=\"" + url + chosen[i].id + "\">Show</a></td><tr>"); } html.push("</table>"); progress.innerHTML = "<a href=\"" + URL.createObjectURL(new Blob(html, {type : 'text/html'})) + "\" target=\"_new\">Show results</a>"; } function query_users() { if(more_lock || parse_lock) return; query_interval = window.setInterval(function() { if(chosen.length >= winner_count || !comments.length) { window.clearInterval(query_interval); render_results(); return; } if(connection_count > 10) return; var comment = comments.splice(Math.floor(Math.random() * comments.length), 1)[0]; if(comment === undefined || comment.body.toLowerCase().indexOf(keyword_included) < 0 || (keyword_excluded && !(comment.body.toLowerCase().indexOf(keyword_excluded) < 0)) || (author_exclude && comment.author === author_exclude) || !(names.indexOf(comment.author) < 0)) return; if(age || karma_link || karma_comment) { GM_xmlhttpRequest({ method: 'GET', url: 'http://www.reddit.com/user/' + comment.author + '/about.json', context: comment, onload: function(response) { connection_count--; userinfo = JSON.parse(response.responseText).data; if((!age || userinfo.created_utc <= age) && userinfo.link_karma >= karma_link && userinfo.comment_karma >= karma_comment && chosen.length < winner_count && names.indexOf(comment.author) < 0) { names.push(userinfo.name); chosen.push(response.context); progress.innerHTML = "Querying Users: " + chosen.length + "/" + winner_count; } }, onerror: function(error) { connection_count--; console.log(error); }, }); connection_count++; } else { names.push(comment.author); chosen.push(comment); progress.innerHTML = "Querying Users: " + chosen.length + "/" + winner_count; } }, 100); } function add_comment(comment) { comments.push(comment); if(comment.replies && comment.replies.kind === "Listing") parse_listing(comment.replies.data.children); } function add_more(children) { more.push.apply(more, children); if(!more_lock) parse_more(); } function parse_more() { if(!more.length) { more_lock = false; query_users(); return; } more_lock = true; var children = more.splice(0, 20); GM_xmlhttpRequest({ method: 'POST', url: 'http://www.reddit.com/api/morechildren.json', headers: { "Content-Type": "application/x-www-form-urlencoded" }, data: 'link_id=' + link + '&api_type=json&children=' + children.join(), onload: function(response) { parse_listing(JSON.parse(response.responseText).json.data.things); progress.innerHTML = "Parsing Comments: " + comments.length + "/" + total_comments; parse_more(); }, enerror: function(error) { more.push.apply(more, children); console.log("Error:", error); parse_more(); } }); } function parse_listing(listing) { var listingLength = listing.length; for(var child = 0; child < listingLength; child++) { if (listing[child].kind === 't1') add_comment(listing[child].data); else if (listing[child].kind === 't3') { link = listing[child].data.name; author_exclude = form.elements.author_exclude.checked ? listing[child].data.author : ""; total_comments = listing[child].data.num_comments; progress.innerHTML = "Parsing Comments: 0/" + total_comments; } else if (listing[child].kind === 'more') add_more(listing[child].data.children); } } function do_raffle() { progress.innerHTML = "Parsing Comments:"; winner_count = parseInt(form.elements.winner_count.value) || 20; keyword_included = form.elements.keyword_included.value.toLowerCase(); keyword_excluded = form.elements.keyword_excluded.value.toLowerCase(); karma_link = parseInt(form.elements.karma_link.value) || 0; karma_comment = parseInt(form.elements.karma_comment.value) || 0; if(form.elements.age_days.value || form.elements.age_month.value || form.elements.age_years.value) { var date = new Date(); date.setDate(date.getDate() - (parseInt(form.elements.age_days.value) || 0)); date.setMonth(date.getMonth() - (parseInt(form.elements.age_month.value) || 0)); date.setFullYear(date.getFullYear() - (parseInt(form.elements.age_years.value) || 0)); age = date.getTime()/1000; } url = window.location.href; if(!(url.indexOf("?") < 0)) { url = url.substring(0, url.indexOf("?")); } parse_lock = true; GM_xmlhttpRequest({ method: 'POST', url: url + '.json', headers: { "Content-Type": "application/x-www-form-urlencoded" }, data: 'limit=500', onload: function(response) { var things = JSON.parse(response.responseText), thingsLength = things.length for(var thing = 0; thing < thingsLength; thing++) if (things[thing].kind === 'Listing') parse_listing(things[thing].data.children); parse_lock = false; query_users(); }, }); } GM_addStyle("#raffle_form input[type=text]{\ width:265px;\ border:1px solid #DBDADA;\ -moz-border-radius:2px;\ -webkit-border-radius:2px;\ -o-border-radius:2px;\ -ms-border-radius:2px;\ -khtml-border-radius:2px;\ border-radius:2px;\ font-size:14px;\ font-style:italic;\ padding:4px\ }"); var spacer = document.createElement("div"); spacer.classList.add("spacer"); spacer.innerHTML = "<div class=\"sidecontentbox \">\ <div class=\"title\"><h1>Raffle</h1></div>\ <form id=\"raffle_form\">\ <ul class=\"content\">\ <li><input type=\"text\" placeholder=\"Number of Winners\" name=\"winner_count\" /></li>\ <li><input type=\"text\" placeholder=\"Comments containing\" name=\"keyword_included\" /></li>\ <li><input type=\"text\" placeholder=\"Comments not containing\" name=\"keyword_excluded\" /></li>\ <li><input type=\"text\" placeholder=\"Required Link Karma\" name=\"karma_link\" /></li>\ <li><input type=\"text\" placeholder=\"Required Comment Karma\" name=\"karma_comment\" /></li>\ <li><input type=\"text\" placeholder=\"Age in Days\" name=\"age_days\" /></li>\ <li><input type=\"text\" placeholder=\"Age in Months\" name=\"age_month\" /></li>\ <li><input type=\"text\" placeholder=\"Age in Years\" name=\"age_years\" /></li>\ <li>\ <button class=\"save\" type=\"button\">Raffle</button>\ <input type=\"checkbox\" name=\"author_exclude\" id=\"author_exclude\" checked=\"checked\"/>\ <label for=\"author_exclude\">Exclude Author</label>\ </li>\ <li><span id=\"raffle_progress\"></span></li>\ </ul>\ </form>\ </div>"; var form = spacer.querySelector("form#raffle_form"), progress = spacer.querySelector("span#raffle_progress"); document.querySelector("div.side").appendChild(spacer); form.querySelector("button").addEventListener("click", do_raffle, true);