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

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

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

Q&A

解決済

1回答

241閲覧

SlackbotアプリでGASのエラーが投稿される。

Shinsuke

総合スコア3

0グッド

3クリップ

投稿2024/01/20 10:18

編集2024/01/20 10:36

実現したいこと

Slackのチャンネルにスラッシュコマンドを投稿したら、天気予報をpost投稿するようにしました。GASを利用しており、ライブラリは、SlackAppとSlack Apiの利用しています。

#予定チャンネルに投稿したいのですが、GAS側のエラーが解消できません。エラーで失敗した投稿と正常に結果を返す投稿の合わせて2投稿が一緒にpostされて困っています。
main関数で投稿しています。

発生している問題・分からないこと

スラッシュコマンドを利用した際に、GASのdoPost()関数にコードエラーがあるようで、チャンネルにGASのエラーが投稿されています。main()関数で天気予報を投稿しています。

イメージ説明

エラーメッセージ

error

1<!DOCTYPE html> 2 <html> 3 <head> 4  <link rel="shortcut icon" href="//ssl.gstatic.com/docs/script/images/favicon.ico"> 5  <title>Error</title> 6  <style type="text/css" nonce="wP9kkBAHoNUxd264f9YYTQ">body {background-color: #fff; margin: 0; padding: 0;}.errorMessage {font-family: Arial,sans-serif; font-size: 12pt; font-weight: bold; line-height: 150%; padding-top: 25px;}</style> 7 </head> 8 <body style="margin:20px"> 9  <div><img alt="Google Apps Script" src="//ssl.gstatic.com/docs/script/images/logo.png"> 10 </div> 11  <div style="text-align:center;font-family:monospace;margin:50px auto 0;max-width:600px">The script completed but did not return anything.</div> 12 </body> 13</html>

該当のソースコード

GAS

1function doPost(e) { 2 3 var slack_token = PropertiesService.getScriptProperties().getProperty('SlackToken'); // Verification Tokenで取得するトークン 4 var params = JSON.parse(e.postData.getDataAsString()); 5 console.log(e.postData.getDataAsString()) 6 7 if (params.type === 'url_verification') { 8 return ContentService.createTextOutput(params.challenge); 9 } 10 const body = JSON.parse(event.body); 11 if (!(body.token === slack_token)) return {"statusCode": 401, "body": "Missing Token"} 12 // 再送かをチェック 13 if (event.headers['X-Slack-Retry-Num']) { 14 return { statusCode: 200, body: JSON.stringify({ message: "No need to resend" }) }; 15 } 16 var channel = postData.event.channel; 17 var ts = postData.event.ts; 18 var cache = CacheService.getScriptCache(); 19 // ここのキーは自由に変えてください。 20 // 今回はメンションに反応するbotなので発言されたチャネルID、タイムスタンプをキーにしました。 21 var cacheKey = channel + ':' + ts; 22 var cached = cache.get(cacheKey); 23 if (cached != null) { 24 console.log('do nothing!'); 25 return; 26 } 27 cache.put(cacheKey, true, 1800); // 30分キャッシュする(ここは目安。もっと短くてもいいかもしれない) 28 main(); 29 30}

試したこと・調べたこと

  • teratailやGoogle等で検索した
  • ソースコードを自分なりに変更した
  • 知人に聞いた
  • その他
上記の詳細・結果

エラー内容は、スクリプトは完了しましたが、何も返されませんでした。このエラーは通常、Google Apps Scriptの関数が値を返さない場合に発生します。
Google Apps Scriptでは、doGetやdoPostなどの関数はHTMLコンテンツや新しいアプリのインスタンスなどの値を返すはずです。これらの関数が何も返さない場合、エラーメッセージが表示されることがあります、という事でした。
また古い情報ではCallbackIDが云々という情報もありましたが、今回はSlackAppなので関係ないように思えました。
CallbackID云々

特に変わらずエラー解消できなかった。
#予定チャンネルがきれいに確認できれば良いので他チャンネルでスラッシュコマンド打って、♯予定チャンネルに投稿されるという方法で凌いでいます。この場合、他チャンネルにエラーが1投稿されて目的の#予定チャンネルに正常な結果『天気予報』だけが1投稿されるので問題はありません。

補足

main()関数はもともと定時実行する、#予定チャンネルに天気予報の投稿をする関数でありトリガーを設定しております。特に支障はなく、定時実行のタイミング若しくはGoogle apps scriptから直接実行した際には、今回のGASのエラーはチャンネルに吐き出しません。

doPost()関数は基本的に、デバッグツールで確認できないので余計に困っています。手動では確認が取れないので途方に暮れています。
Event SubscriptionsのRequest URLには、GASのWeb App URLを登録しています。
Slackボット名やSlach command名などが関係しているのであれば、設定方法自体が誤りかも知れません。

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

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

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

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

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

YellowGreen

2024/01/22 05:14 編集

スラッシュコマンドに他に用途がないのなら、 次のようなシンプルなコードにしてみるというのはどうでしょうか? function doPost(e) { main(); var res = {response_type: 'in_channel', text: 'お天気お姉さんを呼びました。'}; return ContentService.createTextOutput(JSON.stringify(res)).setMimeType(ContentService.MimeType.JSON); }
Shinsuke

2024/01/23 11:21

コメントありがとうございます。参考にして試したところ問題が解決しました! ベストアンサーに選びたいので同じ内容を回答欄に投稿いただけますか?
guest

回答1

0

自己解決

忘れそうなので、回答入力します。

Event Subscriptions
Subscribe to bot events項目に
message.channels
message.groups
のアクセス許可をすればうまくいくようになりました。

Challenge認証は必須のようでした。
いずれにせよ、アプリ挙動可笑しくなったら削除して作り直した方が理由不明ですが解消は早かったです。また教えていただきましたコードを参考に以下のようにしました。大変ありがとうございます。

GAS

1//認証作業 2function doPost(e) { 3 var res = {}; 4 const params = e.parameter; 5 const command = params.command 6 const userId = params.user_id 7 8 if (params.type === "undefined") { 9 return post("invalid request"); 10 } 11 12 //Challenge認証用 13 if (params.type === 'url_verification') { 14 res = {'challenge':postData.challenge} 15 return ContentService.createTextOutput(JSON.stringify(res)).setMimeType(ContentService.MimeType.JSON); 16 } 17 18 //処理 19 switch (command) { 20 case '/rain': 21 main(); 22 let response = { text: '…天気を唱えた' }; 23 return ContentService.createTextOutput(JSON.stringify(response)).setMimeType(ContentService.MimeType.JSON); 24 case '': 25 let excuse = { text: 'お天気お姉さんは' + userId + "が天気を唱えた" }; 26 return ContentService.createTextOutput(JSON.stringify(excuse)).setMimeType(ContentService.MimeType.JSON); 27 28 default: 29 return ContentService.createTextOutput(JSON.stringify(e)); 30 } 31} 32

イメージ説明
それからAPIエラーは当然発生するので、以下コード例を参考にした作りこみを今後改修したいのと、アプリ投稿時に文字数が少ない場合に、アプリ名が縦に表記されるのが困ります。。。

Slack Event Api 回避

GAS

1// Verification Tokenで取得するトークン 2 var legacyVerificationToken = PropertiesService.getScriptProperties().getProperty('SLACK_VERIFICATION_TOKEN'); 3 const event = params.event;//このevent関連情報の取得方法が分からずエラーになる 4 5 if (params.type === "undefined") { 6 return post("invalid request"); 7 } 8 const body = JSON.parse(event.body); 9 if (!(body.token === legacyVerificationToken)) 10 return {"statusCode": 401, "body": "Missing Token"} 11 // 再送かをチェック 12 if (event.headers['X-Slack-Retry-Num']) { 13 return { statusCode: 200, body: JSON.stringify({ message: "No need to resend" }) }; 14 } 15 //Challenge認証用 16 if (params.type === 'url_verification') { 17 res = {'challenge':postData.challenge} 18 //return ContentService.createTextOutput(params.challenge); 19 ontentService.createTextOutput(JSON.stringify(res)).setMimeType(ContentService.MimeType.JSON); 20 } 21 var channel = postData.event.channel; 22 var ts = postData.event.ts; 23 var cache = CacheService.getScriptCache(); 24 // ここのキーは自由に変えてください。 25 // 今回はメンションに反応するbotなので発言されたチャネルID、タイムスタンプをキーにしました。 26 var cacheKey = channel + ':' + ts; 27 var cached = cache.get(cacheKey); 28 if (cached != null) { 29 console.log('do nothing!'); 30 return; 31 } 32 cache.put(cacheKey, true, 1800); // 30分キャッシュする(ここは目安。もっと短くてもいいかもしれない) 33

投稿2024/01/27 15:17

Shinsuke

総合スコア3

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.46%

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

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

質問する

関連した質問