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

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

新規登録して質問してみよう
ただいま回答率
85.48%
LINE Messaging API

LINE Messaging APIは、メッセージの送信・返信ができるAPIです。Web APIを経由しアプリケーションサーバとLINEのAPIでやり取りが可能。複数のメッセージタイプや分かりやすいAPIリファレンスを持ち、グループチャットにも対応しています。

Google スプレッドシート

Google スプレッドシートは、フリーで利用できる表計算ソフト。Webアプリのためインターネットに接続することで利用できます。チャートやグラフの作成のほか、シートを他のユーザーと共有したり、同時に作業を進めることも可能です。

Google Apps Script

Google Apps ScriptはGoogleの製品と第三者のサービスでタスクを自動化するためのJavaScriptのクラウドのスクリプト言語です。

JavaScript

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

Q&A

解決済

2回答

1466閲覧

LINEbot:部分一致で返信したい(GAS、スプレッドシート利用)

uriuriuri

総合スコア1

LINE Messaging API

LINE Messaging APIは、メッセージの送信・返信ができるAPIです。Web APIを経由しアプリケーションサーバとLINEのAPIでやり取りが可能。複数のメッセージタイプや分かりやすいAPIリファレンスを持ち、グループチャットにも対応しています。

Google スプレッドシート

Google スプレッドシートは、フリーで利用できる表計算ソフト。Webアプリのためインターネットに接続することで利用できます。チャートやグラフの作成のほか、シートを他のユーザーと共有したり、同時に作業を進めることも可能です。

Google Apps Script

Google Apps ScriptはGoogleの製品と第三者のサービスでタスクを自動化するためのJavaScriptのクラウドのスクリプト言語です。

JavaScript

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

0グッド

2クリップ

投稿2023/01/23 19:24

前提

完全なる初心者で、GASとスプレッドシートによるLINEbotを作成しようとしています。
恥ずかしながら、有識者様のブログを参考にしているだけの状況です。

実現したいこと

現在は、A列セル内の文字、完全一致で、B列の文字が返ってきます。
例:A列「おはよう」B列「おはよ~」
LINE「おはよう」→「おはよ~」と返ってくる。
LINE「おはよう、いい朝だね」→返ってこない。

今後は、A列セル内の文字が含まれる文章がきたら、B列の文字を返したいです。
例:A列「おはよう」B列「おはよ~」
LINE「おはよう、いい朝だね」→「おはよ~」

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

indexOfを挿入するも、正常に動作しなくなる

該当のソースコード

GAS(Java)

//★★LINE Messaging APIのチャネルアクセストークン★★
var LINE_ACCESS_TOKEN = "●●●";

//★★スプレッドシートID★★
var ss = ●●●");

//★★シート名★★
var sh = ss.getSheetByName("●●●");

//LINE Messaging APIからPOST送信を受けたときに起動する
// e はJSON文字列
function doPost(e){
if (typeof e === "undefined"){
//動作を終了する
return;
} else {
//JSON文字列をパース(解析)し、変数jsonに格納する
var json = JSON.parse(e.postData.contents);

//変数jsonを関数replyFromSheetに渡し、replyFromSheetを実行する replyFromSheet(json)

}
}

//返信用の関数replyFromSheet
// data には変数jsonが代入される
function replyFromSheet(data) {
//返信先URL
var replyUrl = "https://api.line.me/v2/bot/message/reply";

//シートの最終行を取得する
var lastRow = sh.getLastRow();

//シートの全受信語句と返信語句を二次元配列で取得する
var wordList = sh.getRange(1,1,lastRow,2).getValues();

//受信したメッセージ情報を変数に格納する
var reply_token = data.events[0].replyToken; //reply token
var text = data.events[0].message.text; //ユーザーが送信した語句

//返信語句を格納するための空配列を宣言する
var replyTextList = [];

//LINEで受信した語句がシートの受信語句と同じ場合、返信語句をreplyTextにpushする
for(var i = 1; i < wordList.length; i++) {
if(wordList[i][0] == text) {
replyTextList.push(wordList[i][1]);
}
}

//LINEで受信した語句がシートの受信語句と一致しない場合、関数を終了する
if(replyTextList.length < 1) {
return;

//replyTextListのLengthが5より大きい場合、messageLengthを5にする
//※※一度に最大5つの吹き出ししか返信できないためです※※
} else if(replyTextList.length > 5) {
var messageLength = 5;
} else {
var messageLength = replyTextList.length;
}

//"messages"に渡す配列を格納するための空配列を宣言する
//[{"type": "text", "text": "返信語句その1"},{"type": "text", "text": "返信語句その2"}....]
var messageArray = [];

//replyTextListに格納されている返信語句を最大5つ、messageArrayにpushする
for(var j = 0; j < messageLength; j++) {
messageArray.push({"type": "text", "text": replyTextList[j]});
}

var headers = {
"Content-Type": "application/json; charset=UTF-8",
"Authorization": "Bearer " + LINE_ACCESS_TOKEN,
};

var postData = {
"replyToken": reply_token,
"messages": messageArray
};

var options = {
"method" : "post",
"headers" : headers,
"payload" : JSON.stringify(postData)
};

//LINE Messaging APIにデータを送信する
UrlFetchApp.fetch(replyUrl, options);
}

