Ver código fonte

Merge branch 'Anarios-main'

Nikita Krupin 3 anos atrás
pai
commit
939a48e73f
43 arquivos alterados com 476 adições e 1820 exclusões
  1. 3 5
      .github/workflows/weblint.yml
  2. 1 0
      .gitignore
  3. 8 0
      Extensions/combined/debug.js
  4. 0 361
      Extensions/combined/dist/chrome/bundled-content-script.js
  5. 0 26
      Extensions/combined/dist/chrome/content-style.css
  6. BIN
      Extensions/combined/dist/chrome/icons/icon128.png
  7. BIN
      Extensions/combined/dist/chrome/icons/icon48.png
  8. 0 41
      Extensions/combined/dist/chrome/manifest.json
  9. 0 119
      Extensions/combined/dist/chrome/popup.css
  10. 0 48
      Extensions/combined/dist/chrome/popup.html
  11. 0 61
      Extensions/combined/dist/chrome/popup.js
  12. 0 220
      Extensions/combined/dist/chrome/ryd.background.js
  13. 0 361
      Extensions/combined/dist/firefox/bundled-content-script.js
  14. 0 26
      Extensions/combined/dist/firefox/content-style.css
  15. BIN
      Extensions/combined/dist/firefox/icons/icon128.png
  16. BIN
      Extensions/combined/dist/firefox/icons/icon48.png
  17. 0 26
      Extensions/combined/dist/firefox/manifest.json
  18. 0 119
      Extensions/combined/dist/firefox/popup.css
  19. 0 48
      Extensions/combined/dist/firefox/popup.html
  20. 0 61
      Extensions/combined/dist/firefox/popup.js
  21. 0 220
      Extensions/combined/dist/firefox/ryd.background.js
  22. 1 0
      Extensions/combined/icons/server.svg
  23. 4 0
      Extensions/combined/manifest-chrome.json
  24. 5 0
      Extensions/combined/manifest-firefox.json
  25. 11 3
      Extensions/combined/popup.css
  26. 21 11
      Extensions/combined/popup.html
  27. 37 18
      Extensions/combined/popup.js
  28. 5 5
      Extensions/combined/src/events.js
  29. 8 5
      README.md
  30. 7 24
      Website/layouts/default.vue
  31. 10 3
      Website/nuxt.config.js
  32. 60 0
      Website/package-lock.json
  33. 1 0
      Website/package.json
  34. 68 0
      Website/pages/debug.vue
  35. 60 0
      Website/pages/documentation.vue
  36. 19 0
      Website/pages/documentation/endpoints.vue
  37. 78 0
      Website/pages/documentation/fetching.vue
  38. 8 0
      Website/pages/documentation/index.vue
  39. 17 0
      Website/pages/documentation/url.vue
  40. 30 0
      Website/pages/documentation/usage-rights.vue
  41. 1 1
      Website/pages/index.vue
  42. 1 1
      Website/pages/install.vue
  43. 12 7
      package-lock.json

+ 3 - 5
.github/workflows/weblint.yml

@@ -20,9 +20,7 @@ jobs:
 
     steps:
     - uses: actions/checkout@main
-    - name: npm install
-      run: npm install
+    - run: npm install
+      working-directory: Website
+    - run: npm run lint
       working-directory: Website
-    - name: npm run lint
-      run: npm run lint
-      working-directory: Website

+ 1 - 0
.gitignore

@@ -37,3 +37,4 @@ Extensions/combined/bundled-content-script.js
 # Dist Files
 Extensions/combined/dist/*
 package-lock.json
+Website/package-lock.json

+ 8 - 0
Extensions/combined/debug.js

@@ -0,0 +1,8 @@
+//---   Get Extension Information   ---//
+const extension = chrome.runtime.getManifest();
+
+//---   Get Debug Elements   ---//
+const ver = document.getElementById("extension-version");
+
+//---   Set Debug Elements   ---//
+ver.innerHTML = extension.version;

+ 0 - 361
Extensions/combined/dist/chrome/bundled-content-script.js

@@ -1,361 +0,0 @@
-/******/ (() => { // webpackBootstrap
-/******/ 	"use strict";
-var __webpack_exports__ = {};
-
-;// CONCATENATED MODULE: ./Extensions/combined/src/bar.js
-
-
-function createRateBar(likes, dislikes) {
-  var rateBar = document.getElementById("ryd-bar-container");
-  var widthPx = buttons_getButtons().children[0].clientWidth + buttons_getButtons().children[1].clientWidth + 8;
-  var widthPercent = likes + dislikes > 0 ? likes / (likes + dislikes) * 100 : 50;
-
-  if (!rateBar) {
-    (document.getElementById("menu-container") || document.querySelector("ytm-slim-video-action-bar-renderer")).insertAdjacentHTML("beforeend", "\n          <div class=\"ryd-tooltip\" style=\"width: ".concat(widthPx, "px\">\n          <div class=\"ryd-tooltip-bar-container\">\n             <div\n                id=\"ryd-bar-container\"\n                style=\"width: 100%; height: 2px;\"\n                >\n                <div\n                   id=\"ryd-bar\"\n                   style=\"width: ").concat(widthPercent, "%; height: 100%\"\n                   ></div>\n             </div>\n          </div>\n          <tp-yt-paper-tooltip position=\"top\" id=\"ryd-dislike-tooltip\" class=\"style-scope ytd-sentiment-bar-renderer\" role=\"tooltip\" tabindex=\"-1\">\n             <!--css-build:shady-->").concat(likes.toLocaleString(), "&nbsp;/&nbsp;").concat(dislikes.toLocaleString(), "\n          </tp-yt-paper-tooltip>\n          </div>\n  "));
-  } else {
-    document.getElementById("ryd-bar-container").style.width = widthPx + "px";
-    document.getElementById("ryd-bar").style.width = widthPercent + "%";
-    document.querySelector("#ryd-dislike-tooltip > #tooltip").innerHTML = "".concat(likes.toLocaleString(), "&nbsp;/&nbsp;").concat(dislikes.toLocaleString());
-  }
-}
-
-
-;// CONCATENATED MODULE: ./Extensions/combined/src/utils.js
-function roundDown(num) {
-  if (num < 1000) return num;
-
-  var _int = Math.floor(Math.log10(num) - 2);
-
-  var decimal = _int + (_int % 3 ? 1 : 0);
-  var value = Math.floor(num / Math.pow(10, decimal));
-  return value * Math.pow(10, decimal);
-}
-
-function numberFormat(numberState) {
-  var userLocales;
-
-  try {
-    var _URL, _URL$searchParams, _Array$from, _Array$from$find;
-
-    userLocales = (_URL = new URL((_Array$from = Array.from(document.querySelectorAll("head > link[rel='search']"))) === null || _Array$from === void 0 ? void 0 : (_Array$from$find = _Array$from.find(function (n) {
-      var _n$getAttribute;
-
-      return n === null || n === void 0 ? void 0 : (_n$getAttribute = n.getAttribute("href")) === null || _n$getAttribute === void 0 ? void 0 : _n$getAttribute.includes("?locale=");
-    })) === null || _Array$from$find === void 0 ? void 0 : _Array$from$find.getAttribute("href"))) === null || _URL === void 0 ? void 0 : (_URL$searchParams = _URL.searchParams) === null || _URL$searchParams === void 0 ? void 0 : _URL$searchParams.get("locale");
-  } catch (_unused) {}
-
-  var formatter = Intl.NumberFormat(document.documentElement.lang || userLocales || navigator.language, {
-    notation: "compact"
-  });
-  return formatter.format(roundDown(numberState));
-}
-
-function getBrowser() {
-  if (typeof chrome !== "undefined" && typeof chrome.runtime !== "undefined") {
-    return chrome;
-  } else if (typeof browser !== "undefined" && typeof browser.runtime !== "undefined") {
-    return browser;
-  } else {
-    console.log("browser is not supported");
-    return false;
-  }
-}
-
-function getVideoId(url) {
-  var urlObject = new URL(url);
-  var pathname = urlObject.pathname;
-
-  if (pathname.startsWith("/clip")) {
-    return document.querySelector("meta[itemprop='videoId']").content;
-  } else {
-    return urlObject.searchParams.get("v");
-  }
-}
-
-function isVideoLoaded() {
-  var videoId = getVideoId(window.location.href);
-  return document.querySelector("ytd-watch-flexy[video-id='".concat(videoId, "']")) !== null || // mobile: no video-id attribute
-  document.querySelector('#player[loading="false"]:not([hidden])') !== null;
-}
-
-function cLog(message, writer) {
-  message = "[return youtube dislike]: ".concat(message);
-
-  if (writer) {
-    writer(message);
-  } else {
-    console.log(message);
-  }
-}
-
-
-;// CONCATENATED MODULE: ./Extensions/combined/src/events.js
-
-
-
-
-
-function sendVote(vote) {
-  getBrowser().runtime.sendMessage({
-    message: "send_vote",
-    vote: vote,
-    videoId: getVideoId(window.location.href)
-  });
-}
-
-function sendVideoIds() {
-  var links = Array.from(document.getElementsByClassName("yt-simple-endpoint ytd-compact-video-renderer")).concat(Array.from(document.getElementsByClassName("yt-simple-endpoint ytd-thumbnail"))); // Also try mobile
-
-  if (links.length < 1) links = Array.from(document.querySelectorAll(".large-media-item-metadata > a, a.large-media-item-thumbnail-container"));
-  var ids = links.filter(function (x) {
-    return x.href && x.href.indexOf("/watch?v=") > 0;
-  }).map(function (x) {
-    return getVideoId(x.href);
-  });
-  getBrowser().runtime.sendMessage({
-    message: "send_links",
-    videoIds: ids
-  });
-}
-
-function likeClicked(storedData) {
-  if (checkForSignInButton() === false) {
-    if (storedData.previousState === DISLIKED_STATE) {
-      sendVote(1);
-      storedData.dislikes--;
-      storedData.likes++;
-      createRateBar(storedData.likes, storedData.dislikes);
-      setDislikes(numberFormat(storedData.dislikes));
-      storedData.previousState = LIKED_STATE;
-    } else if (storedData.previousState === NEUTRAL_STATE) {
-      sendVote(1);
-      storedData.likes++;
-      createRateBar(storedData.likes, storedData.dislikes);
-      storedData.previousState = LIKED_STATE;
-    } else if (storedData.previousState = LIKED_STATE) {
-      sendVote(0);
-      storedData.likes--;
-      createRateBar(storedData.likes, storedData.dislikes);
-      storedData.previousState = NEUTRAL_STATE;
-    }
-  }
-}
-
-function dislikeClicked(storedData) {
-  if (checkForSignInButton() == false) {
-    if (storedData.previousState === NEUTRAL_STATE) {
-      sendVote(-1);
-      storedData.dislikes++;
-      setDislikes(numberFormat(storedData.dislikes));
-      createRateBar(storedData.likes, storedData.dislikes);
-      storedData.previousState = DISLIKED_STATE;
-    } else if (storedData.previousState === DISLIKED_STATE) {
-      sendVote(0);
-      storedData.dislikes--;
-      setDislikes(numberFormat(storedData.dislikes));
-      createRateBar(storedData.likes, storedData.dislikes);
-      storedData.previousState = NEUTRAL_STATE;
-    } else if (storedData.previousState === LIKED_STATE) {
-      sendVote(-1);
-      storedData.likes--;
-      storedData.dislikes++;
-      setDislikes(numberFormat(storedData.dislikes));
-      createRateBar(storedData.likes, storedData.dislikes);
-      storedData.previousState = DISLIKED_STATE;
-    }
-  }
-}
-
-
-;// CONCATENATED MODULE: ./Extensions/combined/src/state.js
-
-
-
-
-var LIKED_STATE = "LIKED_STATE";
-var DISLIKED_STATE = "DISLIKED_STATE";
-var NEUTRAL_STATE = "NEUTRAL_STATE";
-
-function isMobile() {
-  return location.hostname == "m.youtube.com";
-}
-
-function isVideoLiked() {
-  if (isMobile()) {
-    return getLikeButton().querySelector("button").getAttribute("aria-label") == "true";
-  }
-
-  return getLikeButton().classList.contains("style-default-active");
-}
-
-function isVideoDisliked() {
-  if (isMobile()) {
-    return getDislikeButton().querySelector("button").getAttribute("aria-label") == "true";
-  }
-
-  return getDislikeButton().classList.contains("style-default-active");
-}
-
-function getState(storedData) {
-  if (isVideoLiked()) {
-    return {
-      current: LIKED_STATE,
-      previous: storedData.previousState
-    };
-  }
-
-  if (isVideoDisliked()) {
-    return {
-      current: DISLIKED_STATE,
-      previous: storedData.previousState
-    };
-  }
-
-  return {
-    current: NEUTRAL_STATE,
-    previous: storedData.previousState
-  };
-} //---   Sets The Likes And Dislikes Values   ---//
-
-
-function setLikes(likesCount) {
-  getButtons().children[0].querySelector("#text").innerText = likesCount;
-}
-
-function setDislikes(dislikesCount) {
-  if (isMobile()) {
-    buttons_getButtons().children[1].querySelector(".button-renderer-text").innerText = dislikesCount;
-    return;
-  }
-
-  buttons_getButtons().children[1].querySelector("#text").innerText = dislikesCount;
-}
-
-function getLikeCountFromButton() {
-  var likesStr = getLikeButton().querySelector("button").getAttribute("aria-label").replace(/\D/g, "");
-  return likesStr.length > 0 ? parseInt(likesStr) : false;
-}
-
-function processResponse(response, storedData) {
-  var formattedDislike = numberFormat(response.dislikes);
-  setDislikes(formattedDislike);
-  storedData.dislikes = parseInt(response.dislikes);
-  storedData.likes = getLikeCountFromButton() || parseInt(response.likes);
-  createRateBar(storedData.likes, storedData.dislikes);
-}
-
-function setState(storedData) {
-  storedData.previousState = isVideoDisliked() ? DISLIKED_STATE : isVideoLiked() ? LIKED_STATE : NEUTRAL_STATE;
-  var statsSet = false;
-  getBrowser().runtime.sendMessage({
-    message: "set_state",
-    videoId: getVideoId(window.location.href),
-    state: getState(storedData).current,
-    likeCount: getLikeCountFromButton() || null
-  }, function (response) {
-    cLog("response from api:");
-    cLog(JSON.stringify(response));
-
-    if (response !== undefined && !("traceId" in response) && !statsSet) {
-      processResponse(response, storedData);
-    } else {}
-  });
-}
-
-function setInitialState(storedData) {
-  setState(storedData);
-  setTimeout(function () {
-    sendVideoIds();
-  }, 1500);
-}
-
-
-;// CONCATENATED MODULE: ./Extensions/combined/src/buttons.js
-
-
-function buttons_getButtons() {
-  var _document$getElementB;
-
-  if (isMobile()) {
-    return document.querySelector(".slim-video-action-bar-actions");
-  } //---   If Menu Element Is Displayed:   ---//
-
-
-  if (((_document$getElementB = document.getElementById("menu-container")) === null || _document$getElementB === void 0 ? void 0 : _document$getElementB.offsetParent) === null) {
-    return document.querySelector("ytd-menu-renderer.ytd-watch-metadata > div"); //---   If Menu Element Isnt Displayed:   ---//
-  } else {
-    var _document$getElementB2;
-
-    return (_document$getElementB2 = document.getElementById("menu-container")) === null || _document$getElementB2 === void 0 ? void 0 : _document$getElementB2.querySelector("#top-level-buttons-computed");
-  }
-}
-
-function getLikeButton() {
-  return buttons_getButtons().children[0];
-}
-
-function getDislikeButton() {
-  return buttons_getButtons().children[1];
-}
-
-function checkForSignInButton() {
-  if (document.querySelector("a[href^='https://accounts.google.com/ServiceLogin']")) {
-    return true;
-  } else {
-    return false;
-  }
-}
-
-
-;// CONCATENATED MODULE: ./Extensions/combined/ryd.content-script.js
-
-
-
-
-
-var storedData = {
-  likes: 0,
-  dislikes: 0,
-  previousState: NEUTRAL_STATE
-};
-var jsInitChecktimer = null;
-
-function setEventListeners(evt) {
-  function checkForJS_Finish() {
-    var _getButtons;
-
-    if ((_getButtons = buttons_getButtons()) !== null && _getButtons !== void 0 && _getButtons.offsetParent && isVideoLoaded()) {
-      clearInterval(jsInitChecktimer);
-      jsInitChecktimer = null;
-      var buttons = buttons_getButtons();
-
-      if (!window.returnDislikeButtonlistenersSet) {
-        buttons.children[0].addEventListener("click", function () {
-          return likeClicked(storedData);
-        });
-        buttons.children[1].addEventListener("click", function () {
-          return dislikeClicked(storedData);
-        });
-        window.returnDislikeButtonlistenersSet = true;
-      }
-
-      setInitialState(storedData);
-    }
-  }
-
-  if (window.location.href.indexOf("watch?") >= 0) {
-    jsInitChecktimer = setInterval(checkForJS_Finish, 111);
-  }
-}
-
-setEventListeners();
-document.addEventListener("yt-navigate-finish", function (event) {
-  if (jsInitChecktimer !== null) clearInterval(jsInitChecktimer);
-  window.returnDislikeButtonlistenersSet = false;
-  setEventListeners();
-});
-setTimeout(function () {
-  return sendVideoIds();
-}, 2500);
-/******/ })()
-;

