-
-
Save mohemohe/072df94b9e1f9c90ebfe5778be60e784 to your computer and use it in GitHub Desktop.
YouTubeのクソいチャンネルをいい感じに隠すUserScript
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 YoutubeChannelBlock | |
// @namespace dev.mohemohe.block.channel.youtube | |
// @version 11 | |
// @description fuck channel | |
// @author mohemohe | |
// @match https://www.youtube.com/* | |
// @require https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.min.js | |
// @grant GM.getValue | |
// @grant GM.setValue | |
// ==/UserScript== | |
const channelRegex = /\/(c([^\/]*)|user)\/([^\/]*)\/?/; | |
const targetElemName = [ | |
"ytd-rich-grid-media", | |
"ytd-video-owner-renderer", | |
"ytd-video-renderer", | |
"ytd-comment-renderer", | |
]; | |
class YoutubeChannelBlock { | |
constructor() { | |
this.toggleLock = false; | |
this.channelIdName = {}; | |
this.lastChannelIds = []; | |
} | |
async exec() { | |
await this.mark(); | |
await this.attachCss(); | |
} | |
async toggleBlockChannel(channelId) { | |
if (this.toggleLock) { | |
return; | |
} | |
this.toggleLock = true; | |
let channelIds = await GM.getValue("channelIds", []); | |
if (channelIds.includes(channelId)) { | |
console.log("[YoutubeChannelBlock]", "remove channel:", channelId); | |
channelIds = channelIds.filter((cid) => cid !== channelId); | |
this.removeCss(channelId); | |
} else { | |
console.log("[YoutubeChannelBlock]", "add channel:", channelId, this.channelIdName[channelId]); | |
channelIds.push(channelId); | |
} | |
await GM.setValue("channelIds", channelIds); | |
await this.attachCss(); | |
this.toggleLock = false; | |
} | |
async mark() { | |
let targets = []; | |
targetElemName.some((selector) => { | |
const t = document.querySelectorAll(`${selector}:not([data-channel_id])`); | |
if (t) { | |
[...t].forEach((e) => { | |
if (e.dataset.selector !== selector) { | |
e.dataset.selector = selector; | |
} | |
}); | |
targets.push(...[...t]); | |
return !["/watch", "/results"].includes(location.pathname); | |
} | |
return false; | |
}) | |
if (targets.length === 0) { | |
return; | |
} | |
const channelIds = await GM.getValue("channelIds", []); | |
for (const target of [...targets]) { | |
let a = target.querySelector(`a[href*='/channel/']`); | |
if (!a) { | |
a = target.querySelector(`a[href*='/c/']`); | |
} | |
if (!a) { | |
a = target.querySelector(`a[href*='/user/']`); | |
} | |
if (!a) { | |
continue; | |
} | |
const { href } = a; | |
const channelId = href.match(channelRegex); | |
if (!channelId) { | |
continue; | |
} | |
target.channelName = a.textContent; | |
target.channelId = channelId[3]; | |
this.channelIdName[target.channelId] = target.channelName; | |
if (target.dataset.channel_id !== target.channelId) { | |
target.dataset.channel_id = target.channelId; | |
const currentButton = target.querySelector(".ycb_block"); | |
if (currentButton) { | |
currentButton.remove(); | |
} | |
const button = document.createElement("button"); | |
button.innerText = "ブロック切り替え"; | |
// button.style.position = "absolute"; | |
// button.style.bottom = "0px"; | |
button.style.borderRadius = "2px"; | |
button.style.padding = "2px 15px"; | |
if (["/watch", "/results"].includes(location.pathname)) { | |
button.style.height = "41px"; | |
button.style.marginRight = "4px"; | |
} | |
button.style.color = "#ffa566"; | |
button.style.border = "1px solid #ffa566"; | |
button.style.background = "transparent"; | |
button.style.cursor = "pointer"; | |
button.style.alignItems = "center"; | |
button.addEventListener("click", () => this.toggleBlockChannel(target.channelId)); | |
const wrapper = document.createElement("div"); | |
wrapper.className = "ycb_block"; | |
// wrapper.style.position = "relative"; | |
wrapper.style.display = "flex"; | |
wrapper.style.justifyContent = "flex-end"; | |
wrapper.style.alignItems = "center"; | |
wrapper.appendChild(button); | |
target.insertAdjacentElement("beforeend", wrapper); | |
} | |
} | |
} | |
async attachCss() { | |
const channelIds = await GM.getValue("channelIds", []); | |
const currentCsses = [...document.querySelectorAll(".ycb_blockChannelCss")]; | |
channelIds.forEach((channelId) => { | |
const nextCss = ` | |
[data-channel_id='${channelId}'] * { | |
display: none !important; | |
} | |
[data-channel_id='${channelId}']:before { | |
content: ${`"blocked: ${this.channelIdName[channelId]} (${channelId})"`.replaceAll("\n", "")}; | |
font-size: 1.2rem; | |
display: block !important; | |
color: white; | |
} | |
[data-channel_id='${channelId}'] .ycb_block, | |
[data-channel_id='${channelId}'] .ycb_block * { | |
display: flex !important; | |
} | |
`; | |
const currentCss = currentCsses.find((t) => t.dataset.channel_id === channelId); | |
if (currentCss) { | |
if (currentCss.originalCss !== nextCss) { | |
currentCss.textContent = nextCss; | |
currentCss.originalCss = nextCss; | |
} | |
} else { | |
const style = document.createElement("style"); | |
style.classList.add("ycb_blockChannelCss"); | |
style.dataset.channel_id = channelId; | |
style.textContent = nextCss; | |
style.originalCss = nextCss; | |
document.body.insertAdjacentElement("beforeend", style); | |
} | |
}); | |
const systemCss = document.querySelector(`#ycb_systemCss`); | |
if (!systemCss) { | |
const style = document.createElement("style"); | |
style.id = "ycb_systemCss"; | |
style.textContent = ` | |
#paid-comment-images { | |
display: none !important; | |
} | |
`; | |
document.body.insertAdjacentElement("beforeend", style); | |
} | |
} | |
async removeCss(channelId) { | |
const currentCss = document.querySelector(`.ycb_blockChannelCss[data-channel_id='${channelId}']`); | |
if (currentCss) { | |
currentCss.remove(); | |
} | |
} | |
} | |
function main() { | |
const ycb = new YoutubeChannelBlock(); | |
const watch = new MutationObserver(_.debounce((changes) => { | |
console.debug("[YoutubeChannelBlock]", "changes:", changes); | |
ycb.exec(changes); | |
}), 1000); | |
const pre = new MutationObserver(_.debounce((changes) => { | |
const ypm = document.querySelector('ytd-page-manager'); | |
if (ypm) { | |
watch.observe(ypm, { | |
childList: true, | |
subtree: true, | |
}); | |
pre.disconnect(); | |
} | |
}), 250); | |
const body = document.querySelector('body'); | |
pre.observe(body, { | |
childList: true, | |
subtree: true, | |
}); | |
} | |
window.addEventListener("load", () => { | |
main(); | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment