Skip to content

Instantly share code, notes, and snippets.

@kphrx
Last active May 27, 2025 06:54
Show Gist options
  • Save kphrx/eb4290150bc7556af95eac2c89965cbe to your computer and use it in GitHub Desktop.
Save kphrx/eb4290150bc7556af95eac2c89965cbe to your computer and use it in GitHub Desktop.
// ==UserScript==
// @name YouTube block user comment
// @namespace https://kpherox.dev
// @version 1.1.1
// @downloadURL https://gist.github.com/kphrx/eb4290150bc7556af95eac2c89965cbe/raw/youtube-comment-block.user.js
// @updateURL https://gist.github.com/kphrx/eb4290150bc7556af95eac2c89965cbe/raw/youtube-comment-block.meta.js
// @author kPherox
// @description block user comment
// @noframes
// ==/UserScript==
// ==UserScript==
// @name YouTube block user comment
// @namespace https://kpherox.dev
// @match https://www.youtube.com/*
// @grant GM.addStyle
// @grant GM_addStyle
// @grant GM_getValue
// @grant GM_getValues
// @grant GM_setValue
// @grant GM_listValues
// @grant GM_deleteValue
// @version 1.1.1
// @downloadURL https://gist.github.com/kphrx/eb4290150bc7556af95eac2c89965cbe/raw/youtube-comment-block.user.js
// @updateURL https://gist.github.com/kphrx/eb4290150bc7556af95eac2c89965cbe/raw/youtube-comment-block.meta.js
// @author kPherox
// @description block user comment
// @noframes
// ==/UserScript==
const config = new class {
#blockedCache = null;
get #values() {
return GM_listValues().filter((key) => {
return key.startsWith('/channel/') || key === 'blocked';
});
}
get blockedList() {
if (this.#blockedCache == null) {
this.#blockedCache = GM_getValues(this.#values);
}
return this.#blockedCache;
}
get #requireMigrate() {
return this.#values.includes("blocked");
}
migrate() {
if (this.#requireMigrate) {
for (const blocked of GM_getValue('blocked', [])) {
GM_setValue(blocked.channelUrl, blocked.handle);
}
GM_deleteValue('blocked');
}
}
block({channelUrl, handle}) {
this.#blockedCache[channelUrl] = handle;
GM_setValue(channelUrl, handle);
GM_addStyle(`
ytd-comment-thread-renderer:has(> ytd-comment-view-model > #body > div#author-thumbnail > button#author-thumbnail-button[aria-label="${handle}"]),
ytd-comment-replies-renderer ytd-comment-view-model:has(
> #body > #author-thumbnail > #author-thumbnail-button[aria-label="${handle}"],
> #body > #main > #expander > #content > #content-text a.yt-core-attributed-string__link[href="${channelUrl}"]
) {
display: none;
}
`);
}
};
config.migrate();
Promise.all(Object.entries(config.blockedList).map(([channelUrl, handle]) => {
return GM.addStyle(`
ytd-comment-thread-renderer:has(> ytd-comment-view-model > #body > div#author-thumbnail > button#author-thumbnail-button[aria-label="${handle}"]),
ytd-comment-replies-renderer ytd-comment-view-model:has(
> #body > #author-thumbnail > #author-thumbnail-button[aria-label="${handle}"],
> #body > #main > #expander > #content > #content-text a.yt-core-attributed-string__link[href="${channelUrl}"]
) {
display: none;
}
`);
})).then(console.debug);
const blockUserFn = (handle, channelUrl) => ((ev) => {
config.block({handle, channelUrl});
});
const watchMultiPageMenu = new MutationObserver((records, observer) => {
for (const record of records) {
if (record.type !== "childList" || record.addedNodes.length === 0) {
continue;
}
const profileIdentityInfoView = Array.from(record.addedNodes).find(node => node.nodeName.toLowerCase() === 'yt-profile-identity-info-view-model');
if (profileIdentityInfoView == null) {
continue;
}
const profileIdentityInfo = profileIdentityInfoView.__instance.props.data;
const channelBannerContainer = profileIdentityInfoView.querySelector('.yt-profile-identity-info-view-model-wiz__channel-banner-container');
const wrapButton = channelBannerContainer.appendChild(document.createElement('div'));
wrapButton.classList.add('yt-profile-identity-info-view-model-wiz__wrap-button');
wrapButton.style.paddingLeft = '16px';
const button = wrapButton.appendChild(document.createElement('div'));
button.classList.add('yt-profile-identity-info-view-model-wiz__button');
const buttonViewModel = button.appendChild(document.createElement('div'));
buttonViewModel.classList.add('yt-spec-button-view-model');
const buttonShape = buttonViewModel.appendChild(document.createElement('a'));
buttonShape.classList.add('yt-spec-button-shape-next', 'yt-spec-button-shape-next--tonal', 'yt-spec-button-shape-next--mono', 'yt-spec-button-shape-next--size-m');
const buttonText = buttonShape.appendChild(document.createElement('div'));
buttonText.classList.add('yt-spec-button-shape-next__button-text-content');
buttonText.textContent = 'Block';
const listener = blockUserFn(profileIdentityInfo.channelHandle, profileIdentityInfo.channelAccess.buttonViewModel.onTap.innertubeCommand.commandMetadata.webCommandMetadata.url);
buttonShape.addEventListener('click', listener);
}
});
new MutationObserver((records, observer) => {
const ytdMultiPageMenu = document.querySelector('#sections.ytd-multi-page-menu-renderer');
if (ytdMultiPageMenu == null) {
return;
}
observer.disconnect();
watchMultiPageMenu.observe(ytdMultiPageMenu, {childList: true, subtree: true});
}).observe(document.body, {childList: true});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment