This script auto performs a few checks daily to notify you when specific anime/manga entries gets approved or denied.
当前为
// ==UserScript==
// @name Approved Entries Notifier - MAL
// @namespace NotifyWhenApproved
// @version 0.1
// @description This script auto performs a few checks daily to notify you when specific anime/manga entries gets approved or denied.
// @author hacker09
// @match https://myanimelist.net/*
// @icon https://www.google.com/s2/favicons?domain=myanimelist.net
// @run-at document-end
// @grant GM_setClipboard
// @grant GM_notification
// @grant GM_deleteValue
// @grant GM_listValues
// @grant GM_getValue
// @grant GM_setValue
// ==/UserScript==
(async function() {
'use strict';
var ActualTime = new Date().getHours(); //Save the actual time in a variable
var UnnapprovedAnimes = []; //Store all the unapproved animes in this array later
var UnnapprovedMangas = []; //Store all the unapproved mangas in this array later
var ChecknapprovedAnimes = []; //Store all the animes stored in tampermonkey in this array later
var CheckapprovedMangas = []; //Store all the mangas stored in tampermonkey in this array later
var ApprovedAnimeLinks = []; //Create a new blank array
var ApprovedMangaLinks = []; //Create a new blank array
var Three_Hours_From_LastTime = new Date(new Date().setHours(GM_getValue('Last_Check_Hour') + 3)).getHours(); //Check when it's going to be 3 hours from the last check time
var EntryType = location.pathname.split('/')[1]; //Store the Entry type
var EntryID = location.pathname.match(/\d+/)[0]; //Store the Entry ID
GM_listValues().forEach(function(a) { //For each stored value on tampermonkey
if (a.match('anime') !== null) //If the saved value is an anime id
{ //Starts the if condition
ChecknapprovedAnimes.push(a.match(/\d+/)[0]); //Add the stored anime id to an array
} //Finishes the if condition
if (a.match('manga') !== null) //If the saved value is a manga id
{ //Starts the if condition
CheckapprovedMangas.push(a.match(/\d+/)[0]); //Add the stored manga id to an array
} //Finishes the if condition
}); //Add all Entry IDs and types on tampermonkey to the array
if (GM_getValue('Last_Check_Hour') === undefined || GM_getValue('Last_Day_MAL_Was_Opened') === undefined || GM_getValue('Last_Check_Hour') >= Three_Hours_From_LastTime || (GM_getValue('Last_Check_Hour') <= Three_Hours_From_LastTime && new Date().getDate() !== GM_getValue('Last_Day_MAL_Was_Opened'))) //If the Last_Check_Hour or the Last_Day_MAL_Was_Opened variables wasn't set yet
//Or if 3 or more hours since the last check time has passed
//Or if the actual time is before the 3 hours from the last check time and if today is a another day
{ //Starts the if condition
GM_setValue('Last_Check_Hour', ActualTime); //Get and save the last check hour
GM_setValue('Last_Day_MAL_Was_Opened', new Date().getDate()); //Get and save the Last_Day_MAL_Was_Opened
const response = await fetch(`https://api.allorigins.win/raw?url=${encodeURIComponent('https://sean.fish/mal_unapproved/anime')}`); //Fetch
const html = await response.text(); //Gets the fetch response
const newDocument = new DOMParser().parseFromString(html, 'text/html'); //Parses the fetch response
newDocument.querySelectorAll("#mal-unapproved > ol > li").forEach(a => UnnapprovedAnimes.push(a.innerText.match(/\d+/)[0])); //Store all unnapproved anime entries on the array
const response2 = await fetch(`https://api.allorigins.win/raw?url=${encodeURIComponent('https://sean.fish/mal_unapproved/manga')}`); //Fetch
const html2 = await response2.text(); //Gets the fetch response
const newDocument2 = new DOMParser().parseFromString(html2, 'text/html'); //Parses the fetch response
newDocument2.querySelectorAll("#mal-unapproved > ol > li").forEach(a => UnnapprovedMangas.push(a.innerText.match(/\d+/)[0])); //Store all unnapproved manga entries on the array
var FinalApprovedAnimesArray = ChecknapprovedAnimes.filter(d => !UnnapprovedAnimes.includes(d)); //Get the entry ids that the user is waiting to be approved but sean's website are missing
var FinalApprovedMangasArray = CheckapprovedMangas.filter(d => !UnnapprovedMangas.includes(d)); //Get the entry ids that the user is waiting to be approved but sean's website are missing
if (FinalApprovedAnimesArray.length !== 0 || FinalApprovedMangasArray.length !== 0) //If there's at least 1 entry id we want to know that got approved and is not on sean's website (the entry got approved)
{ //Starts the if condition
FinalApprovedAnimesArray.forEach(a => ApprovedAnimeLinks.push('https://myanimelist.net/anime/' + a)); //Create an array of approved anime links
FinalApprovedMangasArray.forEach(a => ApprovedMangaLinks.push('https://myanimelist.net/manga/' + a)); //Create an array of approved manga links
window.onload = function() { //Starts the function when the website finished loading
GM_notification({ //Shows a browser notification
title: 'Found Approved Entries',
text: 'Click on here to open or copy the approved entries links',
image: 'https://i.imgur.com/RmsXhIl.jpg',
highlight: true,
silent: true,
timeout: 15000, //Define the browser notification details
onclick: () => { //If the browser notification is clicked
if (FinalApprovedAnimesArray.length !== 0 || FinalApprovedMangasArray.length !== 0) //If there's at least 1 entry id we want to know when is approved is not on sean's website (the anime got approved)
{ //Starts the if condition
var JoinedArrays = ApprovedAnimeLinks.concat(ApprovedMangaLinks); //Join both arrays
if (confirm('Click on OK to open ' + JoinedArrays.length + ' approved entries links\nClick on Cancel to copy ' + JoinedArrays.length + ' approved entries links')) { //Give an option to the user
JoinedArrays.forEach(a => window.open(a, '_blank')); //Open all the approved entries links
} //Finishes the if condition
else //If the user clicked on Cancel
{ //Starts the else condition
GM_setClipboard(JoinedArrays.join('\n')); //Copy the approved entries links
} //Finishes the else condition
} //Finishes the if condition
window.focus(); //Refocus on the actual tab
FinalApprovedAnimesArray.forEach(a => GM_deleteValue('anime' + a)); //Erase all the approved animes IDs stored on tampermonkey
FinalApprovedMangasArray.forEach(a => GM_deleteValue('manga' + a)); //Erase all the approved mangas IDs stored on tampermonkey
} //Finishes the onclick event listener
}); //Finishes the browser notification definitions
}; //Finishes the onload event listener
} //Finishes the if condition
} //Finishes the if condition
if (document.querySelector("span.disabled-btn-user-status-add-list") !== null) //If an unapproved entry was opened
{ //Starts the if condition
document.querySelector("span.disabled-btn-user-status-add-list").className = 'btn-user-status-add-list js-form-user-status js-form-user-status-btn myinfo_addtolist'; //Make the button look better
document.querySelector("span.btn-user-status-add-list.js-form-user-status.js-form-user-status-btn.myinfo_addtolist").innerText = 'Notify when Approved'; //Give the user the option to get notified to know when the entry gets approved
document.querySelector("span.btn-user-status-add-list.js-form-user-status.js-form-user-status-btn.myinfo_addtolist").onclick = function() //If the Notify when Approved button is clicked
{ //Starts the onclick listener
GM_notification({ //Shows a browser notification
title: "You will be notified when this entry get's approved!",
text: ' ',
image: 'https://i.imgur.com/RmsXhIl.jpg',
highlight: true,
silent: true,
timeout: 2000, //Define the browser notification details
onclick: () => { //If the browser notification is clicked
window.focus(); //Refocus on the tab
} //Finishes the onclick event listener
}); //Finishes the browser notification definitions
GM_setValue(EntryType + EntryID, ''); //Get and save the Entry type and entry id
} //Finishes the onclick listener
document.querySelector("div.js-myinfo-error.badresult-text.al.pb4").remove(); //Remove the error message
} //Finishes the if condition
})();
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址