yt blocker

none

// ==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
        ),
    })
  }
})()