Hoe maak je een Twitch profanity filter Chrome extensie

Nintendo Engineer
Dec 28, 2020 – 7 min read

Ik doe hier en daar een hoop Twitch gerelateerde projecten, om te zien wat de mogelijkheden zijn. Een van mijn laatste projecten was het maken van een Twitch Emote Extension voor Chrome, waarin ik liet zien hoe je gratis extra emote “slots” kunt krijgen. Dat bracht me in browser extensies, dus ik dacht laten we laten zien hoe je een vanaf nul te maken door het bouwen van een godslastering filter voor de Twitch chat.

Aan het einde van deze, willen we een extensie die, wanneer geïnstalleerd, controleert op een set van gemarkeerde woorden in de chat en vervangt ze door meer vriendelijke versies. Dit kan bijvoorbeeld handig zijn voor kinderen die naar streams kijken.

Als je alleen de code voor deze extensie wilt, is er een link naar het eindresultaat onderaan dit artikel.

Al goed, dus laten we er eerst maar eens aan beginnen. Maak een map ergens waar je wilt en noem het profanity-filter. Ik heb de mijne gemaakt op een plaats waar ik synchroniseer met GitHub.

Elke naam is goed, maar dit lijkt me passend

Nu maakt u in deze map twee nieuwe bestanden: manifest.json en content.js. U zult zien hoe we ze zullen gebruiken wanneer we de extensie gaan bouwen.

Daar gaan we

Open manifest.json, het bestand waar Google metagegevens over uw extensie in opzoekt, en plak het volgende erin:

{ "manifest_version": 2, "name": "Twitch Profanity Filter Extension", "version": "0.1", "content_scripts": , "js": } ]}

Zoals u ziet, vertellen we Google dat deze extensie op elke pagina van Twitch moet werken en zeggen we ook dat de logica die op deze pagina’s moet worden uitgevoerd, zich in het bestand met de naam content.js bevindt. Merk op dat ik de versie op 0.1 heb gezet, omdat dit mijn eerste poging is.

De logica erin zetten

Nu opent u content.js in een teksteditor naar keuze. Ik zou Visual Studio Code ten zeerste aanbevelen, het is mijn go-to tekstverwerker voor alles wat met coderen te maken heeft en het is gratis.

Nu, de manier waarop we dit gaan opzetten is in een paar stappen. Wat willen we bereiken en hoe gaan we dat doen? We weten dat we bepaalde woorden willen veranderen in andere, wat betekent dat we de chatberichten lezen, ze scannen op gemarkeerde woorden en die woorden dan veranderen in vriendelijker woorden. Dus als de pagina laadt, willen we dat onze logica het volgende kan doen:

  • De chatbox vinden
  • Iedere keer als er een nieuw chatbericht verschijnt, het bericht of de berichtencontainer ophalen
  • Gevlagde woorden veranderen in hun vriendelijke tegenhangers

Dus laten we aan de slag gaan. Het eerste deel is eigenlijk het activeren van het script wanneer de pagina, of meer specifiek het venster, is geladen. In javascript, kun je inhaken op die laad gebeurtenis en we gaan precies dat doen. Werk uw content.js bij met het volgende:

Dat zorgt ervoor dat wat we ook in die functie zetten, wordt aangeroepen als de pagina is geladen.

Vind de chatbox

Zo hoe vinden we de chatbox? Nou, in de Chrome-versie van de Twitch-website, de chatbox is opgenomen in een <div> element dat een klasse genaamd chat-scrollable-area__message-container heeft. We gaan dat element, of knooppunt, door javascript halen. Werk het bestand bij zodat het er als volgt uitziet:

De reden waarom we .item(0) erachter zetten, is omdat getElementsByClassName() een array van elementen retourneert. Omdat we weten dat slechts één element deze klasse heeft, halen we het uit de array door aan te geven dat we het eerste ding willen (de meeste programmeertalen beginnen met tellen bij 0).

Krijg elk nieuw bericht in chat

Dit is een beetje lastiger te begrijpen als je niet gewend bent aan programmeren of niet gewend bent aan waarnemerpatronen. De manier waarop we elk nieuw bericht gaan krijgen is door gebruik te maken van een MutationObserver op de chatbox node die we net hebben opgepikt. Werk het bestand bij zodat het overeenkomt met het volgende en dan lopen we door wat er gebeurt:

Eerst, op regel 4, definiëren we een callback-functie die een lijst met mutaties en de waarnemer die we op regel 8 maken, meeneemt. De logica in deze functie is wat wordt aangeroepen wanneer er iets verandert, of muteert, in het knooppunt dat we observeren.

