Go+GAEで「ちょっと不便」を解決するLINEボットをつくった【CAMPHOR- Advent Calendar】

プログラミング

この記事は、CAMPHOR- Advent Calendarの22日目の記事です。

事の発端

僕は大学生協の学生委員会というサークル(?)に所属しており、それらに必要な企画書や議事録などのpdf, OfficeファイルがLINEグループで頻繁に飛び交います。LINEで業務報告するんじゃねぇ、Slackでイチャイチャするぞ

そして、この方法の一番の問題点は「送信されたファイルに保存期限がある」ということです。
送信されたファイルを一度でも開いていればキャッシュに残るので問題ないのですが、あとで見ようと放置していると一週間の保存期限はすぐに過ぎて、あとから必要なファイルが見られないという事態が発生します。

今回はこの問題を、ファイルが送信されたら自動でクラウドストレージに保存するLINEボットを作成することで解決していきたいと思います。
(本来はもともとクラウドストレージに上げたり、Slackなどを使うべきでありますが、エンジニアが少数派の環境で導入するのも大変なのです。)

完成したもの

こんな感じにファイルや写真を送ると、自動でDropboxへ保存し、共有リンクを投げてくれます。

「しおぱんだ」は弊サークルのマスコットキャラクターです

ファイルまたは画像を送信すると、下図のようにDropboxのアプリフォルダ内にトーク別に格納されます。

APIがまだうまく叩けておらず、ファイルの共有リンクを送信する部分は間に合いませんでした😭
ソースはまだ数日かけてリファクタリング予定ではありますが、こちらにあります。

ローカルサーバーでテストする

BotサーバーをGAEにあげる前にローカルでテストするには、

 dev_appserver.py --host=0.0.0.0 app.yaml   

を実行し、その後以下のようにngrokを実行し、発行されたアドレスをLINE DevelopersのWebhook URLに設定してあげればOKです。 -host-header=rewriteオプションをつけ忘れると、LINEからのアクセスがはねられるので注意しましょう。

 ngrok http --host-header=rewrite 8080

Go 1.11への対応

せっかくなので、Go Moduleを活用したかったため、Go 1.11を使用して開発を行いました。しかし、GAE側はGo 1.11へは対応中という感じで、情報量が少なく苦戦しました。

app.yamlの仕様変更

本Botは、こちらのサンプルを参考に作成させていただいたのですが、Go 1.11からはapp.yamlの仕様が割と変わっていました。具体的な差分はこのようになります。

左: サンプル改変前, 右:1.11で動かすための改変後
  • runtime には go111 を指定
  • api_version は不要に
  • handlers 内の scriptauto

http.ListenAndServeの追加

起動時に、http.HandleFunc などを実行した後、 http.ListenAndServe 関数を呼び出す必要があるようです。具体的には以下の一文をmain関数の最後などに追加します。

log.Fatal(http.ListenAndServe(fmt.Sprintf(":%s", port), nil))

GAEのHelloWorldサンプルを見比べた結果、恐らくこれもGo 1.11からの変更と思われます。
一時はなぜかこの一文なしでも動いていましたが、ある時をきっかけに下図のようなエラーが出て起動しなくなり、上述の一文を追加することで解決しました。

ERROR    2018-12-21 13:29:16,002 instance.py:284] Cannot connect to the instance on localhost:15518

そのほかにも、こちらのページを見ると多くの変更点が示されています。まだベータ版であるため、すでに動作しているプロダクトを移行するのはもう少し後でも良いかもしれません。

Migrating your App Engine app from Go 1.9 to Go 1.11  |  App Engine standard environment for Go 1.11 docs  |  Google Cloud

まとめ

大慌てで突貫工事したため、ソース等お見苦しい部分が多数あると思いますが、ひとまずLINEボットを実際に作ってみることができてよかったです。
最近はLIFFやリッチメニュー、Flex Messageなどで、ますます多様なコンテンツを含めた返信ができるようになっているので、Botの特性を生かしたプログラムを書いていきたいです。

またGo言語を使ってみて、JSONの構造体への自動変換やdefer文の便利さなどのありがたみを感じることができました。今回並列処理をゴリゴリ書くことはなかったので、是非もっと使っていきたいです。

コメント