kinako16
@kinako16 (花月 きなこ)

Are you sure you want to delete the question?

If your question is resolved, you may close it.

Leaving a resolved question undeleted may help others!

We hope you find it useful!

Slackで「おはよう」と投稿があると「おはよう」と返すbotが無限ループする

解決したいこと

Slackで「おはよう」と投稿があると「おはよう」と返すbotが無限ループする

▼こちらの記事を参考にしました。
https://pafu-of-duck.hatenablog.com/entry/2019/03/16/022146

この記事の通りに設定して、「おはよう」と投稿してもbotが反応しません・・・。
どこに原因がありますでしょうか・・・?

【追記】
Outgoing WebhooksではなくてEvent SubscriptionsのEnable EventsをonにしたらSlackの投稿を拾うようになりました。

発生している問題・エラー

今度は「おはよう」と投稿するとbotが「おはよう」と無限ループするようになりました・・・。
たぶん「おはよう」という文字列があると「おはよう」と投稿するので無限ループになってます。
無限ループせずに1回だけ「おはよう」と投稿する方法が分かりません。

該当するソースコード

function doPost() {
  var options =
  {
    "method" : "post",
    "contentType" : "application/json",
    "payload" : JSON.stringify(
      {
        "text" : "おはよう!"
      }
    )
  };

  UrlFetchApp.fetch("https://hooks.slack.com/services/XXXXXX(ここはコピペしています)", options);
}

自分で試したこと

プログラムは初心者で書き方が全くわからないです。
ネットに落ちてるのをコピペするのしかした事がないです・・・。

0

1Answer

プログラムは初心者で書き方が全くわからないです。

となると十分な回答になるとは思いませんが、指針程度に参考にしてください。

SlackのEvent APIがドキュメントに示される形式のJSONデータをPOSTしていると思うので、これを受け取って条件分岐するとよいかと思われます。

実際に試していないので全く信用できないですが、イメージとしては下記のように実現できるのではないかなと思ってます…。

function doPost(e) {
  // jsonデータ受け取る
  var json = JSON.parse(e.postData.contents);
  // botの投稿だった場合何もしないで終了
  if (json.event.item.user === 'ここにbotのuser_id') {
    return;
  }

  var options =
  {
    "method" : "post",
    "contentType" : "application/json",
    "payload" : JSON.stringify(
      {
        "text" : "おはよう!"
      }
    )
  };

  UrlFetchApp.fetch("https://hooks.slack.com/services/XXXXXX(ここはコピペしています)", options);
}

そもそもbotのuser_idが固定なのかとか、イベント設定の方で除外できたりしないかとか、いろいろ考えるところはありそうです。

0Like

