// ==UserScript==
// @name yt blocker
// @version 18
// @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
const rclickBlocksUrl = true
const rclickBlocksTitle = true
;(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 ??= []
ls.blockedUrls ??= []
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()
if (rclickBlocksUrl){
log(this.url)
if (ls.blockedUrls.includes(this.url)) {
ls.blockedUrls.splice(
ls.blockedUrls.indexOf(this.url),
1
)
} else {
ls.blockedUrls.push(this.url)
}
update()
log(ls.blockedUrls, this.url)
}
if (rclickBlocksTitle){
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:has(a#video-title)",
"a#video-title",
"#video-title",
"#text > a",
"#channel-info"
)
} else if (LOC.root) {
globalname = null
addVid(
"ytd-rich-item-renderer:has(#video-title-link):has(a.yt-simple-endpoint.style-scope.yt-formatted-string)",
"#video-title-link",
"#video-title:not(.cbCustomTitle)",
"a.yt-simple-endpoint.style-scope.yt-formatted-string",
"#details>#meta>ytd-video-meta-block:has(#additional-metadata-line):has(#metadata)"
)
} else if (LOC.feed) {
addVid(
"#dismissible:has(#video-title-link)",
"#video-title-link",
"#video-title-link>yt-formatted-string:not(.cbCustomTitle)",
"#container>#text-container>yt-formatted-string#text>a",
"#byline-container"
)
} else if (LOC.userhome || LOC.uservids) {
const CREATOR = location.href
?.split("/@")
?.at(-1)
?.split("/")?.[0]
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, btn.url)
? "unblock - " +
JSON.stringify(
isBlocked(btn.creator, btn.title, btn.url)
)
: "block"
}
if (LOC.userhome) {
addVid(
"#dismissible:has(#video-title-link)",
"#video-title-link",
"#video-title-link",
{
raw: CREATOR,
},
"#byline-container"
)
addVid(
"#dismissible:has(#video-title-link)",
"#video-title-link",
"#video-title-link",
"#container>#text-container>yt-formatted-string#text",
"#byline-container"
)
}
if (LOC.uservids) {
addVid(
"ytd-rich-item-renderer:has(#dismissible #video-title-link)",
"#video-title-link",
"#video-title-link",
{
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("ytd-video-owner-renderer") &&
a.qs("#title > h1 > span.cbCustomTitle")
) {
addVid(
"ytd-watch-metadata",
{
raw: location.href.split("?v=").at(-1).split("&")[0],
},
"#title > h1 > yt-formatted-string",
"#container>#text-container>yt-formatted-string#text>a",
"ytd-video-owner-renderer"
)
a.qs("ytd-watch-metadata").style.display = ""
const btn = a.qs("ytd-video-owner-renderer>#blockbtn")
vidlock = isBlocked(btn.creator, btn.title, btn.url)
btn.innerHTML = isBlocked(btn.creator, btn.title, btn.url)
? "unblock - " +
JSON.stringify(
isBlocked(btn.creator, btn.title, btn.url)
)
: "block"
}
// these don't have creator id anywhere only creator name so all will be hidden
// addVid(
// "ytd-compact-video-renderer:has(#dismissible #video-title-link)",
// "#video-title-link",
// "#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"
// )
// new youtube display classes?
a.qsa(
"yt-lockup-view-model:has(yt-lockup-metadata-view-model)"
).forEach((e) => (e.style.visibility = "hidden"))
// addVid(
// "yt-lockup-view-model:has(yt-lockup-metadata-view-model)",
// "div.yt-lockup-metadata-view-model-wiz__text-container > h3 > a",
// "yt-content-metadata-view-model > div:nth-child(1) > span",
// ".yt-lockup-view-model-wiz__metadata:has(yt-lockup-metadata-view-model)"
// )
setVidSpeed()
}
} catch (e) {
trace("update", e)
}
}
function addVid(
mainDivID,
url,
titleID,
creatorID,
blockButtonParentID
) {
try {
// log(mainDivID, a.qsa(mainDivID))
// 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 = a.qs(blockButtonParentID + ">#blockbtn", viddiv)
if (!btn)
btn = a
.qs(blockButtonParentID, viddiv)
.appendChild(newBlockBtn("", ""))
btn.url =
url.raw ??
a.qs(url, viddiv).href.split("?v=").at(-1).split("&")[0]
btn.title = titleID.raw ?? a.qs(titleID, viddiv).textContent
btn.creator =
creatorID.raw ??
(a.qs(creatorID, viddiv).href.match(/(?:\/@|\/channel\/)(.*)/)[1])
btn.innerHTML = ls.blockedCreators.includes(btn.creator)
? "unblock"
: "block"
var prog =
a.qs(
".ytd-thumbnail-overlay-resume-playback-renderer.style-scope",
viddiv
) ||
a.qs(
".ytThumbnailOverlayProgressBarHostWatchedProgressBarSegment",
viddiv
)
viddiv.style.display =
isBlocked(btn.creator, btn.title, btn.url) ||
(hideWatchedVidProg &&
prog &&
prog.style.width.replace("%", "") > hideWatchedVidProg)
? "none"
: ""
}
} catch (e) {
trace("addVid", e, titleID, creatorID, viddiv)
}
}
unsafeWindow.isBlocked = isBlocked
function isBlocked(creator, title, url) {
try {
if (ls.blockedUrls.includes(url))
return { type: "blockedTitles", val: title }
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
),
})
}
})()