【问题标题】:How to return both immediate and delayed response to slack slash command?如何返回对 slack slash 命令的即时和延迟响应?
【发布时间】:2017-10-05 07:30:21
【问题描述】:

我正在尝试使用hook.io microservice 来制作一个斜杠命令机器人。根据docs,我应该能够立即发送回复,然后再发送单独的 POST。但我无法立即得到响应,而后来的 POST 都可以正常工作。

这是我的测试代码。

module['exports'] = function testbot(hook) {

var request = require('request');
// The parameters passed in via the slash command POST request.
var params = hook.params;

data = {
    "response_type": "ephemeral",
    "text": "Immediate Response"
}
hook.res.setHeader('Content-Type', 'application/json');
console.log("returning immediate response")
hook.res.write(JSON.stringify(data), 'utf8', delay(params));
//calling end() here sends the immediate response but the POST never happens.
// but if end() is called below instead slack gives a timeout error but the POST succeeds.
//hook.res.end()

//test with 3.5 second delay
function delay(params) {
    setTimeout(function () {post_response(params)},3500);
}

function post_response(params) {

    console.log("posting delayed response")
    // Set up the options for the HTTP request.
    var options = {
        // Use the Webhook URL from the Slack Incoming Webhooks integration.
        uri: params.response_url,
        method: 'POST',
        // Slack expects a JSON payload with a "text" property.
        json: {"response_type":"in_channel", "text":"Delayed response","parse":"full"}
    };


    // Make the POST request to the Slack incoming webhook.
    request(options, function (error, response, body) {
        // Pass error back to client if request endpoint can't be reached.
        if (error) {
            console.log(error);
            hook.res.end(error.message);
        } else {
            console.log("post OK");
        }
        // calling end() here sends the POST but the immediate response is lost to a slack timeout error.
        hook.res.end()
    })
};
}

正如 cmets 中详述的那样,提前调用 res.end() 意味着立即发送响应,但 POST 永远不会发生,而将 res.end() 延迟到 POST 之后意味着发送延迟响应,但它会从期间松懈。

我是 javascript 新手,所以希望有一个我忽略的简单解决方案。

【问题讨论】:

  • 为什么要延迟 3.5 秒开始?根据 slack 文档,如果您等待超过 3 秒的响应时间,slack 会抛出超时错误。
  • 您似乎将delay 函数作为参数传递给hook.res.write。这是不对的,因为hook.res.write 不接受回调参数。
  • @Marak- 3.5 秒故意超过了松弛超时。我的目标是找到一种立即响应的方法,然后继续在后台处理数据并将结果作为单独的事务发布回来。上面显示的代码按描述工作(post_response 在 3.5 秒后成功完成)所以我对你声称 hook.res.write() 不接受回调有点困惑。
  • hook.res.write 不接受回调,由于 JavaScript 的工作方式,delay 方法将立即执行。无法在后台处理结果或进行单独的交易。您必须在 3 秒内回复 Slack。如果您必须使用延迟响应 API(您不应该),您可能必须将响应 URL 存储在数据存储中以供以后使用。最好尝试立即回复。

标签: node.js slack hook.io


【解决方案1】:

一旦您在 hook.io 中调用 res.end(),脚本将立即中止并结束处理。这相当于调用process.exit。如果你未能结束请求,hook.io 最终会点击它自己的Time-out Limit

hook.io 应该能够在 Slack 要求的三秒内响应 Slack。

这里有一个可能会有所帮助的指南:Making a Custom Slack Slash Command with hook.io

【讨论】:

  • 谢谢@Marak-这就是我的怀疑。看起来 hook.io 虽然是一个很棒的产品,但并不适合这个应用程序,因为它涉及的数据库查找有时需要比松弛超时更长的时间。初步迹象表明webtask.io/docs/model“自定义编程模型”可能更适合这种情况。
  • webtask API 将以几乎完全相同的方式工作。我认为除非您立即响应 slack 并将 Slack URL 存储在 hook.io 数据存储或 webtask 存储中,否则您将无法找到解决方案。
【解决方案2】:

我知道回答自己的问题的形式不好,但以下内容对我使用 webtask 有效,因此我将其包含在此处以防其他人发现它有用。

var express = require('express');
var Webtask    = require('webtask-tools');
var bodyParser = require('body-parser');
var request = require('request');
var app = express();

app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());

//visiting above url in browser is handled by get
app.get('/', function (req, res) {
    console.log(req.query)
    res.send('OK');
});

//post from slack handled here
app.post('/', function (req, res) {
    var params = req.body;
    console.log(params);
    var data = {
        "response_type": "ephemeral",
        "text": "Immediate Response"
    }
    res.setHeader('Content-Type', 'application/json');
    res.send(data);
    // deliberate delay longer than Slack timeout
    // in order to test delayed response.
    setTimeout(function () { post_response(params) }, 3500);
});

function post_response(params) {

    console.log("posting delayed response")
    // Set up the options for the HTTP request.
    var options = {
        // Use the Webhook URL supplied by the slack request.
        uri: params.response_url,
        method: 'POST',
        // Slack expects a JSON payload with a "text" property.
        json: { "response_type": "in_channel", "text": "Delayed response", "parse": "full" }
    };


    // Make the POST request to the Slack incoming webhook.
    request(options, function (error, response, body) {
        if (error) {
            console.log(error);
        } else {
            console.log("post OK");
        }
    })
};
module.exports = Webtask.fromExpress(app);

【讨论】:

  • 谢谢。根据他们的文档,我现在可以看到 webtask 将在响应结束后保持脚本运行长达 30 秒。我会调查,但我们应该能够在 hook.io 上做同样的事情,以便在初始响应后进行后期处理。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-12-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多