如何通过Python程序化触发Slack消息中Verify按钮的交互动作
问题说明
我当前的配置如下:
- 每小时会向
slack_channel_xyz频道发送一条消息 - 若该消息包含特定内容,Slack机器人会生成一条带有两个可点击选项(
Verify或Not Yet)的消息 - 原有预期工作流为人工点击两个按钮中的一个完成交互;当前人工点击按钮时回调功能运行完全符合预期,按钮可正常响应并向外部接收方提交内容
我当前遇到的需求是希望自动化该提交流程:在一天中的特定时段,需要通过外部Python进程点击/触发机器人自动回复消息中的Verify按钮。
我目前已经可以准确定位目标消息,可获取消息内容、block_id、action_id等元数据(出于隐私考虑对内容做了脱敏处理,示例如下):
{ "bot_id": "##########", "type": "message", "text": "ARBITRARY_TEXT", "user": "##########", "ts": "1657662557.465969", "app_id": "##########", "team": "##########", "bot_profile": { "id": "##########", "deleted": "False", "name": "BOT_NAME", "updated": 1649356972, "app_id": "#########", "icons": { "image_36": "IMAGE_URL_36", "image_48": "IMAGE_URL_48", "image_72": "IMAGE_URL_72" }, "team_id": "##########" }, "blocks": [ { "type": "section", "block_id": "mSliR", "text": { "type": "mrkdwn", "text": "text", "verbatim": "False" } }, { "type": "actions", "block_id": "blk_verify", "elements": [ { "type": "button", "action_id": "OS7gz", "text": { "type": "plain_text", "text": "Verify", "emoji": "True" }, "style": "primary", "value": "g_approve" }, { "type": "button", "action_id": "8nzm", "text": { "type": "plain_text", "text": "Not Yet", "emoji": "True" }, "style": "danger", "value": "FILE_URL" } ] } ] }
咨询问题:在已掌握上述可识别的消息参数的前提下,是否存在无需人工干预的程序化实现方式,能够触发点击Verify按钮对应的动作,达到和人类点击按钮完全一致的效果?
解决方案
完全可以实现,核心逻辑是直接模拟Slack交互事件的请求格式,向你配置的Slack按钮回调地址发送符合规则的POST请求即可,效果和人工点击完全一致,不需要模拟前端页面点击操作。
实现步骤
- 先获取人工点击的请求模板
- 临时把按钮的回调地址改成可抓包的测试地址(比如本地启动简易HTTP服务、使用webhook调试工具),手动点一次
Verify按钮,拿到Slack发来的完整POST请求体、请求头信息,记录token、team、channel、user字段规则,以及请求签名校验逻辑。
注意:如果你的Slack应用开启了请求签名校验,必须按照Slack的签名规则生成
X-Slack-Signature和X-Slack-Request-Timestamp请求头,否则回调服务会直接拒绝请求。 - 临时把按钮的回调地址改成可抓包的测试地址(比如本地启动简易HTTP服务、使用webhook调试工具),手动点一次
- 用Python构造匹配规则的请求
你已经拿到目标消息的ts、block_id、action_id、按钮value等参数,直接替换到抓包得到的请求模板中即可,核心代码示例:import time import hmac import hashlib import json import requests # 基础配置,替换为你自己的实际参数 SLACK_SIGNING_SECRET = "你的Slack应用签名密钥" CALLBACK_URL = "Slack交互请求的回调地址" CHANNEL_ID = "slack_channel_xyz对应的频道ID" TARGET_MESSAGE_TS = "定位到的目标消息ts,例如示例中的1657662557.465969" VERIFY_BLOCK_ID = "blk_verify" VERIFY_ACTION_ID = "OS7gz" VERIFY_BTN_VALUE = "g_approve" TRIGGER_USER_ID = "你自己的Slack用户ID,和手动点击时的user字段保持一致" TEAM_ID = "你的Slack团队ID" SLACK_APP_VERIFY_TOKEN = "你的Slack应用校验token" def generate_slack_signature(timestamp: str, request_body: str) -> str: sig_basestring = f"v0:{timestamp}:{request_body}".encode("utf-8") signing_secret = SLACK_SIGNING_SECRET.encode("utf-8") v0_signature = hmac.new(signing_secret, sig_basestring, hashlib.sha256).hexdigest() return f"v0={v0_signature}" def trigger_verify_action(): req_timestamp = str(int(time.time())) # 构造和手动点击完全一致的请求体 payload = { "type": "block_actions", "team": {"id": TEAM_ID}, "user": {"id": TRIGGER_USER_ID}, "channel": {"id": CHANNEL_ID}, "message": {"ts": TARGET_MESSAGE_TS}, "actions": [ { "action_id": VERIFY_ACTION_ID, "block_id": VERIFY_BLOCK_ID, "value": VERIFY_BTN_VALUE, "type": "button", "action_ts": str(time.time()) } ], "token": SLACK_APP_VERIFY_TOKEN } request_body = json.dumps(payload) headers = { "Content-Type": "application/json", "X-Slack-Request-Timestamp": req_timestamp, "X-Slack-Signature": generate_slack_signature(req_timestamp, request_body) } resp = requests.post(CALLBACK_URL, data=request_body, headers=headers) print(f"请求返回状态:{resp.status_code},返回内容:{resp.text}") if __name__ == "__main__": trigger_verify_action() - 配置定时触发
可以直接用系统自带的定时任务能力(Linux使用crontab、Windows使用任务计划程序),也可以在Python脚本中集成APScheduler库,在指定时段调用上面的trigger_verify_action函数即可。
注意事项
- Slack没有提供触发交互组件的公开API,不需要尝试调用官方公开接口模拟点击,直接向你自己的回调服务发匹配格式的请求是最稳定、和人工点击效果完全一致的方案。
- 构造请求时所有字段尽量和抓包得到的手动点击请求保持一致,不要遗漏必填字段,避免回调服务校验不通过。
- 如果你的回调服务配置了来源IP校验,把运行Python脚本的机器IP加入白名单即可。
内容的提问来源于stack exchange,提问作者Jonathan Boos
相关产品推荐
相关产品推荐

