I am trying to use the discord.py library to send messages to a channel using it's name.
This library is asynchronous and I have problems with sending more than 1 message. when I try to send a message afer the send
function has already been called, I get this
Task exception was never retrieved
future: <Task finished name='Task-13' coro=<send() done, defined at C:\Users\paula\DiscordBot\Bot.py:65> exception=RuntimeError('cannot reuse already awaited coroutine')>
RuntimeError: cannot reuse already awaited coroutine
the send function :
async def send():
global en_message, en_ChannelName
guild = client.get_guild(some_guild_ID_you_want)
for channel in guild.channels:
if en_ChannelName.get().lower() in channel.name.lower() and type(channel) == discord.channel.TextChannel and en_ChannelName.get() != "":
await channel.send(en_message.get())
break
the code it is called by :
bt_Send = tk.Button(text="Send", command=partial(client.loop.create_task, send()))
I also have to mention that the discord client is running on a non-main thread (the code :
thread_runBot = t.Thread(target=partial(client.run, botToken))
thread_runBot.start()
TK_dialog.mainloop()
)
CodePudding user response:
As the error states, you can't use a coroutine twice.
There's a way to get around this though. You can create a class with a custom __call__
that changes the behavior when it tries to be called.
class CoroutineCaller:
def __call__(*args, **kwargs):
# you can also use `asyncio.get_event_loop().create_task` if this doesn't work
client.loop.create_task(send(*args, **kwargs))
sender = CoroutineCaller()
When you do sender()
, it will create a new coroutine and add it to the client loop.
You can then do something like this:
bt_Send = tk.Button(text="Send", command=sender)
Here's an updated version that lets you call any coroutine multiple times.
class CoroutineCaller:
def __call__(coro, *args, **kwargs):
client.loop.create_task(coro(*args, **kwargs))
You can call this like caller(ctx.send, 'random message', embed=discord.Embed(title='test'))