+ 0 - 26
Extensions/combined/dist/chrome/content-style.css

@@ -1,26 +0,0 @@
-#ryd-bar-container {
-  background: var(--yt-spec-icon-disabled);
-  border-radius: 2px;
-}
-
-#ryd-bar {
-  background: var(--yt-spec-text-primary);
-  border-radius: 2px;
-  transition: all 0.15s ease-in-out;
-}
-
-.ryd-tooltip {
-  position: relative;
-  display: block;
-  height: 2px;
-  top: 9px;
-}
-
-.ryd-tooltip-bar-container {
-  width: 100%;
-  height: 2px;
-  position: absolute;
-  padding-top: 6px;
-  padding-bottom: 28px;
-  top: -6px;
-}

BIN
Extensions/combined/dist/chrome/icons/icon128.png


BIN
Extensions/combined/dist/chrome/icons/icon48.png


+ 0 - 41
Extensions/combined/dist/chrome/manifest.json

@@ -1,41 +0,0 @@
-{
-  "name": "Return YouTube Dislike",
-  "description": "Returns ability to see dislikes",
-  "version": "2.0.0.3",
-  "manifest_version": 3,
-  "background": {
-    "service_worker": "ryd.background.js"
-  },
-  "icons": {
-    "48": "icons/icon48.png",
-    "128": "icons/icon128.png"
-  },
-  "host_permissions": ["*://*.youtube.com/*"],
-  "permissions": [
-    "storage"
-  ],
-  "action": {
-    "default_popup": "popup.html"
-  },
-  "content_scripts": [
-    {
-      "matches": [
-        "*://youtube.com/*",
-        "*://www.youtube.com/*",
-        "*://m.youtube.com/*"
-      ],
-      "exclude_matches": ["*://*.music.youtube.com/*"],
-      "js": ["bundled-content-script.js"],
-      "css": ["content-style.css"]
-    }
-  ],
-  "externally_connectable": {
-    "matches": ["*://*.youtube.com/*"]
-  },
-  "web_accessible_resources": [
-    {
-      "resources": ["ryd.script.js"],
-      "matches": ["*://*.youtube.com/*"]
-    }
-  ]
-}

+ 0 - 119
Extensions/combined/dist/chrome/popup.css

@@ -1,119 +0,0 @@
-/* Variables */
-:root {
-  --primary: #cc2929;
-  --accent: #581111;
-
-  --background: #111;
-  --secondary: #272727;
-  --tertiary: #333333;
-  --lightGrey: #999;
-  --white: #fff;
-}
-
-/* Window Styling */
-html,
-body {
-  background-color: var(--background);
-  color: var(--white);
-  min-width: 300px;
-  padding: 0.5em;
-  font-family: 'Roboto', Arial, Helvetica, sans-serif;
-  font-size: 14px;
-}
-
-h1 {
-  font-size: 26px;
-}
-
-button {
-  color: var(--white);
-  background: var(--secondary);
-  cursor: pointer;
-  padding: 5px 16px;
-  border: none;
-  border-radius: 4px;
-  font-weight: 500;
-  box-shadow: 0 2px 4px -1px rgb(0 0 0 / 20%), 0 4px 5px 0 rgb(0 0 0 / 14%), 0 1px 10px 0 rgb(0 0 0 / 12%);
-  transition: .4s;
-}
-
-button:hover {
-  background: #444;
-}
-
-#advancedToggle {
-  margin-top: 1em;
-  margin-bottom: 2em;
-}
-
-#advancedSettings {
-  display: none;
-  border: 2px solid var(--secondary);
-  border-radius: 0.5rem;
-  padding: 1rem;
-}
-
-#advancedLegend {
-  color: var(--tertiary) !important;
-  /* margin: auto; */ /* Center the label */
-  /* padding: .25rem .5rem; */
-  /* border-radius: .25rem; */
-  /* border: .25rem solid var(--secondary); */
-}
-
-/*   Switches   */
-.switch {
-  position: relative;
-  display: inline-block;
-  width: 30px;
-  height: 17px;
-  margin-bottom: 1rem;
-}
-
-.switch:last-of-type {
-  margin-bottom: 0;
-}
-
-.switch input {
-  display: none;
-}
-
-.slider {
-  position: absolute;
-  cursor: pointer;
-  top: 0;
-  left: 0;
-  right: 0;
-  bottom: 0;
-  background: var(--secondary);
-  transition: 0.4s;
-  border-radius: 34px;
-}
-
-.slider:before {
-  position: absolute;
-  content: "";
-  height: 13px;
-  width: 13px;
-  left: 2px;
-  bottom: 2px;
-  background: var(--lightGrey);
-  transition: 0.4s;
-  border-radius: 50%;
-}
-
-input:checked + .slider {
-  background: var(--accent);
-}
-
-input:checked + .slider:before {
-  transform: translateX(13px);
-  background: var(--primary);
-}
-
-.switchLabel {
-  margin-left: 0.5rem;
-  width: 250px !important;
-  transform: translateX(35px);
-  display: inline-block;
-}

+ 0 - 48
Extensions/combined/dist/chrome/popup.html

