Heroku × LINEBot × Twitterで猫Botを作ってみた

# 最初に
- ネタ的には多くの猫好きエンジニアがやりそうなこと・・・。
- 2016年12月頃に作ったものなので色々古いかもです。
- 当初の構成図ではラズパイとwebカメラを使用してIoT的な監視botを作りたかったのですが運用開始直前に家庭内稟議で否認され実現できませんでした:sob:
   - 電気代の問題
   - 猫のプライバシー問題
- 各種設定は参考サイトが詳しいのでここでは作成までの道のりを記載します。

# 構成図
## 初期
![猫Bot初期構成図.jpg](https://qiita-image-store.s3.amazonaws.com/0/232177/bd8808ba-b238-0222-953d-915b7c3aaec2.jpeg)

## 現実
![猫Bot妥協構成図.jpg](https://qiita-image-store.s3.amazonaws.com/0/232177/a1fac597-eda7-26c3-ad77-3c3b7e641b31.jpeg)

# heroku設定
## 初期設定
@Arashiさんの記事を参考にさせて頂きました。
参考）http://qiita.com/Arashi/items/b2f2e01259238235e187

## fixieインストール
LINE BOT API の呼び出しには Server IP Whitelist に接続元 IP の指定が必要なのでこいつが必要
https://elements.heroku.com/addons/fixie
@yuya_takeyamaさんの記事を参考にさせて頂きました。
参考）https://qiita.com/yuya_takeyama/items/0660a59d13e2cd0b2516

## config設定方法
http://dackdive.hateblo.jp/entry/2016/01/26/121900

# LINE設定
## BOT APIの登録
https://at.line.me/jp/
https://www.panzee.biz/archives/9115

## APIリファレンス
https://developers.line.me
https://devdocs.line.me/ja/?php#reply-message

# twitter設定
## twitterアプリケーション登録
https://dev.twitter.com/apps

## twitterSDK
https://github.com/abraham/twitteroauth

## PHPでTwitterのツイートを取得・表示する方法
http://2m3g1.com/751.html

# heroku上に設定する環境変数
値は各個人の設定に変えてあげてください。

```bash:heroku.config
heroku config:set LINE_TOKEN=LINE_TOKEN_HOGE
heroku config:set FIXIE_URL=HEROKU_FIXIE_URL
heroku config:set APP_NAME=HEROKU_APP_NAME
heroku config:set tw_consumer_key=TW_CONSUMER_KEY
heroku config:set tw_consumer_secret=TW_CONSUMER?SECRET
heroku config:set tw_access_token=TW_ACCESS_TOKEN
heroku config:set tw_access_token_secret=TW_ACCESS_SECRET
```
# heroku上にデプロイしたアプリケーションのディレクトリ設定
以下のように配置します。

```
|--index.php　← LINEとTwitterをごにょごにょするプログラム
|--twitteroauth　← twitterのSDK
|  |--.gitignore
|  |--.travis.yml
|  |--LICENSE.md
|  |--README.md
|  |--autoload.php
|  |--composer.json
|  |--phpmd.xml
|  |--phpunit.xml
|  |--src
|  |  |--Config.php
|  |  |--Consumer.php
|  |  |--HmacSha1.php
|  |  |--Request.php
|  |  |--Response.php
|  |  |--SignatureMethod.php
|  |  |--Token.php
|  |  |--TwitterOAuth.php
|  |  |--TwitterOAuthException.php
|  |  |--Util
|  |  |--Util.php
|  |  |  |--JsonDecoder.php
|  |  |--cacert.pem
```

# プログラム
```php:index.php
<?php
//--------------------------------
// Line Input
//--------------------------------
$php_input = json_decode(file_get_contents('php://input'));
$text = $php_input->{"events"}[0]->{"message"}->{"text"};
$reply_token = $php_input->{"events"}[0]->{"replyToken"};

//--------------------------------
// Create Media By Twitter 
//--------------------------------
$response_content = getResponseContent($reply_token,$text);

//--------------------------------
// Line Bot 
//--------------------------------
postLineBot($response_content);

function createHttpHeader() {
    $header = array(
        'Content-Type: application/json; charset=UTF-8',
        'Authorization: Bearer '.getenv("LINE_TOKEN")
    );
    return $header;
}
function getResponseContent($reply_token,$text) {
    if((strpos($text, '絹') !== false) || (strpos($text, '鱈') !== false)){
        return createImageResponse($reply_token);
    }
    return createTextResponse($reply_token,"はらへった〜");
    
}
function createTextResponse($reply_token,$message) {
    $response_format_text = [ 
        "type" => "text",
        "text" => $message 
    ];
    
    $post_data = array(
        "replyToken" => $reply_token,
        "messages" => [$response_format_text]
    );

    return $post_data;
}
function createImageResponse($reply_token) {
     $tw_auth = getTwitterAuth();
     $req = $tw_auth->get("statuses/user_timeline",array("count"=>"5"));
     $media_url = array();
     foreach($req as $key => $val){
        $media_url[] = [
           "type" => "image",
           "originalContentUrl" => $val->entities->media[0]->media_url_https.":small",
           "previewImageUrl" => $val->entities->media[0]->media_url_https.":thumb"
        ];
     }

    if(count($media_url) === 0) return createTextResponse($reply_token,"ねむい〜");

    $media_id = mt_rand(0,count($media_url)-1);
    $post_data = array(
        "replyToken" => $reply_token,
        "messages" => [$media_url[$media_id]]
    );

    return $post_data;
}

function getTwitterAuth() {
    require_once("./twitteroauth/autoload.php");
    $consumer_key = getenv("tw_consumer_key");
    $consumer_secret = getenv("tw_consumer_secret");
    $access_token = getenv("tw_access_token");
    $access_token_secret = getenv("tw_access_token_secret");
    $to = new \Abraham\TwitterOAuth\TwitterOAuth($consumer_key,$consumer_secret,$access_token,$access_token_secret);
    return $to;
}

function postLineBot($response_content){
    $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($response_content));
    curl_setopt($ch, CURLOPT_HTTPHEADER, createHttpHeader());
    curl_setopt($ch, CURLOPT_HTTPPROXYTUNNEL, 1);
    curl_setopt($ch, CURLOPT_PROXY, getenv("FIXIE_URL"));
    curl_setopt($ch, CURLOPT_PROXYPORT, 80);
    $result = curl_exec($ch);
    curl_close($ch);
}
```
# デモ
<blockquote class="twitter-tweet" data-lang="ja"><p lang="und" dir="ltr"><a href="https://t.co/Ey2jz14ILs">https://t.co/Ey2jz14ILs</a></p>&mdash; 翔太@猫まっしぐら (@YamaNoSk8NoLife) <a href="https://twitter.com/YamaNoSk8NoLife/status/957471201000960003?ref_src=twsrc%5Etfw">2018年1月28日</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

# その他参考サイト
http://qiita.com/chibi929/items/a368fdc3ef3485302302
http://qiita.com/ttskch/items/7c148fcc595cec4aa59a
http://qiita.com/kurouw/items/f00229e51818d80ae643
http://qiita.com/TetsuyaImagawa/items/7517b287e68efe21c0cc
http://qiita.com/Kosuke-Szk/items/eea6457616b6180c82d3

# その他参考サイト（qiita以外）
http://m-shige1979.hatenablog.com/entry/2016/10/14/080000
http://ola.kironono.com/entry/2016/04/09/205251
http://iti.hatenablog.jp/entry/2016/04/27/113053
http://furyu.hatenablog.com/entry/20160225/1456353020