Vik*_*ini 24 python slack-api slack
我正在使用slack命令(python代码在此后运行),它工作正常,但这给出了错误
This slash command experienced a problem: 'Timeout was reached' (error detail provided only to team owning command).
怎么避免这个?
rco*_*oup 37
根据Slack 斜杠命令文档,您需要在3000毫秒(3秒)内响应.如果您的命令需要更长时间,则会Timeout was reached出现错误.您的代码显然不会停止运行,但用户将无法获得对其命令的任何响应.
如果您的命令可以即时访问数据,那么三秒钟就可以快速完成,但如果您正在调用外部API或执行复杂操作,则可能不够长.如果确实需要更长时间,请参阅文档的延迟响应和多个响应部分:
200马上回复一个回复,也许就是回事{'text': 'ok, got that'}response_url参数.做一个POST与你的后续消息网址:
Content-type 需要是 application/json{'text': 'all done :)'}根据文档,"您可以在用户调用的30分钟内响应用户最多5次命令".
小智 9
在我自己处理这个问题并将我的Flask应用程序托管在Heroku之后,我发现最简单的解决方案是使用线程.我按照这里的例子:https: //blog.miguelgrinberg.com/post/the-flask-mega-tutorial-part-xi-email-support
from threading import Thread
def backgroundworker(somedata,response_url):
# your task
payload = {"text":"your task is complete",
"username": "bot"}
requests.post(response_url,data=json.dumps(payload))
@app.route('/appmethodaddress',methods=['POST','GET'])
def receptionist():
response_url = request.form.get("response_url")
somedata = {}
thr = Thread(target=backgroundworker, args=[somedata,response_url])
thr.start()
return jsonify(message= "working on your request")
Run Code Online (Sandbox Code Playgroud)
所有缓慢繁重的工作都由该backgroundworker()功能执行.我的松弛命令指向https://myappaddress.com/appmethodaddress的其中receptionist()函数采用response_url接收到的时差信息的,并将其传递沿着任何其它任选的数据到backgroundworker().由于该过程现在被拆分,它只是立即将"working on your request"消息返回到Slack通道,并在完成后backgroundworker()发送第二条消息"your task is complete".
我也经常遇到这个错误:
"Darn - 斜杠命令不起作用(错误消息:)
Timeout was reached.在slash-command管理命令"
我在AWS Lambda上编写了Slack slash-command"bot",有时需要执行慢速操作(调用其他外部API等).在某些情况下,Lambda函数需要大于3秒的时间才会导致Timeout was reachedSlack出错.
我在这里找到了@ rcoup的优秀答案,并将其应用于AWS Lambda的上下文中.该错误不再出现.
我用两个独立的Lambda函数做到了这一点.一个是"调度员"或"接待员",它用"200 OK"迎接传入的Slack斜杠命令,并向用户返回简单的"Ok,got that"类型的消息.另一个是实际的"worker"Lambda函数,它以异步方式启动long-ish操作,并在response_url稍后将该操作的结果发布到Slack .
这是调度员/接待员Lambda函数:
def lambda_handler(event, context):
req_body = event['body']
try:
retval = {}
# the param_map contains the 'response_url' that the worker will need to post back to later
param_map = _formparams_to_dict(req_body)
# command_list is a sequence of strings in the slash command such as "slashcommand weather pune"
command_list = param_map['text'].split('+')
# publish SNS message to delegate the actual work to worker lambda function
message = {
"param_map": param_map,
"command_list": command_list
}
sns_response = sns_client.publish(
TopicArn=MY_SNS_TOPIC_ARN,
Message=json.dumps({'default': json.dumps(message)}),
MessageStructure='json'
)
retval['text'] = "Ok, working on your slash command ..."
except Exception as e:
retval['text'] = '[ERROR] {}'.format(str(e))
return retval
def _formparams_to_dict(req_body):
""" Converts the incoming form_params from Slack into a dictionary. """
retval = {}
for val in req_body.split('&'):
k, v = val.split('=')
retval[k] = v
return retval
Run Code Online (Sandbox Code Playgroud)
从上面可以看出,我没有直接从调度程序调用worker Lambda Function(尽管这是可能的).我选择使用AWS SNS发布工作人员接收和处理的消息.
基于此StackOverflow答案,这是更好的方法,因为它是非阻塞(异步)和可伸缩的.此外,使用SNS在AWS Lambda的上下文中分离这两个函数更容易,直接调用对于此用例来说更为棘手.
最后,这是我在工作人员Lambda函数中使用SNS事件的方法:
def lambda_handler(event, context):
message = json.loads(event['Records'][0]['Sns']['Message'])
param_map = message['param_map']
response_url = param_map['response_url']
command_list = message['command_list']
main_command = command_list[0].lower()
# process the command as you need to and finally post results to `response_url`
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
17238 次 |
| 最近记录: |