Selaa lähdekoodia

Merge branch 'main' into main

Eryk Darnowski 3 vuotta sitten
vanhempi
sitoutus
ddcca0017e

+ 2 - 0
CONTRIBUTING.md

@@ -34,6 +34,8 @@ npm run build // to create the build file(s) once
 
 Congratulations, You are now ready to develop!
 
+If you are new to developing Chrome extensions, or need extra help, please see [this YouTube tutorial](https://www.youtube.com/watch?v=mdOj6HYE3_0)
+
 
 ### Issues
 #### Opening a new issue

+ 5 - 5
Docs/FAQ.md

@@ -1,13 +1,13 @@
-# Frquently Asked Questions
+# Frequently Asked Questions
 ## Before asking a question on GitHub or Discord, please refer to this.
 
-### **1. Where does extension get data?**
-Combination of GoogleAPI data and scraped data.
+### **1. Where does this extension get the data?**
+A Combination of Google APIs and scraped data.
 
-We save all available data to our DB for it to be available after google shuts down dislike counts in their API.
+We save all available data to our DB for it to be available after Google shuts down dislike counts in their API.
 
 ### **2. Video dislike count doesn't update**
-Right now video dislikes are cached, and arent updated very frequenly. Once in 2-3 days, not more often.
+Right now video dislikes are cached, and aren't updated very frequenly. Once every 2-3 days, not more often.
 
 Yeah, it's not ideal, but it is what it is. Working on improving how often we can update them.
 

+ 2 - 1
Docs/Guide__Installing.md

@@ -191,7 +191,8 @@ For now, you can try this
 
 ##### App from Play Store
 
-- Although app(s) which use this API exists but aren't they official.
+- Although app(s) which use this API exist, they aren't official.
+
   
 ##### On Firefox
 

+ 8 - 8
Docs/Guide__Troubleshooting.md

@@ -12,7 +12,7 @@ Troubleshooting Guide
   - [Check for conflicting extensions](#check-for-conflicting-extensions)
   - [Known conflicts](#known-conflicts)
 - [iOS app](#ios-app)
-- [YouTube Vanced  app](#youtube-vanced--app)
+- [YouTube Vanced app](#youtube-vanced--app)
 - [Contact in Discord Server](#contact-in-discord-server)
 - [Useful Links](#useful-links)
 
@@ -41,7 +41,7 @@ If the basic checks didn't resolve anything
 
 - If you **don't see something like** this, then the **API is down** and **everything is fine on your side**.
   `{"id":"QOFEgexls14","dateCreated":"2021-12-28T02:53:20.995329Z","likes":2968,"dislikes":204,"rating":4.725047080979285,"viewCount":29157,"deleted":false}`
-- If you see some responses but not in the above format (with likes and dislikes) then probably you are being rate-limited. It is done to prevent bot attacks and database vandalization. It depends on IP (its hash - which is never stored in non-volatile storage) for its countermeasures. If many people are accessing the server from the same IP (as in the case of public/institutional Wi-Fi) then it's possible that the IP is being rate-limited. If that's the case, There's no way for us to differentiate you from a bot/attacker.
+- If you see some responses but not in the above format (with likes and dislikes) then probably you are being rate-limited. It is done to prevent bot attacks and database vandalization. It depends on IP (its hash - which is never stored in non-volatile storage) for its countermeasures. If many people are accessing the server from the same IP (as in the case of public/institutional Wi-Fi) then it's possible that the IP is being rate-limited. If that's the case, there's no way for us to differentiate you from a bot/attacker.
 
 **If you see "Certificate error" and [if you are on Windows 7 (or earlier) read this](#install-certificates)**
 
@@ -63,12 +63,12 @@ You can follow this guide:
 
 [Fix error NET::ERR CERT DATE INVALID - Your connection is not private - Windows 7 - 2021](https://youtu.be/JYZLxP2Z8G4)
 
-If you don't want to install the certificate from Google drive
+If you don't want to install the certificate from Google Drive
 
 - Here is the official link to the certificate [**x1.i.lencr.org**](http://x1.i.lencr.org/).
 - **You will have to close all the tabs** before downloading this certificate.
 
-**The thumb print of real certificate is `cabd2a79a1076a31f21d253635cb039d4329a5e8`**
+**The thumbprint of real certificate is `cabd2a79a1076a31f21d253635cb039d4329a5e8`**
 
 **To make sure that you have installed the correct certificate, you should consider checking if the thumbprints match.** To do this you can follow this guide: [How to check a certificate's thumbprint](https://knowledge.digicert.com/solution/SO9840.html)
 
@@ -117,7 +117,7 @@ If it does, find the extension(s) preventing RYD from working correctly and re-c
 >
 > **Solution:** Trust `returnyoutubedislikeapi.com` manually
 >
-> ![rust returnyoutubedislikeapi.com manually](https://cdn.discordapp.com/attachments/821116437720334397/929814357708247060/unknown.png)
+> ![trust returnyoutubedislikeapi.com manually](https://cdn.discordapp.com/attachments/821116437720334397/929814357708247060/unknown.png)
 
 <br>
 
@@ -139,7 +139,7 @@ Coming soon. Please have patience.
 
 <br>
 
-## YouTube Vanced  app
+## YouTube Vanced app
 
 Coming soon. Please have patience.
 
@@ -153,11 +153,11 @@ Coming soon. Please have patience.
 
 [Discord server link: https://discord.gg/mYnESY4Md5][3]
 
-0. Join the discord server if haven't already
+0. Join the discord server if you haven't already
 1. Go to the #Bugs-and-problems channel
 2. There, thoroughly describe:
    - your problem
-   - what you have tried & what didn't work
+   - what you have tried and what didn't work
    - results of the troubleshooting steps
 
 <!-- {

+ 2 - 2
Docs/SECURITY-FAQ.md

@@ -6,7 +6,7 @@ No. The extension's code is public and you can see it for yourself. The only inf
 
 ### Can you uniquely identify me if I dislike?
 
-Yes. When you dislike a video, we create a randomly generated unique ID for you that is not tied to your Google account. This is done to prevent botting. But there is no way to tie this random Id to you or your personal youtube account.
+Yes. When you dislike a video, we create a randomly generated unique ID for you that is not tied to your Google account. This is done to prevent botting. But there is no way to tie this random Id to you or your personal YouTube account.
 
 ### What information do you have, exactly?
 
@@ -18,7 +18,7 @@ The backend keeps unhashed IP addresses in volatile memory (RAM) only. These add
 
 ### I heard some discussion over OAuth, and access to my YouTube account!
 
-This feature will be optional, and very much opt-in. If you are a YouTube creator, and would like to share your dislike stats with us, you can. The way [OAuth](https://en.wikipedia.org/wiki/OAuth#:~:text=but%20without%20giving%20them%20the%20passwords.) was structured, is it's actually very secure. You can revoke access to your account at any time, and can give very specific permissions to us. We will not ask for any permissions that aren't required. We'll only ask for permissions to view your video stats. 
+This feature will be optional, and very much opt-in. If you are a YouTube creator, and would like to share your dislike stats with us, you can. The way [OAuth](https://en.wikipedia.org/wiki/OAuth#:~:text=but%20without%20giving%20them%20the%20passwords.) was structured, it's actually very secure. You can revoke access to your account at any time, and can give very specific permissions to us. We will not ask for any permissions that aren't required. We'll only ask for permissions to view your video stats. 
 
 ### How can I trust this dislike count?
 

+ 81 - 6
Extensions/UserScript/Return Youtube Dislike.user.js

@@ -33,8 +33,6 @@ const extConfig = {
   colorTheme: "classic", // [classic*, accessible, neon] Color theme (red/green, blue/yellow, pink/cyan)
   numberDisplayFormat: "compactShort", // [compactShort*, compactLong, standard] Number format (For non-English locale users, you may be able to improve appearance with a different option. Please file a feature request if your locale is not covered)
   numberDisplayRoundDown: true, // [true*, false] Round down numbers (Show rounded down numbers)
-  
-  // READING THIS ^ INFO IS NOT IMPLEMENTED HERE (LOOK AT PULL REQUEST #540)
   tooltipPercentageMode: "none", // [none*, dash_like, dash_dislike, both, only_like, only_dislike] Mode of showing percentage in like/dislike bar tooltip.
 // END USER OPTIONS
 };
@@ -248,6 +246,13 @@ function createRateBar(likes, dislikes) {
 
 
   if (!rateBar && !isMobile) {
+    let colorLikeStyle = "";
+    let colorDislikeStyle = "";
+    if (extConfig.coloredBar) {
+      colorLikeStyle = "; background-color: " + getColorFromTheme(true);
+      colorDislikeStyle = "; background-color: " + getColorFromTheme(false);
+    }
+    
     document.getElementById("menu-container").insertAdjacentHTML(
       "beforeend",
       `
@@ -255,11 +260,11 @@ function createRateBar(likes, dislikes) {
         <div class="ryd-tooltip-bar-container">
            <div
               id="return-youtube-dislike-bar-container"
-              style="width: 100%; height: 2px;"
+              style="width: 100%; height: 2px;${colorDislikeStyle}"
               >
               <div
                  id="return-youtube-dislike-bar"
-                 style="width: ${widthPercent}%; height: 100%"
+                 style="width: ${widthPercent}%; height: 100%${colorDislikeStyle}"
                  ></div>
            </div>
         </div>
@@ -279,6 +284,13 @@ function createRateBar(likes, dislikes) {
     document.querySelector(
       "#ryd-dislike-tooltip > #tooltip"
     ).innerHTML = tooltipInnerHTML;
+    
+    if (extConfig.coloredBar) {
+      document.getElementById("return-youtube-dislike-bar-container").style.backgroundColor =
+        getColorFromTheme(false);
+      document.getElementById("return-youtube-dislike-bar").style.backgroundColor =
+        getColorFromTheme(true);
+    }
   }
 }
 
@@ -297,6 +309,10 @@ function setState() {
         dislikesvalue = dislikes;
         setDislikes(numberFormat(dislikes));
         createRateBar(likes, dislikes);
+        if (extConfig.coloredThumbs === true) {
+          getLikeButton().style.color = getColorFromTheme(true);
+          getDislikeButton().style.color = getColorFromTheme(false);
+        }
       }
     });
   });
@@ -390,14 +406,73 @@ function numberFormat(numberState) {
         ?.getAttribute("href")
     )?.searchParams?.get("locale");
   } catch {}
+
+  let numberDisplay;
+  if (extConfig.numberDisplayRoundDown === false) {
+    numberDisplay = numberState;
+  } else {
+    numberDisplay = roundDown(numberState);
+  }
+  return getNumberFormatter(extConfig.numberDisplayFormat).format(
+    numberDisplay
+  );
+}
+
+function getNumberFormatter(optionSelect) {
+  let formatterNotation;
+  let formatterCompactDisplay;
+
+  switch (optionSelect) {
+    case "compactLong":
+      formatterNotation = "compact";
+      formatterCompactDisplay = "long";
+      break;
+    case "standard":
+      formatterNotation = "standard";
+      formatterCompactDisplay = "short";
+      break;
+    case "compactShort":
+    default:
+      formatterNotation = "compact";
+      formatterCompactDisplay = "short";
+  }
+
   const formatter = Intl.NumberFormat(
     document.documentElement.lang || userLocales || navigator.language,
     {
-      notation: "compact",
+      notation: formatterNotation,
+      compactDisplay: formatterCompactDisplay,
     }
   );
+  return formatter;
+}
 
-  return formatter.format(roundDown(numberState));
+function getColorFromTheme(voteIsLike) {
+  let colorString;
+  switch (extConfig.colorTheme) {
+    case "accessible":
+      if (voteIsLike === true) {
+        colorString = "dodgerblue";
+      } else {
+        colorString = "gold";
+      }
+      break;
+    case "neon":
+      if (voteIsLike === true) {
+        colorString = "aqua";
+      } else {
+        colorString = "magenta";
+      }
+      break;
+    case "classic":
+    default:
+      if (voteIsLike === true) {
+        colorString = "lime";
+      } else {
+        colorString = "red";
+      }
+  }
+  return colorString;
 }
 
 function setEventListeners(evt) {

+ 50 - 0
Extensions/combined/_locales/de/messages.json

@@ -0,0 +1,50 @@
+{
+  "extensionName": {
+      "message": "Return YouTube Dislike"
+  },
+  "extensionDesc": {
+      "message": "Macht Dislikes wieder sichtbar"
+  },
+  "textDeveloper": {
+      "message": "von Dmitry Selivanov & Community"
+  },
+  "linkWebsite": {
+      "message": "Website"
+  },
+  "linkFAQ": {
+      "message": "FAQ"
+  },
+  "linkDonate": {
+      "message": "Spenden"
+  },
+  "linkHelp": {
+      "message": "Hilfe"
+  },
+  "legendSettings": {
+      "message": "Einstellungen"
+  },
+  "textSettings": {
+      "message": "Deaktiviere Like/Dislike-Übermittlung"
+  },
+  "textSettingsHover": {
+      "message": "Stoppt deine Likes und Dislikes zu zählen."
+  },
+  "textUpdate": {
+      "message": "aktualisieren auf"
+  },
+  "version30installed": {
+      "message": "Version 4.0.0.0 installiert"
+  },
+  "whatsnew": {
+      "message": "Was ist neu"
+  },
+  "shortsSupport": {
+      "message": "YouTube Shorts Unterstützung"
+  },
+  "customColors": {
+      "message": "Benutzerdefinierte Farben für Dislike-Leiste und Buttons"
+  },
+  "customNumberFormats": {
+      "message": "Benutzerdefinierte Zahlenformate"
+  }
+}

+ 6 - 0
Extensions/combined/_locales/en/messages.json

@@ -26,9 +26,15 @@
     "textSettings": {
         "message": "Disable like/dislike submission"
     },
+    "textLikesDisabled": {
+        "message": "disabled by owner"
+    },
     "textSettingsHover": {
         "message": "Stops counting your likes and dislikes."
     },
+    "textTempUnavailable": {
+        "message": "temporarily unavailable"
+    },
     "textUpdate": {
         "message": "update to"
     },

+ 6 - 0
Extensions/combined/_locales/fr/messages.json

@@ -23,12 +23,18 @@
     "legendSettings": {
         "message": "Paramètres"
     },
+    "textLikesDisabled": {
+        "message": "Désactivé par le créateur"
+    },
     "textSettings": {
         "message": "Désactiver l'envoi des likes/dislikes"
     },
     "textSettingsHover": {
         "message": "Arrête de compter les likes et les dislikes mis sur les vidéos."
     },
+    "textTempUnavailable": {
+        "message": "temporairement indisponible"
+    },
     "textUpdate": {
         "message": "mettre à jour vers"
     }

+ 50 - 0
Extensions/combined/_locales/gr/manifest.json

@@ -0,0 +1,50 @@
+{
+    "extensionName": {
+        "message": "Επιστροφή του YouTube Dislike"
+    },
+    "extensionDesc": {
+        "message": "Επιστρέφει τα dislikes"
+    },
+    "textDeveloper": {
+        "message": "από τον Dmitry Selivanov & την κοινότητα"
+    },
+    "linkWebsite": {
+        "message": "Ιστοσελίδα"
+    },
+    "linkFAQ": {
+        "message": "Γρήγορες Ερωτήσιες & Απαντήσεις"
+    },
+    "linkDonate": {
+        "message": "Στηρίξτε"
+    },
+    "linkHelp": {
+        "message": "Βοήθεια"
+    },
+    "legendSettings": {
+        "message": "Ρυθμίσεις"
+    },
+    "textSettings": {
+        "message": "Διακοπή υποβολής like/dislike"
+    },
+    "textSettingsHover": {
+        "message": "Σταματάει να μετράει τα likes & dislikes που κάνεις."
+    },
+    "textUpdate": {
+        "message": "ενημέρωση σε"
+    },
+    "version30installed": {
+        "message": "Εκδοση 4.0.0.0 εγκαταστάθηκε"
+    },
+    "whatsnew": {
+        "message": "Τι είναι νέο;"
+    },
+    "shortsSupport": {
+        "message": "Υποστήριξη για YouTube Shorts"
+    },
+    "customColors": {
+        "message": "Προσαρμοζόμενα χρώματα για τα κουμπιά και την μπάρα dislike"
+    },
+    "customNumberFormats": {
+        "message": "Προσαρμοζόμενη μορφή αριθμών."
+    }
+}

+ 50 - 0
Extensions/combined/_locales/it/messages.json

@@ -0,0 +1,50 @@
+{
+    "extensionName": {
+        "message": "Return YouTube Dislike"
+    },
+    "extensionDesc": {
+        "message": "Ripristina la possibilità di vedere i dislikes"
+    },
+    "textDeveloper": {
+        "message": "di Dmitry Selivanov e la Community"
+    },
+    "linkWebsite": {
+        "message": "Sito web"
+    },
+    "linkFAQ": {
+        "message": "Domande frequenti"
+    },
+    "linkDonate": {
+        "message": "Fai una donazione"
+    },
+    "linkHelp": {
+        "message": "Aiuto"
+    },
+    "legendSettings": {
+        "message": "Impostazioni"
+    },
+    "textSettings": {
+        "message": "Disabilita l'invio di like/dislike"
+    },
+    "textSettingsHover": {
+        "message": "Interrompe il conteggio dei tuoi likes e dislikes."
+    },
+    "textUpdate": {
+        "message": "aggiorna a"
+    },
+    "version30installed": {
+        "message": "Versione 4.0.0.0 installata"
+    },
+    "whatsnew": {
+        "message": "Cosa c'è di nuovo"
+    },
+    "shortsSupport": {
+        "message": "Supporto per YouTube Shorts"
+    },
+    "customColors": {
+        "message": "Colori personalizzati per la barra dei dislike e i bottoni"
+    },
+    "customNumberFormats": {
+        "message": "Formati numerici personalizzati"
+    }
+}

+ 47 - 47
Extensions/combined/popup.html

@@ -12,54 +12,54 @@
   />
 </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"
+  <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 style="margin-bottom: 0.75rem" title="__MSG_extensionName__">
+      __MSG_extensionName__
+    </h1>
+    <p style="color: var(--lightGrey)" title="__MSG_textDeveloper__">
+      __MSG_textDeveloper__
+    </p>
+  
+    <button id="link_website" title="__MSG_linkWebsite__">
+      __MSG_linkWebsite__
+    </button>
+    <button style="margin-top: 0.3em; background: #ff0000" id="link_donate" title="__MSG_linkDonate__">
+      __MSG_linkDonate__
+    </button>
+    <button id="link_discord">Discord</button>
+    <br/>
+    <button style="margin-top: 0.3rem" id="link_faq" title="__MSG_linkFAQ__">
+      __MSG_linkFAQ__
+    </button>
+    <button id="link_github">GitHub</button>
+    <button style="margin-top: 0.3em" id="link_help" title="__MSG_linkHelp__">
+      __MSG_linkHelp__
+    </button>
+    <br>
+    <button style="margin-top: 0.3em" id="link_changelog" title="__MSG_linkChangelog__">
+      Change Log
+    </button>
+  
+    <br/>
+    <br/>
+    <p style="display: none">API Status: <b id="status"></b></p>
+    <img
+      id="server-status"
+      style="display: none; width: 0.75rem; height: 0.75rem"
+      src="./icons/server.svg"
+      alt=""
     />
-    <path d="m8 12.5 5.1-2.9L8 6.7v5.8z" fill="#fff"/>
-  </svg>
-  <h1 style="margin-bottom: 0.75rem" title="__MSG_extensionName__">
-    __MSG_extensionName__
-  </h1>
-  <p style="color: var(--lightGrey)" title="__MSG_textDeveloper__">
-    __MSG_textDeveloper__
-  </p>
-
-  <button id="link_website" title="__MSG_linkWebsite__">
-    __MSG_linkWebsite__
-  </button>
-  <button
-    style="margin-top: 0.3em; background: #ff0000"
-    id="link_donate"
-    title="__MSG_linkDonate__"
-  >
-    __MSG_linkDonate__
-  </button>
-  <button id="link_discord">Discord</button>
-  <br/>
-  <button style="margin-top: 0.3rem" id="link_faq" title="__MSG_linkFAQ__">
-    __MSG_linkFAQ__
-  </button>
-  <button id="link_github">GitHub</button>
-  <button style="margin-top: 0.3em" id="link_help" title="__MSG_linkHelp__">
-    __MSG_linkHelp__
-  </button>
-
-  <br/>
-  <br/>
-  <p style="display: none">API Status: <b id="status"></b></p>
-  <img
-    id="server-status"
-    style="display: none; width: 0.75rem; height: 0.75rem"
-    src="./icons/server.svg"
-    alt=""
-  />
-
-  <br/>
-  <br/>
-</center>
+  
+    <br/>
+    <br/>
+  </center>
 
 <!-- top-right -->
 <button id="advancedToggle">

+ 2 - 0
Extensions/combined/popup.js

@@ -23,6 +23,7 @@ const config = {
     donate: "https://returnyoutubedislike.com/donate",
     faq: "https://returnyoutubedislike.com/faq",
     help: "https://returnyoutubedislike.com/help",
+    changelog: "/changelog/3/changelog_3.0.html"
   },
 };
 
@@ -53,6 +54,7 @@ createLink(config.links.discord, "link_discord");
 createLink(config.links.faq, "link_faq");
 createLink(config.links.donate, "link_donate");
 createLink(config.links.help, "link_help");
+createLink(config.links.changelog, "link_changelog");
 
 function createLink(url, id) {
   document.getElementById(id).addEventListener("click", () => {

+ 10 - 3
Extensions/combined/ryd.background.js

@@ -74,9 +74,16 @@ api.runtime.onMessage.addListener((request, sender, sendResponse) => {
   }
 });
 
-api.runtime.onInstalled.addListener(() => {
-  api.tabs.create({url: api.runtime.getURL("/changelog/3/changelog_3.0.html")});
-})
+  api.storage.sync.get(['lastShowChangelogVersion'], (details) => {
+    if (extConfig.showUpdatePopup === true &&
+      details.lastShowChangelogVersion !== chrome.runtime.getManifest().version
+      ) {
+      // keep it inside get to avoid race condition
+      api.storage.sync.set({'lastShowChangelogVersion ': chrome.runtime.getManifest().version});
+      // wait until async get runs & don't steal tab focus
+      api.tabs.create({url: api.runtime.getURL("/changelog/3/changelog_3.0.html"), active: false});
+    }
+  });
 
 async function sendVote(videoId, vote) {
   api.storage.sync.get(null, async (storageResult) => {

+ 6 - 3
Extensions/combined/src/bar.js

@@ -1,8 +1,9 @@
 import { getButtons } from "./buttons";
-import { likesDisabledState, extConfig, isMobile } from "./state";
+import { extConfig, isMobile, isLikesDisabled } from "./state";
 import { cLog, getColorFromTheme } from "./utils";
+
 function createRateBar(likes, dislikes) {
-  if (!likesDisabledState) {
+  if (!isLikesDisabled()) {
     let rateBar = document.getElementById("ryd-bar-container");
 
     const widthPx =
@@ -88,7 +89,9 @@ function createRateBar(likes, dislikes) {
   } else {
     cLog("removing bar");
     let ratebar = document.getElementById("ryd-bar-container");
-    ratebar.parentNode.removeChild(ratebar);
+    if(ratebar) {
+      ratebar.parentNode.removeChild(ratebar);
+    }
   }
 }
 

+ 29 - 14
Extensions/combined/src/state.js

@@ -8,6 +8,7 @@ import {
   getColorFromTheme,
 } from "./utils";
 import { sendVideoIds } from "./events";
+import { localize } from "./utils";
 
 //TODO: Do not duplicate here and in ryd.background.js
 const apiUrl = "https://returnyoutubedislikeapi.com";
@@ -15,8 +16,6 @@ const LIKED_STATE = "LIKED_STATE";
 const DISLIKED_STATE = "DISLIKED_STATE";
 const NEUTRAL_STATE = "NEUTRAL_STATE";
 
-const DISLIKES_DISABLED_TEXT = "DISLIKES DISABLED";
-
 let extConfig = {
   disableVoteSubmission: false,
   coloredThumbs: false,
@@ -34,8 +33,6 @@ let storedData = {
   previousState: NEUTRAL_STATE,
 };
 
-let likesDisabledState = true;
-
 function isMobile() {
   return location.hostname == "m.youtube.com";
 }
@@ -44,6 +41,16 @@ function isShorts() {
   return location.pathname.startsWith("/shorts");
 }
 
+function isLikesDisabled() {
+  // return true if the like button's text doesn't contain any number
+  if (isMobile()) {
+    return /^\D*$/.test(
+      getButtons().children[0].querySelector(".button-renderer-text").innerText
+    );
+  }
+  return /^\D*$/.test(getButtons().children[0].querySelector("#text").innerText);
+}
+
 function isVideoLiked() {
   if (isMobile()) {
     return (
@@ -80,7 +87,7 @@ function setLikes(likesCount) {
 }
 
 function setDislikes(dislikesCount) {
-  if (!likesDisabledState) {
+  if (!isLikesDisabled()) {
     if (isMobile()) {
       getButtons().children[1].querySelector(
         ".button-renderer-text"
@@ -93,11 +100,12 @@ function setDislikes(dislikesCount) {
     if (isMobile()) {
       getButtons().children[1].querySelector(
         ".button-renderer-text"
-      ).innerText = DISLIKES_DISABLED_TEXT;
+      ).innerText = localize("TextLikesDisabled");
       return;
     }
-    getButtons().children[1].querySelector("#text").innerText =
-      DISLIKES_DISABLED_TEXT;
+    getButtons().children[1].querySelector("#text").innerText = localize(
+      "TextLikesDisabled"
+    );
   }
 }
 
@@ -126,6 +134,13 @@ function processResponse(response, storedData) {
   }
 }
 
+// Tells the user if the API is down
+function displayError(error) {
+  getButtons().children[1].querySelector("#text").innerText = localize(
+    "textTempUnavailable"
+  );
+}
+
 async function setState(storedData) {
   storedData.previousState = isVideoDisliked()
     ? DISLIKED_STATE
@@ -146,14 +161,14 @@ async function setState(storedData) {
       },
     }
   )
+    .then((response) => {
+      if (!response.ok) displayError(response.error);
+      return response;
+    })
     .then((response) => response.json())
-    .catch();
+    .catch(displayError);
   cLog("response from api:");
   cLog(JSON.stringify(response));
-  likesDisabledState =
-    numberFormat(response.dislikes) == 0 &&
-    numberFormat(response.likes) == 0 &&
-    numberFormat(response.viewCount) == 0;
   if (response !== undefined && !("traceId" in response) && !statsSet) {
     processResponse(response, storedData);
   }
@@ -274,5 +289,5 @@ export {
   extConfig,
   initExtConfig,
   storedData,
-  likesDisabledState,
+  isLikesDisabled
 };

+ 5 - 0
Extensions/combined/src/utils.js

@@ -29,6 +29,10 @@ function numberFormat(numberState) {
   );
 }
 
+function localize(localeString) {
+  return chrome.i18n.getMessage(localeString);
+}
+
 function getNumberFormatter(optionSelect) {
   let formatterNotation;
   let formatterCompactDisplay;
@@ -151,4 +155,5 @@ export {
   isVideoLoaded,
   cLog,
   getColorFromTheme,
+  localize,
 };

+ 1 - 3
README.md

@@ -33,12 +33,10 @@ With the removal of dislike stats from the YouTube API, our backend switched to
 
 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:
 
-
 - **Attribution**: This project should be clearly attributed with a link to [returnyoutubedislike.com](https://returnyoutubedislike.com/).
 - **Rate Limiting**: 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.
 
@@ -79,7 +77,7 @@ You can view all documentation on our website.
 
 ## Contributing
 
-Please read the [contribution guide.](https://github.com/Anarios/return-youtube-dislike/blob/main/CONTRIBUTING.md)
+Please read the [contribution guide](https://github.com/Anarios/return-youtube-dislike/blob/main/CONTRIBUTING.md).
 
 ## Support this project!
 

+ 0 - 1
Website/README.md

@@ -58,7 +58,6 @@ Layouts are a great help when you want to change the look and feel of your Nuxt
 
 More information about the usage of this directory in [the documentation](https://nuxtjs.org/docs/2.x/directory-structure/layouts).
 
-
 ### `pages`
 
 This directory contains your application views and routes. Nuxt will read all the `*.vue` files inside this directory and setup Vue Router automatically.

+ 6 - 1
Website/pages/faq.vue

@@ -36,13 +36,18 @@ export default {
       {
         question: "Where does the extension get its data?",
         answer:
-          "A combination of archived data from before the offical YouTube dislike API shut down, and extrapolated extension user behavior.",
+          "A combination of archived data from before the official YouTube dislike API shut down, and extrapolated extension user behavior.",
       },
       {
         question: "Why isn't the dislike count updating?",
         answer:
           "Right now video dislikes are cached and they aren't updated very frequently. It varies depending on a video's popularity but can take anywhere between a few hours and a few days to update.",
       },
+      {
+        question: "Why is the dislike count on my videos inaccurate?",
+        answer:
+          "Extrapolated data tends to get better with the increase in diversity and the quantity of voters. \nTo ensure and increase the accuracy of the extrapolated vote data for your videos, you can encourage your viewers to use this extension (or any app that submits votes to returnyoutubedislikeapi.com) ",
+      },
       {
         question: "How does this work?",
         answer:

+ 1 - 1
Website/pages/index.vue

@@ -123,7 +123,7 @@ export default {
     };
   },
   mounted() {
-    const YOUTUBE_REGEX = /(?:http:|https:)*?\/\/(?:www\.|)(?:youtube\.com|m\.youtube\.com|youtu\.|youtube-nocookie\.com).*(?:v=|v%3D|v\/|(?:a|p)\/(?:a|u)\/\d.*\/|watch\?|vi(?:=|\/)|\/embed\/|oembed\?|be\/|e\/)([^&?%#\/\n]*)/;
+    const YOUTUBE_REGEX = /(?:http:|https:)*?\/\/(?:www\.|)(?:youtube\.com|m\.youtube\.com|youtu\.|youtube-nocookie\.com).*(?:v=|v%3D|v\/|(?:a|p)\/(?:a|u)\/\d.*\/|watch\?|vi(?:=|\/)|\/embed\/|oembed\?|be\/|e\/)([^&?%#/\n]*)/;
     let lastVideoId = "";
     window.oninput = (e) => {
       const videoId = (e.target.value.match(YOUTUBE_REGEX) || {})[1] || e.target.value;

+ 2 - 2
extension-description-store.txt

@@ -1,6 +1,6 @@
 Return YouTube Dislike restores the ability to see dislikes on YouTube.
 
-If it doesn't work: open extensions tab (chrome://extensions/) disable this extension and enable it again. This is a bug in chromium that breaks the extension in some cases. This should fix most of the problems. Hopefully chromium team will fix this soon
+If it doesn't work: open extensions tab (chrome://extensions/) disable this extension and enable it again. This is a bug in chromium that breaks the extension in some cases. This should fix most of the problems. Hopefully the chromium team will fix this soon.
 
 Starting December 13th 2021, YouTube removed the ability to see dislikes from their API.
 This extension aims to restore power to users by using a combination of archived like and dislike data, as well as the likes and dislikes made by extension users to show the most accurate ratings.
@@ -9,7 +9,7 @@ Currently has 200+ million videos likes/dislikes data stored before December 13t
 
 Actively growing and keeping up to date with uploads after December 13th, 2021
 
-The more users that use the extension, the more accurate it will be
+The more users that use the extension, the more accurate it will be.
 
 Unpopular videos uploaded after December 13th, 2021 may have less accurate data shown than more popular videos.