// ==UserScript== // @name Tapas.io RSS Button // @description Adds RSS buttons to webcomics on tapas.io. // @author Alex V.H. // @namespace https://avhn.us/ // @version 2.03 // @license CC0-1.0 // Copyright: the embedded RSS icon and the script's icon are both derived from assets from tapas.io // I believe that their use in this script is okay, since the RSS icon is generic and universal, // and both the tapas logo and their RSS sprite have been transformed from the original. // @supportURL https://forums.tapas.io/t/rss-feeds-gone/41724 // @icon https://avhn.us/lib/exe/fetch.php?media=blog:tapas_rss:tapas-rss.gif // @compatible firefox browser used for development by author // @compatible chrome briefly tested by author // @match https://tapas.io/series/* // @match https://tapas.io/episode/* // @grant none // @downloadURL none // ==/UserScript== const rssIcon = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAQAAAC1+jfqAAAAAmJLR0QA/4ePzL8AAAAJcEhZcwAALiMAAC4jAXilP3YAAAAHdElNRQfkBg8CGwrcReAoAAAAGXRFWHRDb21tZW50AENyZWF0ZWQgd2l0aCBHSU1QV4EOFwAAAPxJREFUKM99kD9LwgEURc/PQJAQIwkqopaawm/Q3lI0Orrkx2hxaXBrdQmsJmlJ6CsU9IegKQoiSgIriginOg2+zCy643uHd+99ic8M80iLa/bZS+4ZlP36sGnhP0D13ZqZ733iIi+MMskCS+RjesJKcvvbbMiSN3Hnzin+khnrgRyHkWtuWLForgdVAqn9DNmxajaQesQtDLY4dzqMulmagIdue2Cnh2QBLMVfxr98x2wEUo1GD6qW+xs0IksOwE1VdzFxznRc6RoVAVxV9TTFFhccmYakzRkA8wC0AJhIsQwUmAHgCoARAJ4AyKdY55UdLgGYBaANQPdxb589AOJXV9GZEgAAAABJRU5ErkJggg=="; // tapas.io webcomic series all have a unique ID: a few-digit (4-ish?) base-10 number. // The ID is needed to construct the RSS URL. // Fortunately, there are a couple of places to find the ID. // The following functions return the ID, or -1 if they fail to find it. function findIDfromMetas(){ // tapas.io sends a great deal of meta tags in their pages. // Many of these tags are to allow different mobile apps to get to the same page. // These tags have the format "tapastic://series/id[/episode/N]". const tapastic_regex = new RegExp("tapastic:\/\/series\/[0-9]+"); const id_regex = new RegExp("[0-9]+"); const metas = document.getElementsByTagName('meta'); console.log(metas); for (let i=0; i 1) {console.log("More than one \"js-subscribe-cnt\"s found. Using the first one and ignoring the rest.");} let numbers = jsc.href.match("[0-9]+"); // regex: a series of one or more digits if (numbers.length < 1) {console.log("No series ID found! Searched this string for the ID, a base-10 number:", jsc.href); return -1;} console.log("Found a series ID in", jsc); let id = numbers[0]; if (numbers.length > 1) {console.log("More than one base-10 number found where ID should be! Using the first one and ignoring the rest.");} return id; } function findID(){ let id = findIDfromMetas(); if (id == -1){ id = findIDfromSubscribers(); if (id == -1){ console.log("Tried everything but couldn't find series ID! Script is broken!"); console.log("Please file a bug at https://forums.tapas.io/t/rss-feeds-gone/41724 and ping the author!"); } } return id; } function rssURL(id){ return "https://tapas.io/rss/series/" + id; } function addRSSButtons(id){ if (id < 0){return;} // There are 4 places to add an RSS button: // In the Button Wrapper in series-root__footer (visible on the mobile website) let srfs = document.getElementsByClassName("series-root__footer"); console.log(srfs); if (srfs.length > 0){ console.log("There is a series root footer. Looking for its button-wrapper."); let srf = srfs[0]; let bws = srf.getElementsByClassName("button-wrapper"); console.log(bws); if (bws.length > 0){ console.log("There is a button-wrapper in the series root footer."); let bw = bws[0]; let rbs = bw.getElementsByClassName("button-rss"); if (rbs.length > 0) { console.log("This button-wrapper already has an RSS button. Not adding another one."); } else { console.log("Adding an RSS button to the series root footer's button-wrapper."); let img = document.createElement("img"); img.style = "filter: invert(100%)"; img.alt = "RSS Icon"; img.src = rssIcon; let btn = document.createElement("a"); btn.className = "button button--subscribe button-rss"; btn.href = rssURL(id); btn.appendChild(img); bw.appendChild(btn); console.log("Button added to", bw); } } } // In the Button Wrapper in section__top let sts = document.getElementsByClassName("section__top"); console.log(sts); if (sts.length > 0){ // There are 2 section__top elements. One of them is section__top--simple. Don't put a button on it. // The other is just section__top. It (and not section__top--simple) has a button-wrapper. Do put a button in there. let st; for(let i=0; i 0){ console.log(st, "has a button-wrapper."); let bw = bws[0]; let rbs = bw.getElementsByClassName("button-rss"); if (rbs.length > 0){ console.log("This button-wrapper already has an RSS button. Not adding another one."); } else { console.log("Adding an RSS button to this section__top's button-wrapper."); let img = document.createElement("img"); img.alt = "RSS Icon"; img.src = rssIcon; let btn = document.createElement("a"); btn.className = "button button--read button-rss"; // This particular button needs to be re-styled. btn.style = "min-width: 16px; padding: 12px 12px; margin-left: 6px;" btn.href = rssURL(id); btn.appendChild(img); bw.appendChild(btn); console.log("Button added to", bw); } } } } // In the center of the Toolbar at the bottom of the comic browser let trcs = document.getElementsByClassName("toolbar__row--center"); if (trcs.length > 0){ console.log(trcs); let trc = trcs[0]; let ris = trc.getElementsByClassName("row-item"); console.log(ris); if (ris.length > 0){ let ri = ris[0]; let rbs = ri.getElementsByClassName("button-rss"); if (rbs.length > 0){ console.log("This row-item alreads has an RSS button. Not adding another one."); } else { console.log("Adding an RSS button to this toolbar__row--center's row-item."); let a = document.createElement("a"); a.className = "toolbar-btn button-rss"; a.href = rssURL(id); let div = document.createElement("div"); div.className = "ico-wrap"; let img = document.createElement("img"); img.class = "ico"; img.style = "margin: auto;"; img.alt = "RSS Icon"; img.src = rssIcon; div.appendChild(img); let span = document.createElement("span"); let text = document.createTextNode("RSS"); span.appendChild(text); a.appendChild(div); a.appendChild(span); ri.appendChild(a); console.log("Button added to", ri); } } } // In the Dropdown List in the tpFloatMenu (on the mobile website) let tfm = document.getElementById("tpFloatMenu"); if (tfm != null){ console.log("Found a tpFloatMenu:", tfm); if (tfm.text.indexOf("button\-rss") > -1){ console.log("The tpFloatMenu already contains an RSS button. Not adding another one."); } else { // tpFloatMenu is a script tag with a text node. // The text node contains the HTML that goes into the menu: // a
containing a
    , which contains a few
  • s. // We want to insert a new
  • after the first
  • . console.log(tfm.text); let lis = tfm.text.split("\<\/li\>"); lis.splice(1,0,"\n
  • RSS Feed") tfm.text = lis.join("
  • "); console.log(tfm.text); } } } function addLink(id){ let ls = document.head.getElementsByTagName("link"); for (let i=0; i 0) { mlb = mlbs[0]; console.log("Adding callback to more-less-button:", mlb); mlb.addEventListener("click", delayAddButtons); } // Do the thing! addButtons();