使用Python Flask与Slack API处理交互式消息按钮点击的问题
解决方案:Slack应用临时消息交互与OAuth授权问题处理
问题1:获取原消息内容并发送
临时消息的交互payload本身不携带原消息,但你可以在第一次发送临时消息时,把原消息内容嵌入到按钮的value字段中,这样点击Confirm时就能从payload里拿到原消息。
修改步骤:
- 命令处理端点(用户发送命令时触发):捕获用户输入的原消息,发送带自定义
value的临时消息
@app.route('/slack/command/', methods=['POST']) def handle_command(): # 拿到用户输入的原消息内容 original_text = request.form['text'] user_id = request.form['user_id'] channel_id = request.form['channel_id'] # 发送带Confirm/Cancel按钮的临时消息 client.chat_postEphemeral( channel=channel_id, user=user_id, text="确认发送这条消息吗?", attachments=[ { "actions": [ { "name": "confirm", "text": "Confirm", "type": "button", "value": original_text # 把原消息存到按钮的value里 }, { "name": "cancel", "text": "Cancel", "type": "button", "value": "cancel" } ] } ] ) return "", 200
- 交互处理端点:从payload的
actions[0]['value']取出原消息,执行发送/删除操作
payload = request.form["payload"] payload = json.loads(payload) if payload['type'] == 'interactive_message': action = payload['actions'][0]['name'] original_message = payload['actions'][0]['value'] channel_id = payload['channel']['id'] message_ts = payload['message_ts'] if action == 'confirm': # 发送原消息到目标频道 client.chat_postMessage(channel=channel_id, text=original_message) elif action == 'cancel': # 删除临时消息 client.chat_delete(channel=channel_id, ts=message_ts)
问题2:OAuth2授权与API调用权限修复
你的授权端点逻辑有误,且不需要每次发消息都调用授权接口——授权只在用户首次安装应用时执行一次,之后用存储的token调用API即可。
修改步骤:
- 修复授权端点:用户安装应用时,Slack会以GET请求将
code参数传到你设置的回调URL,而非POST payload
@app.route('/slack/authorize/', methods=['GET']) def get_auth_token(): code = request.args.get('code') if not code: return "缺少授权code", 400 # 调用oauth_v2_access换取bot token(优先用bot token发消息) result = client.oauth_v2_access( client_id=CLIENT_ID, client_secret=SIGNING_SECRET, code=code, redirect_uri="你的授权回调URL" # 必须与Slack应用后台设置的一致 ) # 把bot_token存入数据库(比如Redis/SQLite),后续调用API时取出使用 bot_token = result['bot_token'] # 示例存储逻辑:save_token_to_db(team_id=result['team']['id'], token=bot_token) return "授权成功", 200
- 调用API时使用存储的token:从数据库取出对应团队的bot_token,传入
chat_postMessage
# 从数据库取出当前团队的bot token bot_token = get_token_from_db(team_id=payload['team']['id']) # 发送消息时指定token client.chat_postMessage( channel=channel_id, text=original_message, token=bot_token )
问题3:满足3秒内响应要求
Slack要求交互端点必须在3秒内返回200响应,否则会提示错误。可以用异步线程处理后续的消息发送/删除操作,先立刻返回确认响应:
import threading def process_action(action, original_message, channel_id, message_ts, bot_token): if action == 'confirm': client.chat_postMessage(channel=channel_id, text=original_message, token=bot_token) elif action == 'cancel': client.chat_delete(channel=channel_id, ts=message_ts, token=bot_token) # 在交互处理端点中 payload = json.loads(request.form["payload"]) action = payload['actions'][0]['name'] original_message = payload['actions'][0]['value'] channel_id = payload['channel']['id'] message_ts = payload['message_ts'] bot_token = get_token_from_db(payload['team']['id']) # 启动线程处理业务逻辑,立刻返回200 threading.Thread( target=process_action, args=(action, original_message, channel_id, message_ts, bot_token) ).start() return "", 200 # 必须在3秒内返回
内容的提问来源于stack exchange,提问作者Priyanka
相关产品推荐
相关产品推荐

