// ==UserScript== // @name AnimeBytes Bookmarks for Collages & Companies // @author sabs (like "sobs"), sabs@sobs.moe // @namespace sabs // @version 29 // @description Remember your favorite collages and companies! // @match https://animebytes.tv/collage.php* // @match https://animebytes.tv/bookmarks.php* // @match https://animebytes.tv/company.php* // @homepageURL https://animebytes.tv/forums.php?action=viewthread&threadid=26497&page=1#post1318696 // @icon data:image/x-icon;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAABb2lDQ1BpY2MAACiRdZE7SwNBFIW/JEp8YqFFEIsUUSwiiIJop7FIEyTECEZtNutuIiTrspsgwVawsQhYiDa+Cv+BtoKtgiAogoiNf8BXI7LeMUJEdJbZ+3FmzmXmDPgTBb3oNgxC0So5qXgsPJuZCwcfaSaEnyBjmu7aE8lkgn/H2zU+Va8GVK//9/05WhcNVwdfk/CIbjsl4XHhxErJVrwh3KXntUXhPeGoIwcUPld6tsYPinM1flHspFOT4Fc9w7kfnP3Bet4pCvcLR4qFsv59HnWTNsOamZbaLbMHlxRxYoTJUmaJAiUGpFqS2d++wS/fFMvi0eVvU8ERR468eKOilqWrIdUU3ZCvQEXl/jtP1xweqnVvi0Hjvec990JwEz6qnve+73kfBxC4g1Or7l+WnEZfRa/WtcgudKzB8Vldy27ByTqEbm3N0b6kgEy/acLTEbRnoPMSWuZrWX2vc3gD6VV5ogvY3oE+2d+x8AnhZWf8PQBFKQAAAAlwSFlzAAALEgAACxIB0t1+/AAAAbRJREFUOMudU00oRFEUPucOZjGpec+MorCzGIvZWtsgOz8rU8oCmWEjslAiJUkx4ydlyQpblFKWFsqkLCwpI8x7VmJ49zj3+enNNaQ5m9v97rnfOee730XQImvGG5Aw5veVJHNvTj2Bsw2I9wB4hKW4Ydyl0t584d1YRmIWJaWZ4CDwsJghdOYIIExEESKZoJxzyjnrFJksyyNQQDY4uMtJ44BizXhMHbunBGFvASbzcU6fdfOw/0XiEli32Qle2hHAYWj+6wICTn9gelCTnckuuDmWMVwL9HbJ7H5EODHt1UZvql05FKVXOcpjdHtxRUwCo9wBH/Llz4nSei0lmmmvxHwCuvRxWKsBodqBf0TQWt1BxC19FMFMdd9booq/aXBP66JOdSA9g7VQaKz8t+uEMpAPUECw0tdewJJP/b82ILFZhwQSHOQ1KeWMZQy16Yl2MN7DFTp+DOVal92nVM07YMGY/FAivxCRqtxeUJVPC6eUVaGIcJ1oVFWMqM9SNAFeTOXM6lArolgubN3vdl90L2Ch7ywk9JJ6UqAa1uGZAM+50hmhb8m0k1eWEd9kXTqVg98BpA+2IT/y+kMAAAAASUVORK5CYII= // @grant GM_xmlhttpRequest // @grant GM_setValue // @grant GM_getValue // @downloadURL https://update.greasyfork.icu/scripts/453138/AnimeBytes%20Bookmarks%20for%20Collages%20%20Companies.user.js // @updateURL https://update.greasyfork.icu/scripts/453138/AnimeBytes%20Bookmarks%20for%20Collages%20%20Companies.meta.js // ==/UserScript== (function() { 'use strict'; unsafeWindow.abcb = { bookmarks: JSON.parse(GM_getValue("abcb", "{}")) } var bookmarks, header, text, a, linkbox, container function fetchPageForId(id, callback) { var url; if (id.match(/C.*/)) { id = id.substring(1) url = "https://animebytes.tv/company.php?id=" + id } else { url = "https://animebytes.tv/collage.php?id=" + id } GM_xmlhttpRequest({ method: "GET", url: url, onload: function(response) { var container = document.implementation.createHTMLDocument().documentElement; container.innerHTML = response.responseText; callback(container) } }) } function buildBookmarkTab() { bookmarks = document.createElement("div") bookmarks.className = "thin" bookmarks.id = "bookmarks" header = document.createElement("h2") header.className = "center" text = document.createTextNode("Bookmarks") header.appendChild(text) bookmarks.appendChild(header) return bookmarks } function buildBookmarkTableAndSaveData() { let ret = {} let data = [] let table, body, row, text, td table = document.createElement("table") table.width = "100%" body = table.createTBody(); row = body.insertRow(); row.className = "colhead" for (const header of ["Collage", "Torrents when Last Checked"]) { td = document.createElement("td"); text = document.createTextNode(header); td.appendChild(text); row.appendChild(td); } var next = "rowa" for (const [key, value] of Object.entries(unsafeWindow.abcb.bookmarks)) { row = body.insertRow(); row.className = next next = next == "rowa" ? "rowb" : "rowa" td = document.createElement("td"); a = document.createElement("a"); if (key.match(/C.*/)) { a.href = "/company.php?id=" + key.substring(1) } else { a.href = "/collage.php?id=" + key } text = document.createTextNode(value.title); td.appendChild(a); a.appendChild(text); row.appendChild(td); td = document.createElement("td"); text = document.createTextNode(value.groups); td.appendChild(text); row.appendChild(td); data[key] = { id: key, groups: value.groups, td: td, } } ret.table = table ret.data = data return ret } function addBookmark(id, data) { unsafeWindow.abcb.bookmarks = JSON.parse(GM_getValue("abcb", "{}")) unsafeWindow.abcb.bookmarks[id] = data GM_setValue("abcb", JSON.stringify(unsafeWindow.abcb.bookmarks)) } function deleteBookmark(id) { unsafeWindow.abcb.bookmarks = JSON.parse(GM_getValue("abcb", "{}")) delete unsafeWindow.abcb.bookmarks[id] GM_setValue("abcb", JSON.stringify(unsafeWindow.abcb.bookmarks)) } function deleteAllBookmarks(id) { if (confirm('Click "OK" to permanently delete all your bookmarked collages.')) { unsafeWindow.abcb.bookmarks = {} GM_setValue("abcb", JSON.stringify(unsafeWindow.abcb.bookmarks)) location.reload() } } function is404(doc) { return doc.querySelector("#content .thin h2").innerText === "Error 404 - Not Found" } const NO_ERROR = null const PAGE_NOT_FOUND = 2 function getBookmarkDataFromDocument(doc) { if (is404(doc)) { return { error: PAGE_NOT_FOUND } } return { error: NO_ERROR, title: doc.querySelector("#content .thin h2").innerText, groups: doc.querySelector(".sidebar .stats.nobullet").firstElementChild.textContent.replace("Groups: ", "") } } function hideCollagesTab(add_history=true) { unsafeWindow.abcb.tab_bookmarks.style.display = "none"; unsafeWindow.abcb.tab_collages.style.display = "block"; if (add_history) { history.pushState("", document.title, window.location.pathname + window.location.search); } } function showCollagesTab(add_history=true) { unsafeWindow.abcb.tab_bookmarks.style.display = "block"; unsafeWindow.abcb.tab_collages.style.display = "none"; if (add_history) { history.pushState("", document.title, window.location.pathname + window.location.search + "#collages"); } } function toggleCollagesTab() { if (isOnCollagesTab()) { hideCollagesTab() } else { showCollagesTab() } } function refreshBookmarkTable() { let b let i = 0 for (let d of Object.values(unsafeWindow.abcb.table_data)) { d.td.innerHTML = "Checking..." setTimeout(function () { fetchPageForId(d.id, function(doc) { let b = getBookmarkDataFromDocument(doc) if (b.error === PAGE_NOT_FOUND) { d.td.innerHTML = "" let a = createLinkboxLink("Collage no longer exists. Click to forget.", function() { d.td.parentNode.remove() deleteBookmark(d.id) }) d.td.appendChild(a) } else if (b.groups !== d.groups) { d.td.innerHTML = d.groups + " -> " + b.groups deleteBookmark(d.id) addBookmark(d.id, b) d.groups = b.groups } else { d.td.innerHTML = d.groups } })} , i * 1000) i++; } } function getCollageId() { let id = new URLSearchParams(document.location.search).get('id') if (document.location.pathname == '/company.php') { return "C" + id } else { return id } } function isViewingCollage() { return getCollageId() !== null } function isViewingBookmarks() { return document.location.pathname === "/bookmarks.php" } function setupAndGetCollageTab() { container = document.querySelector("#content .thin") container.id = "nonCollages" return container } function createLinkboxLink(text, callback) { a = document.createElement("a") a.addEventListener("click", callback, false) a.style = "cursor: pointer;" a.appendChild(document.createTextNode(text)) return a } function getLinkbox() { return document.querySelectorAll("#content .thin .linkbox")[0] } function createLinkbox() { linkbox = document.createElement("div"); linkbox.className = "linkbox" return linkbox } function idIsBookmarked(id) { unsafeWindow.abcb.bookmarks = JSON.parse(GM_getValue("abcb", "{}")) return unsafeWindow.abcb.bookmarks.hasOwnProperty(id) } function isOnCollagesTab() { return document.location.hash === "#collages" } function hasAnyBookmarks() { return Object.entries(unsafeWindow.abcb.bookmarks).length !== 0 } if (isViewingCollage()) { linkbox = getLinkbox() let id = getCollageId() a = createLinkboxLink(idIsBookmarked(id) ? "[Bookmarked]" : "[Bookmark]", function(e) { if (idIsBookmarked(id)) { deleteBookmark(id) a.innerHTML = "[Bookmark]" } else { if (document.readyState === "complete") { let data = getBookmarkDataFromDocument(document) addBookmark(id, data) a.innerHTML = "[Bookmarked]" } else { a.innerHTML = "[Bookmarking...]" document.onreadystatechange = function() { if (document.readyState === 'complete') { let data = getBookmarkDataFromDocument(document) addBookmark(id, data) a.innerHTML = "[Bookmarked]" } } } } }) let m = document.querySelector(".linkbox") m.append(" ", a) } else if (isViewingBookmarks()) { unsafeWindow.abcb.tab_bookmarks = buildBookmarkTab() unsafeWindow.abcb.tab_collages = setupAndGetCollageTab() let clone_linkbox = getLinkbox().cloneNode(true) clone_linkbox.style = "margin-bottom: 0;" clone_linkbox.innerHTML = '[Torrents: Anime | Music] [Threads] [Collages & Companies]' unsafeWindow.abcb.tab_bookmarks.appendChild(clone_linkbox) // regular linkbox linkbox = getLinkbox() a = createLinkboxLink("Collages & Companies", function() {}) a.href = "#collages" linkbox.append("[") linkbox.append(a) linkbox.append("]") if (hasAnyBookmarks()) { linkbox = createLinkbox() linkbox.style = "margin-top: 0;" a = createLinkboxLink("[Delete all]", deleteAllBookmarks) linkbox.prepend(" ") linkbox.prepend(a) a = createLinkboxLink("[Refresh torrent count]", refreshBookmarkTable) linkbox.prepend(" ") linkbox.prepend(a) unsafeWindow.abcb.tab_bookmarks.appendChild(linkbox) var table = buildBookmarkTableAndSaveData() unsafeWindow.abcb.table_data = table.data unsafeWindow.abcb.tab_bookmarks.appendChild(table.table) } else { let p = document.createElement("p") p.className = "center" p.prepend(document.createTextNode("You don't have any collages bookmarked!")) unsafeWindow.abcb.tab_bookmarks.appendChild(p) } var editor = createLinkboxLink("[Show Data Editor]", refreshBookmarkTable) unsafeWindow.abcb.tab_collages.insertAdjacentElement("beforebegin", unsafeWindow.abcb.tab_bookmarks) if (isOnCollagesTab()) { showCollagesTab(false) } else { hideCollagesTab(false) } window.onhashchange = function() { if (isOnCollagesTab()) { showCollagesTab(false) } else { hideCollagesTab(false) } } } })();