You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.01 17:15:43