// ==UserScript== // @name OAO-FC26 UT模式翻译插件 // @namespace https://github.com/ // @version 1.8.16 // @description 中文翻译Futbin、Futgg网站的英文信息,包括球员信息、进化名称等 // @author 我要欧啊欧 // @match https://www.fut.gg/* // @match https://fut.gg/* // @match https://www.futbin.com/* // @match https://futbin.com/* // @match https://www.easysbc.io/* // @match https://easysbc.io/* // @match https://www.ea.com/ea-sports-fc/ultimate-team/web-app/* // @match https://www.easports.com/*/ea-sports-fc/ultimate-team/web-app/* // @match https://www.ea.com/*/ea-sports-fc/ultimate-team/web-app/* // @connect gitee.com // @connect github.com // @connect cdn.jsdelivr.net // @connect rawcdn.githack.com // @connect giteeusercontent.com // @connect raw.githubusercontent.com // @connect example.com // @connect open.feishu.cn // @connect scriptcat.org // @grant GM_xmlhttpRequest // @grant GM_setValue // @grant GM_getValue // @license MIT // ==/UserScript== (() => { 'use strict'; console.log('[OAO] 脚本开始执行'); console.log('[OAO] 当前页面:', window.location.href); console.log('[OAO] 当前域名:', window.location.hostname); // 存储相关函数 function getStorageValue(key) { try { const value = GM_getValue(key, null); return value ? JSON.parse(value) : null; } catch (error) { // console.warn('Failed to get storage value:', error); return null; } } // 设置缓存 function setStorageValue(key, value) { try { GM_setValue(key, JSON.stringify(value)); } catch (error) { // console.warn('Failed to set storage value:', error); } } const _s = 'OAO-FC26-v1.5.0-20260325'; const _c = getStorageValue('oaevo_code_signature'); if (!_c || _c !== _s) { setStorageValue('oaevo_code_signature', _s); } const _k = 'OAO-FC26-2026'; function _e(data) { const _t = JSON.stringify(data); const _x = []; for (let i = 0; i < _t.length; i++) { _x.push(_t.charCodeAt(i) ^ _k.charCodeAt(i % _k.length)); } return btoa(String.fromCharCode(..._x)); } function _d0(encryptedStr) { try { const _y = atob(encryptedStr); const _z = []; for (let i = 0; i < _y.length; i++) { _z.push(_y.charCodeAt(i) ^ _k.charCodeAt(i % _k.length)); } return JSON.parse(String.fromCharCode(..._z)); } catch (error) { return null; } } // ========== 配置 ========== const USE_SHORTEN_TERMS = true; const SHOW_ORIGINAL_WITH_BRACKETS = false; const LOCATION_CHECK_INTERVAL_MS = 10000; // 从3秒改为10秒,降低检查频率 const EVOLUTIONS_STORAGE_KEY = 'oaevo_evolutions_dict_cache'; const THREE_HOURS_MS = 60 * 1000; // 1分钟 const SIX_HOURS_MS = 5 * 60 * 1000; // 5分钟 // 多数据源配置(优先使用 Gitee,国内访问更快) const EVOLUTIONS_DICT_URLS = [ 'https://gitee.com/rickma11/OAO-evotrans/raw/master/evolutions1.json?inline=true', // 主数据源(Gitee) 'https://raw.githubusercontent.com/rickma11/OAO-evotrans/refs/heads/main/evolutions.json', // 备用数据源(GitHub) 'https://cdn.jsdelivr.net/gh/rickma11/OAO-evotrans@main/evolutions.json', // CDN 数据源 'https://rawcdn.githack.com/rickma11/OAO-evotrans/main/evolutions.json' // CDN 数据源 ]; // 内置翻译字典多数据源配置 const BUILT_IN_DICTIONARIES_URLS = [ 'https://gitee.com/rickma11/OAO-evotrans/raw/master/built-in-dictionaries.json', // 主数据源(Gitee) 'https://raw.githubusercontent.com/rickma11/OAO-evotrans/refs/heads/main/built-in-dictionaries.json', // 备用数据源(GitHub) 'https://cdn.jsdelivr.net/gh/rickma11/OAO-evotrans@main/built-in-dictionaries.json' // CDN 数据源 ]; const BUILT_IN_DICTIONARIES_STORAGE_KEY = 'oaevo_built_in_dictionaries_cache'; const REMOTE_EVOLUTIONS_DICT_URL = EVOLUTIONS_DICT_URLS[0]; // 主数据源 const SIDEBAR_ID = 'oaevo-sidebar'; const SIDEBAR_DOCK_ID = 'oaevo-sidebar-dock'; const SIDEBAR_PANEL_ID = 'oaevo-sidebar-panel'; const SIDEBAR_BUTTON_CLASS = 'oaevo-sidebar-btn'; const FUTGG_TRANSLATION_ENABLED_KEY = 'oaevo_futgg_translation_enabled'; const FUTBIN_TRANSLATION_ENABLED_KEY = 'oaevo_futbin_translation_enabled'; const EASYSBC_TRANSLATION_ENABLED_KEY = 'oaevo_easysbc_translation_enabled'; const EVOLUTION_FORMAT_KEY = 'oaevo_evolution_format'; // 0: 中文(英文), 1: 来源中文, 2: 英文 const SIDEBAR_HIDDEN_KEY = 'oaevo_sidebar_hidden'; // 侧边栏隐藏状态(桌面端用户偏好) const MOBILE_EXPANDED_KEY = 'oaevo_mobile_expanded'; // 移动端用户是否显式展开侧边栏 const FLOAT_ICON_POSITION_KEY = 'oaevo_float_icon_position'; // 悬浮图标位置 // 版本检查配置 const SCRIPTCAT_SCRIPT_URL = 'https://scriptcat.org/zh-CN/script-show-page/5488'; const VERSION_MANIFEST_URL = 'https://gitee.com/rickma11/OAO-evotrans/raw/master/version.json'; const VERSION_CHECK_KEY = 'oaevo_last_version_check_date'; const VERSION_CHECK_INTERVAL = 24 * 60 * 60 * 1000; // 24小时检查一次 const NEW_VERSION_KEY = 'oaevo_new_version_available'; // 存储新版本信息 const LAST_VERSION_PROMPT_KEY = 'oaevo_last_version_prompt'; // 弹窗频率控制:每版本每天只弹一次 // 更新内容配置 const UPDATE_CONTENT_URL = 'https://gitee.com/rickma11/OAO-evotrans/raw/master/catch-evo.json'; const LAST_UPDATE_CHECK_KEY = 'oaevo_last_update_check_date'; // 最后检查更新内容的日期 const UPDATE_CONTENT_KEY = 'oaevo_update_content_cache'; // 缓存更新内容 // 已安装版本记录(用于“覆盖升级”时触发存储迁移) const INSTALLED_VERSION_KEY = 'oaevo_installed_version'; // 按版本自修复:覆盖升级(不删除旧文件)时,GM 存储中的偏好不会自动清空, // 可能残留会阻塞移动端浮标的旧状态(如旧版误写的 MOBILE_EXPANDED_KEY=true)。 // 当检测到的脚本版本与上次记录不一致时,清除该阻塞项,使覆盖升级等价于“干净重装”的移动端 UI 状态。 // 注意:仅清理移动端浮标相关的 MOBILE_EXPANDED_KEY;桌面端 SIDEBAR_HIDDEN_KEY、 // 用户的自定义词条、进化显示格式等其它偏好均予以保留。 function migrateStorageOnUpgrade() { try { const current = (typeof GM_info !== 'undefined' && GM_info.script && GM_info.script.version) ? GM_info.script.version : null; if (!current) return; const last = getStorageValue(INSTALLED_VERSION_KEY); if (last === current) return; // 同版本,无需迁移 // 清除会阻塞移动端悬浮图标的旧状态 setStorageValue(MOBILE_EXPANDED_KEY, false); setStorageValue(INSTALLED_VERSION_KEY, current); } catch (e) { // 迁移失败不应影响主流程 } } migrateStorageOnUpgrade(); // 全局变量存储新版本信息 let newVersionInfo = null; /** * 统一获取当前脚本版本号(双保险) * 方法1: GM_info.script.version(Tampermonkey/Violentmonkey 原生 API) * 方法2: 从页面