您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Also unmutes and refreshes on video player error.
- // ==UserScript==
- // @name Refresh when streamer goes live
- // @namespace https://github.com/Dragosarus/Userscripts/
- // @version 2025-06-04
- // @description Also unmutes and refreshes on video player error.
- // @author Dragosarus
- // @match https://www.twitch.tv/*
- // @icon https://www.google.com/s2/favicons?sz=64&domain=twitch.tv
- // @grant GM_registerMenuCommand
- // @grant GM_setValue
- // @grant GM_getValue
- // @compatible firefox
- // @license Unlicense
- // ==/UserScript==
- (function() {
- 'use strict';
- // Time to wait for the Twitch UI to load
- const INITIAL_DELAY_MS = 10000;
- // Check interval
- const CHECK_INTERVAL_MS = 1000;
- // Enables console logs ("rwsgl: ...")
- const ENABLE_LOGS = true;
- // Unmute after reloading
- const UNMUTE_AFTER_RELOAD = true;
- // Refresh if the player encounters an error
- const RELOAD_ON_ERROR = true;
- // Will refresh the page regardless of live status.
- const DEBUG = false;
- const SELECTORS = {
- // The "LIVE" label under the streamer's profile picture
- "live": ".ScChannelStatusTextIndicatorMask-sc-qtgrnb-1",
- // The "↗ Chat" button
- "chat": "p.ScTitleText-sc-d9mj2s-0:nth-child(2)",
- // The text when hovering over the volume button when muted
- // NOTE: may depend on language settings
- "unmute": '[aria-label="Unmute (m)"]',
- // Class that is only present when the video player encountered
- // an error (e.g. #5000)
- "playerError": ".jjYHlC",
- };
- // Reload only if the streamer wasn't live (and later is)
- let wasLive = true;
- function log(...args) {
- if (ENABLE_LOGS) {
- args.unshift("rwsgl:");
- console.log.apply(this, args);
- }
- }
- function clickIfPresent(selector) {
- if (document.querySelector(selector)) {
- document.querySelector(selector).click();
- }
- }
- function isLive() {
- // BUG: will react to the LIVE label in the "While {streamer} is offline, check out:" window.
- return DEBUG || document.querySelector(SELECTORS.live) != null;
- };
- function playerError() {
- return document.querySelector(SELECTORS.playerError) != null;
- }
- function reload() {
- GM.setValue("reload", true);
- window.location.reload();
- }
- function checkLive() {
- let live = isLive();
- if (isLive() && !wasLive) {
- reload();
- } else if (playerError() && RELOAD_ON_ERROR) {
- log("Player error:", document.querySelector(SELECTORS.playerError));
- reload();
- }
- setLive();
- setTimeout(checkLive, CHECK_INTERVAL_MS);
- }
- function setLive() {
- // Do not reload if the streamer is already live
- wasLive = isLive() && !DEBUG;
- log("Live? " + wasLive);
- }
- function init() {
- setLive();
- // If we just reloaded, ...
- let reload = GM_getValue("reload", false);
- if (reload) {
- GM_setValue("reload", false);
- // Go to the chat view
- clickIfPresent(SELECTORS.chat);
- // Unmute if the stream is muted
- if (UNMUTE_AFTER_RELOAD) {
- clickIfPresent(SELECTORS.unmute);
- }
- }
- setTimeout(checkLive, INITIAL_DELAY_MS + CHECK_INTERVAL_MS);
- }
- GM_registerMenuCommand('Reset live status', function() {
- setLive();
- }, 'r');
- setTimeout(init, INITIAL_DELAY_MS);
- })();