NOTICE: By continued use of this site you understand and agree to the binding Terms of Service and Privacy Policy.
// ==UserScript== // @name GoGoAnime Plus // @namespace http://tampermonkey.net/ // @version 1.3.00 // @description Adds a watch tracker, server ranking, and show ratings to gogoanime.sx. // @author Sadie Hensley // @license ISC // @match https://*.gogoanime.sx/* // @require https://cdn.jsdelivr.net/npm/web-pingjs@1.0.1/ping.min.js // @grant none // @noframes // ==/UserScript== // COPY FROM https://openuserjs.org/scripts/Togooroo/GoGoAnime_Plus // CHANGED domain (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(); ` async function getRatings() { function appendRating(ratscore) { let valuesSection = document.querySelector('div.anime_info_body_bg'); let plotsumm; for (let el in valuesSection.children) { let node = valuesSection.children[el]; if (node.textContent.includes('Plot Summary:')) { plotsumm = valuesSection.children[el]; break; } } let scoreElement = document.createElement('p'); scoreElement.classList.add('type'); scoreElement.id = 'mal_rating'; scoreElement.innerHTML = `<span>Rating:</span> <span id='colorelement'>${ratscore}/10</span>`; valuesSection.insertBefore(scoreElement, plotsumm); let colorele = document.getElementById('colorelement'); if (ratscore <= 4.9) { colorele.style.color = 'red'; } else if (ratscore <= 5.9) { colorele.style.color = 'yellow'; } else if (ratscore <= 7.9) { colorele.style.color = 'white'; } else if (ratscore >= 8.0) { // Green (Default) } } async function checkCache(cval) { let id = await fetch(`https://api.jikan.moe/v3/search/anime?q=${title}`); id = await id.json(); id = await id.results[0].mal_id; let show = await fetch(`https://api.jikan.moe/v3/anime/${id}`); show = await show.json(); let score = await show.score; score = await parseFloat(score).toFixed(1); if (score != cval) { document.getElementById('mal_rating').remove(); appendRating(score); localStorage.setItem(`${title}-score`, score); } } let title = document.querySelector('div.anime_info_body_bg > h1').textContent; let valuesSection = document.querySelector('div.anime_info_body_bg'); let cachedValue = localStorage.getItem(`${title}-score`); if (cachedValue && !isNaN(cachedValue)) { console.log('Getting from cache'); appendRating(cachedValue); checkCache(cachedValue); } else { let id = await fetch(`https://api.jikan.moe/v3/search/anime?q=${title}`); id = await id.json(); id = await id.results[0].mal_id; let show = await fetch(`https://api.jikan.moe/v3/anime/${id}`); show = await show.json(); let score = await show.score; score = await parseFloat(score).toFixed(1); appendRating(score); localStorage.setItem(`${title}-score`, score); } } 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}: ... <span>Choose this server</span>`; // 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} <span>Choose this server</span>`; 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! <span>Choose this server</span>` 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 div = document.querySelector('div.anime_muti_link') let oldul = document.querySelector('div.anime_muti_link > ul'); let ul = document.createElement('ul'); ul.id = 'sorted_ul'; div.prepend(ul); ul = document.getElementById('sorted_ul'); elements.forEach(node => { node = node.parentNode; ul.append(node); }); oldul.remove(); }) } 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'); let title = titlebox.textContent; /* var title = titlebox.textContent.includes('English Subbed') ? titlebox.textContent.replace('English Subbed', '').trim() : titlebox.textContent; */ if (title.includes('English Subbed')) { title = title.replace('English Subbed', '').trim(); titlebox.textContent = title; } 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 markEpisodeListings(episodeListings) { let title = document.querySelector('div.anime_info_body_bg > h1').textContent; let subbedmode = title.includes('English Subbed'); var findEps = setInterval(findEpisodes, 100); function wpwrite(episodes) { // let episodeStringNames = episodes.map((div) => `${title} ${}`); let episodeStringNames = episodes.map((div) => { let epnumber = div.textContent.match(/\d+/)[0]; return `${title} Episode ${epnumber}`; }) let watchcounter = 0; let total = episodeStringNames.length; 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 + "*"; watchcounter++; } } let counter = { "watched": watchcounter, "total": total }; appendWatchList(counter); } function appendWatchList(counter) { let { watched, total } = counter; let valuesSection = document.querySelector('div.anime_info_body_bg'); // console.log(valuesSection); let watchedElement = document.createElement('p'); watchedElement.classList.add('type'); watchedElement.id = 'watchedNumber'; watchedElement.innerHTML = `<span>Watched:</span> ${watched}/${total} Episodes`; valuesSection.appendChild(watchedElement); } function findEpisodes() { let episodeListings = document.querySelectorAll('div.name'); if (episodeListings.length != 0) { clearInterval(findEps); wpwrite(Array.from(episodeListings)); } } } function showpage() { getRatings(); let 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); markEpisodeListings(Array.from(episodeListings)); } } } function markBoxBelowVideo() { var titlebox = document.querySelector('.title_name > h2'); title = titlebox.textContent; let subbedmode = title.includes('English Subbed'); var findEps = setInterval(findEpisodes, 100); function wpwrite(episodes) { let maintitle = document.querySelector('div.anime-info > a').textContent; let episodeStringNames = episodes.map((div) => { let epnumber = div.textContent.match(/\d+/)[0]; return title.includes('(Watched)') ? title.replace('(Watched)', '').replace(/\d+/, epnumber).trim() : title.replace(/\d+/, epnumber); }) 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 title = document.querySelector('div.anime_video_body > h1').textContent; title = title.includes('(Watched)') ? title.replace('(Watched)', '').trim() : title; let subbedmode = title.includes('English Subbed') ? true : false; console.log(title); let previous = document.querySelector('div.anime_video_body_episodes_l > a'); if (previous) { let prevepisode = subbedmode ? `${previous.textContent} English Subbed` : previous.textContent; prevepisode = prevepisode.split('<< ')[1].trim(); if (localStorage.getItem(prevepisode) == 'watched') { previous.textContent = `<< *${prevepisode.replace(' English Subbed', '')}*`; } } let next = document.querySelector('div.anime_video_body_episodes_r > a'); if (next) { let nextepisode = subbedmode ? `${next.textContent} English Subbed` : 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(); markBoxBelowVideo(); } // 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); } })();