Youtube Recommendation Blacklist

Make your own blacklist, remove the pesky youtube channels you don't want to see from the recommendation list

  1. // ==UserScript==
  2. // @name Youtube Recommendation Blacklist
  3. // @namespace https://greasyfork.org/en/users/76021
  4. // @version 1.1
  5. // @description Make your own blacklist, remove the pesky youtube channels you don't want to see from the recommendation list
  6. // @author DaLimCodes
  7. // @icon https://www.youtube.com/yts/img/favicon_144-vflWmzoXw.png
  8. // @match https://www.youtube.com/watch?v=*
  9. // @require https://code.jquery.com/jquery-3.2.1.min.js
  10. // @grant GM_getValue
  11. // @grant GM_setValue
  12. // @grant GM_deleteValue
  13. // ==/UserScript==
  14.  
  15. var blacklist = GM_getValue("blacklist", "").split(",");
  16. emptySpace = blacklist.indexOf(""); //stops empty line from showing up in blacklist
  17. console.log(emptySpace);
  18. if (emptySpace>-1){
  19. blacklist.splice(emptySpace,1);
  20. }
  21. var recommendationList;
  22. var currentlyHoveredChannelName = "";
  23. var timeoutFunction;
  24.  
  25. var floatDivHTML;
  26. var floatDivDOM;
  27. var blacklistManager = {};
  28.  
  29. var hidden;
  30.  
  31. var extraCSS = document.createElement("style");
  32. extraCSS.textContent = `
  33. #floatDiv {
  34. position:absolute;
  35. background:Salmon;
  36. height:45px; width:160px;
  37. border:2px solid Maroon;
  38. z-index:2;
  39. cursor:pointer
  40. }
  41.  
  42. #floatDivButton {
  43. position: absolute;
  44. top: 50%; left: 50%;
  45. transform: translate(-50%, -50%);
  46. color:DarkRed;
  47. font-weight:bold;
  48. cursor:pointer;
  49. }
  50.  
  51. .menuOption {color:White;cursor:pointer;border:2px solid Maroon;background:Salmon; padding: 2px 5px}
  52. .managerMenuCloseOption {color:White;position:absolute;top:20px;right:20px; font-size:200%; cursor:pointer;text-align:center;}
  53. .managerMenuOption {color:White;cursor:pointer;border:1px solid white; font-size:110%}
  54.  
  55. #menu_blacklistToggle{position: relative; float:right; }
  56. #menu_blacklistManager{position: relative; float:right; }
  57.  
  58. #blacklistManager{
  59. color:White;
  60. position:fixed;
  61. top: 50%;left: 50%;
  62. transform: translate(-50%, -50%);
  63. height:300px;width:500px;
  64. background:rgba(0,0,0,0.5);
  65. padding: 20px;
  66. z-index:10
  67. }
  68.  
  69. #blacklistManagerContent{
  70. position: relative;
  71. top: 50%;
  72. transform: translate(-5%, -50%);
  73. width: 600px;
  74. margin: 0 auto;
  75. text-align: center;
  76. }
  77.  
  78. #blacklistSelector {width:300px;}
  79. `;
  80. document.head.appendChild(extraCSS);
  81.  
  82. $(document).ready(function(){
  83.  
  84. recommendationList = $(".video-list-item");
  85. floatDivHTML = '<div id="floatDiv"><button type="button" id="floatDivButton">Remove this channel from recommendation</button></div>'; //maybe use image instead of text
  86. $('#body-container').append(floatDivHTML);
  87. floatDivDOM = $('#floatDiv');
  88. floatDivDOM.hide();
  89. floatDivDOM.click(floatDivClickHandler);
  90.  
  91. blacklistManager.HTML = `
  92. <div id="blacklistManager">
  93. <div class="managerMenuCloseOption">&#10005;</div>
  94. <div id="blacklistManagerContent">Add to blacklist:
  95. <input type="text" name="blacklistEntry" id="blacklistEntry" placeholder="Press Enter to add">
  96. <br>
  97. <br>
  98. Current blacklisted channel
  99. <br>
  100. <select name="BL" id="blacklistSelector" size="10" multiple></select>
  101. <br>
  102. <br>
  103. <button type="button" class="managerMenuOption" id="blacklistRemove">Remove From Blacklist</button>
  104. </div>
  105. </div>
  106. `;
  107. $("body").append(blacklistManager.HTML);
  108. blacklistManager.DOM = $("#blacklistManager");
  109. blacklistManager.DOM.hide();
  110. $("#blacklistRemove").click(function(){
  111. var listToRemove = $("#blacklistSelector").val();
  112. removeFromBlacklist(listToRemove);
  113. });
  114.  
  115. $(".managerMenuCloseOption").click(toggleBlacklistManager);
  116. $("#blacklistEntry").keypress(function(e){
  117. if(e.keyCode == 13){
  118. addToBlacklist($(this).val());
  119. $(this).val('');
  120. }
  121. });
  122.  
  123. $(floatDivDOM).hover(function(){
  124. clearTimeout(timeoutFunction);
  125. },function(){
  126. timeoutFunction = setTimeout(function(){
  127. floatDivDOM.hide();
  128. }, 1000);
  129. });
  130.  
  131. // Hide blacklisted items from the recommendation list
  132. filterRec(true);
  133. for (i=0; i<recommendationList.length; i++){
  134. $(recommendationList[i]).hover(function(){
  135. // Hover on
  136. clearTimeout(timeoutFunction);
  137. currentlyHoveredChannelName = getTitleFromLi(this);
  138.  
  139. var x = getOffset(this).left + 400;
  140. var y = getOffset(this).top;
  141. floatDivDOM.css({ // customize the left and top location
  142. 'left': x+'px',
  143. 'top': y+'px',
  144. });
  145. floatDivDOM.show();
  146. $("#floatDivButton").click(floatDivClickHandler);
  147. },function(){
  148. // Hover off
  149. timeoutFunction = setTimeout(function(){
  150. floatDivDOM.hide();
  151. }, 1000);
  152. });
  153. }
  154.  
  155. appendToggleHidden();
  156. blacklistManagerAttach();
  157.  
  158. });
  159.  
  160. function floatDivClickHandler(){
  161. addToBlacklist(currentlyHoveredChannelName);
  162. timeoutFunction = setTimeout(function(){
  163. floatDivDOM.hide();
  164. }, 100);
  165. }
  166.  
  167. function appendToggleHidden(){
  168. // Add option to toggle the hidden channels
  169. toggleHiddenButtonHTML = '<button type="button" class="menuOption" id="menu_blacklistToggle">Toggle hidden channels</button>'; //maybe use image instead of text
  170. $('#watch-headline-title').append(toggleHiddenButtonHTML);
  171. toggleHiddenButtonDOM = $('#menu_blacklistToggle');
  172. toggleHiddenButtonDOM.click(function(){
  173. if (hidden){
  174. filterRec(false);
  175. } else {
  176. filterRec(true);
  177. }
  178. });
  179. }
  180.  
  181. function blacklistManagerAttach(){
  182. // Add option to manage blacklisted channels
  183. blacklistManager.buttonHTML = '<button type="button" class="menuOption" id="menu_blacklistManager">Manage Blacklist</button>'; //maybe use image instead of text
  184. $('#watch-headline-title').append(blacklistManager.buttonHTML);
  185.  
  186. blacklistManager.buttonDOM = $("#menu_blacklistManager");
  187. blacklistManager.hidden = true;
  188. blacklistManager.buttonDOM.click(function(){
  189. toggleBlacklistManager();
  190. });
  191. }
  192.  
  193. function toggleBlacklistManager(){
  194. if (blacklistManager.hidden){
  195. populateSelectionTable();
  196. blacklistManager.DOM.show();
  197. blacklistManager.hidden = false;
  198. } else {
  199. blacklistManager.DOM.hide();
  200. blacklistManager.hidden = true;
  201. }
  202. }
  203.  
  204. function populateSelectionTable(){
  205. $("#blacklistSelector").empty();
  206. var options = "";
  207. for (i=0;i<blacklist.length;i++){
  208. var item = blacklist[i];
  209. options += '<option value="'+ item +'">'+item;
  210. }
  211. $("#blacklistSelector").append(options);
  212. }
  213.  
  214. function filterRec(bool_hide){
  215. if (bool_hide){
  216. hidden = true;
  217. } else {
  218. hidden = false;
  219. }
  220. for (i=0; i<recommendationList.length; i++){
  221. if(bool_hide){
  222. var nameToCheck = getTitleFromLi(recommendationList[i]);
  223. if (nameToCheck!=="" && blacklist.indexOf(nameToCheck) > -1){
  224. $(recommendationList[i]).hide();
  225. }
  226. } else {
  227. $(recommendationList[i]).show();
  228. }
  229. }
  230. }
  231.  
  232. function filterUser(bool_hide, username){
  233. for (i=0; i<recommendationList.length; i++){
  234. var nameToCheck = getTitleFromLi(recommendationList[i]);
  235. if (nameToCheck!=="" && username === nameToCheck){
  236. if(bool_hide){
  237. $(recommendationList[i]).hide();
  238. } else {
  239. $(recommendationList[i]).show();
  240. }
  241. }
  242. }
  243. }
  244.  
  245. function getTitleFromLi(liItem){
  246. var title = $(liItem).children(".content-wrapper").children("a").children(".stat.attribution").text();
  247. if (title === ""){
  248. title = $(liItem).children(".related-item-dismissable").children(".content-wrapper").children("a").children(".stat.attribution").text();
  249. }
  250. return title;
  251. }
  252.  
  253. function arrayStringtoLine(array){
  254. var returnThis = "";
  255. for (i=0;i<array.length;i++){
  256. if(returnThis === ""){
  257. returnThis = returnThis + array[i];
  258. } else {
  259. returnThis = returnThis +","+ array[i];
  260. }
  261. }
  262. return returnThis;
  263. }
  264.  
  265. function removeFromBlacklist(usernameArray){
  266. for (j=0;j<usernameArray.length;j++){
  267. console.log(j);
  268. var index = blacklist.indexOf(usernameArray[j]);
  269. blacklist.splice(index,1);
  270. filterUser(false, usernameArray[j]);
  271. }
  272. GM_setValue("blacklist", arrayStringtoLine(blacklist));
  273. populateSelectionTable();
  274. }
  275.  
  276. function addToBlacklist(username){
  277. var index = blacklist.indexOf(username);
  278. if(index === -1 && username!==""){
  279. blacklist.push(username);
  280. GM_setValue("blacklist", arrayStringtoLine(blacklist));
  281. filterRec(true);
  282. populateSelectionTable();
  283. }
  284. }
  285.  
  286. // Credit to Adam Grant: http://stackoverflow.com/questions/442404/retrieve-the-position-x-y-of-an-html-element
  287. function getOffset(el) {
  288. el = el.getBoundingClientRect();
  289. return {
  290. left: el.left + window.scrollX,
  291. top: el.top + window.scrollY
  292. };
  293. }