Skip to content

Instantly share code, notes, and snippets.

@Ellivers
Last active June 23, 2024 16:44
Show Gist options
  • Save Ellivers/9d7beaa66590ce719c1d8c333d6cfaa1 to your computer and use it in GitHub Desktop.
Save Ellivers/9d7beaa66590ce719c1d8c333d6cfaa1 to your computer and use it in GitHub Desktop.
Better YouTube Search Control
// ==UserScript==
// @name Better Search Result Control
// @namespace YouTube Search Options
// @match https://www.youtube.com/*
// @downloadURL https://gist.github.com/Ellivers/9d7beaa66590ce719c1d8c333d6cfaa1/raw/youtube-search-options.user.js
// @grant GM_getValue
// @grant GM_setValue
// @version 1.4
// @author Ellivers
// @description 2022-09-06, 19:00:54
// ==/UserScript==
/* Features:
* Hide sections with recommended videos in the search results, such as "People also watched", "For you", and "Previously watched"
* Hide videos that you have already watched
* Hide YouTube Shorts
* Makes search words in quotes mandatory for results
*
* (If it doesn't work, refresh the search page)
*/
const fileref = document.createElement('script');
fileref.setAttribute("id","searchresultctrl");
fileref.setAttribute("type","text/javascript");
document.body.appendChild(fileref);
function getStorage() {
return GM_getValue('better-yt-search-results', {hideWatched: false, hideRelated: false, hideShorts: false});
}
function setStorage(storage) {
return GM_setValue('better-yt-search-results', storage);
}
function waitForElm(selector) {
return new Promise(resolve => {
if (document.querySelector(selector)) {
return resolve(document.querySelector(selector));
}
const observer = new MutationObserver(mutations => {
if (document.querySelector(selector) && $(selector).is(':visible')) {
resolve(document.querySelector(selector));
observer.disconnect();
}
});
observer.observe(document.body, {
childList: true,
subtree: true
});
});
}
function change(type,hide) {
if (type === 'related') {
if (hide) {
$('ytd-shelf-renderer').hide();
$('ytd-horizontal-card-list-renderer.ytd-item-section-renderer').hide();
}
else {
$('ytd-shelf-renderer').show();
$('ytd-horizontal-card-list-renderer.ytd-item-section-renderer').show();
}
}
else if (type === 'shorts') {
if (hide) $('ytd-reel-shelf-renderer').hide();
else $('ytd-reel-shelf-renderer').show();
}
}
const results = [];
function loopThroughResults(mustInclude) {
const st = getStorage();
for (const result of $('#dismissible.ytd-video-renderer')) {
if ($(result).find('ytd-thumbnail-overlay-resume-playback-renderer').length >= 1) {
if ($(result).css('display') !== 'none' && st.hideWatched) {
$(result).hide();
continue;
}
else if (!st.hideWatched) $(result).show();
}
if ($(result).find('ytd-thumbnail-overlay-time-status-renderer').attr('overlay-style') === 'SHORTS') {
if ($(result).css('display') !== 'none' && st.hideShorts) {
$(result).hide();
continue;
}
else if (!st.hideShorts) $(result).show();
}
const link = $(result).find('a#video-title').attr('href');
if (link.startsWith('/shorts')) continue;
const id = /\/watch\?v=([^&]+)/.exec(link)[1];
if (results[results.length-1] === id) continue;
if (results.includes(id)) {
//$(result).hide();
continue;
}
results.push(id);
const shortDescription = $(result).find('.metadata-snippet-text').text().toLowerCase();
const title = $(result).find('.title-and-badge a').attr('title').toLowerCase();
for (const incl of mustInclude) {
if (shortDescription.includes(incl) || title.includes(incl)) continue;
$(result).hide();
break;
}
}
}
document.getElementById("searchresultctrl").onload = () => {
let searchQuery = ''
let mustInclude = ''
//searchQuery = $('input.ytd-searchbox').val();
waitForElm('#filter-menu').then((elem) => {
$(`
<div style="display: flex; align-items: center;">
<span style="font-size: 1.4rem;text-transform: uppercase;font-weight: 500; color: var(--ytd-searchbox-text-color);">Hide suggested videos</span>
<tp-yt-paper-toggle-button id="bt-yt-sr-hiderelated" noink="" class="style-scope ytd-toggle-item-renderer" role="button" toggles="" style="touch-action: pan-y; display: inline-block;">
</tp-yt-paper-toggle-button>
<span style="font-size: 1.4rem;text-transform: uppercase;font-weight: 500; color: var(--ytd-searchbox-text-color);">Hide shorts</span>
<tp-yt-paper-toggle-button id="bt-yt-sr-hideshorts" noink="" class="style-scope ytd-toggle-item-renderer" role="button" toggles="" style="touch-action: pan-y; display: inline-block;">
</tp-yt-paper-toggle-button>
<span style="font-size: 1.4rem;text-transform: uppercase;font-weight: 500; color: var(--ytd-searchbox-text-color);">Hide watched videos</span>
<tp-yt-paper-toggle-button id="bt-yt-sr-hidewatched" noink="" class="style-scope ytd-toggle-item-renderer" role="button" toggles="" style="touch-action: pan-y; display: inline-block;">
</tp-yt-paper-toggle-button>
</div>
`).appendTo(elem);
const storage = getStorage();
$('#bt-yt-sr-hidewatched').prop('active', storage.hideWatched);
$('#bt-yt-sr-hiderelated').prop('active', storage.hideRelated);
$('#bt-yt-sr-hideshorts').prop('active', storage.hideShorts);
new MutationObserver(function(mutationList, observer) {
const storage = getStorage();
if (storage.hideRelated) {
change('related',true);
}
if (storage.hideShorts) {
change('shorts',true);
}
searchQuery = new URLSearchParams(location.search).get('search_query');
mustInclude = Array.from(searchQuery.matchAll(/"([^"]+)"/g)).map(e => {
return e[1].toLowerCase();
});
loopThroughResults(mustInclude);
}).observe($('#contents.ytd-section-list-renderer')[0], { childList: true, subtree: true });
$('#bt-yt-sr-hidewatched').on('change', (event) => {
const elem = $(event.currentTarget);
const hide = elem.prop('active');
const storage = getStorage();
storage.hideWatched = hide;
setStorage(storage);
loopThroughResults(mustInclude);
});
$('#bt-yt-sr-hiderelated').on('change', (event) => {
const elem = $(event.currentTarget);
const hide = elem.prop('active');
const storage = getStorage();
storage.hideRelated = hide;
setStorage(storage);
change('related',hide);
});
$('#bt-yt-sr-hideshorts').on('change', (event) => {
const elem = $(event.currentTarget);
const hide = elem.prop('active');
const storage = getStorage();
storage.hideShorts = hide;
setStorage(storage);
change('shorts',hide);
loopThroughResults(mustInclude);
});
});
};
fileref.setAttribute("src", 'https://code.jquery.com/jquery-3.6.1.min.js');
@yash33391234
Copy link

quick q, how do i get your script to work with GM? do i need to pass the default values in your script?

@Ellivers
Copy link
Author

quick q, how do i get your script to work with GM? do i need to pass the default values in your script?

Ah, this is for Violentmonkey. I'm not sure how you'd make it work with GM.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment