您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Places bots in their own category in the viewer list.
当前为
// ==UserScript== // @name Viewer list bot remover // @namespace https://greasyfork.org/scripts?set=586193 // @version 1.0 // @description Places bots in their own category in the viewer list. // @author Sonyo // @match http*://www.twitch.tv/* // @grant none // @license MIT // @icon https://cdn-icons-png.flaticon.com/512/9092/9092067.png // ==/UserScript== const viewersPanelName = "Viewers"; // Need change if using a different language ! const botsPanelDescription = "Description for bots... Well they're bots :)"; const botsPanelTitle = "Bots"; // Must keep in alphabetical order !! const botList = [ "01ella", "0ax2", "24_7_chatting_on_discord", "a_ok", "aliceydra", "aliengathering", "anotherttvviewer", "aten", "audycia", "buttsbot", "commanderroot", "creatisbot", "digitalinstinct", "discordstreamercommunity", "drapsnatt", "iisabei", "kattah", "lurxx", "lylituf", "maddynsun", "moobot", "nightbot", "network_streamer_discord", "paradise_for_streamers", "pdp_bot", "qnfgogtktls", "rogueg1rl", "roxesy", "soundalerts", "srekrapstob", "streamelements", "thisisunreallol", "waptart", ]; //const botsPanelHtml = '<div class="Layout-sc-1xcs6mc-0 krdEPl"><button class="InjectLayout-sc-1i43xsx-0 daSCXI"><div class="Layout-sc-1xcs6mc-0 bJDKHm"><img alt="Badge VIP de communauté" class="InjectLayout-sc-1i43xsx-0 lfGYGL tw-image" srcset="https://static-cdn.jtvnw.net/badges/v1/b817aba4-fad8-49e2-b88a-7cc744dfa6ec/2 1x,https://static-cdn.jtvnw.net/badges/v1/b817aba4-fad8-49e2-b88a-7cc744dfa6ec/3 2x" src="https://static-cdn.jtvnw.net/badges/v1/b817aba4-fad8-49e2-b88a-7cc744dfa6ec/2"><div class="Layout-sc-1xcs6mc-0 iBQNvW"><p class="CoreText-sc-1txzju1-0 hronDY">Bots</p></div><div direction="up" class="ScExpandableIndicator-sc-f0maby-0 judUOu expandable-indicator__wrapper"><figure class="ScFigure-sc-wkgzod-0 bIevzH tw-svg"><svg width="2rem" height="2rem" viewBox="0 0 20 20"><path d="M6.5 5.5 11 10l-4.5 4.5L8 16l6-6-6-6-1.5 1.5z"></path></svg></figure></div></div></button><div class="Layout-sc-1xcs6mc-0 hvqWsm">Description for bots... Well they\'re bots :)</div><div class="Layout-sc-1xcs6mc-0"></div></div>'; //const botsPanelHtml = '<div class="Layout-sc-1xcs6mc-0 krdEPl"><button class="InjectLayout-sc-1i43xsx-0 daSCXI"><div class="Layout-sc-1xcs6mc-0 bJDKHm"><img alt="Bot badge" class="InjectLayout-sc-1i43xsx-0 lfGYGL tw-image" src="https://cdn-icons-png.flaticon.com/512/9092/9092067.png"><div class="Layout-sc-1xcs6mc-0 iBQNvW"><p class="CoreText-sc-1txzju1-0 hronDY">Bots</p></div><div direction="up" class="ScExpandableIndicator-sc-f0maby-0 judUOu expandable-indicator__wrapper"><figure class="ScFigure-sc-wkgzod-0 bIevzH tw-svg"><svg width="2rem" height="2rem" viewBox="0 0 20 20"><path d="M6.5 5.5 11 10l-4.5 4.5L8 16l6-6-6-6-1.5 1.5z"></path></svg></figure></div></div></button><div class="Layout-sc-1xcs6mc-0 hvqWsm">Description for bots... Well they\'re bots :)</div><div class="Layout-sc-1xcs6mc-0"></div></div>'; var viewerListShown = false; function delay(milliseconds) { return new Promise(resolve => { setTimeout(resolve, milliseconds); }); } void function() { 'use strict'; let prevUrl = undefined; setInterval(async () => { const currUrl = window.location.href; if (currUrl != prevUrl) { prevUrl = currUrl; await setup(); } }, 60); }(); async function setup() { var communityButton = document.querySelector('[data-test-selector="chat-viewer-list"]'); let count = 0; while (communityButton === null) { await delay(1000); communityButton = document.querySelector('[data-test-selector="chat-viewer-list"]'); count++; if (count > 15) { console.log("[Viewer list bot remover]: Community button not found, script not working"); return; } } viewerListShown = false; communityButton.addEventListener("click", buttonClick); } async function getContainer() { // Get the viewers container var scrollable = null; let count = 1; while (scrollable === null) { scrollable = document.querySelector('[class="scrollable-area scrollable-area--suppress-scroll-x"]'); count++; if (count > 150) // 100ms * 150 = 15s { console.log("[Viewer list bot remover]: Loading took too long"); return; } await delay(100); } return scrollable.lastChild.firstChild.firstChild; } function binarySearch(name) { let start = 0; let end = botList.length - 1; while (start <= end) { let mid = Math.floor((start + end) / 2); if (botList[mid] === name) return true; if (botList[mid] < name) start = mid + 1; else end = mid - 1; } return false; } function removeBots(panel) { let viewers = panel.firstChild.lastChild; let bots = []; for (let i = 0; i < viewers.children.length - 1; i++) { let viewer = viewers.children[i]; let name = viewer.firstChild.firstChild.firstChild.firstChild.textContent; let remove = binarySearch(name.toLowerCase()); if (remove) { viewer.remove(); bots.push(viewer); i--; } } // If there is no more viewers, remove the panel if (viewers.children.length === 1) { panel.remove(); } return bots; } // Also works /*function createBotsPanel(container) { let botsPanel = document.createElement("div"); botsPanel.innerHTML = botsPanelHtml; container.lastChild.after(botsPanel); return botsPanel; }*/ function createBotsPanel(container) { let botsPanel = container.lastChild.cloneNode(true); // Doesn't copy event listeners FeelsSadMan container.lastChild.firstChild.lastChild.lastChild.remove(); let botImg = document.createElement("img"); botImg.setAttribute("class", "InjectLayout-sc-1i43xsx-0 lfGYGL tw-image"); botImg.setAttribute("alt", "Bot badge"); botImg.setAttribute("src", "https://cdn-icons-png.flaticon.com/512/9092/9092067.png"); botsPanel.firstChild.children[0].firstChild.children[0].remove(); botsPanel.firstChild.children[0].firstChild.insertBefore(botImg, botsPanel.firstChild.children[0].firstChild.children[0]); botsPanel.firstChild.children[0].firstChild.children[1].firstChild.innerHTML = botsPanelTitle; botsPanel.firstChild.children[1].innerHTML = botsPanelDescription; let viewers = botsPanel.firstChild.children[2]; while (viewers.children[1]) { viewers.removeChild(viewers.firstChild); } container.lastChild.after(botsPanel); return botsPanel; } function handleViewerPanel(panel, container) { let bots = removeBots(panel); if (bots.length === 0) { return; } let botsPanel = createBotsPanel(container); let viewers = botsPanel.firstChild.lastChild; for (let bot of bots) { viewers.lastChild.after(bot); } } async function buttonClick() { if (viewerListShown) { viewerListShown = false; return; } viewerListShown = true; var container = await getContainer(); for (let i = 1; i < container.children.length; i++) { let panelName = container.children[i].firstChild.firstChild.firstChild.children[1].firstChild.firstChild.textContent; if (panelName === viewersPanelName) { // Viewers handleViewerPanel(container.children[i], container); } } }