Youtuberが配信・動画投稿したらメールにて通知するプログラムを作ってみた

# はじめに
私は結構Youtubeを見るようになり、好きなYoutuberから動画投稿の通知があれば気になって視聴していました。
しかし、ある日Youtubeからのメール通知がなくなっていたことに気づきました。

# Youtubeがメール通知機能を2020年8月13日で終了

下記の通達通り、メール通知機能が終わってしまっていました...
https://support.google.com/youtube/thread/63268863?hl=ja
>登録チャンネルの新しいアップロード動画に関するメール通知の変更

>登録しているチャンネルの新しいアップロード、ライブ配信、プレミア公開に関する通知をメールで受け取る機能は、2020 年 8 月 13 日で終了します。この機能を設定している場合はご注意ください。モバイルの YouTube アプリまたはパソコンの Chrome ブラウザ経由の通知をオンにしている場合は、引き続き通知が届きます。

個人的にはメールから開いて動画を視聴することが多かったので、その機能が廃止されるとなると嫌になってしまいますので独自にメールで通知するプログラムを作成しました。

# このプログラムでできること
- 1つのプログラムにつき、1人のYoutuberの配信,動画投稿されたらプログラムに書かれてあるメールアドレス宛に動画URLが送信されるようになる。

- crontabを使って定期的に投稿されたかチャンネルの投稿動画を確認する。

# 運用環境

```unix:環境
OS:CentOS7
プログラム言語：PHP7
データベース：MySQL
定期実行：crontab
サーバ実行環境：さくらVPS(安価なレンタルサーバでPHP7,cron,MySQLの機能が使える環境でもOKです。)
必要ツール：Youtube API
必要な情報：自分の持っているメールアドレス1〜2つ(現在も使用可能であること)
```

# Youtube APIの登録・APIキーの取得
このプログラムを動かすためには、チャンネルの情報を取得する必要があるため、Youtube APIの`APIキーの取得`が必須です。
以下の記事を参考にしてYoutube APIの登録を行いました。
https://blog.codecamp.jp/programming-api-youtube

最終的に、以下のようにAPIキーがコピーできる画面になりますので、`赤枠の部分の情報をメモしてください`。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120727/b609ab54-548c-e942-0990-4adb1e690b3d.png)

# YoutubeのチャンネルページにあるURLを取得する
例として[HikakinTV](https://www.youtube.com/channel/UCZf__ehlCEBPop-_sldpBUQ)さんのチャンネルIDを取得します。
チャンネルページにアクセスして、URLにある`赤枠の部分の情報をメモしてください`。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120727/8cbda076-0551-e0da-4a71-d6081eb68ba2.png)

# MySQLでテーブル作成
MySQLを使い、現状の新しい動画があるか値を保存するデータベースとテーブルを作成します。
例として、CentOS7の端末上で操作しています。

```unix:データベース作成
mysql> CREATE DATABASE NEW_VIDEO_DATA;
mysql> use NEW_VIDEO_DATA
```

```unix:テーブル作成
mysql> create table new_video_check(videoid varchar(200) NOT NULL PRIMARY KEY, title varchar(200));
```

```unix:テーブル中身
mysql> describe new_video_check;
+---------+--------------+------+-----+---------+-------+
| Field   | Type         | Null | Key | Default | Extra |
+---------+--------------+------+-----+---------+-------+
| videoid | varchar(200) | NO   | PRI | NULL    |       |
| title   | varchar(200) | YES  |     | NULL    |       |
+---------+--------------+------+-----+---------+-------+
```

# プログラム
PHPで作成したプログラムは以下の通りです。
コメントの部分の通りにメモした情報を記載してください。

