Replace youtube redirect links

Replace youtube redirect links with direct links and extend links text to its full length

当前为 2023-03-07 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name Replace youtube redirect links
  3. // @description Replace youtube redirect links with direct links and extend links text to its full length
  4. // @author MK
  5. // @namespace max44
  6. // @homepage https://greasyfork.org/en/users/309172-max44
  7. // @match *://*.youtube.com/*
  8. // @match *://*.youtu.be/*
  9. // @icon https://cdn.icon-icons.com/icons2/1488/PNG/512/5295-youtube-i_102568.png
  10. // @version 1.3
  11. // @license MIT
  12. // @require https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js
  13. // @run-at document-idle
  14. // ==/UserScript==
  15.  
  16. (function() {
  17. 'use strict';
  18.  
  19. const rootCallback = function (mutationsList, observer) {
  20. document.querySelectorAll("a[href*='/redirect?']").forEach(replaceRedirect);
  21. document.querySelectorAll("a:not([expanded-by-script])").forEach(showFullLink);
  22. document.querySelectorAll("div#below span.yt-core-attributed-string > span > span.yt-core-attributed-string--highlight-text-decorator:not([expanded-by-script]) > a[href*='/watch?']").forEach(showFullVideoName);
  23. document.querySelectorAll("div#below span.yt-core-attributed-string > span > span.yt-core-attributed-string--highlight-text-decorator:not([expanded-by-script]) > a[href*='/shorts/']").forEach(showFullVideoName);
  24. }
  25.  
  26. const rootNode = document.querySelector("body");
  27. if (rootNode != null) {
  28. const rootObserver = new MutationObserver(rootCallback);
  29. rootObserver.observe(rootNode, {childList: true, subtree: true});
  30. }
  31.  
  32. function replaceRedirect(link) { //Remove redirection
  33. link.href = decodeURIComponent(link.href.replace (/^.*\?(.*&)q=([^&]+)(&.*)?$/, '$2'));
  34. const wrpLink = link.wrappedJSObject || link;
  35. if (wrpLink.data && wrpLink.data.urlEndpoint) {
  36. wrpLink.data.urlEndpoint.url = link.href;
  37. }
  38. showFullLink(link);
  39. }
  40.  
  41. function showFullLink(link) { //Expand link to full length
  42. if (link.innerText.substring(0, 20) == link.href.substring(0, 20) && link.innerText.substring(link.innerText.length-3, link.innerText.length) === "...") {
  43. link.innerText = link.href;
  44. link.setAttribute("expanded-by-script", "true");
  45. } else link.setAttribute("expanded-by-script", "false");
  46. }
  47.  
  48. function showFullVideoName(link) { //Expand short video name to full one, taken from previous text
  49. link.parentElement.setAttribute("expanded-by-script", "false");
  50.  
  51. const rangeBefore = document.createRange(); //Create a range from the start of the parent till the target element
  52. rangeBefore.setStart(link.parentElement.parentElement.parentElement, 0);
  53. rangeBefore.setEndBefore(link.parentElement.parentElement);
  54. var strFullName = rangeBefore.toString();
  55. //console.log("strFullName long: " + strFullName);
  56. strFullName = strFullName.replace(/.*[\n](?!$)/g, ""); //Remove all text except the last line
  57. //console.log("strFullName short: " + strFullName);
  58.  
  59. if (strFullName.length > 0) {
  60. var strHTML = link.parentElement.parentElement.parentElement.outerHTML;
  61. strHTML = strHTML.replace(strFullName, ""); //Remove full video name from text
  62. strHTML = strHTML.replace(/yt-core-image--content-mode-scale-to-fill"><\/span>/gi, "yt-core-image--content-mode-scale-to-fill yt-core-image--loaded\" src=\"https://www.gstatic.com/youtube/img/watch/yt_favicon.png\"></span>"); //Add YT icon if missed
  63. link.parentElement.parentElement.parentElement.outerHTML = strHTML;
  64.  
  65. strFullName = strFullName.replace(/[\n]/g, ""); //Remove \n
  66. strFullName = strFullName.replace(/[ ]+$/g, ""); //Remove trailing spaces
  67. strFullName = strFullName.replace(/[ ]*:+$/g, ""); //Remove trailing semicolon and spaces
  68.  
  69. var newLink = document.querySelector("div#below span.yt-core-attributed-string > span > span.yt-core-attributed-string--highlight-text-decorator[expanded-by-script='false'] > a"); //New query, because previous setting of outerHTML rebuilded this node in DOM
  70. if (newLink != null) {
  71. newLink.parentElement.setAttribute("expanded-by-script", "true");
  72.  
  73. var strHTML2 = newLink.parentElement.outerHTML;
  74. //console.log("strHTML: " + strHTML2);
  75. strHTML2 = strHTML2.replace(/<\/span>&nbsp;•&nbsp;.*&nbsp;&nbsp;<\/a><\/span>/gi, "</span>&nbsp;•&nbsp;" + strFullName + "&nbsp;&nbsp;</a></span>"); //Add full video name to link
  76. //strHTML2 = strHTML2.replace(/yt-core-image--content-mode-scale-to-fill"><\/span>/gi, "yt-core-image--content-mode-scale-to-fill yt-core-image--loaded\" src=\"https://www.gstatic.com/youtube/img/watch/yt_favicon.png\"></span>"); //Add YT icon if missed
  77. newLink.parentElement.outerHTML = strHTML2;
  78. }
  79. }
  80. }
  81. })();