// ==UserScript==
// @name yt blocker
// @version 14
// @description none
// @run-at document-start
// @author rssaromeo
// @license GPLv3
// @match *://youtube.com/*
// @match *://*.youtube.com/*
// @icon data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEgAAABICAMAAABiM0N1AAAAAXNSR0IB2cksfwAAAAlwSFlzAAAOxAAADsQBlSsOGwAAAHJQTFRFAAAAEIijAo2yAI60BYyuF4WaFIifAY6zBI2wB4usGIaZEYigIoiZCIyrE4igG4iYD4mjEomhFoedCoqpDIqnDomlBYyvE4efEYmiDYqlA42xBoytD4mkCYqqGYSUFYidC4qoC4upAo6yCoupDYqmCYur4zowOQAAACZ0Uk5TAO////9vr////1+/D/+/L+/Pf/////+f3///////H4////////+5G91rAAACgUlEQVR4nM2Y22KjIBCGidg1264liZqDadK03X3/V2wNKHMC7MpF/xthHD5mgERAqZhWhfYqH6K+Qf2qNNf625hCoFj9/gblMUi5q5jLkXLCKudgyiRm0FMK82cWJp1fLbV5VmvJbCIc0GCYaFqqlDJgADdBjncqAXYobm1xh72aFMflbysteFfdy2Yi1XGOm5HGBzQ1dq7TzEoxjeNTjQZb7VA3e1c7+ImgasAgQ9+xusNVNZIo5xmOMgihIS2PbCQIiHEUdTvhxCcS/kPomfFI2zHy2PkWmA6aNatIJpKFJyekyy02xh5Y3DI9T4aOT6VhIUrsNTFp1pf79Z4SIIVDegl6IJO6cHiL/GimIZDhgTu/BlYWCQzHMl0zBWT/T3KAhtxOuUB9FtBrpsz0RV4xsjHmW+UCaffcSy/5viMGer0/6HdFNMZBq/vjJL38H9Dqx4Fuy0Em12DbZy+9pGtiDijbglwAehyj11n0tRD3WUBm+lwulE/8h4BuA+iWAQQnteg2Xm63WQLTpnMnpjdge0Mgu/GRPsV4xdjQ94Lfi624fabhDkfUqIKNrM64Q837v8yL0prasepCgrtvw1sJpoqanGEX7b5mQboNW8eawXaWXTMfMGxub472hzWzHSn6Sg2G9+6TAyRruE71s+zAzjWaknoyJCQzwxrghH2k5FDT4eqWunuNxyN9QCGcxVod5oADbYnIUkDTGZEf1xDJnSFteQ3KdsT8zYDMQXcHxsevcLH1TrsABzkNPyA/L7b0jg704viMMlpQI96WsHknCt/3YH0kOEo9zcGkwrFK39ck72rmoehmKqo2RKlilzSy/nJKEV45CT38myJp456fezktHjN5aeMAAAAASUVORK5CYII=
// @grant unsafeWindow
// @require https://update.greasyfork.org/scripts/491829/1356221/tampermonkey%20storage%20proxy.js
// @grant GM_getValue
// @grant GM_setValue
// @grant unsafeWindow
// @namespace https://greasyfork.org/users/1184528
// ==/UserScript==
// % of video watched to hide, 0 to not hide any
const hideWatchedVidProg = 60
;(async () => {
const a = loadlib("allfuncs")
const sp = new storageproxy("globaloptions")
var ls = sp.get()
// var lastvol // stores the last volume to restore to when muting from sub button border
var vidlock = true
const LOC = {}
updateLoc()
// var LOADED = false
function setVidSpeed() {
unsafeWindow.novidspeedcontroller=true
for (var vid of a.qsa("video")) {
vid.playbackRate = vidlock
? 0
: Number(!globalname ? 0 : localStorage.playrate ?? 0)
}
}
ls.blockedCreators ??= []
ls.blockedTitles ??= []
ls.blockedTitlesReg ??= []
ls.blockedCreatorsReg ??= []
if (LOC.watch) {
var fastint = setInterval(setVidSpeed, 0)
setVidSpeed()
update()
await a.waitforelem(
"#channel-name>#container>#text-container>yt-formatted-string>a"
)
clearInterval(fastint)
}
setInterval(update, 1000)
// LOADED = true
var globalname
function newBlockBtn(title, creator) {
var elem = a.newelem("button", {
innerHTML: ls.blockedCreators.includes(this.title)
? "unblock"
: "block",
creator,
title,
id: "blockbtn",
onclick(e) {
e.stopImmediatePropagation()
e.stopPropagation()
e.preventDefault()
log(this.creator)
if (ls.blockedCreators.includes(this.creator)) {
ls.blockedCreators.splice(
ls.blockedCreators.indexOf(this.creator),
1
)
} else {
ls.blockedCreators.push(this.creator)
}
update()
log(ls.blockedCreators, this.creator)
},
oncontextmenu(e) {
e.stopImmediatePropagation()
e.stopPropagation()
e.preventDefault()
log(this.title)
if (ls.blockedTitles.includes(this.title)) {
ls.blockedTitles.splice(
ls.blockedTitles.indexOf(this.title),
1
)
} else {
ls.blockedTitles.push(this.title)
}
update()
log(ls.blockedTitles, this.title)
},
})
;((elem, creator) => {
var val = creator
Object.defineProperty(elem, "creator", {
get() {
return val
},
set(newval) {
val = newval.replace(/ • \d+\w? views$/, "")
},
enumerable: true,
configurable: true,
})
})(elem, creator)
return elem
}
update()
function update() {
try {
updateLoc()
unsafeWindow.ls = ls = sp.get()
if (LOC.search) {
addVid(
"div#dismissible.style-scope.ytd-video-renderer",
"#video-title",
"#text > a",
"#channel-info"
)
} else if (LOC.root) {
globalname = null
addVid(
"ytd-rich-item-renderer.style-scope.ytd-rich-grid-renderer:has(#video-title-link>yt-formatted-string#video-title):has(#details>#meta>ytd-video-meta-block>#metadata>#byline-container>ytd-channel-name#channel-name>#container>#text-container>yt-formatted-string#text>a)",
"#video-title-link>yt-formatted-string#video-title",
"#details>#meta>ytd-video-meta-block>#metadata>#byline-container>ytd-channel-name#channel-name>#container>#text-container>yt-formatted-string#text>a",
"#details>#meta>ytd-video-meta-block:has(#additional-metadata-line):has(#metadata)"
)
} else if (LOC.feed) {
addVid(
"#dismissible:has(#video-title)",
"#video-title",
"#container>#text-container>yt-formatted-string#text",
"#byline-container"
)
} else if (LOC.userhome || LOC.uservids) {
const CREATOR = a.qs(
"#page-header > yt-page-header-renderer > yt-page-header-view-model > div > div.page-header-view-model-wiz__page-header-headline > div > yt-dynamic-text-view-model > h1 > span"
)?.textContent
const btn = a.qs(
"#page-header > yt-page-header-renderer > yt-page-header-view-model > div > div.page-header-view-model-wiz__page-header-headline > div > yt-dynamic-text-view-model > h1 > #blockbtn"
)
if (
a.qs(
"#page-header > yt-page-header-renderer > yt-page-header-view-model > div > div.page-header-view-model-wiz__page-header-headline > div > yt-dynamic-text-view-model > h1"
) &&
!btn
) {
a.qs(
"#page-header > yt-page-header-renderer > yt-page-header-view-model > div > div.page-header-view-model-wiz__page-header-headline > div > yt-dynamic-text-view-model > h1"
).appendChild(newBlockBtn(null, CREATOR))
} else if (btn) {
btn.innerHTML = isBlocked(btn.creator, btn.title)
? "unblock - " +
JSON.stringify(isBlocked(btn.creator, btn.title))
: "block"
}
if (LOC.userhome) {
addVid(
"#dismissible:has(#video-title)",
"#video-title",
{
raw: CREATOR,
},
"#byline-container"
)
addVid(
"#dismissible:has(#video-title)",
"#video-title",
"#container>#text-container>yt-formatted-string#text",
"#byline-container"
)
}
if (LOC.uservids) {
addVid(
"ytd-rich-item-renderer:has(#dismissible #video-title)",
"#video-title",
{
raw: CREATOR,
},
"#meta > h3"
)
}
} else if (LOC.watch) {
if (!a.qs("#playrate") && a.qs(".ytp-right-controls")) {
a.qs(".ytp-right-controls").appendChild(
a.newelem(
"div",
{
display: "inline flex",
flexDirection: "row",
id: "playrate",
class:
"ytp-button ytp-settings-button ytp-hd-quality-badge",
minWidth: "200xp",
Width: "200xp",
},
[
a.newelem("button", {
innerHTML: "1",
onclick() {
localStorage.playrate = 1
update()
},
}),
a.newelem("button", {
innerHTML: "2",
onclick() {
localStorage.playrate = 2
update()
},
}),
]
)
)
}
globalname = a.qs(
"#upload-info>ytd-channel-name#channel-name>#container>#text-container>yt-formatted-string#text > a"
)?.textContent
if (
a.qs("#upload-info") &&
a.qs("#title > h1 > span.cbCustomTitle")
) {
if (a.qs("#upload-info>#blockbtn")) {
a.qs("#upload-info>#blockbtn").creator = globalname
a.qs("#upload-info>#blockbtn").title=a.qs("#title > h1 > span.cbCustomTitle").textContent||a.qs("#title > h1 > yt-formatted-string").textContent
} else {
a.qs("#upload-info").appendChild(
newBlockBtn(
a.qs("#title > h1 > span.cbCustomTitle").textContent||a.qs("#title > h1 > yt-formatted-string").textContent,
globalname
)
)
}
const btn = a.qs("#upload-info>#blockbtn")
vidlock = isBlocked(btn.creator, btn.title)
btn.innerHTML = isBlocked(btn.creator, btn.title)
? "unblock - " +
JSON.stringify(isBlocked(btn.creator, btn.title))
: "block"
}
addVid(
"ytd-compact-video-renderer:has(#dismissible #video-title)",
"#video-title",
"#container>#text-container>yt-formatted-string#text",
"#metadata"
)
addVid(
"#movie_player > div.html5-endscreen.ytp-player-content.videowall-endscreen.ytp-show-tiles > div > a:has(span.ytp-videowall-still-info)",
"span.ytp-videowall-still-info > span > span>div>.cbCustomTitle",
"span.ytp-videowall-still-info > span > span>.ytp-videowall-still-info-author",
"span.ytp-videowall-still-info > span > span>div"
)
setVidSpeed()
}
} catch (e) {
trace("update", e)
}
}
function addVid(
mainDivID,
titleID,
creatorID,
blockButtonParentID
) {
try {
// remove invalid block buttons on root
// if (isroot())
// a.qsa("#blockbtn")
// .filter(function (btn) {
// return btn.closest(blockButtonParentID)
// })
// .forEach((e) => e.remove())
for (var viddiv of a.qsa(mainDivID)) {
var btn
if (
(btn = a.qs(blockButtonParentID + ">#blockbtn", viddiv))
) {
btn.title = titleID.raw ?? a.qs(titleID, viddiv).textContent
btn.creator =
creatorID.raw ?? a.qs(creatorID, viddiv).textContent
btn.innerHTML = ls.blockedCreators.includes(btn.creator)
? "unblock"
: "block"
} else {
btn = a
.qs(blockButtonParentID, viddiv)
.appendChild(
newBlockBtn(
titleID.raw ?? a.qs(titleID, viddiv).textContent,
creatorID.raw ?? a.qs(creatorID, viddiv).textContent
)
)
}
var prog = a.qs(
".ytd-thumbnail-overlay-resume-playback-renderer.style-scope",
viddiv
)
viddiv.style.display = isBlocked(btn.creator, btn.title) || (hideWatchedVidProg && prog && prog.style.width.replace("%", "") > hideWatchedVidProg)
? "none"
: ""
}
} catch (e) {
trace("addVid", e)
}
}
unsafeWindow.isBlocked = isBlocked
function isBlocked(creator, title) {
try {
if (ls.blockedTitles.includes(title))
return { type: "blockedTitles", val: title }
if (ls.blockedCreators.includes(creator))
return { type: "blockedCreators", val: creator }
for (let reg of ls.blockedCreatorsReg) {
if (new RegExp(reg, "i").test(creator))
return { type: "blockedCreatorsReg", val: reg }
}
for (let reg of ls.blockedTitlesReg) {
if (new RegExp(reg, "i").test(title))
return { type: "blockedTitlesReg", val: reg }
}
return false
} catch (e) {
trace("isBlocked", e)
}
}
function updateLoc() {
Object.assign(LOC, {
root: /^https?:\/\/(?:www\.)?youtube\.com\/?(?:\?|#|$)/.test(
location.href
),
watch:
/^https?:\/\/(?:www\.)?youtube\.com\/watch\/?(?:\?|#|$)/.test(
location.href
),
search:
/^https?:\/\/(?:www\.)?youtube\.com\/results\?search_query=.*(?:#|$)/.test(
location.href
),
feed: /^https?:\/\/(?:www\.)?youtube\.com\/feed\/subscriptions/.test(
location.href
),
userhome:
/^https?:\/\/(?:www\.)?youtube\.com\/@[^\/]+\/?$/.test(
location.href
),
uservids:
/^https?:\/\/(?:www\.)?youtube\.com\/@[^\/]+\/videos\/?$/.test(
location.href
),
})
}
})()