Return dislikes on youtube mobile page. Uses returnyoutubedislike.com API
当前为
// ==UserScript==
// @name Return Youtube Dislike On Mobile
// @namespace https://gitlab.com/Dwyriel
// @version 1.2
// @description Return dislikes on youtube mobile page. Uses returnyoutubedislike.com API
// @author Dwyriel
// @license MIT
// @match *://*.youtube.com/*
// @grant none
// @homepageURL https://gitlab.com/Dwyriel/Greasyfork-Scripts
// ==/UserScript==
(function () {
'use strict';
const scriptName = "[Return Youtube Dislike On Mobile]";
const API_URL = "https://returnyoutubedislikeapi.com/votes?videoId=";
const buttonSegmentClass = "YtSegmentedLikeDislikeButtonViewModelSegmentedButtonsWrapper";
const dislikeButtonID = "dislikeButtonID_198wa16df78ms1d";
let dislikeCache = {};
let oldURL = "";
let videoID;
let fetching = false;
const config = { attributes: true, childList: true, subtree: true };
let mutationObserver = new MutationObserver(() => { });
const getVideoID = () => {
return (new Proxy(new URLSearchParams(window.location.search), { get: (UrlSearchParams, key) => UrlSearchParams.get(key) })).v;
}
const formatedDislikeNumber = () => {
let dislikes = dislikeCache[videoID];
let formattedNum = 0, character = '';
if (dislikes / 1000000000 >= 1) {
formattedNum = Math.round(dislikes / 1000000000);
character = 'B';
} else if (dislikes / 1000000 >= 1) {
formattedNum = Math.round(dislikes / 1000000);
character = 'M';
} else if (dislikes / 1000 >= 1) {
formattedNum = Math.round(dislikes / 1000);
character = 'K';
} else
formattedNum = dislikes;
return formattedNum + character;
}
const modifyDislikeButton = () => { //check explanation at the end of the file
let buttons = document.getElementsByClassName(buttonSegmentClass)[0].children;
if (buttons.length == 0)
return;
document.getElementById(dislikeButtonID)?.remove();
let dislikeButton = buttons[1].children[0].children[0];
dislikeButton.children[0].style = "margin: 0 6px 0 -6px";
let dislikes = buttons[0].children[0].children[0].children[1].cloneNode(true);
dislikes.id = dislikeButtonID;
dislikeButton.appendChild(dislikes);
dislikeButton.appendChild(dislikeButton.children[1]);
let dislikeString = formatedDislikeNumber();
dislikes.innerHTML = dislikeString;
dislikeButton.style = `width: ${56 + (8 * dislikeString.length)}px`;
}
let hookObserver = async () => {
let buttons = document.getElementsByClassName(buttonSegmentClass);
if (buttons.length > 0 && buttons[0].children != undefined) {
mutationObserver.disconnect();
modifyDislikeButton();
mutationObserver.observe(buttons[0].children[0].parentNode, config);
}
else
await new Promise(() => setTimeout(hookObserver, 100));
}
const callback = () => {
let currURL = window.location.href;
if (window.location.pathname != "/watch") {
oldURL = currURL;
return;
}
if (fetching || (oldURL == currURL))
return;
fetching = true;
oldURL = currURL;
videoID = getVideoID();
if (typeof videoID != 'string') {
fetching = false;
return;
}
if (dislikeCache[videoID] != undefined) {
fetching = false;
hookObserver();
return;
}
let request = new Request(API_URL + videoID);
fetch(request).then(response => response.json(), (reason) => { fetching = false; console.error("Couldn't fetch dislikes", reason) }).then(response => {
console.log(`${scriptName} response from api: \n${JSON.stringify(response)}`);
dislikeCache[videoID] = response.dislikes;
fetching = false;
hookObserver();
}, (reason) => { fetching = false; console.error("Couldn't fetch dislikes", reason) });
};
mutationObserver = new MutationObserver(() => {
hookObserver();
});
const old_pushState = history.pushState;
history.pushState = function pushState() {
let origFuncReturn = old_pushState.apply(this, arguments);
window.dispatchEvent(new Event('historyChanged'));
return origFuncReturn;
};
window.addEventListener('popstate', () => window.dispatchEvent(new Event('historyChanged')));
window.addEventListener('load', () => callback());
window.addEventListener('historyChanged', () => {
mutationObserver.disconnect();
callback();
});
})();
/* modifyDislikeButton function explanation
let buttons = document.getElementsByClassName(buttonSegmentClass)[0].children; //get both like and dislike buttons if they exist
if (buttons.length == 0)
return;
document.getElementById(dislikeButtonID)?.remove(); //remove if it was already created before
let dislikeButton = buttons[1].children[0].children[0]; //the dislike "button" tag
dislikeButton.children[0].style = "margin: 0 6px 0 -6px"; //fix margin to accomodate changes
let dislikes = buttons[0].children[0].children[0].children[1].cloneNode(true); //clone the text tag of the like button to be added to the dislike
dislikes.id = dislikeButtonID; //set custom ID
dislikeButton.appendChild(dislikes); //append cloned node to dislike button
dislikeButton.appendChild(dislikeButton.children[1]); //move nodes around to be in the same order as the like button
let dislikeString = formatedDislikeNumber(); //formats and adds the formated string to the cloned node's inner HTML
dislikes.innerHTML = dislikeString;
dislikeButton.style = `width: ${56 + (8 * dislikeString.length)}px`; //adjust button width based on formated string
*/