身内専用の新型コロナ対策情報 LINE アカウントを1時間で作成してみた

新型コロナウイルスが猛威を振るっているのと比例して、新型コロナウイルスにテクノロジーで対抗しようとするエンジニアが様々なサイトや API を作成しています。以下の API (個人作成) では県別の新型コロナ感染者の詳細情報を取得できる仕様になっています。(作成していただいている方、ありがとうございます！)

[🇯🇵日本を対象とした🦠コロナウイルス情報 Web APIが無かったので2日間で公開した話](https://qiita.com/ryo-ma/items/20db8cd20f1086838249)

この API を利用することで、自分に必要な情報を上手くフィルターし取得することができそうなので、新型コロナウイルスの感染者の情報等を提供する LINE アカウントを作成してみようと思います。今回は例として、私の地元である長野県の情報を提供する LINE アカウントを作成してみようと思います。(身内用のアカウントだと思ってください。)

作成する手順は以下です。

* LINE 設定
* API を確認し取得できる JSON の Schema を作成
* Logic App でロジックの作成

#完成品
完成品は一般公開しています。以下の QR コードから `【非公式】長野県のコロナ感染状況` というアカウントを友達に追加していただくことで実際に利用することが可能です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/149921/28a77778-db1e-4176-4c04-d3436a5add2c.png)
もしくは ID 検索で追加いただけます。ID -> `@658zgawt`
LINE のイメージはこんな感じです。朝8:00になると昨日までに集計された感染者の詳細情報が提供されます。メニューでは各種情報サイトへのリンクを設定してあります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/149921/34fde029-8de6-bed6-2625-9eec0f52a152.png)


**【4/5 22:00 UPDATE】
コメントにも記載しましたが、LINE PUSH Massage は追加アカウント数にフリープランでは限度があるみたいで、いまは一部のアカウントにしか送信できなくなっています。追加頂いた方申し訳ないです、、！**


#LINE 設定
##LINE Message API の設定
まずは LINE Developers のページで LINE アカウントを作成するための設定を行います。以下ページにサインインし、`Messaging API` を選択します。
参考情報 : [LINE Developers](https://developers.line.biz/en/)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/149921/7148cfc6-0980-096d-cdb9-1f9a67ce1946.png)
Provider作成 -> チャネルの作成、を実施します。作成方法は過去の記事に書いているのでこちらを参考にしてください。
参考情報 : [Logic App × LINE Messaging API で買い時の株アラートをラインに送付する！](https://qiita.com/komiyasa/items/5bbd93342f32f89eaf23)
今回は `StopCovid` という Provider を作成し、`【非公式】長野県のコロナ感染状況` というチャネルを作成しました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/149921/88bbdcaf-cd8a-b65e-4c26-312bd5624cac.png)
作成が完了したら、Basic Setting から `UserID` と、Messaging API から `Channel access token` をコピーしておきます。(あとで Logic App で使用します。)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/149921/7b60e185-ad58-75c3-de8c-e708dfe490d6.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/149921/6246e33f-2c47-bc1c-0c3b-fac38f5c5ad6.png)

これで Messaging API 側の設定は完了です。

##LINE Account のメニュー設定
次に、ラインのメニュー画面をカスタマイズします。Account のページから、`LINE Official Account Manager` に移動します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/149921/2c12123a-3fbd-964f-1f53-1fb6b9f0a72d.png)
Account Manager のページの左側のメニューで `Rich Menus` という設定を選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/149921/ef4b79f6-c337-3dce-a07c-b76feb6ac97b.png)
`Create New` を選びます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/149921/0806cbc7-31c6-6372-44df-ae36a4757f15.png)
カスタマイズするテンプレートを選択し、背景の設定、テキストの設定、リンクの設定を行います。ここは UI が非常に分かりやすいので、感覚的に設定することが出来ます。(LINEさん凄い) 今回の例では以下のような感じで設定しました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/149921/65eef921-7197-e4bc-9a81-fecf3f6a99f7.png)
リンクで設定した URL は以下の 4 つです。