@@ -1,48 +0,0 @@
-<!DOCTYPE html>
-<html lang="en">
-  <head>
-    <meta content="text/html; charset=utf-8" />
-    <title>Return YouTube Dislike</title>
-    <link rel="stylesheet" href="popup.css" />
-    <link rel="preconnect" href="https://fonts.googleapis.com">
-    <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
-    <link href="https://fonts.googleapis.com/css2?family=Roboto:wght@100;300;400;500;700;900&display=swap" rel="stylesheet">
-  </head>
-  <body>
-    <center>
-      <svg width="48" viewBox="0 0 24 24"><path d="M14.9 3H6c-.9 0-1.6.5-1.9 1.2l-3 7c-.1.3-.1.5-.1.7v2c0 1.1.9 2 2 2h6.3l-.9 4.5c-.1.5 0 1 .4 1.4l1.1 1.1 6.5-6.6c.4-.4.6-.9.6-1.4V5c-.1-1.1-1-2-2.1-2zm7.4 12.8h-2.9c-.4 0-.7-.3-.7-.7V3.9c0-.4.3-.7.7-.7h2.9c.4 0 .7.3.7.7V15c0 .4-.3.8-.7.8z" fill="red"/><path d="m8 12.5 5.1-2.9L8 6.7v5.8z" fill="#fff"/></svg>
-      <h1>Return YouTube Dislike</h1>
-      <p>by Dmitrii Selivanov & Community</p>
-
-      <button id="link_website">Website</button>
-      <button id="link_github">GitHub</button>
-      <button id="link_discord">Discord</button>
-
-      <br><br>
-      <button id="link_donate">Donate</button>
-      <br>
-
-      <br>
-<!--      <button id="advancedToggle">Show Settings</button>-->
-      <br>
-
-    </center>
-
-    <fieldset id="advancedSettings">
-      <legend id="advancedLegend">Settings</legend>
-
-      <label class="switch">
-        <input type="checkbox" id="disable_ratio_bar" />
-        <span class="slider" />
-        <span class="switchLabel">Lorem ipsum dolor sit amet</span> </label
-      ><br />
-
-      <label class="switch">
-        <input type="checkbox" id="disable_api_unlisted" />
-        <span class="slider" />
-        <span class="switchLabel">Lorem ipsum dolor sit amet</span> </label
-      ><br />
-    </fieldset>
-  </body>
-  <script src="popup.js"></script>
-</html>

+ 0 - 61
Extensions/combined/dist/chrome/popup.js

@@ -1,61 +0,0 @@
-/*   Config   */
-const config = {
-  advanced: false,
-  showAdvancedMessage: "Show Settings",
-  hideAdvancedMessage: "Hide Settings",
-
-  links: {
-    website: "https://returnyoutubedislike.com",
-    github: "https://github.com/Anarios/return-youtube-dislike",
-    discord: "https://discord.gg/mYnESY4Md5",
-    donate: 'https://returnyoutubedislike.com/donate'
-  },
-};
-
-/*   Links   */
-document.getElementById("link_website").addEventListener("click", () => {
-  chrome.tabs.create({ url: config.links.website });
-});
-
-document.getElementById("link_github").addEventListener("click", () => {
-  chrome.tabs.create({ url: config.links.github });
-});
-
-document.getElementById("link_discord").addEventListener("click", () => {
-  chrome.tabs.create({ url: config.links.discord });
-});
-
-document.getElementById("link_donate").addEventListener("click", () => {
-  chrome.tabs.create({ url: config.links.donate });
-});
-
-
-chrome.runtime.sendMessage({ message: 'get_auth_token' });
-/*   Advanced Toggle   */
-/* Not currently used in this version
-const advancedToggle = document.getElementById("advancedToggle");
-advancedToggle.addEventListener("click", () => {
-  const adv = document.getElementById("advancedSettings");
-  if (config.advanced) {
-    adv.style.display = "none";
-    advancedToggle.innerHTML = config.showAdvancedMessage;
-    config.advanced = false;
-  } else {
-    adv.style.display = "block";
-    advancedToggle.innerHTML = config.hideAdvancedMessage;
-    config.advanced = true;
-  }
-});
-*/
-
-/* popup-script.js
-document.querySelector('#login')
-.addEventListener('click', function () {
-  chrome.runtime.sendMessage({ message: 'get_auth_token' });
-});
-
-
-document.querySelector("#log_off").addEventListener("click", function () {
-  chrome.runtime.sendMessage({ message: "log_off" });
-});
-*/

+ 0 - 220
Extensions/combined/dist/chrome/ryd.background.js

@@ -1,220 +0,0 @@
-const apiUrl = "https://returnyoutubedislikeapi.com";
-let api;
-if (typeof chrome !== "undefined" && typeof chrome.runtime !== "undefined")
-  api = chrome;
-else if (
-  typeof browser !== "undefined" &&
-  typeof browser.runtime !== "undefined"
-)
-  api = browser;
-
-api.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") {
-    // chrome.identity.clearAllCachedAuthTokens(() => console.log("logged off"));
-  } else if (request.message == "set_state") {
-    // chrome.identity.getAuthToken({ interactive: true }, function (token) {
-    let token = "";
-    fetch(`${apiUrl}/votes?videoId=${request.videoId}&likeCount=${request.likeCount || ''}`, {
-      method: "GET",
-      headers: {
-        Accept: "application/json",
-      },
-    })
-      .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 = [];
-    }
-  } else if (request.message == "register") {
-    register();
-    return true;
-  } else if (request.message == "send_vote") {
-    sendVote(request.videoId, request.vote);
-    return true;
-  }
-});
-
-async function sendVote(videoId, vote) {
-  api.storage.sync.get(null, async (storageResult) => {
-    if (!storageResult.userId || !storageResult.registrationConfirmed) {
-      await register();
-      return;
-    }
-    fetch(`${apiUrl}/interact/vote`, {
-      method: "POST",
-      headers: {
-        "Content-Type": "application/json",
-      },
-      body: JSON.stringify({
-        userId: storageResult.userId,
-        videoId,
-        value: vote,
-      }),
-    })
-      .then(async (response) => {
-        if (response.status == 401) {
-          await register();
-          await sendVote(videoId, vote);
-          return;
-        }
-        return response.json()
-      })
-      .then((response) => {
-        solvePuzzle(response).then((solvedPuzzle) => {
-          fetch(`${apiUrl}/interact/confirmVote`, {
-            method: "POST",
-            headers: {
-              "Content-Type": "application/json",
-            },
-            body: JSON.stringify({
-              ...solvedPuzzle,
-              userId: storageResult.userId,
-              videoId,
-            }),
-          });
-        });
-      });
-  });
-}
-
-function register() {
-  let userId = generateUserID();
-  api.storage.sync.set({ userId });
-  return fetch(`${apiUrl}/puzzle/registration?userId=${userId}`, {
-    method: "GET",
-    headers: {
-      Accept: "application/json",
-    },
-  })
-    .then((response) => response.json())
-    .then((response) => {
-      return solvePuzzle(response).then((solvedPuzzle) => {
-        return fetch(`${apiUrl}/puzzle/registration?userId=${userId}`, {
-          method: "POST",
-          headers: {
-            "Content-Type": "application/json",
-          },
-          body: JSON.stringify(solvedPuzzle),
-        }).then((response) =>
-          response.json().then((result) => {
-            if (result === true) {
-              return api.storage.sync.set({ registrationConfirmed: true });
-            }
-          })
-        );
-      });
-    })
-    .catch();
-}
-
-api.storage.sync.get(null, (res) => {
-  if (!res || !res.userId || !res.registrationConfirmed) {
-    register();
-  }
-});
-
-const sentIds = new Set();
-let toSend = [];
-
-function sendUserSubmittedStatisticsToApi(statistics) {
-  fetch(`${apiUrl}/votes/user-submitted`, {
-    method: "POST",
-    headers: {
-      "Content-Type": "application/json",
-    },
-    body: JSON.stringify(statistics),
-  });
-}
-
-function countLeadingZeroes(uInt8View, limit) {
-  let zeroes = 0;
-  let value = 0;
-  for (let i = 0; i < uInt8View.length; i++) {
-    value = uInt8View[i];
-    if (value === 0) {
-      zeroes += 8;
-    } else {
-      let count = 1;
-      if (value >>> 4 === 0) {
-        count += 4;
-        value <<= 4;
-      }
-      if (value >>> 6 === 0) {
-        count += 2;
-        value <<= 2;
-      }
-      zeroes += count - (value >>> 7);
-      break;
-    }
-    if (zeroes >= limit) {
-      break;
-    }
-  }
-  return zeroes;
-}
-
-async function solvePuzzle(puzzle) {
-  let challenge = Uint8Array.from(atob(puzzle.challenge), (c) =>
-    c.charCodeAt(0)
-  );
-  let buffer = new ArrayBuffer(20);
-  let uInt8View = new Uint8Array(buffer);
-  let uInt32View = new Uint32Array(buffer);
-  let maxCount = Math.pow(2, puzzle.difficulty) * 5;
-  for (let i = 4; i < 20; i++) {
-    uInt8View[i] = challenge[i - 4];
-  }
-
-  for (let i = 0; i < maxCount; i++) {
-    uInt32View[0] = i;
-    let hash = await crypto.subtle.digest("SHA-512", buffer);
-    let hashUint8 = new Uint8Array(hash);
-    if (countLeadingZeroes(hashUint8) >= puzzle.difficulty) {
-      return {
-        solution: btoa(String.fromCharCode.apply(null, uInt8View.slice(0, 4))),
-      };
-    }
-  }
-}
-
-function generateUserID(length = 36) {
-  const charset =
-    "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
-  let result = "";
-  if (crypto && crypto.getRandomValues) {
-    const values = new Uint32Array(length);
-    crypto.getRandomValues(values);
-    for (let i = 0; i < length; i++) {
-      result += charset[values[i] % charset.length];
-    }
-    return result;
-  } else {
-    for (let i = 0; i < length; i++) {
-      result += charset[Math.floor(Math.random() * charset.length)];
-    }
-    return result;
-  }
-}

+ 0 - 361
Extensions/combined/dist/firefox/bundled-content-script.js

