Răsfoiți Sursa

Release 0.0.0.4

Rate bar added
Bug caused by security token resolved by removing security token
Various bugs and console errors fixed
More like/dislike data is now saved on scroll
Dmitrii Selivanov 3 ani în urmă
părinte
comite
9df69d65dd

+ 57 - 37
Extensions/chrome/background.js

@@ -1,41 +1,61 @@
 const apiUrl = "https://return-youtube-dislike-api.azurewebsites.net";
 const apiUrl = "https://return-youtube-dislike-api.azurewebsites.net";
-const securityToken = Math.random().toString(36).substring(2, 15);
 
 
-chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
-	sendResponse(securityToken);
-});
+// Security token causes issues if extension is reloaded/updated while several tabs are open
+// const securityToken = Math.random().toString(36).substring(2, 15);
+//
+// chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
+//   sendResponse(securityToken);
+// });
 
 
-chrome.runtime.onMessageExternal.addListener((request, sender, sendResponse) => {
-    if (request.securityToken === securityToken) {
-        if (request.message === "get_auth_token") {
-            // chrome.identity.getAuthToken({ interactive: true }, function (token) {
-            //   console.log(token);
-            //   chrome.identity.getProfileUserInfo(function (userInfo) {
-            //     console.log(JSON.stringify(userInfo));
-            //   });
-            // });
-        } else if (request.message === "log_off") {
-            // console.log("logging off");
-            // chrome.identity.clearAllCachedAuthTokens(() => console.log("logged off"));
-        } else if (request.message == "set_state") {
-            // console.log(request);
-            // chrome.identity.getAuthToken({ interactive: true }, function (token) {
-            let token = "";
-            fetch(`${apiUrl}/votes?videoId=${request.videoId}`, {
-                    method: "GET",
-                    headers: {
-                        Accept: "application/json",
-                        Authorization: "Bearer " + token,
-                    },
-                })
-                .then((response) => response.json())
-                .then((response) => {
-                    console.log(response);
-                    sendResponse(response);
-                })
-                .catch();
-            //});
-            return true;
+chrome.runtime.onMessageExternal.addListener(
+  (request, sender, sendResponse) => {
+      if (request.message === "get_auth_token") {
+        // chrome.identity.getAuthToken({ interactive: true }, function (token) {
+        //   console.log(token);
+        //   chrome.identity.getProfileUserInfo(function (userInfo) {
+        //     console.log(JSON.stringify(userInfo));
+        //   });
+        // });
+      } else if (request.message === "log_off") {
+        // console.log("logging off");
+        // chrome.identity.clearAllCachedAuthTokens(() => console.log("logged off"));
+      } else if (request.message == "set_state") {
+        // console.log(request);
+        // chrome.identity.getAuthToken({ interactive: true }, function (token) {
+        let token = "";
+        fetch(`${apiUrl}/votes?videoId=${request.videoId}`, {
+          method: "GET",
+          headers: {
+            Accept: "application/json",
+            Authorization: "Bearer " + token,
+          },
+        })
+          .then((response) => response.json())
+          .then((response) => {
+            sendResponse(response);
+          })
+          .catch();
+        //});
+        return true;
+      } else if (request.message == "send_links") {
+        toSend = toSend.concat(request.videoIds.filter((x) => !sentIds.has(x)));
+        if (toSend.length >= 20) {
+          fetch(`${apiUrl}/votes`, {
+            method: "POST",
+            headers: {
+              "Content-Type": "application/json",
+            },
+            body: JSON.stringify(toSend),
+          });
+          for (const toSendUrl of toSend) {
+            sentIds.add(toSendUrl);
+          }
+          toSend = [];
         }
         }
-    }
-});
+      }
+
+  }
+);
+
+const sentIds = new Set();
+let toSend = [];

BIN
Extensions/chrome/background.zip


+ 1 - 1
Extensions/chrome/content-script.js

@@ -7,4 +7,4 @@ chrome.runtime.sendMessage({}, (securityToken) => {
 		this.remove();
 		this.remove();
 	};
 	};
 	(document.head || document.documentElement).appendChild(script);
 	(document.head || document.documentElement).appendChild(script);
