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

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

新規登録して質問してみよう
ただいま回答率
86.02%
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

受付中

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

uriuriuri
uriuriuri

総合スコア0

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ブラウザのほとんどに搭載されています。

2回答

0グッド

1クリップ

206閲覧

投稿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/ツールのバージョンなど)

特になし。

以下のような質問にはグッドを送りましょう

  • 質問内容が明確
  • 自分も答えを知りたい
  • 質問者以外のユーザにも役立つ

グッドが多くついた質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

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

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

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

下記のような質問は推奨されていません。

  • 間違っている
  • 質問になっていない投稿
  • スパムや攻撃的な表現を用いた投稿

適切な質問に修正を依頼しましょう。

回答2

1

試したこと

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

総合スコア289

qnoir👍を押しています

良いと思った回答にはグッドを送りましょう。
グッドが多くついた回答ほどページの上位に表示されるので、他の人が素晴らしい回答を見つけやすくなります。

下記のような回答は推奨されていません。

  • 間違っている回答
  • 質問の回答になっていない投稿
  • スパムや攻撃的な表現を用いた投稿

このような回答には修正を依頼しましょう。

回答へのコメント

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かと認識してしまっていました。前提から違って目から鱗です。 是非、検証して、結果をご報告いたします。少しお時間を頂きます!ありがとうございます。

1

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

投稿2023/01/24 02:20

plasticgrammer

総合スコア627

penguin520❤️を押しています

良いと思った回答にはグッドを送りましょう。
グッドが多くついた回答ほどページの上位に表示されるので、他の人が素晴らしい回答を見つけやすくなります。

下記のような回答は推奨されていません。

  • 間違っている回答
  • 質問の回答になっていない投稿
  • スパムや攻撃的な表現を用いた投稿

このような回答には修正を依頼しましょう。

回答へのコメント

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

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

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

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

ただいまの回答率
86.02%

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

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

質問する

関連した質問

同じタグがついた質問を見る

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ブラウザのほとんどに搭載されています。