タイトル | URL
---|---
【公式】長野県庁新型コロナ対策特設ページ | https://www.pref.nagano.lg.jp/hoken-shippei/kenko/kenko/kansensho/joho/corona.html
【公式】NHK新型コロナ特設サイト | https://www3.nhk.or.jp/news/special/coronavirus/
【非公式】長野県感染者状況まとめサイト | https://stop-covid19-nagano.netlify.com/
【非公式】新型コロナ情報ダッシュボード | https://www.stopcovid19.jp/
設定がうまくいくと LINE の Account Manager のページで以下のようなプレビューをみることが出来ます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/149921/ea85564e-b22c-d0b5-3eee-68b7f13e5110.png)
これで LINE 側の設定は完了です。

#API を確認し取得できる JSON の Schema を作成
冒頭で紹介した記事の中に、新型コロナ感染者の詳細情報を取得できる以下の API があります。
https://covid19-japan-web-api.now.sh/api/v1/positives
この API を実行すると、以下のような Response を得ることができます。

```json
[
  {
    "prefecture": "北海道",
    "residence_prefecture": "国外（武漢市）",
    "age": "40代",
    "gender": "女性",
    "attribute": "来日観光客",
    "prefecture_number": "北海道1",
    "travel_or_contact": "渡航歴",
    "detail": "中国（武漢）",
    "src": "https://www.mhlw.go.jp/stf/newpage_09158.html",
    "onset": "1月26日",
    "symptom": "1",
    "death_or_discharge_date": "",
    "comment1": "",
    "outcome": "",
    "outcome_src": "",
    "comment2": ""
  },
  {
    "prefecture": "北海道",
    "residence_prefecture": "札幌市",
    "age": "50代",
    "gender": "男性",
    "attribute": "来日観光客",
    "prefecture_number": "北海道2",
    "travel_or_contact": "",
    "detail": "",
    "src": "http://www.pref.hokkaido.lg.jp/hf/kth/kak/hasseijoukyou.htm",
    "onset": "1月31日",
    "symptom": "1",
    "death_or_discharge_date": "",
    "comment1": "",
    "outcome": "",
    "outcome_src": "",
    "comment2": ""
  },
...
```

この JSON Schema を作成します。以下のような形です。

