NOTICE: By continued use of this site you understand and agree to the binding Terms of Service and Privacy Policy.
// ==UserScript== // @name inflatable switchblade // @namespace agentOfChaos // @description Adds a button linking directly to the current strip's reactions page on sluggy.net // @include http://www.sluggy.com/* // @version 1.1 // @grant GM_xmlhttpRequest // @author agentOfChaos // ==/UserScript== /* * Author: agentOfChaos * All the code is GPLv3 * enjoy! */ var $ = unsafeWindow.jQuery; var basePage; var updatepage="http://feeds.feedburner.com/sluggy_freelance?format=xml"; var homepage="http://www.sluggy.com/"; var update_timeout = 8000; var etag,lastModified; var starting_hour; var base="http://www.sluggy.net/forum/"; var months=["January","February","March","April","May","June","July","August","September","October","November","December"]; var baseURL="http://www.sluggy.net/forum/viewforum.php?f=4&start="; var interruptSearch=false; var target="Daily"; var numreq; //// begin of reaction link locator code function deltaG( date2, date1 ) { //Get 1 day in milliseconds var one_day=1000*60*60*24; // Convert both dates to milliseconds var date1_ms = date1.getTime(); var date2_ms = date2.getTime(); // Calculate the difference in milliseconds var difference_ms = date2_ms - date1_ms; // Convert back to days and return return Math.round(difference_ms/one_day); } function arrot(val, notch) { var divis=Math.floor(val/notch); return divis*notch; } function dateFromSlugURL(url) { var sect=url.split("/"); var len=sect.length; var offset=0; var datestr=sect[len-1]; var ys,ms,ds,year,day,month; var date; if (len<=6) return new Date(); // homepage: set date as "today" if (datestr.length>6)offset=2; // year is 4-digit: read only last 2 ys=datestr.substr(0+offset,2); ms=datestr.substr(2+offset,2); ds=datestr.substr(4+offset,2); if (ys>=97) // sluggy won't run ~100 years, or will it? { year="19" + ys; } else year="20" + ys; month=ms-1; day=ds; date=new Date(year,month,day); return date; } function getBBpageId(today, stripdate) { var delta=deltaG(new Date(2014,8,31),new Date(2004,12,15)); var adjust = 2940 / delta; var dist = deltaG(today,stripdate); console.log("delta: "+delta + " ; approx. location: "+arrot(dist * adjust,20)); return arrot(dist * adjust,20); } function spiral(num) // maps number set N to Z { if (num%2===0) return num/2; else return -((num+1)/2); } function find_string(mbody,tgt) { if (mbody.match(tgt)) return true; else return false; } function run_search(cont) { var num=spiral(cont); var loc=basePage+(num*20); var url=baseURL + loc; // request page via XMLHTTP if (loc < 0) return; console.log("Beginning request "+url); GM_xmlhttpRequest({ method: "GET", url: url, headers: { "User-Agent": "Mozilla/5.0", // If not specified, navigator.userAgent will be used. "Accept": "text/html" // If not specified, browser defaults will be used. }, onload: function(response) { var code=response.responseText; if (find_string(code,target)) { interruptSearch=true; console.log("found: " + code.substr(0,100) + " ..."); extract_link(code); } } }); numreq++; } function extract_link(code) { console.log("extracting link..."); var box=document.createElement("div"); // create a dummy html element for processing var items; var dest; box.innerHTML=code; items=box.getElementsByTagName("a"); console.log("elements: "+items.length); for (var cont=0; cont<items.length; cont++) // scan every <a> element for target { if (find_string(items[cont].innerHTML,target)) { console.log("final url: "+items[cont].href); dest=items[cont].href.split("/"); UI_buttonGo(base+dest[dest.length-1]); break; } } console.log("done!"); } function loop_search(radius) { var stop=(2*radius)+1; var pos; numreq=0; for (var cont=0; cont<stop && !interruptSearch; cont++) { console.log("searching ..." + cont); run_search(cont); } } //// end of reaction link locator code //// begin of ref link crawler code function fetch_reflink(popup) { var ret = new Array(500); if (popup.length > 0) { var links = popup.find("a"); var cont = 0; for (var c=0; c<links.length; c++) { urlo = $(links[c]).attr("href"); if (urlo.charAt(0) == "/") { ret[cont] = links[c]; cont++; } } } else { console.log("no refs to fetch"); } return ret; } function visitLink(link) { var url = $(link).attr("href"); GM_xmlhttpRequest({ method: "GET", url: url, headers: { "User-Agent": "Mozilla/5.0", // If not specified, navigator.userAgent will be used. "Accept": "text/html" // If not specified, browser defaults will be used. }, onload: function(data){ updateLink($(link),data.responseText); } }); } function updateLink(link, code) { var deposit = document.createElement("div"); // create a dummy html element for processing deposit.innerHTML = code; var imgs_code = $($(deposit).find(".comic_content")[0]).html(); var img_url = $($($(deposit).find(".comic_content")[0]).find("img")[0]).attr("src"); $(link).removeAttr("href"); $(link).attr("id",img_url.split("/").pop().split(".")[0]); $(link).css("text-decoration","underline"); $(link).css("color","blue"); document.getElementById(img_url.split("/").pop().split(".")[0]).addEventListener('click', function(){showRef(imgs_code, img_url, $(link));}, true); $(link).attr("target","self"); } function refPreloader(popup) { links = fetch_reflink(popup); for (var cont=0; cont<links.length; cont++) { console.log("exploring ref " + $(links[cont]).attr("href")); visitLink(links[cont]); } } //// end of ref link crawler //// update checker function engage_updater() { GM_xmlhttpRequest({ method: "HEAD", url: updatepage, onload: function(data){ headers = data.responseHeaders.split("\n"); storeHeadersNgo(headers); } }); } function storeHeadersNgo(headers) { var s_et = "Etag: "; var s_lm = "Last-Modified: "; var s_tm = "Date: "; var timestr,serverdate,localdate,s_hour,s_minute,deltam; for (var n in headers) { h = headers[n]; if (h.indexOf(s_et) === 0) {etag = h.substr(s_et.length);} else if (h.indexOf(s_lm) === 0) {lastModified = h.substr(s_lm.length);} else if (h.indexOf(s_tm) === 0) {timestr = h.substr(s_tm.length);} } serverdate = new Date(timestr); localdate = new Date(); s_hour = serverdate.getUTCHours(); s_minute = serverdate.getUTCMinutes(); console.log("server reports date: " + timestr); deltam = ((24-s_hour)*60) + (60 - s_minute) - 1; if (s_hour <= 2) { console.log("starting update check now!"); window.setTimeout(function(){ starting_hour = localdate.getHour(); check_updates(); },update_timeout); } else { console.log("starting update check in " + deltam + " minutes"); window.setTimeout(function(){ starting_hour = localdate.getHour(); check_updates(); },deltam*60000); } } function compareHeaders(headers) { var s_et = "Etag: "; var s_lm = "Last-Modified: "; var t_etag; var t_lastModified; for (var n in headers) { h = headers[n]; if (h.indexOf(s_et) === 0) {t_etag = h.substr(s_et.length);} else if (h.indexOf(s_lm) === 0) {t_lastModified = h.substr(s_lm.length);} } if ((lastModified == t_lastModified) && (etag==t_etag)) return true; return false; } function check_updates() { var localdate = new Date(); GM_xmlhttpRequest({ method: "HEAD", url: updatepage, onload: function(data){ code = data.status; cmp = compareHeaders(data.responseHeaders.split("\n")); if (cmp === false) location.reload(); else { if (localdate.getHour() - starting_hour < 3) window.setTimeout(function(){check_updates()},update_timeout); } } }); } //// end of update checker //// estetic functions function UI_buttonWait() // create dummy button while fetching the url { $(".buttons.fg-buttonset").prepend("<a id=\"locutus\" class=\"fg-button fg-button-icon-left ui-corner-all ui-state-default\" href=\"#\"><span class=\"ui-icon ui-icon-help\"></span>Reactions</a>"); } function UI_buttonGo(link) // create real button now { $("#locutus").remove(); $(".buttons.fg-buttonset").prepend("<a target=\"_blank\" id=\"locutus\" class=\"fg-button fg-button-icon-left ui-corner-all ui-state-default\" href=\""+link+"\"><span class=\"ui-icon ui-icon-comment\"></span>Reactions</a>"); } function UI_buttonVote() // add vote button { $(".buttons.fg-buttonset").prepend("<a target=\"_blank\" class=\"fg-button fg-button-icon-left ui-corner-all ui-state-default\" href=\"http://topwebcomics.com/vote/14089/default.aspx\"><span class=\"ui-icon ui-icon-help\"></span>Vote!</a>"); } function UI_navarea_grow() // expand the navbar to accomodate new buttons { $("#comic_navigation").css("width","860px"); $(".fg-buttonset").css("margin-left","50px"); } //// end of estetic functions function showRef(imgs_code, urlz, link) // manages opening / closing of "quick refs" { var attr = $(link).attr("opened"); var url = urlz.replace(/\./g,"").replace(/\//g,"") if (typeof attr !== 'undefined' && attr !== false) { var ou = $(link).attr("opened_url") if (ou == url) { $(link).removeAttr("opened") $(link).removeAttr("opened_url") $(link).css("color","blue") //$(".comic_popup").css("max-width",oldmwidth) $("#quickrefimage_" + url).remove() } } else { $(link).attr("opened","true") $(link).attr("opened_url",url) $(link).css("color","red") //oldmwidth = $(".comic_popup").css("max-width") $(".comic_popup").css("max-width","1000px") $(link).parent().append("<div id=\"quickrefimage_" + url + "\">" + imgs_code + "</div>") refPreloader($($("#quickrefimage_" + url).find(".comic_popup")[0])) } } function main() { UI_buttonWait(); UI_buttonVote(); UI_navarea_grow() var today=new Date(); var url=location.href; var comicday=dateFromSlugURL(url); var pageID=getBBpageId(today,comicday); basePage=pageID; target=months[comicday.getMonth()] + " [^,]*\\b" + comicday.getDate() + "\\b[^,]*, " + comicday.getFullYear(); console.log("target acquired: " + target); loop_search(10); refPreloader($(".comic_popup")); if (location.href == homepage) engage_updater(); } main();