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

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

新規登録して質問してみよう
ただいま回答率
85.50%
Google Apps Script

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

Slack

Slackは、Tiny Speckという企業からリリースされたコミュニケーションツールです。GoogleDriveやGitHubなど、さまざまな外部サービスと連携することができます。

Q&A

解決済

2回答

6055閲覧

Slackで作ったオリジナルのスラッシュコマンドを入力するとエラーが返ってきてしまう

jimunomado

総合スコア19

Google Apps Script

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

Slack

Slackは、Tiny Speckという企業からリリースされたコミュニケーションツールです。GoogleDriveやGitHubなど、さまざまな外部サービスと連携することができます。

0グッド

0クリップ

投稿2019/02/21 04:20

前提・実現したいこと

特定の電車の遅延情報を知らせるSlackBotを作っています。
オリジナルのスラッシュコマンド /traininfo_nowを作り、このスラッシュコマンドを入力した時に、電車の遅延情報を返すようにしたいと思っています。
以下のサイトを参考に作成しました。

SlackBotで電車の運行情報をスラッシュコマンドで通知してもらうhttps://qiita.com/yuina_i/items/617066e09426194bcd71

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

/trainindfo_nowを入力するとbotは遅延情報を返してくれますが、その直後にエラーを返します。
コマンドを入力すると10:32の遅延状況を返しますが、直後にエラーも返ってきます。中身をよく読むと末尾に

The Script completed but did not return anything

と書いてあります

スラッシュコマンド入力後に帰ってくるエラー

該当のソースコード

Java