Comments

  1. @kinako16

    Questioner

    ご丁寧にありがとうございます!

    いただきましたコードをコピペして実行しましたら、

    TypeError: Cannot read property 'postData' of undefined(行 3、ファイル「コード」)

    というエラーが出ました・・・。
    私でもエラー内容を検索したのですが内容が理解できず・・・(すみません;)


    「e.postData←これが undefinedということです。GASをそのまま実行していませんか?普通はJSONで相手から送られてくると思います」
    のような内容でしたがGASをそのまま実行というのがよく分からず、そのまま実行というのは三角の再生ボタンのようなものを押す事を言うのでしょうか…?

    JSONも何なのかが分からず調べたら「JSONとは「JavaScript Object Notation」の略で、「JavaScriptのオブジェクトの書き方を元にしたデータ定義方法」のことです。」とあったのですが何の事やら分からず…;

    プログラミングは無知で理解が追いつかずすみません;
    実践しながら覚えていく事をしてるので知らない単語を一個一個調べてみます。
  2. > TypeError: Cannot read property 'postData' of undefined(行 3、ファイル「コード」)
    e という変数がundefined(未定義)なのでエラーになってます。未定義なもののプロパティ(変数のようなもの)を読み取ろうとしてもそんなものはないので怒られてます。

    > JSONも何なのか
    決まった形式のあるテキストデータ、くらいの認識で今は大丈夫です。少量のデータを受け渡す際によく用います。

    > そのまま実行というのは三角の再生ボタンのようなものを押す事を言うのでしょうか…?
    そうですね。「コピペしてから実行しましたら」はGASのエディタ画面から三角ボタンを押して実行しましたか?もしそうであった場合該当のエラーが起きるのも自然です。
    実際に「おはよう」してみた場合の挙動はどうでしょうか?

    ちなみに、イベントを検知してbot投稿を行う、という流れはすでに実現していると思っているのですが、間違いないでしょうか?

    性質上、エラーのログを追うことが難しいので、骨が折れる作業かとは思いますが、また進捗を共有していただければ何か力になれるかもしれません。
  3. @kinako16

    Questioner

    再度ご丁寧にありがとうございます!!!(;_:)

    >実際に「おはよう」してみた場合の挙動はどうでしょうか?
    「公開」→「ウェブアプリケーションとして導入」→「Project version:」を「New」→「更新」をしてSlackで該当するチャンネルに「おはよう」と送信してもbotは反応しませんでした・・・;

    >イベントを検知してbot投稿を行う、という流れはすでに実現していると思っているのですが、間違いないでしょうか?
    この質問の最初に記載したコードで無限ループしてますが反応してますのでイベントを検知してbot投稿を行う流れはできていると思われます!
    (ちなみに、トリガーは「おはよう」のままでbotの返事を「Good Morning」にすると、当たり前ですが無限ループしないです。)


    >e という変数がundefined(未定義)なのでエラーになってます。
    「e」という変数が対応されてないとかですかね・・・?
  4. @kinako16

    Questioner

    【追記】
    例えば「ここにbotのuser_id」のuser idが間違ってるとこのエラーが出るとかありますでしょうか・・・?
    Slackを開いて左サイドバーの「App」の中にいるbotを右クリック>「アプリの詳細を開く」で下の方に薄いグレーで「メンバー ID : U0XXXXXX」と書いてある部分をコピペしました。
  5. > user idが間違ってるとこのエラーが出るとかありますでしょうか・・・?
    idが間違っていたらif文の中に入らずreturnされないため、イベントがあるごとに必ずメッセージ送信を試みる(=無限ループの危険)ことになりますが、エラーにはつながらないです。
    いろいろ試す段階では無限ループの起きないようにしたいので、できれば条件分岐のそれぞれで(トリガーワード以外の)別々のメッセージを出力するような形にしておくとよいです。

    > 「おはよう」と送信してもbotは反応しませんでした・・・;
    > 最初に記載したコードで無限ループしてますが反応してますのでイベントを検知してbot投稿を行う流れはできていると思われます!
    検知=>投稿が成功していて該当コードが応答なしということはエラーでコケていそうですね。
    推測ばかりで回答して余計に混乱させては元も子もないので、手元で再現を試みたのですが、ちょっとそちらの現状を把握できていなかったかもという感じです。
    というのは、参考にされたという記事にある"Incoming Webhooks","Outgoing Webhooks"などのカスタムインテグレーションはどうやら非推奨となったらしく、質問本文追記でEvent Subscriptionsの話をしていることから、質問者様もSlackのカスタムアプリを作成してその機能で送受信を実現している、と思い込んでいました。(以下参考です。この通りやれということではないです)
    https://qiita.com/risto24/items/342256f6ed6cb504059a
    しかし、そもそもキーワードトリガーの設定自体Event APIの方にはありませんでしたので、現状はおそらくカスタムインテグレーションのOutgoing Webhooksが働いているのかな、と推測しています。

    整理すると、問題としては無限ループすることで、私の提案する解決法は「トリガーが発生したときにプログラムに送られてくる情報からSlackメッセージの投稿ユーザーの情報を調べ、bot自身のメッセージには反応しないようプログラムで条件分岐する」ということでした。
    そしてそれがうまく行ってない問題としては、1.送られてくる情報の形式が不明 2.おそらくその受け取り方でエラーしてる の2点です。
    1.についてはドキュメントをあたるしかありませんので、プログラムへのPOSTがOutgoing WebhooksとEvent APIのどちらを使っているかで以下参考にしてください。(前者のような気がします)
    https://api.slack.com/legacy/custom-integrations/outgoing-webhooks#legacy-info__post-data
    https://api.slack.com/apis/connections/events-api#the-events-api__receiving-events
    2.については、実際にトリガーワードで実行させているとエラーなどが多分どこにも出ないので、プログラム内でダミーのデータを渡してやってプログラムが正しいか一つずつ検証してやったりとかですかね…。
    これまた推測になって申し訳ないのですが、仮定が正しかった場合3行目を消して5行目を以下のように直すと動くかもしれません。
    if (e.parameter.user_id === 'ここにbotのuser_id') {

    なかなかお力になれずすみません。

Your answer might help someone💌