予定をLINEに通知する


はじめに

日々の予定をカレンダーや表にまとめているのですが、自分から確認しないといけないのを不便に感じていました。そこで、下記を使ってLINEに通知する仕組みを作ったので紹介していきたいと思います。

環境

ざっくり以下を利用しています。

LINE Notifyの設定

LINEにメッセージを送るには主に2通りのやり方があります。
1つはLINE公式アカウントを開設し、そのアカウントと友達になってメッセージを送る方法。
もう1つはLINE Notifyを利用する方法です。
LINE公式アカウントはメッセージ送信だけでなく、Webhookを利用してBotとして活用したり、Official Account ManagerというCMSがあったりして、やれることがたくさんありますが、開設までに少しハードルがあります。
LINE Notifyはメッセージ送信に特化しており、LINEアカウントを既に持っていれば、新たにアカウントを開設することなくすぐに利用開始できるのがメリットです。
APIでメッセージ送信もできますし、Github、IFFFTなど連携することも簡単にできます。

今回はLINE NotifyのAPIを利用して、LINEメッセージを任意のユーザもしくはトークルームに送信することにします。
LINE Notifyにログインし、マイページを開きます。
すると、アクセストークンの発行ボタンがありますので、そこで通知したいユーザもしくはトークルームを設定しトークンを発行してください。

アクセストークンボタン

それでは試しに、terminalからcurlコマンドでAPIを呼び出してメッセージを送信してみましょう。

curl -i -X POST "https://notify-api.line.me/api/notify" \
  -H "Content-Type:application/x-www-form-urlencoded" \
  -H "Authorization: Bearer {your access token}" \
  -d 'message="{"type": "text", "text": "test message!"}"'

これでLINE Notifyの準備はOKです。

ローカル環境のDocker設定

今回、デプロイ先にはHerokuのDyno(Hobby Plan)にします。
そのため、Dockerを利用してデプロイするようにしました。下記記事を参考にしました。
とてもわかり易く記載してあり助かりました。ありがとうございます。

https://qiita.com/croquette0212/items/2b85aa2c6b2933244f07

ローカルで開発する際に、アプリケーションの動作確認をすると思います。
そのとき、Dockerコンテナでcurlコマンドが利用できないと不便だったので、Dockerfileに追記しています。

FROM golang:1.15.3 as builder

ENV CGO_ENABLED=0
ENV GOOS=linux
ENV GOARCH=amd64
# 自身の構成に合わせて下記を変更
WORKDIR /go/src/github.com/{App Name}
COPY . .
RUN go build ./src/cmd/main.go

# runtime image
FROM alpine
# --- ここから
RUN apk update
RUN apk add curl
# --- ここまで追加
# 自身の構成に合わせて下記を変更
COPY --from=builder /go/src/github.com/{App Name} /app

CMD /app/main $PORT

Dockerfileをrootディレクトリ直下ではなく、/dockr/Dockerfileなどに配置しようとしたのですが、Herokuのデプロイの際にDockerfileが見つからないとエラーになってしまいました。
なので、今回はDockerfileはrootディレクトリ直下に配置しています。

開発

言語に関してはWebアプリを開発できるのであればJavaでもRubyでも何でも問題ないです。
やりたいことは下記です。

  • Httpリクエストを受け付け、処理を実行できる
  • Httpリクエストを送信できる(最悪、curlコマンドを直接実行できれば良いです)
  • DBへのアクセスができる

今回は使い慣れているgolang(Gin Framework)で開発をしました。
開発内容自体は特別なことをしていないので省きます。
HerokuではDBとして、Postgresのアドオンが用意されています。それを利用します。
そうするとローカルでもDB環境が欲しくなったので、DBもDockerコンテナで用意することにしました。
先程作成したアプリ用のコンテナとは別にDBのコンテナを作成するので、複数のコンテナを使用するのに便利なDocker Composeを使います。
Docker Composeを使うには、docker-compose.ymlが必要になります。
この記事を参考にしました。

https://solutionware.jp/blog/2018/05/23/docker-tutorial-heroku-postgres/
version: "3"

