返回首頁 

Tapas.io RSS Button

Adds RSS buttons to webcomics on tapas.io.

// ==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.05// @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://archive.org/download/tapas-rss-icon/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/*// @match https://m.tapas.io/series/*// @match https://m.tapas.io/episode/*// @grant    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<metas.length; i++){let meta = metas[i];let content = meta.getAttribute("content");if (tapastic_regex.test(content)) {console.log("Found a series ID in", meta);//let id=content.match("[0-9]+")[0];let id = id_regex.exec(content)[0];return id;}}console.log("Couldn't find a meta tag with the series ID!");return -1;}function findIDfromSubscribers(){// Get the js-subscribe-cnt classed elements, they have an href with the series ID.// In a browser, you can see the URL (and ID) by hovering over the subscriber count in the info page.let jscs = document.getElementsByClassName("js-subscribe-cnt");if (jscs.length < 1) {console.log("No place to get series id!"); return -1;}jsc = jscs[0];console.log(jsc.href);if (jscs.length > 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 digitsif (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__toplet 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<sts.length; i++){let st = sts[i];let bws = st.getElementsByClassName("button-wrapper");if (bws.length > 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 browserlet 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 <div> containing a <ul>, which contains a few <li>s.// We want to insert a new <li> after the first <li>.console.log(tfm.text);let lis = tfm.text.split("\<\/li\>");lis.splice(1,0,"\n <li class=\"dropdown-list__item\"> <a href=\"https://tapas.io/rss/series/" + id + "\" class=\"dropdown-list__button button-rss\"\> <span class=\"ico-wrapper\"><i class=\"ico\"> <img src=\"" + rssIcon + "\"> </i></span>RSS Feed</a>")tfm.text = lis.join("</li>");console.log(tfm.text);}}}function addLink(id){let ls = document.head.getElementsByTagName("link");for (let i=0; i<ls.length; i++){let l = ls[i];if (l.type == "application/rss+xml"){if (l.href == rssURL(id)){console.log("This page's head already has a link tag for the RSS feed. Not adding another one.");return;}}}let l = document.createElement("link");l.rel = "alternate";l.type = "application/rss+xml";l.title = "RSS Feed";l.href = rssURL(id);document.head.appendChild(l);console.log("Added link tag to head:", l);}function addButtons(){let id = findID();if (id < 0) {return;}addRSSButtons(id);addLink(id);}// Tapas has a website feature where,// if while reading a comic you click on the "more..." in the description in the top-right,// the comic's info page loads and is overlaid over the episode page.// This changes the window URL and loads a bunch of new content,// which needs an RSS button added.// But since the overlaid info page is loaded and rendered after the page load,// the script will not have added an RSS button to it.// But because the window URL has changed,// if you click the "more..." link and then refresh the page,// the RSS button will be added to the info page!// The script also works fine if you navigate directly to the info page.// To get around this post-page-load content-and-URL-change,// the script detects clicks on the "more..." link,// waits 2 seconds to give time for the overlaid info page to load,// and then adds the RSS button.function delayAddButtons(){window.setTimeout(addButtons, 2000);}let mlbs = document.getElementsByClassName("more-less-btn");console.log(mlbs.length);if (mlbs.length > 0) {mlb = mlbs[0];console.log("Adding callback to more-less-button:", mlb);mlb.addEventListener("click", delayAddButtons);}// Do the thing!addButtons();