英文:
I'm creating a Slackbot in Python and want to repeat the message until a reaction is added to that message. What am I doing wrong?
问题
如标题所述,我正在用Python编写Slack机器人,并使用NGROK在本地进行托管。我对装饰器不是很熟悉,我可以让机器人在Slack中发布消息,但似乎无法同时处理两个事件。例如,我想处理一条消息,并希望该消息在Slack中重复显示,直到给该消息添加了一个大拇指的反应为止。问题是我无法弄清楚如何在另一个事件仍在运行时处理事件,请参阅以下代码:
英文:
as the title states, I'm writing a Slack Bot in Python and using NGROK to host it locally. I'm not super experienced with decorators, and I can get the bot posting messages in slack, however I can't seem to handle two events at once. For example, I want to handle a message and have the message keep repeating in slack until a thumbs up reaction is added to that message. The issue is I cannot figure out how to handle an event while another event is still running, please see the following code:
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)
I can handle individual events, but I cannot handle them while another is running. Please help!
答案1
得分: 0
Flask 是一个同步的网络框架。
当它运行视图处理程序时,它会使用一个网络工作线程。如果你执行类似 time.sleep(...) 的操作,那个工作线程仍然会被占用,并且直到睡眠结束前不会可用于处理其他请求。
这里有几个选项可供选择。
你可以使用 Bolt for Python,这是一个原生支持异步事件处理的 Python Slack 库。不要使用 time.sleep(),而是可以使用 await asyncio.sleep(...)
,这会将线程返回到异步循环,并允许工作线程处理其他事件。
如果你已经有一个现有的 Slack 应用,并且不想重写整个代码库以适应 Bolt,那么你需要自己处理事件处理。你可以通过在 ThreadLoopExecutor 中进行操作,或者构建自己的异步事件队列机制,或者使用 Celery。或者如果你的 Slack 机器人工作量非常低,你可能只需添加更多的网络工作者,并希望最好不要耗尽工作者。
英文:
Flask is a synchronous web framework.
When it's running a view handler, it uses up a web worker thread. If you does something like time.sleep(...), that worker thread will still be occupied and unavailable to handle other requests until the sleep finishes.
There are a couple options you can do here.
You can use Bolt for Python, which is a Python Slack library that natively support asynchronous even processing. Instead of time.sleep(), you can do await asyncio.sleep(...)
, which returns the thread to the async loop, and allow the worker thread to process other events.
If you already have an existing slack application and don't want to rewrite your entire codebase to Bolt, then you'll need to handle the event processing yourself. You can do this by doing your work in an ThreadLoopExecutor, or by building your own async event Queue mechanism, or use Celery. Or if your slack bot has very low volume, you can probably just add more web workers, and hope for the best that you don't run out of workers.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论