質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

Q&A

解決済

1回答

2321閲覧

【初心者です】GASでのJSを用いたlinebot開発のpostbackアクションについて

komukazu212

総合スコア1

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

0グッド

0クリップ

投稿2020/12/07 09:15

前提・実現したいこと

初心者です
GASでJavascriptを用いてカップルの割り勘botを作っています。

発生している問題・エラーメッセージ

postbackを受け取った時と、messageを受け取った時の、条件分岐で、色々試行錯誤してみたのですが、postbackが受け取れていないみたいで、else if( events.type === 'postback')以下の処理が実行されません。
その直後に処理の確認のために入れていたSpreadsheetApp.getActiveSheet().getRange(1, 11).setValue("クリア");が実行できずにいます。

その前の行までの処理はうまくいっています。

該当のソースコード

JavaScript

1// LINE developersのメッセージ送受信設定に記載のアクセストークン 2const LINE_TOKEN = 'アクセストークン' 3const LINE_URL = 'https://api.line.me/v2/bot/message/reply'; 4 5//postリクエストを受取ったときに発火する関数を定義 6 7 function doPost(e) { 8 // 応答用Tokenを取得 9 const replyToken = JSON.parse(e.postData.contents).events[0].replyToken;//0 10 // メッセージを取得 11 12 const userMessage = JSON.parse(e.postData.contents).events[0].message.text;//0 13 const events = JSON.parse(e.postData.contents).events[0]//0 14 15 //*************************** 16 // スプレットシートからデータを抽出 17 // *************************** 18 // 1. 今開いている(紐付いている)スプレッドシートを定義 19 const sheet = SpreadsheetApp.getActiveSpreadsheet(); 20 // 2. ここでは、デフォルトの「シート1」の名前が書かれているシートを呼び出し 21 const listSheet = sheet.getSheetByName("シート1"); 22 // 3. 最終列の列番号を取得 23 const numColumn = listSheet.getLastColumn(); 24 // 4. 最終行の行番号を取得 25 const numRow = listSheet.getLastRow()-1; 26 // 5. 範囲を指定(上、左、右、下) 27 const topRange = listSheet.getRange(1, 1, 1, numColumn); // 一番上のオレンジ色の部分の範囲を指定 28 const dataRange = listSheet.getRange(2, 1, numRow, numColumn); // データの部分の範囲を指定 29 // 6. 値を取得 30 const topData = topRange.getValues(); // 一番上のオレンジ色の部分の範囲の値を取得 31 const data = dataRange.getValues(); // データの部分の範囲の値を取得 32 const dataNum = data.length +2; // 新しくデータを入れたいセルの列の番号を取得 33 34 //botに対して何か送られてきた時の処理 35if(events.type === "message") { 36 SpreadsheetApp.getActiveSheet().getRange(1, 10).setValue(userMessage); 37 38 //メッセージを改行ごとに分割 39 const all_msg = userMessage.split("\n"); 40 const msg_num = all_msg.length; 41 42 43 // *************************** 44 // スプレッドシートにデータを入力 45 // *************************** 46 //最初のA列は、入力した時間を入れる 47 const dataNow = Utilities.formatDate(new Date() , 'Asia/Tokyo', 'MM'); 48 SpreadsheetApp.getActiveSheet().getRange(dataNum, 1).setValue(dataNow); 49 // 最終列の番号まで、順番にスプレッドシートの左からデータを新しく入力 50 for (let i = 0; i < msg_num; i++) { SpreadsheetApp.getActiveSheet().getRange(dataNum, i+2).setValue(all_msg[i]);} 51 52 //各住人ごとに合計を計算し、スプレッドシートに反映 53 for (let i = 3; i<=5; i++) { 54 SpreadsheetApp.getActiveSheet().getRange(i, 7).setFormula('=SUMIF(B:B,F'+i+',D:D)')} 55 56 //彼氏の合計と、彼女の合計をそれぞれスプレッドシート上に記入した関数をもとに、定義 57 const sumMale =SpreadsheetApp.getActiveSheet().getRange(3,7).getValue(); 58 const sumFemale =SpreadsheetApp.getActiveSheet().getRange(4,7).getValue(); 59 60 //二人のそれぞれの合計をもとに、精算処理を行い、精算結果を示す文字列を定義 61 let deal1 =null; 62 let deal2 = null; 63 if (sumMale<=sumFemale){ 64 deal1 = SpreadsheetApp.getActiveSheet().getRange(4,10).getValue(); 65 deal2 = `彼氏が彼女に¥${deal1}払う` 66 } 67 else{ 68 deal1 = SpreadsheetApp.getActiveSheet().getRange(3,10).getValue(); 69 deal2 = `彼女が彼氏に¥${deal1}払う` 70 }; 71 // *************************** 72 // 返信用のメッセージの定義 73 // *************************** 74 let after_msg =null; 75 76 //「完了」と入力した時に、今までのデータをリセットする 77 if(all_msg[0] === "完了" ){ 78 after_msg = [{"type":"flex","altText":"This is a Flex Message", "contents":{"type":"bubble","body":{"type":"box","layout":"baseline","contents":[{"type":"text","text":"本当に精算完了しますか?","weight":"bold","size":"17px"}]},"footer":{"type":"box","layout":"vertical","spacing":"sm","contents":[{"type":"button","style":"link","height":"sm","action":{"type":"postback","label":"はい","data":"yes","displayText":"はい"}},{"type":"button","style":"link","height":"sm","action":{"type":"postback","label":"いいえ","data":"No","displayText":"いいえ"}},{"type":"spacer","size":"sm"}],"flex":0}}}] 79 80 } 81 //「キャンセル」と入力した時に、最終行のデータを消し、消したアイテムをメッセージで伝える 82 83 else if(all_msg[0] === "キャンセル"){ 84 const missitem =SpreadsheetApp.getActiveSheet().getRange(numRow+1,3).getDisplayValue();SpreadsheetApp.getActiveSheet().getRange(numRow+1, 1, numRow+1 ,4).clearContent(); 85 after_msg =[{"type":"text","text":`${missitem}を取り消しました。`}]; 86 } 87 //「リスト」と入力した時に、リストのスプレッドシートへの入力をとりけし、今まで記録していたリストを呼び出す 88 else if (all_msg[0]==="リスト"){ 89 const numRow_new = listSheet.getLastRow(); 90 SpreadsheetApp.getActiveSheet().getRange(numRow_new, 1, numRow_new ,numColumn).clearContent() 91 92 //今までのスプレッドシートの情報を取得 93 let msg_text = ""; 94 let items = SpreadsheetApp.getActiveSheet().getRange(7,2,numRow+1,numColumn).getDisplayValues(); 95 96 const result_Row = numRow-6 97 //返信用のテキストを定義 98 for (i=0;i<=result_Row;i++) { 99 msg_text= msg_text + '\n'+items[i][0]+ '\t'+items[i][1]+ '\t'+items[i][2]; 100 } 101//返信用メッセージを定義 102 after_msg =[{"type":"text","text":`リストは以下の通りです\n${msg_text}\n\n精算結果\n${deal2}`}]; 103 } 104 //もし彼氏か彼女じゃない文字列が入力されたときに、エラーとして処理 105 else if(all_msg[0]!=="彼氏"&&all_msg[0]!=="彼女"){ 106 const numRow_new = listSheet.getLastRow(); 107 108 SpreadsheetApp.getActiveSheet().getRange(numRow_new, 1, numRow_new ,numColumn).clearContent() 109 110 after_msg =[{"type":"text","text":`エラーが発生しました。\n入力した文字をご確認ください`}]; 111 } else {after_msg = [{"type":"flex","altText":"This is a Flex Message", "contents":{"type":"bubble","header":{"type":"box","layout":"vertical","contents":[{"type":"text","text":`${all_msg[0]}`,"color":"#ffffff"}],"backgroundColor":"#555555"},"body":{"type":"box","layout":"vertical","contents":[{"type":"box","layout":"vertical","contents":[{"type":"box","layout":"horizontal","contents":[{"type":"text","text":`${all_msg[1]}`,"flex":2},{"type":"text","text":`¥${all_msg[2]}`,"flex":1}]},{"type":"separator","margin":"md"}],"margin":"md"},{"type":"box","layout":"vertical","contents":[{"type":"separator","color":"#000000"},{"type":"box","layout":"vertical","contents":[{"type":"text","text":"精算","flex":2,"size": "15px"},{"type":"text","text":`${deal2}`,"flex":1,"size": "18px"}],"margin":"sm"}]}]}}}];} 112 113//lineで返答する 114 UrlFetchApp.fetch(LINE_URL, {'headers': {'Content-Type': 'application/json; charset=UTF-8','Authorization': `Bearer ${LINE_TOKEN}`, },'method': 'post','payload': JSON.stringify({ 'replyToken': replyToken, 'messages': after_msg, }),}) 115//ここまでがもしイベントがメッセージだった時の処理 116 117 118ContentService.createTextOutput(JSON.stringify({'content': 'post ok'})).setMimeType(ContentService.MimeType.JSON); 119 120 const postbackData = JSON.parse(e.postData.contents).events[0].postback.data; 121SpreadsheetApp.getActiveSheet().getRange(1, 11).setValue(postbackData); 122} 123else if(events.type === 'postback' ) 124 125{SpreadsheetApp.getActiveSheet().getRange(1, 11).setValue("クリア"); 126 127 const postbackData = JSON.parse(e.postData.contents).events[0].postback.data;//0 128 const after_msg2 =null; 129 130 if(postBackData ==="yes"){ 131 132 SpreadsheetApp.getActiveSheet().getRange(6, 1, numRow ,numColumn).clearContent(); 133 after_msg2 ="精算完了";} 134 135 else if(postBackData ==="no"){ 136 after_msg2 ="精算完了をキャンセルしました"; 137 }; 138 UrlFetchApp.fetch(LINE_URL, { 139 'headers': { 140 'Content-Type': 'application/json; charset=UTF-8', 141 'Authorization': `Bearer ${LINE_TOKEN}`, 142 }, 143 'method': 'post', 144 'payload': JSON.stringify({ 145 'replyToken': replyToken, 146 'messages': after_msg2, 147 }), 148 }); 149ContentService.createTextOutput(JSON.stringify({'content': 'post ok'})).setMimeType(ContentService.MimeType.JSON); 150 151 152} 153} 154

