Shows when a gallery was last visited and allows the hiding of individual galleries
// ==UserScript==
// @name ExVisited
// @namespace Smoer
// @description Shows when a gallery was last visited and allows the hiding of individual galleries
// @include http://exhentai.org/*
// @include https://exhentai.org/*
// @include http://g.e-hentai.org/*
// @include https://g.e-hentai.org/*
// @version 2.1
// @grant GM_setValue
// @grant GM_getValue
// @require http://code.jquery.com/jquery-1.11.0.min.js
// ==/UserScript==
if(typeof(Storage) == "undefined"){
alert("[ExVisited] Your browser does not support storage.");
}
var url = document.URL;
var sto = localStorage.getItem("exvisit3") ? localStorage.getItem("exvisit3") : '{"data":{}}';
var vis = JSON.parse(sto);
var spl = url.split("/");
var d1 = spl[3]
var d2 = spl[4];
var d3 = spl[5];
var css = GM_getValue("css") ? GM_getValue("css") : "background:#222 !important";
var hidden_raw = localStorage.getItem("exvisit3_h") ? localStorage.getItem("exvisit3_h") : '{"data":{}}';
var hidden_tab = JSON.parse(hidden_raw);
vis["data"] = !vis["data"] ? Array() : vis["data"];
hidden_tab["data"] = !hidden_tab["data"] ? Array() : hidden_tab["data"];
// Helper stuff
if (!Date.now) {
Date.now = function() { return new Date().getTime(); };
}
Number.prototype.pad0 = function(length) {
var result = this.toString();
while(result.length<length) result = "0"+result;
return result;
}
Object.size = function(obj) {
var size = 0, key;
for (key in obj) {
if (obj.hasOwnProperty(key)) size++;
}
return size;
};
var old_storage = localStorage.getItem("exvisit");
if(old_storage){
console.log("Found old storage");
var osj = JSON.parse(old_storage);
console.log(osj);
for(i=0;i<Object.size(osj["data"]);i++){
vis["data"][ osj["data"][i] ] = Date.now();
}
console.log("Merged entries ("+Object.size(osj["data"])+")");
localStorage.setItem("exvisit3",JSON.stringify(vis));
localStorage.removeItem("exvisit"); // ;_;7
}
function ExStore(){
var c = d2+"."+d3;
vis["data"][c] = Date.now();
localStorage.setItem("exvisit3",JSON.stringify(vis));
}
function timeDifference(current, previous) {
var msPerMinute = 60 * 1000;
var msPerHour = msPerMinute * 60;
var msPerDay = msPerHour * 24;
var msPerMonth = msPerDay * 30;
var msPerYear = msPerDay * 365;
var elapsed = current - previous;
if (elapsed < msPerMinute) {
return Math.round(elapsed/1000) + ' seconds ago';
}
else if (elapsed < msPerHour) {
return Math.round(elapsed/msPerMinute) + ' minutes ago';
}
else if (elapsed < msPerDay ) {
return Math.round(elapsed/msPerHour ) + ' hours ago';
}
else if (elapsed < msPerMonth) {
return Math.round(elapsed/msPerDay) + ' days ago';
}
else if (elapsed < msPerYear) {
return Math.round(elapsed/msPerMonth) + ' months ago';
}
else {
return Math.round(elapsed/msPerYear ) + ' years ago';
}
}
var img_hide = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAIhSURBVDjLlZPrThNRFIWJicmJz6BWiYbIkYDEG0JbBiitDQgm0PuFXqSAtKXtpE2hNuoPTXwSnwtExd6w0pl2OtPlrphKLSXhx07OZM769qy19wwAGLhM1ddC184+d18QMzoq3lfsD3LZ7Y3XbE5DL6Atzuyilc5Ciyd7IHVfgNcDYTQ2tvDr5crn6uLSvX+Av2Lk36FFpSVENDe3OxDZu8apO5rROJDLo30+Nlvj5RnTlVNAKs1aCVFr7b4BPn6Cls21AWgEQlz2+Dl1h7IdA+i97A/geP65WhbmrnZZ0GIJpr6OqZqYAd5/gJpKox4Mg7pD2YoC2b0/54rJQuJZdm6Izcgma4TW1WZ0h+y8BfbyJMwBmSxkjw+VObNanp5h/adwGhaTXF4NWbLj9gEONyCmUZmd10pGgf1/vwcgOT3tUQE0DdicwIod2EmSbwsKE1P8QoDkcHPJ5YESjgBJkYQpIEZ2KEB51Y6y3ojvY+P8XEDN7uKS0w0ltA7QGCWHCxSWWpwyaCeLy0BkA7UXyyg8fIzDoWHeBaDN4tQdSvAVdU1Aok+nsNTipIEVnkywo/FHatVkBoIhnFisOBoZxcGtQd4B0GYJNZsDSiAEadUBCkstPtN3Avs2Msa+Dt9XfxoFSNYF/Bh9gP0bOqHLAm2WUF1YQskwrVFYPWkf3h1iXwbvqGfFPSGW9Eah8HSS9fuZDnS32f71m8KFY7xs/QZyu6TH2+2+FAAAAABJRU5ErkJggg==";
console.log( Object.keys(hidden_tab["data"]).sort() );
function ExHide(){
var list = $(".it5");
var thumb = $(".id1");
var ids = [];
// regular list
if(list.length>0){
$("table.itg tbody tr:first-child()").append("<th>Last viewed</th>");
$("div.it5").css("max-width","570px");
for(i=0;i<list.length;i++){
(function(tmp){
var d = $(list[tmp]).find("a").attr("href").split("/");
var galleryId = d[4]+"."+d[5];
if(hidden_tab["data"][ galleryId ] != undefined){
console.log("Found hidden gallery: " + galleryId );
$(list[tmp]).parent().parent().parent().slideUp(500).remove();
}else{
console.log("Found gallery: " + galleryId );
$("<img src='" + img_hide + "' style='cursor:pointer !important; vertical-align:-4px; margin-right:1px; float:left' title='Hide gallery'>" ).prependTo( $(list[tmp]).find("a").first().parent().parent().parent() ).on( 'click', function(){
ExHideGallery( galleryId );
$(list[tmp]).parent().parent().parent().slideUp(500).remove();
});
if(vis["data"][ galleryId ] != undefined){
var d = new Date(vis["data"][ galleryId ]);
$(list[tmp]).parent().parent().parent().addClass('gv');
$(list[tmp]).parent().parent().parent().append("<td style='font-size:9px; text-align:left; width:80px'>"+timeDifference(Date.now(), vis["data"][ galleryId ]) + "<br>" + d.getHours().pad0(2) + ":" + d.getMinutes().pad0(2) + " " + d.getDate() + "/" + (d.getMonth()+1) + "</td>");
}else{
$(list[tmp]).parent().parent().parent().append("<td style='font-size:9px; text-align:left; width:80px'>Never</td>");
}
}
})(i);
}
}
// thumbnails
if(thumb.length>0){
for(i=0;i<thumb.length;i++){
var d = $(thumb[i]).find("a").attr("href").split("/");
var c = d[4]+"."+d[5];
$(thumb[i]).css('padding-bottom','25px');
if(vis["data"][c] != undefined){
var d = new Date(vis["data"][c]);
$(thumb[i]).addClass('gv');
$(thumb[i]).append("<br><div style='font-size:11px; margin-top:-5px; text-align:center'>"+timeDifference(Date.now(), vis["data"][c]) + " (" + d.getHours().pad0(2) + ":" + d.getMinutes().pad0(2) + " " + d.getDate() + "/" + (d.getMonth()+1) + ")</div>")
}
}
}
}
function ExHideGallery(id){
// clean slate
var hidden_raw = localStorage.getItem("exvisit3_h") ? localStorage.getItem("exvisit3_h") : '{"data":{}}';
var hidden_tab = JSON.parse(hidden_raw);
hidden_tab["data"][ id ] = 1;
console.log("Hidden gallery: " + id );
localStorage.setItem("exvisit3_h",JSON.stringify(hidden_tab));
}
$(function(){
$("head").append("<style>.gv { "+css+" }</style>");
if(d1 == "g"){ ExStore(); }
if(d1.substr(0,1) == "?" || d1.substr(0,1) == "#" || d1.substr(0,1) == "f" || d1.substr(0,1) == "t" || !d1){
var len = Object.size(vis["data"]);
$("#toppane").append('<div style="text-align:center">'+len+' visited galleries, ' + Object.size(hidden_tab["data"]) + ' hidden. <a href="javascript:;" id="ExImport">Import</a> / <a href="javascript:;" id="ExExport">Export</a> / <a href="javascript:;" id="ExCss">CSS</a></div>');
$("#ExExport").click(function(){
var e = "";
for(d in vis["data"]){
e += d + ":"+vis["data"][d]+";";
}
$("body").html('<div style="width:400px;height:400px;overflow:auto;padding:10px;margin:10px">'+e+'</div>');
});
$("#ExImport").click(function(){
var c = prompt("Input data here:");
if(c){
var d = JSON.parse('{"data":{}}');
var sp = c.split(";");
for(k in sp){
var s = sp[k].split(":");
d["data"][s[0]] = parseInt(s[1]);
}
alert("Imported "+Object.size(d["data"])+" entries.");
localStorage.setItem("exvisit3", JSON.stringify(d))
location.reload();
}
});
$("#ExCss").click(function(){
var c = prompt("Input CSS here:", css);
if(c){
GM_setValue("css",c);
location.reload();
}
});
ExHide();
}
});