今日は何のゴミの日か教えてくれるLineBotを作成してみた



#要件定義
Lineに「今日は何のゴミの日？」とか「明日は？」、「明後日は」とかメッセージを送ると「燃えるゴミの日です」とか「資源プラゴミの日」ですとか返信してくれるLineBotを作成します。


#開発環境

CENTOSバージョン:8.0

```
$cat /etc/redhat-release
CentOS Linux release 8.0.1905 (Core) 
```

PHPバージョン：7.3

```
$ php -v
PHP 7.3.12 (cli) (built: Nov 19 2019 10:24:51) ( NTS )
Copyright (c) 1997-2018 The PHP Group
Zend Engine v3.3.12, Copyright (c) 1998-2018 Zend Technologies
```

MySQLバージョン：8.0

```
$ mysql --version
mysql  Ver 8.0.17 for Linux on x86_64 (Source distribution)
```

#データベース設計

データベース名は「linebot」とします。とりあえず、今後もいろんなlinebotを作成していくため。
テーブル名は「garbageday」(訳すとゴミの日)とします。

##カラム

- id
- day：日付
- garbage：ゴミ捨ての種別

#Line側の設定

以下にアクセスし、ログインして、諸々設定します。
https://developers.line.biz/ja/

コチラを参考にして、Messaging APIの設定を実施
https://qiita.com/caique/items/50e00c4a5801e2d583a4

#MySQLの設定

##mysqlインストール

```
$ sudo yum -y install mysql  mysql-server
```

##rootでログイン

```
# mysql -u root -p
Enter password: 

```
##rootのパスワード変更

- 8文字以上
- 数字、英字、記号含む


```
mysql> ALTER USER 'root'@'localhost' IDENTIFIED BY "（パスワード）";
```


##ユーザーの作成

```
mysql> create user "jum"@"localhost" identified by '(パスワード)';
```

##データベースの作成

```
mysql>create database linebot default character set utf8mb4;
Query OK, 1 row affected (0.00 sec)
```

##linebotデータベースに権限を付加する。

```
mysql>grant all privileges on linebot.* to "jum"@"localhost" identified by '(パスワード)';
Query OK, 0 rows affected, 1 warning (0.00 sec)
```

※mysql 8.0ではidenti…からは必要ない。

##ユーザーを変更する

```
mysql> exit
$ mysql -u (ユーザー名) -p
```

##テーブルを作成する

テーブル名は「garbageday」とする

```
mysql> use linebot;
Database changed
mysql> create table garbageday(id int not null primary key auto_increment,day date,garbage varchar(50));
Query OK, 0 rows affected (0.02 sec)
```

##テーブルの構成を確認する。

```
mysql> show columns from garbageday;
+---------+-------------+------+-----+---------+----------------+
| Field   | Type        | Null | Key | Default | Extra          |
+---------+-------------+------+-----+---------+----------------+
| id      | int(11)     | NO   | PRI | NULL    | auto_increment |
| day     | date        | YES  |     | NULL    |                |
| garbage | varchar(50) | YES  |     | NULL    |                |
+---------+-------------+------+-----+---------+----------------+
3 rows in set (0.00 sec)
```

##挿入するデータを作成する

sql文のファイルを作成する

```
$ vi insert.sql
```


```sql:insert.sql
insert into garbageday(day,garbage) values("2020-01-14","燃えるゴミ");
insert into garbageday(day,garbage) values("2020-01-15","不燃物ゴミ");
insert into garbageday(day,garbage) values("2020-01-16","資源プラゴミ");
insert into garbageday(day,garbage) values("2020-01-17","燃えるゴミ");
insert into garbageday(day,garbage) values("2020-01-18","無し");
insert into garbageday(day,garbage) values("2020-01-19","無し");
insert into garbageday(day,garbage) values("2020-01-20","缶とびんゴミ");
insert into garbageday(day,garbage) values("2020-01-21","燃えるゴミ");
insert into garbageday(day,garbage) values("2020-01-22","資源プラゴミ");
insert into garbageday(day,garbage) values("2020-01-23","スプレー缶蛍光管ゴミ");
insert into garbageday(day,garbage) values("2020-01-24","燃えるゴミ");
insert into garbageday(day,garbage) values("2020-01-25","ペットボトルゴミ");
insert into garbageday(day,garbage) values("2020-01-26","無し");
insert into garbageday(day,garbage) values("2020-01-27","古紙・布類ゴミ");
insert into garbageday(day,garbage) values("2020-01-28","燃えるゴミ");
insert into garbageday(day,garbage) values("2020-01-29","無し");
insert into garbageday(day,garbage) values("2020-01-30","資源プラゴミ");
insert into garbageday(day,garbage) values("2020-01-31","燃えるゴミ");
```

##データを挿入する

```
$ mysql -u jum -p linebot < insert.sql
```

##挿入されたか確認する

