すだちキャンパス

すだちキャンパス

やってみたこと、学んだことなどのメモ。

GAS (Google Apps Script) でLINE bot を作る時のまとめ

こんにちは。
GAS (Google Apps Script) でLINE bot を作ったので、その時に使ったコードのまとめです。

GASでLINE botを作る準備

まず、LINE Developers に登録します。
この辺の登録の仕方はこちら↓の記事が分かりやすかったです。
qiita.com
無事に登録できて、新規チャネル作成からbotを作成したら、
チャネル基本設定 > メッセージ送受信設定 から、アクセストークン(ロングターム)を取得してコピーします。

次に、GASに移ります。
先ほど取得したアクセストークン(ロングターム)を使うので、スクリプトに書いておきます。

var channel_access_token = "先ほど取得したアクセストークン";

そしたら
公開 > ウェブ アプリケーションとして導入
を押します。導入が完了すると次のような画面が出るので、このURLをコピーしておきます。
f:id:sweetgohan:20181107145658p:plain
最後に、再びLINE Developers に戻って
チャネル基本設定 > メッセージ送受信設定 > Webhook送信
を「利用する」に変更します。
そして、その下にあるWebhook URL に先ほどGAS でコピーしたURL を貼り付けます。

ここまでできたら準備完了です。

LINEとやりとりするスクリプトの基本形

ここからは、LINEとの送受信のやり方を書いていきます。

