Return Youtube Dislike On Mobile

Return dislikes on youtube mobile page. Uses returnyoutubedislike.com API

安装此脚本?
作者推荐脚本

您可能也喜欢Remove Youtube Propaganda

安装此脚本
  1. // ==UserScript==
  2. // @name Return Youtube Dislike On Mobile
  3. // @namespace https://gitlab.com/Dwyriel
  4. // @version 1.3.5
  5. // @description Return dislikes on youtube mobile page. Uses returnyoutubedislike.com API
  6. // @author Dwyriel
  7. // @license MIT
  8. // @match *://*.youtube.com/*
  9. // @grant none
  10. // @homepageURL https://gitlab.com/Dwyriel/Greasyfork-Scripts
  11. // ==/UserScript==
  12.  
  13. (function () {
  14. 'use strict';
  15. const scriptName = "[Return Youtube Dislike On Mobile]";
  16. const scriptPolicyName = "RYDoM_Policy";
  17. const API_URL = "https://returnyoutubedislikeapi.com/votes?videoId=";
  18. const buttonSegmentClass = "ytSegmentedLikeDislikeButtonViewModelSegmentedButtonsWrapper";
  19. const dislikeButtonID = "dislikeButtonID_198wa16df78ms1d";
  20.  
  21. let dislikeCache = {};
  22. let oldURL = "";
  23. let videoID;
  24. let fetching = false;
  25.  
  26. const config = { attributes: true, childList: true, subtree: true };
  27. let mutationObserver = new MutationObserver(() => { });
  28.  
  29. const getVideoID = () => {
  30. return (new Proxy(new URLSearchParams(window.location.search), { get: (UrlSearchParams, key) => UrlSearchParams.get(key) })).v;
  31. }
  32.  
  33. const formatedDislikeNumber = () => {
  34. let dislikes = dislikeCache[videoID];
  35. let formattedNum = "";
  36. if (dislikes / 10E8 >= 1)
  37. formattedNum = `${Math.round(dislikes / 10E8)}B`;
  38. else if (dislikes / 10E5 >= 1)
  39. formattedNum = `${Math.round(dislikes / 10E5)}M`;
  40. else if (dislikes / 1000 >= 1) {
  41. if (dislikes < 10E3)
  42. formattedNum += `${Math.floor(dislikes / 1000)}.${Math.floor((dislikes % 1000) / 100)}K`;
  43. else
  44. formattedNum = `${Math.round(dislikes / 1000)}K`;
  45. }
  46. else
  47. formattedNum = `${dislikes}`;
  48. return formattedNum;
  49. }
  50.  
  51. const setInnerHTML = (element, html) => {
  52. try {
  53. if (trustedTypes) {
  54. const trustedTypesPolice = trustedTypes.createPolicy(scriptPolicyName, { createHTML: (string) => string });
  55. element.innerHTML = trustedTypesPolice.createHTML(html);
  56. } else {
  57. element.innerHTML = html;
  58. }
  59. } catch (err) {
  60. console.error(err);
  61. }
  62. }
  63.  
  64. const modifyDislikeButton = () => { //check explanation at the end of the file
  65. let buttons = document.getElementsByClassName(buttonSegmentClass)[0].children;
  66. if (buttons.length == 0)
  67. return;
  68. document.getElementById(dislikeButtonID)?.remove();
  69. let dislikeButton = buttons[1].getElementsByTagName("button")[0];
  70. dislikeButton.children[0].style = "margin: 0 6px 0 -6px";
  71. let dislikes = buttons[0].getElementsByClassName("yt-spec-button-shape-next__button-text-content")[0].cloneNode(true);
  72. dislikes.id = dislikeButtonID;
  73. dislikeButton.appendChild(dislikes);
  74. dislikeButton.appendChild(dislikeButton.children[1]);
  75. let dislikeString = formatedDislikeNumber();
  76. setInnerHTML(dislikes, dislikeString);
  77. dislikeButton.style = `width: ${62 + (8 * dislikeString.length)}px !important; padding-left: 14px`;
  78. }
  79.  
  80. let hookObserver = async () => {
  81. let buttons = document.getElementsByClassName(buttonSegmentClass);
  82. if (buttons.length > 0 && buttons[0].children != undefined) {
  83. mutationObserver.disconnect();
  84. modifyDislikeButton();
  85. mutationObserver.observe(buttons[0], config);
  86. }
  87. else
  88. await new Promise(() => setTimeout(hookObserver, 100));
  89. }
  90.  
  91. const callback = () => {
  92. let currURL = window.location.href;
  93. if (window.location.pathname != "/watch") {
  94. oldURL = currURL;
  95. return;
  96. }
  97. if (fetching || (oldURL == currURL))
  98. return;
  99. fetching = true;
  100. oldURL = currURL;
  101.  
  102. videoID = getVideoID();
  103. if (typeof videoID != 'string') {
  104. fetching = false;
  105. return;
  106. }
  107.  
  108. if (dislikeCache[videoID] != undefined) {
  109. fetching = false;
  110. hookObserver();
  111. return;
  112. }
  113.  
  114. let request = new Request(API_URL + videoID);
  115. fetch(request).then(response => response.json(), (reason) => { fetching = false; console.error("Couldn't fetch dislikes", reason) }).then(response => {
  116. console.log(`${scriptName} response from api: \n${JSON.stringify(response)}`);
  117. dislikeCache[videoID] = response.dislikes;
  118. fetching = false;
  119. hookObserver();
  120. }, (reason) => { fetching = false; console.error("Couldn't fetch dislikes", reason) });
  121. };
  122.  
  123. mutationObserver = new MutationObserver(() => {
  124. hookObserver();
  125. });
  126.  
  127. const old_pushState = history.pushState;
  128. history.pushState = function pushState() {
  129. let origFuncReturn = old_pushState.apply(this, arguments);
  130. window.dispatchEvent(new Event('historyChanged'));
  131. return origFuncReturn;
  132. };
  133.  
  134. window.addEventListener('popstate', () => window.dispatchEvent(new Event('historyChanged')));
  135. window.addEventListener('load', () => callback());
  136. window.addEventListener('historyChanged', () => {
  137. mutationObserver.disconnect();
  138. callback();
  139. });
  140. })();
  141.  
  142. /* modifyDislikeButton function explanation
  143.  
  144. let buttons = document.getElementsByClassName(buttonSegmentClass)[0].children; //get both like and dislike buttons if they exist
  145. if (buttons.length == 0)
  146. return;
  147.  
  148. document.getElementById(dislikeButtonID)?.remove(); //remove if it was already created before
  149.  
  150. let dislikeButton = buttons[1].getElementsByTagName("button")[0]; //the dislike "button" element
  151. dislikeButton.children[0].style = "margin: 0 6px 0 -6px"; //fix margin to accomodate changes
  152.  
  153. let dislikes = buttons[0].getElementsByClassName("yt-spec-button-shape-next__button-text-content")[0].cloneNode(true); //clone the text tag of the like button to be added to the dislike
  154.  
  155. dislikes.id = dislikeButtonID; //set custom ID
  156.  
  157. dislikeButton.appendChild(dislikes); //append cloned node to dislike button
  158.  
  159. dislikeButton.appendChild(dislikeButton.children[1]); //move nodes around to be in the same order as the like button
  160.  
  161. let dislikeString = formatedDislikeNumber(); //formats and adds the formated string to the cloned node's inner HTML
  162. dislikes.innerHTML = dislikeString;
  163.  
  164. dislikeButton.style = `width: ${56 + (8 * dislikeString.length)}px`; //adjust button width based on formated string
  165. */

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址