您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Add quick quick filter buttons to tab menu. Adds 6h,12h,2w buttons (fetch+filter 1 page per second).
// ==UserScript== // @name Old Reddit Top Filters (1h,6h,12h,24h,W,2W,M,Y,all) // @description Add quick quick filter buttons to tab menu. Adds 6h,12h,2w buttons (fetch+filter 1 page per second). // @version 2.2 // @author C89sd // @namespace https://gf.qytechs.cn/users/1376767 // @match https://old.reddit.com/* // @noframes // ==/UserScript== const MS_TABLE = { h: 3600e3, d: 86400e3, w: 604800e3, m: 2592e6, y: 31536e6 }; const BUTTONS = [ { lbl: '1h', t: 'hour', filter: '' }, //{ lbl: '3h', t: 'day', filter: '3h' }, // may scrape too many pages on large subs //{ lbl: '4h', t: 'day', filter: '4h' }, { lbl: '6h', t: 'day', filter: '6h' }, { lbl: '12h', t: 'day', filter: '12h'}, { lbl: '24h', t: 'day', filter: '' }, { lbl: 'W', t: 'week', filter: '' }, { lbl: '2W', t: 'month', filter: '2w' }, { lbl: 'M', t: 'month', filter: '' }, //{ lbl: '3M', t: 'year', filter: '3m' }, // may scrape too many pages on large subs //{ lbl: '6M', t: 'year', filter: '6m' }, { lbl: 'Y', t: 'year', filter: '' }, { lbl: 'all', t: 'all', filter: '' }, ]; const FILTER_REGEX = /#filter=(\d+)([hdwmy])/i; const MIN_POSTS = 25; const FETCH_DELAY_MS = 750; window.filterClick = function filterClick(e){ const hrefClean = e.currentTarget.href.replace(/#.*/,''); const hereClean = location.href.replace(/#.*/,''); if (hrefClean === hereClean) setTimeout(() => location.reload(), 100); }; const tabMenu = document.querySelector('.tabmenu'); if (tabMenu) { let fetchController = new AbortController(); window.addEventListener('pagehide', () => fetchController.abort()); const { origin, pathname } = window.location; const isFrontOrAllPage = pathname === '/' || pathname.startsWith('/r/all'); const pathPrefix = (pathname.match(/^(\/r\/[^/]+|\/user\/[^/]+\/m\/[^/]+)/) || [''])[0]; const baseUrl = `${origin}${pathPrefix}/top/?sort=top`; const styleTag = document.createElement('style'); styleTag.textContent = '.ggray { filter: saturate(0.1) !important; }'; document.head.appendChild(styleTag); const tMatch = location.search.match(/[?&]t=([^&#]+)/i); const curT = tMatch ? tMatch[1] : ''; const curFilterRx = location.hash.match(FILTER_REGEX); const curFilter = curFilterRx ? curFilterRx[1] + curFilterRx[2] : ''; const buttonsHTML = BUTTONS .filter(btn => !(isFrontOrAllPage && btn.t === 'year')) .map(btn => { const url = `${baseUrl}&t=${btn.t}`; const href = btn.filter ? `${url}#filter=${btn.filter}` : url; const click = btn.filter ? 'onclick="filterClick(event)"' : ''; const isSel = curT === btn.t && curFilter === btn.filter; const liCls = isSel ? 'selected' : (btn.filter ? 'ggray' : ''); return `<li class="${liCls}"><a ${click} href="${href}">${btn.lbl}</a></li>`; }) .join(''); tabMenu.insertAdjacentHTML('beforeend', buttonsHTML); const runCustomFilter = () => { const hashMatch = window.location.hash.match(FILTER_REGEX); if (!hashMatch) return; const siteTable = document.getElementById('siteTable'); if (!siteTable) return; fetchController.abort(); fetchController = new AbortController(); const { signal } = fetchController; const [, amount, unit] = hashMatch; const cutoffTimestamp = Date.now() - parseInt(amount, 10) * MS_TABLE[unit.toLowerCase()]; const loader = document.createElement('div'); loader.style.cssText = 'padding: 15px; font-weight: bold; display: none;'; siteTable.insertAdjacentElement('afterend', loader); const navButtons = document.querySelector('#siteTable .nav-buttons'); if (navButtons) siteTable.insertAdjacentElement('afterend', navButtons); const isTooOld = p => (p.dataset.timestamp || 0) < cutoffTimestamp; const filterPosts = () => siteTable.querySelectorAll('.thing[data-timestamp]').forEach(p => isTooOld(p) && p.remove()); const updateNext = href => { const nextLink = document.querySelector('.next-button a'); if (nextLink) { if (href) nextLink.href = href.replace(/#.*/, '') + window.location.hash; else nextLink.parentElement.remove(); } }; const fetchPage = async url => { const startTime = Date.now(); const html = await (await fetch(url, { credentials: 'include', signal })).text(); const doc = new DOMParser().parseFromString(html, 'text/html'); const endTime = Date.now(); const duration = endTime - startTime; const remainingDelay = Math.max(0, FETCH_DELAY_MS - duration); if (remainingDelay > 0) { await new Promise(r => setTimeout(r, remainingDelay)); } return { posts: doc.querySelectorAll('#siteTable .thing'), next : doc.querySelector('.next-button a')?.href || '' }; }; (async () => { filterPosts(); let nextUrl = document.querySelector('.next-button a')?.href; let fetchCount = 0; while (document.querySelectorAll('#siteTable .thing').length < MIN_POSTS && nextUrl) { if (signal.aborted) break; loader.textContent = `⏳ Filtering and loading more posts... ${++fetchCount}`; loader.style.display = 'block'; try { const { posts, next } = await fetchPage(nextUrl); posts.forEach(p => siteTable.appendChild(p)); filterPosts(); nextUrl = next; updateNext(nextUrl); } catch (err) { if (err.name !== 'AbortError') { loader.textContent = 'An error occurred while loading posts.'; console.error('[Reddit Filter Userscript] Fetch Error:', err); } break; } } loader.style.display = 'none'; })(); }; window.runCustomFilter = runCustomFilter; window.addEventListener('pageshow', e => { if (!e.persisted) runCustomFilter(); }); }
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址