LINE Botでアレルギー児とその家族を支えたい〜プログラミング初心者の小児科医が開発してみた

# はじめに

私はアレルギー疾患を専門とする小児科医です:smiley:

食物アレルギーのお子さんは原因食品を食べてしばらくすると、皮膚が赤くてかゆくなったり、咳やはながでてゼーゼーとしたり、吐いたり下痢をしたりします。これらの症状が同時に出て急速に症状が重くなる状態を「アナフィラキシー」といいます。この状態になると時に生命の危機に至ることもあるのです:disappointed_relieved:
この状態を解決するために、アレルギーやアナフィラキシーをお持ちの方は自宅にお薬を常備しています。しかし、これらを本人や家族が適切なタイミングで使うのはハードルが高いです。

そこで、プログラミング初心者の私が、この悩みを解決するLINEBotを作ってみました:relieved:
# 実際はこんな感じ

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2919962/8d64b2ee-4f3c-3267-dd34-69f589f42fdc.jpeg"width=70%>

こちらのQRコードから友達追加することで、実際に動かすことができます:grinning:

![食物アレルギー対応LINE（公開版）QR.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2919962/70ca95af-4dc3-6cae-25c6-1196d2a4b7c3.png)

スマホ経由で友達追加するには[こちらからどうぞ](https://liff.line.me/1645278921-kWRPP32q/?accountId=803stjbt) :point_left_tone2:


# システム構成はこんな感じ
## リッチメニュー
リッチメニューのデザインは、[Canva](https://www.canva.com/)で作成しました。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2919962/1931e27d-fae2-2cc1-150c-d52f4c521fe3.png"width=80%>


## 「アナフィラキシー・アレルギー対応」

GoogleAppsScriptにコードを書き、LINEと繋ぎました。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2919962/6617218f-7ac1-8c2a-c344-1aa6853bddf0.png"width=110%>

#### アレルギー対応に関する著作権について

このシステムのアレルギー対応は、[ぜんそく予防のために食物アレルギーを正しく知ろう](https://www.erca.go.jp/yobou/pamphlet/form/00/pdf/archives_31421.pdf)を元に作成しています。これを作られている環境再生保全機構は、出典元を記載することで使用が可能となっていますが、ご自身で独自に作成される時には[環境再生保全機構のお問合せ](https://www.erca.go.jp/erca/mail/index.php?conf=copy)へ連絡をなさるとよろしいかと思います。


## 「エピペン使用方法」

[Canva](https://www.canva.com/)で動画を作成して、iPhoneのボイスメモを使って録音した音声とあわせました。それを[YouTube](https://youtu.be/ZazVD73tvvQ)へアップし（限定公開）、リッチメニューにリンクとして貼りました。動画は私の音声なので、少し恥ずかしいですがよろしければご視聴ください:sweat_smile:

## 「使い方・お問合せ」

GoogleFormsでフォームを作成して、リッチメニューにリンクとして貼りました。このフォームとひもづけたGoogleAppsScriptで、問合せいただいた方と管理人である私へメールが飛ぶようにしています。
参考：[【コピペでOK!】GASでGoogleフォーム回答者と管理者に異なる内容のメールを自動送信する方法](https://www.yukibnb.com/entry/gas_form_auto_email_to_submitter_and_admin)

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2919962/47d330fd-2bfe-17ef-9dbf-fb474924a975.png"width=110%>

# 「アナフィラキシー・アレルギー対応」を実装するには
## 概要と参考にしたもの
[GoogleAppsScriptを使ったLINEBot【オウム返しとじゃんけん】](https://kodyblog.com/gas-linebot/)をベースに作成しました。これは、特定のキーワードが選択されたら、次の質問が飛ぶ仕組みになっているので、アレルギー対応だけでなくフローチャートに従って、答えがでるようなシステム全体に応用できると思います:wink:

返ってくるのが文字だけでは味気ないと思い、[LINE Developers](https://developers.line.biz/ja/docs/messaging-api/message-types/)を参考にメッセージタイプを変更しました。それぞれの画像は[Canva](https://www.canva.com/)で作成し、[note](https://note.com/)にアップしURLを貼りました:slight_smile:


## 具体的な手順
① GoogleSpreadSheetを開き、拡張機能からAppsScriptを開いてください。
② AppScriptに以下の「アナフィラキシー・アレルギー対応のコード」を全てコピペしてください。
③ コードのCHANNEL_ACCESS_TOKENに、ご自身のチャンネルアクセストークンを貼りつけてください。
④ このコードは「アレルギー緊急対応を開始します。」などのキーワードを起点として、次の画像が表示される仕組みです。それぞれのキーワードをいれると表示されるのですが、あまりに面倒です:head_bandage:そこで、リッチメニューを作成して、タイプを「テキスト」にして、「アレルギー緊急対応を開始します。」をキーワードにすると良いと思います。リッチメニューの作成には、[LINE Botでリッチメニューを表示する](https://qiita.com/bow_arrow/items/32ac5d2b4c67bd0c1dc2)を参考にしてください。

## アナフィラキシー・アレルギー対応のコード

```diff_javascript
const CHANNEL_ACCESS_TOKEN = 'ここにご自身のチャンネルアクセストークンを貼りつけてください。';
const LINE_URL = 'https://api.line.me/v2/bot/message/reply';

function doPost(e){
  var json = JSON.parse(e.postData.contents);
  var reply_token=json.events[0].replyToken;
  if(typeof reply_token === 'underfined'){
    return;
  }
  
  var message = json.events[0].message.text;
  
  if(message ==='test'){
  var replyMsg = {
    "type": "confirm",
    "text": "Are you sure?",
    "actions": [
      {
        "type": "message",
        "label": "Yes",
        "text": "yes"
      },
      {
        "type": "message",
        "label": "No",
        "text": "no"
      }
    ]
}
  }
  if(message ==='アレルギー緊急対応を開始します。'){　
  var replyMsg = {
    "type": "buttons",
            "thumbnailImageUrl": "https://assets.st-note.com/img/1669907237141-gVT2Oj6DNI.jpg?width=800&dpr=2",
            "imageAspectRatio": "square",
            "imageSize": "cover",
            "imageBackgroundColor": "#feeed2",
            "text": " どちらかをお選びください↓",
            "actions": [
              {
                "type": "message",
                "label": "はい",
                "text": "エピペンが必要な状況です。"
              },
              {
                "type": "message",
                "label": "いいえ",
                "text": "消化器症状を確認します。"
              }
            ]
}
  }
  if(message ==='消化器症状を確認します。'){ 
  var replyMsg = {
    "type": "buttons",
            "thumbnailImageUrl": "https://assets.st-note.com/img/1669907282460-aNVsLibV7f.jpg?width=800&dpr=2",
            "imageAspectRatio": "square",
            "imageSize": "cover",
            "imageBackgroundColor": "#feeed2",
            "text": " どちらかをお選びください↓",
            "actions": [
              {
                "type": "message",
                "label": "はい",
                "text": "エピペンが必要な状況です。"
              },
              {
                "type": "message",
                "label": "いいえ",
                "text": "神経・循環器症状を確認します。"
              }
            ]
}
  }
  if(message ==='神経・循環器症状を確認します。'){  
  var replyMsg = {
    "type": "buttons",
            "thumbnailImageUrl": "https://assets.st-note.com/img/1669907302955-fY3jS7Ka3n.jpg?width=800&dpr=2",
            "imageAspectRatio": "square",
            "imageSize": "cover",
            "imageBackgroundColor": "#feeed2",
            "text": " どちらかをお選びください↓",
            "actions": [
              {
                "type": "message",
                "label": "はい",
                "text": "エピペンが必要な状況です。"
              },
              {
                "type": "message",
                "label": "いいえ",
                "text": "皮膚・粘膜症状を確認します。"
              }
            ]
}
  }
  if(message ==='皮膚・粘膜症状を確認します。'){ 
  var replyMsg = {
    "type": "buttons",
            "thumbnailImageUrl": "https://assets.st-note.com/img/1669946854887-X7ecFuvv1l.jpg?width=800&dpr=2",
            "imageAspectRatio": "square",
            "imageSize": "cover",
            "imageBackgroundColor": "#feeed2",
            "text": " どちらかをお選びください↓",
            "actions": [
              {
                "type": "message",
                "label": "はい",
                "text": "医療機関の受診が必要です。"
              },
              {
                "type": "message",
                "label": "いいえ",
                "text": "中等症の呼吸・消化器症状を確認します。"
              }
            ]
}
  }
  if(message ==='中等症の呼吸・消化器症状を確認します。'){  
  var replyMsg = {
    "type": "buttons",
            "thumbnailImageUrl": "https://assets.st-note.com/img/1669946885133-j94LpogHcb.jpg?width=800&dpr=2",
            "imageAspectRatio": "square",
            "imageSize": "cover",
            "imageBackgroundColor": "#feeed2",
            "text": " どちらかをお選びください↓",
            "actions": [
              {
                "type": "message",
                "label": "はい",
                "text": "医療機関の受診が必要です。"
              },
              {
                "type": "message",
                "label": "いいえ",
                "text": "軽症の皮膚・粘膜症状を確認します。"
              }
            ]
}
  }
  if(message ==='軽症の皮膚・粘膜症状を確認します。'){ 
  var replyMsg = {
    "type": "buttons",
            "thumbnailImageUrl": "https://assets.st-note.com/img/1669946916233-wxgRHHHrm9.jpg?width=800&dpr=2",
            "imageAspectRatio": "square",
            "imageSize": "cover",
            "imageBackgroundColor": "#feeed2",
            "text": " どちらかをお選びください↓",
            "actions": [
              {
                "type": "message",
                "label": "はい",
                "text": "自宅で1時間程度、症状の経過を観察してください。"
              },
              {
                "type": "message",
                "label": "いいえ",
                "text": "軽症の呼吸・消化器症状を確認します。"
              }
            ]
}
  }
  if(message ==='軽症の呼吸・消化器症状を確認します。'){ 
  var replyMsg = {
    "type": "buttons",
            "thumbnailImageUrl": "https://assets.st-note.com/img/1669946940705-oEe7VPIFR7.jpg?width=800&dpr=2",
            "imageAspectRatio": "square",
            "imageSize": "cover",
            "imageBackgroundColor": "#feeed2",
            "text": " どちらかをお選びください↓",
            "actions": [
              {
                "type": "message",
                "label": "はい",
                "text": "自宅で1時間程度、症状の経過を観察してください。"
              },
              {
                "type": "message",
                "label": "いいえ",
                "text": "いまのところ問題なさそうです。"
              }
            ]
}
  }
  if(message ==='エピペンが必要な状況です。'){ 
  var replyMsg = {
    "type": "buttons",
            "thumbnailImageUrl": "https://assets.st-note.com/img/1669955253566-hjjn9YPjO7.jpg?width=800&dpr=2",
            "imageAspectRatio": "square",
            "imageSize": "cover",
            "imageBackgroundColor": "#feeed2",
            "text": " うち方をご確認ください↓",
            "actions": [
              {
                "type": "uri",
                "label": "動画",
                "uri": "https://youtu.be/ZazVD73tvvQ"
              },
              {
                "type": "message",
                "label": "画像",
                "text": "スワイプしてご確認ください。"
              }
            ]
}
  }
  if(message ==='医療機関の受診が必要です。'){  
  var replyMsg = {
    "type": "buttons",
            "thumbnailImageUrl": "https://assets.st-note.com/img/1669892704373-DucI8WsRuo.jpg?width=800&dpr=2",
            "imageAspectRatio": "square",
            "imageSize": "cover",
            "imageBackgroundColor": "#feeed2",
            "text": " 今の症状は中等症です。",
            "actions": [
              {
                "type": "message",
                "label": "はじめから対応を確認",
                "text": "アレルギー緊急対応を開始します。"
              },
            ]
}
  }
  if(message ==='自宅で1時間程度、症状の経過を観察してください。'){  
  var replyMsg = {
    "type": "buttons",
            "thumbnailImageUrl": "https://assets.st-note.com/img/1669904238519-qv7i09PFa9.jpg?width=800&dpr=2",
            "imageAspectRatio": "square",
            "imageSize": "cover",
            "imageBackgroundColor": "#feeed2",
            "text": " 今の症状は軽症です。",
            "actions": [
              {
                "type": "message",
                "label": "はじめから対応を確認",
                "text": "アレルギー緊急対応を開始します。"
              },
            ]
}
  }
  if(message ==='いまのところ問題なさそうです。'){  
  var replyMsg = {
    "type": "buttons",
            "thumbnailImageUrl": "https://assets.st-note.com/img/1669904553219-ZH54r0AYp4.jpg?width=800&dpr=2",
            "imageAspectRatio": "square",
            "imageSize": "cover",
            "imageBackgroundColor": "#feeed2",
            "text": " 明らかなアレルギー症状はありません。",
            "actions": [
              {
                "type": "message",
                "label": "はじめから対応を確認",
                "text": "アレルギー緊急対応を開始します。"
              },
            ]
}
  }
  if(message ==='スワイプしてご確認ください。'){  
  var replyMsg = {
    "type":  "image_carousel",
            "columns": [
              //ステップ1
              {
                "imageUrl": "https://assets.st-note.com/img/1669957259652-BfQA0bAGWS.jpg?width=800&dpr=2",
                "action": {
                  "type": "uri",
                  "label": "動画",
                  "uri": "https://youtu.be/ZazVD73tvvQ"
                }
              },
              //ステップ2
              {
                "imageUrl": "https://assets.st-note.com/img/1669957283774-84niHxGVwZ.jpg?width=800&dpr=2",
                "action": {
                  "type": "uri",
                  "label": "動画",
                  "uri": "https://youtu.be/ZazVD73tvvQ"
                }
              },
              //ステップ3
              {
                "imageUrl": "https://assets.st-note.com/img/1669957311900-xTFkp7Z9GY.jpg?width=800&dpr=2",
                "action": {
                  "type": "uri",
                  "label": "動画",
                  "uri": "https://youtu.be/ZazVD73tvvQ"
                }
              },
              //ステップ4
              {
                "imageUrl": "https://assets.st-note.com/img/1669957333705-6AS4bpmcHw.jpg?width=800&dpr=2",
                "action": {
                  "type": "uri",
                  "label": "動画",
                  "uri": "https://youtu.be/ZazVD73tvvQ"
                }
              }
            ]
}
  }
  
  UrlFetchApp.fetch(LINE_URL, {
    'headers':{
      'Content-Type':'application/json; charset=UTF-8',
      'Authorization':'Bearer '+ CHANNEL_ACCESS_TOKEN,
    },
    'method':'post',
    'payload':JSON.stringify({
      'replyToken':reply_token,
      'messages':[{
       "type": "template",
       "altText": "this is a confirm template",
    　　"template":replyMsg,
      }],
    }),
  });

  return ContentService.createTextOutput(JSON.stringify({'content':'post ok'})).setMimeType(ContentService.MimeType.JSON);
}
```

## ここに注意！

この画像のリンクは、私のnoteにひもづけられていますので、何らかの不具合が生じた場合には表示されなくなるかもしれません。その際には、ご自身で何らかの画像を作成してアップしてそのURLを貼るか、テキストメッセージに変えると良いと思います:smiley:

ここで紹介しているコードはメインの機能のみになります。これだけでは、問合せフォームなどは実装されません。もし同じ様に作りたい方がいらっしゃれば、参考に貼ったサイトなどを元に作成してください！YouTube動画はリンクとして使用していただいても構いません（少し気恥ずかしいですが。笑）

# おわりに

このLINEBotを作るために、プログラミング初心者の小児科医がはじめて作成してみました！
初心者が作成しているので、もっと良い方法があるかもしれません:sweat:
アレルギーをもつ方の助けになれば幸いですし、それ以外にもフローチャートを用いて選択するようなシステムを作る時の参考になればうれしいです:grin: