(forceRefresh)
| 167 | /** 清理历史:删除超过7天未更新的记录;条数超上限时再清除最旧的 */ |
| 168 | function pruneHistory() { |
| 169 | const now = Date.now(); |
| 170 | const list = loadHistory(); |
| 171 | let kept = list.filter(p => now - (p._ts || 0) < HISTORY_TTL_MS); |
| 172 | let changed = kept.length !== list.length; |
| 173 | if (kept.length > HISTORY_MAX_ENTRIES) { |
| 174 | kept.sort((a, b) => (b._ts || 0) - (a._ts || 0)); |
| 175 | kept = kept.slice(0, HISTORY_MAX_ENTRIES); |
| 176 | changed = true; |
| 177 | } |
| 178 | if (changed) saveHistory(kept); |
| 179 | } |
| 180 | /** 拉取到新数据后合并进历史:同一 postId 用新数据替换老记录并重置时间戳 */ |
| 181 | function mergeHistory(posts) { |
| 182 | if (!posts || posts.length === 0) return; |
| 183 | const now = Date.now(); |
| 184 | const list = loadHistory(); |
| 185 | const map = new Map(); |
| 186 | list.forEach(p => { if (p.postId) map.set(p.postId, p); }); |
| 187 | posts.forEach(p => { |
| 188 | if (!p.postId) return; |
| 189 | // 新数据替换老数据,时间重新计算 |
| 190 | map.set(p.postId, Object.assign({}, p, { _ts: now })); |
| 191 | }); |
| 192 | let merged = Array.from(map.values()); |
| 193 | // 超过上限:按更新时间从新到旧保留,清除最旧的记录 |
| 194 | if (merged.length > HISTORY_MAX_ENTRIES) { |
| 195 | merged.sort((a, b) => (b._ts || 0) - (a._ts || 0)); |
| 196 | merged = merged.slice(0, HISTORY_MAX_ENTRIES); |
| 197 | } |
| 198 | saveHistory(merged); |
| 199 | } |
| 200 | /** 供外部(统计功能)读取历史数据(已过滤7天前的过期记录) */ |
| 201 | function getHistory() { |
| 202 | const now = Date.now(); |
| 203 | return loadHistory().filter(p => now - (p._ts || 0) < HISTORY_TTL_MS); |
| 204 | } |
| 205 | |
| 206 | // 脚本启动时清理过期和超上限的历史记录 |
| 207 | pruneHistory(); |
| 208 | // 暴露读取接口供外部统计使用:window.getTopReplyHistory() 返回历史全部帖子数据 |
| 209 | window.getTopReplyHistory = getHistory; |
| 210 | |
| 211 | // 从帖子 URL 中提取数字 ID,如 /post-512810-1 返回 512810 |
| 212 | function extractPostId(url) { |
| 213 | const m = url.match(/post-(\d+)/); |
| 214 | return m ? parseInt(m[1], 10) : 0; |
| 215 | } |
| 216 | |
| 217 | // ---- 拉取 & 解析 ---- |
| 218 | function parsePostFromItem(item) { |
| 219 | const titleEl = item.querySelector('.post-title a'); |
| 220 | if (!titleEl) return null; |
| 221 | const title = titleEl.textContent.trim(); |
| 222 | const url = titleEl.getAttribute('href') || ''; |
| 223 | |
| 224 | const authorEl = item.querySelector('.info-author a'); |
| 225 | const author = authorEl ? authorEl.textContent.trim() : ''; |
| 226 |
no test coverage detected