-});
+});

+ 16 - 0
Extensions/chrome/content-style.css

@@ -0,0 +1,16 @@
+#return-youtube-dislike-bar-container {
+    background: #c6c6c6;
+}
+
+#return-youtube-dislike-bar {
+    background: #5094c8;
+}
+
+
+[dark] #return-youtube-dislike-bar-container {
+
+}
+
+[dark] #return-youtube-dislike-bar {
+    background: #3ea6ff;
+}

+ 4 - 3
Extensions/chrome/manifest.json

@@ -1,7 +1,7 @@
 {
 {
   "name": "Youtube Dislike Button",
   "name": "Youtube Dislike Button",
   "description": "Returns ability to see dislikes",
   "description": "Returns ability to see dislikes",
-  "version": "0.0.0.3",
+  "version": "0.0.0.4",
   "manifest_version": 3,
   "manifest_version": 3,
   "background": {
   "background": {
     "service_worker": "background.js"
     "service_worker": "background.js"
@@ -18,7 +18,8 @@
     {
     {
       "matches": ["*://*.youtube.com/*"],
       "matches": ["*://*.youtube.com/*"],
       "js": ["content-script.js"],
       "js": ["content-script.js"],
-      "run_at": "document_start"
+      "run_at": "document_start",
+      "css": ["content-style.css"]
     }
     }
   ],
   ],
   "externally_connectable": {
   "externally_connectable": {
@@ -30,4 +31,4 @@
       "matches": ["*://*.youtube.com/*"]
       "matches": ["*://*.youtube.com/*"]
 	}
 	}
   ]
   ]
-}
+}

+ 2 - 3
Extensions/chrome/popup.js

@@ -4,7 +4,6 @@ document.querySelector('#login')
   chrome.runtime.sendMessage({ message: 'get_auth_token' });
   chrome.runtime.sendMessage({ message: 'get_auth_token' });
 });
 });
 
 
-document.querySelector('#log_off')
-.addEventListener('click', function () {
-  chrome.runtime.sendMessage({ message: 'log_off' });
+document.querySelector("#log_off").addEventListener("click", function () {
+  chrome.runtime.sendMessage({ message: "log_off" });
 });
 });

+ 183 - 118
Extensions/chrome/script.js