試したこと

GASの処理能力の問題かもしれないと思い、ポストバック 処理を、メッセージを受け取った時の処理の前に置いてみたり、events[0]の処理以外の問題かもしれないと思い、イベントの個数に応じた繰り返し処理を試してみたりしました。

補足情報(FW/ツールのバージョンなど)

初心者でコードも見にくく、簡単なミスの可能性もありますが、回答いただけると助かります。よろしくお願いします。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

draq

2020/12/07 10:03

GAS の質問なら、Google Apps Script タグを付けてください。
guest

回答1

0

ベストアンサー

目視でデバッグしただけですが、ポストバックイベントオブジェクトにはmessageというメンバーは無いので、

JavaScript

1const userMessage = JSON.parse(e.postData.contents).events[0].message.text;//0

は、~.events[0].messageの部分がundefinedになるはずです。
そのためTypeError: Cannot read property 'text' of undefinedエラーが発生してるんじゃないでしょうか。


本題とは関係無いですが、もう少し処理を分けないとプログラムが見にくいです。(イベントタイプがmessageの場合とpostbackの場合の処理を別関数に切り出すとか)

投稿2020/12/07 10:02

draq

総合スコア2577

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

komukazu212

2020/12/08 12:40

回答ありがとうございました!困っていたことが解決しました!! 別関数書き出し等も試してみようと思います!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問