// ==UserScript==
// @name Viewer list bot remover
// @namespace https://gf.qytechs.cn/scripts?set=586193
// @version 1.2.2
// @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==
/*
* OPTIONS
* Modify the following variable for the behavior concerning moderator bots:
*/
const modBotsBehavior = 2;
/*
* 0: Keep them in the Moderators panel
* 1: Place them with the other bots
* 2: Place them in their own panel
*/
let viewersPanelName = "";
let moderatorsPanelName = "";
const botsPanelTitle = "Bots";
const botsPanelDescription = "Description for bots... Well they're bots :)";
const botImageSource = "https://cdn-icons-png.flaticon.com/512/9092/9092067.png";
const modBotsPanelTitle = "Moderator bots";
const modBotsPanelDescription = "Bots used for the moderation of this channel.";
const modBotImageSource = "https://static-cdn.jtvnw.net/badges/v1/3267646d-33f0-4b17-b3df-f923a41db1d0/2";
// Must keep in alphabetical order !!
const botList = [
"007_arthurzz",
"01ella",
"01olivia",
"0arty",
"0ax2",
"0ax5",
"0gb0",
"0hmygirl_",
"0nayli",
"0niva",
"0swallowtail0",
"0ues",
"12317o",
"17liryk",
"1xxquackityxx1",
"24_7_chatting_on_discord",
"24_7_music",
"25godlord",
"38antsy",
"4fxz",
"5ipahi",
"74i4",
"8466321",
"90665921",
"9kmmrbot",
"__mutabor__",
"a5230",
"a_ok",
"a_strangegoose",
"aaaabb99",
"aaron_bermy",
"abcdelf3",
"abiscall",
"abjuui",
"abomb_",
"actually__hannah",
"adrianbarria5",
"advocateplatform",
"adwin666",
"ae86toyota",
"aeonvjack",
"aeroverra",
"agent347",
"aghabaghlava",
"agnis1982",
"agro_kid00",
"ahcydraws",
"ahmed1626727",
"aho0110",
"airblueorc",
"airport_devil_nexuia",
"aitortilla_y_ejarramantas",
"aj_hyper_bit",
"aka_dev_acc",
"aka_kvn",
"akadelta7",
"akaskai",
"alaannn6",
"alan_trd",
"albuchinaa",
"ale59_67",
"alexander_rex_tellus",
"alexdkvip",
"alexisssu",
"alexmur369",
"alexonpeace",
"algoinde",
"aliceydra",
"aliengathering",
"alondrita_2",
"alt512",
"amelaura",
"amine69lyn",
"ampix_123",
"ana35421",
"anaoooo",
"ancient77",
"andro19",
"angband5",
"angel_89tw",
"angelthumpdev",
"angie_kn",
"anon_uwu",
"anotherttvviewer",
"anthropologydept",
"anub1sk",
"aolpb102",
"applecomputers",
"aram_zam_zam13",
"arfabulos",
"arkany_19",
"artemtotti",
"arthurdemonike0",
"artificialsuperman5736391",
"aten",
"audycia",
"avasemaphore",
"avedagamer19",
"avocadoofdoom",
"avocadorable666",
"azayasa",
"azayzull",
"azuka_bdx",
"baatseoisiman",
"ball857",
"barakgar",
"basesqurzee",
"basti4n_tv",
"batterychu5733",
"bbangddeock",
"beatz",
"bebe391",
"beechie",
"beeeeeemong",
"bekiov",
"beppooooooo",
"big__jay__",
"bigbluedeer",
"bigfinfrank",
"bigmonitor69",
"black0ts",
"blackfreeze17",
"blackthe09",
"blade2588",
"bladexzz",
"blankit94",
"blasius82",
"blebbelb",
"blerp",
"blgdamjudge",
"bmang22",
"bonegollrang",
"bonfiredes",
"botisimo",
"bozman18",
"breeze210",
"brickbandson",
"broganrobinson41",
"bronco_86",
"brukernavn0",
"btovar3",
"bubbleduckluck69",
"buddi_bot",
"buddy_love",
"buhr4k",
"bunnyfunnies",
"burning_scar",
"burrb0nwhisk3y",
"business_daddy",
"businesss",
"buttsbot",
"butwhenwilltheylearn",
"bybobmarley",
"bydo_life",
"cadaverinoo",
"calveeezy",
"caonimaas",
"capitao8384",
"captain_hazza",
"captainmare",
"captainskrew",
"captwooty",
"casdune",
"casinolytics",
"chan_serv",
"charbuckss",
"check_your_posture",
"chessmaestro1986",
"chflorinn",
"chikennnnnnnnnnnnnnnnnnn",
"chipmunkundercover",
"chmielu_ch",
"chooego",
"chopbboo_",
"chris48x",
"christoph_waltz",
"chuckernout",
"chung0230",
"civangaming_",
"cjwprostar",
"ck7tomas",
"clipebox",
"cna1s",
"coco_poops",
"cocopine",
"codyppow_12",
"coldsky1028",
"commanderroot",
"competitivestreamwatcher",
"conanwon",
"conqueeftador278",
"cool_noory",
"corn3658",
"cpt_debay",
"cptteempo",
"creatisbot",
"crimzonleon",
"crni_panter028",
"crossbusted",
"cunkas10",
"cupidyu",
"cute_apeach",
"cuzimking5",
"cyderverse",
"cyndyka",
"d0ce___",
"d0minikb2000",
"d3v1l5_r3j3ct",
"d9141809",
"danaplaces",
"danny8376",
"danoba",
"danyfer97",
"darkestofknights_",
"darklarth",
"darrik",
"dasxodnes",
"dawok",
"dbalswkd2358",
"ddidierdusalanga",
"ddukyeol",
"delotx",
"delta_brainwave",
"delusion_011",
"demonio_x0",
"denilsonbarbos",
"denis13579",
"denny91809",
"deny_____________________",
"derath90",
"dergurkii",
"derkautz",
"devjimmyboy",
"df890089",
"diavolik898",
"diegoalonso2222t4r",
"dieguitto78",
"digitalinstinct",
"digyourownhole",
"dinozayr",
"dio_le_cuisto",
"discord_for_streamers__",
"discordstreamercommunity",
"dodoom7",
"dogfunny",
"dominguez_575",
"donationalerts_",
"doritozu",
"dotabod",
"dragonsword563",
"drapsnatt",
"drocck_sy_12-",
"dubr0vsq",
"dugank",
"dwoeste",
"dwsunshine",
"dyadya_zhenya93",
"dynamicgemini",
"dynaterra",
"dyslexia11",
"e7565566e",
"e7d_",
"e_ternalyfe",
"echtkpvl",
"ecoradium",
"edellyna",
"eggyoe",
"einfachfussel",
"einfachmxrc",
"einfachuwe42",
"eiviind",
"ekoyhubs",
"electiricsheep",
"elgamer752",
"elissaj12",
"ellis_22k",
"elmokramli",
"elysian",
"emagrabontilt",
"enrehh5e59x5ms",
"eotlr43",
"ergler",
"erikdaniel_16",
"ernestoaguilera",
"eu2mm",
"eugenius00",
"ex-alecksey_21",
"ex503344",
"executive06",
"ezobay",
"ezvacss",
"f1yshadow",
"f_macedo",
"fabrimila1",
"fae12345",
"faizdanyal",
"fantomdestroyer",
"faps247",
"faszkivan132",
"feathers__mcgraw__",
"feet",
"felipe_fxp_bx",
"felipedavin",
"felpsfps2",
"felsgood",
"ferodriguezm2000",
"fet1sovgod",
"fet1sovgod",
"fexerit",
"flakodontplay",
"flantori",
"fledgerr",
"floboytwi",
"flocki9525",
"fluffy54605",
"fogwillyfog",
"fomos2001",
"foorce",
"forbearanceday",
"fossabot",
"fpiol",
"fpython",
"freakybabetv",
"fremye",
"freso",
"frostymrostybg",
"frostysandstorm",
"furdnad",
"fzr__",
"gacodemon",
"gamev7878",
"ganadara0123",
"gaversolo",
"geall",
"geeeet",
"gekkogo",
"germaindu17",
"getstreamru",
"ghassan___",
"gianigeorgian",
"gik_gok",
"giockjaws",
"goldhobgoblin",
"goodausk",
"gooedkabuki3016",
"goofycatcher",
"gosugo",
"gotop3035",
"greenmetal201",
"grndcontrol",
"grosslukass",
"gryv",
"gu0ke",
"guiiillerm_7",
"guosheng_aa",
"guywithanamazinghat",
"h2oplusc",
"h3llhound8",
"h4xe",
"haaaton",
"hackmax",
"haithabu_viking",
"hak3r_bot",
"haloshayamasha",
"hama_riahi",
"hampfyren",
"hanhonie",
"hasanoo5",
"hdgf9876",
"hearthstonedecktracker",
"hebmil",
"hectorgr27",
"hellothere751",
"helmijohari_",
"helpmesus2",
"helvetianhobbit",
"hexman20",
"hierbasal",
"highspeedchaos",
"hill",
"hipmandrew",
"hodudgkr",
"hoid__",
"hook_trovo",
"hortalica",
"hrutsson",
"hseki",
"huehang",
"hydrate322115_devilish",
"hyperghostxd",
"i_emka",
"iamgoodyes",
"iansalless",
"ibluna",
"icaro12oliveira",
"icekream",
"id17171717",
"ideavoid",
"ieyeeyee",
"iisabei",
"illllliiiilff",
"ilybeamic",
"imitate34",
"impalatv",
"imperfektdaemon",
"imthebesthere",
"infinite_c0re",
"intersyy",
"iqtdf8412",
"isnicable",
"isqvn",
"issnoopy",
"itchy_utflod",
"its_bluntman",
"its_nisgme",
"itsderob",
"itsrobert",
"itsvodoo",
"iviotic",
"ivyharvie",
"ixneilxi",
"jackmaks",
"jamiexavier",
"jan1997b",
"jarmoest",
"jarppiz",
"jaseyang",
"jayohya",
"jbbresh",
"jenix0528",
"jerren",
"jhodymoon",
"jhonny021",
"jiffjj",
"jimmylin",
"jinal",
"jinwoo54",
"jivedevil13",
"jjunn5699",
"jo_jo_nyeb",
"job0209",
"joe6124",
"joei__",
"johnchicken699",
"jonas_",
"jose_ramiro_q",
"josefirex",
"josejaviergud",
"joyc13sou",
"joztr",
"jrooks86",
"juancabardo",
"jungjy2002",
"junkisly",
"justblxkk",
"justintheshell",
"jvaad",
"jxmedinan",
"jymboshrimp",
"k0bep_",
"k1ng_cal4brese",
"k1tty_zx",
"k4vity_",
"k__2022",
"kai_thedhai",
"kaiouzus",
"kana_pei",
"kandalor",
"kappa_votes",
"kardez_1",
"kasilo",
"kat_tomboy",
"kataztrophik",
"katsuloll",
"kattah",
"kattynah",
"kawada_tenshi",
"kayleedepaolaa",
"kdhoo0422",
"kelvin15826952",
"kennethjaxon",
"kenshiro26",
"kenso247",
"kevin53_6536",
"kevin_1006",
"kexves",
"kheironzade",
"khmadoka",
"kidteteu",
"kimtwo10",
"kingkong_1020",
"kirby011",
"kittenrescue",
"kittykat513",
"klarc",
"klunky",
"knight124002296",
"kodiakbrujah",
"kofistreambot",
"kohagames",
"kolis22",
"krizmat",
"krokoloko88",
"kuacnai",
"kusanagi2k5",
"kusolistener2",
"kwarcinskia",
"laeppatohtori",
"laguitoss",
"laptopdud3",
"larakraf",
"lastdice",
"laurent20222",
"lazy_nara",
"lazywill87",
"ldk9812",
"leogiraa",
"leonag110107",
"leoriioooo",
"leovalen1",
"leroypierre",
"lewdprim",
"lg_angel1710",
"lightninggamertr",
"lilian__n",
"liliovvy",
"lionheart_swe",
"lipatovaa",
"lipes99",
"littlecill",
"lizletty",
"ljlcard",
"loftyvtr",
"lolnotnate",
"lolrankbot",
"lone_star",
"lonewolf6117",
"lordleon77",
"lorypub",
"losjaraswines",
"louiexu",
"lovey1903",
"lucabucaduca",
"lucentcrown1234567891011",
"luis_el_beto_",
"luke_skywalker325",
"luki4fun_bot_master",
"lumiastream",
"lunchbar",
"lurxx",
"lylituf",
"lyrabut",
"lzrdblzzrd",
"m1stzwastaken",
"m3tal_monkey",
"m4st3rx01",
"mabus98",
"mactep__4ex",
"maddynsun",
"maddyson_moy_bog",
"maiwou36",
"makdokken138",
"maly_90",
"mando8574",
"mango944",
"manning_wilkins",
"mararomano",
"marioj94",
"markzynk",
"martensv",
"master_dinochan",
"matmeds",
"matteow05",
"matthias_mrb",
"mattylol",
"max_blanck",
"maxother",
"maxswellfilho",
"mayhem614",
"mcbdakilla",
"meanmorbid",
"meatballgangsta",
"medre",
"megalux17xd",
"mfam_diaz",
"mgsintruder",
"mhs1710",
"mhytrarl",
"michaelrpg",
"miczi11",
"mikeymax23",
"milio2405",
"minion619",
"misarol",
"mistahjoe",
"misterzmarkz",
"mito_kuhaku",
"moffetking_gaming",
"moisesalbertinss",
"mojomarvelous",
"moneyhoarder",
"monovid",
"moobot",
"mota_gada",
"mr_gamers_tv",
"mr_hipe",
"mr_protocol",
"mrfikulat",
"mrjiz1",
"mrksmnio",
"mrmalet",
"mtgbot",
"myself_",
"mythicalasscheeks",
"myyooou",
"n1ceeqq",
"na_icke_erst",
"naeramarth",
"nakanishi893",
"nartman99",
"nasiislife",
"nasty_____",
"natzelly",
"navsar3",
"ndg4355",
"nekodemon76",
"neo86869",
"nephetes",
"nerobathory",
"network_streamer_discord",
"nicdipples",
"nichtdanger",
"nicki26241",
"nickv54",
"niclasfinn",
"nicolaspexorro",
"nightbot",
"nightchillbc",
"nightlights22",
"nightmarejoker2",
"ninatela",
"nittygrittycity",
"nivedhgta5",
"niventho",
"nizmo4",
"nle_aboba",
"noblewolf",
"noluckwithnames",
"nonafayeclaypool",
"nono__0401",
"north4life",
"nosmad5",
"notesaki",
"notmedic",
"notmemez",
"nuxbot_com",
"nyoodlebrain",
"obsessedgamer77",
"official_tubebot",
"ogladygaga",
"ohbot",
"oiamiano",
"omg_fashionman",
"omicron",
"omnikiller958",
"oni_monarch",
"onlyone_k3ll",
"oopsies49",
"osmankrtl53",
"ostovero",
"outcontrol23",
"own3d",
"p1drneo",
"panic45",
"paradise_for_streamers",
"paradogx",
"partment",
"paula_nahomi",
"pdp_bot",
"peanutk_k",
"pechpils",
"peepostreambot",
"peppsitrinker",
"perznoce",
"phoenixleon",
"phoenpc",
"phoerou",
"pianoplayer88key",
"pigeon_6417",
"piouswig",
"pixelbypixel_bot",
"plaginator",
"play24hrs",
"playwithviewersbot",
"pogbaa__",
"pokemoncommunitygame",
"pokernemo",
"poku777",
"polasscan",
"popypplaytimee",
"por3m",
"ppmarely",
"praktic326",
"progrueso",
"public_enemy821",
"punkmetalska",
"puptime",
"pwn",
"pycroas",
"q1zz_",
"q_acula",
"qawsedrf1211",
"qnfgogtktls",
"quaking_nut",
"quote_if_v1_von",
"quynguyen10",
"qwe402040402",
"r0vaa",
"rafaelima_ch",
"rainman7_7",
"raiwo",
"rajeshkoolps4",
"rammy0407",
"ranger341",
"rare__potato",
"ratitasonriente",
"raventheespada",
"rea_lovesy123",
"reallifetsundere",
"reapxhemi",
"rebelprince",
"ree_is",
"refuzz_",
"reggx",
"reginaldolhp23",
"regisboeing",
"remasuri_bot",
"remix01906",
"remy_tw",
"renancosta",
"requiredusername1",
"resinify",
"restreambot",
"reyben3000",
"rikellme_",
"rinnuxx",
"rippedmann",
"ririi29",
"rkn_fry",
"rladmsdb88",
"rlalftjfb",
"rmenchik",
"rogueg1rl",
"rogueshady",
"rokkuon_sutoratosu",
"roxesy",
"royaljzx",
"rsef722721",
"rupshiffu_",
"ryokunox",
"s1ly228",
"saberj716",
"sablotron",
"sadanddepresso",
"sagakflask",
"sakua28",
"salemggwp",
"sam1e_eu",
"sanctiifiied",
"sanguinis013",
"sanisk_rs",
"sanjayragu9105",
"sanniee",
"saralna",
"sardanapalos420",
"saturos87",
"saydrodriguess",
"schmuckle13",
"scriptorex",
"scurvymitch",
"seanbean3000",
"senseiwu_chan",
"servicemedal",
"sery_bot",
"shadon34",
"shadowkniche02",
"shadowmane4",
"shalavan",
"shanszxc123",
"shanuala",
"shepherdshang",
"shiggitty",
"shonon_dy",
"show__gg__",
"shuabeenz",
"shypuf",
"sidedney",
"sigurniv",
"silvergrayviv",
"silverspiritgod",
"simon_bolski",
"simple148",
"simply_pineapple",
"sirrelu",
"sjfoxs",
"skaterbagel",
"skrypi_",
"slaystation89",
"slickinterior",
"slowpoke_ting",
"slylisk",
"smiterholic",
"smuxged",
"sneakywreckingball",
"solitary0314",
"solsaidimabot",
"someone0neone",
"sonecacps",
"songlistbot",
"sophikal",
"soundalerts",
"soundofraindrops",
"soychicki",
"spadey88",
"sparker_watcher",
"sparklywastaken",
"speedtrix",
"speedysingh",
"spehovacek",
"spolerist",
"sponge1214",
"srekrapstob",
"srokates",
"ssakdook",
"ssayonaras",
"ssgayato",
"sssmajopp",
"staint96",
"staniss",
"starloord1720",
"starman_30",
"starsky8814",
"stayupthetree",
"stealthmodelocke",
"stealthytaters",
"stephanbruh",
"sterymobie",
"stewlew89",
"stone1367",
"strange_vaaanek",
"streamelements",
"streamfahrer",
"streamholics",
"streamlabs",
"streamstickers",
"stuartfm",
"sukitacat",
"sunamano",
"supahsub",
"supavigilante",
"supibot",
"sushi_yes",
"sushixt4",
"sussystussy",
"swooshycueb",
"syhrham",
"synergyxdd",
"szonin",
"t0mas23",
"tachyon87",
"tacotuesday7313",
"tae_0413",
"tanonjaeng",
"tarkovchangesbot",
"tarmaz123",
"tavert0",
"tavmelo",
"tavoec",
"tchukinho_kpopeiro",
"teamliquiddev",
"techniquality",
"tempeyey",
"teufpss",
"texxti",
"thebraverlurkerschweijkg",
"thebytesniper",
"theguy1501",
"thehiiddenn",
"thekingrulz9090",
"thelaughingjoke1975",
"themoatman",
"thepatse",
"therubi02",
"thevoiceinthehead",
"thisiseku",
"thisisunreallol",
"thorekh",
"timeoutwithbits",
"tinarif",
"tlwms1059",
"tml4life17",
"toastyprime",
"tobanikum",
"tomasvamosargentina",
"tontierri",
"tox1c_dodo",
"tranziner",
"trincomonkey",
"truxbrid",
"tshego34",
"tteezzz",
"tteppu_ytkohoc_",
"twiscordbot",
"twitchmodsquad",
"twitchraik",
"twitchrandbot",
"twitchstatstracker",
"tyee",
"tylergl98",
"uchineko",
"umuto123",
"uniukky",
"userdeestefi",
"ve1ryy",
"vedzaa",
"viceeeen",
"vidrochka228",
"vikingomega",
"vitorfluminense",
"volumezeroix",
"vonicky",
"vznumm",
"w3_po1xd",
"w3xios_1",
"wallow177",
"waptart",
"warkaoss",
"wbzc",
"webgems",
"wendy666__",
"wh20",
"whalewatcherggx",
"whataboutgaminglive",
"whodel01",
"whysad08042",
"wizebot",
"woody0987654",
"wook0458",
"wpfid5555",
"wtfainacs",
"wuigi77",
"wzbot",
"xchatterx",
"xctofu",
"xd_mau5",
"xdolos",
"xeclypt",
"xeodk",
"xerxes087",
"xhylane",
"xionvenus",
"xizzzy_2nd",
"xkey",
"xkofi",
"xl3naa",
"xoddi_",
"xqcow_waiting_room",
"xx3nvyxx",
"xx_vov4ik_xx",
"xxxnezuko_yt",
"xzibit200",
"yamickle",
"yarikmodnik_",
"yellow280888",
"yellowpikachu",
"yellowran",
"yoda_odar",
"yomyking",
"yoremeofga",
"youknown0thing",
"yourlocalweeb",
"yuki_0_0_3",
"yungsev_",
"yuskadc",
"zack331203",
"zerox_black",
"zexc_",
"zhijun_0117",
"zltr0n",
"zombieocean",
"zooyxwv",
"zorg666",
"zorkky_",
"zpatopt1",
"zura_janai_katsura__da",
"zurhyxd",
"zurityhehe",
"zxasd159753",
"zxf123",
"zycries"
];
var viewerListShown = false;
var botsPanel = null;
function delay(milliseconds) {
return new Promise(resolve => {
setTimeout(resolve, milliseconds);
});
}
async function detectLanguage() {
var div = document.querySelector('[class="ScInputBase-sc-vu7u7d-0 ScInput-sc-19xfhag-0 gXVFsI jhrDHh InjectLayout-sc-1i43xsx-0 kvZgmT tw-input tw-input--large"]');
let count = 0;
while (div === null) {
await delay(1000);
div = document.querySelector('[class="ScInputBase-sc-vu7u7d-0 ScInput-sc-19xfhag-0 gXVFsI jhrDHh InjectLayout-sc-1i43xsx-0 kvZgmT tw-input tw-input--large"]');
count++;
if (count > 15) {
console.log("[Viewer list bot remover]: Search bar not found, script not working");
return;
}
}
let searchText = div.placeholder;
switch (searchText) {
case "Search":
viewersPanelName = "Viewers";
moderatorsPanelName = "Moderators";
break;
case "Søg":
viewersPanelName = "Seere";
moderatorsPanelName = "Moderatorer";
break;
case "Suchen":
viewersPanelName = "Zuschauer";
moderatorsPanelName = "Moderatoren";
break;
case "Buscar":
viewersPanelName = "Espectadores";
moderatorsPanelName = "Moderadores";
break;
case "Rechercher":
viewersPanelName = "Spectateurs";
moderatorsPanelName = "Modérateurs";
break;
case "Cerca":
viewersPanelName = "Spettatori";
moderatorsPanelName = "Moderatori";
break;
case "Keresés":
viewersPanelName = "Nézők";
moderatorsPanelName = "Moderátorok";
break;
case "Zoeken":
viewersPanelName = "Kijkers";
moderatorsPanelName = "Moderators";
break;
case "Søk":
viewersPanelName = "Seere";
moderatorsPanelName = "Moderatorer";
break;
case "Wyszukaj":
viewersPanelName = "widzowie";
moderatorsPanelName = "Moderatorzy";
break;
case "Pesquisa":
viewersPanelName = "Espetadores";
moderatorsPanelName = "Moderadores";
break;
case "Căutare":
viewersPanelName = "Vizualizatori";
moderatorsPanelName = "Moderatori";
break;
case "Hľadať":
viewersPanelName = "Diváci";
moderatorsPanelName = "Moderátori";
break;
case "Etsi":
viewersPanelName = "Katsojat";
moderatorsPanelName = "Moderaattorit";
break;
case "Sök":
viewersPanelName = "Tittare";
moderatorsPanelName = "Moderatorer";
break;
case "Tìm kiếm":
viewersPanelName = "Người xem";
moderatorsPanelName = "Người điều hành";
break;
case "Ara":
viewersPanelName = "İzleyici";
moderatorsPanelName = "Moderatörler";
break;
case "Hledat":
viewersPanelName = "Diváci";
moderatorsPanelName = "Moderátoři";
break;
case "Αναζήτηση":
viewersPanelName = "Θεατές";
moderatorsPanelName = "Επόπτες";
break;
case "Търсене":
viewersPanelName = "Зрители";
moderatorsPanelName = "Модератори";
break;
case "Поиск":
viewersPanelName = "Зрители";
moderatorsPanelName = "Модераторы";
break;
case "ค้นหา":
viewersPanelName = "ผู้ชม";
moderatorsPanelName = "ผู้ดำเนินรายการ";
break;
case "搜索":
viewersPanelName = "观众";
moderatorsPanelName = "管理员";
break;
case "搜尋":
viewersPanelName = "觀眾";
moderatorsPanelName = "Mod";
break;
case "検索":
viewersPanelName = "視聴者数";
moderatorsPanelName = "モデレーター";
break;
case "검색":
viewersPanelName = "시청자 수";
moderatorsPanelName = "매니저";
break;
default:
alert("Unknown language !");
break;
}
//alert(`viewers:${viewersPanelName}, mods:${moderatorsPanelName}`);
}
void async function () {
'use strict';
await detectLanguage();
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", communityButtonClick);
}
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 > 300) // 50ms * 300 = 15s
{
console.log("[Viewer list bot remover]: Loading took too long");
return;
}
await delay(50);
}
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, container) {
let viewers = panel.firstChild.lastChild;
let bots = [];
for (let i = 0; i < viewers.children.length; 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 === 0) {
panel.remove();
}
return bots;
}
function createBotsPanel(panel, container, options) {
let newPanel = panel.cloneNode(true); // Doesn't copy event listeners FeelsSadMan
let botImg = document.createElement("img");
botImg.setAttribute("class", "InjectLayout-sc-1i43xsx-0 lfGYGL tw-image");
botImg.setAttribute("alt", "Bot badge");
botImg.setAttribute("src", options.ImageSrc);
newPanel.firstChild.children[0].firstChild.children[0].remove();
newPanel.firstChild.children[0].firstChild.insertBefore(botImg, newPanel.firstChild.children[0].firstChild.firstChild);
newPanel.firstChild.children[0].firstChild.children[1].firstChild.innerHTML = options.Title;
newPanel.firstChild.children[1].innerHTML = options.Description;
let viewers = newPanel.firstChild.children[2];
while (viewers.firstChild) {
viewers.removeChild(viewers.firstChild);
}
container.appendChild(newPanel);
return newPanel;
}
function handleViewerPanel(panel, container) {
let bots = removeBots(panel, container);
if (bots.length === 0) {
return;
}
if (botsPanel === null) {
botsPanel = createBotsPanel(panel, container, {ImageSrc: botImageSource, Title: botsPanelTitle, Description: botsPanelDescription});
}
let viewers = botsPanel.firstChild.lastChild;
for (let bot of bots) {
viewers.appendChild(bot);
}
}
function handleModeratorPanel(panel, container) {
if (modBotsBehavior < 0 || modBotsBehavior > 2) {
alert("[Viewer list bot remover]: modBotsBehavior incorrectly set.");
return;
}
if (modBotsBehavior === 0) {
return;
}
let bots = removeBots(panel, container);
if (bots.length === 0) {
return;
}
let viewers;
if (modBotsBehavior === 1) {
botsPanel = createBotsPanel(panel, container, {ImageSrc: botImageSource, Title: botsPanelTitle, Description: botsPanelDescription});
viewers = botsPanel.firstChild.lastChild;
}
if (modBotsBehavior === 2) {
let modBotsPanel = createBotsPanel(panel, container, {ImageSrc: modBotImageSource, Title: modBotsPanelTitle, Description: modBotsPanelDescription})
viewers = modBotsPanel.firstChild.lastChild;
}
for (let bot of bots) {
viewers.insertBefore(bot, viewers.firstChild);
}
}
async function communityButtonClick() {
if (viewerListShown) {
viewerListShown = false;
return;
}
viewerListShown = true;
var container = await getContainer();
if (container.children.length === 1) {
// No one in chat
return;
}
let endScroll = container.lastChild.lastChild.lastChild.lastChild;
endScroll.remove();
//const start = Date.now();
botsPanel = null;
for (let i = 1; i < container.children.length; i++) {
let panel = container.children[i];
let panelName = panel.firstChild.firstChild.firstChild.children[1].firstChild.firstChild.textContent;
switch (panelName) {
case moderatorsPanelName:
handleModeratorPanel(panel, container);
break;
case viewersPanelName:
handleViewerPanel(panel, container);
break;
}
if (panel.parentElement === null) {
// Panel was empty, and got removed
i--;
}
}
container.lastChild.lastChild.lastChild.appendChild(endScroll);
//const end = Date.now();
//console.log(`[Viewer list bot remover]: Execution time: ${end - start} ms`);
}