// ==UserScript== // @name B站直播间自动点赞 (定时+按钮版) // @namespace http://tampermonkey.net/ // @version 3.2.0 // @description 在B站直播间“点赞”按钮前增加控制按钮,点击或按小键盘【-】键可启动自动点赞,间隔、时长和单日最大次数可配置 // @author Xubai0224 // @match https://live.bilibili.com/* // @grant none // @license MIT // ==/UserScript== (function() { 'use strict'; // 配置项 - 可根据需要修改 const MIN_INTERVAL_SEC = 0.2; // 最小点击间隔时间(秒) const MAX_INTERVAL_SEC = 0.5; // 最大点击间隔时间(秒) const AUTO_DURATION_MIN = 10; // 自动点赞持续时间(分钟) const DAILY_MAX_LIKES = 10; // 单日最大点赞次数(单个直播间) // 状态变量 let autoLikeInterval = null; // 自动点赞定时器ID let autoStopTimeout = null; // 自动停止定时器ID let controlButton = null; // 控制按钮元素 let currentRoomId = null; // 当前直播间ID let likeStats = {}; // 点赞统计数据 {房间ID: {date: 日期, count: 次数}} /** * 初始化点赞统计数据 */ function initLikeStats() { // 从URL提取直播间ID const urlMatch = window.location.href.match(/live\.bilibili\.com\/(\d+)/); if (urlMatch && urlMatch[1]) { currentRoomId = urlMatch[1]; } else { console.log('无法获取直播间ID'); return; } // 从localStorage加载数据 const savedStats = localStorage.getItem('bilibiliAutoLikeStats'); if (savedStats) { try { likeStats = JSON.parse(savedStats); } catch (e) { console.error('解析点赞统计数据失败', e); likeStats = {}; } } // 检查日期,每天重置计数 const today = new Date().toISOString().split('T')[0]; // 格式: YYYY-MM-DD if (!likeStats[currentRoomId] || likeStats[currentRoomId].date !== today) { likeStats[currentRoomId] = { date: today, count: 0 }; } saveLikeStats(); } /** * 保存点赞统计数据到localStorage */ function saveLikeStats() { try { localStorage.setItem('bilibiliAutoLikeStats', JSON.stringify(likeStats)); } catch (e) { console.error('保存点赞统计数据失败', e); } } /** * 增加点赞计数 * @returns {boolean} 是否超过每日限制 */ function incrementLikeCount() { if (!currentRoomId) return true; likeStats[currentRoomId].count++; saveLikeStats(); return likeStats[currentRoomId].count >= DAILY_MAX_LIKES; } /** * 检查是否已达到每日点赞限制 * @returns {boolean} 是否超过限制 */ function isOverDailyLimit() { if (!currentRoomId) return false; return likeStats[currentRoomId].count >= DAILY_MAX_LIKES; } /** * 生成随机间隔时间(毫秒) * @returns {number} 随机间隔时间 */ function getRandomInterval() { const minMs = MIN_INTERVAL_SEC * 1000; const maxMs = MAX_INTERVAL_SEC * 1000; return Math.random() * (maxMs - minMs) + minMs; } /** * 切换自动点赞状态 */ function toggleAutoLike() { // 检查是否超过每日限制 if (!autoLikeInterval && isOverDailyLimit()) { alert(`本直播间点赞次数已达到单日最大点赞次数(${DAILY_MAX_LIKES}次)`); return; } if (autoLikeInterval) { // 停止自动点赞 clearInterval(autoLikeInterval); clearTimeout(autoStopTimeout); autoLikeInterval = null; autoStopTimeout = null; console.log('自动点赞已停止'); updateButtonState(false); } else { // 启动自动点赞 const durationText = AUTO_DURATION_MIN % 1 === 0 ? `${AUTO_DURATION_MIN}分钟` : `${AUTO_DURATION_MIN}分钟`; console.log(`自动点赞已启动,将持续${durationText},间隔: ${MIN_INTERVAL_SEC}-${MAX_INTERVAL_SEC}秒`); // 立即执行一次 if (triggerLikeClick()) { // 如果首次点击就触发了限制,直接返回 return; } // 使用随机间隔的方式实现定时器 startRandomInterval(); // 设置自动停止定时器 const durationMs = AUTO_DURATION_MIN * 60 * 1000; autoStopTimeout = setTimeout(() => { if (autoLikeInterval) { clearInterval(autoLikeInterval); autoLikeInterval = null; console.log(`自动点赞已达到${durationText},已停止`); updateButtonState(false); } }, durationMs); updateButtonState(true); } } /** * 启动随机间隔的点赞定时器 */ function startRandomInterval() { // 清除可能存在的定时器 if (autoLikeInterval) { clearInterval(autoLikeInterval); } // 使用随机间隔设置下一次执行 const nextInterval = getRandomInterval(); autoLikeInterval = setTimeout(() => { // 如果触发了限制,停止定时器 if (triggerLikeClick()) { clearInterval(autoLikeInterval); autoLikeInterval = null; updateButtonState(false); return; } startRandomInterval(); }, nextInterval); } /** * 触发点赞按钮点击 * @returns {boolean} 是否达到点赞限制 */ function triggerLikeClick() { const likeButton = document.querySelector('.like-btn'); if (!likeButton) { console.log('未找到点赞按钮,已停止自动点赞'); if (autoLikeInterval) { toggleAutoLike(); } return false; } // 检查是否超过每日限制 if (isOverDailyLimit()) { alert(`本直播间点赞次数已达到单日最大点赞次数(${DAILY_MAX_LIKES}次)`); if (autoLikeInterval) { toggleAutoLike(); } return true; } likeButton.click(); // 增加计数并检查是否超过限制 const isOverLimit = incrementLikeCount(); if (isOverLimit) { alert(`本直播间点赞次数已达到单日最大点赞次数(${DAILY_MAX_LIKES}次)`); return true; } return false; } /** * 更新控制按钮状态 * @param {boolean} isRunning - 是否正在运行自动点赞 */ function updateButtonState(isRunning) { if (!controlButton) return; // 格式化显示时间(去除小数部分如果是整数) const displayDuration = AUTO_DURATION_MIN % 1 === 0 ? Math.floor(AUTO_DURATION_MIN) : AUTO_DURATION_MIN; if (isRunning) { controlButton.textContent = '停止点赞'; controlButton.style.backgroundColor = '#e74c3c'; controlButton.style.borderColor = '#c0392b'; } else { controlButton.textContent = `自动赞${displayDuration}min`; controlButton.style.backgroundColor = '#3498db'; controlButton.style.borderColor = '#2980b9'; } } /** * 创建并插入控制按钮 */ function createControlButton() { // 避免重复创建或在点赞按钮未加载时创建 if (document.getElementById('auto-like-control-btn') || !document.querySelector('.like-btn')) { return; } const likeButton = document.querySelector('.like-btn'); controlButton = document.createElement('button'); controlButton.id = 'auto-like-control-btn'; // 设置按钮样式 Object.assign(controlButton.style, { marginRight: '8px', padding: '0 10px', border: '1px solid', borderRadius: '4px', cursor: 'pointer', fontSize: '12px', height: `${likeButton.offsetHeight}px`, color: 'white', transition: 'background-color 0.3s' }); // 初始化按钮状态 updateButtonState(false); // 绑定点击事件 controlButton.addEventListener('click', toggleAutoLike); // 插入到点赞按钮前方 likeButton.parentNode.insertBefore(controlButton, likeButton); console.log('自动点赞控制按钮已加载'); } /** * 初始化键盘事件监听 */ function initKeyboardListener() { document.addEventListener('keydown', (event) => { // 小键盘减号键控制 if (event.code === 'NumpadSubtract') { toggleAutoLike(); } }); } /** * 初始化程序 */ function init() { // 初始化点赞统计 initLikeStats(); // 监听键盘事件 initKeyboardListener(); // 定时检查点赞按钮是否加载完成 const checkInterval = setInterval(() => { if (document.querySelector('.like-btn')) { createControlButton(); clearInterval(checkInterval); } }, 1000); } // 启动初始化 init(); })();