您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
微软Rewards自动搜索获取积分 - 通用版本:智能环境检测、手动启动控制、搜索词缓存、暂停模式记忆、优化通知提示
// ==UserScript== // @ts-nocheck // @name 微软Rewards自动搜索脚本 - 通用版 // @version 3.1.0 // @description 微软Rewards自动搜索获取积分 - 通用版本:智能环境检测、手动启动控制、搜索词缓存、暂停模式记忆、优化通知提示 // @author lutiancheng1 // @match https://*.bing.com/* // @exclude https://rewards.bing.com/* // @license MIT // @icon https://www.bing.com/favicon.ico // @connect gumengya.com // @run-at document-end // @grant GM_registerMenuCommand // @grant GM_addStyle // @grant GM_openInTab // @grant GM_setValue // @grant GM_getValue // @grant GM_xmlhttpRequest // @namespace personal-rewards-script-universal // ==/UserScript== // 环境检测 const isMobile = /iPhone|iPad|iPod|Android|Mobile/i.test(navigator.userAgent) || (navigator.userAgent.includes('Safari') && !navigator.userAgent.includes('Chrome')); const isStay = navigator.userAgent.includes('Stay') || window.location.href.includes('stay'); const isPCEnvironment = !isMobile && !isStay; // 只在首次加载时打印环境信息 if (!window.rewardsScriptLoaded) { console.log('🚀 微软Rewards脚本初始化'); console.log('环境检测:', { platform: isPCEnvironment ? 'PC版' : '移动版', userAgent: navigator.userAgent.substring(0, 50) + '...' }); window.rewardsScriptLoaded = true; } // 根据环境设置参数 const config = { maxRewards: isPCEnvironment ? 40 : 30, pauseTime: isPCEnvironment ? 300000 : 240000, // PC版5分钟,移动版4分钟 searchDelay: isPCEnvironment ? () => Math.floor(Math.random() * 20000) + 10000 : // PC版10-30秒随机 () => Math.floor(Math.random() * 15000) + 30000, // 移动版30-45秒随机 enableStringObfuscation: isPCEnvironment, // 只有PC版启用字符串混淆 scrollDuration: isPCEnvironment ? 4000 : 5000, // PC版4秒,移动版5秒(更慢更自然) platformName: isPCEnvironment ? 'PC版' : '移动版' }; // 全局变量 var search_words = []; var appkey = ""; // 用户可通过菜单设置自己的故梦API密钥 var enable_pause = false; var isTaskStopped = false; // 添加停止标志 var isTaskManuallyStarted = false; // 添加手动启动标志 // 热搜API配置 var hotSearchAPI = { name: "故梦热门词API", url: "https://api.gmya.net/Api/", sources: ['BaiduHot', 'WeiBoHot', 'TouTiaoHot', 'DouYinHot'], parser: (data) => data.data && data.data.map(item => item.title) }; // 默认搜索词 var default_search_words = [ "人工智能发展趋势", "新能源汽车技术", "量子计算突破", "5G网络应用", "区块链技术创新", "元宇宙概念解析", "机器学习算法", "云计算服务", "物联网应用", "大数据分析", "网络安全防护", "移动支付发展", "电商平台创新", "在线教育模式", "远程办公趋势", "智能家居系统", "无人驾驶技术", "虚拟现实体验", "增强现实应用", "生物识别技术", "绿色能源发展", "环保科技创新", "可持续发展", "数字化转型", "智慧城市建设", "医疗科技进步", "基因编辑技术", "精准医疗", "健康管理系统", "运动科学研究", "盛年不重来,一日难再晨", "千里之行,始于足下", "少年易学老难成,一寸光阴不可轻", "敏而好学,不耻下问", "海内存知已,天涯若比邻", "三人行,必有我师焉", "莫愁前路无知已,天下谁人不识君", "人生贵相知,何用金与钱", "天生我材必有用", "海纳百川有容乃大;壁立千仞无欲则刚", "穷则独善其身,达则兼济天下", "读书破万卷,下笔如有神" ]; // 统一的每日缓存系统(支持平台区分) function getTodayKey() { const today = new Date(); const dateKey = today.getFullYear() + '-' + (today.getMonth() + 1).toString().padStart(2, '0') + '-' + today.getDate().toString().padStart(2, '0'); return `${dateKey}_${config.platformName}`; } function getTodayCount() { try { const todayKey = getTodayKey(); const savedData = GM_getValue('dailyProgress', '{}'); // 确保savedData是有效的JSON字符串 if (!savedData || typeof savedData !== 'string') { console.log(`获取dailyProgress失败,使用默认值`); return 0; } let progressData; try { progressData = JSON.parse(savedData); } catch (e) { console.log(`解析dailyProgress失败: ${e.message},使用默认值`); return 0; } // 确保progressData是对象且todayKey存在 if (!progressData || typeof progressData !== 'object') { console.log(`dailyProgress不是有效对象,使用默认值`); return 0; } // 确保todayKey对应的值存在 if (progressData[todayKey] === undefined || progressData[todayKey] === null) { return 0; } return progressData[todayKey] || 0; } catch (error) { console.log(`getTodayCount出错: ${error.message},使用默认值`); return 0; } } function saveTodayCount(count) { try { const todayKey = getTodayKey(); const savedData = GM_getValue('dailyProgress', '{}'); // 确保savedData是有效的JSON字符串 if (!savedData || typeof savedData !== 'string') { console.log(`获取dailyProgress失败,使用空对象初始化`); GM_setValue('dailyProgress', '{}'); // 避免递归调用可能导致的栈溢出 setTimeout(() => saveTodayCount(count), 100); return; } let progressData; try { progressData = JSON.parse(savedData); } catch (e) { console.log(`解析dailyProgress失败: ${e.message},使用空对象初始化`); GM_setValue('dailyProgress', '{}'); // 避免递归调用可能导致的栈溢出 setTimeout(() => saveTodayCount(count), 100); return; } // 确保progressData是对象 if (!progressData || typeof progressData !== 'object') { console.log(`dailyProgress不是有效对象,使用空对象初始化`); GM_setValue('dailyProgress', '{}'); // 避免递归调用可能导致的栈溢出 setTimeout(() => saveTodayCount(count), 100); return; } // 确保count是数字 const numCount = typeof count === 'number' ? count : parseInt(count) || 0; progressData[todayKey] = numCount; // 清理7天前的数据 const sevenDaysAgo = new Date(); sevenDaysAgo.setDate(sevenDaysAgo.getDate() - 7); const cutoffDate = sevenDaysAgo.getFullYear() + '-' + (sevenDaysAgo.getMonth() + 1).toString().padStart(2, '0') + '-' + sevenDaysAgo.getDate().toString().padStart(2, '0'); const cutoffKey = `${cutoffDate}_${config.platformName}`; Object.keys(progressData).forEach(key => { if (key < cutoffKey) { delete progressData[key]; } }); GM_setValue('dailyProgress', JSON.stringify(progressData)); console.log(`${config.platformName}今日进度已保存:`, todayKey, '=', numCount); } catch (error) { console.log(`saveTodayCount出错: ${error.message}`); // 出错时尝试重置进度数据 try { GM_setValue('dailyProgress', '{}'); console.log('已重置进度数据'); } catch (e) { console.log(`重置进度数据失败: ${e.message}`); } } } // 保存暂停模式设置 function savePauseMode(enablePause) { const key = `pauseMode_${config.platformName}`; GM_setValue(key, enablePause); console.log(`${config.platformName}暂停模式已保存:`, enablePause); } // 获取暂停模式设置 function getPauseMode() { const key = `pauseMode_${config.platformName}`; return GM_getValue(key, false); // 默认不启用暂停 } // 保存手动启动标志 function saveManualStartFlag(isStarted) { const key = `manualStart_${config.platformName}`; GM_setValue(key, isStarted); console.log(`${config.platformName}手动启动标志已保存:`, isStarted); } // 获取手动启动标志 function getManualStartFlag() { const key = `manualStart_${config.platformName}`; return GM_getValue(key, false); } // 清除手动启动标志 function clearManualStartFlag() { const key = `manualStart_${config.platformName}`; GM_setValue(key, false); console.log(`${config.platformName}手动启动标志已清除`); } // 保存搜索词缓存 function saveSearchWordsCache(words) { const today = new Date(); const dateKey = today.getFullYear() + '-' + (today.getMonth() + 1).toString().padStart(2, '0') + '-' + today.getDate().toString().padStart(2, '0'); const cacheKey = `searchWords_${config.platformName}_${dateKey}`; const cacheData = { words: words, timestamp: Date.now(), date: dateKey }; GM_setValue(cacheKey, JSON.stringify(cacheData)); console.log(`${config.platformName}搜索词缓存已保存:`, dateKey, words.length, '条'); } // 获取搜索词缓存 function getSearchWordsCache() { const today = new Date(); const dateKey = today.getFullYear() + '-' + (today.getMonth() + 1).toString().padStart(2, '0') + '-' + today.getDate().toString().padStart(2, '0'); const cacheKey = `searchWords_${config.platformName}_${dateKey}`; const cacheData = GM_getValue(cacheKey, null); if (cacheData) { try { const parsed = JSON.parse(cacheData); if (parsed.date === dateKey && parsed.words && parsed.words.length > 0) { // 简化日志输出 return parsed.words; } } catch (error) { console.log('搜索词缓存解析失败:', error); } } return null; } // 清理过期的搜索词缓存(优化版) function cleanupSearchWordsCache() { const today = new Date(); const sevenDaysAgo = new Date(); sevenDaysAgo.setDate(sevenDaysAgo.getDate() - 7); // 只检查过去7天的缓存键 for (let i = 1; i <= 7; i++) { const testDate = new Date(sevenDaysAgo); testDate.setDate(testDate.getDate() - i); // 检查更早的日期 const dateKey = testDate.getFullYear() + '-' + (testDate.getMonth() + 1).toString().padStart(2, '0') + '-' + testDate.getDate().toString().padStart(2, '0'); const cacheKey = `searchWords_${config.platformName}_${dateKey}`; const cacheData = GM_getValue(cacheKey, null); if (cacheData) { GM_setValue(cacheKey, null); // 删除过期缓存 console.log('清理过期搜索词缓存:', dateKey); } } } // AppKey管理功能 function loadAppKey() { const savedKey = GM_getValue('userAppKey', ''); if (savedKey) { appkey = savedKey; console.log('已加载用户设置的AppKey'); } } function saveAppKey(key) { GM_setValue('userAppKey', key); appkey = key; console.log('AppKey已保存'); } function showAppKeyDialog() { const currentKey = GM_getValue('userAppKey', ''); const newKey = prompt(`设置故梦API密钥(可选):\n\n• 有密钥:获取更稳定的热搜词\n• 无密钥:使用免费额度\n• 申请地址:https://www.gmya.net/api\n\n当前密钥:${currentKey ? '已设置' : '未设置'}`, currentKey); if (newKey !== null) { if (newKey.trim() === '') { GM_setValue('userAppKey', ''); appkey = ''; showNotification('AppKey已清空,将使用免费额度', 'info'); } else { saveAppKey(newKey.trim()); showNotification('AppKey已保存,重新加载词库以生效', 'success'); // 重新加载搜索词 getHotSearchWords().then(words => { search_words = words; const isHotWords = !words.includes("人工智能发展趋势"); const wordType = isHotWords ? '热门搜索词' : '默认搜索词'; showNotification(`词库已更新:${wordType}`, 'success'); }); } } } // 清除今日进度的函数 function clearTodayProgress() { const currentProgress = getTodayCount(); // 即使进度为0,也可能需要重置其他状态和跳转首页 const hasOtherStates = isTaskManuallyStarted || enable_pause || getManualStartFlag() || getPauseMode(); if (currentProgress === 0 && !hasOtherStates) { // 进度为0且没有其他状态,直接跳转首页 showNotification(`${config.platformName}今日进度已经是0,直接跳转到首页`, 'info'); setTimeout(() => { location.href = "https://www.bing.com/"; }, 1500); return; } const progressText = currentProgress === 0 ? '0(但可能有其他状态需要重置)' : `${currentProgress}`; const confirmMessage = `确定要重置${config.platformName}所有任务状态并跳转到首页吗?\n\n当前进度:${progressText} / ${config.maxRewards} 次\n\n将重置以下内容:\n• 今日搜索进度\n• 任务运行状态\n• 暂停模式设置\n• 手动启动标志\n\n保留:API密钥、搜索词缓存\n\n重置后将跳转到首页重新开始。`; if (confirm(confirmMessage)) { // 1. 清除今日进度缓存 const todayKey = getTodayKey(); const savedData = GM_getValue('dailyProgress', '{}'); const progressData = JSON.parse(savedData); if (progressData[todayKey]) { delete progressData[todayKey]; GM_setValue('dailyProgress', JSON.stringify(progressData)); } // 2. 清除所有运行时状态变量 isTaskStopped = true; // 停止当前任务 isTaskManuallyStarted = false; // 清除手动启动标志 enable_pause = false; // 清除暂停模式 // 3. 清除所有持久化的任务状态(保留用户设置如API密钥) clearManualStartFlag(); // 清除持久化的手动启动标志 savePauseMode(false); // 清除持久化的暂停模式设置 // 注意:不清除以下用户设置 // - userAppKey: 用户的API密钥设置 // - searchWords_*: 搜索词缓存(用户可能想保留) console.log(`${config.platformName}所有任务状态已重置:`); console.log(`✅ 今日进度: ${currentProgress} -> 0`); console.log(`✅ 任务状态: 已停止`); console.log(`✅ 暂停模式: 已关闭`); console.log(`✅ 手动启动标志: 已清除`); console.log(`ℹ️ 保留用户设置: API密钥、搜索词缓存`); const statusText = currentProgress === 0 ? '所有任务状态已重置' : '今日进度和所有状态已清除'; showNotification(`${config.platformName}${statusText}\n即将跳转到首页重新开始`, 'success'); // 4. 清除完毕后跳转到首页 setTimeout(() => { location.href = "https://www.bing.com/"; }, 2000); // 2秒后跳转,让用户看到通知 } } // 初始化时加载用户的AppKey loadAppKey(); // 字符串混淆函数(仅PC版使用) function AutoStrTrans(st) { if (!config.enableStringObfuscation) return st; let yStr = st; let rStr = ""; let zStr = ""; let prePo = 0; for (let i = 0; i < yStr.length;) { let step = Math.floor(Math.random() * 5) + 1; if (i > 0) { zStr = zStr + yStr.substr(prePo, i - prePo) + rStr; prePo = i; } i = i + step; } if (prePo < yStr.length) { zStr = zStr + yStr.substr(prePo, yStr.length - prePo); } return zStr; } // 生成带次数后缀的搜索词(移动版功能) function generateSearchWord(baseWord, searchCount) { if (config.enableStringObfuscation) { // PC版使用字符串混淆 return AutoStrTrans(baseWord); } else { // 移动版使用次数后缀 const suffixes = [ " 第" + searchCount + "次", " " + searchCount + "号", " 搜索" + searchCount, " #" + searchCount, " (" + searchCount + ")", " 查询" + searchCount, " 了解" + searchCount, " 研究" + searchCount ]; const randomSuffix = suffixes[Math.floor(Math.random() * suffixes.length)]; return baseWord + randomSuffix; } } // 生成随机字符串 function generateRandomString(length) { const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'; let result = ''; const charactersLength = characters.length; for (let i = 0; i < length; i++) { result += characters.charAt(Math.floor(Math.random() * charactersLength)); } return result; } // 获取热门搜索词的函数 function getHotSearchWords() { return new Promise((resolve) => { console.log("开始获取热门搜索词..."); const allWords = []; const sources = hotSearchAPI.sources; let completedRequests = 0; let successfulRequests = 0; // 根据平台动态计算每个数据源需要获取的词汇数量 const wordsPerSource = isPCEnvironment ? 10 : 8; // 为每个数据源发送请求 sources.forEach((source, index) => { let url = hotSearchAPI.url + source; if (appkey) { url += "?format=json&appkey=" + appkey; } console.log(`请求 ${source}:`, url); GM_xmlhttpRequest({ method: 'GET', url: url, timeout: 8000, headers: { 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36' }, onload: function (response) { completedRequests++; try { if (response.status === 200) { const data = JSON.parse(response.responseText); const words = hotSearchAPI.parser(data); if (words && words.length > 0) { // 过滤并根据平台取相应数量的词汇 const filteredWords = words.filter(word => word && word.length >= 2 && word.length <= 20 && !word.includes('http') && !word.includes('www') && !word.includes('undefined') && word.trim() !== '' ).slice(0, wordsPerSource); if (filteredWords.length > 0) { allWords.push(...filteredWords); successfulRequests++; console.log(`✅ ${source} 成功获取 ${filteredWords.length} 条词汇`); } } } else { console.log(`❌ ${source} HTTP错误:`, response.status); } } catch (error) { console.log(`❌ ${source} 解析失败:`, error.message); } checkCompletion(); }, onerror: function (error) { completedRequests++; console.log(`❌ ${source} 请求失败:`, error); checkCompletion(); }, ontimeout: function () { completedRequests++; console.log(`❌ ${source} 请求超时`); checkCompletion(); } }); }); // 检查所有请求是否完成 function checkCompletion() { if (completedRequests === sources.length) { if (allWords.length >= 10) { // 打乱顺序并取前30条 const shuffledWords = allWords.sort(() => Math.random() - 0.5).slice(0, config.maxRewards); console.log(`✅ 成功组合热搜词: ${shuffledWords.length} 条,来自 ${successfulRequests} 个数据源`); resolve(shuffledWords); } else { console.log(`❌ 热搜词数量不足: ${allWords.length} 条,使用默认搜索词`); resolve(default_search_words.slice(0, config.maxRewards)); } } } // 设置总体超时 setTimeout(() => { if (completedRequests < sources.length) { console.log("⏰ 部分请求超时,使用已获取的词汇"); if (allWords.length >= 10) { const shuffledWords = allWords.sort(() => Math.random() - 0.5).slice(0, config.maxRewards); resolve(shuffledWords); } else { resolve(default_search_words.slice(0, config.maxRewards)); } } }, 5000); }); } // 初始化搜索词(热门词缓存一天,默认词每次尝试更新) function initializeSearchWords() { // 先尝试从缓存获取 const cachedWords = getSearchWordsCache(); if (cachedWords) { const isHotWords = !cachedWords.includes("人工智能发展趋势"); if (isHotWords) { // 如果缓存的是热门搜索词,直接使用 search_words = cachedWords; const wordType = '热门搜索词(缓存)'; // 简化日志输出 // 完成初始化 completeInitialization(wordType, cachedWords.length); } else { // 如果缓存的是默认搜索词,尝试重新获取热门搜索词 console.log(`${config.platformName}检测到缓存为默认搜索词,尝试获取热门搜索词...`); attemptToGetHotWords(cachedWords); } } else { // 缓存不存在,从网络获取 console.log(`${config.platformName}缓存不存在,从网络获取搜索词...`); attemptToGetHotWords(null); } } // 尝试获取热门搜索词 function attemptToGetHotWords(fallbackWords) { getHotSearchWords() .then(words => { search_words = words; const isHotWords = !words.includes("人工智能发展趋势"); const wordType = isHotWords ? '热门搜索词' : '默认搜索词'; // 简化日志输出 // 保存到缓存 saveSearchWordsCache(words); // 完成初始化 completeInitialization(wordType, words.length); }) .catch(error => { console.error("获取搜索词失败:", error); if (fallbackWords) { // 使用缓存的默认搜索词 search_words = fallbackWords; console.log(`${config.platformName}网络获取失败,使用缓存的默认搜索词库,共 ${fallbackWords.length} 条`); completeInitialization('默认搜索词(缓存)', fallbackWords.length); } else { // 使用内置的默认搜索词 search_words = default_search_words.slice(0, config.maxRewards); console.log(`${config.platformName}网络获取失败,使用内置默认搜索词库,共 ${search_words.length} 条`); // 保存默认搜索词到缓存 saveSearchWordsCache(search_words); // 完成初始化 completeInitialization('默认搜索词', search_words.length); } }); } // 完成初始化的通用函数 function completeInitialization(wordType, wordCount) { // 清理过期缓存 cleanupSearchWordsCache(); // 词库加载完成后,检查当前页面状态 setTimeout(() => { // 检查是否需要执行任务 const isPauseResume = window.location.href.includes('br_msg=Please-Wait'); const hasManualStartFlag = getManualStartFlag(); const isSearchPage = window.location.href.includes('/search?') || window.location.href.includes('cn.bing.com/search'); const todayCount = getTodayCount(); const hasRunningTask = todayCount > 0 && !isTaskStopped; if (isPauseResume || hasManualStartFlag) { exec(); } else if (isSearchPage && hasRunningTask) { exec(); } }, 1000); // 只在首页打印一次初始化信息 const currentCount = getTodayCount(); const isHomePage = window.location.href === 'https://www.bing.com/' || (window.location.href.includes('bing.com') && !window.location.href.includes('/search')); if (isHomePage && !window.rewardsInitPrinted) { console.log(`✅ ${config.platformName}脚本就绪 | 词库:${wordType}(${wordCount}条) | 进度:${currentCount}/${config.maxRewards}`); window.rewardsInitPrinted = true; } } // 启动初始化 initializeSearchWords(); // 根据环境创建不同的菜单 if (isPCEnvironment) { // PC版菜单 let menu1 = GM_registerMenuCommand('🚀 PC版开始', function () { isTaskStopped = false; // 重置停止状态 isTaskManuallyStarted = false; // 重置手动启动状态,由startPCSearchTask设置 startPCSearchTask(true); // PC版默认启用暂停模式 }, 'o'); let menu2 = GM_registerMenuCommand('⏹️ 停止搜索', function () { isTaskStopped = true; isTaskManuallyStarted = false; clearManualStartFlag(); // 清除手动启动标志 enable_pause = false; savePauseMode(false); // 清除暂停模式设置 showNotification(`${config.platformName}搜索任务已停止`, 'warning'); console.log(`${config.platformName}搜索任务已停止`); }, 'o'); let menu3 = GM_registerMenuCommand('📊 今日进度', function () { const todayCount = getTodayCount(); const remaining = Math.max(0, config.maxRewards - todayCount); const progress = Math.round((todayCount / config.maxRewards) * 100); const statusText = isTaskStopped ? '已停止' : '就绪'; const wordType = search_words.includes("人工智能发展趋势") ? '默认搜索词' : '热门搜索词'; showNotification(`${config.platformName}状态报告:\n\n今日进度:${todayCount} / ${config.maxRewards} 次 (${progress}%)\n剩余次数:${remaining} 次\n任务状态:${statusText}\n词库类型:${wordType} (${search_words.length}条)`, 'info'); }, 'o'); let menu4 = GM_registerMenuCommand('🔑 设置API密钥', function () { showAppKeyDialog(); }, 'o'); let menu5 = GM_registerMenuCommand('🔄 刷新词库', function () { showNotification('正在从多个数据源刷新搜索词库...', 'info'); getHotSearchWords() .then(words => { search_words = words; const isHotWords = !words.includes("人工智能发展趋势"); const wordType = isHotWords ? '热门搜索词' : '默认搜索词'; // 更新缓存 saveSearchWordsCache(words); showNotification(`搜索词库已更新:${wordType}\n共 ${words.length} 条词汇\n示例:${words.slice(0, 3).join('、')}\n\n缓存已更新`, 'success'); }) .catch(error => { search_words = default_search_words.slice(0, config.maxRewards); saveSearchWordsCache(search_words); showNotification('刷新搜索词库失败,使用默认词库\n缓存已更新', 'error'); }); }, 'o'); let menu6 = GM_registerMenuCommand('🗑️ 清除今日进度', function () { clearTodayProgress(); }, 'o'); } else { // 移动版菜单 let menu1 = GM_registerMenuCommand('📱 快速开始(无暂停)', function () { isTaskStopped = false; // 重置停止状态 isTaskManuallyStarted = false; // 重置手动启动状态,由startSearchTask设置 startSearchTask(false); }, 'o'); let menu1_safe = GM_registerMenuCommand('🛡️ 安全开始(带暂停)', function () { isTaskStopped = false; // 重置停止状态 isTaskManuallyStarted = false; // 重置手动启动状态,由startSearchTask设置 startSearchTask(true); }, 'o'); let menu2 = GM_registerMenuCommand('⏹️ 停止任务', function () { isTaskStopped = true; isTaskManuallyStarted = false; clearManualStartFlag(); // 清除手动启动标志 enable_pause = false; savePauseMode(false); // 清除暂停模式设置 showNotification('搜索任务已停止', 'warning'); console.log(`${config.platformName}搜索任务已停止`); }, 'o'); let menu3 = GM_registerMenuCommand('📊 今日进度', function () { const todayCount = getTodayCount(); const remainingCount = Math.max(0, config.maxRewards - todayCount); const progressPercent = Math.round((todayCount / config.maxRewards) * 100); const statusText = isTaskStopped ? '已停止' : '就绪'; const wordType = search_words && search_words.includes("人工智能发展趋势") ? '默认搜索词' : '热门搜索词'; const wordCount = search_words ? search_words.length : 0; showNotification(`${config.platformName}状态报告 v3.0.0:\n\n今日进度:${todayCount} / ${config.maxRewards} 次 (${progressPercent}%)\n剩余次数:${remainingCount} 次\n任务状态:${statusText}\n词库类型:${wordType} (${wordCount}条)`, 'info'); }, 'o'); let menu4 = GM_registerMenuCommand('🔑 设置API密钥', function () { showAppKeyDialog(); }, 'o'); let menu5 = GM_registerMenuCommand('🔄 刷新词库', function () { showNotification('正在从多个数据源刷新搜索词库...', 'info'); getHotSearchWords() .then(words => { search_words = words; const isHotWords = !words.includes("人工智能发展趋势"); const wordType = isHotWords ? '热门搜索词' : '默认搜索词'; // 更新缓存 saveSearchWordsCache(words); showNotification(`搜索词库已更新:${wordType}\n共 ${words.length} 条词汇\n示例:${words.slice(0, 3).join('、')}\n\n缓存已更新`, 'success'); }) .catch(error => { search_words = default_search_words.slice(0, config.maxRewards); saveSearchWordsCache(search_words); showNotification('刷新搜索词库失败,使用默认词库\n缓存已更新', 'error'); }); }, 'o'); let menu6 = GM_registerMenuCommand('📝 查看所有搜索词', function () { if (search_words.length === 0) { showNotification('搜索词库为空,请先刷新词库', 'warning'); return; } const isHotWords = !search_words.includes("人工智能发展趋势"); const wordType = isHotWords ? '热门搜索词' : '默认搜索词'; showSearchWordsModal(search_words, wordType); }, 'o'); let menu7 = GM_registerMenuCommand('🗑️ 清除今日进度', function () { clearTodayProgress(); }, 'o'); } // PC版开始搜索任务函数 function startPCSearchTask(enablePause) { const currentCount = getTodayCount(); const remaining = Math.max(0, config.maxRewards - currentCount); if (currentCount >= config.maxRewards) { showNotification(`${config.platformName}搜索任务已完成!已执行 ${currentCount} 次搜索。`, 'success'); return; } // 重置停止标志并设置手动启动标志 isTaskStopped = false; isTaskManuallyStarted = true; saveManualStartFlag(true); // 保存手动启动标志到本地存储 enable_pause = enablePause; savePauseMode(enablePause); // 保存暂停模式设置 const modeText = '安全模式(每5次暂停5分钟)'; showNotification(`开始执行搜索任务 - ${modeText}\n已完成:${currentCount} / ${config.maxRewards} 次\n剩余:${remaining} 次`, 'info'); console.log(`开始${config.platformName}搜索任务 - ${modeText},已完成:${currentCount} 次,剩余:${remaining} 次`); // 直接在当前页面开始执行搜索任务,不需要跳转 console.log("PC版任务启动,直接开始执行搜索逻辑"); setTimeout(() => { exec(); // 直接执行搜索逻辑 }, 1000); } // 统一的开始搜索任务函数(移动版) function startSearchTask(enablePause) { const todayCount = getTodayCount(); const remainingCount = config.maxRewards - todayCount; if (remainingCount <= 0) { showNotification('今日搜索任务已完成!已执行 ' + todayCount + ' 次搜索。', 'success'); return; } // 重置停止标志并设置手动启动标志 isTaskStopped = false; isTaskManuallyStarted = true; saveManualStartFlag(true); // 保存手动启动标志到本地存储 enable_pause = enablePause; savePauseMode(enablePause); // 保存暂停模式设置 const modeText = enablePause ? '安全模式(每5次暂停4分钟)' : '快速模式(无暂停)'; showNotification('开始执行搜索任务 - ' + modeText + '\n今日已执行:' + todayCount + ' 次,剩余:' + remainingCount + ' 次', 'info'); // 直接在当前页面开始执行搜索任务,不需要跳转 console.log("移动版任务启动,直接开始执行搜索逻辑"); setTimeout(() => { exec(); // 直接执行搜索逻辑 }, 1000); } // 显示搜索词弹窗的函数(移动版功能) function showSearchWordsModal(words, wordType) { const existingModal = document.getElementById('search-words-modal'); if (existingModal) { existingModal.remove(); } const overlay = document.createElement('div'); overlay.id = 'search-words-modal'; overlay.style.cssText = ` position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0, 0, 0, 0.5); z-index: 10001; display: flex; justify-content: center; align-items: center; animation: fadeIn 0.3s ease-out; `; const modal = document.createElement('div'); modal.style.cssText = ` background: white; border-radius: 12px; box-shadow: 0 8px 32px rgba(0,0,0,0.3); max-width: 80%; max-height: 80%; overflow: hidden; animation: slideIn 0.3s ease-out; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; `; const header = document.createElement('div'); header.style.cssText = ` background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white; padding: 20px; font-size: 18px; font-weight: bold; display: flex; justify-content: space-between; align-items: center; `; header.innerHTML = ` <span>📝 当前搜索词库 (${wordType} - 共${words.length}条)</span> <span id="modal-close-btn" style="cursor: pointer; font-size: 24px; opacity: 0.8; user-select: none;">×</span> `; // 为关闭按钮添加事件监听器 const closeButton = header.querySelector('#modal-close-btn'); if (closeButton) { closeButton.addEventListener('click', () => { overlay.remove(); }); } const content = document.createElement('div'); content.style.cssText = ` padding: 20px; max-height: 400px; overflow-y: auto; line-height: 1.6; `; const wordsList = document.createElement('div'); wordsList.style.cssText = ` display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 10px; margin-top: 10px; `; words.forEach((word, index) => { const wordItem = document.createElement('div'); wordItem.style.cssText = ` background: #f8f9fa; border: 1px solid #e9ecef; border-radius: 6px; padding: 8px 12px; font-size: 14px; color: #495057; transition: all 0.2s ease; cursor: pointer; `; wordItem.innerHTML = `<strong>${index + 1}.</strong> ${word}`; wordItem.onmouseover = () => { wordItem.style.background = '#e3f2fd'; wordItem.style.borderColor = '#2196f3'; wordItem.style.transform = 'translateY(-1px)'; }; wordItem.onmouseout = () => { wordItem.style.background = '#f8f9fa'; wordItem.style.borderColor = '#e9ecef'; wordItem.style.transform = 'translateY(0)'; }; wordsList.appendChild(wordItem); }); content.appendChild(wordsList); modal.appendChild(header); modal.appendChild(content); overlay.appendChild(modal); const style = document.createElement('style'); style.textContent = ` @keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } } @keyframes slideIn { from { transform: scale(0.9) translateY(-20px); opacity: 0; } to { transform: scale(1) translateY(0); opacity: 1; } } `; document.head.appendChild(style); overlay.onclick = (e) => { if (e.target === overlay) { overlay.remove(); } }; document.body.appendChild(overlay); } // 创建页面内通知的函数 function showNotification(message, type = 'info') { const existingNotification = document.getElementById('rewards-notification'); if (existingNotification) { existingNotification.remove(); } const notification = document.createElement('div'); notification.id = 'rewards-notification'; notification.style.cssText = ` position: fixed; top: 20px; right: 20px; max-width: 350px; padding: 15px 20px; border-radius: 8px; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; font-size: 14px; line-height: 1.4; box-shadow: 0 4px 12px rgba(0,0,0,0.15); z-index: 10000; animation: slideIn 0.3s ease-out; white-space: pre-line; `; const colors = { 'info': { bg: '#e3f2fd', border: '#2196f3', text: '#1565c0' }, 'success': { bg: '#e8f5e8', border: '#4caf50', text: '#2e7d32' }, 'warning': { bg: '#fff3e0', border: '#ff9800', text: '#f57c00' }, 'error': { bg: '#ffebee', border: '#f44336', text: '#c62828' } }; const color = colors[type] || colors.info; notification.style.backgroundColor = color.bg; notification.style.border = `2px solid ${color.border}`; notification.style.color = color.text; notification.textContent = message; const closeBtn = document.createElement('span'); closeBtn.innerHTML = '×'; closeBtn.style.cssText = ` position: absolute; top: 8px; right: 12px; cursor: pointer; font-size: 18px; font-weight: bold; opacity: 0.7; `; closeBtn.onclick = () => notification.remove(); notification.appendChild(closeBtn); document.body.appendChild(notification); setTimeout(() => { if (notification.parentNode) { notification.style.animation = 'slideIn 0.3s ease-out reverse'; setTimeout(() => notification.remove(), 300); } }, 5000); } // 主执行函数(只在用户手动启动或暂停恢复时执行) function exec() { console.log("=== exec() 函数开始执行 ==="); console.log("当前页面URL:", window.location.href); console.log("平台:", config.platformName); // 检查是否已停止任务 if (isTaskStopped) { console.log("任务已停止,不执行搜索"); return; } // 检查页面状态 const isSearchPage = window.location.href.includes('/search?') || window.location.href.includes('cn.bing.com/search'); const isPauseResume = window.location.href.includes('br_msg=Please-Wait'); const isBingPage = window.location.href.includes('bing.com'); // 如果不是Bing相关页面,则不执行 if (!isBingPage) { console.log("当前页面不是Bing页面,不执行搜索逻辑"); return; } // 获取当前任务状态 let todayCount = getTodayCount(); const searchTaskStarted = sessionStorage.getItem('searchTaskStarted') === 'true'; const hasRunningTask = (todayCount > 0 || searchTaskStarted) && !isTaskStopped; const hasManualStartFlag = getManualStartFlag(); // 检查持久化的手动启动标志 console.log(`页面状态检查: 搜索页=${isSearchPage}, 暂停恢复=${isPauseResume}, 搜索任务已启动=${searchTaskStarted}, 有运行任务=${hasRunningTask}, 今日计数=${todayCount}, 任务已停止=${isTaskStopped}, 手动启动标志=${hasManualStartFlag}`); // 关键修复:只有在以下情况才执行搜索逻辑 // 1. 暂停恢复页面(br_msg=Please-Wait) // 2. 用户手动启动了任务 // 3. 有正在运行的任务(今日计数>0且未停止) if (isPauseResume) { console.log("检测到暂停恢复页面,继续执行搜索逻辑"); } else if (isTaskManuallyStarted || hasManualStartFlag) { console.log("检测到用户手动启动的任务,开始执行搜索逻辑"); // 清除手动启动标志,避免重复执行 isTaskManuallyStarted = false; clearManualStartFlag(); // 恢复暂停模式设置 enable_pause = getPauseMode(); console.log(`恢复暂停模式设置: ${enable_pause}`); // 如果当前在首页,直接执行第一次搜索,不要在这里更新计数器 if (window.location.href.includes('bing.com') && !isSearchPage) { console.log("在首页启动任务,直接执行第一次搜索"); executeFirstSearch(); return; } } else if (hasRunningTask && isSearchPage) { console.log("检测到有正在运行的任务,在搜索页面继续执行搜索逻辑"); // 恢复之前保存的暂停模式 enable_pause = getPauseMode(); console.log(`恢复暂停模式设置: ${enable_pause}`); // 在搜索结果页面,等待滚动完成后使用随机延迟执行下一次搜索 console.log("在搜索结果页面,等待滚动完成后使用随机延迟执行下一次搜索"); continueSearchFromResultPage(); return; // 提前返回,避免立即执行 } else if (isSearchPage && todayCount > 0) { // 额外检查:如果在搜索页面且有计数,说明任务正在进行 console.log("在搜索页面检测到任务进行中,继续执行"); enable_pause = getPauseMode(); continueSearchFromResultPage(); return; } else { console.log("脚本已就绪,等待用户手动启动任务"); return; } const randomDelay = config.searchDelay(); let randomString = generateRandomString(4); let randomCvid = generateRandomString(32); // 检查是否在暂停等待状态 if (window.location.href.includes('br_msg=Please-Wait')) { todayCount = getTodayCount(); // 重新获取最新的计数 const remaining = config.maxRewards - todayCount; // 从URL参数获取暂停时间,如果没有则使用默认值 const urlParams = new URLSearchParams(window.location.search); const pauseTime = parseInt(urlParams.get('pause_time')) || config.pauseTime; const pauseMinutes = Math.round(pauseTime / 60000); console.log(`检测到暂停等待状态,当前进度:${todayCount}/${config.maxRewards},剩余:${remaining}次,等待${pauseMinutes}分钟`); // 显示暂停等待状态 let tt = document.getElementsByTagName("title")[0]; if (tt) { tt.innerHTML = `[${config.platformName}: 暂停等待${pauseMinutes}分钟... ${todayCount}/${config.maxRewards}] Bing`; } // 显示等待通知和倒计时 showNotification(`🛡️ ${config.platformName}安全暂停中...\n\n✅ 已完成一轮搜索(5次)\n📊 当前进度:${todayCount} / ${config.maxRewards} 次\n⏰ 暂停时间:${pauseMinutes} 分钟\n\n等待结束后将自动继续搜索`, 'warning'); // 使用URL参数中的暂停时间 setTimeout(function () { if (isTaskStopped) { console.log("任务已停止,取消继续搜索"); return; } const currentCount = getTodayCount(); // 检查是否已完成所有搜索 if (currentCount >= config.maxRewards) { console.log(`${config.platformName}搜索任务已完成!`); showNotification(`${config.platformName}搜索任务已完成!已执行 ${currentCount} 次搜索。`, 'success'); return; } // 暂停结束后,准备执行下一次搜索 const nextCount = currentCount + 1; let baseWord = search_words[currentCount % search_words.length]; let searchWord = generateSearchWord(baseWord, nextCount); console.log(`暂停等待结束,继续执行第 ${nextCount} 次搜索`); // 先更新计数器,然后执行搜索 saveTodayCount(nextCount); executeSearch(currentCount, searchWord, randomString, randomCvid); }, pauseTime); return; } // 重新获取今日搜索次数(可能在暂停等待中已更新) todayCount = getTodayCount(); // 检查是否已完成所有搜索 if (todayCount >= config.maxRewards) { console.log(`${config.platformName}搜索任务已完成!已执行 ${todayCount} 次搜索。`); clearManualStartFlag(); // 清除手动启动标志 showNotification(`${config.platformName}搜索任务已完成!已执行 ${todayCount} 次搜索。`, 'success'); return; } // 再次检查是否已停止任务 if (isTaskStopped) { console.log("任务已停止,终止执行"); return; } console.log("今日已执行次数:", todayCount); console.log("剩余搜索次数:", config.maxRewards - todayCount); // 注意:搜索逻辑已经在上面的条件分支中处理,这里不需要重复执行 // 执行首次搜索的函数(从首页启动时使用) function executeFirstSearch() { const todayCount = getTodayCount(); // 检查是否已完成所有搜索 if (todayCount >= config.maxRewards) { console.log(`${config.platformName}搜索任务已完成!已执行 ${todayCount} 次搜索。`); return; } // 不再提前更新计数器,只在搜索结果页面加载完成后更新 // 设置一个标记,表示任务已启动但尚未完成第一次搜索 sessionStorage.setItem('searchTaskStarted', 'true'); console.log(`首次搜索:准备执行,当前计数 ${todayCount}`); // 添加页面标题更新逻辑(与continueSearchFromResultPage保持一致) let tt = document.getElementsByTagName("title")[0]; const remainingCount = config.maxRewards - todayCount; if (tt) { tt.innerHTML = `[${config.platformName}: ${todayCount}/${config.maxRewards} | 剩余: ${remainingCount}] ` + tt.innerHTML; } // 立即执行第一次搜索,不等待,不显示通知 if (isTaskStopped) { console.log("任务已停止,取消搜索"); return; } let baseWord = search_words[todayCount % search_words.length]; let searchWord = generateSearchWord(baseWord, todayCount); let randomString = generateRandomString(4); let randomCvid = generateRandomString(32); console.log(`立即执行首次搜索: "${searchWord}"`); executeSearch(todayCount, searchWord, randomString, randomCvid); } // 执行搜索的函数 function executeSearch(searchCount, searchWord, formString, cvid) { if (searchCount < config.maxRewards / 2) { location.href = "https://www.bing.com/search?q=" + encodeURI(searchWord) + "&form=" + formString + "&cvid=" + cvid; } else { location.href = "https://cn.bing.com/search?q=" + encodeURI(searchWord) + "&form=" + formString + "&cvid=" + cvid; } } // 从搜索结果页面继续执行搜索的函数 function continueSearchFromResultPage() { let todayCount = getTodayCount(); // 检查是否已完成所有搜索 if (todayCount >= config.maxRewards) { console.log(`${config.platformName}搜索任务已完成!已执行 ${todayCount} 次搜索。`); clearManualStartFlag(); return; } // 更新计数器(因为当前搜索页面已经加载完成,说明搜索已完成) const newCount = todayCount + 1; saveTodayCount(newCount); console.log(`搜索结果页面加载完成,更新计数器 ${todayCount} -> ${newCount}`); // 清除任务启动标记 sessionStorage.removeItem('searchTaskStarted'); // 更新页面标题显示当前进度 let tt = document.getElementsByTagName("title")[0]; const remainingCount = config.maxRewards - newCount; if (tt) { tt.innerHTML = `[${config.platformName}: ${newCount}/${config.maxRewards} | 剩余: ${remainingCount}] ` + tt.innerHTML; } // 检查是否需要暂停(从会话存储中获取标记) const needPauseAfterSearch = sessionStorage.getItem('needPauseAfterSearch') === 'true'; const pauseTime = parseInt(sessionStorage.getItem('pauseTime') || config.pauseTime.toString()); if (needPauseAfterSearch) { // 清除暂停标记,避免重复暂停 sessionStorage.removeItem('needPauseAfterSearch'); sessionStorage.removeItem('pauseTime'); console.log(`${config.platformName}已完成第${newCount}次搜索,即将暂停${pauseTime / 60000}分钟...`); console.log('正在滚动到页面底部...'); // 先滚动到底部 smoothScrollToBottom(() => { console.log('页面滚动完成,5秒后跳转到暂停页面...'); // 滚动完成后延迟5秒再跳转 setTimeout(() => { console.log('开始跳转到暂停页面...'); location.href = "https://www.bing.com/?br_msg=Please-Wait&pause_time=" + pauseTime; }, 5000); }); return; // 重要:暂停时不继续执行下一次搜索 } console.log(`从搜索结果页面准备执行下一次搜索,当前进度: ${newCount}/${config.maxRewards}`); // 准备下一次搜索的计数 const nextCount = newCount + 1; // 立即开始随机延迟计时,同时开始滚动(并行进行) startDelayAndScroll(newCount, nextCount); } // 滚动完成后继续搜索的函数 function startDelayAndScroll(todayCount, newCount) { // 立即检查任务状态 if (isTaskStopped) { console.log("任务已停止,取消搜索"); return; } // 再次检查是否已完成 if (todayCount >= config.maxRewards) { console.log(`${config.platformName}搜索任务已完成!`); return; } // 准备搜索词 let baseWord = search_words[todayCount % search_words.length]; let searchWord = generateSearchWord(baseWord, newCount); let randomString = generateRandomString(4); let randomCvid = generateRandomString(32); console.log(`准备执行第${newCount}次搜索: "${searchWord}"`); // 先执行滚动和延迟 const searchDelay = config.searchDelay(); console.log(`开始随机延迟计时:${searchDelay / 1000}秒后执行第${newCount}次搜索...`); // 同时开始滚动(不等待滚动完成) console.log(`同时开始页面滚动...`); smoothScrollToBottom(); // 滚动和延迟并行进行 // 延迟时间到后,先检查是否需要暂停 setTimeout(function () { if (isTaskStopped) { console.log("任务已停止,取消搜索"); return; } // 检查是否需要暂停(在执行搜索之后检查) const shouldPause = enable_pause && newCount % 5 === 0 && newCount < config.maxRewards; // 先执行搜索,无论是否需要暂停 console.log(`执行第${newCount}次搜索`); // 如果需要暂停,设置一个标记,在搜索结果页面加载后处理暂停 if (shouldPause) { // 设置一个会话存储标记,表示这次搜索后需要暂停 sessionStorage.setItem('needPauseAfterSearch', 'true'); sessionStorage.setItem('pauseTime', config.pauseTime.toString()); console.log(`标记第${newCount}次搜索完成后需要暂停${config.pauseTime / 60000}分钟`); } // 执行搜索(无论是否需要暂停都先执行搜索) executeSearch(todayCount, searchWord, randomString, randomCvid); // 注意:executeSearch会立即跳转页面,所以这里不能更新计数器 // 计数器的更新需要在新页面加载后进行 }, searchDelay); } // 实现平滑滚动到页面底部的函数(移动端优化版) function smoothScrollToBottom(callback) { // callback 是可选参数 // 移动端需要更长的等待时间,因为搜索结果加载较慢 const waitTime = isMobile ? 4000 : 1500; // 简化等待滚动日志 setTimeout(() => { // 移动端需要更多检查次数和更长间隔 let checkCount = 0; const maxChecks = isMobile ? 10 : 6; const checkInterval = isMobile ? 800 : 500; let lastHeight = 0; let stableCount = 0; // 连续稳定次数 function checkAndScroll() { const currentHeight = document.body.scrollHeight; const hasSearchResults = document.querySelector('#b_results, .b_algo, .b_searchboxForm, [data-priority]'); // 简化滚动检查日志 // 检查页面高度是否稳定 if (currentHeight === lastHeight) { stableCount++; } else { stableCount = 0; lastHeight = currentHeight; } // 满足以下条件之一就开始滚动: // 1. 页面高度连续2次稳定且检测到搜索结果 // 2. 达到最大检查次数 // 3. 页面高度足够大(说明内容已加载) const shouldScroll = (stableCount >= 2 && hasSearchResults) || checkCount >= maxChecks - 1 || currentHeight > 2000; if (shouldScroll) { // 简化滚动开始日志 performScroll(); } else { checkCount++; setTimeout(checkAndScroll, checkInterval); } } function performScroll() { const startPosition = window.pageYOffset; const targetPosition = Math.max(0, document.body.scrollHeight - window.innerHeight); const distance = targetPosition - startPosition; const duration = config.scrollDuration; let startTime = null; // 简化滚动详情日志 function animation(currentTime) { if (startTime === null) startTime = currentTime; const timeElapsed = currentTime - startTime; const progress = Math.min(timeElapsed / duration, 1); const easeInOutQuad = progress < 0.5 ? 2 * progress * progress : 1 - Math.pow(-2 * progress + 2, 2) / 2; const currentPosition = startPosition + (distance * easeInOutQuad); window.scrollTo(0, currentPosition); if (progress < 1) { requestAnimationFrame(animation); } else { // 简化滚动完成日志 // 移动端额外滚动一点,确保触发更多内容加载 if (isMobile && distance > 100) { setTimeout(() => { window.scrollTo(0, window.pageYOffset + 200); // 简化移动端滚动日志 // 移动端额外滚动完成后调用回调 if (callback) callback(); }, 500); } else { // PC端或滚动距离小的情况,直接调用回调 if (callback) callback(); } } } if (distance > 30) { // 进一步降低最小滚动距离阈值 requestAnimationFrame(animation); } else { // 简化跳过滚动日志 // 跳过滚动时也要调用回调 if (callback) callback(); } } // 开始检查 checkAndScroll(); }, waitTime); } }