您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Reload Twitch stream if Error #2000 appears. Full feature set: GUI, retry counter, audio, notifications, logs, dark mode, draggable panel, and error history tracking.
当前为
// ==UserScript== // @name Twitch Auto Reload on Error #2000 (God Mode) // @namespace http://tampermonkey.net/ // @version 5.0 // @description Reload Twitch stream if Error #2000 appears. Full feature set: GUI, retry counter, audio, notifications, logs, dark mode, draggable panel, and error history tracking. // @author You // @match https://www.twitch.tv/* // @grant GM_registerMenuCommand // @license MIT // ==/UserScript== (function () { 'use strict'; const SETTINGS_KEY = 'twitchErrorReloadSettings_v5'; const LOGS_KEY = 'twitchErrorLogs_v5'; const DEFAULT_SETTINGS = { maxRetries: 5, startDelayMs: 5000, reloadDelayMs: 2000, retryCount: 0, darkMode: true, enableAudio: true, enableNotify: true }; let settings = loadSettings(); let logs = loadLogs(); function loadSettings() { const saved = localStorage.getItem(SETTINGS_KEY); return saved ? JSON.parse(saved) : { ...DEFAULT_SETTINGS }; } function saveSettings() { localStorage.setItem(SETTINGS_KEY, JSON.stringify(settings)); } function loadLogs() { const saved = localStorage.getItem(LOGS_KEY); return saved ? JSON.parse(saved) : []; } function saveLogs() { localStorage.setItem(LOGS_KEY, JSON.stringify(logs)); } function logEvent(msg) { const time = new Date().toLocaleTimeString(); const entry = `[${time}] ${msg}`; logs.push(entry); if (logs.length > 50) logs.shift(); // Keep last 50 saveLogs(); updateLogPanel(); } function playAlertSound() { if (!settings.enableAudio) return; const beep = new Audio("https://notificationsounds.com/storage/sounds/file-sounds-1153-pristine.mp3"); beep.volume = 0.5; beep.play(); } function showToast(message, success = true) { if (!settings.enableNotify) return; const toast = document.createElement('div'); toast.innerText = message; toast.style.position = 'fixed'; toast.style.bottom = '20px'; toast.style.left = '50%'; toast.style.transform = 'translateX(-50%)'; toast.style.background = success ? '#28a745' : '#dc3545'; toast.style.color = 'white'; toast.style.padding = '10px 16px'; toast.style.borderRadius = '5px'; toast.style.zIndex = 9999; toast.style.boxShadow = '0 4px 10px rgba(0,0,0,0.3)'; document.body.appendChild(toast); setTimeout(() => toast.remove(), 4000); } function updateLogPanel() { const panel = document.getElementById('log-panel'); if (panel) { panel.innerHTML = '<strong>📜 Error History:</strong><br>' + logs.slice().reverse().map(l => `<div style='margin:2px 0'>${l}</div>`).join(''); } } function createUI() { const container = document.createElement('div'); container.id = 'twitch-reload-ui'; container.style.position = 'fixed'; container.style.top = '20px'; container.style.right = '20px'; container.style.zIndex = '9999'; container.style.padding = '10px'; container.style.borderRadius = '8px'; container.style.boxShadow = '0 4px 12px rgba(0, 0, 0, 0.3)'; container.style.fontFamily = 'Arial, sans-serif'; container.style.width = '280px'; container.style.maxWidth = '90vw'; container.style.cursor = 'move'; applyTheme(container); let offsetX = 0, offsetY = 0, isDragging = false; container.addEventListener('mousedown', function(e) { isDragging = true; offsetX = e.clientX - container.getBoundingClientRect().left; offsetY = e.clientY - container.getBoundingClientRect().top; }); document.addEventListener('mouseup', () => isDragging = false); document.addEventListener('mousemove', function(e) { if (isDragging) { container.style.left = (e.clientX - offsetX) + 'px'; container.style.top = (e.clientY - offsetY) + 'px'; container.style.right = 'auto'; } }); const title = document.createElement('div'); title.innerText = '⚙️ Twitch Auto Reload'; title.style.fontWeight = 'bold'; title.style.marginBottom = '10px'; const counter = document.createElement('div'); counter.id = 'retry-counter'; counter.innerText = `Retries: ${settings.retryCount}/${settings.maxRetries}`; counter.style.marginBottom = '10px'; function createSetting(labelText, type, settingKey, extra = {}) { const wrapper = document.createElement('div'); wrapper.style.margin = '5px 0'; const label = document.createElement('label'); label.innerText = labelText; label.style.display = 'block'; label.style.marginBottom = '2px'; let input; if (type === 'checkbox') { input = document.createElement('input'); input.type = 'checkbox'; input.checked = settings[settingKey]; input.onchange = () => { settings[settingKey] = input.checked; saveSettings(); if (settingKey === 'darkMode') applyTheme(container); }; } else { input = document.createElement('input'); input.type = 'number'; input.value = settings[settingKey]; input.min = extra.min || 0; input.style.width = '100%'; input.onchange = () => { settings[settingKey] = parseInt(input.value); saveSettings(); updateRetryDisplay(); }; } wrapper.appendChild(label); wrapper.appendChild(input); return wrapper; } const retryBtn = document.createElement('button'); retryBtn.innerText = '🔁 Retry Now'; retryBtn.onclick = () => { showToast('Manual Reload', true); logEvent('Manual reload triggered.'); location.reload(); }; const logPanel = document.createElement('div'); logPanel.id = 'log-panel'; logPanel.style.marginTop = '10px'; logPanel.style.maxHeight = '120px'; logPanel.style.overflowY = 'auto'; logPanel.style.fontSize = '12px'; container.appendChild(title); container.appendChild(counter); container.appendChild(createSetting('Max Retries', 'number', 'maxRetries')); container.appendChild(createSetting('Start Delay (ms)', 'number', 'startDelayMs')); container.appendChild(createSetting('Reload Delay (ms)', 'number', 'reloadDelayMs')); container.appendChild(createSetting('Enable Audio', 'checkbox', 'enableAudio')); container.appendChild(createSetting('Enable Notify', 'checkbox', 'enableNotify')); container.appendChild(createSetting('Dark Mode', 'checkbox', 'darkMode')); container.appendChild(retryBtn); container.appendChild(logPanel); document.body.appendChild(container); updateLogPanel(); } function applyTheme(container) { const isDark = settings.darkMode; container.style.backgroundColor = isDark ? '#1f1f23' : '#f4f4f4'; container.style.color = isDark ? '#f4f4f4' : '#1f1f23'; const inputs = container.querySelectorAll('input'); inputs.forEach(input => { input.style.backgroundColor = isDark ? '#333' : '#fff'; input.style.color = isDark ? '#f4f4f4' : '#1f1f23'; }); const buttons = container.querySelectorAll('button'); buttons.forEach(btn => { btn.style.width = '100%'; btn.style.padding = '8px'; btn.style.marginTop = '10px'; btn.style.backgroundColor = isDark ? '#9147ff' : '#e6e6e6'; btn.style.color = isDark ? 'white' : 'black'; btn.style.border = 'none'; btn.style.borderRadius = '5px'; btn.style.cursor = 'pointer'; }); } function updateRetryDisplay() { const counter = document.getElementById('retry-counter'); if (counter) counter.innerText = `Retries: ${settings.retryCount}/${settings.maxRetries}`; } function observeError() { const observer = new MutationObserver(() => { const text = document.body.innerText; if (text.includes('There was a network error. Please try again. (Error #2000)')) { if (settings.retryCount < settings.maxRetries) { settings.retryCount++; saveSettings(); updateRetryDisplay(); playAlertSound(); showToast('Reloading Twitch due to Error #2000...', true); logEvent('Auto reload due to Error #2000'); setTimeout(() => location.reload(), settings.reloadDelayMs); } else { showToast('Retry limit reached. Not reloading.', false); logEvent('Retry limit reached. No reload.'); } } }); observer.observe(document.body, { childList: true, subtree: true, characterData: true }); } // ==UserScript== additions for Tampermonkey menu command // Add menu command to show the UI GM_registerMenuCommand("Show Twitch Reload Panel", () => { const existing = document.getElementById('twitch-reload-ui'); if (existing) { existing.style.display = 'block'; } else { createUI(); } }); document.addEventListener('keydown', (e) => { if (e.key === 'F3') { const panel = document.getElementById('twitch-reload-ui'); if (panel) { panel.style.display = (panel.style.display === 'none') ? 'block' : 'none'; } else { createUI(); } } }); window.addEventListener('load', () => { setTimeout(() => { createUI(); observeError(); logEvent('Observer initialized.'); }, settings.startDelayMs); }); })();
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址