LINE MessagingAPIをGASとで触ってみた


ふと何か新しいものを自作したく、気軽に遊べそうだったLINE MessageAPIに触れてみました。その際の手順とかいろいろ書いていきます。
n番煎じのネタなのとコードが汚いのは目を瞑っていただけると幸いです。

##1. LINE MessagingAPIの設定をする
[LineDevelopers](https://developers.line.biz/ja/)よりMessagingAPIの設定を行います。

#####1-1. サイト中段にあるプロダクトより、MessagingAPIを選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/678785/69c92929-3474-77b6-6ab7-4e90649ec31b.png)
バナーの「今すぐ始めよう」から更に遷移。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/678785/3db4097d-3935-e67e-8d8b-6e10c08767c3.png)

#####1-2. 各必須項目を入力し作成を行う。

**チャネルの種類**
MessagingAPIを選択選択します。

**プロバイダー**
実行する管理者を登録します。初回は作成の必要あり。
 
**チャネル名**
実際のBotの名前になります。

**チャネル説明**
なんでも大丈夫です。

**大業種**
**小業種**
**メールアドレス**
ご自身に合わせて選択、入力してください。

上記の必須項目の入力が完了したら、同意項目を確認し作成します。

#####1-3. Messaging API設定を行う。
タブ内の「Message API設定」を開きます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/678785/f9a669c2-03ff-7ed7-418a-f0f404a7b582.png)

最下部にある「チャネルアクセストークン」を発行します。
こちらのアクセストークンは次で使用しますのでメモ等で取っておいてください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/678785/87c76ba7-4e19-3859-92c2-95e643e21480.png)

応答メッセージの設定も無効にしておきましょう。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/678785/3fe3cd13-eba9-d75c-dcfe-a02bd9513e24.png)


##2. Gasでオウム返しのスクリプトをデプロイしてみる
#####2-1. GoogleDriveから新規スクリプトを作成する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/678785/11784f71-d8af-1682-081d-99a6f3c2dc50.png)

#####2-2. 以下のスクリプトを作成したGasシートに張り付け
貼り付けの前に2行目の ■■■■■■■■■■■■■を 1-3 でメモしておいた自身のアクセストークンに置換してください。

```js:オウム返し
// line token
const channel_token = "■■■■■■■■■■■■■";
// line api url
const url = "https://api.line.me/v2/bot/message/reply";

function doPost(e) {
  let json = e.postData.contents;
  let events = JSON.parse(json).events;
  let requestMessage = events[0].message.text;

  returnMessage(events[0],requestMessage);
}

function returnMessage(event,messageText){
  let message = {
    "replyToken" : event.replyToken,
    "messages" : [{"type": "text","text" : messageText}]
  };
      
  let options = {
    "method" : "post",
    "headers" : {
      "Content-Type" : "application/json",
      "Authorization" : "Bearer " + channel_token
    },
    "payload" : JSON.stringify(message)
   };
  UrlFetchApp.fetch(url, options);
}
```

#####2-3. デプロイする
ページ右上の「デプロイ」>「新しいデプロイ」を選択。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/678785/470eabc0-e603-2ddc-9a7b-c823d50f36e0.png)

歯車マークから「ウェブアプリ」を選択。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/678785/01df8c7c-6be3-fb89-59d5-b7c055c57769.png)

アクセスできるユーザーを「自分のみ」から「全員」に変更したらデプロイを押下します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/678785/017c63f2-f039-7038-9fdf-ed0e4854848a.png)

ウェブアプリのURLは次で使用しますのでメモ等で取っておいてください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/678785/78991db2-c73d-bab6-eeb6-7c03cb19811b.png)

※アクセス許可の確認が初回のみ出ます。

##3. MessagingAPIに戻る
#####3-1. Webhookを有効にする。
MessagingAPI設定にあるWebhook設定を編集します。
展開されたテキストエリアに先ほどメモに取っていたウェブアプリURLを入力します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/678785/6924667e-919e-e8ff-0c54-011179df85e3.png)

更新を押したら完了になります。

Webhook利用のチェックを入れるのを忘れずに。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/678785/a99a32be-51c8-42ba-1587-9f5d5d03357b.png)


##実際に動かしてみる
MessagingAPI設定に表示されているQRコードからLINE友達追加できます。
メッセージを送信してオウム返しで帰ってくれば成功になります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/678785/3b40515b-a5af-3644-25a2-c667f77fcaf6.png)