```php:newvideocheck.php
<?php

class NewVideoCheck {
    
    private function apikey() {
        /* メモしたAPIキーを記載 */
        $apikey = "XXXXXXXXXXXXXXXXX";
        return $apikey;
    }

    private function mail_send($videoid) {
        /* 送信元メールアドレスを記載(送信元,送信先のメールアドレスは同じでも良い) */
        $from = "hogehoge@yahoo.co.jp";

        mb_language("Japanese");
        mb_internal_encoding("UTF-8");

        /* 送信先メールアドレスを記載(送信元,送信先のメールアドレスは同じでも良い) */
        $to      = 'hogehoge@gmail.com';
        $subject = '新しい動画・配信されたよ！';
        $message = 'URL https://www.youtube.com/watch?v=' . $videoid;
        $headers = "From: ".$from."\r\n";
        /* メール送信 */
        mb_send_mail($to, $subject, $message, $headers);
    }


    public function mysql_connect() {
        /* Mysql接続(サーバのIPアドレス、ユーザ情報、パスワードを記載してDBにアクセス) */
        $IPADDR = isset($_SERVER['SERVER_ADDR'])?$_SERVER['SERVER_ADDR']:gethostbyname(gethostname());
        if($IPADDR == 'YYY.YYY.YYY.YYY'){
            $link = mysqli_connect('YYY.YYY.YYY.YYY','root','XXXXXXXX');
        }
        if(!$link){
            die("エラー：DBに接続できません");
        }

        /* テーブル選択 */
        $db_selected = mysqli_select_db($link, 'NEW_VIDEO_DATA');
        if (!$db_selected){
            die("エラー：テーブルに接続できません");
        }

        return $link;
    }

    public function video_info($link) {
        /* channelIdにはメモしたチャンネルIDを記載する */
        $view_info_url = "https://www.googleapis.com/youtube/v3/search?part=snippet&channelId=UCZf__ehlCEBPop-_sldpBUQ&maxResults=1&order=date&type=video";
        /* YoutubeAPIキーを取得しURLに連結させる */    
        $view_info_url .= "&key=".$this->apikey();
    
        /* Youtube APIを使い動画の情報取得 */
        $json = file_get_contents($view_info_url);
        $json = mb_convert_encoding($json, 'UTF8', 'ASCII,JIS,UTF-8,EUC-JP,SJIS-WIN');
        $arr = json_decode($json, true);
        $videoid = $arr["items"][0]["id"]["videoId"];
        $title = $arr["items"][0]["snippet"]["title"];
        $videoinfo[0] = $videoid;
        $videoinfo[1] = $title;
        
        /* テーブル内にある動画IDと比較し、違っていたらメールを送信 */
        $select_sql = "select * from new_video_check limit 1";
        $select = mysqli_query($link, $select_sql);
        $tbl = mysqli_fetch_array($select);
        $new_videoid = $tbl[0];
        if($videoid != $new_videoid) {
            $this->mail_send($videoid);
        }

        return $videoinfo; 
    }

    public function video_register($link, $videoinfo) {

        $delete_sql = "delete from new_video_check";
        $delete = mysqli_query($link, $delete_sql);

        $register_sql = "insert into new_video_check values('".$videoinfo[0]."', '".$videoinfo[1]."')";
        $register = mysqli_query($link, $register_sql);
    }
}

// Mysqlのデータベースへアクセスする
$newvideocheck = new NewVideoCheck();
$link = $newvideocheck->mysql_connect();

// チャンネル内の最新動画を調べる
$videoinfo = $newvideocheck->video_info($link);

// チャンネル内で最新動画あげたら最新動画を登録する
$newvideocheck->video_register($link, $videoinfo);

?>
```

# cronを使って定期実行させる
作成したプログラムをサーバにアップロードさせてcronに定期実行させるようにします。
私の場合は1時間ごとにプログラムを動かすよう定期実行させています。

```unix:crontab
# 動画更新されたらメールで通知
00 */1 * * * /bin/php /tmp/batch/newvideocheck.php
```


# 動画投稿されたらメールが届くのを確認
以下の通りにHikakinTVのチャンネル内で動画投稿されたらメールで通知されました。
画像はGmailで確認しています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120727/afe6d8b5-e45d-8242-e32b-4a3d0fa9b02c.png)

# 問題点
1つのプログラムにつき1チャンネルの投稿を確認するので、複数のチャンネルでメール通知したいときはその分のデータベースとプログラムとcronへの記載が必要となる。