@@ -1,361 +0,0 @@
-/******/ (() => { // webpackBootstrap
-/******/ 	"use strict";
-var __webpack_exports__ = {};
-
-;// CONCATENATED MODULE: ./Extensions/combined/src/bar.js
-
-
-function createRateBar(likes, dislikes) {
-  var rateBar = document.getElementById("ryd-bar-container");
-  var widthPx = buttons_getButtons().children[0].clientWidth + buttons_getButtons().children[1].clientWidth + 8;
-  var widthPercent = likes + dislikes > 0 ? likes / (likes + dislikes) * 100 : 50;
-
-  if (!rateBar) {
-    (document.getElementById("menu-container") || document.querySelector("ytm-slim-video-action-bar-renderer")).insertAdjacentHTML("beforeend", "\n          <div class=\"ryd-tooltip\" style=\"width: ".concat(widthPx, "px\">\n          <div class=\"ryd-tooltip-bar-container\">\n             <div\n                id=\"ryd-bar-container\"\n                style=\"width: 100%; height: 2px;\"\n                >\n                <div\n                   id=\"ryd-bar\"\n                   style=\"width: ").concat(widthPercent, "%; height: 100%\"\n                   ></div>\n             </div>\n          </div>\n          <tp-yt-paper-tooltip position=\"top\" id=\"ryd-dislike-tooltip\" class=\"style-scope ytd-sentiment-bar-renderer\" role=\"tooltip\" tabindex=\"-1\">\n             <!--css-build:shady-->").concat(likes.toLocaleString(), "&nbsp;/&nbsp;").concat(dislikes.toLocaleString(), "\n          </tp-yt-paper-tooltip>\n          </div>\n  "));
-  } else {
-    document.getElementById("ryd-bar-container").style.width = widthPx + "px";
-    document.getElementById("ryd-bar").style.width = widthPercent + "%";
-    document.querySelector("#ryd-dislike-tooltip > #tooltip").innerHTML = "".concat(likes.toLocaleString(), "&nbsp;/&nbsp;").concat(dislikes.toLocaleString());
-  }
-}
-
-
-;// CONCATENATED MODULE: ./Extensions/combined/src/utils.js
-function roundDown(num) {
-  if (num < 1000) return num;
-
-  var _int = Math.floor(Math.log10(num) - 2);
-
-  var decimal = _int + (_int % 3 ? 1 : 0);
-  var value = Math.floor(num / Math.pow(10, decimal));
-  return value * Math.pow(10, decimal);
-}
-
-function numberFormat(numberState) {
-  var userLocales;
-
-  try {
-    var _URL, _URL$searchParams, _Array$from, _Array$from$find;
-
-    userLocales = (_URL = new URL((_Array$from = Array.from(document.querySelectorAll("head > link[rel='search']"))) === null || _Array$from === void 0 ? void 0 : (_Array$from$find = _Array$from.find(function (n) {
-      var _n$getAttribute;
-
-      return n === null || n === void 0 ? void 0 : (_n$getAttribute = n.getAttribute("href")) === null || _n$getAttribute === void 0 ? void 0 : _n$getAttribute.includes("?locale=");
-    })) === null || _Array$from$find === void 0 ? void 0 : _Array$from$find.getAttribute("href"))) === null || _URL === void 0 ? void 0 : (_URL$searchParams = _URL.searchParams) === null || _URL$searchParams === void 0 ? void 0 : _URL$searchParams.get("locale");
-  } catch (_unused) {}
-
-  var formatter = Intl.NumberFormat(document.documentElement.lang || userLocales || navigator.language, {
-    notation: "compact"
-  });
-  return formatter.format(roundDown(numberState));
-}
-
-function getBrowser() {
-  if (typeof chrome !== "undefined" && typeof chrome.runtime !== "undefined") {
-    return chrome;
-  } else if (typeof browser !== "undefined" && typeof browser.runtime !== "undefined") {
-    return browser;
-  } else {
-    console.log("browser is not supported");
-    return false;
-  }
-}
-
-function getVideoId(url) {
-  var urlObject = new URL(url);
-  var pathname = urlObject.pathname;
-
-  if (pathname.startsWith("/clip")) {
-    return document.querySelector("meta[itemprop='videoId']").content;
-  } else {
-    return urlObject.searchParams.get("v");
-  }
-}
-
-function isVideoLoaded() {
-  var videoId = getVideoId(window.location.href);
-  return document.querySelector("ytd-watch-flexy[video-id='".concat(videoId, "']")) !== null || // mobile: no video-id attribute
-  document.querySelector('#player[loading="false"]:not([hidden])') !== null;
-}
-
-function cLog(message, writer) {
-  message = "[return youtube dislike]: ".concat(message);
-
-  if (writer) {
-    writer(message);
-  } else {
-    console.log(message);
-  }
-}
-
-
-;// CONCATENATED MODULE: ./Extensions/combined/src/events.js
-
-
-
-
-
-function sendVote(vote) {
-  getBrowser().runtime.sendMessage({
-    message: "send_vote",
-    vote: vote,
-    videoId: getVideoId(window.location.href)
-  });
-}
-
-function sendVideoIds() {
-  var links = Array.from(document.getElementsByClassName("yt-simple-endpoint ytd-compact-video-renderer")).concat(Array.from(document.getElementsByClassName("yt-simple-endpoint ytd-thumbnail"))); // Also try mobile
-
-  if (links.length < 1) links = Array.from(document.querySelectorAll(".large-media-item-metadata > a, a.large-media-item-thumbnail-container"));
-  var ids = links.filter(function (x) {
-    return x.href && x.href.indexOf("/watch?v=") > 0;
-  }).map(function (x) {
-    return getVideoId(x.href);
-  });
-  getBrowser().runtime.sendMessage({
-    message: "send_links",
-    videoIds: ids
-  });
-}
-
-function likeClicked(storedData) {
-  if (checkForSignInButton() === false) {
-    if (storedData.previousState === DISLIKED_STATE) {
-      sendVote(1);
-      storedData.dislikes--;
-      storedData.likes++;
-      createRateBar(storedData.likes, storedData.dislikes);
-      setDislikes(numberFormat(storedData.dislikes));
-      storedData.previousState = LIKED_STATE;
-    } else if (storedData.previousState === NEUTRAL_STATE) {
-      sendVote(1);
-      storedData.likes++;
-      createRateBar(storedData.likes, storedData.dislikes);
-      storedData.previousState = LIKED_STATE;
-    } else if (storedData.previousState = LIKED_STATE) {
-      sendVote(0);
-      storedData.likes--;
-      createRateBar(storedData.likes, storedData.dislikes);
-      storedData.previousState = NEUTRAL_STATE;
-    }
-  }
-}
-
-function dislikeClicked(storedData) {
-  if (checkForSignInButton() == false) {
-    if (storedData.previousState === NEUTRAL_STATE) {
-      sendVote(-1);
-      storedData.dislikes++;
-      setDislikes(numberFormat(storedData.dislikes));
-      createRateBar(storedData.likes, storedData.dislikes);
-      storedData.previousState = DISLIKED_STATE;
-    } else if (storedData.previousState === DISLIKED_STATE) {
-      sendVote(0);
-      storedData.dislikes--;
-      setDislikes(numberFormat(storedData.dislikes));
-      createRateBar(storedData.likes, storedData.dislikes);
-      storedData.previousState = NEUTRAL_STATE;
-    } else if (storedData.previousState === LIKED_STATE) {
-      sendVote(-1);
-      storedData.likes--;
-      storedData.dislikes++;
-      setDislikes(numberFormat(storedData.dislikes));
-      createRateBar(storedData.likes, storedData.dislikes);
-      storedData.previousState = DISLIKED_STATE;
-    }
-  }
-}
-
-
-;// CONCATENATED MODULE: ./Extensions/combined/src/state.js
-
-
-
-
-var LIKED_STATE = "LIKED_STATE";
-var DISLIKED_STATE = "DISLIKED_STATE";
-var NEUTRAL_STATE = "NEUTRAL_STATE";
-
-function isMobile() {
-  return location.hostname == "m.youtube.com";
-}
-
-function isVideoLiked() {
-  if (isMobile()) {
-    return getLikeButton().querySelector("button").getAttribute("aria-label") == "true";
-  }
-
-  return getLikeButton().classList.contains("style-default-active");
-}
-
-function isVideoDisliked() {
-  if (isMobile()) {
-    return getDislikeButton().querySelector("button").getAttribute("aria-label") == "true";
-  }
-
-  return getDislikeButton().classList.contains("style-default-active");
-}
-
-function getState(storedData) {
-  if (isVideoLiked()) {
-    return {
-      current: LIKED_STATE,
-      previous: storedData.previousState
-    };
-  }
-
-  if (isVideoDisliked()) {
-    return {
-      current: DISLIKED_STATE,
-      previous: storedData.previousState
-    };
-  }
-
-  return {
-    current: NEUTRAL_STATE,
-    previous: storedData.previousState
-  };
-} //---   Sets The Likes And Dislikes Values   ---//
-
-
-function setLikes(likesCount) {
-  getButtons().children[0].querySelector("#text").innerText = likesCount;
-}
-
-function setDislikes(dislikesCount) {
-  if (isMobile()) {
-    buttons_getButtons().children[1].querySelector(".button-renderer-text").innerText = dislikesCount;
-    return;
-  }
-
-  buttons_getButtons().children[1].querySelector("#text").innerText = dislikesCount;
-}
-
-function getLikeCountFromButton() {
-  var likesStr = getLikeButton().querySelector("button").getAttribute("aria-label").replace(/\D/g, "");
-  return likesStr.length > 0 ? parseInt(likesStr) : false;
-}
-
-function processResponse(response, storedData) {
-  var formattedDislike = numberFormat(response.dislikes);
-  setDislikes(formattedDislike);
-  storedData.dislikes = parseInt(response.dislikes);
-  storedData.likes = getLikeCountFromButton() || parseInt(response.likes);
-  createRateBar(storedData.likes, storedData.dislikes);
-}
-
-function setState(storedData) {
-  storedData.previousState = isVideoDisliked() ? DISLIKED_STATE : isVideoLiked() ? LIKED_STATE : NEUTRAL_STATE;
-  var statsSet = false;
-  getBrowser().runtime.sendMessage({
-    message: "set_state",
-    videoId: getVideoId(window.location.href),
-    state: getState(storedData).current,
-    likeCount: getLikeCountFromButton() || null
-  }, function (response) {
-    cLog("response from api:");
-    cLog(JSON.stringify(response));
-
-    if (response !== undefined && !("traceId" in response) && !statsSet) {
-      processResponse(response, storedData);
-    } else {}
-  });
-}
-
-function setInitialState(storedData) {
-  setState(storedData);
-  setTimeout(function () {
-    sendVideoIds();
-  }, 1500);
-}
-
-
-;// CONCATENATED MODULE: ./Extensions/combined/src/buttons.js
-
-
-function buttons_getButtons() {
-  var _document$getElementB;
-
-  if (isMobile()) {
-    return document.querySelector(".slim-video-action-bar-actions");
-  } //---   If Menu Element Is Displayed:   ---//
-
-
-  if (((_document$getElementB = document.getElementById("menu-container")) === null || _document$getElementB === void 0 ? void 0 : _document$getElementB.offsetParent) === null) {
-    return document.querySelector("ytd-menu-renderer.ytd-watch-metadata > div"); //---   If Menu Element Isnt Displayed:   ---//
-  } else {
-    var _document$getElementB2;
-
-    return (_document$getElementB2 = document.getElementById("menu-container")) === null || _document$getElementB2 === void 0 ? void 0 : _document$getElementB2.querySelector("#top-level-buttons-computed");
-  }
-}
-
-function getLikeButton() {
-  return buttons_getButtons().children[0];
-}
-
-function getDislikeButton() {
-  return buttons_getButtons().children[1];
-}
-
-function checkForSignInButton() {
-  if (document.querySelector("a[href^='https://accounts.google.com/ServiceLogin']")) {
-    return true;
-  } else {
-    return false;
-  }
-}
-
-
-;// CONCATENATED MODULE: ./Extensions/combined/ryd.content-script.js
-
-
-
-
-
-var storedData = {
-  likes: 0,
-  dislikes: 0,
-  previousState: NEUTRAL_STATE
-};
-var jsInitChecktimer = null;
-
-function setEventListeners(evt) {
-  function checkForJS_Finish() {
-    var _getButtons;
-
-    if ((_getButtons = buttons_getButtons()) !== null && _getButtons !== void 0 && _getButtons.offsetParent && isVideoLoaded()) {
-      clearInterval(jsInitChecktimer);
-      jsInitChecktimer = null;
-      var buttons = buttons_getButtons();
-
-      if (!window.returnDislikeButtonlistenersSet) {
-        buttons.children[0].addEventListener("click", function () {
-          return likeClicked(storedData);
-        });
-        buttons.children[1].addEventListener("click", function () {
-          return dislikeClicked(storedData);
-        });
-        window.returnDislikeButtonlistenersSet = true;
-      }
-
-      setInitialState(storedData);
-    }
-  }
-
-  if (window.location.href.indexOf("watch?") >= 0) {
-    jsInitChecktimer = setInterval(checkForJS_Finish, 111);
-  }
-}
-
-setEventListeners();
-document.addEventListener("yt-navigate-finish", function (event) {
-  if (jsInitChecktimer !== null) clearInterval(jsInitChecktimer);
-  window.returnDislikeButtonlistenersSet = false;
-  setEventListeners();
-});
-setTimeout(function () {
-  return sendVideoIds();
-}, 2500);
-/******/ })()
-;

+ 0 - 26
Extensions/combined/dist/firefox/content-style.css

@@ -1,26 +0,0 @@
-#ryd-bar-container {
-  background: var(--yt-spec-icon-disabled);
-  border-radius: 2px;
-}
-
-#ryd-bar {
-  background: var(--yt-spec-text-primary);
-  border-radius: 2px;
-  transition: all 0.15s ease-in-out;
-}
-
-.ryd-tooltip {
-  position: relative;
-  display: block;
-  height: 2px;
-  top: 9px;
-}
-
-.ryd-tooltip-bar-container {
-  width: 100%;
-  height: 2px;
-  position: absolute;
-  padding-top: 6px;
-  padding-bottom: 28px;
-  top: -6px;
-}