##ミニゲーム
折角なのでMessagingAPIとGASを使用して一方通行のヌメロンを作りました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/678785/6cf17e51-af5f-d4a9-a940-a32119918f72.png)

```js:main.gs
// line token
const channel_token = "■■■■■■■■■■■■■■";
// line api url
const url = "https://api.line.me/v2/bot/message/reply";
// cache
const cache = CacheService.getScriptCache();

function doPost(e) {
  let json = e.postData.contents;
  let events = JSON.parse(json).events;
  let returnText = "半角0でスタート\nqqで終了"
  let requestMessage = events[0].message.text;
  let status = cache.get("status");
  if(requestMessage == "qq"){
    returnText = endGame();
  }else if(status == 1){
    returnText = inputNumber(requestMessage);
  }else if(requestMessage == "0"){
    returnText = startGame();
  }
  returnMessage(events[0],returnText);
}

function returnMessage(event,messageText){
  let message = {
    "replyToken" : event.replyToken,
    "messages" : [{"type": "text","text" : messageText}]
  };
  let options = {
    "method" : "post",
    "headers" : {
      "Content-Type" : "application/json",
      "Authorization" : "Bearer " + channel_token
    },
    "payload" : JSON.stringify(message)
   };
  UrlFetchApp.fetch(url, options);
}
```
```js:service.gs
function startGame(){
  let returnText = "";
  let fir = Math.floor(Math.random()*10);
  let sec = Math.floor(Math.random()*10);
  let third = Math.floor(Math.random()*10);
  let num;

  while(sec == fir){
    sec = Math.floor(Math.random()*10);
  }
  while(third == sec || third == fir){
    third = Math.floor(Math.random()*10);
  }

  num = "" + fir + sec + third;
  cache.put("targetNum",num);
  cache.put("status",1);

  returnText = "3桁の数字をセットしました。\n3桁の数字を入力して当ててください。"
  return returnText;
}

function endGame(){
  cache.remove("status");
  return "終了します。";
}

function inputNumber(request){
  let targetNum = cache.get("targetNum");
  let returnText = "";
  let regex = new RegExp(/^[0-9]{3}$/);
 
  // 正規表現マッチ /^[0-9]{3}$/
  if(regex.test(request)){
    let hitCnt = 0;
    let blowCnt = 0;

    // ドンピシャ
    if(request == targetNum){
      returnText = "3Hit 0Blow！\n終了します。";
      cache.remove("status");
    }else{
      let requestArray = request.split('');
      let targetArray = targetNum.split('');

      // 重複チェック
      let duplicateArray = Array.from(new Set(requestArray));
      if(duplicateArray.length == requestArray.length){

        for(let i = 0; i < requestArray.length; i++){

          // hit数チェック -> hit箇所は h に置換
          if(requestArray[i] == targetArray[i]){
            hitCnt++;
            targetArray.splice([i],1,"h");
          }

          // blow数チェック
          if(targetArray.indexOf(requestArray[i]) != -1){
            blowCnt++;
          }
        }
        returnText = hitCnt + "Hit "+ blowCnt + "blow"; 
      }else{
        returnText = "入力に重複している数字があります。";
      }
    }
  }else{
    returnText = "3桁の半角数字を入力してください。";
  }
  return returnText;
}
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2348088/33527bd6-814e-e44d-1019-080b67f76674.png)
BotQR
読み込んでLINEを開くと実際に追加できます。

##所感
MessagingAPIは以前から知ってはいましたが、実際触ってみたところ頭の中で考えてることをお手軽に実現できるので面白かったです。
キャッシュとかで対話型のBot、スプシを連携させてDB代わりに使用したりなどもできそうで夢が広がリングです。

今回は一方通行のBotでしたが今度は対話型（対戦型）のBotも作ってみたいと思います。
おわり

#####追記（2021/12/07）
ミニゲームで遊んでた際に「2hit 1blow」と出るのが発覚。
2つ合ってるけど1つ位置が違うってなんじゃそりゃ。。
原因としてはService.gsのinputNumber中の処理がダメでした。
hitしたナンバーは「h」に置換するようにして解消してます。
```targetArray.splice([i],1);```
から
```targetArray.splice([i],1,"h");```

あと重複数字が入力された時のバリデーション追加しました。