Op regel 8 maken we de waarnemer en geven deze onze callback-functie door. Dan, op regel 9, vertellen we de waarnemer om te beginnen met het observeren van onze doel node en geven we een configuratie door die zegt dat we alleen geïnteresseerd zijn in mutaties in de childList. Berichten verschijnen als child nodes in de chatbox node waar we naar kijken, dus onze callback functie zal getriggerd worden iedere keer dat er een nieuw chat bericht verschijnt. Dat is precies wat we willen!

Maar nu moeten we nog de eigenlijke bericht-elementen ophalen en daarvoor voegen we nog een regel code toe in onze callback:

De naam lijkt misschien een beetje vreemd, maar alle tekstdelen van een bericht (we scannen geen emotes, alleen de eigenlijke teksten) worden geplaatst in <span> HTML-elementen die de klasse text-fragment hebben. Omdat deze functie bij elk nieuw bericht wordt geactiveerd, weten we dat het bericht dat we willen hebben het laatste element in de chatbox moet zijn, dus daarom pakken we het lastElementChild.

Gevlagde woorden wijzigen in hun vriendelijke tegenhangers

Laten we nu naar het sappige gedeelte gaan. Als we gevlagde woorden willen veranderen, hebben we eerst iets nodig dat ons vertelt wat gevlagde woorden en hun tegenhangers zijn. We zullen dit doen door een simpel woordenboek te gebruiken. Werk het bestand bij zodat het er als volgt uitziet:

Je kunt meer woorden toevoegen als je wilt, maar vergeet de komma aan het eind niet

Nu gaan we de eigenlijke tekst in alle tekst-fragment elementen lezen, lus over alle verboden woorden en vervangen ze indien nodig. Laten we die lus starten, dus update uw callback-functie met het volgende:

Wat hier gebeurt, is dat we een lus maken door al deze elementen die tekst bevatten. Op regel 18 nemen we één specifiek element per keer en op regel 19 halen we de eigenlijke tekst eruit in kleine letters, omdat onze gemarkeerde woorden ook allemaal in kleine letters zijn. Het maakt het makkelijker voor vergelijkingsdoeleinden, maar in een meer geavanceerde versie zouden we zorgen voor het netjes handhaven van de casing. Nu we onze tekst hebben, willen we lus over onze gemarkeerde woorden en controleren of ze aanwezig zijn. Zo ja, dan verwijderen we ze. Werk de functie bij:

Het woordenboek dat we hebben gemaakt werkt met sleutel-waarde paren, waarbij de sleutels de gevlagde woorden zijn en de waarden de vriendelijke woorden, dus op regel 21 krijgen we gewoon een array van alle sleutels, wat de array van gevlagde woorden is waar we een lus over willen maken. In de lus pakken we het gevlagde woord waar we op dat moment naar kijken en als onze tekst een of meer van hen bevat, pakken we het vriendelijke woord en updaten we onze tekst door de gevlagde woorden te vervangen. Dat is bijna alles, nu hoeven we alleen nog maar onze nieuwe en verbeterde tekst terug te plaatsen in het element waar we hem vandaan hebben gehaald:

Op regel 31 hebben we nu de tekst teruggeplaatst in het element en dat is het! Laten we dit nu gaan testen in Chrome.

De test

Open Chrome en blader naar chrome://extensions. U zou uw extensies moeten zien en in de rechterbovenhoek ziet u Ontwikkelaars modus. Schakel deze in als dat nog niet het geval is. Daarna ziet u rechtsboven de optie Uitgepakt laden. We gaan die gebruiken om onze lokale extensie te laden zonder de Chrome Web Store-route te hoeven volgen. Klik erop en selecteer de map waarin de bestanden zich bevinden:

Dit zou ervoor moeten zorgen dat de extensie direct in onze extensielijst wordt weergegeven:

Goed! Laten we nu naar een kanaal gaan waar we kunnen chatten. Ik ga naar het kanaal van mijn vriend Bjarke, een hilarische Deense streamer, en probeer het uit:

Daar gaan we, het werkt! Onze eigen godslastering filter. Dat was niet zo moeilijk, toch? Als u wilt, hoeft u het alleen nog maar vrij te geven in de Chrome Web Store. Ik zal deze lijst met woorden uitbreiden en vrijgeven, dus als je niet meer dan dit nodig hebt, hoef je het niet vrij te geven, aangezien het een vergoeding vereist om in het programma te komen. Ik zal niet ingaan op hoe de release werkt, maar als je geïnteresseerd bent, ik heb een Twitch Emote Extension gemaakt om je eigen onbeperkte emote slots te krijgen en dit artikel legt uit hoe je extensies aan het einde kunt releasen.

Als je alle code voor deze extensie wilt zien, bekijk dan de GitHub repo hier. Vrolijk coderen!