```
$ mysql -u jum -p
Enter password: 
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 31
Server version: 8.0.17 Source distribution

Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.


mysql> use linebot
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Database changed
mysql> select * from garbageday;
+----+------------+--------------------------------+
| id | day        | garbage                        |
+----+------------+--------------------------------+
|  1 | 2020-01-14 | 燃えるゴミ                     |
|  2 | 2020-01-15 | 不燃物ゴミ                     |
|  3 | 2020-01-16 | 資源プラゴミ                   |
|  4 | 2020-01-17 | 燃えるゴミ                     |
|  5 | 2020-01-18 | 無し                           |
|  6 | 2020-01-19 | 無し                           |
|  7 | 2020-01-20 | 缶とびんゴミ                   |
|  8 | 2020-01-21 | 燃えるゴミ                     |
|  9 | 2020-01-22 | 資源プラゴミ                   |
| 10 | 2020-01-23 | スプレー缶蛍光管ゴミ           |
| 11 | 2020-01-24 | 燃えるゴミ                     |
| 12 | 2020-01-25 | ペットボトルゴミ               |
| 13 | 2020-01-26 | 無し                           |
| 14 | 2020-01-27 | 古紙・布類ゴミ                 |
| 15 | 2020-01-28 | 燃えるゴミ                     |
| 16 | 2020-01-29 | 無し                           |
| 17 | 2020-01-30 | 資源プラゴミ                   |
| 18 | 2020-01-31 | 燃えるゴミ                     |
+----+------------+--------------------------------+
18 rows in set (0.00 sec)
```

#Lineで返信するための、コードを作成

```php:linebot.php
<?php

//line apiより
$accessToken = '（ここにはline apiよりアクセストークンを確認し入力してください）';

//ユーザーからのメッセージ取得
$json_string = file_get_contents('php://input');
$json_object = json_decode($json_string);

//取得データ
$replyToken = $json_object->{"events"}[0]->{"replyToken"};        //返信用トークン
$message_type = $json_object->{"events"}[0]->{"message"}->{"type"};    //メッセージタイプ
$message_text = $json_object->{"events"}[0]->{"message"}->{"text"};    //メッセージ内容

//メッセージタイプが「text」以外のときは何も返さず終了
if($message_type != "text") exit;

//mysqlに接続
define("DB_DATABASE","linebot");
define("DB_USERNAME","jum");
define("DB_PASSWORD","（設定したパスワード）");
define("PDO_DSN","mysql:host=localhost;dbname=" . DB_DATABASE);

 try{
   $db = new PDO(PDO_DSN,DB_USERNAME,DB_PASSWORD);
   $db->setAttribute(PDO::ATTR_ERRMODE,PDO::ERRMODE_EXCEPTION);
   $db->setAttribute(PDO::ATTR_EMULATE_PREPARES,false);
    } catch(PDOException $e) {
   $db->rollback();
   echo $e->getMessage();
   exit;
 }

//日付関連の処理
date_default_timezone_set('Asia/Tokyo');
$date = new DateTime();
$today = $date->format('Y-m-d');
$tomorrow = $date->modify('+1 days')->format('Y-m-d');
$day_after_tomorrow = $date->modify('+1 days')->format('Y-m-d');

//ユーザーが確認したいゴミの日
$Verification_Garbage_Day = "";

if(strpos($message_text,"今日") !== false) {
  $Verification_Garbage_Day = $today;
}
elseif(strpos($message_text,"きょう") !== false) {
  $Verification_Garbage_Day = $today;
}

elseif(strpos($message_text,"明日") !== false) {
  $Verification_Garbage_Day = $tomorrow;
}
elseif(strpos($message_text,"あした") !== false) {
  $Verification_Garbage_Day = $tomorrow;
}
elseif(strpos($message_text,"明後日") !== false) {
  $Verification_Garbage_Day = $day_after_tomorrow;
}

else {
  $Verification_Garbage_Day = "";
}

//変数$Verification_Garbage_Dayに値が入っていた場合、データベースと照合する
if(!empty($Verification_Garbage_Day)){

//返信する内容を保存する変数
$Return_Verification_Garbage_Day = "";

//データベースから読み取ったゴミの日
try{
    $sql = "select * from garbageday";
    $stmt = $db->query($sql);
    }
    catch(PDOException $e) {
    $db->rollback();
    echo $e->getMessage();
    exit;
                          }

    //データベースとユーザーが投稿した内容が一致するか確認する
    while($Garbage_Day_db = $stmt->fetch(PDO::FETCH_ASSOC)){

    if($Garbage_Day_db["day"] == $Verification_Garbage_Day) {

      $Return_Verification_Garbage_Day = $Garbage_Day_db["garbage"];

    }
  }
}else {
  $Return_Verification_Garbage_Day = "もう一度入力してください";
}

  sending_messages($accessToken, $replyToken, $message_type, $Return_Verification_Garbage_Day);
?>

<?php
  function sending_messages($accessToken, $replyToken, $message_type, $Return_Verification_Garbage_Day){



    //レスポンスフォーマット
    $response_format_text = [
        "type" => $message_type,
        "text" => $Return_Verification_Garbage_Day
      ];

        //ポストデータ
        $post_data = [
            "replyToken" => $replyToken,
            "messages" => [$response_format_text]
        ];

        //curl実行
        $ch = curl_init("https://api.line.me/v2/bot/message/reply");
        curl_setopt($ch, CURLOPT_POST, true);
        curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST');
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($post_data));
        curl_setopt($ch, CURLOPT_HTTPHEADER, array(
            'Content-Type: application/json; charser=UTF-8',
            'Authorization: Bearer ' . $accessToken
        ));
        $result = curl_exec($ch);
        curl_close($ch);
    }

?>
```

#こんな感じで出来上がりました

![スクリーンショット 2020-01-13 14.16.32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/420746/d74e676f-d932-db64-0386-1a62ecd62860.png)



データベースに今日の日付を入れていなかったので、今日には反応しませんでした。
明日が今日になれば反応するはず。


以上です。