فهرست منبع

Merge pull request #115 from DARKDRAGON532/patch-1

Userscript now fetches from youtube
Dmitrii Selivanov 3 سال پیش
والد
کامیت
1e4d5f3601
1فایلهای تغییر یافته به همراه67 افزوده شده و 48 حذف شده
  1. 67 48
      Extensions/UserScript/Return Youtube Dislike.user.js

+ 67 - 48
Extensions/UserScript/Return Youtube Dislike.user.js

@@ -19,33 +19,9 @@ function cLog(text, subtext = '') {
   console.log(`[Return YouTube Dislikes] ${text} ${subtext}`);
 }
 
-function doXHR(opts) {
-  if (typeof GM_xmlhttpRequest === 'function') {
-    return GM_xmlhttpRequest(opts);
-  }
-  if (typeof GM !== 'undefined') /*This will prevent from throwing "Uncaught ReferenceError: GM is not defined"*/ {
-    if (typeof GM.xmlHttpRequest === 'function') {
-      return GM.xmlHttpRequest(opts);
-    }
-  }
-
-  console.warn('Unable to detect UserScript plugin, falling back to native XHR.');
-
-  const xhr = new XMLHttpRequest();
-
-  xhr.open(opts.method, opts.url, true);
-  xhr.onload = () => opts.onload({
-    response: JSON.parse(xhr.responseText),
-  });
-  xhr.onerror = err => console.error('XHR Failed', err);
-  xhr.send();
-}
-
 function getButtons() {
   if (document.getElementById("menu-container").offsetParent === null) {
-    return document.querySelector(
-      "ytd-menu-renderer.ytd-watch-metadata > div"
-    );
+    return document.querySelector("ytd-menu-renderer.ytd-watch-metadata > div");
   } else {
     return document
       .getElementById("menu-container")
@@ -96,9 +72,7 @@ function setDislikes(dislikesCount) {
 }
 
 function createRateBar(likes, dislikes) {
-  var rateBar = document.getElementById(
-    "return-youtube-dislike-bar-container"
-  );
+  var rateBar = document.getElementById("return-youtube-dislike-bar-container");
 
   const widthPx =
     getButtons().children[0].clientWidth +
@@ -144,32 +118,46 @@ function createRateBar(likes, dislikes) {
 }
 
 function setState() {
-  cLog('Fetching votes...');
-
-  doXHR({
-    method: "GET",
-    responseType: "json",
-    url:
-      "https://return-youtube-dislike-api.azurewebsites.net/votes?videoId=" +
-      getVideoId(),
-    onload: function (xhr) {
-      if (xhr != undefined) {
-        const { dislikes, likes } = xhr.response;
+  cLog("Fetching votes...");
+  let statsSet = false;
+
+  fetch(`https://www.youtube.com/watch?v=${getVideoId()}`).then((response) => {
+    response.text().then((text) => {
+      let result = getDislikesFromYoutubeResponse(text);
+      if (result) {
+        cLog("response from youtube:");
+        cLog(JSON.stringify(result));
+        if (result.likes || result.dislikes) {
+          const formattedDislike = numberFormat(result.dislikes);
+          setDislikes(formattedDislike);
+          createRateBar(result.likes, result.dislikes);
+          statsSet = true;
+        }
+      }
+    });
+  });
+
+  fetch(
+    `https://return-youtube-dislike-api.azurewebsites.net/votes?videoId=${getVideoId()}`
+  ).then((response) => {
+    response.json().then((json) => {
+      if (json && !statsSet) {
+        const { dislikes, likes } = json;
         cLog(`Received count: ${dislikes}`);
         setDislikes(numberFormat(dislikes));
         createRateBar(likes, dislikes);
       }
-    },
+    });
   });
 }
 
 function likeClicked() {
-  cLog('Like clicked', getState());
+  cLog("Like clicked", getState());
   setState();
 }
 
 function dislikeClicked() {
-  cLog('Dislike clicked', getState());
+  cLog("Dislike clicked", getState());
   setState();
 }
 
@@ -197,19 +185,50 @@ function roundDown(num) {
   const int = Math.floor(Math.log10(num) - 2);
   const decimal = int + (int % 3 ? 1 : 0);
   const value = Math.floor(num / 10 ** decimal);
-  return value * (10 ** decimal);
+  return value * 10 ** decimal;
 }
 
 function numberFormat(numberState) {
   const userLocales = navigator.language;
 
   const formatter = Intl.NumberFormat(userLocales, {
-    notation: 'compact',
+    notation: "compact",
     minimumFractionDigits: 1,
-    maximumFractionDigits: 1
+    maximumFractionDigits: 1,
   });
 
-  return formatter.format(roundDown(numberState)).replace(/\.0|,0/, '');
+  return formatter.format(roundDown(numberState)).replace(/\.0|,0/, "");
+}
+
+function getDislikesFromYoutubeResponse(htmlResponse) {
+  let start =
+    htmlResponse.indexOf('"videoDetails":') + '"videoDetails":'.length;
+  let end =
+    htmlResponse.indexOf('"isLiveContent":false}', start) +
+    '"isLiveContent":false}'.length;
+  if (end < start) {
+    end =
+      htmlResponse.indexOf('"isLiveContent":true}', start) +
+      '"isLiveContent":true}'.length;
+  }
+  let jsonStr = htmlResponse.substring(start, end);
+  let jsonResult = JSON.parse(jsonStr);
+  let rating = jsonResult.averageRating;
+
+  start = htmlResponse.indexOf('"topLevelButtons":[', end);
+  start =
+    htmlResponse.indexOf('"accessibilityData":', start) +
+    '"accessibilityData":'.length;
+  end = htmlResponse.indexOf("}", start);
+  let likes = +htmlResponse.substring(start, end).replace(/\D/g, "");
+  let dislikes = (likes * (5 - rating)) / (rating - 1);
+  let result = {
+    likes,
+    dislikes: Math.round(dislikes),
+    rating,
+    viewCount: +jsonResult.viewCount,
+  };
+  return result;
 }
 
 function setEventListeners(evt) {
@@ -219,7 +238,7 @@ function setEventListeners(evt) {
       const buttons = getButtons();
 
       if (!window.returnDislikeButtonlistenersSet) {
-        cLog('Registering button listeners...');
+        cLog("Registering button listeners...");
         buttons.children[0].addEventListener("click", likeClicked);
         buttons.children[1].addEventListener("click", dislikeClicked);
         window.returnDislikeButtonlistenersSet = true;
@@ -229,7 +248,7 @@ function setEventListeners(evt) {
   }
 
   if (window.location.href.indexOf("watch?") >= 0) {
-    cLog('Setting up...');
+    cLog("Setting up...");
     var jsInitChecktimer = setInterval(checkForJS_Finish, 111);
   }
 }