// ==UserScript== // @name Twitter/X Pro (CTO领哥版 V10.5) // @namespace http://tampermonkey.net/ // @version 10.5 // @description 1.无感VIP标记 2.备注防丢 3.漏翻修复 4.智能翻译 // @author LingGe // @license MIT // @match https://twitter.com/* // @match https://x.com/* // @match https://pro.twitter.com/* // @match https://pro.x.com/* // @match https://tweetdeck.twitter.com/* // @icon https://www.google.com/s2/favicons?sz=64&domain=twitter.com // @grant GM_xmlhttpRequest // @grant GM_addStyle // @grant GM_setValue // @grant GM_getValue // @grant GM_registerMenuCommand // @downloadURL none // ==/UserScript== (function() { 'use strict'; console.log("🚀 领哥情报终端 V10.5 (MIT开源版) 已启动..."); const TARGET_LANG = 'zh-CN'; const GMGN_REF = '1DRFPE0z'; const DEFAULT_CONFIG = { transColor: '#00E676', transFontSize: '14px', noteColor: '#1D9BF0', noteFontSize: '11px', vipBorderColor: '#F3BA2F' }; // 内置初始 VIP 名单 const INITIAL_VIP_MAP = { 'vitalikbuterin': ['🏛️ ETH创始人', '#716b94', '#fff'], 'cz_binance': ['🔶 币安创始人', '#F0B90B', '#000'], 'elonmusk': ['🚀 狗狗教父', '#000000', '#fff'], 'brian_armstrong': ['🛡️ Coinbase CEO', '#0052FF', '#fff'], 'aeyakovenko': ['🟣 Solana创始人', '#9945FF', '#fff'], 'cryptohayes': ['📝 Arthur Hayes', '#444', '#fff'], 'zachxbt': ['🚨 链上侦探', '#FF0000', '#fff'], 'a16z': ['💰 a16z', '#FF6600', '#fff'], 'paradigm': ['🧠 Paradigm', '#000', '#fff'] }; // ================= 1. 存储管理模块 (本地数据库) ================= const Storage = { // 读取配置,如果不存在则使用默认 getConfig: () => ({ ...DEFAULT_CONFIG, ...JSON.parse(GM_getValue('ling_config', '{}')) }), // 保存配置 setConfig: (cfg) => GM_setValue('ling_config', JSON.stringify(cfg)), getNotes: () => JSON.parse(GM_getValue('ling_user_notes', '{}')), setNotes: (notes) => GM_setValue('ling_user_notes', JSON.stringify(notes)), // 安全添加备注:防止误操作 addNote: (handle, note) => { const notes = Storage.getNotes(); const h = handle.toLowerCase(); if (note && note.trim()) { notes[h] = note.trim(); } else { // 如果用户输入空白,且确认要删除,则删除 delete notes[h]; } Storage.setNotes(notes); }, getNote: (handle) => Storage.getNotes()[handle.toLowerCase()] || null, getVips: () => { let vips = JSON.parse(GM_getValue('ling_vips', 'null')); if (!vips) { vips = INITIAL_VIP_MAP; GM_setValue('ling_vips', JSON.stringify(vips)); } return vips; }, setVips: (vips) => GM_setValue('ling_vips', JSON.stringify(vips)), getVipInfo: (handle) => { const vips = Storage.getVips(); return vips[handle.toLowerCase()] || null; }, addVip: (handle, label) => { const vips = Storage.getVips(); vips[handle.toLowerCase()] = [label, '#F3BA2F', '#000']; Storage.setVips(vips); }, removeVip: (handle) => { const vips = Storage.getVips(); delete vips[handle.toLowerCase()]; Storage.setVips(vips); }, // 全量备份:备注 + VIP + 设置 export: () => { const data = { version: "10.5", timestamp: new Date().getTime(), notes: Storage.getNotes(), vips: Storage.getVips(), config: Storage.getConfig() }; const blob = new Blob([JSON.stringify(data)], {type: 'application/json'}); const url = URL.createObjectURL(blob); const a = document.createElement('a'); a.href = url; a.download = `LingGe_Intel_Backup_${new Date().toISOString().slice(0,10)}.json`; a.click(); }, // 恢复备份 import: () => { const input = document.createElement('input'); input.type = 'file'; input.accept = '.json,.txt'; input.onchange = (e) => { const reader = new FileReader(); reader.onload = (event) => { try { const raw = JSON.parse(event.target.result); // 兼容旧版数据结构 if (raw['$myTwitterNoteItems']) { const notes = Storage.getNotes(); for (let k in raw['$myTwitterNoteItems']) { if(raw['$myTwitterNoteItems'][k]?.tag) notes[k.toLowerCase()] = raw['$myTwitterNoteItems'][k].tag; } Storage.setNotes(notes); } else { if(raw.notes) Storage.setNotes({...Storage.getNotes(), ...raw.notes}); if(raw.vips) Storage.setVips({...Storage.getVips(), ...raw.vips}); if(raw.config) Storage.setConfig({...Storage.getConfig(), ...raw.config}); } alert("✅ 数据恢复成功!页面将刷新..."); location.reload(); } catch (err) { alert('❌ 备份文件格式错误'); } }; reader.readAsText(e.target.files[0]); }; input.click(); } }; // ================= 2. 动态样式 (持久化应用) ================= function updateStyles() { const cfg = Storage.getConfig(); const oldStyle = document.getElementById('ling-style'); if (oldStyle) oldStyle.remove(); const css = ` .ling-vip-tweet { border: 2px solid ${cfg.vipBorderColor} !important; background: rgba(243, 186, 47, 0.05) !important; border-radius: 8px !important; } .ling-identity-badge { font-weight: 900; font-size: 10px; padding: 2px 5px; border-radius: 3px; margin-left: 5px; vertical-align: middle; display: inline-block; box-shadow: 0 1px 2px rgba(0,0,0,0.5); color: #000; background: ${cfg.vipBorderColor}; } .ling-trans-box { margin-top: 6px; padding: 8px 10px; background: #000; border: 1px solid ${cfg.transColor}; border-left: 4px solid ${cfg.transColor}; border-radius: 4px; color: ${cfg.transColor} !important; font-size: ${cfg.transFontSize}; line-height: 1.5; font-family: "Consolas", monospace; } .ling-ca-link { color: #F3BA2F !important; font-weight: bold; cursor: pointer; background: rgba(243, 186, 47, 0.15); padding: 0 4px; border-radius: 3px; margin-right: 4px; text-decoration: none !important; } .ling-ca-link:hover { background: rgba(243, 186, 47, 0.4); } .ling-action-btn { cursor: pointer; margin-left: 6px; font-size: 14px; vertical-align: middle; display: inline-block; opacity: 0.4; transition: all 0.2s; filter: grayscale(100%); } .ling-action-btn:hover { opacity: 1; filter: grayscale(0%); transform: scale(1.2); } .ling-action-btn.active { opacity: 1; filter: grayscale(0%); text-shadow: 0 0 8px gold; } .ling-user-note { background-color: ${cfg.noteColor}; color: #fff; font-size: ${cfg.noteFontSize}; padding: 2px 6px; border-radius: 4px; margin-left: 5px; vertical-align: middle; display: inline-block; cursor: pointer; max-width: 150px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; font-weight: bold; } #ling-settings-overlay { position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0,0,0,0.7); z-index: 99999; display: flex; justify-content: center; align-items: center; } #ling-settings-box { background: #16181c; border: 1px solid #333; border-radius: 12px; padding: 20px; width: 300px; color: #fff; } .ling-row { margin-bottom: 15px; display: flex; justify-content: space-between; align-items: center; } .ling-btn { background: #00E676; color: #000; border: none; padding: 8px; border-radius: 5px; width: 100%; font-weight: bold; cursor: pointer; } `; const node = document.createElement('style'); node.id = 'ling-style'; node.innerHTML = css; document.head.appendChild(node); } // ================= 3. 核心逻辑 ================= // 设置菜单 function openSettings() { if (document.getElementById('ling-settings-overlay')) return; const cfg = Storage.getConfig(); const div = document.createElement('div'); div.id = 'ling-settings-overlay'; div.innerHTML = `