return-youtube-dislike.script.js 9.2 KB

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