【自分専用ボット】LINEBOTのUI改造で使い勝手アップ大作戦!(3/3)

「クイックリプライ」で時間を簡単選択

ウサギ先輩
時間の入力には、「クイックリプライ」機能を使おう。
LINEボット側からクイックリプライボタンを含んだメッセージで応答すると、トーク画面の下部にボタンが表示できるんだ。

そのクリックリプライボタンとして直近の時間、「09:00」「09:15」「09:30」といったの時間選択ボタンを表示すれば、簡単に時間をボタンで選択することが可能だよね!

わん太郎
へぇ!選択肢となるボタンを動的に作ることが可能というわけですね!


ウサギ先輩
さらにクイックリプライボタンに「時刻選択ダイアログ」を呼び出すアクションを設定することもできる。
選択肢以外の時間を入力したい場合は、時刻選択ダイアログを呼び出して使えばどの時間入力にも対応できるぞ。

わん太郎
なるほどなるほど!
「LINEボット側からクイックリプライボタンを含んだメッセージで応答」ってどんな応答メッセージなんですか?

ウサギ先輩
JSON形式のデータを返却するんだよ。こんな感じ。
{
  "type": "text",
  "text": "下のボタンより、開始時間を選択してください。",
  "quickReply": {
    "items": [
      {
        "type": "action",
        "action": {
          "type": "postback",
          "label": "09:00",
          "displayText": "09:00",
          "data": "開始,09:00"
        },
        {
          "type": "action",
          "action": {
          "type": "postback",
          "label": "09:15",
          "displayText": "09:15",
          "data": "開始,09:15"
        },
          :
      ]
    }
  }

わん太郎
「quickReply」の部分がクイックリプライボタンになるのか。
ちょっとJSONデータの構造が複雑だけど・・・真似すれば何とかなりますよね?

ウサギ先輩
そうだね!
では、GASのソースを見てみよう。


/*
 POSTリクエスト受信
  request:受信リクエスト
*/
function doPost(request) {
  //POSTリクエストをJSONデータにパース
  var receiveJSON = JSON.parse(request.postData.contents);
  
  for (var i = 0; i < receiveJSON.events.length; i++){
    var event =  receiveJSON.events[i];
    //応答トークン取得
    var replyToken = event.replyToken;
    
    //メッセージ受信の場合
    if (event.type == "message"){
      //テキストメッセージの場合
      if (event.message.type == "text"){
        //テキストメッセージ取得
        var msg = event.message.text;
        //リッチメニューからのメッセージ送信は"開始"か"終了"
        if (msg == "開始" || msg == "終了"){
          //クイックリプライメッセージの生成
          var quickReplyMsg = createQuickReplyMsg(msg);
          //LINEの応答
          replyMessage(replyToken, quickReplyMsg);
        }
      }
    }
    
    //クイックリプライからのポストバックの場合
    if (event.type == "postback"){
      //ポストバックされたデータを取得
      var data = event.postback.data;
      //カンマ区切りで配列に分解
      var dataAry = data.split(",");
      
      var actType = dataAry[0];  //"開始"または"終了"
      var actTime = dataAry[1];  //何時何分
      
      //時刻選択ダイアログからの時刻選択の場合
      if (actTime == "時刻選択"){
        //選択された時刻を取得
        actTime = event.postback.params.time;
      }
      
      //メール送信【テレワーク開始・終了】
      sendMail_telework(actType, actTime);
      
      //LINEの応答
      var msg = [{"type": "text",
                  "text": "メール送信:" + actType + actTime}];
      replyMessage(replyToken, msg);
    }
  }
}
/*
 メール送信【テレワーク開始・終了】
  actType:"開始"または"終了"
  actTime:何時何分
*/
function sendMail_telework(actType, actTime) {
  
  var sheetAddress = SpreadsheetApp.getActive().getSheetByName("宛先");
  var sheetTemplate = SpreadsheetApp.getActive().getSheetByName("定型文");
  
  //【宛先】
  //宛先シートからA1セルの値を取得
  var toAddress = sheetAddress.getRange("A1").getValue();
  
  //【メール本文】
  var body = "";
  //定型文シートのすべてのセルデータを取得
  var values = sheetTemplate.getDataRange().getValues();
  for (var i = 0; i < values.length; i++){
    if (body != ""){
      body += "\n";
    }
    body += values[i][0];
  }
  //"{TIME}"キーワードを置換
  body = body.replace("{TIME}", actTime);
  //"{ACTION}"キーワードを置換
  body = body.replace("{ACTION}", actType);
  
  //件名
  var subject = "テレワーク" + actType;
  //オプション
  var option = {name: "わん太郎"};    //送信者名
 
  //Gmail送信
  MailApp.sendEmail(toAddress,subject,body,option);
}
/*
 クイックリプライメッセージの生成
  actType:"開始"または"終了"
*/
function createQuickReplyMsg(actType){
  // 現在時刻を15分単位で取得
  var dt_now = new Date();
  dt_now.setMinutes(dt_now.getMinutes() - (dt_now.getMinutes() % 15) );
  // 15分前の時刻を取得
  var dt_before15 = new Date();
  dt_before15.setMinutes(dt_now.getMinutes() - 15);
  // 15分後の時刻を取得
  var dt_after15 = new Date();
  dt_after15.setMinutes(dt_now.getMinutes() + 15);
    
  var msg = [
    {
      "type": "text",
      "text": "下のボタンより、" + actType + "時間を選択してください。",
      "quickReply": {
        "items": [
          {
            "type": "action",
            "action": {
              "type": "postback",
              "label": Utilities.formatDate(dt_before15, 'Asia/Tokyo', 'HH:mm'),
              "displayText": Utilities.formatDate(dt_before15, 'Asia/Tokyo', 'HH:mm'),
              "data": actType + "," + Utilities.formatDate(dt_before15, 'Asia/Tokyo', 'HH:mm')
            }
          },
          {
            "type": "action",
            "action": {
              "type": "postback",
              "label": Utilities.formatDate(dt_now, 'Asia/Tokyo', 'HH:mm'),
              "displayText": Utilities.formatDate(dt_now, 'Asia/Tokyo', 'HH:mm'),
              "data": actType + "," + Utilities.formatDate(dt_now, 'Asia/Tokyo', 'HH:mm')
            }
          },
          {
            "type": "action",
            "action": {
              "type": "postback",
              "label": Utilities.formatDate(dt_after15, 'Asia/Tokyo', 'HH:mm'),
              "displayText": Utilities.formatDate(dt_after15, 'Asia/Tokyo', 'HH:mm'),
              "data": actType + "," + Utilities.formatDate(dt_after15, 'Asia/Tokyo', 'HH:mm')
            }
          },
          {
            "type": "action",
            "action": {
              "type": "datetimepicker",
              "label": "時刻選択",
              "mode": "time",
              "data": actType + "," + "時刻選択"
            }
          }
        ]
      }
    }
  ];

  return msg;
}
/*
 LINEの応答
  replyToken:応答トークン
  messages:応答メッセージ
*/
function replyMessage(replyToken, messages){
  var replyURL = "https://api.line.me/v2/bot/message/reply";
  var ACCESS_TOKEN = "xxxxxxxxxxxxxxxxxxxx";
  UrlFetchApp.fetch(replyURL, {
    "headers": {
      "Content-Type": "application/json",
      "Authorization": "Bearer " + ACCESS_TOKEN
    },
    "method": "post",
    "payload": JSON.stringify({
      "replyToken": replyToken,
      "messages": messages
    }),
  });
}
【GAS】クイックリプライ対応版
【ポイント解説】
GASソースの改造ポイントを解説しよう。
[114〜121行目]
{
  "type": "action",
  "action": {
    "type": "postback",
    "label": "09:00",
    "displayText": "09:00",
    "data": "開始,09:00"
  }
}
"postback"タイプのアクションメッセージは、「ポストバック(ボタン操作による応答)アクション」のクイックリプライボタンを表示するぞ。
ボタンをタップすると、dataプロパティに指定された文字列が通知される仕組みだ。
dataプロパティに「開始,09:00」とカンマ区切りで指定しておけば、『開始か終了か』と『選択肢の時刻』が通知できる。
[141〜149行目]
{
  "type": "action",
  "action": {
    "type": "datetimepicker",
    "label": "時刻選択",
    "mode": "time",
    "data": "開始,時刻選択"
  }
}
"datetimepicker"タイプのアクションメッセージは、「日時選択アクション」のクイックリプライボタンを表示するぞ。
ボタンをタップすると、日時選択ダイアログが表示される。
modeプロパティを"time"と指定すれば、時刻のみを選択するダイアログになる。
dataプロパティに「開始,時刻選択」とカンマ区切りで指定しておけば、『開始か終了か』と『時刻選択』(時刻選択ダイアログから選択したことを判別)というメッセージが通知できる。
[163〜175行目]
var replyURL = "https://api.line.me/v2/bot/message/reply";
var ACCESS_TOKEN = "xxxxxxxxxxxxxxxxxxxx";
UrlFetchApp.fetch(replyURL, {
  "headers": {
    "Content-Type": "application/json",
    "Authorization": "Bearer " + ACCESS_TOKEN
  },
  "method": "post",
  "payload": JSON.stringify({
    "replyToken": replyToken,
    "messages": messages
  }),
});
JSON形式の応答メッセージは「https://api.line.me/v2/bot/message/reply」のアドレスに送信する決まりだ。
ヘッダ情報の"Authorization"には、Messaging APIのチャネル基本設定から取得できる「アクセストークン」を指定して認証しよう。
ペイロード情報(データ部分)の"replyToken"には、受信リクエストのevent.replyTokenを指定することで、応答するトークンを特定させる。

ウサギ先輩
さぁ、完成だ!
「リッチメニュー」を押した後に、「クイックリプライボタン」で時間入力できるようになっているぞ。

わん太郎
よし!!
「テレワーク開始」ボタンをポチッと。
・・・おお、時間選択ボタンが!
「テレワーク終了」ボタンをポチッと。
・・・次は「時刻選択」ボタンを押してみよう。
はは!これが時刻選択ダイアログか。こりゃいいや!

ウサギ先輩
どうだい?思い通りのUIに近づいたかい?


わん太郎
はい!これですよ、ほしかったのは!!
数回のタップで入力できる。求めていた完璧のユーザーインタフェースですよ!
LINEBOTって面白いなぁ。僕ももっと研究してみます!

ウサギ先輩
それはよかった。期待しているよ!



1
2
3

あなたへのおすすめ記事