您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
B 站经验助手,自动投币视频、模拟移动端分享、经验获取统计、升级时间估计(2025年更新版)
// ==UserScript== // @name NewBilibiliExp // @namespace NewBilibiliExp // @match *://www.bilibili.com/video/* // @version 2.0.2 // @author Dreace (原作者) & Updated by Mario // @license GPL-3.0 // @description B 站经验助手,自动投币视频、模拟移动端分享、经验获取统计、升级时间估计(2025年更新版) // @grant GM.xmlHttpRequest // @grant GM.setValue // @grant GM.getValue // @grant GM.deleteValue // @grant unsafeWindow // @connect api.bilibili.com // @connect www.bilibili.com // @connect at.alicdn.com // @require https://cdn.jsdelivr.net/npm/[email protected]/dist/jquery.min.js // @require https://cdn.jsdelivr.net/npm/[email protected]/js/md5.min.js // ==/UserScript== "use strict"; // 配置选项 const CONFIG = { AUTO_COIN: true, // 是否自动投币 AUTO_SHARE: true, // 是否自动分享 COIN_NUMBER: 1, // 每个视频投币数量 (1 或 2) SHOW_STATS: true, // 是否显示经验统计 AUTO_VIP_EXP: true, // 是否自动获取大会员观看经验 }; // API端点 const API = { NAV: "https://api.bilibili.com/x/web-interface/nav", REWARD: "https://api.bilibili.com/x/member/web/exp/reward", COIN_ADD: "https://api.bilibili.com/x/web-interface/coin/add", SHARE: "https://api.bilibili.com/x/web-interface/share/add", WBI_IMG: "https://api.bilibili.com/x/web-interface/nav", VIP_EXP: "https://api.bilibili.com/x/vip/experience/add", }; // WBI签名相关 const WBI = { img_key: "", sub_key: "", // 初始化WBI密钥 async init() { try { const res = await request({ url: API.WBI_IMG, method: "GET" }); if (res.code === 0 && res.data.wbi_img) { const { img_url, sub_url } = res.data.wbi_img; this.img_key = this.extractKey(img_url); this.sub_key = this.extractKey(sub_url); return true; } return false; } catch (err) { console.error("[BilibiliExp] WBI初始化失败", err); return false; } }, // 从URL提取密钥 extractKey(url) { return url.substring(url.lastIndexOf('/') + 1, url.lastIndexOf('.')); }, // 混合密钥 getMixinKey() { if (!this.img_key || !this.sub_key) return ''; const mixed_key = this.img_key + this.sub_key; const MIXIN_KEY_ORDER = [46, 47, 18, 2, 53, 8, 23, 32, 15, 50, 10, 31, 58, 3, 45, 35, 27, 43, 5, 49, 33, 9, 42, 19, 29, 28, 14, 39, 12, 38, 41, 13]; let result = ''; for (let i = 0; i < MIXIN_KEY_ORDER.length; i++) { if (MIXIN_KEY_ORDER[i] < mixed_key.length) { result += mixed_key[MIXIN_KEY_ORDER[i]]; } } return result; }, // 对参数进行WBI签名 sign(params) { if (!this.img_key || !this.sub_key) { console.error("[BilibiliExp] WBI密钥未初始化"); return params; } // 添加时间戳和随机数 params.wts = Math.floor(Date.now() / 1000); // 对参数排序 const query = Object.keys(params) .sort() .map(key => `${key}=${params[key]}`) .join('&'); // 计算w_rid const wrid = md5(query + this.getMixinKey()); // 返回带签名的参数 return { ...params, w_rid: wrid }; } }; // 用户信息模块 const UserInfo = { // 获取用户信息 async get() { try { const res = await request({ url: API.NAV, method: "GET" }); if (res.code === 0) { return { isLogin: res.data.isLogin, money: res.data.money, uname: res.data.uname, level_info: res.data.level_info, isVip: res.data.vipStatus === 1 || res.data.vip_status === 1, // 检查是否为大会员 vipType: res.data.vipType || res.data.vip_type || 0 // 大会员类型 }; } return null; } catch (err) { console.error("[BilibiliExp] 获取用户信息失败", err); return null; } } }; // 每日奖励模块 const DailyReward = { // 获取每日奖励状态 async getStatus() { try { const res = await request({ url: API.REWARD, method: "GET" }); if (res.code === 0) { // 如果数据不包含level_info,获取用户信息以补充 if (!res.data.level_info) { console.log("[BilibiliExp] 奖励API返回数据不包含等级信息,尝试从用户信息获取"); const userInfo = await UserInfo.get(); if (userInfo && userInfo.level_info) { res.data.level_info = userInfo.level_info; // 添加大会员状态信息 res.data.isVip = userInfo.isVip; res.data.vipType = userInfo.vipType; } else { // 尝试从页面元素获取 res.data.level_info = this.getUserLevelInfo(); // 页面中无法可靠获取大会员状态,设为false res.data.isVip = false; } } // 补充大会员观看经验获取状态 res.data.vipExp = VIPExpModule.hasGotVipExp(); return res.data; } return null; } catch (err) { console.error("[BilibiliExp] 获取每日奖励状态失败", err); return null; } }, // 计算升级所需天数 calculateDaysToUpgrade(rewardInfo) { // 增强防御性检查 if (!rewardInfo || !rewardInfo.level_info) { console.warn("[BilibiliExp] 无法计算升级天数:缺少等级信息"); return 0; } const { current_level, current_exp, next_exp } = rewardInfo.level_info; // 确保所有需要的字段都存在 if (current_level === undefined || current_exp === undefined || next_exp === undefined) { console.warn("[BilibiliExp] 无法计算升级天数:等级信息不完整"); return 0; } if (current_level >= 6) return 0; // 根据是否为大会员确定每日经验值 const exp_per_day = rewardInfo.isVip ? 75 : 65; return Math.ceil((next_exp - current_exp) / exp_per_day); }, // 从页面元素获取用户等级信息 getUserLevelInfo() { // 尝试从页面元素获取等级信息 try { // 尝试从顶部用户信息获取 const levelElement = document.querySelector('.user-level') || document.querySelector('.level-info') || document.querySelector('[class*="level"]'); if (levelElement) { const levelText = levelElement.textContent || ''; const levelMatch = levelText.match(/Lv\.(\d+)/); if (levelMatch && levelMatch[1]) { const level = parseInt(levelMatch[1]); // 创建一个简单的等级信息对象 return { current_level: level, current_exp: 0, next_exp: level >= 6 ? 0 : 1 }; } } // 备选:检查页面中是否有其他地方显示了等级 const pageContent = document.body.textContent || ''; const levelMatches = pageContent.match(/LV\.(\d+)/i) || pageContent.match(/等级[::]?\s*(\d+)/); if (levelMatches && levelMatches[1]) { const level = parseInt(levelMatches[1]); return { current_level: level, current_exp: 0, next_exp: level >= 6 ? 0 : 1 }; } } catch (err) { console.error("[BilibiliExp] 从页面获取等级信息失败", err); } // 如果无法从页面获取,返回默认值 console.log("[BilibiliExp] 无法从页面获取等级信息,使用默认值"); return { current_level: 0, current_exp: 0, next_exp: 1 }; } }; // 投币模块 const CoinModule = { // 给视频投币 async add(aid, num = 1) { if (!aid) return { code: -1, message: "视频ID为空" }; const csrf = getCookie("bili_jct"); if (!csrf) return { code: -1, message: "未获取到CSRF令牌" }; // 准备参数并添加WBI签名 const params = WBI.sign({ aid: aid, multiply: num, select_like: 1, csrf: csrf }); try { const res = await request({ url: API.COIN_ADD, method: "POST", data: params }); return res; } catch (err) { console.error("[BilibiliExp] 投币失败", err); return { code: -1, message: "投币请求失败" }; } } }; // 分享模块 const ShareModule = { // 分享视频 async share(aid) { if (!aid) return { code: -1, message: "视频ID为空" }; const csrf = getCookie("bili_jct"); if (!csrf) return { code: -1, message: "未获取到CSRF令牌" }; // 准备参数并添加WBI签名 const params = WBI.sign({ aid: aid, csrf: csrf }); try { const res = await request({ url: API.SHARE, method: "POST", data: params }); return res; } catch (err) { console.error("[BilibiliExp] 分享失败", err); return { code: -1, message: "分享请求失败" }; } } }; // 大会员经验模块 const VIPExpModule = { // 本地存储键名 STORAGE_KEY: 'bili_vip_exp_status', // 检查是否已获取大会员观看经验 hasGotVipExp() { const status = this.getStoredStatus(); if (!status) return false; // 检查日期是否为今天 const today = new Date().toDateString(); if (status.date !== today) { // 如果不是今天的记录,返回false return false; } return status.hasGotExp === true; }, // 获取存储状态 getStoredStatus() { try { const data = localStorage.getItem(this.STORAGE_KEY); if (data) { return JSON.parse(data); } } catch (err) { console.error("[BilibiliExp] 读取本地存储状态失败", err); } return null; }, // 存储状态 saveStatus(hasGotExp) { try { const status = { date: new Date().toDateString(), hasGotExp: hasGotExp }; localStorage.setItem(this.STORAGE_KEY, JSON.stringify(status)); } catch (err) { console.error("[BilibiliExp] 保存本地存储状态失败", err); } }, // 获取大会员观看经验 async getVipExp() { // 检查是否已经获取过 if (this.hasGotVipExp()) { console.log("[BilibiliExp] 今日已获取过大会员观看经验"); return { code: 0, message: "已经获取过", data: { is_grant: true } }; } const csrf = getCookie("bili_jct"); if (!csrf) { return { code: -1, message: "未获取到CSRF令牌" }; } // 准备参数 const params = { csrf: csrf }; try { const res = await request({ url: API.VIP_EXP, method: "POST", data: params, headers: { "Content-Type": "application/x-www-form-urlencoded", "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36" } }); // //打印res字符串 // console.log(res); //{code: 69198, message: '用户经验已经领取', ttl: 1, data: {is_grant:false, type: 0}} if (res.code === 69198) { this.saveStatus(true); console.log("[BilibiliExp] 用户已经领取过大会员经验"); } // 如果获取成功,更新本地存储 if (res.code === 0 && res.data && res.data.is_grant) { this.saveStatus(true); console.log("[BilibiliExp] 成功获取大会员观看经验"); } else { console.log(`[BilibiliExp] 获取大会员观看经验失败: ${res.message || '未知错误'}`); } return res; } catch (err) { console.error("[BilibiliExp] 获取大会员观看经验失败", err); return { code: -1, message: "请求失败" }; } } }; // UI渲染模块 const UIRenderer = { // 插入经验统计界面 async renderExpStats() { if (!CONFIG.SHOW_STATS) return; try { const rewardInfo = await DailyReward.getStatus(); if (!rewardInfo) { console.error("[BilibiliExp] 无法获取奖励状态,取消统计显示"); return false; } // 创建图标样式 this.insertIconStyle(); // 准备统计数据 const statsData = this.prepareStatsData(rewardInfo); // 检查是否获取到了统计数据 if (!statsData || statsData.length === 0) { console.error("[BilibiliExp] 统计数据为空,取消显示"); return false; } // 尝试创建一个我们自己的容器,避免修改B站元素 // 首先查找是否已经存在我们的容器 let ourContainer = document.querySelector(".bili-exp-container"); if (!ourContainer) { // 获取工具栏位置 - 尝试多个可能的选择器 const toolbarSelectors = [ ".video-toolbar-v1", // 原始选择器 ".video-toolbar-container", // 2024年可能的新选择器 ".bpx-player-video-toolbar", // B站可能的播放器工具栏 ".video-info-container", // 视频信息容器 ".video-info-operation", // 操作按钮区域 ".video-tool-bar", // 可能的工具栏类名 ".bili-video-toolbar", // 另一个可能的工具栏类名 ".operation-list", // 操作列表 "[data-type='toolbar']" // 通过数据属性查找 ]; // 尝试查找工具栏 let toolbar = null; for (const selector of toolbarSelectors) { toolbar = document.querySelector(selector); if (toolbar) { console.log(`[BilibiliExp] 找到工具栏元素: ${selector}`); // 使用辅助函数应用样式 this.applyToolbarStyle(toolbar, selector); // 创建我们自己的容器,附加到工具栏 ourContainer = document.createElement("div"); ourContainer.className = "bili-exp-container"; // 通过插入而不是appendChild,避免可能的DOM冲突 try { toolbar.insertAdjacentElement('beforeend', ourContainer); console.log(`[BilibiliExp] 成功在${selector}中插入容器`); } catch (e) { console.error(`[BilibiliExp] 插入容器失败,尝试appendChild`, e); try { toolbar.appendChild(ourContainer); } catch (e2) { console.error(`[BilibiliExp] appendChild也失败`, e2); // 继续尝试其他容器 ourContainer = null; continue; } } break; } } if (!ourContainer) { // 降级方案 - 尝试查找其他可能的容器 const alternativeContainers = [ ".video-container-v1", // 视频容器 ".bpx-player-container", // 播放器容器 "#bilibili-player", // 播放器元素 "#playerWrap", // 播放器包装 ".player-wrap", // 播放器包装 ".video-container" // 通用视频容器 ]; for (const selector of alternativeContainers) { const container = document.querySelector(selector); if (container) { console.log(`[BilibiliExp] 找到替代容器: ${selector}`); // 创建我们自己的容器 ourContainer = document.createElement("div"); ourContainer.className = "bili-exp-container"; ourContainer.style.cssText = "margin-top: 10px; padding: 8px; background: rgba(0,0,0,0.03); border-radius: 6px;"; try { container.insertAdjacentElement('beforeend', ourContainer); } catch (e) { console.error(`[BilibiliExp] 插入容器失败,尝试appendChild`, e); try { container.appendChild(ourContainer); } catch (e2) { console.error(`[BilibiliExp] appendChild也失败`, e2); // 继续尝试其他容器 ourContainer = null; continue; } } break; } } } } if (!ourContainer) { // 最终降级方案 - 直接添加到页面底部 console.log("[BilibiliExp] 未找到任何合适的容器,将添加到页面底部"); ourContainer = document.createElement("div"); ourContainer.className = "bili-exp-container bili-exp-toolbar-fallback"; ourContainer.style.cssText = "position: fixed; bottom: 10px; right: 10px; padding: 8px; background: rgba(0,0,0,0.7); color: white; border-radius: 8px; z-index: 9999;"; document.body.appendChild(ourContainer); } // 检查是否已经有统计容器 let statsContainer = ourContainer.querySelector(".bili-exp-stats"); if (!statsContainer) { // 如果没有,创建新的统计容器 statsContainer = document.createElement("div"); statsContainer.className = "bili-exp-stats"; ourContainer.appendChild(statsContainer); } // 更新统计内容 statsContainer.innerHTML = this.generateStatsHTML(statsData); return true; } catch (err) { console.error("[BilibiliExp] 渲染经验统计时出错", err); return false; } }, // 插入图标样式 insertIconStyle() { // 避免重复插入 if (document.getElementById("bili-exp-style")) return; const style = document.createElement("style"); style.id = "bili-exp-style"; style.textContent = ` .bili-exp-stats { margin-top: 10px; padding: 8px; background: rgba(0,0,0,0.03); border-radius: 6px; font-size: 14px; display: flex; flex-wrap: wrap; justify-content: space-around; width: 100%; /* 确保占用全宽 */ box-sizing: border-box; /* 确保padding不增加宽度 */ } .bilibili-exp-toolbar-fallback .bili-exp-stats { background: transparent; margin-top: 0; } .bili-exp-stats span { margin: 4px 4px; /* 减小水平间距 */ display: flex; flex-direction: column; align-items: flex-start; min-width: 90px; /* 减小最小宽度,更容易适应小空间 */ max-width: 120px; /* 限制最大宽度 */ padding: 2px 4px; /* 保持内边距 */ flex-grow: 0; /* 防止自动拉伸 */ } /* 特定统计项样式 */ .bili-exp-stat-item { transition: all 0.2s ease; border-radius: 4px; } .bili-exp-stat-item:hover { background: rgba(0,0,0,0.05); } .bilibili-exp-toolbar-fallback .bili-exp-stat-item:hover { background: rgba(255,255,255,0.1); } @media screen and (max-width: 768px) { .bili-exp-stats span { min-width: 70px; /* 在小屏幕上进一步减小 */ margin: 2px 2px; } } .bili-exp-stats span small { color: #999; } .bilibili-exp-toolbar-fallback .bili-exp-stats span small { color: #ddd; } .bili-exp-stats .completed { color: #fb7299; } .bili-exp-stats .incomplete { color: #666; } .bilibili-exp-toolbar-fallback .bili-exp-stats .incomplete { color: #ccc; } .bili-exp-stats i { margin-right: 5px; font-size: 18px; } /* 使用我们的自定义类修改工具栏样式 */ .bili-exp-enhanced-toolbar { display: flex !important; flex-wrap: wrap !important; row-gap: 8px !important; align-items: center !important; } /* 针对插入到toolbar的统计容器的特殊样式 */ .bili-exp-enhanced-toolbar .bili-exp-stats { margin-top: 4px !important; width: 100% !important; order: 999 !important; /* 确保显示在底部 */ } .bili-exp-stats .icon-login:before { content: "\\e62b"; } .bili-exp-stats .icon-share:before { content: "\\e614"; } .bili-exp-stats .icon-play:before { content: "\\e616"; } .bili-exp-stats .icon-coin:before { content: "\\e60a"; } .bili-exp-stats .icon-total:before { content: "\\e619"; } .bili-exp-stats .icon-day:before { content: "\\e61e"; } .bili-exp-stats .icon-vip:before { content: "\\e630"; } `; document.head.appendChild(style); // 加载图标字体 if (!document.querySelector('link[href*="font_1537779_4srood2g1uk.css"]')) { const link = document.createElement("link"); link.rel = "stylesheet"; link.href = "//at.alicdn.com/t/font_1537779_4srood2g1uk.css"; document.head.appendChild(link); } }, // 安全地应用样式到工具栏 applyToolbarStyle(toolbar, selector) { try { // 首先检查toolbar是否有效 if (!toolbar || typeof toolbar !== 'object' || !toolbar.classList) { console.error(`[BilibiliExp] 工具栏元素无效: ${selector}`); return false; } // 添加我们自己的标识类,而不是直接修改style toolbar.classList.add("bili-exp-enhanced-toolbar"); // 记录我们修改了该元素,便于调试 console.log(`[BilibiliExp] 为${selector}添加bili-exp-enhanced-toolbar类`); return true; } catch (err) { console.error(`[BilibiliExp] 应用工具栏样式失败:`, err); return false; } }, // 准备统计数据 prepareStatsData(rewardInfo) { // 参数校验 if (!rewardInfo) { console.error("[BilibiliExp] 无法准备统计数据:奖励信息为空"); return []; } let total = 0; const data = []; // 登录经验(检查字段是否存在) const hasLogin = typeof rewardInfo.login === 'boolean' ? rewardInfo.login : false; total += hasLogin ? 5 : 0; data.push({ ok: hasLogin, name: "每日登录", text: (hasLogin ? 5 : 0) + "/5", className: "icon-login" }); // 分享经验(检查字段是否存在) const hasShare = typeof rewardInfo.share === 'boolean' ? rewardInfo.share : false; total += hasShare ? 5 : 0; data.push({ ok: hasShare, name: "分享视频", text: (hasShare ? 5 : 0) + "/5", className: "icon-share" }); // 观看经验(检查字段是否存在) const hasWatch = typeof rewardInfo.watch === 'boolean' ? rewardInfo.watch : false; total += hasWatch ? 5 : 0; data.push({ ok: hasWatch, name: "观看视频", text: (hasWatch ? 5 : 0) + "/5", className: "icon-play" }); // 投币经验(检查字段是否存在) const coins = typeof rewardInfo.coins === 'number' ? rewardInfo.coins : 0; total += coins; data.push({ ok: coins >= 50, name: "视频投币", text: coins + "/50", className: "icon-coin" }); // 大会员观看经验(仅对大会员显示) if (rewardInfo.isVip) { const hasVipExp = rewardInfo.vipExp === true; const vipExpValue = hasVipExp ? 10 : 0; total += vipExpValue; data.push({ ok: hasVipExp, name: "大会员观看", text: vipExpValue + "/10", className: "icon-vip", tooltip: hasVipExp ? "已获取大会员观看经验" : "大会员观看视频可获得10经验" }); } // 总计 data.push({ ok: total >= (rewardInfo.isVip ? 75 : 65), name: "总计", text: total + "/" + (rewardInfo.isVip ? "75" : "65"), className: "icon-total" }); // 升级天数(添加防御性检查) const daysToUpgrade = DailyReward.calculateDaysToUpgrade(rewardInfo); // 确保level_info存在且有current_level字段 if (rewardInfo.level_info && typeof rewardInfo.level_info.current_level === 'number') { if (rewardInfo.level_info.current_level >= 6) { data.push({ ok: true, name: "一个成熟的六级大佬", text: "六级辣", className: "icon-day" }); } else { // 安全访问 current_level const nextLevel = (rewardInfo.level_info.current_level || 0) + 1; data.push({ ok: false, name: `到 ${nextLevel} 级预计`, text: daysToUpgrade + " 天", className: "icon-day" }); } } else { // 如果没有等级信息,显示占位符 data.push({ ok: false, name: "等级信息", text: "未知", className: "icon-day" }); } return data; }, // 生成经验统计HTML generateStatsHTML(data) { if (!data || !data.length) return ""; return data.map(item => { const className = item.ok ? "completed" : "incomplete"; // 构建基本HTML,添加更好的样式类 let html = `<span class="${className} bili-exp-stat-item" title="${item.tooltip || ''}" ${item.onClick ? `onclick="${item.onClick}"` : ""}> <i class="${item.className} iconfont"></i>${item.name}: ${item.text}`; html += '</span>'; return html; }).join(""); } }; // 工具函数 function getCookie(name) { const value = `; ${document.cookie}`; const parts = value.split(`; ${name}=`); if (parts.length === 2) return parts.pop().split(';').shift(); return ''; } // AJAX请求封装 async function request(options) { return new Promise((resolve, reject) => { const defaultOptions = { xhrFields: { withCredentials: true }, crossDomain: true }; // 合并选项 const opt = { ...defaultOptions, ...options }; // 如果是POST,自动添加Content-Type if (opt.method === 'POST' && !opt.headers) { opt.headers = { 'Content-Type': 'application/x-www-form-urlencoded' }; } // 发送请求 GM.xmlHttpRequest({ method: opt.method, url: opt.url, data: typeof opt.data === 'string' ? opt.data : new URLSearchParams(opt.data).toString(), headers: opt.headers, onload: function(response) { try { const res = JSON.parse(response.responseText); resolve(res); } catch (error) { reject(error); } }, onerror: function(error) { reject(error); } }); }); } // 等待函数 function wait(ms) { return new Promise(resolve => setTimeout(resolve, ms)); } // 获取视频ID function getVideoId() { try { // 新版B站页面中获取AID const videoData = unsafeWindow.__INITIAL_STATE__; if (videoData && videoData.aid) { return videoData.aid; } // 尝试从URL中获取 const urlMatch = location.href.match(/\/video\/(\w+)/); if (urlMatch && unsafeWindow.bvid) { return unsafeWindow.aid || null; } return null; } catch (error) { console.error("[BilibiliExp] 获取视频ID失败", error); return null; } } // 主函数 async function main() { // 初始化WBI签名 await WBI.init(); // 获取视频ID const aid = getVideoId(); if (!aid) { console.error("[BilibiliExp] 无法获取视频ID"); return; } // 获取用户信息 const userInfo = await UserInfo.get(); if (!userInfo || !userInfo.isLogin) { console.error("[BilibiliExp] 用户未登录"); return; } // 获取奖励状态 const rewardStatus = await DailyReward.getStatus(); if (!rewardStatus) { console.error("[BilibiliExp] 获取奖励状态失败"); return; } // 自动分享 if (CONFIG.AUTO_SHARE && !rewardStatus.share) { console.log("[BilibiliExp] 尝试分享视频"); const shareResult = await ShareModule.share(aid); if (shareResult && shareResult.code === 0) { console.log("[BilibiliExp] 分享成功"); } } // 自动投币 if (CONFIG.AUTO_COIN && rewardStatus.coins < 50 && userInfo.money > 5) { const coinNum = Math.min(CONFIG.COIN_NUMBER, Math.floor((50 - rewardStatus.coins) / 10)); if (coinNum > 0) { console.log(`[BilibiliExp] 尝试投${coinNum}个币`); const coinResult = await CoinModule.add(aid, coinNum); if (coinResult && coinResult.code === 0) { console.log(`[BilibiliExp] 投币成功`); } } } // 如果是大会员,尝试获取观看经验 if (CONFIG.AUTO_VIP_EXP && userInfo.isVip) { console.log("[BilibiliExp] 检测到大会员账号,尝试获取观看经验"); // 直接尝试获取经验,API会判断是否满足条件 VIPExpModule.getVipExp().then(result => { if (result.code === 0) { console.log("[BilibiliExp] 大会员经验获取成功"); // 刷新统计显示 UIRenderer.renderExpStats(); } else { console.log(`[BilibiliExp] 大会员经验获取结果: ${result.message || '未知'}`); } }); } // 渲染经验统计 - 增加延迟和重试机制 let attempts = 0; const maxAttempts = 10; // 增加最大尝试次数 const attemptRender = async () => { await wait(3000); // 增加等待时间,确保页面加载完毕 try { // 首先检查页面是否已经加载完成 if (document.readyState !== "complete") { console.log(`[BilibiliExp] 页面尚未完全加载,等待后重试...`); attempts++; if (attempts < maxAttempts) { setTimeout(attemptRender, 2000); // 2秒后重试 } return; } // 检查关键元素是否存在 const pageLoaded = !!document.querySelector(".video-toolbar-container") || !!document.querySelector(".bpx-player-video-toolbar") || !!document.querySelector(".video-info-container"); if (!pageLoaded) { console.log(`[BilibiliExp] 关键页面元素尚未加载,等待后重试...`); attempts++; if (attempts < maxAttempts) { setTimeout(attemptRender, 2000); // 2秒后重试 } return; } const result = await UIRenderer.renderExpStats(); if (result === false && attempts < maxAttempts) { console.log(`[BilibiliExp] 渲染尝试 ${attempts + 1}/${maxAttempts} 失败,将重试...`); attempts++; setTimeout(attemptRender, 3000); // 3秒后重试,增加等待时间 } } catch (e) { console.error("[BilibiliExp] 渲染经验统计出错", e); if (attempts < maxAttempts) { console.log(`[BilibiliExp] 渲染尝试 ${attempts + 1}/${maxAttempts} 失败,将重试...`); attempts++; setTimeout(attemptRender, 3000); // 3秒后重试,增加等待时间 } } }; // 开始渲染尝试 attemptRender(); } // 页面加载完成后初始化 (function() { // 等待页面加载完成 if (document.readyState === "complete" || document.readyState === "interactive") { console.log("[BilibiliExp] 页面已加载,延迟5秒执行初始化..."); setTimeout(main, 5000); // 增加到5秒 } else { console.log("[BilibiliExp] 等待页面加载..."); window.addEventListener("load", () => { console.log("[BilibiliExp] 页面加载完成,延迟5秒执行初始化..."); setTimeout(main, 5000); // 使用load事件,确保完全加载,并延迟5秒 }); } })();