Twitch冒涜フィルターChrome拡張の作り方

Nintendo Engineer
Dec 28, 2020 – 7 min read

Twitch関連企画をちらちらやってます。 どんな可能性があるのか、試してみたい。 最新のプロジェクトのひとつに、Chrome用のTwitch Emote Extensionを作成し、追加のエモート「スロット」を無料で入手する方法を紹介しました。 そこで、Twitch チャット用の冒涜的なフィルタを構築して、ゼロから 1 つ作る方法を示そうと考えました。

最終的には、インストールすると、チャットでフラグ付きの一連の単語をチェックし、よりフレンドリーなバージョンに置き換える拡張機能を実現したいと思います。 これは、たとえば、ストリームを見る子供たちに便利です。

この拡張機能のコードだけが必要な場合、この記事の下部に最終結果へのリンクがあります。 どこか好きな場所にフォルダを作成し、それを profanity-filter と呼びます。 私は GitHub と同期している場所に作成しました。

名前は何でも良いですが、これがぴったりです

次に、このフォルダー内に manifest.json と content.js という新しいファイルを 2 つ作成します。 これらのファイルをどのように使用するかは、拡張機能を構築する際にわかります。

ここで

manifest を開きます。json を開き、拡張機能に関するメタデータとして Google が参照するファイルに、次の内容を貼り付けます。

Getting the logic in

次に、お好みのテキスト エディターで content.js を開きます。 Visual Studio Code は、コーディングに関連するあらゆることに使える、私のお気に入りのテキスト エディターで、無料です。 何を達成したいのか、それをどのように達成するのか。 私たちは、特定の単語を他の単語に変更したいことを知っています。これは、チャット メッセージを読み、フラグ付きの単語をスキャンして、それらの単語をより友好的なものに更新することを意味します。

  • Find the chatbox
  • Every time the new chat message appears, get the message or message container
  • Change flagged words to their friendly counterparts

So let’s get to it.というように、ページロード時に以下の処理を行うことができるような論理にしたいと考えます。 最初の部分は、ページ、より具体的にはウィンドウが読み込まれたときに実際にスクリプトをアクティブにすることです。 javascript では、その読み込みイベントにフックすることができますので、それを実行します。

これにより、その関数内に置いたものはすべて、ページがロードされたときに呼び出されるようにします。 Chrome 版の Twitch Web サイトでは、チャットボックスは <div> 要素に含まれており、その要素には chat-scrollable-area__message-container というクラスが設定されています。 その要素、つまりノードを、javascriptで取得することにします。 ファイルを次のように更新します。

この後ろに .item(0) を追加した理由は、 getElementsByClassName() が、要素の配列を返すからです。 このクラスを持つ要素は 1 つだけであることがわかっているので、最初のものが欲しいと指定することにより、配列からそれを取得します (ほとんどのプログラミング言語は 0 から数え始めます)。

Get every new message in chat

これは、プログラミングに慣れていない人やオブザーバーのパターンに慣れていない人が理解するには少しトリッキーなことです。 すべての新しいメッセージを取得する方法は、先ほどピックアップしたチャットボックスノードで MutationObserver を使用することです。 以下のようにファイルを更新してから、何が起こっているのかを見ていきましょう:

最初に、4 行目で、突然変異のリストと 8 行目で作成するオブザーバーを受け取るコールバック関数を定義しています。 この関数のロジックは、観察しているノードで何かが変更、または変異するたびに呼び出されます。

8 行目でオブザーバーを作成し、コールバック関数を渡します。 そして、9 行目でオブザーバーにターゲット ノードの観察を開始するように指示し、childList への変異にのみ関心を持つという設定を渡しています。 メッセージはチャットボックスノードの子ノードとして表示されるので、新しいチャットメッセージが表示されるたびにコールバック関数がトリガーされます。 これこそ、私たちが望んでいることです

しかし、まだ実際のメッセージ要素を取得する必要があり、そのためにコールバックでもう 1 行コードを追加します。

この名前は少し変かもしれませんが、メッセージのすべてのテキスト部分 (ここでは、エモートはスキャンせず、実際のテキストのみ) はクラス text-fragment がある <span> HTML 要素に配置されます。 また、この関数は新しいメッセージごとにトリガーされるので、必要なメッセージはチャットボックス ノードの最後の要素でなければならないことがわかっており、それが lastElementChild.

Change flagged words to their friendly counterparts

Get the juicy bit. フラグ付きの単語を変更したい場合、まず、フラグ付きの単語とその対応する単語が何であるかを教えてくれるものが必要です。 これは、単純な辞書を使用することで行います。

好きなように単語を追加することができますが、最後のカンマを忘れないでください

さて、すべてのテキスト-フラグメント要素で実際のテキストを読み、すべての禁制単語上でループして必要ならばそれらを置き換えるつもりです。

ここで起こっていることは、テキストを含むこれらすべての要素をループしていることです。 18 行目で一度に 1 つの特定の要素を取得し、19 行目でその要素から実際のテキストを小文字で取得しています。フラグ付きの単語はすべて小文字であるため、小文字も取得しています。 これは、フラグを立てた単語がすべて小文字であるためで、比較しやすくするためです。 テキストができたので、フラグを付けた単語をループして、それらが存在するかどうかをチェックします。 もしあれば、それらを削除します。 関数を更新します:

私たちが作った辞書は、キーと値のペアで動作し、キーはフラグ付きの単語、値はフレンドリー単語なので、21行目ですべてのキーの配列、これはループオーバーしたい flaggedword の配列となります。 ループの中で、現在見ているフラグ付きの単語を取得し、もしテキストに一つ以上含まれていたら、フレンドリーな単語を取得し、フラグ付きの単語を置き換えてテキストを更新しています。 これでほぼ完了です。あとは、新しく改善されたテキストを取得し、取得した要素に戻すだけです。

31 行目でテキストを要素に戻し、これで完了です!

テスト

Chrome を開き、chrome://extensions にブラウズしてください。 拡張機能が表示され、右上に開発者モードが表示されているはずです。 まだならオンに切り替えてください。 その後、右上にLoad unpackedという項目があります。 これを利用して、Chrome ウェブストアのルートを通さずにローカルの拡張機能を読み込むことができます。

これで拡張機能リストに即座に表示されるはずです。

Good! では、チャットができるチャンネルに移動してみましょう。 友人の Bjarke のチャンネルに行って、試してみます。

ほら、うまくいきましたね。 私たち自身の冒涜的なフィルターです。 難しくなかったですか? あとは、Chrome ウェブストアに公開するだけです。 この単語リストを拡張してリリースしていくので、これ以上必要ない場合は、プログラムに参加するために料金が必要なことを見て、リリースする必要はない。 リリースの仕組みについては割愛しますが、もし興味があれば、自分で無限のエモートスロットを手に入れるための Twitch Emote Extension を作って、この記事では最後に拡張機能のリリース方法を説明しています。

この拡張機能のすべてのコードを見たい場合は、こちらの GitHub リポをチェックしてみてください。 メリー コーディング!