// ==UserScript== // @name 抖音点赞/收藏/推荐/进入下一个视频(陈天翊测试版)带语音播报 // @namespace http://tampermonkey.net/ // @version 1.7 // @description 点赞、收藏、推荐 依据视频刷新量执行 // @author 陈天翊 // @match https://www.douyin.com/* // @grant GM_setValue // @grant GM_getValue // @grant GM_registerMenuCommand // @grant GM_addStyle // @grant unsafeWindow // @run-at document-idle // ==/UserScript== (function() { 'use strict'; // 配置 const CONFIG = { enabled: GM_getValue('enabled', true), // 点赞功能 autoLike: GM_getValue('autoLike', true), likeVideoMin: GM_getValue('likeVideoMin', 5), // 检测到3个新视频 likeVideoMax: GM_getValue('likeVideoMax', 12), // 检测到5个新视频 // 收藏功能 autoCollect: GM_getValue('autoCollect', true), collectVideoMin: GM_getValue('collectVideoMin', 20), // 检测到5个新视频 collectVideoMax: GM_getValue('collectVideoMax', 68), // 检测到8个新视频 // 推荐功能 autoShare: GM_getValue('autoShare', true), shareVideoMin: GM_getValue('shareVideoMin', 30), // 检测到2个新视频 shareVideoMax: GM_getValue('shareVideoMax', 100), // 检测到4个新视频 // 语音播报功能 speechEnabled: GM_getValue('speechEnabled', true), speechRate: GM_getValue('speechRate', 1.0), speechVolume: GM_getValue('speechVolume', 1.0), speechVoice: GM_getValue('speechVoice', ''), // 自动滑动功能 autoSwipe: GM_getValue('autoSwipe', false), swipeMinTime: GM_getValue('swipeMinTime', 5), // 最小停留时间(秒) swipeMaxTime: GM_getValue('swipeMaxTime', 15), // 最大停留时间(秒) swipeKey: GM_getValue('swipeKey', 'ArrowDown') // 滑动按键 }; // 统计 const STATS = { likes: GM_getValue('likes', 0), collects: GM_getValue('collects', 0), shares: GM_getValue('shares', 0), successes: GM_getValue('successes', 0), failures: GM_getValue('failures', 0), videoCount: GM_getValue('videoCount', 0), // 累计新视频数量 swipes: GM_getValue('swipes', 0) // 累计滑动次数 }; // 当前状态 let currentState = { isProcessing: false, currentVideo: '', panelVisible: false, panel: null, panelMinimized: false, // 新增:面板是否最小化 likeCounter: 0, // 点赞计数器 collectCounter: 0, // 收藏计数器 shareCounter: 0, // 推荐计数器 speech: null, // 语音合成对象 voices: [], // 可用语音列表 voiceLoaded: false, // 语音是否已加载 swipeTimer: null, // 滑动计时器 swipeStartTime: 0, // 当前视频开始时间 currentStayTime: 0, // 当前视频计划停留时间 isVideoPlaying: false, // 视频是否在播放 lastSwipeTime: 0 // 上次滑动时间 }; class DouyinAutoHelper { constructor() { this.init(); } init() { console.log('👽 抖音点赞/收藏/推荐 v1.7 已加载(陈天翊测试版)'); this.setupMenuCommands(); this.addCSSStyles(); this.initSpeechSynthesis(); // 等待页面加载完成后初始化 if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', () => this.delayedInit()); } else { this.delayedInit(); } } delayedInit() { setTimeout(() => { this.startVideoMonitoring(); if (CONFIG.enabled) { this.startAutoMode(); } // 默认显示控制面板 this.showControlPanel(); console.log('🚀 脚本初始化完成'); console.log('📊 当前执行规则:'); console.log('- 点赞:每' + CONFIG.likeVideoMin + '-' + CONFIG.likeVideoMax + '个新视频'); console.log('- 收藏:每' + CONFIG.collectVideoMin + '-' + CONFIG.collectVideoMax + '个新视频'); console.log('- 推荐:每' + CONFIG.shareVideoMin + '-' + CONFIG.shareVideoMax + '个新视频'); console.log('- 自动滑动:' + (CONFIG.autoSwipe ? '已开启' : '已关闭')); console.log('- 滑动时间:' + CONFIG.swipeMinTime + '-' + CONFIG.swipeMaxTime + '秒'); // 语音播报初始化完成 if (CONFIG.speechEnabled && currentState.voiceLoaded) { this.speak('抖音助手已启动,开始为您服务。'); } // 启动自动滑动 this.updateAutoSwipe(); }, 3000); } // ==================== 自动滑动功能 ==================== getRandomTime() { return Math.floor(Math.random() * (CONFIG.swipeMaxTime - CONFIG.swipeMinTime + 1)) + CONFIG.swipeMinTime; } startAutoSwipe() { if (!CONFIG.autoSwipe || !CONFIG.enabled) { console.log('⏸️ 自动滑动已禁用'); return; } // 清除现有计时器 if (currentState.swipeTimer) { clearTimeout(currentState.swipeTimer); currentState.swipeTimer = null; } // 计算随机停留时间 currentState.currentStayTime = this.getRandomTime(); currentState.swipeStartTime = Date.now(); currentState.lastSwipeTime = 0; // 设置滑动倒计时 this.setSwipeTimer(); // 开始监控视频播放状态 this.startVideoPlaybackMonitoring(); console.log('🔀 自动滑动已启动'); console.log('⏱️ 当前视频停留时间:' + currentState.currentStayTime + '秒'); if (CONFIG.speechEnabled) { this.speak('自动滑动已启动,当前视频停留' + currentState.currentStayTime + '秒'); } } stopAutoSwipe() { if (currentState.swipeTimer) { clearTimeout(currentState.swipeTimer); currentState.swipeTimer = null; } // 停止视频播放监控 this.stopVideoPlaybackMonitoring(); console.log('⏸️ 自动滑动已停止'); if (CONFIG.speechEnabled) { this.speak('自动滑动已停止'); } } toggleAutoSwipe() { CONFIG.autoSwipe = !CONFIG.autoSwipe; GM_setValue('autoSwipe', CONFIG.autoSwipe); if (CONFIG.autoSwipe) { this.startAutoSwipe(); this.showNotification('🔀 自动滑动已开启'); } else { this.stopAutoSwipe(); this.showNotification('⏸️ 自动滑动已关闭'); } this.updateControlPanel(); } setSwipeTimer() { if (!CONFIG.autoSwipe || !CONFIG.enabled) { return; } const now = Date.now(); const elapsed = (now - currentState.swipeStartTime) / 1000; const remaining = Math.max(0, currentState.currentStayTime - elapsed); console.log('⏱️ 滑动倒计时:已停留' + elapsed.toFixed(1) + '秒,剩余' + remaining.toFixed(1) + '秒'); // 更新面板显示 this.updateSwipeTimerDisplay(remaining); if (remaining <= 0) { this.performSwipe(); } else { // 设置下次检查 currentState.swipeTimer = setTimeout(() => { this.setSwipeTimer(); }, 1000); } } performSwipe() { if (!CONFIG.enabled || !CONFIG.autoSwipe) { return; } // 检查是否在冷却期(防止连续滑动) const now = Date.now(); if (now - currentState.lastSwipeTime < 1000) { console.log('⏸️ 滑动冷却中,等待1秒'); setTimeout(() => this.performSwipe(), 1000); return; } console.log('🔀 执行滑动操作,按键:' + CONFIG.swipeKey); // 模拟按键 this.simulateKeyPress(CONFIG.swipeKey); // 更新统计 STATS.swipes++; GM_setValue('swipes', STATS.swipes); // 记录滑动时间 currentState.lastSwipeTime = now; // 语音播报 if (CONFIG.speechEnabled) { this.speak('切换到下一个视频'); } // 重置计时器 this.resetSwipeTimer(); this.showNotification('🔀 切换到下一个视频'); } resetSwipeTimer() { // 重新计算停留时间 currentState.currentStayTime = this.getRandomTime(); currentState.swipeStartTime = Date.now(); console.log('🔄 重置滑动计时器,新停留时间:' + currentState.currentStayTime + '秒'); // 重新设置计时器 if (currentState.swipeTimer) { clearTimeout(currentState.swipeTimer); } this.setSwipeTimer(); } updateAutoSwipe() { if (CONFIG.autoSwipe && CONFIG.enabled) { this.startAutoSwipe(); } else { this.stopAutoSwipe(); } } setSwipeTime(min, max) { CONFIG.swipeMinTime = Math.max(1, min); CONFIG.swipeMaxTime = Math.max(min, max); GM_setValue('swipeMinTime', CONFIG.swipeMinTime); GM_setValue('swipeMaxTime', CONFIG.swipeMaxTime); console.log('⏱️ 滑动时间设置为:' + min + '-' + max + '秒'); if (CONFIG.speechEnabled) { this.speak('滑动时间设置为' + min + '到' + max + '秒'); } // 重置计时器 this.resetSwipeTimer(); } setSwipeKey(key) { CONFIG.swipeKey = key; GM_setValue('swipeKey', key); console.log('⌨️ 滑动按键设置为:' + key); if (CONFIG.speechEnabled) { this.speak('滑动按键已设置为' + key); } } // 监控视频播放状态 startVideoPlaybackMonitoring() { const video = this.getVideoElement(); if (!video) { console.log('⚠️ 未找到视频元素,延迟重试'); setTimeout(() => this.startVideoPlaybackMonitoring(), 1000); return; } // 监听视频播放事件 const handlePlay = () => { currentState.isVideoPlaying = true; console.log('▶️ 视频开始播放'); }; const handlePause = () => { currentState.isVideoPlaying = false; console.log('⏸️ 视频已暂停'); // 视频暂停时暂停计时器 if (currentState.swipeTimer) { clearTimeout(currentState.swipeTimer); console.log('⏸️ 滑动计时器已暂停'); } }; video.addEventListener('play', handlePlay); video.addEventListener('pause', handlePause); // 保存事件监听器以便移除 currentState.videoPlayListener = handlePlay; currentState.videoPauseListener = handlePause; // 检查初始状态 currentState.isVideoPlaying = !video.paused; } stopVideoPlaybackMonitoring() { const video = this.getVideoElement(); if (video && currentState.videoPlayListener && currentState.videoPauseListener) { video.removeEventListener('play', currentState.videoPlayListener); video.removeEventListener('pause', currentState.videoPauseListener); } } // 手动滑动功能 manualSwipe() { this.simulateKeyPress('ArrowDown'); STATS.swipes++; GM_setValue('swipes', STATS.swipes); this.showNotification('🔀 手动切换到下一个视频'); this.updatePanelStats(); if (CONFIG.speechEnabled) { this.speak('已切换到下一个视频'); } // 如果自动滑动开启,重置计时器 if (CONFIG.autoSwipe) { this.resetSwipeTimer(); } } // ==================== 语音播报功能 ==================== initSpeechSynthesis() { if ('speechSynthesis' in window) { currentState.speech = window.speechSynthesis; // 获取可用语音列表 this.loadVoices(); // 监听语音列表加载完成 currentState.speech.onvoiceschanged = () => { this.loadVoices(); }; console.log('🎤 语音播报功能已初始化'); } else { console.warn('⚠️ 浏览器不支持语音合成功能'); } } loadVoices() { if (!currentState.speech) return; const voices = currentState.speech.getVoices(); if (voices.length > 0) { currentState.voices = voices; currentState.voiceLoaded = true; console.log('🎤 可用语音列表加载完成,共' + voices.length + '个语音'); // 尝试设置首选中文语音 if (!CONFIG.speechVoice) { const chineseVoice = voices.find(voice => voice.lang.startsWith('zh-') || voice.name.toLowerCase().includes('chinese') ); if (chineseVoice) { CONFIG.speechVoice = chineseVoice.name; console.log('🎤 自动选择中文语音:' + chineseVoice.name); } } } } speak(text, rate = CONFIG.speechRate, volume = CONFIG.speechVolume) { if (!CONFIG.speechEnabled || !currentState.speech || !currentState.voiceLoaded) { console.log('🎤 语音播报已禁用或不可用'); return; } // 停止当前正在播放的语音 if (currentState.speech.speaking) { currentState.speech.cancel(); } const utterance = new SpeechSynthesisUtterance(text); utterance.rate = rate; utterance.volume = volume; // 设置语音 if (CONFIG.speechVoice) { const selectedVoice = currentState.voices.find(voice => voice.name === CONFIG.speechVoice); if (selectedVoice) { utterance.voice = selectedVoice; } } // 语音播放事件 utterance.onstart = () => { console.log('🎤 开始播报:' + text); }; utterance.onend = () => { console.log('🎤 播报结束'); }; utterance.onerror = (event) => { console.error('🎤 语音播报错误:', event); }; // 播放语音 currentState.speech.speak(utterance); } toggleSpeech() { CONFIG.speechEnabled = !CONFIG.speechEnabled; GM_setValue('speechEnabled', CONFIG.speechEnabled); if (CONFIG.speechEnabled) { this.speak('语音播报已开启'); this.showNotification('🎤 语音播报已开启'); } else { this.speak('语音播报已关闭'); this.showNotification('🔇 语音播报已关闭'); } this.updateControlPanel(); } setSpeechRate(rate) { CONFIG.speechRate = rate; GM_setValue('speechRate', rate); this.speak('语音速度已设置为' + rate.toFixed(1)); } setSpeechVolume(volume) { CONFIG.speechVolume = volume; GM_setValue('speechVolume', volume); this.speak('语音音量已设置为' + (volume * 100) + '百分比'); } setSpeechVoice(voiceName) { CONFIG.speechVoice = voiceName; GM_setValue('speechVoice', voiceName); this.speak('语音已切换为' + voiceName); } showVoiceSelector() { if (!currentState.voices.length) { alert('无法获取语音列表,请刷新页面后重试'); return; } let voiceList = '请选择语音:\n\n'; currentState.voices.forEach((voice, index) => { const isSelected = voice.name === CONFIG.speechVoice ? '✅ ' : ' '; voiceList += `${index + 1}. ${isSelected}${voice.name} (${voice.lang})\n`; }); const choice = prompt(voiceList + '\n请输入要选择的语音编号:'); if (choice && !isNaN(choice)) { const index = parseInt(choice) - 1; if (index >= 0 && index < currentState.voices.length) { this.setSpeechVoice(currentState.voices[index].name); } } } // ==================== 菜单命令 ==================== setupMenuCommands() { if (typeof GM_registerMenuCommand === 'function') { GM_registerMenuCommand('🎮 显示控制面板', () => this.showControlPanel()); GM_registerMenuCommand('📊 查看统计', () => this.showStats()); GM_registerMenuCommand('▶️ 启动自动模式', () => this.startAutoMode()); GM_registerMenuCommand('⏸️ 停止自动模式', () => this.stopAutoMode()); GM_registerMenuCommand('🔀 开启/关闭自动滑动', () => this.toggleAutoSwipe()); GM_registerMenuCommand('🎤 开启/关闭语音播报', () => this.toggleSpeech()); GM_registerMenuCommand('🧹 重置统计', () => this.resetStats()); } } addCSSStyles() { const style = document.createElement('style'); style.textContent = ` .tianyi-panel { position: fixed; top: 20px; left: 20px; background: linear-gradient(135deg, #0f0c29, #302b63, #24243e); color: white; padding: 15px; border-radius: 10px; z-index: 10000; font-family: system-ui; font-size: 12px; min-width: 320px; box-shadow: 0 5px 20px rgba(0,0,0,0.3); border: 2px solid #4cc9f0; transition: all 0.3s ease; } .tianyi-panel-minimized { padding: 5px 15px; min-width: 150px; } .tianyi-panel-hidden { display: none; } .tianyi-panel-content { transition: all 0.3s ease; } .tianyi-panel-minimized .tianyi-panel-content { display: none; } .tianyi-notification { position: fixed; bottom: 20px; right: 20px; background: #0f0c29; color: white; padding: 10px 15px; border-radius: 5px; z-index: 10001; font-size: 14px; border-left: 4px solid #4cc9f0; animation: tianyiSlideIn 0.3s ease-out; } @keyframes tianyiSlideIn { from { transform: translateX(100%); opacity: 0; } to { transform: translateX(0); opacity: 1; } } .tianyi-btn { padding: 8px 12px; border: none; border-radius: 5px; color: white; cursor: pointer; margin: 2px; font-size: 11px; transition: all 0.3s; } .tianyi-btn:hover { transform: translateY(-2px); box-shadow: 0 4px 8px rgba(0,0,0,0.3); } .tianyi-counter { font-size: 9px; opacity: 0.7; margin-top: 2px; } .tianyi-panel-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 10px; } .tianyi-minimize-btn { background: transparent; border: none; color: white; font-size: 16px; cursor: pointer; padding: 2px 8px; border-radius: 3px; transition: all 0.3s; } .tianyi-minimize-btn:hover { background: rgba(255,255,255,0.1); } .tianyi-minimized-content { display: flex; align-items: center; justify-content: space-between; width: 100%; } .tianyi-minimized-stats { display: flex; gap: 10px; } .tianyi-minimized-stat { font-size: 11px; text-align: center; } .tianyi-minimized-icon { font-size: 12px; margin-right: 2px; } .tianyi-minimized-count { font-weight: bold; font-size: 13px; } .tianyi-speech-controls { display: grid; grid-template-columns: repeat(3, 1fr); gap: 5px; margin-top: 5px; } .tianyi-speech-btn { padding: 4px 8px; font-size: 10px; } .tianyi-speech-status { display: flex; align-items: center; justify-content: space-between; background: rgba(255,255,255,0.1); padding: 4px 8px; border-radius: 3px; margin-bottom: 5px; } .tianyi-speech-indicator { width: 8px; height: 8px; border-radius: 50%; background-color: ${CONFIG.speechEnabled ? '#4cc9f0' : '#888'}; animation: ${CONFIG.speechEnabled ? 'tianyiPulse 2s infinite' : 'none'}; } @keyframes tianyiPulse { 0% { opacity: 1; } 50% { opacity: 0.3; } 100% { opacity: 1; } } .tianyi-slider-container { display: flex; align-items: center; gap: 8px; font-size: 10px; } .tianyi-slider { flex: 1; height: 4px; background: rgba(255,255,255,0.2); border-radius: 2px; outline: none; -webkit-appearance: none; } .tianyi-slider::-webkit-slider-thumb { -webkit-appearance: none; width: 12px; height: 12px; border-radius: 50%; background: #4cc9f0; cursor: pointer; } .tianyi-voice-btn { width: 100%; margin-top: 5px; } .tianyi-swipe-timer { font-size: 10px; text-align: center; background: rgba(255,255,255,0.1); padding: 4px 8px; border-radius: 3px; margin-top: 5px; font-family: monospace; } .tianyi-swipe-remaining { color: #4cc9f0; font-weight: bold; font-size: 12px; } .tianyi-swipe-controls { display: grid; grid-template-columns: 1fr 1fr; gap: 5px; margin-top: 5px; } .tianyi-swipe-settings { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; margin-top: 5px; } .tianyi-swipe-input { background: rgba(255,255,255,0.1); border: 1px solid rgba(255,255,255,0.2); color: white; padding: 4px 8px; border-radius: 3px; font-size: 10px; width: 100%; } .tianyi-swipe-input:focus { outline: none; border-color: #4cc9f0; } .tianyi-swipe-label { font-size: 9px; opacity: 0.8; margin-top: 2px; } .tianyi-status-indicator { display: inline-block; width: 8px; height: 8px; border-radius: 50%; margin-right: 5px; } .tianyi-status-active { background-color: #4cc9f0; animation: tianyiPulse 1s infinite; } .tianyi-status-inactive { background-color: #888; } .tianyi-status-playing { background-color: #f72585; } `; document.head.appendChild(style); } // ==================== 核心功能 ==================== getRandomCount(min, max) { return Math.floor(Math.random() * (max - min + 1)) + min; } performLike() { console.log('执行点赞操作'); this.simulateKeyPress('z'); STATS.likes++; this.saveStats(); this.updatePanelStats(); // 重置计数器 currentState.likeCounter = 0; this.showNotification('❤️ 点赞成功'); // 语音播报 if (CONFIG.speechEnabled) { this.speak('点赞成功'); } STATS.successes++; this.saveStats(); } performCollect() { console.log('执行收藏操作'); this.simulateKeyPress('c'); STATS.collects++; this.saveStats(); this.updatePanelStats(); // 重置计数器 currentState.collectCounter = 0; this.showNotification('⭐ 收藏成功'); // 语音播报 if (CONFIG.speechEnabled) { this.speak('收藏成功'); } STATS.successes++; this.saveStats(); } performShare() { console.log('执行推荐操作'); this.simulateKeyPress('p'); STATS.shares++; this.saveStats(); this.updatePanelStats(); // 等待推荐面板打开后关闭 setTimeout(() => { this.simulateKeyPress('Escape'); }, 1000); // 重置计数器 currentState.shareCounter = 0; this.showNotification('📤 推荐成功'); // 语音播报 if (CONFIG.speechEnabled) { this.speak('推荐成功'); } STATS.successes++; this.saveStats(); } // ==================== 自动模式 ==================== startAutoMode() { CONFIG.enabled = true; GM_setValue('enabled', true); console.log('启动自动模式'); this.showNotification('👽 自动模式已启动'); // 语音播报 if (CONFIG.speechEnabled) { this.speak('自动模式已启动,开始为您服务'); } // 更新自动滑动 this.updateAutoSwipe(); this.updateControlPanel(); } stopAutoMode() { CONFIG.enabled = false; GM_setValue('enabled', false); console.log('停止自动模式'); this.showNotification('⏸️ 自动模式已停止'); // 语音播报 if (CONFIG.speechEnabled) { this.speak('自动模式已停止'); } // 停止自动滑动 this.stopAutoSwipe(); this.updateControlPanel(); } toggleAutoMode() { if (CONFIG.enabled) { this.stopAutoMode(); } else { this.startAutoMode(); } } // 检测新视频 startVideoMonitoring() { let lastVideoSrc = ''; setInterval(() => { if (!CONFIG.enabled) return; const video = this.getVideoElement(); if (video && video.src && video.src !== lastVideoSrc) { console.log('🎬 检测到新视频'); lastVideoSrc = video.src; // 增加视频计数 STATS.videoCount++; this.saveStats(); // 增加各功能计数器 currentState.likeCounter++; currentState.collectCounter++; currentState.shareCounter++; // 更新面板显示 this.updatePanelStats(); // 重置滑动计时器 if (CONFIG.autoSwipe) { this.resetSwipeTimer(); } // 检查是否满足执行条件 this.checkAndExecuteActions(); } }, 2000); } checkAndExecuteActions() { console.log('📊 计数器状态:'); console.log('- 点赞计数器:' + currentState.likeCounter + '/' + CONFIG.likeVideoMin + '-' + CONFIG.likeVideoMax); console.log('- 收藏计数器:' + currentState.collectCounter + '/' + CONFIG.collectVideoMin + '-' + CONFIG.collectVideoMax); console.log('- 推荐计数器:' + currentState.shareCounter + '/' + CONFIG.shareVideoMin + '-' + CONFIG.shareVideoMax); // 检查点赞条件 if (CONFIG.autoLike && currentState.likeCounter >= this.getRandomCount(CONFIG.likeVideoMin, CONFIG.likeVideoMax)) { console.log('✅ 满足点赞条件,执行点赞'); this.performLike(); } // 检查收藏条件 if (CONFIG.autoCollect && currentState.collectCounter >= this.getRandomCount(CONFIG.collectVideoMin, CONFIG.collectVideoMax)) { console.log('✅ 满足收藏条件,执行收藏'); this.performCollect(); } // 检查推荐条件 if (CONFIG.autoShare && currentState.shareCounter >= this.getRandomCount(CONFIG.shareVideoMin, CONFIG.shareVideoMax)) { console.log('✅ 满足推荐条件,执行推荐'); this.performShare(); } } // ==================== 控制面板 ==================== showControlPanel() { if (currentState.panel) { currentState.panel.classList.remove('tianyi-panel-hidden'); currentState.panelVisible = true; this.updateControlPanel(); return; } const panel = document.createElement('div'); panel.className = 'tianyi-panel'; panel.innerHTML = this.getPanelHTML(); document.body.appendChild(panel); this.setupPanelEvents(panel); this.makeDraggable(panel); currentState.panel = panel; currentState.panelVisible = true; } getPanelHTML() { if (currentState.panelMinimized) { return this.getMinimizedPanelHTML(); } return this.getFullPanelHTML(); } getFullPanelHTML() { const remaining = Math.max(0, currentState.currentStayTime - ((Date.now() - currentState.swipeStartTime) / 1000)); return `