

Egy csomó Twitchhez kapcsolódó projektet csinálok itt-ott, próbálom megnézni, hogy mik a lehetőségek. Az egyik legutóbbi projektem egy Twitch Emote Extension létrehozása volt a Chrome számára, ahol megmutattam, hogyan lehet ingyenesen extra emote “slotokat” szerezni. Ez vitt rá a böngészőbővítményekre, ezért úgy gondoltam, mutassuk meg, hogyan készíthetünk egyet a semmiből, egy trágárságszűrőt építve a Twitch chathez.
A végén egy olyan bővítményt szeretnénk, amely telepítéskor ellenőrzi a chatben a megjelölt szavak egy csoportját, és barátságosabb változatokra cseréli őket. Ez hasznos lehet például a streameket néző gyerekek számára.
Ha csak a bővítmény kódjára vagy kíváncsi, a cikk alján található egy link a végeredményhez.
Jól van, akkor vágjunk bele fejest. Hozzunk létre egy mappát valahol, ahol szeretnénk, és nevezzük el profanity-filter-nek. Én az enyémet egy olyan helyen hoztam létre, ahol szinkronizálódom a GitHubbal.

Most ebben a mappában hozz létre két új fájlt: manifest.json és content.js. Majd meglátod, hogyan fogjuk használni őket, amint elkezdjük építeni a kiterjesztést.

Nyisd meg a manifestet.json-t, amely az a fájl, amelyet a Google megnéz a kiterjesztésünkre vonatkozó metaadatokért, és illesszük bele a következőket:
{ "manifest_version": 2, "name": "Twitch Profanity Filter Extension", "version": "0.1", "content_scripts": , "js": } ]}
Amint láthatod, azt mondjuk a Google-nak, hogy ennek a kiterjesztésnek a Twitch bármelyik oldalán működnie kell, és azt is mondjuk, hogy az ezeken az oldalakon futtatandó logika a content.js nevű fájlban található. Vegye figyelembe, hogy a verziót 0.1-nek adtam meg, mivel ez az első próbálkozásom.
A logika beillesztése
Most nyissa meg a content.js fájlt a választott szövegszerkesztőben. Nagyon ajánlom a Visual Studio Code-t, ez az én szövegszerkesztőm minden kódolással kapcsolatos dologhoz, és ingyenes.
Most, a beállítás módja néhány lépésből áll. Mit akarunk elérni, és hogyan fogjuk ezt elérni? Tudjuk, hogy bizonyos szavakat másra akarunk cserélni, ami azt jelenti, hogy elolvassuk a csevegőüzeneteket, átvizsgáljuk őket a megjelölt szavakra, majd ezeket a szavakat barátságosabbakra frissítjük. Tehát amikor az oldal betöltődik, azt akarjuk, hogy a logikánk képes legyen a következőkre:
- Keresd meg a chatboxot
- Minden alkalommal, amikor új chat-üzenet jelenik meg, szerezd meg az üzenetet vagy az üzenet tárolóját
- A megjelölt szavakat cseréld barátságos megfelelőikre
Vágjunk tehát bele. Az első rész tulajdonképpen a szkript aktiválása, amikor az oldal, pontosabban az ablak betöltődik. A javascriptben be tudunk kapcsolódni ebbe a betöltési eseménybe, és mi most pontosan ezt fogjuk tenni. Frissítsd a content.js fájlodat úgy, hogy a következőket tartalmazza:

Ez biztosítja, hogy bármit is teszünk a függvénybe, meghívásra kerüljön, amikor az oldal betöltődik.
Keresd meg a chatboxot
Hogyan találjuk meg a chatboxot? Nos, a Twitch weboldal Chrome verziójában a chatbox egy <div> elemben található, amelynek van egy chat-scrollable-area__message-container nevű osztálya. Ezt az elemet, illetve csomópontot javascript segítségével fogjuk megszerezni. Frissítsük a fájlt, hogy így nézzen ki:

Az ok, amiért .item(0)-t adunk mögé, az az, hogy a getElementsByClassName() egy elemtömböt ad vissza. Mivel tudjuk, hogy csak egy elemnek van ilyen osztálya, ezért azt vesszük ki a tömbből azzal, hogy megadjuk, hogy az elsőt akarjuk (a legtöbb programozási nyelv 0-nál kezdi a számolást).
Minden új üzenet lekérése a chatben
Ez egy kicsit nehezebben érthető, ha nem vagy hozzászokva a programozáshoz vagy a megfigyelési mintákhoz. Minden új üzenetet úgy fogunk megszerezni, hogy egy MutationObserver-t használunk az imént felvett chatbox csomóponton. Frissítsük a fájlt az alábbiak szerint, majd végigmegyünk a dolgokon:

