私はずっとYoutubeに欲しい機能があったのです。
それはライブチャットのデフォルトを「すべてのチャット」にするという機能。
というのもチャット欄はデフォルトで「トップチャット」になっているのですが私は不適切なコメントでさえも見たいタイプなのでいつも「すべてのチャットに」切り替えていました。
設定にありそうなのにどれだけ探しても無い…拡張機能にもない…
しょうがない。。以前から興味はあったので結局拡張機能を自作することにしました。
準備
まずは拡張機能の作り方を調べてみると最低限以下のファイルが必要とのこと。
├── content.js(実際に動かすファイル)
├── manifest.json(設定ファイル)
├── icon.png(拡張機能のアイコン画像)
JSはほぼ初心者ですが実際に手を動かしてみることにします。
テキストエディタはVisual Studio Codeを使いました。
実装
manifest.json(設定ファイル)
拡張機能の設定ファイルです。備忘録として今回設定した各項目についてまとめておきます。
{
"name": "Show All YouTube Chats by Default",
"version": "1.0.0",
"manifest_version": 3,
"description": "YouTubeのデフォルトチャット表示をトップチャットからすべてのチャットに変更します。",
"icons": {
"96": "icon48.png"
},
"content_scripts": [
{
"matches": ["*://www.youtube.com/*"],
"js": ["content.js"]
}
]
}
manifest.jsonの内容
| フィールド名 | 内容 |
|---|---|
| name | 拡張機能の名前。今回は「Show All YouTube Chats by Default」にしました。 |
| version | 拡張機能のバージョン。初回リリースなので「1.0.0」にしています。 |
| manifest_version | 拡張機能の仕様バージョン。最新のV3を使っています。V2のサポートが終わったみたいなのでV3が必須みたいです。 |
| description | 拡張機能の説明。 |
| icons | 拡張機能のアイコン設定。今回は「icon48.png」にしました。 |
| content_scripts | Webページにスクリプトを埋め込む設定。”js” に実行するスクリプト、”matches” に適用するページを指定します。今回はすべてのYouTubeページに適用するようにしています。 |
content.js(実際に動かすファイル)
実際に動かすプログラムです。JSはほぼ知識がないので1週間以上かかってしまいました。
多分無駄な記述や間違いもあると思いますがなんとか動くものができました。
/*チャット選択ボタンの生成判定後、存在すれば「すべてのチャット」ボタンをクリック*/
const buttonClick = () => {
const chatFrame = document.getElementById("chatframe");
if (chatFrame == null) {
setTimeout(buttonClick, 1000);
return;
}
const chatButton = chatFrame.contentWindow.document.querySelectorAll(
".yt-simple-endpoint.style-scope.yt-dropdown-menu"
);
if (chatButton[chatButton.length - 1] == null) {
setTimeout(buttonClick, 1000);
return;
}
chatButton[chatButton.length - 1].click();
};
/*ObserverがiconImageの変化を感知した際の処理*/
const observer = new MutationObserver(() => {
/*ページ遷移の際にチャット欄が再生成されるので一度削除*/
const chatFrame = document.getElementById("chatframe");
if (chatFrame != undefined) {
const chathtml = chatFrame.contentWindow.document.querySelector("html");
chathtml.removeChild(chathtml.lastElementChild);
buttonClick();
}
});
/*Observer設定*/
const config = {
attributes: true,
attributeOldValue: true,
attributeFilter: ["href"],
};
/*アイコン画像の生成待ち*/
const iconImagePolling = (iconImg) => {
if (iconImg == null) {
setTimeout(iconImagePolling(iconImg), 1000);
return;
}
};
/*初期処理*/
const init = setInterval(() => {
const iconImg = document.querySelector(
".yt-simple-endpoint.style-scope.ytd-video-owner-renderer"
);
if (iconImg != null) {
observer.observe(iconImg, config);
clearInterval(init);
buttonClick();
} else {
iconImagePolling(iconImg);
}
}, 1000);
content.jsの内容をざっくり
1秒ごとにチャット欄の
iframe が生成されているかをチェックし、見つかったら次はチャット選択ボタンの存在を判定します。ボタンも生成されたことを確認できたら、最後に一番最後のボタン(「すべてのチャット」ボタン)をクリックします。
問題なのは、「すべてのチャット」ボタンをクリックした後にリロードが発生するため、
せっかく選択したのに 「トップチャット」に戻ってしまうことです。
これは結構強引ですがページ遷移が確認されたらチャット欄を削除する処理を入れました。
その後、もう一度 「すべてのチャット」ボタンをクリックする処理を実行して、リロード後も設定が維持されるようにしています。
本当はURLやタイトルタグの変化で判定したかったのですが、うまくいかなかったためこの方法にしました。
ページ遷移が確認できたら、「チャット欄を削除 → ボタンを押し直す」 の順で処理を実行します。
実は
iframe の中に要素があったため、通常の document.querySelector では取得できませんでした。contentWindow.document を使うことで iframe 内の要素を取得できます。完成したのでストアに公開
完成した拡張機能はYouTubeライブやアーカイブを開くと以下のように自動ですべてのチャットに切り替わります。
実装後、結局 Chrome ウェブストアにも公開しちゃいました。
意外にも現在25人もインストールしてくれているようです。
Chrome ウェブストアへの公開方法(ざっくり)
Chrome 拡張機能は500円の登録費を払えば誰でもウェブストアに公開できます。
一度登録すれば次からの公開は無料です。公開までの流れはこんな感じ。
まとめ
とにかく途中で投げ出さず最後まで完成させられて良かったです。
ボタン1つクリックさせるだけなのに思った以上に苦戦しました。プログラマーは大変ですね…
今後は、例えば固定コメントや登録者限定メッセージなど、個人的にあまり必要ない機能を非表示にできる設定などを追加できたらいいなぁとふんわり思ってます。
同じ悩みを持っている方の参考になれば嬉しいです!
