Prechádzať zdrojové kódy

Merge pull request #14 from Anarios/release/0_0_0_4

Release 0.0.0.4 for chrome
Dmitrii Selivanov 3 rokov pred
rodič
commit
2dd6b0f29b

+ 55 - 41
Extensions/chrome/background.js

@@ -1,46 +1,60 @@
 const apiUrl = "https://return-youtube-dislike-api.azurewebsites.net";
 
-chrome.runtime.onMessage.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) => {
-        console.log(response);
-        sendResponse(response);
+// 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.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,
+        },
       })
-      .catch();
-    //});
-    return true;
+        .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 = [];
+      }
+    }
   }
-});
+);
 
-chrome.tabs.onUpdated.addListener(async (tabId, changeInfo, tab) => {
-  if (changeInfo.status == "complete") {
-    if (tab.url && tab.url.indexOf("youtube.") < 0) return;
-    chrome.tabs.get(tabId, (tab) => {
-      chrome.scripting.executeScript({
-        target: { tabId: tab.id },
-        files: ["script.js"],
-      });
-    });
-  }
-});
+const sentIds = new Set();
+let toSend = [];

BIN
Extensions/chrome/background.zip


+ 10 - 0
Extensions/chrome/content-script.js

@@ -0,0 +1,10 @@
+chrome.runtime.sendMessage({}, (securityToken) => {
+  var script = document.createElement("script");
+  script.setAttribute("security-token", securityToken);
+  script.setAttribute("extension-id", chrome.runtime.id);
+  script.src = chrome.runtime.getURL("script.js");
+  script.onload = function () {
+    this.remove();
+  };
+  (document.head || document.documentElement).appendChild(script);
+});

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

@@ -0,0 +1,14 @@
+#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;
+}

+ 12 - 3
Extensions/chrome/manifest.json

@@ -1,12 +1,11 @@
 {
   "name": "Youtube Dislike Button",
   "description": "Returns ability to see dislikes",
-  "version": "0.0.0.3",
+  "version": "0.0.0.4",
   "manifest_version": 3,
   "background": {
     "service_worker": "background.js"
   },
-  "permissions": ["activeTab", "scripting"],
   "host_permissions": ["*://*.youtube.com/*"],
   "action": {
     "default_popup": "popup.html"
@@ -19,7 +18,17 @@
     {
       "matches": ["*://*.youtube.com/*"],
       "js": ["content-script.js"],
-      "run_at": "document_idle"
+      "run_at": "document_start",
+      "css": ["content-style.css"]
+    }
+  ],
+  "externally_connectable": {
+    "matches": ["*://*.youtube.com/*"]
+  },
+  "web_accessible_resources": [
+    {
+      "resources": ["script.js"],
+      "matches": ["*://*.youtube.com/*"]
     }
   ]
 }

+ 2 - 3
Extensions/chrome/popup.js

@@ -4,7 +4,6 @@ document.querySelector('#login')
   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" });
 });

+ 179 - 114
Extensions/chrome/script.js

@@ -1,122 +1,187 @@
-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(
-    {
-      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 (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";
     }
-  );
-}
-
-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;
+    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 {
+        }
       }
-      setInitalState();
+    );
+  }
+
+  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);
     }
   }
 
-  if (window.location.href.indexOf("watch?") >= 0) {
-    var 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();
+  setEventListeners();
+
+  document.addEventListener("yt-navigate-finish", function (event) {
+    if (jsInitChecktimer !== null) clearInterval(jsInitChecktimer);
+    window.returnDislikeButtonlistenersSet = false;
+    setEventListeners();
+  });
+
+  window.onscrollend = () => {
+    sendVideoIds();
+  };
 
-//window.addEventListener("hashchange", setEventListeners, false);
+  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
         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
         if
         a video had public display of dislikes enabled before YouTube removed dislike stats.</p>