return-youtube-dislike.script.js 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280
  1. let storedData = {
  2. dislikes: 0
  3. };
  4. function cLog(message, writer) {
  5. message = `[return youtube dislike]: ${message}`;
  6. if (writer) {
  7. writer(message);
  8. } else {
  9. console.log(message);
  10. }
  11. }
  12. function getButtons() {
  13. //--- If Menu Element Is Displayed: ---//
  14. if (document.getElementById("menu-container").offsetParent === null) {
  15. return document.querySelector("ytd-menu-renderer.ytd-watch-metadata > div");
  16. //--- If Menu Element Isnt Displayed: ---//
  17. } else {
  18. return document
  19. .getElementById("menu-container")
  20. ?.querySelector("#top-level-buttons-computed");
  21. }
  22. }
  23. function getLikeButton() {
  24. return getButtons().children[0];
  25. }
  26. function getDislikeButton() {
  27. return getButtons().children[1];
  28. }
  29. function isVideoLiked() {
  30. return getLikeButton().classList.contains("style-default-active");
  31. }
  32. function isVideoDisliked() {
  33. return getDislikeButton().classList.contains("style-default-active");
  34. }
  35. function isVideoNotLiked() {
  36. return getLikeButton().classList.contains("style-text");
  37. }
  38. function isVideoNotDisliked() {
  39. return getDislikeButton().classList.contains("style-text");
  40. }
  41. function getState() {
  42. if (isVideoLiked()) {
  43. return "liked";
  44. }
  45. if (isVideoDisliked()) {
  46. return "disliked";
  47. }
  48. return "neutral";
  49. }
  50. //--- Sets The Likes And Dislikes Values ---//
  51. function setLikes(likesCount) {
  52. getButtons().children[0].querySelector("#text").innerText = likesCount;
  53. }
  54. function setDislikes(dislikesCount) {
  55. getButtons().children[1].querySelector("#text").innerText = dislikesCount;
  56. }
  57. function setState() {
  58. let statsSet = false;
  59. browser.runtime.sendMessage(
  60. {
  61. message: "fetch_from_youtube",
  62. videoId: getVideoId(window.location.href),
  63. },
  64. function (response) {
  65. if (response != undefined) {
  66. cLog("response from youtube:");
  67. cLog(JSON.stringify(response));
  68. try {
  69. if (response.likes || response.dislikes) {
  70. const formattedDislike = numberFormat(response.dislikes);
  71. setDislikes(formattedDislike);
  72. storedData.dislikes = parseInt(response.dislikes);
  73. createRateBar(response.likes, response.dislikes);
  74. statsSet = true;
  75. }
  76. } catch (e) {
  77. statsSet = false;
  78. }
  79. }
  80. }
  81. );
  82. browser.runtime.sendMessage(
  83. {
  84. message: "set_state",
  85. videoId: getVideoId(window.location.href),
  86. state: getState(),
  87. },
  88. function (response) {
  89. cLog("response from api:");
  90. cLog(JSON.stringify(response));
  91. if (response != undefined && !statsSet) {
  92. const formattedDislike = numberFormat(response.dislikes);
  93. storedData.dislikes = response.dislikes;
  94. // setLikes(response.likes);
  95. console.log(response);
  96. setDislikes(formattedDislike);
  97. createRateBar(response.likes, response.dislikes);
  98. } else {
  99. }
  100. }
  101. );
  102. }
  103. function likeClicked() {
  104. console.log("Dislike State:",getState());
  105. // setState();
  106. }
  107. function dislikeClicked() {
  108. let state = getState();
  109. console.log("Dislike State:",state);
  110. if (state == 'disliked') {
  111. setDislikes(numberFormat(storedData.dislikes + 1))
  112. } else if (state == 'neutral') {
  113. setDislikes(numberFormat(storedData.dislikes))
  114. }
  115. // setState();
  116. }
  117. function setInitalState() {
  118. setState();
  119. // setTimeout(() => sendVideoIds(), 1500);
  120. }
  121. function getVideoId(url) {
  122. const urlObject = new URL(url);
  123. const videoId = urlObject.searchParams.get("v");
  124. return videoId;
  125. }
  126. function isVideoLoaded() {
  127. const videoId = getVideoId(window.location.href);
  128. return (
  129. document.querySelector(`ytd-watch-flexy[video-id='${videoId}']`) !== null
  130. );
  131. }
  132. function roundDown(num) {
  133. if (num < 1000) return num;
  134. const int = Math.floor(Math.log10(num) - 2);
  135. const decimal = int + (int % 3 ? 1 : 0);
  136. const value = Math.floor(num / 10 ** decimal);
  137. return value * (10 ** decimal);
  138. }
  139. function numberFormat(numberState) {
  140. const userLocales = navigator.language;
  141. const formatter = Intl.NumberFormat(userLocales, {
  142. notation: 'compact',
  143. minimumFractionDigits: 1,
  144. maximumFractionDigits: 1
  145. });
  146. return formatter.format(roundDown(numberState)).replace(/\.0|,0/, '');
  147. }
  148. function setEventListeners(evt) {
  149. function checkForJS_Finish() {
  150. if (getButtons()?.offsetParent && isVideoLoaded()) {
  151. clearInterval(jsInitChecktimer);
  152. const buttons = getButtons();
  153. if (!window.returnDislikeButtonlistenersSet) {
  154. buttons.children[0].addEventListener("click", likeClicked);
  155. buttons.children[1].addEventListener("click", dislikeClicked);
  156. let lastKnownScrollPosition = 0;
  157. let ticking = false;
  158. // document.addEventListener('scroll', function(e) {
  159. // lastKnownScrollPosition = window.scrollY;
  160. //
  161. // if (!ticking) {
  162. // window.requestAnimationFrame(function() {
  163. // // sendVideoIds();
  164. // ticking = false;
  165. // });
  166. //
  167. // ticking = true;
  168. // }
  169. // });
  170. window.returnDislikeButtonlistenersSet = true;
  171. }
  172. setInitalState();
  173. }
  174. }
  175. if (window.location.href.indexOf("watch?") >= 0) {
  176. var jsInitChecktimer = setInterval(checkForJS_Finish, 111);
  177. }
  178. }
  179. function createRateBar(likes, dislikes) {
  180. var rateBar = document.getElementById("return-youtube-dislike-bar-container");
  181. const widthPx =
  182. getButtons().children[0].clientWidth +
  183. getButtons().children[1].clientWidth +
  184. 8;
  185. const widthPercent =
  186. likes + dislikes > 0 ? (likes / (likes + dislikes)) * 100 : 50;
  187. if (!rateBar) {
  188. (
  189. document.querySelector("#actions-inner") ||
  190. document.getElementById("menu-container")
  191. ).insertAdjacentHTML(
  192. "beforeend",
  193. `
  194. <div class="ryd-tooltip" style="width: ${widthPx}px">
  195. <div class="ryd-tooltip-bar-container">
  196. <div
  197. id="return-youtube-dislike-bar-container"
  198. style="width: 100%; height: 2px;"
  199. >
  200. <div
  201. id="return-youtube-dislike-bar"
  202. style="width: ${widthPercent}%; height: 100%"
  203. ></div>
  204. </div>
  205. </div>
  206. <tp-yt-paper-tooltip position="top" id="ryd-dislike-tooltip" class="style-scope ytd-sentiment-bar-renderer" role="tooltip" tabindex="-1">
  207. <div>
  208. <!--css-build:shady-->${likes.toLocaleString()}&nbsp;/&nbsp;${dislikes.toLocaleString()}
  209. </tp-yt-paper-tooltip>
  210. </div>
  211. `
  212. );
  213. } else {
  214. document.getElementById(
  215. "return-youtube-dislike-bar-container"
  216. ).style.width = widthPx + "px";
  217. document.getElementById("return-youtube-dislike-bar").style.width =
  218. widthPercent + "%";
  219. document.querySelector(
  220. "#ryd-dislike-tooltip > #tooltip"
  221. ).innerHTML = `${likes.toLocaleString()}&nbsp;/&nbsp;${dislikes.toLocaleString()}`;
  222. }
  223. }
  224. function sendVideoIds() {
  225. const ids = Array.from(
  226. document.getElementsByClassName(
  227. "yt-simple-endpoint ytd-compact-video-renderer"
  228. )
  229. )
  230. .concat(
  231. Array.from(
  232. document.getElementsByClassName("yt-simple-endpoint ytd-thumbnail")
  233. )
  234. )
  235. .filter((x) => x.href && x.href.indexOf("/watch?v=") > 0)
  236. .map((x) => getVideoId(x.href));
  237. browser.runtime.sendMessage({
  238. message: "send_links",
  239. videoIds: ids,
  240. });
  241. }
  242. setEventListeners();
  243. setTimeout(() => sendVideoIds(), 1500);