как говорится в заголовке, я пишу Slack Bot на Python и использую NGROK для его локального размещения. У меня нет большого опыта работы с декораторами, и я могу заставить бота публиковать сообщения в slack, однако я не могу обрабатывать два события одновременно. Например, я хочу обработать сообщение и повторять его в спящем режиме до тех пор, пока к этому сообщению не будет добавлена реакция "большой палец вверх". Проблема в том, что я не могу понять, как обрабатывать событие, пока другое событие все еще выполняется, см. следующий код:
rom slack import WebClient
import os
import time
from pathlib import Path
from dotenv import load_dotenv
from flask import Flask
from slackeventsapi import SlackEventAdapter
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 = {}
@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')
messageid = message.get('ts')
state[messageid] = {"channel_id": channel_id, "user_id": user_id, "text": text}
if BOT_ID != user_id:
if text[0:12] == ":red_circle:":
time.sleep(5)
client.chat_postMessage(channel=channel_id, text=text)
if text[0:21] == ":large_yellow_circle:":
client.chat_postMessage(channel=channel_id, text = "it's a yellow question!")
if text[0:14] == ":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')
emoji_id = reaction.get('item',{}).get('ts')
emoji_channel_id = reaction.get('item',{}).get('channel')
client.chat_postMessage(channel=emoji_channel_id, text=emoji)
for message_id, message_data in state.items():
channel_id = message_data["channel_id"]
text = message_data["text"]
client.chat_postMessage(channel=channel_id, text=text)
print(message_id,message_data)
if __name__ == "__main__":
app.run(debug=True)
Я могу обрабатывать отдельные события, но я не могу обрабатывать их, пока выполняется другое. Пожалуйста помоги! :)
Flask — это синхронный веб-фреймворк.
Когда он запускает обработчик представления, он использует рабочий веб-поток. Если вы сделаете что-то вроде time.sleep(...), этот рабочий поток все еще будет занят и недоступен для обработки других запросов, пока не завершится сон.
Есть несколько вариантов, которые вы можете сделать здесь.
Вы можете использовать Bolt для Python, библиотеку Python Slack, изначально поддерживающую асинхронную равномерную обработку. Вместо time.sleep() вы можете использовать await asyncio.sleep(...)
, которая возвращает поток в асинхронный цикл и позволяет рабочему потоку обрабатывать другие события.
Если у вас уже есть слабое приложение и вы не хотите переписывать всю свою кодовую базу в Bolt, вам придется самостоятельно обрабатывать события. Вы можете сделать это, выполнив свою работу в ThreadLoopExecutor, создав собственный механизм очереди асинхронных событий или используя Celery. Или, если ваш слабый бот имеет очень низкий объем, вы, вероятно, можете просто добавить больше веб-воркеров и надеяться на лучшее, что у вас не закончатся рабочие.
Довольно технично, но спасибо, что разобрали это для меня.