Python Slack Bot无法并行处理事件:重复消息至添加反应求助
问题解决思路
你的核心问题是Flask默认单线程运行,导致事件处理被阻塞——当handle_message里执行time.sleep或循环逻辑时,整个服务会卡住,无法处理新的reaction_added事件。下面是修改后的代码,实现「收到特定消息后重复发送,直到有人给原消息点thumbs up」的需求:
from slack import WebClient import os import time from pathlib import Path from dotenv import load_dotenv from flask import Flask from slackeventsapi import SlackEventAdapter import threading # 新增多线程模块 env_path = Path('.') / '.env' load_dotenv(dotenv_path=env_path) app = Flask(__name__) slack_event_adapter = SlackEventAdapter( os.environ['SIGNING_SECRET'], '/slack/events', app) client = WebClient(token=os.environ['SLACK_TOKEN']) BOT_ID = client.api_call("auth.test")['user_id'] state = {} # 结构: {message_ts: {"channel_id": "...", "text": "...", "running": True}} def repeat_message(message_ts): """单独线程执行重复发消息的逻辑""" while state[message_ts]["running"]: channel_id = state[message_ts]["channel_id"] text = state[message_ts]["text"] client.chat_postMessage(channel=channel_id, text=text) time.sleep(5) # 每5秒发送一次 @slack_event_adapter.on('message') def handle_message(event_data): message = event_data.get('event', {}) channel_id = message.get('channel') user_id = message.get('user') text = message.get('text') message_ts = message.get('ts') if BOT_ID == user_id: return # 忽略机器人自身发送的消息 # 处理带红色圆圈的消息,启动重复发送线程 if text and text.startswith(":red_circle:"): # 初始化消息状态 state[message_ts] = { "channel_id": channel_id, "text": text, "running": True } # 启动独立线程执行循环,不阻塞主线程 threading.Thread(target=repeat_message, args=(message_ts,), daemon=True).start() # 保留其他消息逻辑 elif text and text.startswith(":large_yellow_circle:"): client.chat_postMessage(channel=channel_id, text="it's a yellow question!") elif text and text.startswith(":white_circle:"): client.chat_postMessage(channel=channel_id, text="it's a white question!") @slack_event_adapter.on('reaction_added') def reaction_added(event_data): reaction = event_data.get('event', {}) emoji = reaction.get('reaction') item = reaction.get('item', {}) message_ts = item.get('ts') channel_id = item.get('channel') # 检测是否是目标消息的thumbs up反应 if emoji == "thumbsup" and message_ts in state: state[message_ts]["running"] = False # 停止重复发送 client.chat_postMessage(channel=channel_id, text="已收到点赞,停止重复发送!") if __name__ == "__main__": app.run(debug=True)
关键改动说明
- 引入
threading模块:将重复发消息的逻辑放到独立线程中,主线程可以继续处理Slack的事件请求,避免阻塞。 - 优化
state结构:新增running字段,用来控制线程内的循环是否继续执行。 - 拆分循环逻辑:
repeat_message函数在单独线程中运行,直到对应的running被设为False。 - 事件解耦:处理消息时启动线程,处理反应时标记停止,两个事件互不干扰。
注意事项
- 确保Slack Bot拥有
chat:write(发送消息)、reactions:read(读取反应)权限。 - 线程设置
daemon=True:主程序退出时,线程会自动终止,避免残留后台进程。 - Slack反应标识:
thumbsup是标准点赞emoji的标识,若你的Slack环境使用其他标识,需对应修改。
内容的提问来源于stack exchange,提问作者Mirage24
相关产品推荐
相关产品推荐

