Last active
June 23, 2024 16:44
-
-
Save Ellivers/9d7beaa66590ce719c1d8c333d6cfaa1 to your computer and use it in GitHub Desktop.
Better YouTube Search Control
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// ==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'); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Ah, this is for Violentmonkey. I'm not sure how you'd make it work with GM.