コロナで暇だからあつ森株価記録LINE botを作った

コロナでおうち出れないから暇すぎたので，あつ森の株価とか余ってるレシピとかを記録して，他者と共有できるようなLINE botを作成しました．データベースに株価登録したり，余り物記録したり，それを取り出したりするだけの簡単なもの．
備忘録+文章力向上目的で書きます．

#環境
- macOS Mojave v10.14.6
- node.js v12.4.0
- Heroku
- PostgreSQL(HerokuのPosgreアドオンを使用)

#準備
環境構築とか事前準備とかは他の方の記事を見てもらえば十分理解できるので割愛．
サーバ関係は全部Herokuにぶん投げました．

参考にさせていただいたサイト
[LINE BOTをHeroku + Node.jsでやるまで](https://qiita.com/TakuTaku04/items/cb71f10669a9e9cbf71b)


#機能紹介
<img width="414" alt="IMG_A1A5A603BD02-1.jpeg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/508053/a1664c1f-4470-617f-78d5-dfdd43c3ae74.jpeg">

- botに数値を入力すると，その日の日付と午後か午前かを取得して株価として記録する．
- "株価一覧"と入力すれば，自分の今までの記録が見れる．
- すでにその日の記録がされている場合は，上書きするか確認する．

<img width="414" alt="IMG_09C0BEFEE70D-1.jpeg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/508053/2be3db8f-7887-bff1-3e56-4b0c3cc813cb.jpeg">

- リッチメニューの実装
- 余り物記録＆管理機能


#システム構成
![system_bot.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/508053/a1a3d86f-2829-5a00-0d61-01d8a2bdeda3.png)
システム構成はこんな感じ
botにメッセージを送ると，Herokuで処理して，必要ならデータベースにアクセスする.

#躓いたところ
##Webhook URLからレスポンスが帰ってこない
botのwebhook設定画面のURLと
コードのURLは同じ名前にしないとダメだよ（当たり前）

ちなみに名前はなんでもいい
callbackとかwebhookとか好きなので

##ユーザ名を取得したいのにうまくいかない
```js
const line = require('@line/bot-sdk');

const client = new line.Client(config);

function getUserName() {
    const userId = event.source.userId;
    const profile = client.getProfile(userId);
    return profile.displayName
}

const userName = getUserName();
console.log('ユーザ名は${userName}です');
```
出力結果

```shell

ユーザ名はundefinedです
```
undefinedが出力されてしまう．
どうやらユーザIDからプロフィールを取得する処理を待つ前に変数に代入していたため"undefined"となっていたようだ.
####しっかり非同期処理で書こう
```js
async function getUserName() {
    const userId = event.source.userId;
    const profile = await client.getProfile(userId);
    return profile.displayName
}

getUserName().then(userName => {
    console.log('ユーザ名は${userName}です');
})
```
async/awaitの使い方については[この記事](https://qiita.com/soarflat/items/1a9613e023200bbebcb3)を参考にしました．

##確認テンプレートが何回も作動してしまう
本来ならば”はい”を押せば，"いいえ"は押せちゃダメだし，もう一度”はい”も押せてはいけない．
だけど，初期設定のままだと何回も押せてしまう．
![スクリーンショット 2020-04-29 6.34.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/508053/cce3d99e-c8ae-49e7-2ed5-2d06f6aafede.png)
なので，事前に押したかどうかのフラグを建てておいて，”はい”，もしくは”いいえ”を押した時に，フラグをおろすようにする．
次にフラグを建てるのは確認テンプレートがもう一度呼ばれた時でおk

##データベースとの連携がうまくいかない
正直どんなエラー文が出ていたかは，全く覚えてないが
[node-postgres](https://node-postgres.com/)の使い方が間違ってたというか，理解してなかった.
公式ページを見るとこんな感じに書けと書いてあるけど，なぜかこれではうまくいかなかったので

```js
const { Client } = require('pg')
const client = new Client({
  host: 'my.database-server.com',
  port: 5334,
  user: 'database-user',
  password: 'secretpassword!!',
})
```

heroku側にデータベースのURLを環境変数としてセッティングし，

```shell
$ heroku config:set DATABASE_URL="LINEbotの管理画面に記述されているデータベースURL" --app "app_name"
```

これをそのまま呼び出した方が楽

```js
const {Client} = require('pg');

const dbclient = new Client({
    connectionString: process.env.DATABASE_URL,
});
```

なぜうまくいかなかったのかは不明．
多分僕のやり方が悪いので，pgとは別のところに問題があったと思われる．

あと，
herokuにSSL認証を設定してない場合は，ssl要素をtrueにすると，エラーが出るので注意

```js
const dbclient = new Client({
    connectionString: process.env.DATABASE_URL,
    ssl: true,
});
```
何処かのサイトを脳死で参照してたら，このエラーで時間がとけた．

#未解決な問題
###時間指定して株価を記録したい
現在は，株価を入力した時の時間として記録しかできないが，入力した株価がいつのものなのか指定して入力できるようにしたい．

どうやら[日時選択アクション](https://developers.line.biz/ja/reference/messaging-api/#datetime-picker-action)というのが，できるらしいのでこれを使えばいいっぽい．
けど実装がめんどくさいので．気が向かないとやらない．

###複数人同時処理ができない
例えば，このbotだと
余り物を記録する時は，"余り物記録"と入力することによって入力待ち状態とし，次に入力したメッセージを余り物としてデータベースに格納する．

しかし，この入力待ち状態の時に，他のユーザがメッセージをPostしてしまうと，それが余り物として記録されてしまう．
その後，bot側は入力したメッセージをただの文字列だと判断して，本来余り物を記録するはずだったユーザに定型文を返してしまうのだ．

ユーザごと別々に処理されると考えていたので，大きな誤算だった．

多分[これ](https://www.eisbahn.jp/yoichiro/2016/04/line_bot_api.html)を実装すればなんとかなるような気がするが，趣味で作ったものなのでそこまでやる気力はない．

簡単な方法があれば知りたい
教えてすごい人

#最後に
記事を書いている最中にやる気が無くなったので，半分以上投げやり
というか，この記事は自分の役にすら立たない内容な気がする．
今度からはコード書きつつ，詰まったところをメモろう．

コードは人に見せられる状態じゃないので，上げれません．

でも，
LINEbot開発結構楽しい
そこそこのJSの知識あれば書けるし，Pythonとかでも書ける．
日本人とLINEは切っても切れないものなので，自分で色々作れたら何かと便利そう．