Először a 4. sorban definiálunk egy visszahívási függvényt, amely elfogad egy listát a mutációkról és a megfigyelőt, amelyet a 8. sorban hozunk létre. Ennek a függvénynek a logikája az, ami meghívásra kerül, amikor a megfigyelt csomópontban valami megváltozik vagy mutálódik.
A 8. sorban létrehozzuk a megfigyelőt, és átadjuk neki a visszahívási függvényünket. Ezután a 9. sorban megmondjuk a megfigyelőnek, hogy kezdje el megfigyelni a célcsomópontunkat, és átadunk egy olyan konfigurációt, amely szerint csak a childList mutációi érdekelnek minket. Az üzenetek a megfigyelt chatbox csomópontban gyermekcsomópontként jelennek meg, így a callback függvényünk minden alkalommal elindul, amikor egy új chat-üzenet jelenik meg. Pontosan ezt akarjuk!
De most még meg kell szereznünk a tényleges üzenetelemeket, és ehhez még egy sor kódot adunk hozzá a callbackünkhöz:

A név talán kicsit furcsának tűnik, de az üzenet összes szöveges része (nem az emoteket, csak a tényleges szövegeket vizsgáljuk) <span> HTML elemekben helyezkedik el, amelyeknek text-fragment osztálya van. Továbbá, mivel ez a függvény minden új üzenetnél elindul, tudjuk, hogy a kívánt üzenetnek a chatbox csomópont utolsó elemének kell lennie, ezért ragadjuk meg a lastElementChild-et.
A megjelölt szavakat barátságos megfelelőjükre változtatjuk
Lássunk a szaftos részhez. Ha meg akarjuk változtatni a megjelölt szavakat, először is szükségünk van valamire, ami megmondja, hogy melyek a megjelölt szavak és azok megfelelői. Ezt egy egyszerű szótár segítségével fogjuk megtenni. Frissítsük a fájlt, hogy így nézzen ki:

Most az összes szövegtöredék elemben el fogjuk olvasni a tényleges szöveget, végighaladunk az összes tiltott szón és szükség esetén kicseréljük őket. Indítsuk el ezt a hurkot, ezért frissítsük a callback függvényünket a következőkkel:

Az történik itt, hogy végighaladunk ezeken a szöveget tartalmazó elemeken. A 18. sorban egyszerre egy adott elemet veszünk, és a 19. sorban megkapjuk belőle a tényleges szöveget kisbetűvel, mivel a megjelölt szavaink is mind kisbetűsek. Ez megkönnyíti az összehasonlítást, de egy fejlettebb változatban gondoskodnánk a nagybetűs írásmód szépen megtartásáról. Most, hogy megvan a szövegünk, végig akarunk menni a megjelölt szavakon, és ellenőrizni, hogy jelen vannak-e. Ha igen, akkor töröljük őket. Frissítsük a függvényt:

A létrehozott szótár kulcs-érték párokkal dolgozik, ahol a kulcsok a megjelölt szavak, az értékek pedig a barátságos szavak, így a 21. sorban egyszerűen megkapjuk az összes kulcs tömbjét, ami a megjelölt szavak tömbje, amin át akarunk lépni. A ciklusban megragadjuk a megjelölt szót, amelyet éppen nézünk, és ha a szövegünk egy vagy több ilyen szót tartalmaz, megragadjuk a barátságos szót, és frissítjük a szövegünket a megjelölt szavak helyettesítésével. Ez majdnem minden, most már csak az új és javított szövegünket kell fognunk, és visszahelyeznünk abba az elembe, ahonnan megragadtuk:

A 31. sorban már visszahelyeztük a szöveget az elembe, és kész! Lássunk hozzá a teszteléshez a Chrome-ban.
A teszt
Nyissuk meg a Chrome-ot, és keressük meg a chrome://extensions. Látnod kell a bővítményeidet, és a jobb felső sarokban megjelenik a Fejlesztői mód. Kapcsolja be, ha még nincs. Ezután a jobb felső sarokban látni fogod a Load unpacked opciót. Ezt fogjuk használni, hogy betöltsük a helyi bővítményünket anélkül, hogy egyelőre a Chrome Web Store útvonalát kellene bejárnunk. Kattintsunk rá, és válasszuk ki a mappát, ahol a fájlok találhatók:

Ezzel azonnal meg fog jelenni a bővítményünk listájában:

Jó! Most pedig irány valamelyik csatorna, ahol tudunk beszélgetni. Átmegyek Bjarke barátom csatornájára, aki egy vicces dán streamer, és kipróbálom:

Íme, működik! A saját trágárságszűrőnk. Nem is volt olyan nehéz, ugye? Már csak ki kell adni a Chrome Web Store-ban, ha akarod. Ezt a szólistát bővíteni fogom, és ezt fogom kiadni, tehát ha ennél többre nincs szükséged, akkor nem kell kiadnod, mivel a programba való belépéshez díjfizetésre van szükség. Nem fogok belemenni abba, hogyan működik a kiadás, de ha érdekel, készítettem egy Twitch Emote Extensiont, hogy saját korlátlan emote slotokat kapj, és ez a cikk a végén elmagyarázza, hogyan kell kiadni a kiterjesztéseket.
Ha látni akarod ennek a kiterjesztésnek az összes kódját, nézd meg a GitHub repót itt. Kellemes kódolást!