// ==UserScript== // @name GoGoAnime Plus // @namespace http://tampermonkey.net/ // @version 1.2 // @description Adds a watch tracker to gogoanime.io. // @author Sadie Hensley // @license ISC // @match https://*.gogoanime.io/* // @require https://cdn.jsdelivr.net/npm/web-pingjs@1.0.1/ping.min.js // @grant none // @noframes // @downloadURL none // ==/UserScript== (function() { 'use strict'; var title; var pagetype; const impexpclientcode = ` function importData(text){ var dataObj = JSON.parse(text); if (window.confirm('Warning: Importing data will replace existing data. Continue?')){ localStorage.clear(); for(var i in dataObj){ localStorage.setItem(i, dataObj[i]); } location.reload(); }else{ window.alert('Not Imported'); } } function handleFile(e){ var reader = new FileReader(); var data; reader.onload = (text => importData(text.target.result)); reader.readAsText(importbt.files[0]); } var importbt = document.getElementById('import-button'); importbt.addEventListener('change', handleFile); ` const injectsrc = ` const realTitle = document.querySelector('.title_name > h2').textContent.trim(); function getRealTitle(){ var title = document.querySelector('.title_name > h2').textContent.trim(); if (title.includes('(Watched)')){ title = title.slice(10); } return title; } function parse(){ try{ var titlenode = document.querySelector('.title_name > h2'); var title = titlenode.textContent.trim(); var buttonspan = document.getElementById('buttonspan'); var titleheader = document.querySelector('div.anime_video_body > h1'); var watched = localStorage.getItem(realTitle); //alert(watched); if (!watched){ localStorage.setItem(realTitle, "unwatched"); parse(); }if (watched == "watched"){ buttonspan.textContent = "Mark as Unwatched"; title = "(Watched) " + realTitle; titlenode.textContent = title; titleheader.textContent = title; }else if (watched == "unwatched"){ buttonspan.textContent = "Mark as Watched"; title = realTitle; titlenode.textContent = title; titleheader.textContent = title; } }catch(e){ console.error("*&* " + e); } } function clicked(){ try{ watched = localStorage.getItem(realTitle); if (watched){ if (watched == 'watched'){ localStorage.setItem(realTitle, 'unwatched'); parse(); } if (watched == 'unwatched'){ localStorage.setItem(realTitle, 'watched'); parse(); } }else if (!watched){ localStorage.setItem(realTitle, 'unwatched'); } }catch(e){ console.error('*&* ' + e); } } var buttonlink = document.getElementById('buttonlink'); buttonlink.addEventListener('click', clicked); parse(); ` function runTests(){ var serverList = document.querySelectorAll('div.anime_muti_link > ul > li > a'); serverList = Array.from(serverList); var pings = []; serverList.forEach(a => { let video = a.dataset.video; let name = a.textContent.split('Choose this server')[0] a.innerHTML = `${name}: ... Choose this server`; // a.id = Math.random().toString(36).substr(7); a.classList.add('serveroption'); pings.push(ping(video, 0.3).then(delta => { let aproxdelta = Math.round(delta); a.innerHTML = `${name}: ${aproxdelta} Choose this server`; a.dataset.ping = aproxdelta; a.dataset.truePing = delta; }).catch(e => { let name = a.textContent.split('Choose this server')[0]; console.error(e); a.innerHTML = `${name}: Error! Choose this server` a.dataset.ping = '99999'; a.dataset.truePing = '99999'; })); }); Promise.allSettled(pings).then(res => { var elements = Array.from(document.querySelectorAll('a.serveroption')); elements.sort((a, b) => { let an = a.dataset.truePing; let bn = b.dataset.truePing; return an - bn; }); let ul = document.querySelector('div.anime_muti_link > ul') elements.forEach(node => { node = node.parentNode; let newnode = node.cloneNode(true); node.remove(); ul.append(newnode); }); }) } function extendImportFunctionality(){ var storedObj = localStorage; var storedString = JSON.stringify(storedObj); var menuplace = document.querySelector('div.submenu_intro'); var divider1 = document.createElement('span'); divider1.textContent = '|'; var divider2 = divider1.cloneNode(); menuplace.appendChild(divider1); var importlink = document.createElement('a'); importlink.href = 'javascript:void(0);'; importlink.id = 'import-link'; menuplace.appendChild(importlink); importlink = document.getElementById('import-link'); var importlabel = document.createElement('label'); importlabel.htmlFor = 'import-button'; importlabel.id = 'import-label'; importlabel.textContent = ' Import '; importlink.appendChild(importlabel); var importbt = document.createElement('input'); importbt.type = 'File' importbt.id = 'import-button'; importbt.style.height = '1px'; importbt.style.width = '1px'; importbt.accept = '.gga'; menuplace.appendChild(importbt); menuplace.appendChild(divider2); var today = new Date(); var dd = String(today.getDate()).padStart(2, '0'); var mm = String(today.getMonth() + 1).padStart(2, '0'); //January is 0! var yyyy = today.getFullYear(); var exportlink = document.createElement('a'); exportlink.href = `data:text/plain;charset=utf-8, ${encodeURIComponent(storedString)}`; exportlink.id = 'export-link'; exportlink.textContent = ' Export '; exportlink.download = `gogoanime-backup-${mm}-${dd}-${yyyy}.gga`; menuplace.appendChild(exportlink); importlink = document.getElementById('import-link'); var head = document.querySelector('head'); var injectorsrc = document.createElement('script'); injectorsrc.innerHTML = impexpclientcode; injectorsrc.id = 'injectedjs'; head.appendChild(injectorsrc); } function appendWatchButton(){ try { var head = document.querySelector('head'); var titlebox = document.querySelector('.title_name > h2'); var title = titlebox.textContent; var titleheader = document.querySelector('div.anime_video_body > h1'); titleheader.textContent = title; var vbox = document.querySelector('div.anime_video_body_cate'); var buttonlink = document.createElement('a'); buttonlink.href = "javascript:void(0);"; buttonlink.id = "buttonlink"; vbox.appendChild(buttonlink); buttonlink = document.getElementById('buttonlink'); var buttonspan = document.createElement('span'); buttonspan.id = 'buttonspan'; buttonspan.style.marginLeft = '0.8em'; buttonspan.classList.add("btndownload"); buttonspan.textContent = 'Mark as Watched'; buttonlink.appendChild(buttonspan); var script = document.createElement('script'); script.type = 'application/javascript'; script.id = 'injectedsc'; script.innerHTML = injectsrc; head.appendChild(script); }catch(e){ console.error(e); } } function removeSocialIcons(){ try{ let icons = document.querySelectorAll('div.link_face'); icons.forEach((div) => div.parentNode.removeChild(div)); }catch(e){ console.error(e); } } function getTitle(){ let title = document.title; title = title.split(' at ') } function showpageCont(episodeListings){ let title = document.querySelector('div.anime_info_body_bg > h1').textContent; let episodeStringNames = episodeListings.map((div) => title + " " + div.textContent.replace('EP', "Episode")); for (let val in episodeStringNames){ let name = episodeStringNames[val]; let node = episodeListings[val]; let watchstatus = localStorage.getItem(name); if (!watchstatus){ watchstatus = "unwatched"; } if (watchstatus == "watched"){ node.textContent = "*" + node.textContent + "*"; } } } function showpage(){ var titlebox = document.querySelector('div.anime_info_body_bg > h1'); title = titlebox.textContent; var findEps = setInterval(findEpisodes, 100); function findEpisodes(){ let episodeListings = document.querySelectorAll('div.name'); if (episodeListings.length != 0){ clearInterval(findEps); showpageCont(Array.from(episodeListings)); } } } function watchpage2(){ var titlebox = document.querySelector('.title_name > h2'); title = titlebox.textContent; var findEps = setInterval(findEpisodes, 100); function wpwrite(episodes){ title = document.querySelector('div.anime-info > a').textContent; let episodeStringNames = episodes.map((div) => title + " " + div.textContent.replace('EP', "Episode")); for (let val in episodeStringNames){ let name = episodeStringNames[val]; let node = episodes[val]; let watchstatus = localStorage.getItem(name); if (!watchstatus){ watchstatus = "unwatched"; } if (watchstatus == "watched"){ node.textContent = "*" + node.textContent + "*"; } } } function findEpisodes(){ let episodeListings = document.querySelectorAll('div.name'); if (episodeListings.length != 0){ clearInterval(findEps); wpwrite(Array.from(episodeListings)); } } } function markNextandLastButtons(){ let previous = document.querySelector('div.anime_video_body_episodes_l > a'); let prevepisode = previous.textContent; prevepisode = prevepisode.split('<< ')[1].trim(); if (localStorage.getItem(prevepisode) == 'watched'){ previous.textContent = `<< *${prevepisode}*`; } let next = document.querySelector('div.anime_video_body_episodes_r > a'); let nextepisode = next.textContent; nextepisode = nextepisode.split(' >>')[0].trim(); if (localStorage.getItem(nextepisode) == 'watched'){ next.textContent = `*${nextepisode}* >>`; } } function watchpage(){ //Fix Spelling Mistake: var divopps = document.querySelector('div.anime_video_body > div:nth-of-type(5)').textContent = "Please scroll down to select a server."; document.title = `${document.title} Plus`; runTests(); appendWatchButton(); markNextandLastButtons(); watchpage2(); } // Init: const url = window.location; var htmltest = new RegExp(/https:\/\/.*\.gogoanime\.io\/.*\.html.*/, 'gi'); var showpagetest = new RegExp(/.*gogoanime.io\/(?=(category\/)).*/, 'gi'); var watchpagetest = new RegExp(/.*gogoanime.io\/(?!(category))(?!(genre))(?!(.*\.html)).+/, 'gi'); var mainpagetest = new RegExp(/.*gogoanime.io\/(?!.{2,})/, 'gi'); var genretest = new RegExp(/.*gogoanime.io\/(?=(genre\/)).*/, 'gi'); var showres = showpagetest.test(url); var watchres = watchpagetest.test(url); removeSocialIcons(); extendImportFunctionality(); if (watchres){ watchpage(); } if (showres){ window.addEventListener('load', showpage, false); } })();