1var slackAccessToken = PropertiesService.getScriptProperties().getProperty('slack APIで取得した Verification TOKEN'); 2 3function doPost(e) { 4var slackApp = SlackApp.create(slackAccessToken); 5// 対象チャンネル 6var channelId = "#train_info"; 7var options = { 8// 投稿するユーザーの名前 9username: "train_info", 10icon_emoji: ":train:", 11} 12 13 var currentDate = new Date(); 14 var weekday = currentDate.getDay(); 15 var date = Utilities.formatDate( currentDate, 'Asia/Tokyo', 'M月d日 HH時mm分'); 16 17 if (weekday == 0 || weekday == 6) { 18 return; 19 } 20 var calendar = CalendarApp.getCalendarById('ja.japanese#holiday@group.v.calendar.google.com'); 21 if (calendar.getEventsForDay(currentDate, {max: 1}).length > 0) { 22 return; 23 } 24 25 //soubu line info 26 var yahoodata = UrlFetchApp.fetch("https://transit.yahoo.co.jp/traininfo/detail/40/0/").getContentText(); 27 if(yahoodata.indexOf('現在、事故・遅延に関する情報はありません。') > -1){ 28 // match the word 29 postMessage("\n" + "◆総武線は平常運転です。\n",'slack APIで取得した Webhook Address'); 30 }else{ 31 //get error info 32 var yahoodatastart = yahoodata.indexOf('og:description" content="'); 33 //4 japanese word only 34 yahoodatastart += 25; 35 var yahoodataend = yahoodata.indexOf('の情報です。'); 36 var yahoodataoutput = yahoodata.substring(yahoodatastart, yahoodataend); 37 38 postMessage("\n" + "◆総武線 " + date + "\n" + yahoodataoutput + "\n",'slack APIで取得した Webhook Address'); 39 } 40 41 42 //tokyometro tozai line info 43 var yahoodata2 = UrlFetchApp.fetch("https://transit.yahoo.co.jp/traininfo/detail/135/0/").getContentText(); 44 if(yahoodata2.indexOf('現在、事故・遅延に関する情報はありません。') > -1){ 45 // match the word 46 postMessage("\n" + "◆東西線は平常運転です。\n",'slack APIで取得した Webhook Address'); 47 }else{ 48 //get error info 49 var yahoodatastart2 = yahoodata2.indexOf('og:description" content="'); 50 //4 japanese word only 51 yahoodatastart2 += 25; 52 var yahoodataend2 = yahoodata2.indexOf('の情報です。'); 53 var yahoodataoutput2 = yahoodata2.substring(yahoodatastart2, yahoodataend2); 54 55 postMessage("\n" + "◆東京メトロ東西線 " + date + yahoodataoutput2 + "\n",'slack APIで取得した Webhook Address'); 56 57 } 58 59 // JR Chuo line info 60 var yahoodata2 = UrlFetchApp.fetch("https://transit.yahoo.co.jp/traininfo/detail/38/0/").getContentText(); 61 if(yahoodata2.indexOf('現在、事故・遅延に関する情報はありません。') > -1){ 62 // match the word 63 postMessage("\n" + "◆JR中央線(快速)は平常運転です。\n",'slack APIで取得した Webhook Address') 64 }else{ 65 //get error info 66 var yahoodatastart2 = yahoodata2.indexOf('og:description" content="'); 67 //4 japanese word only 68 yahoodatastart2 += 25; 69 var yahoodataend2 = yahoodata2.indexOf('の情報です。'); 70 var yahoodataoutput2 = yahoodata2.substring(yahoodatastart2, yahoodataend2); 71 72 postMessage("\n" + "◆JR中央線(快速) " + date + yahoodataoutput2 + "\n",'slack APIで取得した Webhook Address'); 73 74 } 75 76 77} 78 79 80function postMessage(message, hookpoint){ 81 var payload = { 82 "text": message, 83 "channelId": '#train_info', 84 "userName": 'train_info', 85 "icon_emoji": ':train:' 86 } 87 var options = { 88 "method": "POST", 89 "payload": JSON.stringify(payload), 90 "headers": { 91 "Content-type": "application/json", 92 } 93 } 94 var response = UrlFetchApp.fetch('slack APIで取得した Webhook Address',options); 95 96 if (response.getResponseCode() == 200) { 97 return response; 98 } 99 return false; 100}

事の発端と考えてみたこと

もともと定時に電車の遅延を知らせるbotを作っていました。
※参考: https://teratail.com/questions/174195#

この後ネットの海をさまよっていたところ、スラッシュコマンド入力でbotに電車遅延を知らせることができるようになると知りました。
個人的には定時&任意の時に知りたい→任意の時に知りたいならスラッシュコマンド便利じゃん!となり、実装を決意しました。
最初、もともと実装していたコードをそのまま動かそうとしたのですが「doPostがないよ!」とエラーを返されました。そのため元々のコードにdoPost Functionを足し、またメッセージを返すWebhook URLもslack API側のWebhook URLに直しました。(元のコードでは、Incoming Webhookから取得したURLを利用しています)
自分がいじったコードがまずそう、というのはなんとなくわかるのですが、何をどう処理したらよいのか(そもそもコードの問題でもなくて、slackでbot生成した際の不具合なのか?)わからずにいます。

ご教示願えますと幸いです。

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

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

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

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

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

guest

回答2

0

ベストアンサー

doPost関数が何も返していないので何か返すようにすればエラーは解消されると思います。
例えば空文字を返すとか
return ContentService.createTextOutput("");

投稿2019/02/21 05:05

退会済みユーザー

退会済みユーザー

総合スコア0

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

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

jimunomado

2019/02/21 05:14

これはdoPost関数の末尾に入れればよいでしょうか・・・?
退会済みユーザー

退会済みユーザー

2019/02/21 05:21

はい、末尾に追加すれば今発生しているエラーは解消されると思います。 (そもそも、記事と同じような実装でいいのでは?という疑いはありますが)
jimunomado

2019/02/21 05:33

こちらで一応解決しました! 記事と同様の実装については今晩からでもさっそく実行してみます。
papinianus

2019/02/21 05:44

土日祝日にスラッシュコマンド打ったら同じエラー再現すると思う
jimunomado

2019/02/21 05:51

土日祝除く設定にしているのは把握しております。ひとまずスラッシュコマンドを試してみたかったというような感じですので、細かい設定ほかについては改めて実装しなおします。
guest

0

postSlackを実行するのではなく、参考リンクのようにjsonにしてreturnしましょう

方針としては、メッセージ取得部分を切り離して、トリガーでコールされたときと、doPost(slack command)でコールされたときで、それぞれのハンドラが何をするか制御したほうがいいですね。

ただこうしたとき、時刻トリガで動作したときに、遅延がなくてもメッセージが送られてしまいますね
それがいやだとなると、ちょっと面倒(既存コードのコピペですまないので、自分で考えてほしいです)

javascript

1const slackAccessToken = PropertiesService.getScriptProperties().getProperty('slack APIで取得した Verification TOKEN'); 2 3function triggerDriver() { 4 const slackApp = SlackApp.create(slackAccessToken); 5 // 対象チャンネル 6 const channelId = "#train_info"; 7 const options = { 8 // 投稿するユーザーの名前 9 username: "train_info", 10 icon_emoji: ":train:", 11 } 12 13 const currentDate = new Date(); 14 const weekday = currentDate.getDay(); 15 const date = Utilities.formatDate( currentDate, 'Asia/Tokyo', 'M月d日 HH時mm分'); 16 17 if (weekday === 0 || weekday === 6) { 18 return; 19 } 20 const calendar = CalendarApp.getCalendarById('ja.japanese#holiday@group.v.calendar.google.com'); 21 if (calendar.getEventsForDay(currentDate, {max: 1}).length > 0) { 22 return; 23 } 24 const infos = getMessages(); 25 postMessage(infos, 'slack APIで取得した Webhook Address'); 26} 27function doPost(e) { 28 const infos = getMessages(); 29 const res = {"text": infos}; 30 return ContentService.createTextOutput(JSON.stringify(res)).setMimeType(ContentService.MimeType.JSON); 31} 32function getMessages() { 33 //soubu line info 34 const soubuLine = clipInfo("総武線", UrlFetchApp.fetch("https://transit.yahoo.co.jp/traininfo/detail/40/0/").getContentText()); 35 36 //tokyometro tozai line info 37 const tozaiLine = clipInfo("東西線", UrlFetchApp.fetch("https://transit.yahoo.co.jp/traininfo/detail/135/0").getContentText()); 38 39 // JR Chuo line info 40 const chuoLine = clipInfo("R中央線(快速)", UrlFetchApp.fetch("https://transit.yahoo.co.jp/traininfo/detail/38/0").getContentText()); 41 return soubuLine + "\n" + tozaiLine + "\n" + chuoLine + "\n"; 42} 43 44function clipInfo(line, content) { 45 if(content.indexOf('現在、事故・遅延に関する情報はありません。') > -1){ 46 return "◆" + "は平常運転です"; 47 } 48 const currentDate = new Date(); 49 const date = Utilities.formatDate( currentDate, 'Asia/Tokyo', 'M月d日 HH時mm分'); 50 const yahoodatastart = content.indexOf('og:description" content="') + 25; 51 const yahoodataend = content.indexOf('の情報です。'); 52 const yahoodataoutput = content.substring(yahoodatastart, yahoodataend); 53 54 return "◆" + line + date + "\n" + yahoodataoutput ; 55} 56function postMessage(message, hookpoint){ 57 var payload = { 58 "text": message, 59 "channelId": '#train_info', 60 "userName": 'train_info', 61 "icon_emoji": ':train:' 62 } 63 var options = { 64 "method": "POST", 65 "payload": JSON.stringify(payload), 66 "headers": { 67 "Content-type": "application/json", 68 } 69 } 70 var response = UrlFetchApp.fetch('slack APIで取得した Webhook Address',options); 71 72 if (response.getResponseCode() == 200) { 73 return response; 74 } 75 return false; 76} 77

投稿2019/02/21 04:37

編集2019/02/21 05:15
papinianus

総合スコア12705

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

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

jimunomado

2019/02/21 05:36

こちらは先般作ったのとは別のGASファイルを作りました。ので時刻トリガーとは連動しておりません。 プログラミングど初心者ですが、いただいた情報をもとに何とか頑張って作ってみようと思います。いつもありがとうございます。
papinianus

2019/02/21 05:42

連動する必要は全くありませんし、連動しているのではなく、機能ごとに関数切り出しをすべきだという提案です。 別のGASを作ればいいというのは発想としてあまり良いものではないです。それは同じ実装をコピーしたということですよね?バージョン管理しているのですか?引越し・転職で路線がかわったときに2つ直すのですか? 私は「基本的に動けばいい」の方針ですが、ベストの回答はエラーを握り潰しているだけです。 APIに則ったコーディングをすべきです。
jimunomado

2019/02/21 05:57

お恥ずかしながらプログラミングど初心者(普段はVBAをちょろっと触る人間で、元はBASICを少し習っていた程度です)で、JavaScriptなんて触ったことがなかったのです。 今回別のGASを作ったというのが発想としてよろしくないというのは理解しております。 しかし私の足りない頭ではこうするよりほかなかった、というのが正直なところです。 貴重なご意見、本当にありがとうございます。おっしゃることごもっともですので、今後の糧にしてまいりたいと思います。
退会済みユーザー

退会済みユーザー

2019/02/21 06:49

何か変な誤解が生じていたら嫌なので一応僕の回答について説明します。(特に誤解がなければ無視してください) 僕はエラー文を検索して、なぜエラーが発生したのか?どうすればエラーがなくなるかを調べただけです。この質問の背景、コード、元ネタの記事等はよく読んでいないです。 また僕が回答に記載し始めた時は回答が0でした。papinianusさんの回答を読んでいない状態で自分の回答を送信しました。もしpapinianusさんの回答を読んでいたら自分の回答を送信しようとは思わなかったです。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問