var channel_access_token = "アクセストークン";
//メッセージが送られてきた時等の処理
function main(e) {
 var events = JSON.parse(e.postData.contents).events;
 //botに対して何かされた時の処理
 events.forEach(function(event) {
  //botに対して何か送られてきた時の処理
  if(event.type == "message") { 
   //受け取った文章によって反応を変更
  switch (true) {
      (event.message.text).match(/ねこ/):
        CatMessage(event);
        break
      default:
        QuestionMessage(event);
        break
  }
  //botが送信したメッセージのボタンなどを押した時の処理
  if("postback" in event){
   //ここに関数などを書く
  }
 }
}

基本的に、この関数が中心となって動きます。
ここでは、例として、CatMessage(event) などの関数を作っていてそれで返信などの行動を行う、という想定で書いています。
それでは、実際にメッセージを送信する関数を書いてみましょう。

LINEの返信

登録された返事をする関数は、次のように書けます。

function CatMessage(e) {
  var CatMessage = {
    "replyToken" : e.replyToken,
    "messages" : [
      {
        "type" : "text",
        "text" : "にゃー" //これが返信されるテキスト
      }
    ]
  };
  var CatMessageData = {
    "method" : "post",
    "headers" : {
      "Content-Type" : "application/json",
      "Authorization" : "Bearer " + channel_access_token
    },
    "payload" : JSON.stringify(CatMessage)
  };
    UrlFetchApp.fetch("https://api.line.me/v2/bot/message/reply", CatMessageData);
}

例えば、あらかじめスプレッドシートに様々な語句を登録しておいて、その文字列をランダムに呼び出す・・・などの処理を加えたら返事の幅は広がると思います。
前回の記事で (こちらはTwitterですが)、似たようなことをしているので参考にしてください。
kabos.hatenablog.jp

LINEの送信(push通知)

push通知は、botに対してメッセージが送信された時ではなく、bot自身からメッセージを送信する時に使います。
これは簡単で、先ほどの関数に送信先を付け加えるだけです。

function pushMessage(e){
  var pushMessage = {
          "to" : "userID",
          "messages" : [
            {
              "type" : "text",
              "text" : "こんにちは。"
            }
          ]
        };
  var pushMessageData = {
          "method" : "post",
          "headers" : {
          "Content-Type" : "application/json",
          "Authorization" : "Bearer " + channel_access_token
          },
          "payload" : JSON.stringify(pushMessage)
        };
  UrlFetchApp.fetch("https://api.line.me/v2/bot/message/push", pushMessageData);
}

ここで出てきた"userId"は、それぞれのLINEのアカウントに割り当てられているIDで、個人で設定したLINEのIDなどとは異なります。
これを取得する方法は、次の項で説明します。

ユーザー情報の取得

userId は、最初に書いたmain関数の中の、 events.forEach(function(event) {}の中で次のように書くことで取得できます。

var userID = event.source.userId;

これは、Webhookイベントオブジェクトにsourceが含まれていて、sourceの中にuserIdが入っているということのようです。
公式のリファレンスに、どこに何が入っているのか書いてあります。↓
Messaging APIリファレンス | LINE Developers
userIdが取得できると、ユーザーのプロフィールが取得できます。
プロフィールの中に表示名などが入っているので、名前で呼びかけることなどができます。
具体的には、次のような関数を書きます。

//表示名を取得する関数
function getUserName(userID) {
  var url = "https://api.line.me/v2/bot/profile/" + userID;
  var response = UrlFetchApp.fetch(url, {
              "headers" : {
              "Authorization" : "Bearer " + channel_access_token
              }
  });
  return JSON.parse(response.getContentText()).displayName;
}
//アイコン画像を取得する関数
function getUserPicture(userID) {
  var url = "https://api.line.me/v2/bot/profile/" + userID;
  var response = UrlFetchApp.fetch(url, {
              "headers" : {
              "Authorization" : "Bearer " + channel_access_token
              }
  });
  return JSON.parse(response.getContentText()).pictureUrl;
}

ちなみに、userIdは取得したらスプレッドシートなどに書き込むとみることができます。これを取得することでプッシュメッセージが送れます。
(他の関数の中でも、eventを引き継いでいるのだから「var userID = e.source.userId;」と書いたら取得できるのでは・・・と思ってやってみたのですが何故かできませんでした。理由がわかる方がいらっしゃいましたらコメントなどで教えていただけるとありがたいです。)

送信できる色々なメッセージ(Flex Message)

LINEでは、色々な形のメッセージを送ることができます。
りんなや広告などでみるやつですね。(ピンとこない方は、こちらのリンクから用意されているサンプルをご覧ください)
ここでは2つ例を紹介します。

Yes/No ボタン

2つのボタンがあって、ボタンを押すと反応したりリンクに飛んだりするものです。

function QuestionMessage(e) {
  var QuestionMessage =  {
  "type": "template",
  "altText": "this is a confirm template",
  "template": {
      "type": "confirm",
      "text": "私と話しますか?",
      "actions": [
          {
            "type":"postback", //「押した」というイベントを取得できる
            "label":"Yes",
            "data":"action=yes",
            "text":"お話ししたい" //押された時にこちらから送信されるメッセージ
          },
          {
            "type": "message", //メッセージが送られるだけ
            "label": "No",
            "text": "嫌だ"
          }
      ]
  }
}

  var QuestionMessageData = {
      "replyToken" : e.replyToken,
      "messages" : [QuestionMessage]
    }
    var Qoptions = {
      "method" : "post",
      "headers" : {
        "Content-Type" : "application/json",
        "Authorization" : "Bearer " + channel_access_token
      },
      "payload" : JSON.stringify(QuestionMessageData)
    };
    UrlFetchApp.fetch("https://api.line.me/v2/bot/message/reply", Qoptions);
}

ここで、Yes を押した時に何か反応させたければ、最初のmain関数内に次のように付け加えます。

if("postback" in event){
   //ここに関数などを書く(ここから付け足し)
   if(event.postback.data == "action=yes"){
    HappyMessage(event); //返事をする関数など
   }
}
カラム

カラムは、横並びにいくつか表示できるメッセージです。投票する時などに便利です。

function Vote(e){
  var vote =  {
        "type": "template",
        "template": {
          "type" : "carousel",
          "columns": [
            {
              "thumbnailImageUrl": "画像リンク",
              "title": "Title欄(40文字まで)",
              "text": "text欄(60文字まで)",
              "actions": [{"type": "postback",
                          "label": "にゃんこ",
                          "data": "CatData",
                          "text": "投票しました。"}]
            },
            {
              "thumbnailImageUrl": "画像リンク",
              "title": "Title欄(40文字まで)",
              "text": "text欄(60文字まで)",
              "actions": [{"type": "postback",
                          "label": "わんこ",
                          "data": "DogData",
                          "text": "投票しました"}]
            }
          ]
        },
        "altText": "代替テキスト"
      }
  var voteData = {
      "replyToken" : e.replyToken,
      "messages" : [vote]
    }
  var voteOptions = {
      "method" : "post",
      "headers" : {
        "Content-Type" : "application/json",
        "Authorization" : "Bearer " + channel_access_token
      },
      "payload" : JSON.stringify(voteData)
    };
    UrlFetchApp.fetch("https://api.line.me/v2/bot/message/reply", voteOptions);    
}

まとめ

基本的に、データの送受信は、そのために必要なデータ(メッセージの内容など)を指定された形式 (LINEのAPI リファレンスに書いてある)で書いて、HTTPリクエストのURLを実行したら良いみたいです。
なんか当たり前のことを書いているように思えますが、その形式の書き方などがわからないとせっかくリファレンスに書いてあっても使えないんですよね・・・。
今回は、「こうしたらこう動く!」ということを羅列しましたが、もう少し詳しい仕組みを理解することができたら、また記事にするかもしれません。