YouTubeの登録チャンネルページにおけるショート動画を非表示にするchrome拡張機能を作ってみた

## はじめに
タイトル通りです。
せっかく作ったし備忘録的な感じで記事に残そう！ってことで書きました。
JavaScriptは基礎文法知ってる程度です。
普段このような記事を書くことはないので拙い文章になると思いますがお許しください。
## 経緯
勉強がてら何か作りたい
　　　　↓
JavaScriptでchrome拡張機能を自作できるらしい
　　　　↓
YouTubeの拡張機能を作ってみよう

だいたいこんな感じです。
とりあえずショート動画を非表示にする機能を作ってみました。
なぜ登録しているチャンネルのショート動画かというと、
たまたま僕が登録しているチャンネルがそういうスタイルなだけかもしれませんがショート動画ってメイン動画の切り抜きなことがほとんどなので見ないんですよね。
それとショート動画ってスマホだからだらだら見ちゃうみたいなところあると思うんですよ。
PCでショート動画をみることはないので非表示にしてメイン動画や配信アーカイブを見つけやすくしようってことです。


## 今回作成したファイル

<details><summary>script.js</summary>


```javascript:script.js
// 登録chにある動画のリストを作る
const video_list = () => {
  const q = document.getElementsByTagName("ytd-item-section-renderer");
  let save_list = [];
  for(i=0;i<q.length;i++){
    save_list[i] = q[i].getElementsByTagName("ytd-grid-video-renderer");
  }
  return save_list;
};

// 登録chからshorts動画を隠す
const shorts_hide = save_list => {
  let tmp;
  for(i=0;i<save_list.length;i++){
    tmp = save_list[i];
    for(j=0;j<tmp.length;j++){
      if(true==save_list[i][j].querySelector("#thumbnail").href.includes('shorts')){
        save_list[i][j].style.display = "none";
      }
    }
  }
};
// 1秒ごとに実行
setInterval(() => {
  const videos = video_list();
  shorts_hide(videos);
}, 1000);
```
</details>

<details><summary>manifest.json</summary>


```json:manifest.json
{
  "name": "Hide short videos in YouTube",
  "description": "Hide short videos on the registered channel page.",
  "version": "0.1.8",
  "manifest_version": 3,
  "content_scripts": [
    {
      "matches": ["https://www.youtube.com/*"],
      "js": ["script.js"]
    }
  ]
}

```
</details>
今回はmanifest.jsonについてはあまり触れません。
versionの更新だけ忘れずに後は各々自由にどうぞ。

