楼主

// ==UserScript==
// @name Linux SB 已读帖子灰显
// @namespace https://linux.sb/
// @version 1.0.0
// @description 将看过的 Linux SB 帖子标题灰显;已读记录 60 天后自动清理。
// @author Cindy
// @match https://linux.sb/*
// @grant GM_registerMenuCommand
// @run-at document-start
// ==/UserScript==
(() => {
'use strict';
const STORAGE_KEY = 'linuxSbReadTopicsV1';
const RETENTION_DAYS = 60;
const MAX_ENTRIES = 3000;
const CLEANUP_INTERVAL_MS = 24 * 60 * 60 * 1000;
const TOPIC_PATH = /^\/topic\/(\d+)(?:\/|$)/;
function readStore() {
try {
const stored = JSON.parse(localStorage.getItem(STORAGE_KEY) || '{}');
return stored && typeof stored === 'object' ? stored : {};
} catch {
return {};
}
}
function writeStore(store) {
localStorage.setItem(STORAGE_KEY, JSON.stringify(store));
}
function topicKey(url = location.href) {
const { pathname } = new URL(url, location.origin);
const match = pathname.match(TOPIC_PATH);
return match ? `/topic/${match[1]}` : null;
}
function prune(store, now = Date.now()) {
const expiresAt = now - RETENTION_DAYS * 24 * 60 * 60 * 1000;
const entries = Object.entries(store)
.filter(([key, timestamp]) => TOPIC_PATH.test(key) && Number.isFinite(timestamp) && timestamp >= expiresAt)
.sort(([, left], [, right]) => right - left)
.slice(0, MAX_ENTRIES);
return Object.fromEntries(entries);
}
function markCurrentTopicRead() {
const key = topicKey();
if (!key) return;
const store = readStore();
store[key] = Date.now();
writeStore(prune(store));
}
function installStyle() {
const style = document.createElement('style');
style.id = 'linux-sb-read-marker-style';
style.textContent = `
.post-title.linux-sb-read-marker {
color: #9ca3af !important;
opacity: 0.72;
}
.post-title.linux-sb-read-marker:hover {
color: #6b7280 !important;
opacity: 1;
}
`;
document.documentElement.append(style);
}
function renderReadTopics() {
const store = prune(readStore());
writeStore(store);
for (const link of document.querySelectorAll('a.post-title[href]')) {
const key = topicKey(link.href);
link.classList.toggle('linux-sb-read-marker', Boolean(key && store[key]));
}
}
function resetReadTopics() {
localStorage.removeItem(STORAGE_KEY);
renderReadTopics();
}
function start() {
markCurrentTopicRead();
installStyle();
renderReadTopics();
const observer = new MutationObserver(renderReadTopics);
observer.observe(document.body, { childList: true, subtree: true });
window.setInterval(renderReadTopics, CLEANUP_INTERVAL_MS);
}
if (typeof GM_registerMenuCommand === 'function') {
GM_registerMenuCommand('清空 Linux SB 已读记录', resetReadTopics);
}
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', start, { once: true });
} else {
start();
}
})();虽然写一下很简单,给大家省点token