为什么我不能通过函数 Discord.py 发送消息?
Why can I not send a message via Discord.py from a function?
我创建了一个脚本,它接收格式为 !notice [MM/DD/YY HH:mm], message, target
的消息,然后使用 threading.Timer
调用一个函数,以在 UTC 消息中给出的时间调用它。
我在从该函数发送消息时遇到问题,无论消息输入如何,我似乎都无法从该函数发送消息。
见下文:
import discord
import asyncio
from datetime import *
import threading
client = discord.Client()
@client.event
async def on_message(message):
if message.content[:7].lower() == "!notice".lower():
try:
notice = [datetime.strptime(message.content[message.content.find("[")+1:message.content.find("]")], "%m/%d/%y %H:%M"), message.content.split(", ")[1], message.content.split(", ")[2]]
await client.send_message(message.channel, 'Created notice "'+notice[1]+'" to be sent to '+notice[2]+' at '+str(notice[0])+' UTC.')
threading.Timer((notice[0] - datetime.utcnow()).total_seconds(), lambda a=notice[1], b=notice[2]: func(a, b)).start()
print(str((notice[0] - datetime.utcnow()).total_seconds())+" seconds until message is sent")
except (ValueError, IndexError):
await client.send_message(message.channel, 'Incorrect Notice Format.\nMust be "!notice [MM/DD/YY HH:mm], Notice contents, Target".\nEG: "!notice [01/01/2017 12:00], This is a notice, Siren Raid Team".')
def func(message, target):
print("Func called")
for i in client.servers:
for c in i.channels:
client.send_message(c, target+message)
client.run(MY_SESSION_KEY)
这 returns "Func called"
所以我知道正在调用该函数,但没有引发异常,也没有在我的聊天中发布消息。
我还尝试将 func
替换为:
async def func(message, target):
print("Func called")
for i in client.servers:
for c in i.channels:
await client.send_message(c, target+message)
但是这会引发异常:
RuntimeWarning: coroutine 'func' was never awaited
坦率地说,我在这里无法理解。为什么这不起作用?
我在网上看到asyncio
不是线程安全的。但是,除非我误解了,否则我的第一个示例没有在函数中使用该库。是否仍然存在问题?
discord.py的discord.Client.send_message
is a coroutine and must be awaited
, like you did in your second code snippet. However, threading.Timer
不支持协程。
您正在寻找的是 create_task
,它使您能够 运行 事件循环中的协程。由于协程所做的大部分工作是休眠(模仿 threading.Timer
),如果您使用 asyncio.sleep
而不是 time.sleep
,您的 on_message
将继续进行 运行 -后者阻止事件循环。这是一个示例,包括将参数传递给函数:
import asyncio
loop = asyncio.get_event_loop()
async def sleep_and_add(a, b):
await asyncio.sleep(3)
print(a, '+', b, 'is', a + b)
async def on_message():
# prepare arguments to your function
loop.create_task(sleep_and_add(2, 3))
# continue doing other things
以防有人需要帮助从 flask 函数内部向服务器发送消息。在进入异步和线程的兔子洞之后,我自己花了几个小时解决这个问题。事实证明比我想象的要容易得多。 Webhooks 与常规的 Discord 机器人不同,它是完全同步的,这意味着它们可以 运行 在 flask 中正常运行。
如果您的目标只是简单地从 Flask 端点向通道发送消息而不使用任何其他功能,请尝试 Webhooks。
from discord import Webhook, RequestsWebhookAdapter
webhook = Webhook.partial(WEB_HOOK_ID, 'WEB_HOOK_TOKEN', adapter=RequestsWebhookAdapter())
然后 post 消息
webhook.send('MESSAGE', username='WEBHOOK_BOT')
我创建了一个脚本,它接收格式为 !notice [MM/DD/YY HH:mm], message, target
的消息,然后使用 threading.Timer
调用一个函数,以在 UTC 消息中给出的时间调用它。
我在从该函数发送消息时遇到问题,无论消息输入如何,我似乎都无法从该函数发送消息。
见下文:
import discord
import asyncio
from datetime import *
import threading
client = discord.Client()
@client.event
async def on_message(message):
if message.content[:7].lower() == "!notice".lower():
try:
notice = [datetime.strptime(message.content[message.content.find("[")+1:message.content.find("]")], "%m/%d/%y %H:%M"), message.content.split(", ")[1], message.content.split(", ")[2]]
await client.send_message(message.channel, 'Created notice "'+notice[1]+'" to be sent to '+notice[2]+' at '+str(notice[0])+' UTC.')
threading.Timer((notice[0] - datetime.utcnow()).total_seconds(), lambda a=notice[1], b=notice[2]: func(a, b)).start()
print(str((notice[0] - datetime.utcnow()).total_seconds())+" seconds until message is sent")
except (ValueError, IndexError):
await client.send_message(message.channel, 'Incorrect Notice Format.\nMust be "!notice [MM/DD/YY HH:mm], Notice contents, Target".\nEG: "!notice [01/01/2017 12:00], This is a notice, Siren Raid Team".')
def func(message, target):
print("Func called")
for i in client.servers:
for c in i.channels:
client.send_message(c, target+message)
client.run(MY_SESSION_KEY)
这 returns "Func called"
所以我知道正在调用该函数,但没有引发异常,也没有在我的聊天中发布消息。
我还尝试将 func
替换为:
async def func(message, target):
print("Func called")
for i in client.servers:
for c in i.channels:
await client.send_message(c, target+message)
但是这会引发异常:
RuntimeWarning: coroutine 'func' was never awaited
坦率地说,我在这里无法理解。为什么这不起作用?
我在网上看到asyncio
不是线程安全的。但是,除非我误解了,否则我的第一个示例没有在函数中使用该库。是否仍然存在问题?
discord.py的discord.Client.send_message
is a coroutine and must be awaited
, like you did in your second code snippet. However, threading.Timer
不支持协程。
您正在寻找的是 create_task
,它使您能够 运行 事件循环中的协程。由于协程所做的大部分工作是休眠(模仿 threading.Timer
),如果您使用 asyncio.sleep
而不是 time.sleep
,您的 on_message
将继续进行 运行 -后者阻止事件循环。这是一个示例,包括将参数传递给函数:
import asyncio
loop = asyncio.get_event_loop()
async def sleep_and_add(a, b):
await asyncio.sleep(3)
print(a, '+', b, 'is', a + b)
async def on_message():
# prepare arguments to your function
loop.create_task(sleep_and_add(2, 3))
# continue doing other things
以防有人需要帮助从 flask 函数内部向服务器发送消息。在进入异步和线程的兔子洞之后,我自己花了几个小时解决这个问题。事实证明比我想象的要容易得多。 Webhooks 与常规的 Discord 机器人不同,它是完全同步的,这意味着它们可以 运行 在 flask 中正常运行。
如果您的目标只是简单地从 Flask 端点向通道发送消息而不使用任何其他功能,请尝试 Webhooks。
from discord import Webhook, RequestsWebhookAdapter
webhook = Webhook.partial(WEB_HOOK_ID, 'WEB_HOOK_TOKEN', adapter=RequestsWebhookAdapter())
然后 post 消息
webhook.send('MESSAGE', username='WEBHOOK_BOT')