BIN
Extensions/combined/dist/firefox/icons/icon128.png


BIN
Extensions/combined/dist/firefox/icons/icon48.png


+ 0 - 26
Extensions/combined/dist/firefox/manifest.json

@@ -1,26 +0,0 @@
-{
-  "name": "Return YouTube Dislike",
-  "description": "Returns ability to see dislikes",
-  "version": "2.0.0.3",
-  "manifest_version": 2,
-  "background": {
-    "scripts": ["ryd.background.js"]
-  },
-  "icons": {
-    "48": "icons/icon48.png",
-   "128": "icons/icon128.png"
-  },
-  "permissions": ["activeTab", "*://*.youtube.com/*", "storage"],
-  "browser_action": {
-    "default_popup": "popup.html"
-  },
-  "content_scripts": [
-    {
-      "matches": ["*://*.youtube.com/*"],
-      "exclude_matches": ["*://*.music.youtube.com/*"],
-      "run_at": "document_idle",
-      "css": ["content-style.css"],
-      "js": ["bundled-content-script.js"]
-    }
-  ]
-}

+ 0 - 119
Extensions/combined/dist/firefox/popup.css

@@ -1,119 +0,0 @@
-/* Variables */
-:root {
-  --primary: #cc2929;
-  --accent: #581111;
-
-  --background: #111;
-  --secondary: #272727;
-  --tertiary: #333333;
-  --lightGrey: #999;
-  --white: #fff;
-}
-
-/* Window Styling */
-html,
-body {
-  background-color: var(--background);
-  color: var(--white);
-  min-width: 300px;
-  padding: 0.5em;
-  font-family: 'Roboto', Arial, Helvetica, sans-serif;
-  font-size: 14px;
-}
-
-h1 {
-  font-size: 26px;
-}
-
-button {
-  color: var(--white);
-  background: var(--secondary);
-  cursor: pointer;
-  padding: 5px 16px;
-  border: none;
-  border-radius: 4px;
-  font-weight: 500;
-  box-shadow: 0 2px 4px -1px rgb(0 0 0 / 20%), 0 4px 5px 0 rgb(0 0 0 / 14%), 0 1px 10px 0 rgb(0 0 0 / 12%);
-  transition: .4s;
-}
-
-button:hover {
-  background: #444;
-}
-
-#advancedToggle {
-  margin-top: 1em;
-  margin-bottom: 2em;
-}
-
-#advancedSettings {
-  display: none;
-  border: 2px solid var(--secondary);
-  border-radius: 0.5rem;
-  padding: 1rem;
-}
-
-#advancedLegend {
-  color: var(--tertiary) !important;
-  /* margin: auto; */ /* Center the label */
-  /* padding: .25rem .5rem; */
-  /* border-radius: .25rem; */
-  /* border: .25rem solid var(--secondary); */
-}
-
-/*   Switches   */
-.switch {
-  position: relative;
-  display: inline-block;
-  width: 30px;
-  height: 17px;
-  margin-bottom: 1rem;
-}
-
-.switch:last-of-type {
-  margin-bottom: 0;
-}
-
-.switch input {
-  display: none;
-}
-
-.slider {
-  position: absolute;
-  cursor: pointer;
-  top: 0;
-  left: 0;
-  right: 0;
-  bottom: 0;
-  background: var(--secondary);
-  transition: 0.4s;
-  border-radius: 34px;
-}
-
-.slider:before {
-  position: absolute;
-  content: "";
-  height: 13px;
-  width: 13px;
-  left: 2px;
-  bottom: 2px;
-  background: var(--lightGrey);
-  transition: 0.4s;
-  border-radius: 50%;
-}
-
-input:checked + .slider {
-  background: var(--accent);
-}
-
-input:checked + .slider:before {
-  transform: translateX(13px);
-  background: var(--primary);
-}
-
-.switchLabel {
-  margin-left: 0.5rem;
-  width: 250px !important;
-  transform: translateX(35px);
-  display: inline-block;
-}

+ 0 - 48
Extensions/combined/dist/firefox/popup.html

@@ -1,48 +0,0 @@
-<!DOCTYPE html>
-<html lang="en">
-  <head>
-    <meta content="text/html; charset=utf-8" />
-    <title>Return YouTube Dislike</title>
-    <link rel="stylesheet" href="popup.css" />
-    <link rel="preconnect" href="https://fonts.googleapis.com">
-    <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
-    <link href="https://fonts.googleapis.com/css2?family=Roboto:wght@100;300;400;500;700;900&display=swap" rel="stylesheet">
-  </head>
-  <body>
-    <center>
-      <svg width="48" viewBox="0 0 24 24"><path d="M14.9 3H6c-.9 0-1.6.5-1.9 1.2l-3 7c-.1.3-.1.5-.1.7v2c0 1.1.9 2 2 2h6.3l-.9 4.5c-.1.5 0 1 .4 1.4l1.1 1.1 6.5-6.6c.4-.4.6-.9.6-1.4V5c-.1-1.1-1-2-2.1-2zm7.4 12.8h-2.9c-.4 0-.7-.3-.7-.7V3.9c0-.4.3-.7.7-.7h2.9c.4 0 .7.3.7.7V15c0 .4-.3.8-.7.8z" fill="red"/><path d="m8 12.5 5.1-2.9L8 6.7v5.8z" fill="#fff"/></svg>
-      <h1>Return YouTube Dislike</h1>
-      <p>by Dmitrii Selivanov & Community</p>
-
-      <button id="link_website">Website</button>
-      <button id="link_github">GitHub</button>
-      <button id="link_discord">Discord</button>
-
-      <br><br>
-      <button id="link_donate">Donate</button>
-      <br>
-
-      <br>
-<!--      <button id="advancedToggle">Show Settings</button>-->
-      <br>
-
-    </center>
-
-    <fieldset id="advancedSettings">
-      <legend id="advancedLegend">Settings</legend>
-
-      <label class="switch">
-        <input type="checkbox" id="disable_ratio_bar" />
-        <span class="slider" />
-        <span class="switchLabel">Lorem ipsum dolor sit amet</span> </label
-      ><br />
-
-      <label class="switch">
-        <input type="checkbox" id="disable_api_unlisted" />
-        <span class="slider" />
-        <span class="switchLabel">Lorem ipsum dolor sit amet</span> </label
-      ><br />
-    </fieldset>
-  </body>
-  <script src="popup.js"></script>
-</html>

+ 0 - 61
Extensions/combined/dist/firefox/popup.js

@@ -1,61 +0,0 @@
-/*   Config   */
-const config = {
-  advanced: false,
-  showAdvancedMessage: "Show Settings",
-  hideAdvancedMessage: "Hide Settings",
-
-  links: {
-    website: "https://returnyoutubedislike.com",
-    github: "https://github.com/Anarios/return-youtube-dislike",
-    discord: "https://discord.gg/mYnESY4Md5",
-    donate: 'https://returnyoutubedislike.com/donate'
-  },
-};
-
-/*   Links   */
-document.getElementById("link_website").addEventListener("click", () => {
-  chrome.tabs.create({ url: config.links.website });
-});
-
-document.getElementById("link_github").addEventListener("click", () => {
-  chrome.tabs.create({ url: config.links.github });
-});
-
-document.getElementById("link_discord").addEventListener("click", () => {
-  chrome.tabs.create({ url: config.links.discord });
-});
-
-document.getElementById("link_donate").addEventListener("click", () => {
-  chrome.tabs.create({ url: config.links.donate });
-});
-
-
-chrome.runtime.sendMessage({ message: 'get_auth_token' });
-/*   Advanced Toggle   */
-/* Not currently used in this version
-const advancedToggle = document.getElementById("advancedToggle");
-advancedToggle.addEventListener("click", () => {
-  const adv = document.getElementById("advancedSettings");
-  if (config.advanced) {
-    adv.style.display = "none";
-    advancedToggle.innerHTML = config.showAdvancedMessage;
-    config.advanced = false;
-  } else {
-    adv.style.display = "block";
-    advancedToggle.innerHTML = config.hideAdvancedMessage;
-    config.advanced = true;
-  }
-});
-*/
-
-/* popup-script.js
-document.querySelector('#login')
-.addEventListener('click', function () {
-  chrome.runtime.sendMessage({ message: 'get_auth_token' });
-});
-
-
-document.querySelector("#log_off").addEventListener("click", function () {
-  chrome.runtime.sendMessage({ message: "log_off" });
-});
-*/

+ 0 - 220
Extensions/combined/dist/firefox/ryd.background.js

@@ -1,220 +0,0 @@
-const apiUrl = "https://returnyoutubedislikeapi.com";
-let api;
-if (typeof chrome !== "undefined" && typeof chrome.runtime !== "undefined")
-  api = chrome;
-else if (
-  typeof browser !== "undefined" &&
-  typeof browser.runtime !== "undefined"
-)
-  api = browser;
-
-api.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") {
-    // chrome.identity.clearAllCachedAuthTokens(() => console.log("logged off"));
-  } else if (request.message == "set_state") {
-    // chrome.identity.getAuthToken({ interactive: true }, function (token) {
-    let token = "";
-    fetch(`${apiUrl}/votes?videoId=${request.videoId}&likeCount=${request.likeCount || ''}`, {
-      method: "GET",
-      headers: {
-        Accept: "application/json",
-      },
-    })
-      .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 = [];
-    }
-  } else if (request.message == "register") {
-    register();
-    return true;
-  } else if (request.message == "send_vote") {
-    sendVote(request.videoId, request.vote);
-    return true;
-  }
-});
-
-async function sendVote(videoId, vote) {
-  api.storage.sync.get(null, async (storageResult) => {
-    if (!storageResult.userId || !storageResult.registrationConfirmed) {
-      await register();
-      return;
-    }
-    fetch(`${apiUrl}/interact/vote`, {
-      method: "POST",
-      headers: {
-        "Content-Type": "application/json",
-      },
-      body: JSON.stringify({
-        userId: storageResult.userId,
-        videoId,
-        value: vote,
-      }),
-    })
-      .then(async (response) => {
-        if (response.status == 401) {
-          await register();
-          await sendVote(videoId, vote);
-          return;
-        }
-        return response.json()
-      })
-      .then((response) => {
-        solvePuzzle(response).then((solvedPuzzle) => {
-          fetch(`${apiUrl}/interact/confirmVote`, {
-            method: "POST",
-            headers: {
-              "Content-Type": "application/json",
-            },
-            body: JSON.stringify({
-              ...solvedPuzzle,
-              userId: storageResult.userId,
-              videoId,
-            }),
-          });
-        });
-      });
-  });
-}
-
-function register() {
-  let userId = generateUserID();
-  api.storage.sync.set({ userId });
-  return fetch(`${apiUrl}/puzzle/registration?userId=${userId}`, {
-    method: "GET",
-    headers: {
-      Accept: "application/json",
-    },
-  })
-    .then((response) => response.json())
-    .then((response) => {
-      return solvePuzzle(response).then((solvedPuzzle) => {
-        return fetch(`${apiUrl}/puzzle/registration?userId=${userId}`, {
-          method: "POST",
-          headers: {
-            "Content-Type": "application/json",
-          },
-          body: JSON.stringify(solvedPuzzle),
-        }).then((response) =>
-          response.json().then((result) => {
-            if (result === true) {
-              return api.storage.sync.set({ registrationConfirmed: true });
-            }
-          })
-        );
-      });
-    })
-    .catch();
-}
-
-api.storage.sync.get(null, (res) => {
-  if (!res || !res.userId || !res.registrationConfirmed) {
-    register();
-  }
-});
-
-const sentIds = new Set();
-let toSend = [];
-
-function sendUserSubmittedStatisticsToApi(statistics) {
-  fetch(`${apiUrl}/votes/user-submitted`, {
-    method: "POST",
-    headers: {
-      "Content-Type": "application/json",
-    },
-    body: JSON.stringify(statistics),
-  });
-}
-
-function countLeadingZeroes(uInt8View, limit) {
-  let zeroes = 0;
-  let value = 0;
-  for (let i = 0; i < uInt8View.length; i++) {
-    value = uInt8View[i];
-    if (value === 0) {
-      zeroes += 8;
-    } else {
-      let count = 1;
-      if (value >>> 4 === 0) {
-        count += 4;
-        value <<= 4;
-      }
-      if (value >>> 6 === 0) {
-        count += 2;
-        value <<= 2;
-      }
-      zeroes += count - (value >>> 7);
-      break;
-    }
-    if (zeroes >= limit) {
-      break;
-    }
-  }
-  return zeroes;
-}
-
-async function solvePuzzle(puzzle) {
-  let challenge = Uint8Array.from(atob(puzzle.challenge), (c) =>
-    c.charCodeAt(0)
-  );
-  let buffer = new ArrayBuffer(20);
-  let uInt8View = new Uint8Array(buffer);
-  let uInt32View = new Uint32Array(buffer);
-  let maxCount = Math.pow(2, puzzle.difficulty) * 5;
-  for (let i = 4; i < 20; i++) {
-    uInt8View[i] = challenge[i - 4];
-  }
-
-  for (let i = 0; i < maxCount; i++) {
-    uInt32View[0] = i;
-    let hash = await crypto.subtle.digest("SHA-512", buffer);
-    let hashUint8 = new Uint8Array(hash);
-    if (countLeadingZeroes(hashUint8) >= puzzle.difficulty) {
-      return {
-        solution: btoa(String.fromCharCode.apply(null, uInt8View.slice(0, 4))),
-      };
-    }
-  }
-}
-
-function generateUserID(length = 36) {
-  const charset =
-    "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
-  let result = "";
-  if (crypto && crypto.getRandomValues) {
-    const values = new Uint32Array(length);
-    crypto.getRandomValues(values);
-    for (let i = 0; i < length; i++) {
-      result += charset[values[i] % charset.length];
-    }
-    return result;
-  } else {
-    for (let i = 0; i < length; i++) {
-      result += charset[Math.floor(Math.random() * charset.length)];
-    }
-    return result;
-  }
-}