```json

{
    "type": "array",
    "title": "The Root Schema",
    "description": "The root schema comprises the entire JSON document.",
    "items": {
        "$id": "#/items",
        "type": "object",
        "title": "The Items Schema",
        "description": "An explanation about the purpose of this instance.",
        "default": {},
        "required": [
        ],
        "properties": {
            "id": {
                "$id": "#/items/properties/id",
                "type": "string",
                "title": "The Id Schema",
                "description": "An explanation about the purpose of this instance.",
                "default": "",
                "examples": [
                    "ID01001"
                ]
            },
            "announcement_date": {
                "$id": "#/items/properties/announcement_date",
                "type": "string",
                "title": "The Announcement_date Schema",
                "description": "An explanation about the purpose of this instance.",
                "default": "",
                "examples": [
                    "2020/01/28"
                ]
            },
            "diagnosis_date": {
                "$id": "#/items/properties/diagnosis_date",
                "type": "string",
                "title": "The Diagnosis_date Schema",
                "description": "An explanation about the purpose of this instance.",
                "default": "",
                "examples": [
                    ""
                ]
            },
            "prefecture": {
                "$id": "#/items/properties/prefecture",
                "type": "string",
                "title": "The Prefecture Schema",
                "description": "An explanation about the purpose of this instance.",
                "default": "",
                "examples": [
                    "北海道"
                ]
            },
            "residence_prefecture": {
                "$id": "#/items/properties/residence_prefecture",
                "type": "string",
                "title": "The Residence_prefecture Schema",
                "description": "An explanation about the purpose of this instance.",
                "default": "",
                "examples": [
                    "国外（武漢市）"
                ]
            },
            "age": {
                "$id": "#/items/properties/age",
                "type": "string",
                "title": "The Age Schema",
                "description": "An explanation about the purpose of this instance.",
                "default": "",
                "examples": [
                    "40代"
                ]
            },
            "gender": {
                "$id": "#/items/properties/gender",
                "type": "string",
                "title": "The Gender Schema",
                "description": "An explanation about the purpose of this instance.",
                "default": "",
                "examples": [
                    "女性"
                ]
            },
            "attribute": {
                "$id": "#/items/properties/attribute",
                "type": "string",
                "title": "The Attribute Schema",
                "description": "An explanation about the purpose of this instance.",
                "default": "",
                "examples": [
                    "来日観光客"
                ]
            },
            "prefecture_number": {
                "$id": "#/items/properties/prefecture_number",
                "type": "string",
                "title": "The Prefecture_number Schema",
                "description": "An explanation about the purpose of this instance.",
                "default": "",
                "examples": [
                    "北海道1"
                ]
            },
            "travel_or_contact": {
                "$id": "#/items/properties/travel_or_contact",
                "type": "string",
                "title": "The Travel_or_contact Schema",
                "description": "An explanation about the purpose of this instance.",
                "default": "",
                "examples": [
                    "渡航歴"
                ]
            },
            "detail": {
                "$id": "#/items/properties/detail",
                "type": "string",
                "title": "The Detail Schema",
                "description": "An explanation about the purpose of this instance.",
                "default": "",
                "examples": [
                    "中国（武漢）"
                ]
            },
            "cluster": {
                "$id": "#/items/properties/cluster",
                "type": "string",
                "title": "The Cluster Schema",
                "description": "An explanation about the purpose of this instance.",
                "default": "",
                "examples": [
                    ""
                ]
            },
            "src": {
                "$id": "#/items/properties/src",
                "type": "string",
                "title": "The Src Schema",
                "description": "An explanation about the purpose of this instance.",
                "default": "",
                "examples": [
                    "https://www.mhlw.go.jp/stf/newpage_09158.html"
                ]
            },
            "onset": {
                "$id": "#/items/properties/onset",
                "type": "string",
                "title": "The Onset Schema",
                "description": "An explanation about the purpose of this instance.",
                "default": "",
                "examples": [
                    "2020/01/26"
                ]
            },
            "symptom": {
                "$id": "#/items/properties/symptom",
                "type": "string",
                "title": "The Symptom Schema",
                "description": "An explanation about the purpose of this instance.",
                "default": "",
                "examples": [
                    "1"
                ]
            },
            "death_or_discharge_date": {
                "$id": "#/items/properties/death_or_discharge_date",
                "type": "string",
                "title": "The Death_or_discharge_date Schema",
                "description": "An explanation about the purpose of this instance.",
                "default": "",
                "examples": [
                    ""
                ]
            },
            "comment1": {
                "$id": "#/items/properties/comment1",
                "type": "string",
                "title": "The Comment1 Schema",
                "description": "An explanation about the purpose of this instance.",
                "default": "",
                "examples": [
                    ""
                ]
            },
            "outcome": {
                "$id": "#/items/properties/outcome",
                "type": "string",
                "title": "The Outcome Schema",
                "description": "An explanation about the purpose of this instance.",
                "default": "",
                "examples": [
                    ""
                ]
            },
            "outcome_src": {
                "$id": "#/items/properties/outcome_src",
                "type": "string",
                "title": "The Outcome_src Schema",
                "description": "An explanation about the purpose of this instance.",
                "default": "",
                "examples": [
                    ""
                ]
            },
            "comment2": {
                "$id": "#/items/properties/comment2",
                "type": "string",
                "title": "The Comment2 Schema",
                "description": "An explanation about the purpose of this instance.",
                "default": "",
                "examples": [
                    ""
                ]
            }
        }
    }
}
```
Schema を作成しておくことで、Logic App からデータを抜き出すときに便利です。これをそのままどこかにコピーしておきます。

#Logic App でロジックの作成
##Timer トリガーの設定
Azure Logic App でロジックを作成します。毎朝8時にアラートを投げるため、Timer トリガーを設定します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/149921/4c1e654b-255b-a8fd-d9d1-55417b52ac73.png)
Timer トリガーを設定するためには、タイムゾーンを設定する必要があります。以下のドキュメントが参考になります。
参考情報 : [Azure Logic Apps で繰り返しトリガーを使用して繰り返しタスクおよびワークフローを作成、スケジュール設定、および実行する](https://docs.microsoft.com/ja-jp/azure/connectors/connectors-native-recurrence)

##HTTP リクエストを設定する
次に先ほどの API で HTTP リクエストを送信します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/149921/2ac9238a-37b0-d918-4fa8-9c4a93c2726c.png)
参考情報 : [Azure Logic Apps を使用して HTTP または HTTPS エンドポイントに発信呼び出しを送信する](https://docs.microsoft.com/ja-jp/azure/connectors/connectors-native-http)

##JSON をパースする
次に API で取得した JSON をパースします。先ほど作成した JSON Schema を入力します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/149921/8a4d4f5b-c5d3-7e01-bc3e-ce138223552d.png)
JSON Perse をすることで、あとで Filter をかけたい値や、取り出したい値を動的コンテンツとして取得することができるようになります。
参考情報 : [Azure Logic Apps でデータの操作を実行する](https://docs.microsoft.com/ja-jp/azure/logic-apps/logic-apps-perform-data-operations)

##JSON を Filter する
次に Filter Array で県が `長野県` と一致するものにフィルターをかけます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/149921/dbfe2317-e328-7938-bd89-74fa4b6e1efd.png)

