Block Youtube Users

Hide videos of blacklisted users/channels (from recommended, search, related channels...)

Ekde 2018/03/26. Vidu La ĝisdata versio.

You will need to install an extension such as Tampermonkey, Greasemonkey or Violentmonkey to install this script.

You will need to install an extension such as Tampermonkey or Violentmonkey to install this script.

You will need to install an extension such as Tampermonkey or Violentmonkey to install this script.

You will need to install an extension such as Tampermonkey or Userscripts to install this script.

You will need to install an extension such as Tampermonkey to install this script.

You will need to install a user script manager extension to install this script.

(I already have a user script manager, let me install it!)

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

(I already have a user style manager, let me install it!)

  1. // ==UserScript==
  2. // @name Block Youtube Users
  3. // @author Schegge
  4. // @namespace https://github.com/Schegge
  5. // @description Hide videos of blacklisted users/channels (from recommended, search, related channels...)
  6. // @version 2.3.4
  7. // @match *://www.youtube.com/*
  8. // @exclude *://www.youtube.com/embed/*
  9. // @require https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js
  10. // @grant GM_getValue
  11. // @icon data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAC4AAAAuCAYAAABXuSs3AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyBpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMC1jMDYwIDYxLjEzNDc3NywgMjAxMC8wMi8xMi0xNzozMjowMCAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNSBXaW5kb3dzIiB4bXBNTTpJbnN0YW5jZUlEPSJ4bXAuaWlkOkMzRDhDREZEMzVGMDExRTVBOUUzRDg5MDZENTJEMTA2IiB4bXBNTTpEb2N1bWVudElEPSJ4bXAuZGlkOkMzRDhDREZFMzVGMDExRTVBOUUzRDg5MDZENTJEMTA2Ij4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6QzNEOENERkIzNUYwMTFFNUE5RTNEODkwNkQ1MkQxMDYiIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6QzNEOENERkMzNUYwMTFFNUE5RTNEODkwNkQ1MkQxMDYiLz4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz6dWQTHAAADwklEQVR42tRaTUwTQRR+u10q5WKTclOExASMwXT1aExoQpB4UHswajyVSDx40Caa6AmrJ000URI9EJP2ZOJJiBeh/oD4c6S9iScRDxyoQQ4USuk6s4wy2c7szP6Uti95TCAz3W9nvve996YohmFAM5oKTWpNC1wTTchOTibQ8Bj5Xh+fm0e+gvwH8WniQhsYHJQDjizhM2hsUTL2kfEOGSeQZ5CP+0GV3C4y4CzyV+SZuieqkCMFZbkAwedpT6gqh3qgcqADjd1gtLWJTmQO+RA5AVfAYRv4Mqjz370pAbV+66gO5ZP95svYWJqKgcZQlcBcDvY8eAQtL16KpmYaUg617DsRBTuJQLjjuC13O/YDIM7Sx46phePCShHm7n/+CgG0duvEcd6UpHXnNT9UZePeCP3rAut4tZnZU9qb7BFlaSnE+oyW8dd2wKOug5NnRiRSpfuhoSusZJIyf4Zap6C4PlAV/IUCqD8XTdXhWIwOUs8cN9ojzhYU189zVefbvP+1itHe7lc84piZYUruWrEWwCPQSFYfOVRV5i7Y8LtK3VTJo3ViYVvp7D18ESqVXnZJ0M1btmBVN1/k0KoexfSYTr009i6l8LtV+zh7LpB9f5C1qDzQb1e/pHyXQ5xcgqPPwNg55qhVd7FaKEjqlCI7+IxQCMrx07xHTDDzgl91B8y5q34x6NLtm7zd/sNK946Dk5FsvOUABBpnXZugjPNizBlwnyURUyc4+tTMmAybsWvn6l4dqou/IHj/IQt8HwEe9tRImLa2xvwzbgoMOw1G6zAwXpWId74FlbaWYo0GH7NSRnO6O1Xa29MNpWtXJbuogtk4BBiBjD878OkLq0KMEjlM1o0qOEbwS+ITYh7/1Fve0us4F/guh4wsN85RA4xYR5rdydt1BdGKI41JetdrATyD6vGUbWWbHsOc/cCkE4oFg91Ax2ngMlTR/X4zTqMhsk6aLjLAww4fkPO0Gfb3LV2Og5OTJNxWk3Fu9Whf2rpQFY6Gu6CWbpU2Wlp3r5GofqGwzTGnSEJhXqKW+V2+q8wZEyUlFGz/d0tZXR1mrNFBcOOLC7gtMfBp3+WQSuf7iDuy0nBCNCXfUEWWCfpyQnT5CWC5M9fqCRjX45uXLshQBMDFFVxNAFeO6bAZPyNb4z+B7etm58GJj3Lj1g1mwqC1V3gbZZkvYXnPzbIED6XmOLB/PedKw3VAgiozxishGhX4XaL9OS8JKAc7X+vV0vJEOTIy9Y4M8CQB3yWbTSVtmhpz4PCqT2nWf0L4K8AAGQEtCug+rd8AAAAASUVORK5CYII=
  12. // ==/UserScript==
  13.  
  14. /*** DESCRIPTION
  15. → the program is case-insensitive
  16. → put a * in front of a word for wildcard (only in the blacklist!), it will find the word no matter its position in the username (example: *vevo)
  17. → you can choose the symbol to split the usernames (default is a comma) ('*' not allowed) (max 1 character)
  18. → you can enable/disable to blacklist channels by clicking/right clicking on '[x]' before the usernames
  19. → you can suspend temporarily the block (to reactivate it just click on save or refresh the page)
  20. → it hides videos of blacklisted users/channels from recommended, search, related channels...
  21. → also from the playlists/mixes, but it doesn't prevent them from playing if the playlist is in autoplay
  22. → for both the new and the old youtube layout
  23.  
  24. <!> please report any bugs
  25. ***/
  26.  
  27. var showUpdates = true;
  28. var byuDebug = false;
  29.  
  30. // saved data from obsolete GM_+ default values
  31. var _sBL, _sWL, _sep, _add;
  32. if (!localStorage.getItem('savedblocks') && typeof GM_getValue === 'function') {
  33. _sBL = GM_getValue('savedblocks', '');
  34. _sWL = GM_getValue('savedwhites', '');
  35. _sep = GM_getValue('sep', ',');
  36. _add = GM_getValue('enableadd', '');
  37. } else {
  38. _sBL = '';
  39. _sWL = '';
  40. _sep = ',';
  41. _add = '';
  42. }
  43.  
  44. (function($) {
  45. function getValue(key, d) {
  46. if (!localStorage.getItem(key)) localStorage.setItem(key, d);
  47. return localStorage.getItem(key);
  48. }
  49.  
  50. // get black/whitelist saved
  51. var sBL, sWL, sep, add, ytblacklist, ytwhitelist;
  52. function getValues() {
  53. sBL = getValue('savedblocks', _sBL);
  54. sWL = getValue('savedwhites', _sWL);
  55. sep = getValue('sep', _sep);
  56. add = getValue('enableadd', _add);
  57. ytblacklist = sBL.split(sep);
  58. ytwhitelist = sWL.split(sep);
  59. }
  60. getValues();
  61.  
  62. // changes' notice
  63. if (showUpdates) {
  64. if (getValue('byuver', '1').trim() !== '2.3.3' && getValue('byuver', '1').trim() !== '2.3.4') {
  65. localStorage.setItem('byuver', '2.3.4');
  66. $('body').append('<div id="byu-notice" style="position: fixed; z-index: 999999; width: 40%; min-width: 200px; font-size: 1.2em; padding: 1.5em; bottom: 50px; right: 50px; background: red; color: #fff">[2.3.3] Due to changes how to store users\' values, you may have lost your previous data, sorry.<br><small>(moved from <i>GM</i> to <i>localStorage</i>)</small><br><br>[2.3.1] KNOWN BUG (with the new layout): clicking on [x] opens the video, so <b>right-click</b> it instead.<br><br><span style="cursor: pointer; background: rgba(0,0,0,.5); border-radius: 5px; padding: 0 5px">dismiss</span></div>');
  67. $('#byu-notice span').on('click', function() { $('#byu-notice').remove(); });
  68. }
  69. } else {
  70. localStorage.setItem('byuver', '2.3.4');
  71. }
  72.  
  73. // vars
  74. var suspend = false;
  75. var uClasses, tClasses, margintop;
  76.  
  77. // check what layout
  78. var ver = $('#upload-btn').length ? 'old' : 'new';
  79.  
  80. if (ver == 'new') {
  81. // where the usernames are
  82. // //grid
  83. uClasses = ['#byline.ytd-grid-video-renderer a',
  84. //big channel recommend
  85. 'a.ytd-shelf-renderer[href*=user] #title.ytd-shelf-renderer, a.ytd-shelf-renderer[href*=channel] #title.ytd-shelf-renderer, #title-annotation.ytd-shelf-renderer a',
  86. //search
  87. '#byline.ytd-video-meta-block',
  88. //search channels
  89. '#channel-title.ytd-channel-renderer span.ytd-channel-renderer',
  90. //related channels
  91. '.title.ytd-mini-channel-renderer',
  92. //playlist
  93. '#byline.ytd-playlist-panel-video-renderer'];
  94. tClasses = 'ytd-video-renderer, ytd-grid-video-renderer, ytd-shelf-renderer, ytd-channel-renderer, ytd-mini-channel-renderer, ytd-playlist-renderer, ytd-compact-video-renderer, ytd-compact-autoplay-renderer, ytd-playlist-panel-video-renderer';
  95.  
  96. // research
  97. window.addEventListener('yt-action', search, false);
  98. window.addEventListener('yt-page-data-updated', search, false);
  99. window.addEventListener('yt-load-next-continuation', search, false);
  100. window.addEventListener('yt-load-reload-continuation', search, false);
  101. window.addEventListener('shown-items-changed', search, false);
  102.  
  103. } else { // old
  104. uClasses = ['.yt-lockup-byline > a',
  105. '.branded-page-module-title-text',
  106. 'span.shelf-annotation.shelf-title-annotation a',
  107. 'span.stat.attribution > span:not(.byu-add)',
  108. '.branded-page-related-channels-list .yt-uix-tile-link',
  109. '.video-uploader-byline'];
  110. tClasses = 'tr, li';
  111.  
  112. // research
  113. var target = document.querySelector('#content');
  114. var config = { attributes: false, childList: true, characterData: false, subtree: true };
  115. var observer = new MutationObserver(function(mutations) { search(); });
  116.  
  117. try { observer.observe(target, config); } catch (e) {}
  118. }
  119.  
  120. // CSS + Menu
  121. $('head').append('<style> ' +
  122. '#byu-is-black { display: none!important; } ' +
  123. '#byu { color: #A0A0A0; cursor: pointer; font-size: 22px; vertical-align: middle; } ' +
  124. '#byu-options { width: 500px; display: flex; flex-flow: row wrap; align-items: baseline; position: fixed; right: 70px; padding: 0 20px 15px; background-color: #fff; box-shadow: 0 1px 2px 0 rgba(0,0,0,.1); border: 1px solid #fafafa; border-top: 0; z-index: 9999999999; } ' +
  125. '#byu-options div { box-sizing: border-box; padding: 5px; font-size: 1em; } ' +
  126. '#byu-options .textarea div { font-size: 1.2em; width: 100%; text-align: center; font-weight: 500; } ' +
  127. '#byu-options .textarea textarea { font-size: 1em; resize: vertical; width: 100%; padding: 4px; border: 2px solid rgba(0,0,0,.13); box-sizing: border-box; } ' +
  128. '#byu-options .textarea.wl { width: 40%; } ' +
  129. '#byu-options .textarea.bl { width: 60%; } ' +
  130. '#byu-saveblacklist { font-size: 1.2em; font-weight: bold; cursor: pointer; color: #FF0000; } ' +
  131. '.byu-sep { width: 33%; font-size: 9px; color: rgba(0,0,0,.5); } ' +
  132. '#byu-sep-symbol { width: 10px; background: #fff; border: 1px dotted rgba(0,0,0,.13); padding: 0 2px; color: #000; } ' +
  133. '#byu-enableadd { width: 33%; cursor: pointer; color: rgba(0,0,0,.5); text-align: center; } ' +
  134. '#byu-suspend { width: 33%; cursor: pointer; color: rgba(0,0,0,.5); text-align: right; } ' +
  135. '.byu-add { font-size: .8em; margin-right: .5em; cursor: pointer; color: #FF0000; font-family: consolas, monospace; vertical-align: top; }' +
  136. '</style>');
  137.  
  138. $('body').append('<div id="byu-options" style="display: none">' +
  139. '<div style="width: 100%; text-align: right"><span id="byu-saveblacklist">save</span></div>' +
  140. '<div class="textarea wl"><div>Whitelist</div><textarea rows="4" id="byu-whitelist-words">' + sWL + '</textarea></div>' +
  141. '<div class="textarea bl"><div>Blacklist</div><textarea rows="4" id="byu-blacklist-words">' + sBL + '</textarea></div>' +
  142. '<div class="byu-sep">separator: <input id="byu-sep-symbol" type="text" value="' + sep + '" maxlength="1" /></div>' +
  143. '<div id="byu-enableadd">enable click add</div>' +
  144. '<div id="byu-suspend">suspend block</div>' +
  145. '</div>');
  146. if (add) $('#byu-enableadd').text('disable click add');
  147.  
  148. // with the new layout, wait till the masthead is added
  149. var waiting = setInterval(function() {
  150. if (ver == 'old' || $('#buttons').length) {
  151. clearInterval(waiting);
  152. button();
  153. }
  154. }, 1000);
  155.  
  156. function button() {
  157. if (ver == 'new') {
  158. $('#buttons').before('<div style="display: inline-block; position: relative; height: 28px; width: 30px"><span id="byu">B</span></div>');
  159. margintop = $('#container.ytd-masthead').height();
  160. } else {
  161. $('#upload-btn').before('<div style="display: inline-block; position: relative; height: 28px; width: 30px"><span id="byu">B</span></div>');
  162. margintop = $('#yt-masthead-container').height() + parseInt($('#yt-masthead-container').css('padding-top')) + parseInt($('#yt-masthead-container').css('padding-bottom'));
  163. }
  164.  
  165. $('head').append('<style>#byu-options {top:' + margintop + 'px; }</style>');
  166. }
  167.  
  168. // check if a username is whitelisted
  169. function ifWhite(u) {
  170. var whitelisted = false;
  171. for(var z = 0; z < ytwhitelist.length; z++) {
  172. var w = ytwhitelist[z].trim().toLowerCase();
  173. if (w.length && u == w) {
  174. whitelisted = true;
  175. }
  176. }
  177. return whitelisted;
  178. }
  179.  
  180. // check if a username is blacklisted
  181. function ifMatch(u) {
  182. var match = false;
  183. if (!ifWhite(u)) { // if the username isn't whitelisted
  184. for (var j = 0; j < ytblacklist.length; j++) {
  185. var b = ytblacklist[j].trim().toLowerCase();
  186. if (b.charAt(0) == '*') { // wildcards
  187. var part = b.split('*'),
  188. item = part[1];
  189. if (item.length && u.indexOf(item) !== -1) {
  190. match = true;
  191. }
  192. } else { // exact match
  193. if (b.length && u == b) {
  194. match = true;
  195. }
  196. }
  197. }
  198. }
  199. return match;
  200. }
  201.  
  202. // do the thing
  203. function findMatch(s) {
  204. $(s).each(function() {
  205. var username = $(this).text().trim().toLowerCase();
  206. if (!username) return 'continue';
  207.  
  208. // if the username is blacklisted
  209. if (!suspend && ifMatch(username)) {
  210. if (!$(this).closest(tClasses).attr('id', 'byu-is-black')) {
  211. $(this).closest(tClasses).attr('id', 'byu-is-black');
  212. }
  213.  
  214. // add click
  215. } else if (add) {
  216. if (!$(this).siblings('.byu-add').length) {
  217. $('<span class="byu-add" data="' + username + '">[x]</span>').insertBefore($(this));
  218. } else if ($(this).siblings('.byu-add').attr('data') != username) {
  219. $(this).siblings('.byu-add').attr('data', username);
  220. }
  221. }
  222. });
  223. }
  224.  
  225. // debug general info
  226. if (byuDebug) console.log('[BLOCK YOUTUBE USERS]\n(Youtube Layout) ' + ver + '\n(BYU ver.) ' + getValue('byuver', '1') + '\n(Sep.) ' + sep + '\n(Blacklist) ' + sBL.toString());
  227.  
  228. // the final search function
  229. function search() {
  230. var url = window.location.href;
  231. // playlist?list=WL = Watch Later | != feed/t... = History, Subscriptions
  232. if (!/.*youtube\.com\/(playlist\?list=WL|feed\/[^t]\w+)/.test(url)) {
  233. for (var i = 0; i < uClasses.length; i++) {
  234. findMatch(uClasses[i]);
  235. }
  236. }
  237.  
  238. if (byuDebug) console.log('[BLOCK YOUTUBE USERS] (SEARCHED)');
  239. }
  240. search();
  241.  
  242. // open and close options
  243. $('body').on('click', '#byu', function() {
  244. $('#byu-options').slideToggle();
  245. $(this).css('font-weight', $(this).css('font-weight') === '700' ? '400' : '700');
  246. });
  247.  
  248. // save blacklist changes and research
  249. $saved = $('<span style="margin-right: 7px; font-size: 80%">saved</span>');
  250. $error = $('<span style="margin-right: 7px; font-size: 80%; color: red">ERROR! * NOT ALLOWED AS SEPARATOR</span>');
  251. $('#byu-saveblacklist').on('click', function() {
  252. if ($('#byu-sep-symbol').val() == '*') {
  253. $(this).before($error);
  254. setTimeout(function() { $error.remove(); }, 4000);
  255. } else {
  256. // save new values
  257. localStorage.setItem('savedblocks', $('#byu-blacklist-words').val());
  258. localStorage.setItem('savedwhites', $('#byu-whitelist-words').val());
  259. localStorage.setItem('sep', $('#byu-sep-symbol').val());
  260. // add notification
  261. $(this).before($saved);
  262. setTimeout(function() { $saved.remove(); }, 2000);
  263. // clear everything
  264. $('[id="byu-is-black"]').each(function(){ $(this).attr('id', ''); });
  265. suspend = false;
  266. $('#byu-suspend').css('font-weight', '400');
  267. // research
  268. getValues();
  269. search();
  270. }
  271. });
  272.  
  273. // enable/disable click add
  274. $('#byu-enableadd').on('click', function() {
  275. if (add) {
  276. add = '';
  277. $('.byu-add').remove();
  278. $(this).text('enable click add');
  279. } else {
  280. add = 'yes';
  281. $(this).text('disable click add');
  282. }
  283. localStorage.setItem('enableadd', add);
  284. search();
  285. });
  286.  
  287. // suspend
  288. $('#byu-suspend').on('click', function() {
  289. suspend = true;
  290. $('[id="byu-is-black"]').each(function(){ $(this).attr('id', ''); });
  291. $(this).css('font-weight', '700');
  292. });
  293.  
  294. // add usernames to blacklist
  295. $('body').on('click contextmenu', '.byu-add', function(e) {
  296. e.preventDefault();
  297. e.stopPropagation();
  298. var q = sBL.trim().length ? sep + ' ' : '';
  299. $('#byu-blacklist-words').val($('#byu-blacklist-words').val() + q + $(this).attr('data'));
  300. localStorage.setItem('savedblocks', $('#byu-blacklist-words').val());
  301. getValues();
  302. search();
  303. });
  304. })(jQuery);