+ 1 - 0
Extensions/combined/icons/server.svg

@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!-- Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --><path d="M480 160H32c-17.673 0-32-14.327-32-32V64c0-17.673 14.327-32 32-32h448c17.673 0 32 14.327 32 32v64c0 17.673-14.327 32-32 32zm-48-88c-13.255 0-24 10.745-24 24s10.745 24 24 24 24-10.745 24-24-10.745-24-24-24zm-64 0c-13.255 0-24 10.745-24 24s10.745 24 24 24 24-10.745 24-24-10.745-24-24-24zm112 248H32c-17.673 0-32-14.327-32-32v-64c0-17.673 14.327-32 32-32h448c17.673 0 32 14.327 32 32v64c0 17.673-14.327 32-32 32zm-48-88c-13.255 0-24 10.745-24 24s10.745 24 24 24 24-10.745 24-24-10.745-24-24-24zm-64 0c-13.255 0-24 10.745-24 24s10.745 24 24 24 24-10.745 24-24-10.745-24-24-24zm112 248H32c-17.673 0-32-14.327-32-32v-64c0-17.673 14.327-32 32-32h448c17.673 0 32 14.327 32 32v64c0 17.673-14.327 32-32 32zm-48-88c-13.255 0-24 10.745-24 24s10.745 24 24 24 24-10.745 24-24-10.745-24-24-24zm-64 0c-13.255 0-24 10.745-24 24s10.745 24 24 24 24-10.745 24-24-10.745-24-24-24z"/></svg>

+ 4 - 0
Extensions/combined/manifest-chrome.json

@@ -27,6 +27,10 @@
       "exclude_matches": ["*://*.music.youtube.com/*"],
       "js": ["bundled-content-script.js"],
       "css": ["content-style.css"]
+    },
+    {
+      "matches": ["*://*.returnyoutubedislike.com/debug","http://localhost/debug"],
+      "js": ["debug.js"]
     }
   ],
   "externally_connectable": {

+ 5 - 0
Extensions/combined/manifest-firefox.json

@@ -21,6 +21,11 @@
       "run_at": "document_idle",
       "css": ["content-style.css"],
       "js": ["bundled-content-script.js"]
+    },
+    {
+      "matches": ["*://*.returnyoutubedislike.com/debug","http://localhost/debug"],
+      "run_at": "document_idle",
+      "js": ["debug.js"]
     }
   ]
 }

+ 11 - 3
Extensions/combined/popup.css

@@ -17,7 +17,7 @@ body {
   color: var(--white);
   min-width: 300px;
   padding: 0.5em;
-  font-family: 'Roboto', Arial, Helvetica, sans-serif;
+  font-family: "Roboto", Arial, Helvetica, sans-serif;
   font-size: 14px;
 }
 
@@ -33,8 +33,9 @@ button {
   border: none;
   border-radius: 4px;
   font-weight: 500;
-  box-shadow: 0 2px 4px -1px rgb(0 0 0 / 20%), 0 4px 5px 0 rgb(0 0 0 / 14%), 0 1px 10px 0 rgb(0 0 0 / 12%);
-  transition: .4s;
+  box-shadow: 0 2px 4px -1px rgb(0 0 0 / 20%), 0 4px 5px 0 rgb(0 0 0 / 14%),
+    0 1px 10px 0 rgb(0 0 0 / 12%);
+  transition: 0.4s;
 }
 
 button:hover {
@@ -117,3 +118,10 @@ input:checked + .slider:before {
   transform: translateX(35px);
   display: inline-block;
 }
+
+#server-status {
+  height: 72px;
+  width: 90px;
+  /* filter: invert(21%) sepia(100%) saturate(3618%) hue-rotate(102deg)
+    brightness(96%) contrast(108%); */
+}

+ 21 - 11
Extensions/combined/popup.html

@@ -4,14 +4,25 @@
     <meta content="text/html; charset=utf-8" />
     <title>Return YouTube Dislike</title>
     <link rel="stylesheet" href="popup.css" />
-    <link rel="preconnect" href="https://fonts.googleapis.com">
-    <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
-    <link href="https://fonts.googleapis.com/css2?family=Roboto:wght@100;300;400;500;700;900&display=swap" rel="stylesheet">
+    <link rel="preconnect" href="https://fonts.googleapis.com" />
+    <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
+    <link
+      href="https://fonts.googleapis.com/css2?family=Roboto:wght@100;300;400;500;700;900&display=swap"
+      rel="stylesheet"
+    />
   </head>
   <body>
     <center>
-      <svg width="48" viewBox="0 0 24 24"><path d="M14.9 3H6c-.9 0-1.6.5-1.9 1.2l-3 7c-.1.3-.1.5-.1.7v2c0 1.1.9 2 2 2h6.3l-.9 4.5c-.1.5 0 1 .4 1.4l1.1 1.1 6.5-6.6c.4-.4.6-.9.6-1.4V5c-.1-1.1-1-2-2.1-2zm7.4 12.8h-2.9c-.4 0-.7-.3-.7-.7V3.9c0-.4.3-.7.7-.7h2.9c.4 0 .7.3.7.7V15c0 .4-.3.8-.7.8z" fill="red"/><path d="m8 12.5 5.1-2.9L8 6.7v5.8z" fill="#fff"/></svg>
+      <svg width="48" viewBox="0 0 24 24">
+        <path
+          d="M14.9 3H6c-.9 0-1.6.5-1.9 1.2l-3 7c-.1.3-.1.5-.1.7v2c0 1.1.9 2 2 2h6.3l-.9 4.5c-.1.5 0 1 .4 1.4l1.1 1.1 6.5-6.6c.4-.4.6-.9.6-1.4V5c-.1-1.1-1-2-2.1-2zm7.4 12.8h-2.9c-.4 0-.7-.3-.7-.7V3.9c0-.4.3-.7.7-.7h2.9c.4 0 .7.3.7.7V15c0 .4-.3.8-.7.8z"
+          fill="red"
+        />
+        <path d="m8 12.5 5.1-2.9L8 6.7v5.8z" fill="#fff" />
+      </svg>
       <h1>Return YouTube Dislike</h1>
+      <img id="server-status" src="./icons/server.svg" alt="" />
+      <p>API Status: <span id="status"></span></p>
       <p>by Dmitrii Selivanov & Community</p>
       <p id="ext-version"></p>
 
@@ -19,15 +30,14 @@
       <button id="link_github">GitHub</button>
       <button id="link_discord">Discord</button>
 
-      <br><br>
-       <button id="link_faq">FAQ</button>
+      <br /><br />
+      <button id="link_faq">FAQ</button>
       <button id="link_donate">Donate</button>
-      <br>
+      <br />
 
-      <br>
+      <br />
       <button id="advancedToggle">Show Settings</button>
-      <br>
-
+      <br />
     </center>
 
     <fieldset id="advancedSettings">
@@ -38,7 +48,7 @@
         <span class="slider" />
         <span class="switchLabel">Disable like/dislike submission</span>
       </label>
-      <br/>
+      <br />
 
       <!-- <label class="switch">
         <input type="checkbox" id="disable_api_unlisted" />

+ 37 - 18
Extensions/combined/popup.js

@@ -4,23 +4,13 @@ const config = {
   showAdvancedMessage: "Show Settings",
   hideAdvancedMessage: "Hide Settings",
   disableVoteSubmission: false,
-}
-
- function initConfig() {
-  initializeVersionNumber();
-  }
-
- function initializeVersionNumber() {
-  const version = chrome.runtime.getManifest().version;
-  document.getElementById('ext-version').innerHTML = 'v' + version;
-}
   
   links: {
     website: "https://returnyoutubedislike.com",
     github: "https://github.com/Anarios/return-youtube-dislike",
     discord: "https://discord.gg/mYnESY4Md5",
-    donate: 'https://returnyoutubedislike.com/donate',
-    faq: 'https://returnyoutubedislike.com/faq'
+    donate: "https://returnyoutubedislike.com/donate",
+    faq: "https://returnyoutubedislike.com/faq",
   },
 };
 
@@ -45,10 +35,11 @@ document.getElementById("link_donate").addEventListener("click", () => {
   chrome.tabs.create({ url: config.links.donate });
 });
 
-
-document.getElementById("disable_vote_submission").addEventListener("click", (ev) => {
-  chrome.storage.sync.set({ disableVoteSubmission: ev.target.checked });
-});
+document
+  .getElementById("disable_vote_submission")
+  .addEventListener("click", (ev) => {
+    chrome.storage.sync.set({ disableVoteSubmission: ev.target.checked });
+  });
 
 /*   Advanced Toggle   */
 const advancedToggle = document.getElementById("advancedToggle");
