ニコニコ動画のタグ問題を解決(したい)拡張機能

# はじめに
皆さんはニコニコ動画を見たことがあるでしょうか？
日本ではYouTubeに並ぶ(と思っている)動画投稿サイトですが、その特徴として**タグ**機能が挙げられます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1509462/11fc9d93-843b-a9ae-4363-6e9cda172350.png)

YouTubeはじめタグ機能を採用しているサイトはよく見ます。Qiitaもその一つですね。
ニコニコの場合、タグをクリックするとそのタグ付けがされている動画一覧を検索することができます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1509462/a02c2492-047d-fbd6-c73e-83f968c00d12.png)

便利なタグ機能ですがタグの上限が11個であり、表記ゆれなどに対応しようとすると枠が足りなくなることがあります。
**視聴者からしても表記ゆれがあると検索の取りこぼしが生じます。**

# あいまい検索のようなもの
そこで表記ゆれに対応するために、ユーザそれぞれがタグ検索の範囲を任意に広げることができるChrome拡張機能を作りました。
Chromeストア → https://chrome.google.com/webstore/detail/nicotag-box/phkcmpbancelmdlpbdkelnhdlkigango?hl=ja
GitHub → https://github.com/gyosit/NicotagBox

この拡張機能では、
- 「AAA」タグをクリックした際に「AAA」と「BBB」を両方検索する。
- 「AAA***」タグをクリックした際に「AAA***」と「BBB***」を両方検索する。

といったことができます。
例えば「Python」タグをクリックした際に「Python言語」タグが付いている動画を検索結果に含めることで「Python言語」タグしかついていない動画も見落とさずに済むことができます。

# 使い方
NicotagBoxインストール後、アイコンをクリックすると以下のようなボックスが現れます。
(最初はundefinedになっていると思います...)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1509462/79f34659-70d0-6a23-642f-24c794eea140.png)
ここに転送設定を書いていきます。
書き方のルールは以下の3種類です。
|書き方|トリガー|検索結果|
|:--|:--|:--|
|AAA BBB CCC|「AAA」「BBB」「CCC」タグ<br>いずれかのクリック時|「AAA」「BBB」「CCC」タグ<br>を同時検索|
|*AAA BBB CCC|「～AAA～」「～BBB～」「～CCC～」タグ<br>いずれかのクリック時|「～AAA～」「～BBB～」「～CCC～」タグ<br>を同時検索
|上記ルールの最後に-DDD|　|「-DDD」タグを検索結果から除外|

一つのルールにつき一行で記述し、複数行書くことで複数のルールを適用できます。
他の機能についてはChromeウェブストアでご確認ください。

# デモ
試しに「python python言語 -ruby」ルール適用下でタグをクリックしてみましょう(別にRubyに恨みはありません)。
なおニコニコ動画は大文字・小文字は区別しないため本拡張機能でも区別していません。

Pythonタグが付いたとある動画の視聴ページに行きます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1509462/7a0e4523-b31d-9cc9-40f7-be23a22d488d.png)
Pythonタグをクリックしてみます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1509462/09131815-b183-bd6f-f178-19df26d1756a.png)
ちゃんと反映されました！



# ソースコード
ちょっと汚いです。ご了承下さい。
実際には上記よりもう少し色々やっているのですが、コアな部分を抜粋すると、
### ① ローカルストレージの読み込み
タグ転送の設定はChromeのローカルストレージに保存します。
それと一時的に転送機能を無効にできるので、その設定を読み込んでいます。
```javascript
// 設定の読み込み
let transsetting;
let unablesetting;
console.log("Start:Loading strage");
chrome.storage.local.get(['transset', 'unablecheck'], function(items) {
    console.log("End:Loading strage");
    transsetting = items.transset.toLowerCase();
    unablesetting = items.unablecheck;
```

### ② タグ要素の探索
ニコニコ動画のタグはclass名が`.TagItem-name`または`.tag`なのでこれを探します。
```javascript
let transsets = transsetting.split('\n');
let basepath = "https://www.nicovideo.jp/tag/"
// .TagItem-name:視聴ページ、.tag:検索結果
let tags = document.querySelectorAll(".TagItem-name, .tag");
```

### ③ タグのリンク先の置換
力技です。
設定した転送設定と表示ページから見つけたタグを一つひとつ照らし合わせていき、条件に合ったものがあれば置換＋OR結合で転送先となる検索画面のURLを作っていきます。
最終的に該当するタグの`href属性`を生成したURLで置き換えます。
前述したようにニコニコ動画は大文字・小文字を区別しないので、NicotagBoxの設定内容やページ内で見つけたタグはまとめて`toLowerCase関数`で小文字にしています。
```javascript
for(let i=0;i<tags.length;i++){
    let new_tag = tags[i].textContent;
    for(let j=0;j<transsets.length;j++){
        let tmp_sets = transsets[j].split(' ');
        minus_tags = [];
        plus_tags = [];
        ～～～中略～～～～
        if(plus_tags[0][0] == '*'){
            // 置換
            let common;
            let fi_id;
            for(let k=0;k<plus_tags.length;k++){
                fi_id = tags[i].textContent.toLowerCase().indexOf(plus_tags[k].replace("*", ""));
                // タグにある文字列が含まれていればそこをXXXに置き換える
                if(fi_id != -1){
                    common = tags[i].textContent.toLowerCase().replace(plus_tags[k].replace("*", ""), "XXX");
                    break;
                }
            }
            // 置換リストのどれかに引っかかったらXXXを置換してORで結合
            if(fi_id != -1){
                let new_children = [];
                for(let k=0;k<plus_tags.length;k++){
                    let new_child = common.replace("XXX", plus_tags[k].replace("*", ""));
                    if(count(new_child) > 40) continue;
                    new_children.push(new_child);
                }
                new_tag = new_children.join(' OR ');
                break;
            }
        }else{
            // 転送
            // 転送リストのどれかに引っかかったらORで結合
            let fi_id = plus_tags.indexOf(tags[i].textContent.toLowerCase());
            if(fi_id != -1){
                new_tag = plus_tags.join(' OR ');
                break;
            }
        }
        minus_tags = [];
        plus_tags = [];
    }
    new_tag += " " + minus_tags.join(' ');
    new_tag = encodeURIComponent(new_tag);
    tags[i].href = basepath + new_tag;
}
```

# 反響
特別バズった...というわけではないのですがNicotagBoxの紹介動画内では感謝のコメントをいただきました。
(ニコニコ動画の埋め込みはできないんですかね？)
https://nico.ms/sm39479704

# ちなみに
NicotagBoxは表記ゆれ問題を解決するためのツールと銘打っていますが、開発の直接的なきっかけはニコニコ動画では比較的ポピュラーなジャンルであるVOICEROID動画です。
VOICEROIDとは音声合成ソフトの一種であり、ニコニコではVOICEROIDにゲーム実況させた動画には「VOICEROID実況」タグ、解説させた動画には「VOICEROID解説」タグが付きます。
最近では類似ソフトが増えてきており、それぞれ「(ソフト名)実況」タグなどが付いています。
個人的には音声合成ソフトを用いた動画はソフト別ではなく一括でまとめて検索したいので、よく「VOICEROID実況 OR (ソフト1)実況 OR (ソフト2)実況 OR ...」と検索していましたが面倒なのでこの拡張機能を作成しました。

私が利用している設定は、
```:タグ転送設定 
*非voiceroid voiceroid coefont ガイノイドtalk cevio voicevox ソフトウェアトーク A.I.VOICE つくよみちゃん CeVIO_AI COEIROINK TALQu ボイロ
```
です。