您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Allows you to block videos from youtube
// ==UserScript== // @name Youtube video blocker // @namespace Danielv123 // @version 1.4 // @description Allows you to block videos from youtube // @author Danielv123 // @match https://www.youtube.com/* // @grant none // @require https://code.jquery.com/jquery.js // ==/UserScript== //'use strict'; /* Videos in sidebar Get video ID document.querySelectorAll(".video-list-item .yt-uix-simple-thumb-wrap")[0].dataset.vid Get video title document.querySelectorAll(".video-list-item .content-wrapper a:nth-child(1)")[2].title Get username document.querySelectorAll(".video-list-item .content-wrapper .stat.attribution span")[2].innerHTML Hide document.querySelectorAll(".video-list-item")[2].style.display = "none"; */ var sidebar = { ID: function(x) { return document.querySelectorAll(".video-list-item.related-list-item-compact-video > .related-item-dismissable .yt-uix-simple-thumb-wrap")[x].dataset.vid; }, title: function(x) { if(document.querySelectorAll(".video-list-item.related-list-item-compact-video > .related-item-dismissable > .content-wrapper a:nth-child(1)")[x]){ return document.querySelectorAll(".video-list-item.related-list-item-compact-video > .related-item-dismissable > .content-wrapper a:nth-child(1)")[x].title; } else { return ""; } }, username: function(x) { let y=document.querySelectorAll(".video-list-item.related-list-item-compact-video > .related-item-dismissable > .content-wrapper .stat.attribution span")[x]; if(y) return y.innerHTML; return ""; }, hide: function(x) { document.querySelectorAll(".video-list-item.related-list-item-compact-video")[x].style.display = "none"; } }; /* Videos on subscriptions page Get video ID document.querySelectorAll(".yt-shelf-grid-item > div")[0].dataset.contextItemId Get video title document.querySelectorAll(".yt-shelf-grid-item .yt-lockup-content .yt-lockup-title a")[0].title Get username document.querySelectorAll(".yt-shelf-grid-item .yt-lockup-content .yt-lockup-byline a")[0].innerHTML Hide document.querySelectorAll(".yt-shelf-grid-item")[0].style.display = "none" */ var shelfvideos = { ID: function(x) { return document.querySelectorAll(".yt-shelf-grid-item > div")[x].dataset.contextItemId; }, title: function(x) { if(document.querySelectorAll(".yt-shelf-grid-item .yt-lockup-content .yt-lockup-title a")[x] && document.querySelectorAll(".yt-shelf-grid-item .yt-lockup-content .yt-lockup-title a")[x].title){ return document.querySelectorAll(".yt-shelf-grid-item .yt-lockup-content .yt-lockup-title a")[x].title; } }, username: function(x) { return document.querySelectorAll(".yt-shelf-grid-item .yt-lockup-content .yt-lockup-byline a")[x].innerHTML; }, hide: function(x) { document.querySelectorAll(".yt-shelf-grid-item")[x].style.display = "none"; } }; /* Videos on autolplay list Title document.querySelector("#watch-related > li:nth-child(1) > div.related-item-dismissable > div.content-wrapper > a > span.title") Username document.querySelector("#watch7-sidebar-modules > div:nth-child(1) > div > div.watch-sidebar-body > ul > li > div.content-wrapper > a > span.stat.attribution > span") */ // Code goes here and onwards function main() { if(!localStorage.blockedUsers){ localStorage.blockedUsers = JSON.stringify([]); } if(!localStorage.blockedTitles){ localStorage.blockedTitles = JSON.stringify([]); } if(!localStorage.blockedRegex){ localStorage.blockedRegex = JSON.stringify([]); } //hideSidebarVideos("","PewDiePie"); //hideShelfVideos("","nigahiga"); //hideShelfVideos("","","s"); // Hide videos let userFilters = JSON.parse(localStorage.blockedUsers); let titleFilters = JSON.parse(localStorage.blockedTitles); let regexFilters = JSON.parse(localStorage.blockedRegex); // Loop until we are through the largest of our filter sets for(let i = 0; i < Math.max(regexFilters.length, Math.max(userFilters.length, titleFilters.length));i++){ // hideSidebarVideos(id, username, title, regex) let id = ""; let user = userFilters[i] || ""; let title = titleFilters[i] || ""; let regex = regexFilters[i] || ""; hideSidebarVideos(id, user, title); hideShelfVideos(id, user, title); // only responds to title, but whatever. hideEndscreenVideos(undefined, undefined, title); } } setTimeout(main, 500); injectScripts(); makeFilterGui(); function makeFilterGui() { let HTML = '<div id="youtubeBlockerGui" style="">'; // Close button HTML += '<div id="youtubeBlockerGuiCloseButton"><img src="http://www.drodd.com/images14/x23.png"></img></div>'; HTML += '<h1>Youtube Blocker</h1><p>Below are a few textfields. Enter , (comma) seperated lists of titles and/or channels to exclude from your youtube feed.</p><p>Video titles don\'t have to match completely, just having part of the title is enough. Ex "porn,1000 degree,prank" will match "1000 degree knife vs water baloon EPIC"<br>'; HTML += '<h2>Blocked channels</h2><p><i>All channels with this excact name will be hidden</i></p><textarea id="blockedChannels"></textarea>'; HTML += '<h2>Blocked videos by name</h2><p><i>All videos with this in their names will be hidden</i></p><textarea id="blockedVideos"></textarea>'; HTML += '<h2>Regex blocks</h2><p><i>All video titles matching this regex will be hidden</i></p><textarea id="blockedRegex"></textarea>'; // Save button HTML += '<div id="saveButton"><h2>Save</h2></div>'; // Close everything HTML += '</div>'; // Open settings button in botttom right corner HTML += '<div id="gearwheelButton"><img src="https://upload.wikimedia.org/wikipedia/commons/thumb/b/bd/Simpleicons_Interface_gear-wheel-in-black.svg/2000px-Simpleicons_Interface_gear-wheel-in-black.svg.png"></img></div>'; // inject into body let container = document.createElement('div'); container.innerHTML = HTML; (document.body || document.head || document.documentElement).appendChild(container); // Populate textareas with old settings let x = JSON.parse(localStorage.blockedUsers); let y = ""; for(let i in x) { y += x[i]+",\n"; } $("textarea#blockedChannels")[0].value = y; x = JSON.parse(localStorage.blockedTitles); y = ""; for(let i in x) { y += x[i]+",\n"; } $("textarea#blockedVideos")[0].value = y; x = JSON.parse(localStorage.blockedRegex); y = ""; for(let i in x) { y += x[i]+",\n"; } $("textarea#blockedRegex")[0].value = y; document.querySelector("#youtubeBlockerGui #youtubeBlockerGuiCloseButton").onclick = toggleGuiDisplay; document.querySelector("#gearwheelButton").onclick = toggleGuiDisplay; document.querySelector("#saveButton").onclick = function(){ console.log("Saving lists of blocked channels, users and regexes"); // Regex to replace linebreaks localStorage.blockedUsers = JSON.stringify($("textarea#blockedChannels")[0].value.replace(/(\r\n|\n|\r)/gm,"").split(",")); localStorage.blockedTitles = JSON.stringify($("textarea#blockedVideos")[0].value.replace(/(\r\n|\n|\r)/gm,"").split(",")); localStorage.blockedRegex = JSON.stringify($("textarea#blockedRegex")[0].value.replace(/(\r\n|\n|\r)/gm,"").split(",")); }; } function readBlockSettings(){ return $("#youtubeBlockerGui textarea")[0].value.replace(/(\r\n|\n|\r)/gm,"").split(","); } function toggleGuiDisplay(){ let gui = $("#youtubeBlockerGui")[0]; if(gui.style.display == "none"){ gui.style.display = "block"; console.log("showing blocker gui"); } else { gui.style.display = "none"; console.log("hiding blocker gui"); } } function injectScripts(){ // jQuery var s=document.createElement('script'); s.setAttribute('src','https://code.jquery.com/jquery.js'); document.getElementsByTagName('head')[0].appendChild(s); // CSS var d=document.createElement('style'); d.innerHTML = "#youtubeBlockerGui {"+ "display:none;"+ "width:60%;"+ "height:80%;"+ "background-color:white;"+ "position:fixed;"+ "top:10%;"+ "left:20%;"+ "border:1px solid lightgrey;"+ // damn, the youtube sidebar apparently has a z index of 1999999999... "z-index:2000000000;"+ "}"+ // red X on gui to close "#youtubeBlockerGuiCloseButton {"+ "float:right;"+ "height:30px;"+ "width:30px;"+ "cursor:pointer;"+ "}"+ "#youtubeBlockerGuiCloseButton img {"+ "height:100%;"+ "width:100%;"+ "}"+ // gearwheel in bottom right corner "#gearwheelButton {"+ "position:fixed;"+ "height:30px;"+ "width:30px;"+ "bottom:0px;"+ "right:0px;"+ "cursor:pointer;"+ "}"+ "#gearwheelButton img {"+ "height:100%;"+ "width:100%;"+ "}"+ "#saveButton {"+ "cursor:pointer;"+ "}" ; document.getElementsByTagName('body')[0].appendChild(d); } function hideShelfVideos(id, username,title, regex) { let videos = document.querySelectorAll(".yt-shelf-grid-item"); for(let i = 0; i < videos.length; i++){ let hideVideo = function(number, filter){ // document.querySelectorAll(".yt-shelf-grid-item")[number].style.display = "none"; shelfvideos.hide(number); console.log("Filter: " + filter + " Hidden: " + document.querySelectorAll(".yt-shelf-grid-item .yt-lockup-content .yt-lockup-title a")[number].title); }; // Check by video ID if(id && id == shelfvideos.ID(i)){ hideVideo(i, id); } // Check by channel name if(username && username.toLowerCase() == shelfvideos.username(i).toLowerCase()){ hideVideo(i, username); } // Check if video title contains title if(title && title != " " && shelfvideos.title(i).toLowerCase().includes(title.toLowerCase())){ hideVideo(i, title); } // Check if title matches regex if(regex && shelfvideos.title(i).match(regex)){ hideVideo(i, regex); } } } function hideSidebarVideos(id, username, title, regex) { let videos = document.querySelectorAll(".video-list-item"); for(let i = 0; i < videos.length; i++){ let hideVideo = function(number, filter){ // document.querySelectorAll(".video-list-item")[number].style.display = "none"; sidebar.hide(number); console.log("Filter: " + filter + " Hidden sidebar: " + document.querySelectorAll(".video-list-item .content-wrapper a:nth-child(1)")[number].title); }; // Check by video ID if(id && id == sidebar.ID(i)){ hideVideo(i, id); } // Check by channel name if(username && username.toLowerCase() == sidebar.username(i).toLowerCase()){ hideVideo(i, username); } // Check if video title contains title if(title && title != " " && sidebar.title(i).toLowerCase().includes(title.toLowerCase())){ hideVideo(i, title); } // Check if title matches regex if(regex && sidebar.title(i).match(regex)){ hideVideo(i, regex); } } } // hide endscreen videos function hideEndscreenVideos(id, username, title, regex){ let x = document.querySelectorAll('[aria-label].ytp-videowall-still.ytp-suggestion-set'); for(let i = 0;i<x.length;i++){ // if elemnt has aria-label (lots of those that are unrelated) and includes title and title is not falsey (ex "") beause that would trigger on lots of non video things if(x[i].getAttribute("aria-label") && x[i].getAttribute("aria-label").toLowerCase().includes(title) && title){ x[i].style.display = "none"; console.log("Filter: "+title+" Hidden: " + x[i].getAttribute("aria-label")); } } } // https://stackoverflow.com/questions/3219758/detect-changes-in-the-dom var observeDOM = (function(){ var MutationObserver = window.MutationObserver || window.WebKitMutationObserver, eventListenerSupported = window.addEventListener; return function(obj, callback){ if( MutationObserver ){ // define a new observer var obs = new MutationObserver(function(mutations, observer){ if( mutations[0].addedNodes.length || mutations[0].removedNodes.length ) callback(); }); // have the observer observe foo for changes in children obs.observe( obj, { childList:true, subtree:true }); } else if( eventListenerSupported ){ obj.addEventListener('DOMNodeInserted', callback, false); obj.addEventListener('DOMNodeRemoved', callback, false); } }; })(); observeDOM( document.querySelector("#content") ,function(){ console.log('dom changed, hiding videos...'); main(); });