Greasy Fork is available in English.

Block Youtube Users

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

Pada tanggal 18 November 2019. Lihat %(latest_version_link).

  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.4.5.1
  7. // @match *://www.youtube.com/*
  8. // @exclude *://www.youtube.com/embed/*
  9. // @exclude *://www.youtube.com/live_chat?*
  10. // @grant GM_getValue
  11. // @grant GM_setValue
  12. // @grant GM.getValue
  13. // @grant GM.setValue
  14. // @require https://greasemonkey.github.io/gm4-polyfill/gm4-polyfill.js
  15. // @require https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js
  16. // @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=
  17. // ==/UserScript==
  18.  
  19. /** DESCRIPTION
  20. - for both the new and the old youtube layout
  21. - it is not case-sensitive
  22. - it hides videos of blacklisted users/channels from recommended, search, related channels...
  23. - also from the playlists/mixes, but it doesn't prevent them from playing if the playlist is in autoplay
  24. - 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, *buzzfeed)
  25. - when you use it, but still you want continue seeing a channel that has that word in the name, you can put it in the whitelist (example -> balcklist: *buzzfeed; whitelist: BuzzFeed Nifty)
  26. - you can choose the symbol to split the usernames (default is a comma, * and " not allowed, min-max 1 character)
  27. - you can enable/disable to blacklist channels by clicking (old yt layout)/right clicking (new yt layout) on '[x]' before the usernames
  28. - in any case, the [x] buttons are automatically shown when the "B" menu is open
  29. - from a direct link to youtube, it pauses the video if blacklisted (you can enable/disable it)
  30. - you can suspend temporarily the block (to reactivate it just click on save or refresh the page)
  31. **/
  32.  
  33. (async function($) {
  34.  
  35. /* VARIABLES */
  36.  
  37. // get black/whitelist saved
  38. var sep, add, pv, blacklist, whitelist;
  39. async function getValues() {
  40. add = await GM.getValue('enableadd', '');
  41. pv = await GM.getValue('enablepause', '');
  42. sep = await GM.getValue('sep', ',');
  43. blacklist = await GM.getValue('savedblocks', '');
  44. whitelist = await GM.getValue('savedwhites', '');
  45. blacklist = blacklist ? blacklist.split(sep).map(function(v) { return v.trim(); }) : [];
  46. whitelist = whitelist ? whitelist.split(sep).map(function(v) { return v.trim(); }) : [];
  47. }
  48. await getValues();
  49.  
  50. var byuver = await GM.getValue('byuver', '2.4.5.1');
  51. var bOpen = false;
  52. var suspend = false;
  53. var uClasses, tClasses, uVideo, margintop;
  54.  
  55. // check what layout
  56. var ver = $('#yt-masthead-container').length ? 'old' : 'new';
  57. if (ver === 'new') {
  58. uClasses = '' +
  59. // grid
  60. '#text.ytd-channel-name, ' +
  61. // big channel recommend
  62. '#title-text.ytd-shelf-renderer a.ytd-shelf-renderer[href*="user"], #title-text.ytd-shelf-renderer a.ytd-shelf-renderer[href*="channel"], #title-annotation.ytd-shelf-renderer a, ' +
  63. // search channels
  64. '#channel-title.ytd-channel-renderer span.ytd-channel-renderer, ' +
  65. // related channels
  66. '.title.ytd-mini-channel-renderer, ' +
  67. // playlist
  68. '#byline.ytd-playlist-panel-video-renderer';
  69. tClasses = 'ytd-video-renderer, ytd-grid-video-renderer, ytd-rich-item-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';
  70. uVideo = '#upload-info #channel-name #text.ytd-channel-name';
  71.  
  72. // old
  73. } else {
  74. uClasses = '' +
  75. '.yt-lockup-byline > a, ' +
  76. '.yt-lockup-title > a[href*="user"], .yt-lockup-title > a[href*="channel"], ' +
  77. 'a.branded-page-module-title-link[href*="user"] .branded-page-module-title-text, a.branded-page-module-title-link[href*="channel"] .branded-page-module-title-text, ' +
  78. 'span.shelf-annotation.shelf-title-annotation a, ' +
  79. 'span.stat.attribution > span:not(.byu-add), ' +
  80. '.branded-page-related-channels-list .yt-uix-tile-link, ' +
  81. '#watch7-user-header .yt-user-info > a';
  82. tClasses = 'tr, li';
  83. uVideo = '.yt-user-info a';
  84. }
  85.  
  86. /* INTERVAL FOR BLACKLISTING */
  87.  
  88. search();
  89. setInterval(search, 1500);
  90.  
  91. /* CSS */
  92.  
  93. $('head').append('<style> ' +
  94. '#byu-is-black { display: none!important; } ' +
  95. '.byu-add { font-size: .8em; margin-right: .5em; cursor: pointer; color: #FF0000; font-family: consolas, monospace; float: left; }' +
  96. '#byu-video-page-black { position: fixed; z-index: 999999; width: 20%; min-width: 200px; font-size: 1.1em; padding: 1em; bottom: 50px; left: 50px; background: red; color: #fff; border-radius: 2px; }' +
  97. '#byu { color: var(--yt-spec-icon-active-other); cursor: pointer; font-size: 22px; vertical-align: middle; } ' +
  98. '#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; } ' +
  99. '#byu-options div { box-sizing: border-box; padding: 5px; font-size: 1em; } ' +
  100. '#byu-options .byu-textarea div { font-size: 1.2em; width: 100%; text-align: center; font-weight: 500; } ' +
  101. '#byu-options .byu-textarea textarea { font-size: 1em; line-height: 1em; min-height: 6em; resize: vertical; width: 100%; padding: 4px; border: 2px solid rgba(0,0,0,.13); box-sizing: border-box; } ' +
  102. '#byu-options .byu-textarea.wl { width: 35%; } ' +
  103. '#byu-options .byu-textarea.bl { width: 65%; } ' +
  104. '.byu-ver { width: 50%; font-size: .8em; color: rgba(0,0,0,.4); }' +
  105. '.byu-save { width: 50%; text-align: right; }' +
  106. '#byu-saveblacklist { font-size: 1.2em; font-weight: bold; cursor: pointer; color: #FF0000; } ' +
  107. '.byu-sep { width: auto; flex-grow: 1; color: rgba(0,0,0,.5); } ' +
  108. '.byu-opt { width: auto; flex-grow: 1; color: rgba(0,0,0,.5); text-align: center; } ' +
  109. '#byu-suspend { width: auto; flex-grow: 1; cursor: pointer; color: rgba(0,0,0,.5); text-align: right; } ' +
  110. '#byu-sep-symbol { width: 1em; background: #fff; border: 1px solid rgba(0,0,0,.2); padding: 0 2px; color: #000; height: 1.3em; line-height: 1em; vertical-align: bottom; box-sizing: border-box; } ' +
  111. 'input[type="checkbox"] { margin: 0; vertical-align: bottom; } ' +
  112. (ver === 'old' ? '#byu-options { font-size: 10px; } #byu { color: #808080; } ' : '') +
  113. '</style>');
  114.  
  115. /* VIDEO FIRST PAGE */
  116.  
  117. // when the first page opened is 'watch', pause video if blacklisted
  118. if (pv && /\/watch/.test(window.location.href)) {
  119. var video = $('#player video.video-stream.html5-main-video');
  120.  
  121. var pausevideo = function(u) {
  122. if (ifMatch(u.toLowerCase().trim())) {
  123. video.get(0).pause();
  124. video.get(0).currentTime = 0;
  125. var pausing = setInterval(function() {
  126. if (!suspend && !video.get(0).paused) {
  127. video.get(0).pause();
  128. video.get(0).currentTime = 0;
  129. }
  130. }, 500);
  131. $('body').append($('<div id="byu-video-page-black">' + u + ' is blacklisted</div>'));
  132. setTimeout(function() { $('#byu-video-page-black').remove(); clearInterval(pausing); }, 10000);
  133. $('body').on('click', '.html5-video-player, button.ytp-play-button', function() { clearInterval(pausing); });
  134. }
  135. };
  136.  
  137. if (typeof window.ytplayer !== 'undefined' && typeof window.ytplayer.config.args.author !== 'undefined') {
  138. pausevideo(window.ytplayer.config.args.author);
  139. } else {
  140. // for greasemonkey
  141. var waitUvideo = setInterval(function() {
  142. if ($(uVideo).length) {
  143. clearInterval(waitUvideo);
  144. pausevideo($(uVideo).text());
  145. }
  146. }, 1000);
  147. }
  148. }
  149.  
  150. /* BLACKLIST MENU */
  151.  
  152. // changes' ver
  153. if (byuver !== '2.4.5.1') {
  154. byuver = '2.4.5.1';
  155. GM.setValue('byuver', byuver);
  156. /* $('body').append('<div style="position: fixed; z-index: 999999; width: 35%; min-width: 200px; font-size: 1em; padding: 1.5em; bottom: 50px; right: 50px; color: red; background: #fff; border-radius: .5em; border: 1px solid red;">BLOCK YOUTUBE USERS [2.4.6]<br><br><br><br><span id="byu-notice-dismiss" style="cursor: pointer; background: red; color: #fff; border-radius: 2px; padding: 0 5px;">dismiss</span></div>');
  157. $('#byu-notice-dismiss').on('click', function() { $('#byu-notice-dismiss').parent().remove(); }); */
  158. }
  159.  
  160. // menu
  161. $('body').append('<div id="byu-options" style="display: none">' +
  162. '<div class="byu-ver">v' + byuver + '</div>' +
  163. '<div class="byu-save"><span id="byu-saveblacklist">save</span></div>' +
  164. '<div class="byu-textarea wl"><div>Whitelist</div><textarea spellcheck="false" id="byu-whitelist-words">' + whitelist.join(sep + ' ') + '</textarea></div>' +
  165. '<div class="byu-textarea bl"><div>Blacklist</div><textarea spellcheck="false" id="byu-blacklist-words">' + blacklist.join(sep + ' ') + '</textarea></div>' +
  166. '<div class="byu-sep">separator <input id="byu-sep-symbol" type="text" value="' + sep + '" maxlength="1" /></div>' +
  167. '<div class="byu-opt">right-click to add <input type="checkbox" name="clickadd" value="clickadd"' + (add ? ' checked' : '') + '></div>' +
  168. '<div class="byu-opt">pause blacklisted video <input type="checkbox" name="pausevideo" value="pausevideo"' + (pv ? ' checked' : '') + '></div>' +
  169. '<div id="byu-suspend">suspend</div>' +
  170. '</div>');
  171.  
  172. // for the button with the new layout, wait till the masthead is added
  173. var waitButton = setInterval(function() {
  174. if (ver === 'old' || $('#buttons').length) {
  175. clearInterval(waitButton);
  176. button();
  177. }
  178. }, 1000);
  179.  
  180. function button() {
  181. var btn = '<div style="display: inline-block; position: relative; height: 28px; width: 30px"><span id="byu">B</span></div>';
  182. if (ver === 'new') {
  183. $('#buttons').before(btn);
  184. margintop = $('#container.ytd-masthead').height();
  185. } else {
  186. $('#yt-masthead-creation-menu').before(btn);
  187. margintop = $('#yt-masthead-container').height() + parseInt($('#yt-masthead-container').css('padding-top'), 10) + parseInt($('#yt-masthead-container').css('padding-bottom'), 10);
  188. }
  189. $('head').append('<style>#byu-options {top:' + margintop + 'px; }</style>');
  190. }
  191.  
  192. /* BLACKLISTING FUNCTIONS */
  193.  
  194. // check if a username is whitelisted
  195. function ifWhite(u) {
  196. if (!whitelist) return false;
  197. return whitelist.some(function(w) {
  198. return u === w.trim().toLowerCase();
  199. });
  200. }
  201.  
  202. // check if a username is blacklisted
  203. function ifBlack(u) {
  204. return blacklist.some(function(b) {
  205. if (b.charAt(0) === '*') {
  206. b = b.replace('*', '');
  207. return b && u.indexOf(b) !== -1;
  208. } else {
  209. b = b.trim().toLowerCase();
  210. return b && u === b;
  211. }
  212. });
  213. }
  214.  
  215. // check if it needs to be blacklisted
  216. function ifMatch(u) {
  217. return !suspend && !ifWhite(u) && ifBlack(u);
  218. }
  219.  
  220. // do the thing
  221. function findMatch(el, newAdd) {
  222. var username = $(el).text().trim().toLowerCase();
  223. if (!username) return;
  224. var same = $(el).data('username') === username;
  225.  
  226. if ((!same || newAdd) && ifMatch(username)) {
  227. $(el).closest(tClasses).attr('id', 'byu-is-black');
  228.  
  229. } else if ((add || bOpen) && !$(el).siblings('.byu-add').length) {
  230. $('<span class="byu-add">[x]</span>').insertBefore($(el));
  231. }
  232.  
  233. if (!same) $(el).data('username', username);
  234. }
  235.  
  236. // global search
  237. function search(newAdd) {
  238. $(uClasses).each(function() {
  239. findMatch($(this), newAdd);
  240. });
  241. }
  242.  
  243. /* EVENT LISTENERS */
  244.  
  245. // open and close options
  246. $('body').on('click', '#byu', function() {
  247. $('#byu-options').slideToggle();
  248. $(this).css('font-weight', $(this).css('font-weight') === '700' ? '400' : '700');
  249. bOpen = bOpen ? false : true;
  250. if (!add) {
  251. if (bOpen) search();
  252. else $('.byu-add').remove();
  253. }
  254. });
  255.  
  256. // save blacklist changes and research
  257. $('#byu-saveblacklist').on('click', async function() {
  258. if (/[*"]|^$/.test($('#byu-sep-symbol').val())) {
  259. $(this).text('ERROR! separator not allowed');
  260. } else {
  261. // save new values
  262. await GM.setValue('savedblocks', $('#byu-blacklist-words').val().trim());
  263. await GM.setValue('savedwhites', $('#byu-whitelist-words').val().trim());
  264. await GM.setValue('sep', $('#byu-sep-symbol').val());
  265. // add notification
  266. $(this).text('saved');
  267. // clear everything
  268. $('[id="byu-is-black"]').removeAttr('id');
  269. suspend = false;
  270. $('#byu-suspend').css('font-weight', '400');
  271. // research
  272. await getValues();
  273. search(true);
  274. }
  275. setTimeout(function() { $('#byu-saveblacklist').text('save'); }, 2000);
  276. });
  277.  
  278. // add usernames to blacklist
  279. $('body').on('click contextmenu', '.byu-add', async function(e) {
  280. e.preventDefault();
  281. e.stopPropagation();
  282. $('#byu-blacklist-words').val($('#byu-blacklist-words').val() + (blacklist.length ? sep + ' ' : '') + $(this).next().data('username'));
  283. await GM.setValue('savedblocks', $('#byu-blacklist-words').val());
  284. await getValues();
  285. search(true);
  286. });
  287.  
  288. // enable/disable click add
  289. $('input[name=clickadd]').on('change', async function() {
  290. if ($(this).is(':checked')) {
  291. add = 'yes';
  292. } else {
  293. add = '';
  294. }
  295. await GM.setValue('enableadd', add);
  296. });
  297.  
  298. // enable/disable pause video
  299. $('input[name=pausevideo]').on('change', function() {
  300. pv = $(this).is(':checked') ? 'yes' : '';
  301. GM.setValue('enablepause', pv);
  302. });
  303.  
  304. // suspend
  305. $('#byu-suspend').on('click', function() {
  306. suspend = true;
  307. $('[id="byu-is-black"]').removeAttr('id');
  308. $(this).css('font-weight', '700');
  309. });
  310.  
  311. })(jQuery);