Youtube - Hide Livestreams in Subscriptions

Simply hides all videos that were produced by livestreams and livestreams themselves from your subscriptions feed.

当前为 2025-07-13 提交的版本,查看 最新版本

// ==UserScript==
// @name        Youtube - Hide Livestreams in Subscriptions
// @description Simply hides all videos that were produced by livestreams and livestreams themselves from your subscriptions feed.
// @namespace   azzurite.tv
// @match       https://www.youtube.com/feed/subscriptions
// @grant       none
// @version     1.0
// @author      Azzurite
// @license     GPLv3
// ==/UserScript==

function hasLiveTag(card) {
    return [...card.querySelectorAll(`p`)].some(elem => elem.textContent === `LIVE`);
}

function hasStreamedMetadata(card) {
    return card.querySelector(`#metadata-line`)?.textContent.includes(`Streamed`);
}

function isFromLivestream(card) {
    return hasLiveTag(card) || hasStreamedMetadata(card);
}

function fixLayoutAfterRemoving(feed) {


    (function shiftUp() {
        const items = [...feed.children];
        const idx = items.findLastIndex(item => item.tagName.toLowerCase() === `ytd-rich-section-renderer`)
        const shorts = items[idx];
        let toShiftUp = 7 - idx;
        let i = idx + 1;
        for (let i = idx + 1; toShiftUp !== 0; ++i, --toShiftUp) {
            feed.insertBefore(items[i], shorts);
        }
    })();
    (function fixFirstOfColumn() {
        const items = [...feed.querySelectorAll(`ytd-rich-item-renderer`)];
        for (let i = 0; i !== items.length; ++i) {
            const item = items[i];
            if (i % 3 === 0) {
                if (!item.hasAttribute(`is-in-first-column`)) item.setAttribute(`is-in-first-column`);
            } else {
                item.removeAttribute(`is-in-first-column`);
            }
        }
    })();
}

setInterval(() => {
    const feed = document.querySelector(`#contents`);
    if (!feed) {
        return;
    }

    const items = [...document.querySelectorAll(`#contents > ytd-rich-item-renderer`)];
    const shorts = document.querySelectorAll(`#contents > ytd-rich-section-renderer`)[1];
    for (let i = 0; i < items.length; ++i) {
        const cur = items[i];
        if (isFromLivestream(cur)) {
            cur.remove();
        }
    }

    fixLayoutAfterRemoving(feed);
}, 500);