使用最激进的方法强制后台运行
当前为
// ==UserScript==
// @name 终极后台自动阅读脚本
// @namespace http://tampermonkey.net/
// @version 3.0
// @description 使用最激进的方法强制后台运行
// @author You
// @match https://linux.do/*
// @grant none
// @license AIBot
// ==/UserScript==
(function() {
'use strict';
let isRunning = false;
let scrollCount = 0;
let visitedPosts = new Set();
let keepAliveInterval = null;
let scrollInterval = null;
let lastScrollTime = 0;
let backgroundCheckInterval = null;
// 终极保活方法
function ultimateKeepAlive() {
// 1. 重写所有页面可见性API
const originalHidden = Object.getOwnPropertyDescriptor(Document.prototype, 'hidden') ||
Object.getOwnPropertyDescriptor(document, 'hidden');
Object.defineProperty(document, 'hidden', {
get: () => false,
configurable: true,
enumerable: true
});
Object.defineProperty(document, 'visibilityState', {
get: () => 'visible',
configurable: true,
enumerable: true
});
// 2. 阻止所有可能暂停的事件
const events = ['visibilitychange', 'blur', 'focus', 'pagehide', 'pageshow', 'beforeunload', 'unload'];
events.forEach(event => {
window.addEventListener(event, (e) => {
e.stopImmediatePropagation();
e.preventDefault();
}, { capture: true, passive: false });
document.addEventListener(event, (e) => {
e.stopImmediatePropagation();
e.preventDefault();
}, { capture: true, passive: false });
});
// 3. 创建持续的音频上下文
try {
const audioContext = new (window.AudioContext || window.webkitAudioContext)();
const oscillator = audioContext.createOscillator();
const gainNode = audioContext.createGain();
oscillator.connect(gainNode);
gainNode.connect(audioContext.destination);
gainNode.gain.setValueAtTime(0.001, audioContext.currentTime); // 极小音量
oscillator.frequency.setValueAtTime(20000, audioContext.currentTime);
oscillator.start();
console.log('🔊 音频上下文已创建');
} catch (e) {
console.log('音频创建失败:', e);
}
// 4. 创建WebRTC连接保持活跃
try {
const pc = new RTCPeerConnection();
const dc = pc.createDataChannel('keepalive');
pc.createOffer().then(offer => pc.setLocalDescription(offer));
console.log('📡 WebRTC连接已创建');
} catch (e) {
console.log('WebRTC创建失败:', e);
}
// 5. 持续的网络请求和用户活动模拟
keepAliveInterval = setInterval(() => {
// 网络请求保活
fetch('/srv/status', { method: 'HEAD' }).catch(() => {});
// 模拟多种用户活动
const events = [
new MouseEvent('mousemove', {
view: window,
bubbles: true,
cancelable: true,
clientX: Math.random() * 10,
clientY: Math.random() * 10
}),
new MouseEvent('click', {
view: window,
bubbles: true,
cancelable: true,
clientX: 1,
clientY: 1
}),
new KeyboardEvent('keydown', {
view: window,
bubbles: true,
cancelable: true,
key: 'Tab'
})
];
events.forEach(event => {
document.dispatchEvent(event);
});
// 强制页面保持活跃
if (document.hidden) {
console.log('⚠️ 检测到页面隐藏,强制保持活跃');
// 触发页面可见性变化
Object.defineProperty(document, 'hidden', {
get: () => false,
configurable: true,
enumerable: true
});
}
console.log(`💓 保活心跳 [${new Date().toLocaleTimeString()}] [Hidden:${document.hidden}]`);
}, 3000); // 减少间隔到3秒,更频繁保活
console.log('🔒 终极保活系统已启动');
// 6. 后台检测和自动恢复机制
backgroundCheckInterval = setInterval(() => {
const now = Date.now();
const timeSinceLastScroll = now - lastScrollTime;
// 如果超过10秒没有滚动,说明可能被暂停了
if (isRunning && timeSinceLastScroll > 10000) {
console.log('⚠️ 检测到滚动停止,尝试恢复...');
// 重新启动滚动
if (scrollInterval) {
clearInterval(scrollInterval);
}
scrollInterval = setInterval(() => {
if (!isRunning) return;
doScroll();
}, 800);
console.log('🔄 滚动已重新启动');
}
// 检查页面状态
if (document.hidden) {
console.log('⚠️ 页面在后台,强制保持活跃状态');
// 重新设置页面可见性
Object.defineProperty(document, 'hidden', {
get: () => false,
configurable: true,
enumerable: true
});
}
}, 5000); // 每5秒检查一次
}
// 获取帖子链接 - 优化版本,缓存结果
let cachedLinks = null;
let lastCacheTime = 0;
const CACHE_DURATION = 2000; // 2秒缓存
function getPostLinks() {
const now = Date.now();
// 使用缓存结果
if (cachedLinks && (now - lastCacheTime) < CACHE_DURATION) {
return cachedLinks;
}
const selectors = [
'.topic-list tbody tr .main-link a.title',
'.topic-list tbody tr td a.title',
'.topic-list tr td a[href*="/t/"]',
'table tr td a[href*="/t/"]',
'a[href*="/t/"]'
];
let links = [];
for (const selector of selectors) {
links = document.querySelectorAll(selector);
if (links.length > 0) break;
}
const filteredLinks = Array.from(links).filter(link => {
return link.href &&
link.href.includes('/t/') &&
!visitedPosts.has(link.href) &&
link.textContent.trim().length > 5;
});
// 缓存结果
cachedLinks = filteredLinks;
lastCacheTime = now;
return filteredLinks;
}
// 进入帖子
function enterPost() {
const links = getPostLinks();
if (links.length === 0) return false;
const randomLink = links[Math.floor(Math.random() * links.length)];
console.log(`🎯 进入: ${randomLink.textContent.trim().substring(0, 30)}...`);
visitedPosts.add(randomLink.href);
randomLink.click();
return true;
}
// 检测页面类型
function getPageType() {
return window.location.href.includes('/t/') && window.location.href.match(/\/\d+$/) ? 'post' : 'list';
}
// 执行滚动 - 智能加速版本
function doScroll() {
if (!isRunning) return;
// 更新最后滚动时间
lastScrollTime = Date.now();
scrollCount++;
const pageType = getPageType();
const time = new Date().toLocaleTimeString();
console.log(`🔄 [${time}] 滚动#${scrollCount} [${pageType}] [Hidden:${document.hidden}] [Visibility:${document.visibilityState}]`);
const scrollTop = window.pageYOffset;
const windowHeight = window.innerHeight;
const documentHeight = document.documentElement.scrollHeight;
// 智能滚动距离:列表页面更快,帖子页面适中
let scrollDistance = 150; // 默认距离
if (pageType === 'list') {
scrollDistance = 200; // 列表页面更快
} else if (pageType === 'post') {
scrollDistance = 100; // 帖子页面适中,便于阅读
}
// 智能底部检测 - 提前触发避免浪费滚动
const distanceToBottom = documentHeight - (scrollTop + windowHeight);
const isNearBottom = distanceToBottom <= 200; // 提前200px检测
if (isNearBottom) {
console.log(`📍 接近页面底部 (距离: ${distanceToBottom}px)`);
if (pageType === 'list') {
if (enterPost()) {
scrollCount = 0;
return;
}
} else {
console.log('📖 返回列表');
window.history.back();
scrollCount = 0;
return;
}
}
// 尝试进入帖子 - 列表页面更频繁尝试
if (pageType === 'list') {
const tryEnterInterval = scrollCount % 2 === 0; // 每2次尝试
if (tryEnterInterval && enterPost()) {
scrollCount = 0;
return;
}
}
// 执行智能滚动
window.scrollBy(0, scrollDistance);
}
// 动态调整滚动间隔
function getScrollInterval() {
const pageType = getPageType();
if (pageType === 'list') {
return 600; // 列表页面更快
} else if (pageType === 'post') {
return 1000; // 帖子页面适中
}
return 800; // 默认
}
// 启动自动阅读
function startReading() {
if (isRunning) return;
isRunning = true;
ultimateKeepAlive();
// 使用setInterval确保后台标签页也能正常工作
scrollInterval = setInterval(() => {
if (!isRunning) return;
doScroll();
}, 800); // 使用固定间隔,setInterval在后台更稳定
console.log('🚀 终极后台自动阅读已启动');
console.log('⚡ 使用setInterval确保后台标签页正常工作');
console.log('🔒 终极保活系统运行中');
}
// 停止自动阅读
function stopReading() {
isRunning = false;
if (scrollInterval) {
clearInterval(scrollInterval);
scrollInterval = null;
}
if (keepAliveInterval) {
clearInterval(keepAliveInterval);
keepAliveInterval = null;
}
if (backgroundCheckInterval) {
clearInterval(backgroundCheckInterval);
backgroundCheckInterval = null;
}
console.log('⏹️ 自动阅读已停止');
}
// 创建控制面板
function createPanel() {
const panel = document.createElement('div');
panel.style.cssText = `
position: fixed;
top: 10px;
right: 10px;
background: linear-gradient(45deg, #ff6b6b, #4ecdc4);
border-radius: 12px;
padding: 16px;
z-index: 99999;
font-family: 'Segoe UI', Arial, sans-serif;
color: white;
box-shadow: 0 10px 25px rgba(0,0,0,0.3);
min-width: 240px;
backdrop-filter: blur(10px);
`;
panel.innerHTML = `
<div style="font-weight: bold; margin-bottom: 12px; text-align: center; font-size: 16px;">
⚡ 终极后台阅读
</div>
<button id="ultimate-start" style="width: 100%; padding: 12px; margin-bottom: 8px; border: none; border-radius: 8px; background: rgba(255,255,255,0.9); color: #333; cursor: pointer; font-weight: bold; font-size: 14px;">
🚀 启动终极阅读
</button>
<button id="ultimate-stop" style="width: 100%; padding: 12px; margin-bottom: 8px; border: none; border-radius: 8px; background: rgba(255,255,255,0.2); color: white; cursor: pointer; font-weight: bold; font-size: 14px;">
⏹️ 停止阅读
</button>
<div style="display: flex; gap: 4px; margin-bottom: 8px;">
<button id="test-links" style="flex: 1; padding: 8px; border: none; border-radius: 6px; background: rgba(255,255,255,0.2); color: white; cursor: pointer; font-size: 12px;">
🔍 检查
</button>
<button id="test-enter" style="flex: 1; padding: 8px; border: none; border-radius: 6px; background: rgba(255,255,255,0.2); color: white; cursor: pointer; font-size: 12px;">
🎯 进入
</button>
</div>
<div style="font-size: 12px; text-align: center; opacity: 0.9; background: rgba(0,0,0,0.2); padding: 8px; border-radius: 6px;">
滚动: <span id="scroll-count">0</span> | 访问: <span id="visited-count">0</span><br>
<span id="page-type">未知</span> | <span id="status" style="font-weight: bold;">已停止</span><br>
<span style="font-size: 10px;">Hidden: <span id="hidden-status">-</span></span>
</div>
`;
document.body.appendChild(panel);
// 事件绑定
document.getElementById('ultimate-start').addEventListener('click', startReading);
document.getElementById('ultimate-stop').addEventListener('click', stopReading);
document.getElementById('test-links').addEventListener('click', () => {
const links = getPostLinks();
console.log(`🔍 找到 ${links.length} 个帖子链接`);
});
document.getElementById('test-enter').addEventListener('click', enterPost);
// 状态更新
setInterval(() => {
document.getElementById('scroll-count').textContent = scrollCount;
document.getElementById('visited-count').textContent = visitedPosts.size;
document.getElementById('page-type').textContent = getPageType();
document.getElementById('status').textContent = isRunning ? '运行中' : '已停止';
document.getElementById('hidden-status').textContent = document.hidden ? 'true' : 'false';
}, 1000);
}
// 初始化
function init() {
console.log('⚡ 终极后台自动阅读脚本已加载');
console.log('💡 使用最激进的方法确保后台运行');
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', createPanel);
} else {
createPanel();
}
}
init();
})();