// ==UserScript== // @name Linux.do Credit Display // @namespace http://tampermonkey.net/ // @version 2.1 // @description 显示 linux.do 基础积分,支持手动计算差值 // @author You // @match https://linux.do/* // @grant GM_xmlhttpRequest // @grant GM_setValue // @grant GM_getValue // @connect credit.linux.do // @downloadURL none // ==/UserScript== (function() { 'use strict'; const TRANSACTIONS_API = 'https://credit.linux.do/api/v1/order/transactions'; const LEADERBOARD_URL = 'https://linux.do/leaderboard'; const STORAGE_KEY = 'linux_do_credit_cache'; // 获取今天的时间范围 function getTodayRange() { const now = new Date(); const y = now.getFullYear(); const m = String(now.getMonth() + 1).padStart(2, '0'); const d = String(now.getDate()).padStart(2, '0'); return { startTime: `${y}-${m}-${d}T00:00:00+08:00`, endTime: `${y}-${m}-${d}T23:59:59+08:00` }; } // 从 remark 解析积分: "社区积分从 1877 更新到 1938,变化 61" -> 1938 function parseScore(remark) { const match = remark.match(/更新到\s*(\d+)/); return match ? parseInt(match[1], 10) : null; } // 获取今日基础积分 function fetchBaseScore() { return new Promise((resolve, reject) => { const { startTime, endTime } = getTodayRange(); GM_xmlhttpRequest({ method: 'POST', url: TRANSACTIONS_API, headers: { 'Content-Type': 'application/json' }, data: JSON.stringify({ page: 1, page_size: 20, startTime, endTime }), onload: (res) => { try { const data = JSON.parse(res.responseText); const orders = data.data?.orders || []; for (const item of orders) { if (item.remark?.includes('社区积分')) { const score = parseScore(item.remark); if (score !== null) { resolve(score); return; } } } reject(new Error('未找到积分记录')); } catch (e) { reject(e); } }, onerror: reject }); }); } // 检查缓存是否有效(当天有效) function getCachedScore() { const cache = GM_getValue(STORAGE_KEY, null); if (cache && cache.date === new Date().toDateString()) { return cache.score; } return null; } // 保存缓存 function setCachedScore(score) { GM_setValue(STORAGE_KEY, { score, date: new Date().toDateString() }); } // 创建 UI function createUI(baseScore) { const container = document.createElement('div'); container.id = 'linux-do-credit'; container.style.cssText = ` position: fixed; bottom: 20px; right: 20px; background: #fff; color: #333; padding: 10px 14px; border-radius: 8px; font-size: 14px; z-index: 9999; box-shadow: 0 2px 12px rgba(0,0,0,0.15); display: flex; flex-direction: column; gap: 8px; `; container.innerHTML = `