Home > other >  Send Discord messages from Tkinter GUI via discord.py
Send Discord messages from Tkinter GUI via discord.py

Time:06-27

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'))

  • Related