@@ -69,10 +60,16 @@ initConfig();
 
 function initConfig() {
   initializeDisableVoteSubmission();
+  initializeVersionNumber();
+}
+
+function initializeVersionNumber() {
+  const version = chrome.runtime.getManifest().version;
+  document.getElementById('ext-version').innerHTML = 'v' + version;
 }
 
 function initializeDisableVoteSubmission() {
-  chrome.storage.sync.get(['disableVoteSubmission'], (res) => {
+  chrome.storage.sync.get(["disableVoteSubmission"], (res) => {
     handleDisableVoteSubmissionChangeEvent(res.disableVoteSubmission);
   });
 }
@@ -81,7 +78,9 @@ chrome.storage.onChanged.addListener(storageChangeHandler);
 
 function storageChangeHandler(changes, area) {
   if (changes.disableVoteSubmission !== undefined) {
-    handleDisableVoteSubmissionChangeEvent(changes.disableVoteSubmission.newValue);
+    handleDisableVoteSubmissionChangeEvent(
+      changes.disableVoteSubmission.newValue
+    );
   }
 }
 
@@ -90,6 +89,26 @@ function handleDisableVoteSubmissionChangeEvent(value) {
   document.getElementById("disable_vote_submission").checked = value;
 }
 
+(async function getStatus() {
+  let status = document.getElementById("status");
+  let serverStatus = document.getElementById("server-status");
+  let resp = await fetch(
+    "https://returnyoutubedislikeapi.com/votes?videoId=YbJOTdZBX1g"
+  );
+  let result = await resp.status;
+  if (result === 200) {
+    status.innerText = "Online";
+    status.style.color = "green";
+    serverStatus.style.filter =
+      "invert(58%) sepia(81%) saturate(2618%) hue-rotate(81deg) brightness(119%) contrast(129%)";
+  } else {
+    status.innerText = "Offline";
+    status.style.color = "red";
+    serverStatus.style.filter =
+      "invert(11%) sepia(100%) saturate(6449%) hue-rotate(3deg) brightness(116%) contrast(115%)";
+  }
+})();
+
 /* popup-script.js
 document.querySelector('#login')
 .addEventListener('click', function () {

+ 5 - 5
Extensions/combined/src/events.js

@@ -43,7 +43,7 @@ function likeClicked() {
   if (checkForSignInButton() === false) {
     if (storedData.previousState === DISLIKED_STATE) {
       sendVote(1);
-      storedData.dislikes--;
+      if (storedData.dislikes > 0) storedData.dislikes--;
       storedData.likes++;
       createRateBar(storedData.likes, storedData.dislikes);
       setDislikes(numberFormat(storedData.dislikes));
@@ -55,7 +55,7 @@ function likeClicked() {
       storedData.previousState = LIKED_STATE;
     } else if ((storedData.previousState = LIKED_STATE)) {
       sendVote(0);
-      storedData.likes--;
+      if (storedData.likes > 0) storedData.likes--;
       createRateBar(storedData.likes, storedData.dislikes);
       storedData.previousState = NEUTRAL_STATE;
     }
@@ -72,13 +72,13 @@ function dislikeClicked() {
       storedData.previousState = DISLIKED_STATE;
     } else if (storedData.previousState === DISLIKED_STATE) {
       sendVote(0);
-      storedData.dislikes--;
+      if (storedData.dislikes > 0) storedData.dislikes--;
       setDislikes(numberFormat(storedData.dislikes));
       createRateBar(storedData.likes, storedData.dislikes);
       storedData.previousState = NEUTRAL_STATE;
     } else if (storedData.previousState === LIKED_STATE) {
       sendVote(-1);
-      storedData.likes--;
+      if (storedData.likes > 0) storedData.likes--;
       storedData.dislikes++;
       setDislikes(numberFormat(storedData.dislikes));
       createRateBar(storedData.likes, storedData.dislikes);
@@ -113,4 +113,4 @@ export {
   dislikeClicked,
   addLikeDislikeEventListener,
   storageChangeHandler,
-};
+};

+ 8 - 5
README.md

@@ -25,8 +25,7 @@ Additionally, the `dislike` field in the YouTube API was [removed](https://suppo
 
 ## What it Does
 
-With the removal of dislike stats from the YouTube API, our backend switched to using a combination of scraped dislike stats, estimates extrapolated from extension user data
-and estimates based on view\like ratios.
+With the removal of dislike stats from the YouTube API, our backend switched to using a combination of scraped dislike stats, estimates extrapolated from extension user data.
 
 [FAQ](https://github.com/Anarios/return-youtube-dislike/blob/main/FAQ.md)
 
@@ -34,6 +33,7 @@ and estimates based on view\like ratios.
 
 You can learn more at our website at: [returnyoutubedislike.com](https://www.returnyoutubedislike.com/)
 
+
 ## API documentation
 
 Third party use of this open API is allowed with the following restrictions:
@@ -66,11 +66,14 @@ Example to get votes of a given YouTube video ID:
 None existing YouTube ID will return status code *404* "Not Found".  
 Wrong formed YouTube ID will return *400* "Bad Request".
 
-## HELP WANTED
 
-We have an issue which is happening to a low percentage of Chrome users. service worker (ex background script) goes to Inactive state and doesn't wake up even when youtube tab is reopened. Only switching the extension off and on in extensions tab helps. This looks like a Chrome manifestv3 bug - so if anyone knows a good workaround - please open an issue\create a PR.
 
-Looks like its [this bug in chromium](https://bugs.chromium.org/p/chromium/issues/detail?id=1271154), and there is no good workaround. If anyone is aware of a workaounds - please contact.
+<!---
+## API documentation
+
+You can view all documentation on our website.
+[https://returnyoutubedislike.com/documentation/](https://returnyoutubedislike.com/documentation/) -->
+
 
 ## Contributing
 

+ 7 - 24
Website/layouts/default.vue

@@ -31,30 +31,13 @@
 export default {
   data: () => ({
     links: [
-      {
-        name: "Home",
-        path: "/",
-      },
-      {
-        name: "Install",
-        path: "/install",
-      },
-      {
-        name: "Help",
-        path: "/help",
-      },
-      {
-        name: "FAQ",
-        path: "/faq",
-      },
-      {
-        name: "Donate",
-        path: "/donate",
-      },
-      {
-        name: "Links",
-        path: "/links",
-      },
+      { name: "Home", path: "/" },
+      { name: "Install", path: "/install" },
+      { name: "Help", path: "/help" },
+      { name: "FAQ", path: "/faq" },
+      { name: "Donate", path: "/donate" },
+      { name: "Links", path: "/links" },
+      { name: "API", path: "/documentation" },
     ],
   }),
 };

+ 10 - 3
Website/nuxt.config.js

@@ -27,12 +27,18 @@ export default {
     ],
   },
 
+  env: {
+    apiUrl: "https://returnyoutubedislikeapi.com",
+  },
+
+  //server: { host: '0.0.0.0', port: 80 }, //LINE FOR DEBUGGING ONLY
+
   target: "static",
   css: [],
   plugins: [],
   components: true,
   buildModules: ["@nuxtjs/vuetify"],
-  modules: [],
+  modules: ["nuxt-user-agent"],
 
   // Vuetify module configuration: https://go.nuxtjs.dev/config-vuetify
   vuetify: {
@@ -52,7 +58,7 @@ export default {
       },
     },
   },
-
+  /*
   build: {
     extend(config, ctx) {
       // Run ESLint on save (dev-only)
@@ -65,5 +71,6 @@ export default {
         });
       }
     },
-  },
+  }
+*/
 };

+ 60 - 0
Website/package-lock.json

@@ -10,9 +10,11 @@
       "dependencies": {
         "core-js": "^3.15.1",
         "nuxt": "^2.15.7",
+        "nuxt-user-agent": "^1.2.2",
         "vuetify": "^2.5.5"
       },
       "devDependencies": {
+        "@nuxtjs/device": "^2.1.0",
         "@nuxtjs/vuetify": "^1.12.1",
         "babel-eslint": "^10.1.0",
         "eslint": "^7.32.0",
@@ -2643,6 +2645,21 @@
       "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
       "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="
     },
+    "node_modules/@nuxtjs/device": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/@nuxtjs/device/-/device-2.1.0.tgz",
+      "integrity": "sha512-TYBdt1w2bmCCWp+MhgcBATZtqyUBi3nSdNpcLGILw5USLwCsC/yZtIkq9YisuEzuRnod9w/RZpoE80MxLftEuA==",
+      "dev": true,
+      "dependencies": {
+        "defu": "^3.2.2"
+      }
+    },
+    "node_modules/@nuxtjs/device/node_modules/defu": {
+      "version": "3.2.2",
+      "resolved": "https://registry.npmjs.org/defu/-/defu-3.2.2.tgz",
+      "integrity": "sha512-8UWj5lNv7HD+kB0e9w77Z7TdQlbUYDVWqITLHNqFIn6khrNHv5WQo38Dcm1f6HeNyZf0U7UbPf6WeZDSdCzGDQ==",
+      "dev": true
+    },
     "node_modules/@nuxtjs/vuetify": {
       "version": "1.12.1",
       "resolved": "https://registry.npmjs.org/@nuxtjs/vuetify/-/vuetify-1.12.1.tgz",
@@ -8914,6 +8931,14 @@
         "nuxt": "bin/nuxt.js"
       }
     },
+    "node_modules/nuxt-user-agent": {
+      "version": "1.2.2",
+      "resolved": "https://registry.npmjs.org/nuxt-user-agent/-/nuxt-user-agent-1.2.2.tgz",
+      "integrity": "sha512-Z9d+r1/PzJAvrr4rX70IWvRyI3qw3RukAGrRZPZ9WeByuCWmVKiW8G1AhdkUOyrDrVoBUC59iLqIVkop/NjSuQ==",
+      "dependencies": {
+        "woothee": "^1.8.1"
+      }
+    },
     "node_modules/object-assign": {
       "version": "4.1.1",
       "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
@@ -14548,6 +14573,11 @@
         "node": ">=8"
       }
     },
+    "node_modules/woothee": {
+      "version": "1.11.1",
+      "resolved": "https://registry.npmjs.org/woothee/-/woothee-1.11.1.tgz",
+      "integrity": "sha512-KdArM3MsNa5tlSBSL29w9ouy9MXZoFPeUdPVnL4QZH3iyV8HsqnwbWw2YLiXEx2wAh0bM55dnl0+qDE6KHBlhQ=="
+    },
     "node_modules/word-wrap": {
       "version": "1.2.3",
       "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz",
@@ -16628,6 +16658,23 @@
         }
       }
     },
+    "@nuxtjs/device": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/@nuxtjs/device/-/device-2.1.0.tgz",
+      "integrity": "sha512-TYBdt1w2bmCCWp+MhgcBATZtqyUBi3nSdNpcLGILw5USLwCsC/yZtIkq9YisuEzuRnod9w/RZpoE80MxLftEuA==",
+      "dev": true,
+      "requires": {
+        "defu": "^3.2.2"
+      },
+      "dependencies": {
+        "defu": {
+          "version": "3.2.2",
+          "resolved": "https://registry.npmjs.org/defu/-/defu-3.2.2.tgz",
+          "integrity": "sha512-8UWj5lNv7HD+kB0e9w77Z7TdQlbUYDVWqITLHNqFIn6khrNHv5WQo38Dcm1f6HeNyZf0U7UbPf6WeZDSdCzGDQ==",
+          "dev": true
+        }
+      }
+    },
     "@nuxtjs/vuetify": {
       "version": "1.12.1",
       "resolved": "https://registry.npmjs.org/@nuxtjs/vuetify/-/vuetify-1.12.1.tgz",
@@ -21504,6 +21551,14 @@
         "@nuxt/webpack": "2.15.8"
       }
     },
+    "nuxt-user-agent": {
+      "version": "1.2.2",
+      "resolved": "https://registry.npmjs.org/nuxt-user-agent/-/nuxt-user-agent-1.2.2.tgz",
+      "integrity": "sha512-Z9d+r1/PzJAvrr4rX70IWvRyI3qw3RukAGrRZPZ9WeByuCWmVKiW8G1AhdkUOyrDrVoBUC59iLqIVkop/NjSuQ==",
+      "requires": {
+        "woothee": "^1.8.1"
+      }
+    },
     "object-assign": {
       "version": "4.1.1",
       "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
@@ -25917,6 +25972,11 @@
         "string-width": "^4.0.0"
       }
     },