services:
  app:
    build:
      context: .
      dockerfile: Dockerfile # ここで先程のDockerfileを指定する
    ports:
      - 3000:3000
    env_file: ./.env
  db:
    image: postgres:12.4-alpine
    environment:
      IMPORT_FROM_DIR:
      POSTGRES_USER: user
      POSTGRES_PASSWORD: password
      POSTGRES_DB: db
    ports:
      - 5432:5432
    volumes:
      - ./db/sh:/docker-entrypoint-initdb.d
      - ./db/scripts:/scripts

docker-compose.ymlが用意できたら、下記コマンドで実行してみましょう。

docker-compose up -d

起動したら、curlなどで開発したAPIにアクセスして稼働確認してみてください。
今回の設定だとlocalhost:3000/{APIのパス}で接続できるはずです。

app:
    ...
    env_file: ./.env

上記設定でアプリ実行時に読み込む環境変数を設定しています。
githubでソースコード管理をしていますが、アクセストークンなどの漏洩させてはいけない情報はアップロードしたくありません。そのため、ローカル開発環境では.envファイルを作成し、その中に情報を記載しています。
もちろん.gitignoreでgithubで管理する対象から除外しています。

Herokuへデプロイ

アプリが用意できたら、Herokuへデプロイしましょう。
まずはHerokuにアプリを作成します。

# 開発中のアプリのルートディレクトリに移動します
cd {ルートディレクトリ}

# まずはHerokuにログインします
heroku login
heroku container:login

# Herokuアプリの作成をします
heroku create

# Herokuアプリに環境変数を設定します
# LINE Notifyのアクセストークンなどを設定します
heroku config:set {key}="{value}"

# Herokuへアプリをデプロイします
heroku container:push web

これでデプロイできたはずです。アクセスしてみましょう。
HerokuアプリのURLを調べる場合は下記コマンドで見てみましょう。

heroku info

出力された内容のWeb URLという項目がアプリのURLになります。
さきほど設定した環境変数を見る場合はheroku configで設定されている環境変数一覧が確認できます。

Heroku Schedulerの設定

今回やりたいことが定期的にLINEに通知するということだったのですが、Heroku DynoのHobby Planだとアクセスがない状態が一定時間続くとスリープ状態になってしまいます。
そのため、cronのように10分起きに起動するという方法なども考えられます。しかし、そこまで頻繁に予定を通知したいわけではなかったので、Heroku Schedulerを利用することにします。
Heroku Schedulerを利用するには先程作成したHerokuアプリの管理画面を開き、Configure Add-onsでHeroku Schedulerを追加してください。
Schedule作成画面は次のような感じです。

Schedulerから直接URLを叩く方法やgolangを起動する方法がわからず、画像のようにスクリプトファイルを起動する形になっています。スクリプトの中身は以下です。

#! /bin/sh

curl -X GET "${APP_URL}" -H "Authorization: Bearer ${ACCESS_TOKEN}"

${APP_URL}${ACCESS_TOKEN}は環境変数です。APP_URLは用意したAPIのURLです。
ACCESS_TOKENはLINE Notifyのアクセストークンではなく、任意で決めた文字列です。
これがないと誰でもAPIにアクセスできてしまうので、ほかの人が推測できないような文字列にしています。
他にもセキュリティを担保するやり方はいくつもあると思いますが、今回は簡易的に実装しています。

また、注意点として、Schedulerの設定時刻です。こちらはUTCが基準となっているため日本時間に合わせるには9時間の時差を考慮する必要があります。
毎日朝8時にSchedulerを起動したい場合は、9時間マイナスしてUTCの23時に設定しなければならないということです。

さいごに

ざっと説明しましたが、これで毎朝登録してある予定がLINE Notifyを通じて任意のトークルームに通知されるようになりました。
仕組みとしては単純ですが、出てくる技術要素が意外と多く楽しく取り組むことができました。
LINEではなくSlackへ通知したい場合などもほぼ同じ仕組みで実装できると思います。
今後もこういったものを作成したときは記事にしようと思います。
最後までお付き合いいただきありがとうございました。