Youtube - Fix channel links in sidebar recommendations

Fixes the channel links for the "Up next" and recommended videos below it on youtube.

2024-01-16 يوللانغان نەشرى. ئەڭ يېڭى نەشرىنى كۆرۈش.

  1. // ==UserScript==
  2. // @name Youtube - Fix channel links in sidebar recommendations
  3. // @namespace 1N07
  4. // @version 0.6
  5. // @description Fixes the channel links for the "Up next" and recommended videos below it on youtube.
  6. // @author 1N07
  7. // @license unlicense
  8. // @icon https://www.google.com/s2/favicons?domain=youtube.com
  9. // @match https://www.youtube.com/*
  10. // @require https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js
  11. // @grant GM_registerMenuCommand
  12. // @grant GM_unregisterMenuCommand
  13. // @grant GM_getValue
  14. // @grant GM_setValue
  15. // @grant GM_addStyle
  16. // ==/UserScript==
  17.  
  18. (function() {
  19. 'use strict';
  20.  
  21. var videoSectionOption;
  22. var videoSection = GM_getValue("videoSection", true);
  23. SetVidSecOption();
  24.  
  25. GM_addStyle(`
  26. ytd-compact-video-renderer .channel-link-blocker:hover ~ a #text.ytd-channel-name {
  27. text-decoration: underline;
  28. }
  29. .channel-link-blocker-parent
  30. {
  31. position: relative;
  32. }
  33. .channel-link-blocker
  34. {
  35. display: inline-block;
  36. position: absolute;
  37. width: 100%;
  38. height: 25px;
  39. background-color: rgba(255, 25, 25, 0);
  40. top: 32px;
  41. left: 0;
  42. z-index: 2019;
  43. }
  44. `);
  45.  
  46. setInterval(AddListeners, 200); //fairly stupid way to do this, but hey, it works so this is how I'm doing it for now... -> switch to mutationobserver?
  47.  
  48. function AddListeners() {
  49. // My big brain high IQ plan for preventing the video from opening, since seems whatever I do some click event is caught by youtube:
  50. // Adding invisible divs on top of channel links so I can handle the clicks however I want. :DD
  51. $(`ytd-compact-video-renderer .metadata.ytd-compact-video-renderer:not(.channel-link-blocker-parent) > a[href^='/watch'],
  52. ytd-compact-playlist-renderer .metadata.ytd-compact-playlist-renderer:not(.channel-link-blocker-parent) > a[href^='/watch']`
  53. ).each(function(){
  54. $(this).parent().addClass("channel-link-blocker-parent");
  55. $(this).parent().prepend(`<a class="channel-link-blocker" href="#"></a>`);
  56.  
  57. //no idea what the longBylineText.runs array can contain other than the object we want, so throwing a find method in there so that if there are other random objects in the array, we hopefully get the right one (also tons of optional chaining so that if something goes wrong we gracefully get falsy as the final value)
  58. let channelHandle = $(this).closest("ytd-compact-video-renderer")?.[0]?.polymerController?.data?.longBylineText?.runs?.find(el => el.navigationEndpoint?.browseEndpoint?.canonicalBaseUrl?.startsWith("/@"))?.navigationEndpoint.browseEndpoint.canonicalBaseUrl;
  59.  
  60. if(channelHandle?.length) {
  61. $(this).parent().find(".channel-link-blocker").prop("href", channelHandle + (videoSection ? "/videos" : ""));
  62. } else {
  63. console.log("Failed to get channel url");
  64. $(this).parent().find(".channel-link-blocker").on("click", (e) => {
  65. e.preventDefault();
  66. e.stopPropagation();
  67. alert("'Youtube - Fix channel links in sidebar recommendations' failed to get the channel link for this video for some reason. If this happens consistently, please report it at greasyfork.");
  68. });
  69. }
  70.  
  71. //blocker position adjustment
  72. $(this).parent().find(".channel-link-blocker").prop("style", "top: " + $(this).parent().find("a[href^='/watch']:first > h3").height() + "px;");
  73. //above adjustment appears to randomly fail. Attempted fix by delaying adjustment as perhaps the height hasn't been computed yet?
  74. //$(this) doesn't work from inside the seTimeout, so storing it here
  75. let storedThis = $(this);
  76. setTimeout(function() { storedThis.parent().find(".channel-link-blocker").prop("style", "top: " + storedThis.parent().find("a[href^='/watch']:first > h3").height() + "px;"); }, 1000);
  77. });
  78. }
  79.  
  80. function SetVidSecOption() {
  81. GM_unregisterMenuCommand(videoSectionOption);
  82. videoSectionOption = GM_registerMenuCommand("Fix channel links- videos section (" + (videoSection ? "yes" : "no") + ") -click to change-", function(){
  83. videoSection = !videoSection;
  84. GM_setValue("videoSection", videoSection);
  85. SetVidSecOption();
  86. });
  87. }
  88. })();