// ==UserScript==
// @name ReleaseBB rlsbb TV Show Tracker
// @description Follow TV Shows on rlsbb.com and swiftly find new episodes
// @namespace drdre
// @include /^http:\/\/(www\.)?rlsbb\.com\/$/
// @include /^http:\/\/(www\.)?rlsbb\.com\/page\/\d+\/?(#.*)?$/
// @include /^http:\/\/(www\.)?rlsbb\.com\/category\/tv-shows\/(page\/\d+\/?)?$/
// @include /^http:\/\/(www\.)?rlsbb\.com\/\?s=.+&submit=Find$/
// @include /^http:\/\/(www\.)?rlsbb\.com\/search/.*$/
// @exclude http://www.rlsbb.ru/maintenance.html
// @exclude http://www.rlsbb.com/maintenance.htm
// @exclude http://rlsbb.ru/maintenance.html
// @exclude http:/rlsbb.com/maintenance.htm
// @version 2
// @grant GM_setValue
// @grant GM_getValue
// @grant GM_xmlhttpRequest
// ==/UserScript==
"use strict";
var nukes = ["PROPER","REPACK","RERIP","UPDATE","REAL"];
// #################################
// Production steps of ECMA-262, Edition 6, 22.1.2.1
// Reference: https://people.mozilla.org/~jorendorff/es6-draft.html#sec-array.from
if (!Array.from) {
Array.from = (function () {
var toStr = Object.prototype.toString;
var isCallable = function (fn) {
return typeof fn === 'function' || toStr.call(fn) === '[object Function]';
};
var toInteger = function (value) {
var number = Number(value);
if (isNaN(number)) { return 0; }
if (number === 0 || !isFinite(number)) { return number; }
return (number > 0 ? 1 : -1) * Math.floor(Math.abs(number));
};
var maxSafeInteger = Math.pow(2, 53) - 1;
var toLength = function (value) {
var len = toInteger(value);
return Math.min(Math.max(len, 0), maxSafeInteger);
};
// The length property of the from method is 1.
return function from(arrayLike/*, mapFn, thisArg */) {
// 1. Let C be the this value.
var C = this;
// 2. Let items be ToObject(arrayLike).
var items = Object(arrayLike);
// 3. ReturnIfAbrupt(items).
if (arrayLike == null) {
throw new TypeError("Array.from requires an array-like object - not null or undefined");
}
// 4. If mapfn is undefined, then let mapping be false.
var mapFn = arguments.length > 1 ? arguments[1] : void undefined;
var T;
if (typeof mapFn !== 'undefined') {
// 5. else
// 5. a If IsCallable(mapfn) is false, throw a TypeError exception.
if (!isCallable(mapFn)) {
throw new TypeError('Array.from: when provided, the second argument must be a function');
}
// 5. b. If thisArg was supplied, let T be thisArg; else let T be undefined.
if (arguments.length > 2) {
T = arguments[2];
}
}
// 10. Let lenValue be Get(items, "length").
// 11. Let len be ToLength(lenValue).
var len = toLength(items.length);
// 13. If IsConstructor(C) is true, then
// 13. a. Let A be the result of calling the [[Construct]] internal method of C with an argument list containing the single item len.
// 14. a. Else, Let A be ArrayCreate(len).
var A = isCallable(C) ? Object(new C(len)) : new Array(len);
// 16. Let k be 0.
var k = 0;
// 17. Repeat, while k < len… (also steps a - h)
var kValue;
while (k < len) {
kValue = items[k];
if (mapFn) {
A[k] = typeof T === 'undefined' ? mapFn(kValue, k) : mapFn.call(T, kValue, k);
} else {
A[k] = kValue;
}
k += 1;
}
// 18. Let putStatus be Put(A, "length", len, true).
A.length = len;
// 20. Return A.
return A;
};
}());
}
function pad2(i) {
if(i < 10 && i > -10) {
return "0"+parseInt(i,10)
}
return ""+parseInt(i,10);
}
function int(s) {
return parseInt(s,10);
}
function float(s) {
return parseFloat(s);
}
function trim(str) {
return str.replace(/^\s\s*/, '').replace(/\s\s*$/, '');
}
function parseMonthname(name) {
var o = {"month": "long"};
for(var i = 0; i < 12; i++) {
if((new Date(i*2678400000)).toLocaleDateString("en-US", o) == name) {
return i;
}
}
return -1;
}
function humanBytes(bytes, precision) {
bytes = parseInt(bytes,10);
if(bytes === 0) return '0 Byte';
var k = 1024;
var sizes = ['B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];
var i = Math.floor(Math.log(bytes) / Math.log(k));
return parseFloat((bytes / Math.pow(k, i)).toPrecision(2)) + ' ' + sizes[i];
}
function base64BinaryString(s) {
const base64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
const l = s.length;
var o = [];
var char0,char1,char2,char3;
var byte0,byte1,byte2;
var t;
var i = 0;
while(i < l) {
byte0 = s.charCodeAt(i++) & 0xff;
byte1 = i<l?s.charCodeAt(i++) & 0xff:0;
byte2 = i<l?s.charCodeAt(i++) & 0xff:0;
char0 = byte0 >> 2;
char1 = ((byte0 & 0x3) << 4) | (byte1 >> 4);
char2 = ((byte1 & 0x0f) << 2) | (byte2 >> 6);
char3 = byte2 & 0x3f;
t = i - (l - 1);
if(t == 1) {
char3 = 64;
} else if(t == 2) {
char3 = 64;
char2 = 64;
}
o.push(base64.charAt(char0), base64.charAt(char1), base64.charAt(char2), base64.charAt(char3));
}
return o.join("");
}
function loadCrossSiteImage(url,cb) {
var canvas = document.createElement("canvas");
var ctx = canvas.getContext("2d");
var img0 = document.createElement("img"); // To get image dimensions
img0.addEventListener("load",function(){
if(img0.height == 0 || img0.width == 0) return;
canvas.height = img0.height;
canvas.width = img0.width;
GM_xmlhttpRequest ({
method: 'GET',
overrideMimeType: 'text/plain; charset=x-user-defined',
url: url, // Load cross site image into canvase
onload: function (resp) {
var dataurl = "data:image/jpeg;base64," + base64BinaryString(resp.responseText);
var img1 = document.createElement("img"); // Image is already data url, but let's compress it a little bit
img1.addEventListener("load",function(){
ctx.drawImage(img1, 0, 0);
cb(url,canvas.toDataURL("image/jpeg",0.2));
});
img1.src = dataurl;
}
});
});
img0.src = url;
}
// #################################
var libversion = false;
var lastlibversion = false;
var records;
var ignoreShows;
var mapID2Index = {}; // temporary cache for finding an entry by its ID i.e. unique URL
function load() {
libversion = int(GM_getValue("libversion",Number.MIN_SAFE_INTEGER));
if(lastlibversion == libversion) return;
records = JSON.parse(GM_getValue("records","[]"));
ignoreShows = new Set(JSON.parse(GM_getValue("ignoreShows","[]")));
lastlibversion = libversion;
mapID2Index = {};
}
function save() {
if(libversion === false) {
throw Error("save() cannot be called before load()");
}
libversion++;
if(libversion == Number.MAX_SAFE_INTEGER) {
libersion = Number.MIN_SAFE_INTEGER;
}
GM_setValue("libversion",libversion);
records = sortRecords(records);
GM_setValue("records",JSON.stringify(records));
GM_setValue("ignoreShows",JSON.stringify(Array.from(ignoreShows)));
lastlibversion++;
}
function getRecordById(id) {
if(mapID2Index[id]) {
return records[mapID2Index[id]];
}
for(var i = 0; i < records.length; i++) {
if(records[i].id == id) {
mapID2Index[id] = i;
return records[i];
}
}
return false;
}
function Episode(episode) {
load();
if(typeof episode == "string") {
return getRecordById(episode);
} else if("id" in episode) {
return getRecordById(episode.id);
} else {
throw new Error("Wrong format episode:"+JSON.stringify(episode));
}
}
function isDownloaded(id) {
var record = Episode(id);
return record.hasOwnProperty("downloaded") && record.downloaded;
}
function setDownloaded(id) {
var record = Episode(id);
record.downloaded = true;
save();
}
function isIgnoredShow(id) {
var record = Episode(id);
if(record.show && ignoreShows.has(record.show)) {
return true;
}
return false;
}
function ignoreShow(id) {
if(isIgnoredShow(id)) {
return true;
} else {
var record = Episode(id);
if(record.show) {
ignoreShows.add(record.show);
save();
return true;
}
}
return false;
}
function unIgnoreShow(id) {
if(!isIgnoredShow(id)) {
return true;
} else {
var record = Episode(id);
if(record.show) {
if(!ignoreShows.has(record.show)) {
return true;
} else {
ignoreShows.delete(record.show);
save();
return true;
}
}
}
return false;
}
function toggleIgnoreShow(id) {
if(isIgnoredShow(id)) {
if(unIgnoreShow(id)) {
return 1;
}
} else {
if(ignoreShow(id)) {
return -1;
}
}
return 0;
}
function removeIgnoredShowsFrom(arr) {
var narr = arr.filter(function(record){
return record.show && !ignoreShows.has(record.show);
});
return narr;
}
function sortRecords(arr) {
var narr = arr.slice(0);
narr.sort(function(a,b) {
return b.time - a.time;
});
return narr;
}
function sortRecordsByTitle(arr) {
var narr = arr.slice(0);
narr.sort(function(a,b) {
return a.title.localeCompare(b.title);
});
return narr;
}
function getLatestEpisodes() {
load();
var episodes = {};
for(var i = 0; i < records.length; i++) {
if(("show" in records[i]) && (!(records[i].show in episodes) || episodes[records[i].show].time <= records[i].time)) {
episodes[records[i].show] = records[i];
}
}
return Object.keys(episodes).map(function (show) {
return episodes[show];
});
}
function readPost(post) {
var entryContent = post.getElementsByClassName("entry-content")[0];
var link = post.getElementsByClassName("postTitle")[0].getElementsByTagName("a")[0];
var subtitle = post.getElementsByClassName("postSubTitle")[0];
var id = link.href;
var upperCaseContent = entryContent.innerHTML.toUpperCase();
var isnuke = false;
if(getRecordById(id) !== false) {
if(0 == Array.filter(nukes,function(a) { return -1!=upperCaseContent.indexOf(a)}).length) {
throw "error_recordexists";
return;
} else {
// It's a nuke
isnuke = true;
}
}
var time = subtitle.innerHTML.match(/Posted on (\D+) (\d+)\D\D, (\d{4}) at (\d+):(\d{2}) (am|pm)/); // Posted on August 17th, 2014 at 10:47 pm
var title = trim(link.innerHTML);
var result = {
"id": id,
"title": title,
"time": (new Date(int(time[3]), parseMonthname(time[1]),int(time[2]), int(time[4])+(time[6] == 'pm'?12:0), int(time[5]), 0, 0)).getTime(),
"release" : []
};
var tvshow;
if((tvshow = title.match(/^(.*)\s(\d+)\xD70*(\d+)\s/)) || (tvshow = title.match(/^(.*)\sS0*(\d+)E0*(\d+)\s/) )) {
result["show"] = trim(tvshow[1]).toLowerCase();
result["showWithCase"] = trim(tvshow[1]);
result["season"] = int(tvshow[2]);
result["episode"] = int(tvshow[3]);
}
// Find actual releasenames of movie
var strong = entryContent.getElementsByTagName("strong");
for(var i = 0; i < strong.length; i++) {
if(strong[i].innerHTML.match(/Release Name:/)) {
result["release"].push(trim(strong[i].nextSibling.textContent));
} else if(strong[i].innerHTML.match(/Links:/)) {
var a = strong[i].parentNode.getElementsByTagName("a");
var m;
for(var j = 0; j < a.length; j++) {
if(m = a[j].href.match(/imdb\.com\/title\/(\w+)/)) {
result["imdb"] = m[1];
break;
}
}
}
}
// Find actual releasenames of tvshow
var strong = entryContent.getElementsByTagName("strong");
for(var i = 0; i < strong.length; i++) {
var m;
if((m = strong[i].innerHTML.match(/\.(\d+)\xD70*(\d+)\./)) || (m = strong[i].innerHTML.match(/\.S0*(\d+)E0*(\d+)\./) )) {
result["release"].push(trim(strong[i].innerHTML));
}
}
// Find tvshow image
var img = false;
if(entryContent.getElementsByTagName("p").length) {
if(entryContent.getElementsByTagName("p")[0].getElementsByTagName("img").length) {
img = entryContent.getElementsByTagName("p")[0].getElementsByTagName("img")[0];
}
}
if("show" in result && img) {
result["image"] = img.src;
}
if("show" in result || "imdb" in result) { // Only save tvshows or movies
if(isnuke) {
records[mapID2Index[id]] = result; // Overwrite record
} else {
records.push(result); // New record
}
}
}
function readPosts() {
load();
var error_recordexists = false;
var posts = document.getElementsByClassName("entry post");
for(var i = 0; i < posts.length; i++) {
try {
readPost(posts[i]);
} catch(e) {
if(e == "error_recordexists") {
error_recordexists = true;
} else {
throw e;
}
}
}
save();
if(error_recordexists) {
throw "error_recordexists";
}
}
function crawl() {
if(document.location.href.indexOf("#crawlbackto=") == -1) {
if(!confirm("Start scanning?\nTo stop the process you'll have to close the tab/window!")) {
return false;
}
}
var url = document.getElementById("olderEntries").getElementsByTagName("a")[0].href+"#crawlbackto=-1";
document.location.href = url;
}
var mw;
function getMainWindow() {
const id = "rlsbbmymainwin";
if(mw) {
return mw;
}
mw = {};
mw.main = document.createElement("div");
mw.main.id = id;
mw.main.style = "position:fixed; top:0px; left:0px; z-index:999";
document.body.appendChild(mw.main);
mw.controls = document.createElement("div");
mw.main.appendChild(mw.controls);
mw.menu = document.createElement("div");
mw.menu.setAttribute("style","overflow:auto; margin-top:1px; margin-bottom:3px; max-height:"+(window.innerHeight-150)+"px; background: -moz-linear-gradient(center top , #eee, #bbb) repeat scroll 0 0 #ccc;");
mw.main.appendChild(mw.menu);
mw.lists = document.createElement("div");
mw.lists.setAttribute("style","");
mw.main.appendChild(mw.lists);
return mw;
}
function showButton(title,click) {
var c = getMainWindow().controls;
var br = c.getElementsByTagName("br");
if(br.length) {
br = br[br.length-1];
} else {
br = document.createElement("br");
br.style = "clear:left";
c.appendChild(br);
}
var b = document.createElement("div");
b.style = "cursor:pointer; border-radius: 5px 5px 0 0; color: black; background: -moz-linear-gradient(center top , #eee, #bbb) repeat scroll 0 0 #ccc; text-shadow: 1px 1px 0 #eee;\
float: left; padding:2px 4px 1px; margin: 2px; height: 20px; text-align: center; font-size: 14px;";
b.addEventListener("click",click);
b.addEventListener("mouseover",function() {
this.dataset.oldbgImage = this.style.backgroundImage;
this.style.backgroundImage = "-moz-linear-gradient(center top , #fff, #bbb)";
});
b.addEventListener("mouseout",function() {
if(this.dataset.oldbgImage)
this.style.backgroundImage = this.dataset.oldbgImage;
});
b.innerHTML = title;
c.insertBefore(b,br);
}
function showIgnoreMenu() {
var c = getMainWindow().menu;
c.innerHTML = "";
if(c.dataset.menu == "ignore") {
c.dataset.menu = "";
return;
} else {
c.dataset.menu = "ignore";
}
var allshows = getLatestEpisodes();
allshows = sortRecordsByTitle(allshows);
var ul = document.createElement("ul");
var li;
var lis = [];
// Search by key
var search = function(s) {
for(var i = 0; i < lis.length; i++) {
if(lis[i].textContent.toLowerCase().startsWith(s)) {
lis[i].scrollIntoView();
window.scrollY = 0;
return;
}
}
};
var search_it = false;
var search_str = "";
var keyup = function(ev) {
search_str += ev.key;
search(search_str);
if(search_it !== false) {
clearTimeout(search_it);
}
search_it = setTimeout(function() {
search_str = "";
},2000);
};
document.body.addEventListener("keyup",keyup,false);
var toggle = function(ev) {
var id = this.dataset.id;
var status = toggleIgnoreShow(id);
if(status == 1) {
this.style.background = "#99CC99";
} else if(status == -1) {
this.style.background = "red";
} else {
this.style.background = "yellow";
alert("An error occurred. Try reloading the page.");
}
};
var ignoreAll = function(ev) {
if(!confirm("Really ignore all shows?")) return;
var allshows = getLatestEpisodes();
for(var i = 0; i < allshows.length; i++) {
ignoreShow(allshows[i].id);
}
document.location.reload();
};
var showAll = function(ev) {
for(var i = 0; i < lis.length; i++) {
ul.removeChild(lis[i]);
}
lis = [];
for(var i = 0; i < allshows.length; i++) {
li = document.createElement("li");
li.setAttribute("data-id",allshows[i].id);
li.appendChild(document.createTextNode(allshows[i].showWithCase+" S"+ pad2(allshows[i].season)+"E"+pad2(allshows[i].episode)));
if(isIgnoredShow(allshows[i].id)) {
li.style.background = "red";
} else {
li.style.background = "#99CC99";
}
li.addEventListener("click",toggle,false);
ul.appendChild(li);
lis.push(li);
}
};
var b;
b = document.createElement("button");
b.innerHTML = "Show all";
b.addEventListener("click",function() {showAll();},false);
c.appendChild(b);
b = document.createElement("button");
b.innerHTML = "Ignore all";
b.addEventListener("click",function() {ignoreAll();},false);
c.appendChild(b);
for(var i = 0; i < allshows.length; i++) {
if(isIgnoredShow(allshows[i].id)) {
continue;
}
li = document.createElement("li");
li.setAttribute("data-id",allshows[i].id);
li.appendChild(document.createTextNode(allshows[i].showWithCase+" S"+ pad2(allshows[i].season)+"E"+pad2(allshows[i].episode)));
if(!isDownloaded(allshows[i])) {
li.style.background = "white"; // New show
} else {
li.style.background = "#99CC99"; // Old show that is not ignored
}
li.addEventListener("click",toggle,false);
ul.appendChild(li);
lis.push(li);
}
c.appendChild(ul);
}
function showCleanMenu(forceshow) {
// Toggle Clean Menu
var c = getMainWindow().menu;
c.innerHTML = "";
if(c.dataset.menu == "clean" && forceshow !== true) {
c.dataset.menu = "";
return;
} else {
c.dataset.menu = "clean";
}
loadImageCache();
var allshows = getLatestEpisodes();
var ul = document.createElement("ul");
var clearButKeepEpisodes = function(ev) {
load();
records = records.filter(function(record){
return "show" in record && record.show;
});
save();
showCleanMenu();
};
var clearButKeepEpisodesDeleteIgnored = function(ev) {
load();
records = records.filter(function(record){
return "show" in record && record.show && !ignoreShows.has(record.show);
});
save();
showCleanMenu(true);
};
var clearAllImageCache = function(ev) {
GM_setValue("imageCache","{}");
loadImageCache();
showCleanMenu(true);
};
var clearImageCacheButKeepEpisodes = function(ev) {
loadImageCache();
var episodes = getLatestEpisodes();
episodes = removeIgnoredShowsFrom(episodes);
var newImageCache = {}
for(var i = 0; i < episodes.length; i++) {
if(episodes[i].image) {
var url = episodes[i].image;
if(imageCache[url]) {
newImageCache[url] = imageCache[url];
}
}
}
GM_setValue("imageCache",JSON.stringify(newImageCache));
loadImageCache();
showCleanMenu(true);
};
var b,li;
li = document.createElement("li");
li.appendChild(document.createTextNode("Cleaning options:"))
c.appendChild(li);
li = document.createElement("li");
b = document.createElement("button");
b.innerHTML = "Keep TV Shows";
b.addEventListener("click",function() {clearButKeepEpisodes();},false);
li.appendChild(b)
c.appendChild(li);
li = document.createElement("li");
b = document.createElement("button");
b.innerHTML = "Keep TV Shows (delete ignored shows)";
b.addEventListener("click",function() {clearButKeepEpisodesDeleteIgnored();},false);
li.appendChild(b)
c.appendChild(li);
li = document.createElement("li");
b = document.createElement("button");
b.innerHTML = "Clear image cache";
b.addEventListener("click",function() {clearAllImageCache();},false);
li.appendChild(b)
c.appendChild(li)
li = document.createElement("li");
b = document.createElement("button");
b.innerHTML = "Clear image cache (keep tracked TV Shows)";
b.addEventListener("click",function() {clearImageCacheButKeepEpisodes();},false);
li.appendChild(b)
c.appendChild(li)
li = document.createElement("li");
b = document.createElement("input");
b.value = allshows.length +" TV shows";
b.disabled = 1;
li.appendChild(b)
c.appendChild(li);
li = document.createElement("li");
b = document.createElement("input");
b.value = records.length +" total records";
b.disabled = 1;
li.appendChild(b)
c.appendChild(li);
li = document.createElement("li");
b = document.createElement("input");
b.value = Object.keys(imageCache).length +" images ("+humanBytes(GM_getValue("imageCache","").length)+")";
b.disabled = 1;
li.appendChild(b)
c.appendChild(li);
c.appendChild(ul);
}
var imageCache;
function loadImageCache() {
imageCache = JSON.parse(GM_getValue("imageCache","{}"));
}
function cacheImage(url,dataurl) {
imageCache[url] = dataurl;
GM_setValue("imageCache",JSON.stringify(imageCache));
}
function showTVShows() {
loadImageCache();
var c = getMainWindow().lists;
var div = document.createElement("div");
div.setAttribute("style","max-height:"+(window.innerHeight-150)+"px; overflow:auto; border-bottom-right-radius: 5px; border-bottom-left-radius: 5px;")
var openEpisode = function() {
if(this.dataset.episodeid) {
var record = Episode(this.dataset.episodeid);
//window.open("http://www.rlsbb.com/?s=%22"+encodeURIComponent(record.showWithCase)+"%22&submit=Find");
window.open("http://rlsbb.com/search/"+encodeURIComponent(record.showWithCase));
//if(confirm("Set "+record.title+" as downloaded")) {
setDownloaded(this.dataset.episodeid);
//}
}
};
var div_header = document.createElement("div");
var bg = "background: -moz-linear-gradient(center top , #eee, #bbb) repeat scroll 0 0 #ccc;";
div_header.style = bg+"cursor:pointer;";
div_header.appendChild(document.createTextNode("TVShows"));
div.appendChild(div_header);
var div_select = document.createElement("div");
div_select.style.display = "none";
div.appendChild(div_select);
div_header.addEventListener("click",function(ev) {
// Show/Load TV episodes
if(div_select.style.display == "block") {
div_select.style.display = "none";
return;
}
div_select.style.display = "block";
if(div_select.children.length > 1) {
return;
}
var episodes = getLatestEpisodes();
episodes = removeIgnoredShowsFrom(episodes);
episodes = sortRecords(episodes);
var onLoadBackgroundImage = function() {
var entry = this.parentNode;
var w = float(entry.clientWidth);
var img = this;
if(!img.width || !img.height) {
entry.removeChild(img);
return; // Something is wrong with the image!
}
entry.style.background = "no-repeat url('"+img.src+"') white";
var h = Math.ceil(w * (float(img.height)/ float(img.width)));
entry.style.height = h+"px";
entry.style.backgroundSize = w+"px "+h+"px";
entry.removeChild(img);
};
var entries = [];
for(var i = 0; i < episodes.length; i++) {
var entry = document.createElement("div");
entries.push(entry)
entry.dataset.episodeid = episodes[i].id;
entry.appendChild(document.createTextNode(episodes[i].showWithCase+" S"+ pad2(episodes[i].season)+"E"+pad2(episodes[i].episode)));
entry.addEventListener("click",openEpisode);
div_select.appendChild(entry);
entry.style = bg+" margin:3px 10px 3px; min-width:200px; min-height:20px; font-weight:bolder; text-shadow:1px -1px 5px white;";
if(!isDownloaded(episodes[i])) { // New episode
entry.style.textShadow = "1px -1px 5px black";
entry.style.color = "#ff2";
entry.style.borderStyle = "solid";
entry.style.borderColor = "rgba(255, 255, 0, 0.4) yellow"
entry.style.borderWidth = "1px 1px 1px 6px";
// NEW tag
var div_new = document.createElement("div");
div_new.style = "display: inline-block; margin-top:20px; -3px -3px 8px white; background: rgba(255, 255, 0, 0.6); border: 2px solid black; color: black; font-family: comic sans ms; font-weight: normal; border-radius:20px 5px 5px 50px; padding:0 2px 0 6px; ";
if(episodes[i].image) {
div_new.style.transform = "rotate("+(310+Math.ceil(Math.random()*20))+"deg)";
}
div_new.appendChild(document.createTextNode("\u309C NEW")); //゜
entry.appendChild(div_new);
// Ignore button
var div_ign = document.createElement("div");
div_ign.style = "margin-top: 0px; margin-left:220px; text-shadow:1px -1px 5px white; color:silver; cursor:pointer; ";
div_ign.appendChild(document.createTextNode("\u2717")); //✗
div_ign.addEventListener("click",function(ev) { ev.stopPropagation(); if(confirm("Ignore?")) {if(ignoreShow(this.parentNode.dataset.episodeid)) { this.parentNode.parentNode.removeChild(this.parentNode); } else { alert("An error occured!"); } } });
entry.insertBefore(div_ign,entry.firstChild);
}
if(episodes[i].image) {
var url = episodes[i].image;
if(imageCache[url]) {
url = imageCache[url]
} else {
loadCrossSiteImage(url,cacheImage);
}
var img = document.createElement("img");
img.addEventListener("load",onLoadBackgroundImage);
img.src = url; // Preload background image to get size
img.style = "max-width:180px; display:none";
entry.appendChild(img);
} else {
entry.style.borderStyle = "solid";
entry.style.borderWidth = "1px";
}
}
});
c.appendChild(div);
}
function page_articles() {
var error_recordexists = false;
try {
readPosts();
} catch(e) {
if(e == "error_recordexists") {
error_recordexists = true;
} else {
throw e;
}
}
var crawlback;
if(crawlback = document.location.hash.match(/crawlbackto=(-?\d+)/)) {
if(!error_recordexists) {
var end = int(crawlback[1]);
if(!document.location.href.match(new RegExp("page\/"+end+"\/"))) {
document.title = "Crawling...";
crawl();
return;
}
} else {
document.title = "Scanning finished!";
alert("Scanning finished!");
}
}
showTVShows();
showButton("Scan",crawl);
showButton("Ignore",showIgnoreMenu);
showButton("Clean",showCleanMenu);
}
function page_searchresults() {
var m = document.body.firstChild.textContent.match(/Please try again in (\d+) seconds./);
if(m) {
window.setTimeout(function() { document.location.reload() },3000+int(m[1])*1000);
}
}
(function() {
if(document.location.href.endsWith("&submit=Find") || document.location.href.contains("/search/")) {
page_searchresults();
} else {
page_articles();
}
})();