くわしくは[こちら](https://qiita.com/mdstoy/items/9866544e37987337dc79)

## デベロッパーツールでYouTubeのHTMLを調べる
これが大変でした。
ショート動画はタイトルに"#shorts"を含めないと普通の動画と判別されることがあるらしく、
"#shorts"を含むことが推奨されているのですが、別に含まなくてもショート動画として投稿できるし、
普通の動画に変更されることもおそらくないのでタイトルで判別するのはベストではありません。
というかタイトルで判別して非表示になるやつとならないやつがあって気付きました。
そこで今回はURLに"shorts"があるかどうかで判別することにしました(ショート動画のURLには"shorts"が含まれてる)
サムネでも動画タイトルでもいいのでhref属性を見つけて判別します。


## JavaScriptを書く
上から説明していきます(といっても３か所しかありませんが)
まずは１か所目
```javascript:script.js
// 登録chにある動画のリストを作る
const video_list = () => {
  const q = document.getElementsByTagName("ytd-item-section-renderer");
  let save_list = [];
  for(i=0;i<q.length;i++){
    save_list[i] = q[i].getElementsByTagName("ytd-grid-video-renderer");
  }
  return save_list;
};

```
登録チャンネルページにある動画のリストを返すvideo_list関数です。
`const q = document.getElementsByTagName("ytd-item-section-renderer");`
qには以下のような要素が格納されます。
![qの中身](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2628083/38622cb0-316a-87cb-e6f4-c3236192004d.jpeg)
それぞれの"ytd-item-section-renderer"タグには
0:今日の動画一覧、1:昨日の動画一覧、2:一昨日の動画一覧
が格納されています。
この段階ではまだそれぞれ１ブロックの塊です。

`save_list[i] = q[i].getElementsByTagName("ytd-grid-video-renderer");`
save_listには以下のような要素が格納されます。
それぞれの"ytd-grid-video-renderer"タグには
0:今日の動画リスト、1:昨日の動画リスト、2:一昨日の動画リスト
が格納されています。
ここで初めてそれぞれに動画が１つ１つ要素としてリストになって格納されています。
![save_listの中身](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2628083/f9cf69b2-c448-8623-5c40-7e8f1b0573db.jpeg)
以下は1つ目の要素の中身です。
"ytd-grid-video-renderer"タグの中身が各動画です。
![qiita_3.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2628083/24150fb2-afa1-600d-35db-e8a36784e8e1.jpeg)


続いて２か所目
```javascript:script.js
// 登録chからshorts動画を隠す
const shorts_hide = save_list => {
  let tmp;
  for(i=0;i<save_list.length;i++){
    tmp = save_list[i];
    for(j=0;j<tmp.length;j++){
      if(true==save_list[i][j].querySelector("#thumbnail").href.includes('shorts')){
        save_list[i][j].style.display = "none";
      }
    }
  }
};
```
登録チャンネルページからshorts動画を非表示にするshorts_hide関数です。
引数としてsave_listを受け取ります。
`tmp = save_list[i];`
save_listの各要素を保持しておくtmp変数です。
save_list[i].lengthだとエラーになってこの後のfor文を回せなかったのでこういった形にしました(他の書き方が思いつかなかったです)

`save_list[i][j].querySelector("#thumbnail").href.includes('shorts')`
各動画のid="thumbnail"を含むタグのhref属性の中身を.includes('shorts')でチェックします。
返り値は真偽値です。
shortsが含まれている、つまり返り値がtrueなら、
`save_list[i][j].style.display = "none";`
該当動画のstyleにdisplay: none;を追加して非表示にします。

こんな感じでhref属性のURLを取得できます。
1つ目のURLにはshortsが含まれているのでtrue、
2つ目のURLにはshortsが含まれていないのでfalseが返されます。
![qiita_4.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2628083/0e9c32fc-b944-50c5-8830-024113f1559a.jpeg)


最後です。
```javascript:script.js
// 1秒ごとに実行
setInterval(() => {
  const videos = video_list();
  shorts_hide(videos);
}, 1000);
```
上述していた関数をそれぞれ実行しています。
videosにはsave_listが格納されています。
さて、こちらではsetIntervalメソッドを使って1000ミリ秒、つまり1秒ごとに定期実行しています。
なぜこのような形にしているかと言いますと、
YouTubeの仕様的に登録チャンネルページのタブを押してページ遷移するときにページの更新をしないっぽいんです。
デフォルトだとおそらくページの更新時に拡張機能が実行されます。
YouTubeにアクセスする際にはおそらく皆さんホーム画面だと思いますので、
実行時には登録チャンネルページの動画は取得できないので非表示にできないのです。
ページの更新がされないのでmanifest.jsonのmatchesに登録チャンネルページ自体を設定しても
手動で更新しないと拡張機能が実行されません。
以上の理由により定期実行にしています。

## おわりに
初めて拡張機能を作ってみました。
思ってたより簡単に作れたかなと思います。
作成した拡張機能は"拡張機能を管理"のページから読み込んで使うことが出来ます。
物は試しですね。
ここからさらに機能を拡張させていきたいと思います。
次はホーム画面のショート動画や自動で作られる再生リスト、
動画の最後の方の画面に表示されるおすすめ動画やチャンネルリンクを非表示にしてみようかな。

非常に読みづらい文章だったと思いますが、最後まで読んでくださりありがとうございました！

## 参考

https://qiita.com/RyBB/items/32b2a7b879f21b3edefc

https://qiita.com/mdstoy/items/9866544e37987337dc79