GASを使って天気予報botを作ってみよう！

#はじめに
###どんな記事？
高校一年生が送る、高校生でも作れるLINEbot講座
###こんなものを作ります
<img src="https://firebasestorage.googleapis.com/v0/b/picture-e5254.appspot.com/o/wc3e1-mulgq.gif?alt=media&token=09639388-6e98-4a46-b4da-af0397639686" width=50%>
郵便番号を送信したらその地域の天気予報をFlexMessageで返してくれるbotです！
###今回使うもの
・LINE Messaging API
・GAS(GoogleAppsScript)
・OpenWeatherMapAPI
#まずはLINEBotを作ってみよう！
①[こちらのページ](https://developers.line.me/console/register/messaging-api/provider/)にアクセスしてログインをしてください（メアドとパスワードはLINEのアプリで設定したものです）
②既にLINEbot作ったことがある方は既存のプロパイダーを、初めての人は新規プロパイダーを選択してプロパイダー名（テキトーに好きな名前）を入力し、プロパイダーの作成を完了させてください
③新規プロパイダーを制作した方はチャネル作成画面が出てくるので、Messaging APIを選択してください
④画像以外は必須項目なので、全て入力して「入力内容を確認する」を押してください
**※この際にDeveloper Trialプランを選択すると最大友だち数が50人になってしまいますのでご注意ください**
フリープランとDeveloper Trialプランの違いについては[こちらのページ](https://qiita.com/line_gamebook/items/2fc3f4319fc59a1e31d3)がとても分かりやすかったです
⑤確認画面が出てくるので、入力内容に間違いがなければ利用規約に同意するにチェックを入れて「作成」を押してください
⑥チャネル一覧が出てくるので、今作ったチャネルを選択してください
⑦下の方にスクロールすると「アクセストークン（ロングターム）」という項目が出てくるので、「再発行」を押してください（0時間でおｋ）
※出てきた文字列は後で使うので、コピペするなりしてどこかに保管しておいてください
#OpenWeatherMapの設定
①[こちらのページ](https://home.openweathermap.org/users/sign_up)にアクセスして、必要事項を入力し、アカウントを作成してください
②[こちらのページ](https://home.openweathermap.org/api_keys)にアクセスして、APIKeyをコピーしてください（APIKeyがない場合は発行してください）
#次はGASでプロジェクトを作ってみよう！
①[こちらのページ](https://www.google.com/script/start/)にアクセスして「Start Scripting」を押してください
②スクリプトの編集ページが出てくるので、左上の「無題のプロジェクト」を押し、好きな名前に変更してください
③書いてあるコードを全部消して、以下のコードをコピペしてください
https://github.com/shinbunbun/Weather-bot/blob/master/%E3%82%B3%E3%83%BC%E3%83%89.js
④ペーストしたコードの1行目の「さっき発行したとーくん」をさっき発行したLINEのアクセストークンに、403行目の「さっき発行したえーぴーあいきー」をさっき発行したOpenWeatherMAPのAPIKeyに置き換えてください
④上の「公開」ボタンを押して、「ウェブアプリケーションとして導入」→「アプリケーションにアクセスできるユーザー」を「全員（匿名ユーザーを含む）」にして「導入」ボタンを押してください
⑤承認を求められることがあるので「許可を確認」を押して色々やって許可をしてください
④ウェブアプリケーションのURLが出てくるので、コピーして先ほどのLINEbotのページの「Webhook URL」というところにペーストしてください
⑤「webhook送信」を利用するにチェックを入れてください

**これで完成です！！郵便番号を送信したらFlexMessageで天気が返ってくるはずです！**
#コード解説
```js:doPost関数
function doPost(e) {
  const events = JSON.parse(e.postData.contents).events;
  events.forEach(function(event) {
    switch (event.type) {
      case "message":
        reply(event);
        break;
      //postbackイベントの時はここに入る
      /*case "postback" :
        postback(event);
        break;*/
    }
  });
}
```
GASではPOSTが飛んでくるとdoPost関数が呼ばれます。（ちなみにGETの場合はdoGetが呼ばれます）
doPost関数の中では、飛んできたJSONをパースしてeventオブジェクトを取り出し、イベントタイプごとに関数を振り分けるという処理をしています。

```js:reply関数(前半)
function reply(e) {
    var userMessage = e.message.text;
    var response = getWeather(userMessage);
    if (response != "error") {
        var country = response.city.country,
            cityName = response.city.name;
        var date = [],
            weather = [],
            icon = [],
            temperature = [];
        for (var i = 0; i <= 8; i++) {
            if (Number(response.list[i].dt_txt.slice(11, 13)) + 9 > 24) {
                date.push(Number(response.list[i].dt_txt.slice(11, 13)) + 9 - 24);
            }
            else {
                date.push(Number(response.list[i].dt_txt.slice(11, 13)) + 9);
            }
            weather.push(response.list[i].weather[0].main);
            icon.push(response.list[i].weather[0].icon);
            temperature.push((Math.round((Number(response.list[i].main.temp) - 273.15) * 10) / 10).toString() + '℃');
        }
```
reply関数の前半では、ユーザーから送られてきたメッセージ（郵便番号）を引数としてgetWeather関数を呼び出し、天気予報を取得しています。その地域の天気予報のJSONを取得し、getWeatherの戻り値がerrorじゃなかった場合は、必要なデータ（時間、天気、アイコンの画像、温度）を取り出しています。その後にデータごとに配列に格納しています。

```js:getWeather関数
function getWeather(e) {
    try {
        var apiKey = 'さっき発行したえーぴーあいきー';
        var url = 'http://api.openweathermap.org/data/2.5/forecast' + '?zip=' + e + ',jp&APPID=' + apiKey;
        var response = UrlFetchApp.fetch(url);
        return JSON.parse(response);
        Logger.log(response.list[0])
    } catch (e) {
        return "error";
    }
}
```
reply関数の後半の前にgetWeather関数の説明をします。
getWeather関数では、OpenWeatherMapAPIを叩いて天気予報を取得する処理をしています。
郵便番号とAPIKEYをパラメータにしてAPIを叩き、レスポンスがエラーの場合（メッセージが郵便番号でなかった場合）は、念のためエラー内容を出力してから、"error"という戻り値を返します。
※APIの利用制限に引っかかった場合などもエラーが返ってくるため、念のためエラー内容を出力しておく。
~~存在する郵便番号かどうかを判別する処理を間に入れればこんなめんどくさいことしなくて済むのに~~

```js:reply関数(後半)
        var message = {
            "replyToken": e.replyToken,
            "messages": [{
                "type": "flex",
                "altText": '天気予報',
                "contents": {
                    "type": "bubble",
                    "styles": {
                        "footer": {
                            "separator": true
                        }
                    },
                    "body": {
                        "type": "box",
                        "layout": "vertical",
                        "contents": [
                            {
                                "type": "text",
                                "text": "天気予報",
                                "weight": "bold",
                                "size": "xxl",
                                "margin": "md"
                            },
                            {
                                "type": "text",
                                "text": country + '.' + cityName,
                                "size": "md",
                                "color": "#aaaaaa",
                                "wrap": true
                            },
                            {
                                "type": "separator",
                                "margin": "xxl"
                            },
                            {
                                "type": "box",
                                "layout": "vertical",
                                "margin": "xxl",
                                "spacing": "sm",
                                "contents": [
                                    {
                                        "type": "box",
                                        "layout": "baseline",
                                        "contents": [
                                            {
                                                "type": "text",
                                                "text": date[0] + ":00",
                                                "size": "sm",
                                                "color": "#555555",
                                                "flex": 0
                                            },
                                            {
                                                "type": "text",
                                                "text": weather[0],
                                                "size": "sm",
                                                "color": "#111111",
                                                "align": "end"
                                            },
                                            {
                                                "type": "icon",
                                                "url": "https://openweathermap.org/img/w/" + icon[0] + ".png",
                                                "size": "xl"
                                            },
                                            {
                                                "type": "text",
                                                "text": temperature[0],
                                                "size": "sm",
                                                "color": "#111111",
                                                "align": "end"
                                            }
                                        ]
                                    },
                                    {
                                        "type": "box",
                                        "layout": "baseline",
                                        "contents": [
                                            {
                                                "type": "text",
                                                "text": date[1] + ":00",
                                                "size": "sm",
                                                "color": "#555555",
                                                "flex": 0
                                            },
                                            {
                                                "type": "text",
                                                "text": weather[1],
                                                "size": "sm",
                                                "color": "#111111",
                                                "align": "end"
                                            },
                                            {
                                                "type": "icon",
                                                "url": "https://openweathermap.org/img/w/" + icon[1] + ".png",
                                                "size": "xl"
                                            },
                                            {
                                                "type": "text",
                                                "text": temperature[1],
                                                "size": "sm",
                                                "color": "#111111",
                                                "align": "end"
                                            }
                                        ]
                                    },
                                    {
                                        "type": "box",
                                        "layout": "baseline",
                                        "contents": [
                                            {
                                                "type": "text",
                                                "text": date[2] + ":00",
                                                "size": "sm",
                                                "color": "#555555",
                                                "flex": 0
                                            },
                                            {
                                                "type": "text",
                                                "text": weather[2],
                                                "size": "sm",
                                                "color": "#111111",
                                                "align": "end"
                                            },
                                            {
                                                "type": "icon",
                                                "url": "https://openweathermap.org/img/w/" + icon[2] + ".png",
                                                "size": "xl"
                                            },
                                            {
                                                "type": "text",
                                                "text": temperature[2],
                                                "size": "sm",
                                                "color": "#111111",
                                                "align": "end"
                                            }
                                        ]
                                    },
                                    {
                                        "type": "box",
                                        "layout": "baseline",
                                        "contents": [
                                            {
                                                "type": "text",
                                                "text": date[3] + ":00",
                                                "size": "sm",
                                                "color": "#555555",
                                                "flex": 0
                                            },
                                            {
                                                "type": "text",
                                                "text": weather[3],
                                                "size": "sm",
                                                "color": "#111111",
                                                "align": "end"
                                            },
                                            {
                                                "type": "icon",
                                                "url": "https://openweathermap.org/img/w/" + icon[3] + ".png",
                                                "size": "xl"
                                            },
                                            {
                                                "type": "text",
                                                "text": temperature[3],
                                                "size": "sm",
                                                "color": "#111111",
                                                "align": "end"
                                            }
                                        ]
                                    },
                                    {
                                        "type": "box",
                                        "layout": "baseline",
                                        "contents": [
                                            {
                                                "type": "text",
                                                "text": date[4] + ":00",
                                                "size": "sm",
                                                "color": "#555555",
                                                "flex": 0
                                            },
                                            {
                                                "type": "text",
                                                "text": weather[4],
                                                "size": "sm",
                                                "color": "#111111",
                                                "align": "end"
                                            },
                                            {
                                                "type": "icon",
                                                "url": "https://openweathermap.org/img/w/" + icon[4] + ".png",
                                                "size": "xl"
                                            },
                                            {
                                                "type": "text",
                                                "text": temperature[4],
                                                "size": "sm",
                                                "color": "#111111",
                                                "align": "end"
                                            }
                                        ]
                                    },
                                    {
                                        "type": "box",
                                        "layout": "baseline",
                                        "contents": [
                                            {
                                                "type": "text",
                                                "text": date[5] + ":00",
                                                "size": "sm",
                                                "color": "#555555",
                                                "flex": 0
                                            },
                                            {
                                                "type": "text",
                                                "text": weather[5],
                                                "size": "sm",
                                                "color": "#111111",
                                                "align": "end"
                                            },
                                            {
                                                "type": "icon",
                                                "url": "https://openweathermap.org/img/w/" + icon[5] + ".png",
                                                "size": "xl"
                                            },
                                            {
                                                "type": "text",
                                                "text": temperature[5],
                                                "size": "sm",
                                                "color": "#111111",
                                                "align": "end"
                                            }
                                        ]
                                    },
                                    {
                                        "type": "box",
                                        "layout": "baseline",
                                        "contents": [
                                            {
                                                "type": "text",
                                                "text": date[6] + ":00",
                                                "size": "sm",
                                                "color": "#555555",
                                                "flex": 0
                                            },
                                            {
                                                "type": "text",
                                                "text": weather[6],
                                                "size": "sm",
                                                "color": "#111111",
                                                "align": "end"
                                            },
                                            {
                                                "type": "icon",
                                                "url": "https://openweathermap.org/img/w/" + icon[6] + ".png",
                                                "size": "xl"
                                            },
                                            {
                                                "type": "text",
                                                "text": temperature[6],
                                                "size": "sm",
                                                "color": "#111111",
                                                "align": "end"
                                            }
                                        ]
                                    },
                                    {
                                        "type": "box",
                                        "layout": "baseline",
                                        "contents": [
                                            {
                                                "type": "text",
                                                "text": date[7] + ":00",
                                                "size": "sm",
                                                "color": "#555555",
                                                "flex": 0
                                            },
                                            {
                                                "type": "text",
                                                "text": weather[7],
                                                "size": "sm",
                                                "color": "#111111",
                                                "align": "end"
                                            },
                                            {
                                                "type": "icon",
                                                "url": "https://openweathermap.org/img/w/" + icon[7] + ".png",
                                                "size": "xl"
                                            },
                                            {
                                                "type": "text",
                                                "text": temperature[7],
                                                "size": "sm",
                                                "color": "#111111",
                                                "align": "end"
                                            }
                                        ]
                                    },
                                    {
                                        "type": "box",
                                        "layout": "baseline",
                                        "contents": [
                                            {
                                                "type": "text",
                                                "text": date[8] + ":00",
                                                "size": "sm",
                                                "color": "#555555",
                                                "flex": 0
                                            },
                                            {
                                                "type": "text",
                                                "text": weather[8],
                                                "size": "sm",
                                                "color": "#111111",
                                                "align": "end"
                                            },
                                            {
                                                "type": "icon",
                                                "url": "https://openweathermap.org/img/w/" + icon[8] + ".png",
                                                "size": "xl"
                                            },
                                            {
                                                "type": "text",
                                                "text": temperature[8],
                                                "size": "sm",
                                                "color": "#111111",
                                                "align": "end"
                                            }
                                        ]
                                    }
                                ]
                            },
                            {
                                "type": "separator",
                                "margin": "xxl"
                            }
                        ]
                    }
                }
            }]
        };
    } else {
        var message = {
            "replyToken": e.replyToken,
            "messages": [{
                "type": "text",
                "text": "その郵便番号は存在しておりません"
            }]
        };
    }
    var replyData = {
        "method": "post",
        "headers": {
            "Content-Type": "application/json",
            "Authorization": "Bearer " + access_token
        },
        "payload": JSON.stringify(message)
    };
    try {
        UrlFetchApp.fetch("https://api.line.me/v2/bot/message/reply", replyData);
    } catch (e) {

    }
}
```
reply関数の後半では、まずgetWeatherの戻り値が"error"でなかった場合に送信するFlexMessageを作っています。詳しくは[こちらのリファレンス](https://developers.line.biz/ja/reference/messaging-api/#flex-message)を参照。
その次にgetWeatherの戻り値が"error"だった場合（郵便番号が存在しなかった場合）に送信するメッセージを作っています。
最後に出来上がったメッセージをLINEのサーバにPOSTで飛ばして終了です！
#宣伝
###時間割bot
僕が作っている学生向けのサービス。利用者数は680人(2018/11/29現在)。
<a href="https://line.me/R/ti/p/%40ywg0561x"><img height="36" border="0" alt="友だち追加" src="https://scdn.line-apps.com/n/line_add_friends/btn/ja.png"></a>
<blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">当日や翌日の時間割を教えてくれる時間割botを作りました！<br>小学生から大学生まで幅広く使えると思うので、学生の方は是非使ってみてください！！<br>以下のリンクからアカウントを追加できます<a href="https://t.co/xj3yE4mhVg">https://t.co/xj3yE4mhVg</a><a href="https://twitter.com/hashtag/linebootawards?src=hash&amp;ref_src=twsrc%5Etfw">#linebootawards</a> <a href="https://twitter.com/hashtag/LINE_API?src=hash&amp;ref_src=twsrc%5Etfw">#LINE_API</a> <a href="https://t.co/bTkLt96fg4">pic.twitter.com/bTkLt96fg4</a></p>&mdash; しんぶんぶん(ぶんぶん) (@unix_yuto) <a href="https://twitter.com/unix_yuto/status/1034478893795663873?ref_src=twsrc%5Etfw">2018年8月28日</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
##Twitter
https://twitter.com/shinbunbun_