@@ -1,122 +1,187 @@
-(function(securityToken, extensionId) {
-    function getButtons() {
-        return document
-            .getElementById("menu-container")
-            ?.querySelector("#top-level-buttons-computed");
-    }
-
-    function getLikeButton() {
-        return getButtons().children[0];
-    }
-
-    function getDislikeButton() {
-        return getButtons().children[1];
-    }
-
-    function isVideoLiked() {
-        return getLikeButton().classList.contains("style-default-active");
-    }
-
-    function isVideoDisliked() {
-        return getDislikeButton().classList.contains("style-default-active");
-    }
-
-    function isVideoNotLiked() {
-        return getLikeButton().classList.contains("style-text");
-    }
-
-    function isVideoNotDisliked() {
-        return getDislikeButton().classList.contains("style-text");
-    }
-
-    function getState() {
-        if (isVideoLiked()) {
-            return "liked";
-        }
-        if (isVideoDisliked()) {
-            return "disliked";
-        }
-        return "neutral";
-    }
-
-    function setLikes(likesCount) {
-        getButtons().children[0].querySelector("#text").innerText = likesCount;
-    }
-
-    function setDislikes(dislikesCount) {
-        getButtons().children[1].querySelector("#text").innerText = dislikesCount;
-    }
-
-    function setState() {
-        chrome.runtime.sendMessage(extensionId, {
-				securityToken: securityToken,
-                message: "set_state",
-                videoId: getVideoId(),
-                state: getState(),
-            },
-            function(response) {
-                if (response != undefined) {
-                    const formattedDislike = numberFormat(response.dislikes);
-                    // setLikes(response.likes);
-                    console.log(response);
-                    setDislikes(formattedDislike);
-                } else {}
-            }
-        );
-    }
-
-    function likeClicked() {
-        console.log("like" + getState());
-        setState();
-    }
-
-    function dislikeClicked() {
-        console.log("dislike" + getState());
-        setState();
-    }
-
-    function setInitalState() {
-        setState();
-    }
-
-    function getVideoId() {
-        const urlParams = new URLSearchParams(window.location.search);
-        const videoId = urlParams.get("v");
-        return videoId;
-    }
-
-    function isVideoLoaded() {
-        const videoId = getVideoId();
-        return (
-            document.querySelector(`ytd-watch-flexy[video-id='${videoId}']`) !== null
-        );
-    }
-
-    function numberFormat(numberState) {
-        const userLocales = navigator.language;
-        const formatter = Intl.NumberFormat(userLocales, { notation: "compact" });
-        return formatter.format(numberState);
-    }
-
-    function setEventListeners(evt) {
-        function checkForJS_Finish() {
-            if (getButtons()?.offsetParent && isVideoLoaded()) {
-                clearInterval(jsInitChecktimer);
-                const buttons = getButtons();
-                if (!window.returnDislikeButtonlistenersSet) {
-                    buttons.children[0].addEventListener("click", likeClicked);
-                    buttons.children[1].addEventListener("click", dislikeClicked);
-                    window.returnDislikeButtonlistenersSet = true;
-                }
-                setInitalState();
-            }
+(function (extensionId) {
+  function getButtons() {
+    return document
+      .getElementById("menu-container")
+      ?.querySelector("#top-level-buttons-computed");
+  }
+
+  function getLikeButton() {
+    return getButtons().children[0];
+  }
+
+  function getDislikeButton() {
+    return getButtons().children[1];
+  }
+
+  function isVideoLiked() {
+    return getLikeButton().classList.contains("style-default-active");
+  }
+
+  function isVideoDisliked() {
+    return getDislikeButton().classList.contains("style-default-active");
+  }
+
+  function isVideoNotLiked() {
+    return getLikeButton().classList.contains("style-text");
+  }
+
+  function isVideoNotDisliked() {
+    return getDislikeButton().classList.contains("style-text");
+  }
+
+  function getState() {
+    if (isVideoLiked()) {
+      return "liked";
+    }
+    if (isVideoDisliked()) {
+      return "disliked";
+    }
+    return "neutral";
+  }
+
+  function setLikes(likesCount) {
+    getButtons().children[0].querySelector("#text").innerText = likesCount;
+  }
+
+  function setDislikes(dislikesCount) {
+    getButtons().children[1].querySelector("#text").innerText = dislikesCount;
+  }
+
+  function setState() {
+    chrome.runtime.sendMessage(
+      extensionId,
+      {
+        message: "set_state",
+        videoId: getVideoId(window.location.href),
+        state: getState(),
+      },
+      function (response) {
+        if (response != undefined) {
+          const formattedDislike = numberFormat(response.dislikes);
+          // setLikes(response.likes);
+          setDislikes(formattedDislike);
+          createRateBar(response.likes, response.dislikes);
+        } else {
         }
         }
-
-        if (window.location.href.indexOf("watch?") >= 0) {
-            var jsInitChecktimer = setInterval(checkForJS_Finish, 111);
+      }
+    );
+  }
+
+  function likeClicked() {
+    // console.log("like" + getState());
+    // setState();
+  }
+
+  function dislikeClicked() {
+    // console.log("dislike" + getState());
+    // setState();
+  }
+
+  function setInitalState() {
+    setState();
+    setTimeout(() => sendVideoIds(), 1500);
+  }
+
+  function getVideoId(url) {
+    const urlObject = new URL(url);
+    const videoId = urlObject.searchParams.get("v");
+    return videoId;
+  }
+
+  function isVideoLoaded() {
+    const videoId = getVideoId(window.location.href);
+    return (
+      document.querySelector(`ytd-watch-flexy[video-id='${videoId}']`) !== null
+    );
+  }
+
+  function numberFormat(numberState) {
+    const userLocales = navigator.language;
+    const formatter = Intl.NumberFormat(userLocales, { notation: "compact" });
+    return formatter.format(numberState);
+  }
+
+  var jsInitChecktimer = null;
+
+  function setEventListeners(evt) {
+    function checkForJS_Finish() {
+      if (getButtons()?.offsetParent && isVideoLoaded()) {
+        clearInterval(jsInitChecktimer);
+        jsInitChecktimer = null;
+        const buttons = getButtons();
+        if (!window.returnDislikeButtonlistenersSet) {
+          buttons.children[0].addEventListener("click", likeClicked);
+          buttons.children[1].addEventListener("click", dislikeClicked);
+          window.returnDislikeButtonlistenersSet = true;
         }
         }
-    }
-
+        setInitalState();
+      }
+    }
+
+    if (window.location.href.indexOf("watch?") >= 0) {
+      jsInitChecktimer = setInterval(checkForJS_Finish, 111);
+    }
+  }
+
+  function createRateBar(likes, dislikes) {
+    var rateBar = document.getElementById(
+      "return-youtube-dislike-bar-container"
+    );
+    const widthPx =
+      getButtons().children[0].clientWidth +
+      getButtons().children[1].clientWidth;
+
+    const widthPercent =
+      likes + dislikes > 0 ? (likes / (likes + dislikes)) * 100 : 50;
+
+    if (!rateBar) {
+      document.getElementById("menu-container").insertAdjacentHTML(
+        "beforeend",
+        `<div id="return-youtube-dislike-bar-container" 
+                  style="width: ${widthPx}px; 
+                  height: 3px; margin-left: 6px;">
+                  <div id="return-youtube-dislike-bar" style="width: ${widthPercent}%; height: 100%" ></div>
+                </div>`
+      );
+    } else {
+      document.getElementById(
+        "return-youtube-dislike-bar-container"
+      ).style.width = widthPx + "px";
+      document.getElementById("return-youtube-dislike-bar").style.width =
+        widthPercent + "%";
+    }
+  }
+
+  function sendVideoIds() {
+    const ids = Array.from(
+      document.getElementsByClassName(
+        "yt-simple-endpoint ytd-compact-video-renderer"
+      )
+    )
+      .concat(
+        Array.from(
+          document.getElementsByClassName("yt-simple-endpoint ytd-thumbnail")
+        )
+      )
+      .filter((x) => x.href && x.href.indexOf("/watch?v=") > 0)
+      .map((x) => getVideoId(x.href));
+    chrome.runtime.sendMessage(extensionId, {
+      message: "send_links",
+      videoIds: ids,
+    });
+  }
+
+  setEventListeners();
+
+  document.addEventListener("yt-navigate-finish", function (event) {
+    if (jsInitChecktimer !== null) clearInterval(jsInitChecktimer);
+    window.returnDislikeButtonlistenersSet = false;
     setEventListeners();
     setEventListeners();
+  });
+
+  window.onscrollend = () => {
+    sendVideoIds();
+  };
 
 
-})(document.currentScript.getAttribute("security-token"), document.currentScript.getAttribute("extension-id"));
+  setTimeout(() => sendVideoIds(), 1500);
+})(document.currentScript.getAttribute("extension-id"));

+ 1 - 1
StaticSite/index.html

@@ -20,7 +20,7 @@
       <p><strong>Now <a href="https://addons.mozilla.org/en-US/firefox/addon/return-youtube-dislikes/">available</a> in
       <p><strong>Now <a href="https://addons.mozilla.org/en-US/firefox/addon/return-youtube-dislikes/">available</a> in
         firefox addon store! </strong></p>
         firefox addon store! </strong></p>
 
 
-      <p><strong>Chrome users - update to 0.0.0.3 (via Load Unpacked, instructions below) to prevent Chrome disabling the extension</strong></p>
+      <p><strong>Version 0.0.0.4 released - ratio (like/dislike) bar added</strong></p>
       <p>This is a Chrome/Firefox/Userscript extension that return dislike statistics to YouTube. For now, it only works
       <p>This is a Chrome/Firefox/Userscript extension that return dislike statistics to YouTube. For now, it only works
         if
         if
         a video had public display of dislikes enabled before YouTube removed dislike stats.</p>
         a video had public display of dislikes enabled before YouTube removed dislike stats.</p>