##CSVテーブルを作成する
JSON オブジェクトからのプロパティと値を配列に含むコンマ区切り値 (CSV) テーブルを作成するには、CSV テーブルの作成アクションを使用します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/149921/1ce6e006-25da-9c27-436a-481088838f90.png)
参考情報 : [CSV テーブルの作成アクション](https://docs.microsoft.com/ja-jp/azure/logic-apps/logic-apps-perform-data-operations)

##HTTP で LINE にポストする
最後に設定した CSV を LINE にポストします。PUSH メッセージを送信するためには、URI を `https://api.line.me/v2/bot/message/push` に設定し、Header に `Authorization` と `Content-Type` を設定します。Message は JSON で設定しますが、LINE の公式ドキュメントには以下のような記載例があります。

```js

curl -v -X POST https://api.line.me/v2/bot/message/push \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer {channel access token}' \
-d '{
    "to": "U4af4980629...",
    "messages":[
        {
            "type":"text",
            "text":"Hello, world1"
        },
        {
            "type":"text",
            "text":"Hello, world2"
        }
    ]
}'
```
この例にならって、Logic App 側でも以下のような形で設定します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/149921/da460181-6dee-013d-4732-6446f591c9c7.png)

以上で設定が完了です。

#テスト
Timer トリガーで設定しましたが、Azure Portal から Trigger を実行しテストすることが出来ます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/149921/5ab8f72a-b64a-e31f-2b6f-38a161342b95.png)
トリガーが実行されると、以下のような LINE 通知が来ます。感染者の一覧と詳細情報を取得することができます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/149921/6b0717f1-4010-4a56-06cf-245f80fed505.png)
テキストベースでみるとこのような形です。

```
昨日までに報告されている長野県の新型コロナ感染情報をお届けします。以下APIソースの凡例 : 【患者識別番号】,情報詳細 
【長野県1】,2020/02/25に松本管内に住む60代男性の感染が報告されました。詳細情報:https://www.pref.nagano.lg.jp/hoken-shippei/happyou/20200225corona.html 
【長野県2】,2020/02/26に松本管内に住む50代女性の感染が報告されました。詳細情報:https://www.pref.nagano.lg.jp/hoken-shippei/happyou/press20200226corona.html 
【長野県3】,2020/03/06に佐久管内に住む50代女性の感染が報告されました。詳細情報:https://www.pref.nagano.lg.jp/hoken-shippei/happyou/press20200306corona3.html 
【長野県4】,2020/03/14に松本管内に住む20代女性の感染が報告されました。詳細情報:https://www.pref.nagano.lg.jp/hoken-shippei/happyou/documents/0314press.pdf 
【長野県5】,2020/03/24に松本管内に住む70代男性の感染が報告されました。詳細情報:https://www.pref.nagano.lg.jp/hoken-shippei/happyou/press20200324corona4.html 
【長野県6】,2020/03/27に県外（東京都）に住む20代男性の感染が報告されました。詳細情報:https://www.pref.nagano.lg.jp/hoken-shippei/happyou/200327press.html 
【長野県7】,2020/03/29に飯田管内に住む20代男性の感染が報告されました。詳細情報:https://www.pref.nagano.lg.jp/hoken-shippei/happyou/0329press.html 
【長野県8】,2020/03/29に松本管内に住む40代男性の感染が報告されました。詳細情報:https://www.pref.nagano.lg.jp/hoken-shippei/happyou/0329press.html 
【長野県9】,2020/04/03に大町管内に住む20代男性の感染が報告されました。詳細情報:https://www.pref.nagano.lg.jp/hoken-shippei/happyou/0403press2.html
```

作成時間は 1 時間くらいですが、身内が使える情報取得 LINE を簡単に作成することができました。API を作成頂いた方、ありがとうございました！