您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Sorts the YouTube feed so that all scheduled streams come before uploaded videos.
当前为
// ==UserScript== // @name YT Feed Sorter // @namespace YTFeedSorter // @version 0.6.2 // @description Sorts the YouTube feed so that all scheduled streams come before uploaded videos. // @match *://*.youtube.com/* // @author KFP // ==/UserScript== (function() { 'use strict'; let feedSorted = false; const feedGridSelector = 'ytd-browse[page-subtype="subscriptions"][role="main"] #contents.ytd-rich-grid-renderer'; const feedListSelector = 'ytd-browse[page-subtype="subscriptions"][role="main"] #contents.ytd-section-list-renderer'; const liveSelector = '.badge-style-type-live-now-alternate'; const soonSelector = 'ytd-toggle-button-renderer'; const sortFeed = feed => { try{ const isList = feed.classList.contains('ytd-section-list-renderer'); if (isList) { [...feed.children].sort((a, b) => { const aInner = a.root.querySelector('ytd-shelf-renderer').root.querySelector('ytd-expanded-shelf-contents-renderer').root.querySelector('ytd-video-renderer'); const bInner = b.root.querySelector('ytd-shelf-renderer').root.querySelector('ytd-expanded-shelf-contents-renderer').root.querySelector('ytd-video-renderer'); const aLive = aInner.querySelector('ytd-badge-supported-renderer:not([hidden])')?.root.querySelector(liveSelector); const aSoon = aInner.querySelector(soonSelector); const bLive = bInner.querySelector('ytd-badge-supported-renderer:not([hidden])')?.root.querySelector(liveSelector); const bSoon = bInner.querySelector(soonSelector); const ai = aLive ? 2 : aSoon ? 1 : 0; const bi = bLive ? 2 : bSoon ? 1 : 0; return (ai > bi) ? -1 : (ai < bi) ? 1 : 0; }).forEach(item => feed.appendChild(item)); } else { const rows = feed.querySelectorAll('ytd-rich-grid-row'); let currentRowI = 0; let currentRow = rows[0].querySelector('#contents'); let rowLength = currentRow.children.length; let items = []; rows.forEach(row => { const rowItems = row.querySelectorAll('ytd-rich-item-renderer'); items = items.concat([...rowItems]); }); items.sort((a, b) => { const aInner = a.querySelector('ytd-rich-grid-media'); const bInner = b.querySelector('ytd-rich-grid-media'); const aLive = aInner.querySelector('.video-badge:not([hidden])')?.root.querySelector(liveSelector); const aSoon = aInner.querySelector(soonSelector); const bLive = bInner.querySelector('.video-badge:not([hidden])')?.root.querySelector(liveSelector); const bSoon = bInner.querySelector(soonSelector); const ai = aLive ? 2 : aSoon ? 1 : 0; const bi = bLive ? 2 : bSoon ? 1 : 0; return (ai > bi) ? -1 : (ai < bi) ? 1 : 0; }).forEach((item, i) => { currentRow.appendChild(item); if (i && ((i + 1) % rowLength === 0)) { currentRowI++; if (rows[currentRowI]) { currentRow = rows[currentRowI].querySelector('#contents'); } } }); } } catch(e) { console.log(e); } }; const gridObserver = new MutationObserver(mutations => { for (const mut of mutations) { if (mut.removedNodes?.length) { setTimeout(() => sortFeed(mut.target), 200); setTimeout(() => sortFeed(mut.target), 2000); setTimeout(() => sortFeed(mut.target), 4000); } } }); let listObserverTimer = 0; const listObserver = new MutationObserver(mutations => { for (const mut of mutations) { if (mut.addedNodes?.length) { const now = Date.now(); if (now - listObserverTimer > 5200) { setTimeout(() => sortFeed(mut.target), 200); setTimeout(() => sortFeed(mut.target), 5000); listObserverTimer = now; } } } }); let pageChanged = false; setInterval(() => { let isList = false; let feed = document.querySelector(feedGridSelector); if (!feed) { feed = document.querySelector(feedListSelector); if (feed) isList = true; } if (feed) { if (feedSorted) return; if (isList) { setTimeout(() => sortFeed(feed), 200); setTimeout(() => sortFeed(feed), 2000); listObserver.observe(feed, {childList: true}); } else { if (pageChanged) { setTimeout(() => sortFeed(feed), 1000); setTimeout(() => sortFeed(feed), 3000); setTimeout(() => sortFeed(feed), 6000); } else { setTimeout(() => sortFeed(feed), 1); } gridObserver.observe(feed, {childList: true}); } feedSorted = true; } else if (feedSorted) { gridObserver.disconnect(); listObserver.disconnect(); pageChanged = true; feedSorted = false; } }, 100); })();