試したこと

for (var i = 0; i < wordList.length; i++) {
if (json.indexOf(wordList[i][0]) > -1) {
gyo = i;
break;
}
}

などに置き換えたりしてみましたが、動作自体が止まります。
(上記と似たようなパターンで何度か置き換えしてみましたがダメでした。。)

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

特になし。

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

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

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

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

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

guest

回答2

0

ベストアンサー

試したこと

for (var i = 0; i < wordList.length; i++) {
if (json.indexOf(wordList[i][0]) > -1) {
gyo = i;
break;
}
}

GAS

1break;

ではなく、

GAS

1continue;

では?

追記:進捗
ご質問のコードでは、実行エラーになり。どの行で止まっているか判断つかないため。
https://first-contact.jp/blog/article/linebot/
こちらの情報を参考に1から作り直しています。

GAS

1function doPost(e) { 2 var replyToken = JSON.parse(e.postData.contents).events[0].replyToken; 3 var replytext = JSON.parse(e.postData.contents).events[0].message.text; 4 if (typeof replyToken === 'undefined') { 5 return; 6 } 7 8 var url = 'https://api.line.me/v2/bot/message/reply'; 9 var channelToken = ''; 10 11 var messages = [{ 12 'type': 'text', 13 'text': replytext, 14 }]; 15 16 UrlFetchApp.fetch(url, { 17 'headers': { 18 'Content-Type': 'application/json; charset=UTF-8', 19 'Authorization': 'Bearer ' + channelToken, 20 }, 21 'method': 'post', 22 'payload': JSON.stringify({ 23 'replyToken': replyToken, 24 'messages': messages, 25 }), 26 }); 27 return ContentService.createTextOutput(JSON.stringify({ 'content': 'post ok' })).setMimeType(ContentService.MimeType.JSON);

このコードで 変数

GAS

1replytext

に、送信された文字列が落ちてきていることが確認できたため。 replytext の文章を、いまからスプレッドシートを比較して、それに応じて返答が変わるようにしていきます。

追記:進捗
A列と同じ文言についてはB列の言葉で返答するように構築(ここまでは質問者さんも実装済み)

GAS

1function doPost(e) { 2 let replyToken = JSON.parse(e.postData.contents).events[0].replyToken; //replyToken取得 3 let replytext = JSON.parse(e.postData.contents).events[0].message.text;//送信されたメッセージを取得 4 if (typeof replyToken === 'undefined') { 5 return; 6 } 7 8 let url = 'https://api.line.me/v2/bot/message/reply'; 9 let channelToken = '';//チャンネルトークンとかそのへん。 10 11 let sh = SpreadsheetApp.openById("").getSheetByName("シート1"); //変数shにスプレッドシートの場所を保存(本来letではなくconstにすべき) 12 13 let lastRow = sh.getLastRow(); //データーの最終行を取得 14 let list = sh.getRange(1, 1, lastRow, 2).getValues(); //データーを2次元配列で格納 15 16 for (let index = 0; index < list.length; index++) { 17 if (replytext == list[index][0]) { 18 replytext = list[index][1]; 19 } 20 21 } 22 23 24 var messages = [{ 25 'type': 'text', 26 'text': replytext, 27 }]; 28 29 UrlFetchApp.fetch(url, { 30 'headers': { 31 'Content-Type': 'application/json; charset=UTF-8', 32 'Authorization': 'Bearer ' + channelToken, 33 }, 34 'method': 'post', 35 'payload': JSON.stringify({ 36 'replyToken': replyToken, 37 'messages': messages, 38 }), 39 }); 40 return ContentService.createTextOutput(JSON.stringify({ 'content': 'post ok' })).setMimeType(ContentService.MimeType.JSON); 41}

進捗:実装完了
indexOf だとうまくいかず(こんにちわって言ってるのに倍返ししてくる)。リファレンスをみると、indexOfは、何文字目に同じ文字が来ているかを探すもののようなので、mach()を使ったらうまくいきました。
他、この回答のコメント欄にメッセージ差し上げます。

GAS

1function doPost(e) { 2 let replyToken = JSON.parse(e.postData.contents).events[0].replyToken; //replyToken取得 3 let replytext = JSON.parse(e.postData.contents).events[0].message.text;//送信されたメッセージを取得 4 if (typeof replyToken === 'undefined') { 5 return; 6 } 7 8 let url = 'https://api.line.me/v2/bot/message/reply'; 9 let channelToken = '';//チャンネルトークンとかそのへん。 10 11 let sh = SpreadsheetApp.openById("").getSheetByName("シート1"); //変数shにスプレッドシートの場所を保存(本来letではなくconstにすべき) 12 13 let lastRow = sh.getLastRow(); //データーの最終行を取得 14 let list = sh.getRange(1, 1, lastRow, 2).getValues(); //データーを2次元配列で格納 15 16 for (let index = 0; index < list.length; index++) { 17 if (replytext.match(list[index][0])) { 18 replytext = list[index][1]; 19 } 20 21 } 22 23 24 var messages = [{ 25 'type': 'text', 26 'text': replytext, 27 }]; 28 29 UrlFetchApp.fetch(url, { 30 'headers': { 31 'Content-Type': 'application/json; charset=UTF-8', 32 'Authorization': 'Bearer ' + channelToken, 33 }, 34 'method': 'post', 35 'payload': JSON.stringify({ 36 'replyToken': replyToken, 37 'messages': messages, 38 }), 39 }); 40 return ContentService.createTextOutput(JSON.stringify({ 'content': 'post ok' })).setMimeType(ContentService.MimeType.JSON); 41}

イメージ説明
イメージ説明

投稿2023/01/24 03:52

編集2023/01/25 05:41
penguin520

総合スコア345

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

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

uriuriuri

2023/01/24 07:32

構文こみのご回答、ありがとうございます!わかりやすかったです。 ただ、助言いただいた通り、break;をcontinue;に差し替えてみましたが、動作しませんでした。 力及ばずで申し訳ありません。。
penguin520

2023/01/24 07:35

ちょっと明日、ご質問のコードを走らせて調べてみますね。 他の方の回答で解決したら、それはそれでよしとして。 対応させてもらいます。
uriuriuri

2023/01/24 07:46

えっ!!わわわ、すみません、ありがとうございます;; 大変恐縮ですが…個人では限界があったので頼らせていただければと思います。 よろしくお願いいたします。
penguin520

2023/01/25 05:38

とりあえず、やりたいことについては、こちらで再現できたのですが。ご質問のコードのどこを変えればいいかというところまでできていません。 ①うまく動いていたコード と ②動かなくなったコード の 両方を差分で公開していただければデバックができるかもしれません。 とりえず、 .mach() 使えばできました。
uriuriuri

2023/01/25 17:35

スクショまで上げてくださって、本当にありがとうございます;; すぐの検証時間が取れなさそうだったので、取り急ぎお礼を…ありがとうございます。 色々検索してindexOfかと認識してしまっていました。前提から違って目から鱗です。 是非、検証して、結果をご報告いたします。少しお時間を頂きます!ありがとうございます。
uriuriuri

2023/02/02 14:28

めちゃくちゃお時間頂いてしまい申し訳ございませんでした! 結論から申し上げると、無事できました…!!ありがとうございます。 お恥ずかしい話ですが、コードを丸っとコピペさせていただく形で無事、動作しました。 ずぶの初心者という点も考慮していただき、大変助かりました。 本当にありがとうございます! (返信どうぞお気遣いなく)
penguin520

2023/02/03 02:11

解決してよかったです。よくお勉強されているようなので、がんばってください! もし、いっしょにお仕事するようになったらよろしくお願いします!!
guest

0

変数jsonは構造化されたオブジェクトです。
やりたいことは変数text(メッセージ文字列)に対してindexOfすればよいのではないでしょうか。

投稿2023/01/24 02:20

plasticgrammer

総合スコア629

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

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

uriuriuri

2023/01/24 07:30

早々のご回答、まことにありがとうございます! 基礎がなってない故に、textらしき箇所にindexOfを入れてみましたが、動作が止まってしまいました。 私のやり方が間違っているのだと思います。せっかく助言いただいたのに申し訳ないです。 一応試した構文を下記に記載いたします。 ① for(var i = 1; i < wordList.length; i++) { if(wordList[i][0] == indexOf(text)) {  replyTextList.push(wordList[i][1]); } } ② var text = indexOf(data.events[0]).message.text; //ユーザーが送信した語句 ③ var text = indexOf(data.events[0].message.text); //ユーザーが送信した語句 ④ //シートの全受信語句と返信語句を二次元配列で取得する var wordList = sh.getRange(indexOf(1),1,lastRow,2).getValues(); ルール無視な突っ込み方をしていると思います。お恥ずかしい。。
plasticgrammer

2023/01/24 14:35

説明が足りておらず、すみません。 json.indexOf ではなく text.indexOf にすれば良いのでは?ということでした。
uriuriuri

2023/01/24 15:00

わぁ、お恥ずかしい。。 下記の認識で合ってますでしょうか。ただこれも動作が止まってしまいました。すみません。 for (var i = 0; i < wordList.length; i++) { if (text.indexOf(wordList[i][0]) > -1) { gyo = i; continue; } }
plasticgrammer

2023/01/25 01:42

現状のソースがどのようになっているのかがわかりませんが、最初に if (wordList[i][0] == text) { としていた箇所を if (text.indexOf(wordList[i][0]) > -1) { にするだけのイメージです。 これで駄目だということでしょうか。
uriuriuri

2023/01/25 17:33

返信が遅くなり申し訳ありません!そしてありがとうございます。 すぐに検証の時間が取れなさそうだったので、取り急ぎお礼まで。 少しお時間を頂きます。また進捗を報告いたします。
uriuriuri

2023/02/02 14:27 編集

お待たせして申し訳ありません。 今回、ほかの回答者様の内容で解決いたしました。 お時間を割いていただき、本当にありがとうございました!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問