您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
No more 4 hours of the mind numbing drivel just to be butt bois'd after less than 1 hour of gaming. Just open the steam,switch tab/monitor and you will be alerted/unmuted when the stalling has ended.
// ==UserScript== // @name Quin Anti-Stall // @namespace Violentmonkey Scripts // @match http*://www.twitch.tv/* // @grant GM_notification // @version 0.9.1 // @author i made this :) // @license MIT // @description No more 4 hours of the mind numbing drivel just to be butt bois'd after less than 1 hour of gaming. Just open the steam,switch tab/monitor and you will be alerted/unmuted when the stalling has ended. // @icon https://cdn.betterttv.net/emote/5f77d7eaccde1f4a870c06c6/3x // ==/UserScript== //SETTINGS-------true = enabled---false = disabled---------------------------------------------------------------// const ALERTS = true; // Displays a notification when the streamer starts playing a game. const AUTO_MUTE = false; // Automatically mutes the stream when the streamer is stalling. const AUTO_UNMUTE = true; // Automatically unmutes the stream when the streamer starts playing a game. // Hatewatch options, will affect viewer count. const AUTO_PAUSE = true; // Automatically pauses the stream while the streamer is stalling. const AUTO_UNPAUSE = true; // Automatically unpauses the stream when the streamer starts playing a game. Inconsistent when the tab is not visible. //---------------------------------------------------------------------------------------------------------------// const STALLING = "Just Chatting"; //TODO add list of stalling catergories let stream_time = null; //currently unused let live = null; //acts as init detection bool let current_game = null; let streamer = null; const callback = function (mutationsList) { //TODO clean this up if (!document.getElementsByClassName("channel-info-content")[0]) { //navigated away from stream pages observer.disconnect(); setTimeout(start_observer, 100); } for (mutation in mutationsList) { let game_node = document.querySelectorAll("[data-a-target='stream-game-link']")[0]; if (game_node) { if (document.getElementsByClassName("tw-channel-status-text-indicator")[0]) { //content has finished loading if (document.getElementsByClassName("tw-channel-status-text-indicator")[0].innerText == "LIVE") { let new_streamer = document.getElementsByClassName("channel-info-content")[0].getElementsByClassName("tw-title")[0].innerText; let new_game = game_node.innerText; live = true; if (new_streamer != streamer && streamer != null) {//switched streamer after loading current_game = null; if (AUTO_PAUSE&&new_game==STALLING) { // twitch likes to unpause you when the new stream loads for(i = 1;i<11;i++){ setTimeout(function() {player_pause(true);},i*100); //need to find a way to wait for twitch to autoplay } } } if (current_game != new_game) { //game changed if (new_game != STALLING && current_game == STALLING) { //stopped stalling //TODO add new game to alert if (ALERTS) { if (!document.hasFocus()) { if (new_streamer == "Quin69") { alert("Clown69 has stopped stalling."); GM_notification("Clown69 has stopped stalling.", "Allo", "https://cdn.frankerfacez.com/emoticon/243789/4", null); } else { alert(streamer + " has stopped stalling."); GM_notification(streamer + " has stopped stalling.", "Allo", "https://cdn.frankerfacez.com/emoticon/243789/4", null); } } } if (AUTO_UNMUTE) { player_mute(false); } if (AUTO_UNPAUSE) { if(!document.hasFocus()){ location.reload(); } else{ player_pause(false); } } } else if (new_game == STALLING && current_game != STALLING) { //stalling if (AUTO_MUTE) { player_mute(true); } if (AUTO_PAUSE) { player_pause(true); } } current_game = new_game; let time_node = document.getElementsByClassName("live-time")[0]; if (!time_node) { time_node = document.querySelectorAll("[data-key='uptime']")[0]; } stream_time = time_node.innerText; streamer = new_streamer; console.group("QAS"); console.log("STREAMER: " + streamer); console.log("CURRENT GAME: " + current_game); console.log("LIVE: " + (document.getElementsByClassName("tw-channel-status-text-indicator")[0].innerText == "LIVE" ? "YES" : "NO")); console.log("STREAM TIME: " + stream_time); console.groupEnd(); break; } } else { if (live == true) { //stream ended if (parseInt(stream_time.split(":")[0]) < 4) { //stream over in less than 4 hours //add flavour alert "surely the vibe isnt off already" } else { //add flavour alert "the circus has closed" } live = false; } } } } } }; function player_mute(status) { const mute_node = document.querySelectorAll("[data-a-target='player-mute-unmute-button']")[0]; const mute_status = (mute_node.ariaLabel == "Mute (m)" ? true : false) if (mute_status == status) { mute_node.click(); } } function player_pause(status) { const play_node = document.querySelectorAll("[data-a-target='player-play-pause-button']")[0]; const play_status = (play_node.attributes.getNamedItem("data-a-player-state").value == "playing" ? true : false); if (play_status == status) { play_node.click(); } } function start_observer() { if (document.getElementsByClassName("channel-info-content")[0]) { observer.observe(document.getElementsByClassName("channel-info-content")[0], { childList: true, subtree: true, attributes: false, characterData: false }) } else { //manages the user starting on non streamer pages, could not find an event to listen for url changes setTimeout(start_observer, 100); } } const observer = new MutationObserver(callback); start_observer();