+    "woothee": {
+      "version": "1.11.1",
+      "resolved": "https://registry.npmjs.org/woothee/-/woothee-1.11.1.tgz",
+      "integrity": "sha512-KdArM3MsNa5tlSBSL29w9ouy9MXZoFPeUdPVnL4QZH3iyV8HsqnwbWw2YLiXEx2wAh0bM55dnl0+qDE6KHBlhQ=="
+    },
     "word-wrap": {
       "version": "1.2.3",
       "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz",

+ 1 - 0
Website/package.json

@@ -12,6 +12,7 @@
   "dependencies": {
     "core-js": "^3.15.1",
     "nuxt": "^2.15.7",
+    "nuxt-user-agent": "^1.2.2",
     "vuetify": "^2.5.5"
   },
   "devDependencies": {

+ 68 - 0
Website/pages/debug.vue

@@ -0,0 +1,68 @@
+<template>
+  <div>
+    <!--   Top Section // "Sections" Card   -->
+    <v-card max-width="600px" class="rounded-lg">
+      <v-card-title style="padding-bottom: 0">Debug Information</v-card-title>
+      <v-card-text style="text-align: left">
+        <!--   Gather Browser Information   -->
+        <span><b>Browser Information:</b></span
+        ><br />
+        <span>Browser: {{ device._parsed.name }}</span
+        ><br />
+        <span>Browser Vendor: {{ device._parsed.vendor }}</span
+        ><br />
+        <span>Version: {{ device._parsed.version }}</span
+        ><br />
+        <span>Operating System: {{ device._parsed.os }}</span
+        ><br />
+        <span>Operating System Version: {{ device._parsed.os_version }}</span
+        ><br />
+        <span>Device Type: {{ device._parsed.category }}</span
+        ><br /><br />
+        <!--   Gather Extension Information   -->
+        <span><b>Installed Extension Information:</b></span
+        ><br />
+        <span
+          >Extension Version:
+          <span id="extension-version">Waiting For Extension...</span></span
+        ><br />
+      </v-card-text>
+      <v-card-actions>
+        <v-spacer />
+        <v-btn @click="copy()">
+          <v-icon small style="margin-right: 0.25em">mdi-content-copy</v-icon
+          >Copy
+        </v-btn>
+      </v-card-actions>
+    </v-card>
+  </div>
+</template>
+
+<script>
+export default {
+  data() {
+    return {
+      device: this.$ua,
+    };
+  },
+
+  methods: {
+    copy() {
+      const toCopy = `\`\`\`
+Browser Information:
+Browser: ${this.device._parsed.name}
+Browser Vendor: ${this.device._parsed.vendor}
+Version: ${this.device._parsed.version}
+Operating System: ${this.device._parsed.os}
+Operating System Version: ${this.device._parsed.os_version}
+Device Type: ${this.device._parsed.category}
+
+Installed Extension Information:
+Extension Version: ${document.getElementById("extension-version").innerHTML}
+\`\`\``;
+
+      navigator.clipboard.writeText(toCopy);
+    },
+  },
+};
+</script>

+ 60 - 0
Website/pages/documentation.vue

@@ -0,0 +1,60 @@
+<template>
+  <div>
+    <!--   Top Section // "Sections" Card   -->
+    <v-card max-width="600px" class="rounded-lg">
+      <v-card-title style="padding-bottom: 0">Sections</v-card-title>
+      <v-list>
+        <!--   Dynamically Generate Links From Below   -->
+        <v-list-item v-for="(item, i) in links" :key="i" router :to="item.to">
+          <v-list-item-icon>
+            <v-icon v-text="item.icon" />
+          </v-list-item-icon>
+          <v-list-item-title style="text-align: left">
+            <v-list-item-title v-text="item.text" />
+          </v-list-item-title>
+        </v-list-item>
+      </v-list>
+    </v-card>
+
+    <!--   Child Pages // Card   -->
+    <v-card
+      max-width="600px"
+      class="rounded-lg"
+      style="margin: 1em; padding: 0.75em; text-align: left"
+    >
+      <NuxtChild />
+    </v-card>
+  </div>
+</template>
+
+<script>
+export default {
+  data() {
+    return {
+      //---   Links To Generate Above    ---//
+      links: [
+        {
+          text: "Usage Rights",
+          icon: "mdi-book-open-variant",
+          to: "/documentation/usage-rights",
+        },
+        {
+          text: "URL Information",
+          icon: "mdi-web",
+          to: "/documentation/url",
+        },
+        {
+          text: "Available Endpoints",
+          icon: "mdi-transit-connection-variant",
+          to: "/documentation/endpoints",
+        },
+        {
+          text: "Basic Fetching Tutorial",
+          icon: "mdi-school",
+          to: "/documentation/fetching",
+        },
+      ],
+    };
+  },
+};
+</script>

+ 19 - 0
Website/pages/documentation/endpoints.vue

@@ -0,0 +1,19 @@
+<template>
+  <div>
+    <h1 class="primary--text">Available Endpoints</h1>
+    List of available endpoints is available here:<br />
+    <a :href="endpointUrl" target="_blank" v-text="endpointUrl" />
+  </div>
+</template>
+
+<script>
+let apiUrl = process.env.apiUrl;
+export default {
+  data() {
+    return {
+      apiUrl: apiUrl,
+      endpointUrl: apiUrl + "/swagger/index.html",
+    };
+  },
+};
+</script>

+ 78 - 0
Website/pages/documentation/fetching.vue

@@ -0,0 +1,78 @@
+<template>
+  <div>
+    <h1 class="primary--text">Basic Fetching Tutorial</h1>
+
+    <span>Example to get votes of a given YouTube video ID:</span>
+    <a href="https://youtube.com/watch?v=kxOuG8jMIgI" target="_blank"
+      >kxOuG8jMIgI</a
+    ><br /><br />
+
+    <h2>Example Request:</h2>
+    <span><b>Request URL:</b></span>
+    <a
+      :href="apiUrl + '/votes?videoId=kxOuG8jMIgI'"
+      target="_blank"
+      v-text="apiUrl + '/votes?videoId=kxOuG8jMIgI'"
+    /><br />
+    <span
+      ><b>Request Method:</b>
+      <a
+        href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/GET"
+        target="_blank"
+        >HTTP/GET</a
+      ></span
+    ><br />
+    <span><b>Headers:</b></span
+    ><br />
+    <code class="code">
+      Accept: text/html,application/xhtml+xml,application/xml;q=0.9<br />
+      Pragma: no-cache<br />
+      Cache-Control: no-cache<br />
+      Connection: keep-alive </code
+    ><br />
+    <span><b>Response:</b></span
+    ><br />
+    <div class="code">
+      <code style="background-color: rgba(0, 0, 0, 0)">
+        {<br />
+        "id": "kxOuG8jMIgI",<br />
+        "dateCreated": "2021-12-20T12:25:54.418014Z",<br />
+        "likes": 27326,<br />
+        "dislikes": 498153,<br />
+        "rating": 1.212014408444885,<br />
+        "viewCount": 3149885,<br />
+        "deleted": false<br />
+        }
+      </code>
+    </div>
+    <br /><br />
+    <v-alert border="left" color="orange" text type="info">
+      <span>An invalid YouTube ID will return status code 404 "Not Found".</span
+      ><br />
+      <span
+        >An incorrectly formatted YouTube ID will return 400 "Bad
+        Request".</span
+      >
+    </v-alert>
+
+    <a :href="endpointUrl" target="_blank" v-text="endpointUrl" />
+  </div>
+</template>
+
+<style scoped>
+.code {
+  width: 100%;
+  background: #353535;
+  border-radius: 3px;
+}
+</style>
+
+<script>
+export default {
+  data() {
+    return {
+      apiUrl: process.env.apiUrl,
+    };
+  },
+};
+</script>

+ 8 - 0
Website/pages/documentation/index.vue

@@ -0,0 +1,8 @@
+<template>
+  <div>
+    <h1>
+      Welcome to the <span class="primary--text">official RYD docs</span>!
+    </h1>
+    <p>To get started, select a section.</p>
+  </div>
+</template>

+ 17 - 0
Website/pages/documentation/url.vue

@@ -0,0 +1,17 @@
+<template>
+  <div>
+    <h1 class="primary--text">URL Information</h1>
+    The API is accessible over the following base URL:<br />
+    <a :href="apiUrl" target="_blank" v-text="apiUrl" />
+  </div>
+</template>
+
+<script>
+export default {
+  data() {
+    return {
+      apiUrl: process.env.apiUrl,
+    };
+  },
+};
+</script>

+ 30 - 0
Website/pages/documentation/usage-rights.vue

@@ -0,0 +1,30 @@
+<template>
+  <div>
+    <h1 class="primary--text">Usage Rights</h1>
+    <p>
+      Third party use of this open API is allowed with the following
+      restrictions:
+    </p>
+    <ul>
+      <li>
+        <b>Attribution:</b> This project should be clearly attributed with
+        either a link to this repo or a link to returnyoutubedislike.com.
+      </li>
+      <li>
+        <b>Rate Limiting:</b> There are per client rate limits in place of 100
+        per minute and 10'000 per day. This will return a 429 status code
+        indicating that your application should back off.
+      </li>
+    </ul>
+  </div>
+</template>
+
+<style scoped>
+li {
+  margin-top: 0.5em;
+}
+
+b {
+  font-weight: 900 !important;
+}
+</style>

+ 1 - 1
Website/pages/index.vue

@@ -28,7 +28,7 @@
       <h1 class="title-text">Return YouTube Dislike</h1>
       <div class="mb-4" style="color: #999">
         <p style="margin-top: 0">
-          Browser extension and an API that show you dislikes on Youtube
+          Browser extension and an API that shows you dislikes on Youtube
         </p>
       </div>
 

+ 1 - 1
Website/pages/install.vue

@@ -92,7 +92,7 @@ export default {
       scriptLink:
         "https://github.com/Anarios/return-youtube-dislike/raw/main/Extensions/UserScript/Return%20Youtube%20Dislike.user.js",
 
-      iosJailbreakLink: "https://repo.lillieweeb001.xyz/",
+      iosJailbreakLink: "https://chariz.com/get/return-youtube-dislike/",
     };
   },
 };

+ 12 - 7
package-lock.json

@@ -2141,6 +2141,8 @@
       "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.8.2.tgz",
       "integrity": "sha512-x9VuX+R/jcFj1DHo/fCp99esgGDWiHENrKxaCENuCxpoMCmAt/COCGVDwA7kleEpEzJjDnvh3yGoOuLu0Dtllw==",
       "dev": true,
+      "optional": true,
+      "peer": true,
       "dependencies": {
         "fast-deep-equal": "^3.1.1",
         "json-schema-traverse": "^1.0.0",
@@ -2156,7 +2158,9 @@
       "version": "1.0.0",
       "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz",
       "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==",
-      "dev": true
+      "dev": true,
+      "optional": true,
+      "peer": true
     },
     "node_modules/ajv-keywords": {
       "version": "3.5.2",
@@ -5570,15 +5574,14 @@
       "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz",
       "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==",
       "dev": true,
-      "requires": {
-        "ajv": "^8.0.0"
-      },
+      "requires": {},
       "dependencies": {
         "ajv": {
-          "version": "8.8.2",
-          "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.8.2.tgz",
+          "version": "https://registry.npmjs.org/ajv/-/ajv-8.8.2.tgz",
           "integrity": "sha512-x9VuX+R/jcFj1DHo/fCp99esgGDWiHENrKxaCENuCxpoMCmAt/COCGVDwA7kleEpEzJjDnvh3yGoOuLu0Dtllw==",
           "dev": true,
+          "optional": true,
+          "peer": true,
           "requires": {
             "fast-deep-equal": "^3.1.1",
             "json-schema-traverse": "^1.0.0",
@@ -5590,7 +5593,9 @@
           "version": "1.0.0",
           "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz",
           "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==",
-          "dev": true
+          "dev": true,
+          "optional": true,
+          "peer": true
         }
       }
     },