// ==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);
}
})();