yt blocker

none

  1. // ==UserScript==
  2. // @name yt blocker
  3. // @version 20
  4. // @description none
  5. // @run-at document-start
  6. // @author rssaromeo
  7. // @license GPLv3
  8. // @match *://youtube.com/*
  9. // @match *://*.youtube.com/*
  10. // @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=
  11. // @grant unsafeWindow
  12. // @require https://update.gf.qytechs.cn/scripts/491829/1356221/tampermonkey%20storage%20proxy.js
  13. // @grant GM_getValue
  14. // @grant GM_setValue
  15. // @grant unsafeWindow
  16. // @namespace https://gf.qytechs.cn/users/1184528
  17. // ==/UserScript==
  18.  
  19. // % of video watched to hide, 0 to not hide any
  20. const hideWatchedVidProg = 1
  21.  
  22. const rclickBlocksUrl = true
  23. const rclickBlocksTitle = true
  24.  
  25. ;(async () => {
  26. const a = loadlib("allfuncs")
  27. const sp = new storageproxy("globaloptions")
  28. var ls = sp.get()
  29. // var lastvol // stores the last volume to restore to when muting from sub button border
  30. var vidlock = true
  31. const LOC = {}
  32. updateLoc()
  33.  
  34. // var LOADED = false
  35. function setVidSpeed() {
  36. unsafeWindow.novidspeedcontroller = true
  37. for (var vid of a.qsa("video")) {
  38. vid.playbackRate = vidlock
  39. ? 0
  40. : Number(!globalname ? 0 : localStorage.playrate ?? 0)
  41. }
  42. }
  43. ls.blockedCreators ??= []
  44. ls.blockedTitles ??= []
  45. ls.blockedTitlesReg ??= []
  46. ls.blockedCreatorsReg ??= []
  47. ls.blockedUrls ??= []
  48. if (LOC.watch) {
  49. var fastint = setInterval(setVidSpeed, 0)
  50. setVidSpeed()
  51. update()
  52. await a.waitforelem(
  53. "#channel-name>#container>#text-container>yt-formatted-string>a"
  54. )
  55. clearInterval(fastint)
  56. }
  57. setInterval(update, 1000)
  58. // LOADED = true
  59. var globalname
  60. function newBlockBtn(title, creator) {
  61. var elem = a.newelem("button", {
  62. innerHTML: ls.blockedCreators.includes(this.title)
  63. ? "unblock"
  64. : "block",
  65. creator,
  66. title,
  67. id: "blockbtn",
  68. onclick(e) {
  69. e.stopImmediatePropagation()
  70. e.stopPropagation()
  71. e.preventDefault()
  72. log(this.creator)
  73. if (ls.blockedCreators.includes(this.creator)) {
  74. ls.blockedCreators.splice(
  75. ls.blockedCreators.indexOf(this.creator),
  76. 1
  77. )
  78. } else {
  79. ls.blockedCreators.push(this.creator)
  80. }
  81. update()
  82. log(ls.blockedCreators, this.creator)
  83. },
  84. oncontextmenu(e) {
  85. e.stopImmediatePropagation()
  86. e.stopPropagation()
  87. e.preventDefault()
  88. if (rclickBlocksUrl){
  89. log(this.url)
  90. if (ls.blockedUrls.includes(this.url)) {
  91. ls.blockedUrls.splice(
  92. ls.blockedUrls.indexOf(this.url),
  93. 1
  94. )
  95. } else {
  96. ls.blockedUrls.push(this.url)
  97. }
  98. update()
  99. log(ls.blockedUrls, this.url)
  100. }
  101. if (rclickBlocksTitle){
  102. log(this.title)
  103. if (ls.blockedTitles.includes(this.title)) {
  104. ls.blockedTitles.splice(
  105. ls.blockedTitles.indexOf(this.title),
  106. 1
  107. )
  108. } else {
  109. ls.blockedTitles.push(this.title)
  110. }
  111. update()
  112. log(ls.blockedTitles, this.title)
  113. }
  114. },
  115. })
  116. ;((elem, creator) => {
  117. var val = creator
  118. Object.defineProperty(elem, "creator", {
  119. get() {
  120. return val
  121. },
  122. set(newval) {
  123. val = newval.replace(/ • \d+\w? views$/, "")
  124. },
  125. enumerable: true,
  126. configurable: true,
  127. })
  128. })(elem, creator)
  129. return elem
  130. }
  131. update()
  132. function update() {
  133. try {
  134. updateLoc()
  135. unsafeWindow.ls = ls = sp.get()
  136.  
  137. if (LOC.search) {
  138. addVid(
  139. "div#dismissible.style-scope.ytd-video-renderer:has(a#video-title)",
  140. "a#video-title",
  141. "#video-title",
  142. "#text > a",
  143. "#channel-info"
  144. )
  145. } else if (LOC.root) {
  146. globalname = null
  147. addVid(
  148. "ytd-rich-item-renderer:has(#video-title-link):has(a.yt-simple-endpoint.style-scope.yt-formatted-string)",
  149. "#video-title-link",
  150. "#video-title:not(.cbCustomTitle)",
  151. "a.yt-simple-endpoint.style-scope.yt-formatted-string",
  152. "#details>#meta>ytd-video-meta-block:has(#additional-metadata-line):has(#metadata)"
  153. )
  154. } else if (LOC.feed) {
  155. addVid(
  156. "#dismissible:has(#video-title-link)",
  157. "#video-title-link",
  158. "#video-title-link>yt-formatted-string:not(.cbCustomTitle)",
  159. "#container>#text-container>yt-formatted-string#text>a",
  160. "#byline-container"
  161. )
  162. } else if (LOC.userhome || LOC.uservids) {
  163. const CREATOR = location.href
  164. ?.match?.(/(?:\/@|\/(?:channel|user)\/)(.*)/)?.[1]
  165. const btn = a.qs(
  166. "#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"
  167. )
  168. if (
  169. a.qs(
  170. "#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"
  171. ) &&
  172. !btn
  173. ) {
  174. a.qs(
  175. "#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"
  176. ).appendChild(newBlockBtn(null, CREATOR))
  177. } else if (btn) {
  178. btn.innerHTML = isBlocked(btn.creator, btn.title, btn.url)
  179. ? "unblock - " +
  180. JSON.stringify(
  181. isBlocked(btn.creator, btn.title, btn.url)
  182. )
  183. : "block"
  184. }
  185. if (LOC.userhome) {
  186. addVid(
  187. "#dismissible:has(#video-title-link)",
  188. "#video-title-link",
  189. "#video-title-link",
  190. {
  191. raw: CREATOR,
  192. },
  193. "#byline-container"
  194. )
  195. addVid(
  196. "#dismissible:has(#video-title-link)",
  197. "#video-title-link",
  198. "#video-title-link",
  199. "#container>#text-container>yt-formatted-string#text",
  200. "#byline-container"
  201. )
  202. }
  203. if (LOC.uservids) {
  204. addVid(
  205. "ytd-rich-item-renderer:has(#dismissible #video-title-link)",
  206. "#video-title-link",
  207. "#video-title-link",
  208. {
  209. raw: CREATOR,
  210. },
  211. "#meta > h3"
  212. )
  213. }
  214. } else if (LOC.watch) {
  215. if (!a.qs("#playrate") && a.qs(".ytp-right-controls")) {
  216. a.qs(".ytp-right-controls").appendChild(
  217. a.newelem(
  218. "div",
  219. {
  220. display: "inline flex",
  221. flexDirection: "row",
  222. id: "playrate",
  223. class:
  224. "ytp-button ytp-settings-button ytp-hd-quality-badge",
  225. minWidth: "200xp",
  226. Width: "200xp",
  227. },
  228. [
  229. a.newelem("button", {
  230. innerHTML: "1",
  231. onclick() {
  232. localStorage.playrate = 1
  233. update()
  234. },
  235. }),
  236. a.newelem("button", {
  237. innerHTML: "2",
  238. onclick() {
  239. localStorage.playrate = 2
  240. update()
  241. },
  242. }),
  243. ]
  244. )
  245. )
  246. }
  247. globalname = a.qs(
  248. "#upload-info>ytd-channel-name#channel-name>#container>#text-container>yt-formatted-string#text > a"
  249. )?.textContent
  250. if (
  251. a.qs("ytd-video-owner-renderer") &&
  252. a.qs("#title > h1 > span.cbCustomTitle")
  253. ) {
  254. addVid(
  255. "ytd-watch-metadata",
  256. {
  257. raw: location.href.split("?v=").at(-1).split("&")[0],
  258. },
  259. "#title > h1 > yt-formatted-string",
  260. "#container>#text-container>yt-formatted-string#text>a",
  261. "ytd-video-owner-renderer"
  262. )
  263. a.qs("ytd-watch-metadata").style.display = ""
  264. const btn = a.qs("ytd-video-owner-renderer>#blockbtn")
  265. vidlock = isBlocked(btn.creator, btn.title, btn.url)
  266. btn.innerHTML = isBlocked(btn.creator, btn.title, btn.url)
  267. ? "unblock - " +
  268. JSON.stringify(
  269. isBlocked(btn.creator, btn.title, btn.url)
  270. )
  271. : "block"
  272. }
  273.  
  274. // these don't have creator id anywhere only creator name so all will be hidden
  275.  
  276. // addVid(
  277. // "ytd-compact-video-renderer:has(#dismissible #video-title-link)",
  278. // "#video-title-link",
  279. // "#container>#text-container>yt-formatted-string#text",
  280. // "#metadata"
  281. // )
  282. // these also don't have creator data
  283. // addVid(
  284. // "#movie_player > div.html5-endscreen.ytp-player-content.videowall-endscreen.ytp-show-tiles > div > a:has(span.ytp-videowall-still-info)",
  285. // "span.ytp-videowall-still-info > span > span>div>.cbCustomTitle",
  286. // "span.ytp-videowall-still-info > span > span>.ytp-videowall-still-info-author",
  287. // "span.ytp-videowall-still-info > span > span>div"
  288. // )
  289. // new youtube display classes?
  290. a.qsa(
  291. "yt-lockup-view-model:has(yt-lockup-metadata-view-model)"
  292. ).forEach((e) => (e.style.visibility = "hidden"))
  293. a.qsa(
  294. ".ytp-videowall-still"
  295. ).forEach((e) => (e.style.visibility = "hidden"))
  296. // addVid(
  297. // "yt-lockup-view-model:has(yt-lockup-metadata-view-model)",
  298. // "div.yt-lockup-metadata-view-model-wiz__text-container > h3 > a",
  299. // "yt-content-metadata-view-model > div:nth-child(1) > span",
  300. // ".yt-lockup-view-model-wiz__metadata:has(yt-lockup-metadata-view-model)"
  301. // )
  302. setVidSpeed()
  303. }
  304. } catch (e) {
  305. trace("update", e)
  306. }
  307. }
  308.  
  309. function addVid(
  310. mainDivID,
  311. url,
  312. titleID,
  313. creatorID,
  314. blockButtonParentID
  315. ) {
  316. try {
  317. // log(mainDivID, a.qsa(mainDivID))
  318. // remove invalid block buttons on root
  319. // if (isroot())
  320. // a.qsa("#blockbtn")
  321. // .filter(function (btn) {
  322. // return btn.closest(blockButtonParentID)
  323. // })
  324. // .forEach((e) => e.remove())
  325. for (var viddiv of a.qsa(mainDivID)) {
  326. var btn = a.qs(blockButtonParentID + ">#blockbtn", viddiv)
  327. if (!btn)
  328. btn = a
  329. .qs(blockButtonParentID, viddiv)
  330. .appendChild(newBlockBtn("", ""))
  331. btn.url =
  332. url.raw ??
  333. a.qs(url, viddiv).href.split("?v=").at(-1).split("&")[0]
  334. btn.title = titleID.raw ?? a.qs(titleID, viddiv).textContent
  335. btn.creator =
  336. creatorID.raw ??
  337. (a.qs(creatorID, viddiv).href.match(/(?:\/@|\/(?:channel|user)\/)(.*)/)[1])
  338. btn.innerHTML = ls.blockedCreators.includes(btn.creator)
  339. ? "unblock"
  340. : "block"
  341. var prog =
  342. a.qs(
  343. ".ytd-thumbnail-overlay-resume-playback-renderer.style-scope",
  344. viddiv
  345. ) ||
  346. a.qs(
  347. ".ytThumbnailOverlayProgressBarHostWatchedProgressBarSegment",
  348. viddiv
  349. )
  350.  
  351. viddiv.style.display =
  352. isBlocked(btn.creator, btn.title, btn.url) ||
  353. (hideWatchedVidProg &&
  354. prog &&
  355. prog.style.width.replace("%", "") > hideWatchedVidProg)
  356. ? "none"
  357. : ""
  358. }
  359. } catch (e) {
  360. trace("addVid", e, titleID, creatorID, viddiv)
  361. }
  362. }
  363. unsafeWindow.isBlocked = isBlocked
  364. unsafeWindow.addVid = addVid
  365. function isBlocked(creator, title, url) {
  366. try {
  367. if (ls.blockedUrls.includes(url))
  368. return { type: "blockedUrls", val: url }
  369. if (ls.blockedTitles.includes(title))
  370. return { type: "blockedTitles", val: title }
  371. if (ls.blockedCreators.includes(creator))
  372. return { type: "blockedCreators", val: creator }
  373. for (let reg of ls.blockedCreatorsReg) {
  374. if (new RegExp(reg, "i").test(creator))
  375. return { type: "blockedCreatorsReg", val: reg }
  376. }
  377. for (let reg of ls.blockedTitlesReg) {
  378. if (new RegExp(reg, "i").test(title))
  379. return { type: "blockedTitlesReg", val: reg }
  380. }
  381. return false
  382. } catch (e) {
  383. trace("isBlocked", e)
  384. }
  385. }
  386. function updateLoc() {
  387. Object.assign(LOC, {
  388. root: /^https?:\/\/(?:www\.)?youtube\.com\/?(?:\?|#|$)/.test(
  389. location.href
  390. ),
  391. watch:
  392. /^https?:\/\/(?:www\.)?youtube\.com\/watch\/?(?:\?|#|$)/.test(
  393. location.href
  394. ),
  395. search:
  396. /^https?:\/\/(?:www\.)?youtube\.com\/results\?search_query=.*(?:#|$)/.test(
  397. location.href
  398. ),
  399. feed: /^https?:\/\/(?:www\.)?youtube\.com\/feed\/subscriptions/.test(
  400. location.href
  401. ),
  402. userhome:
  403. /^https?:\/\/(?:www\.)?youtube\.com\/@[^\/]+\/?$/.test(
  404. location.href
  405. ),
  406. uservids:
  407. /^https?:\/\/(?:www\.)?youtube\.com\/@[^\/]+\/videos\/?$/.test(
  408. location.href
  409. ),
  410. })
  411. }
  412. })()

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址