EntchenEric
EntchenEric

Reputation: 386

discord.py send Message faster to multiple Channels

I am about to make a Global Chat bot and it works pretty good but since it is in 70 Servers, he really struggles with sending the Messages. At the moment my code to send the messages looks like this:

async def sendallchannel(self, embed):
for channel in fetchedchannel:
    try:
        await channel.send(embed = embed)
    except:
        pass

and as I just said, it take about 1 Minute till the Message is send to every Server. Is there a way to send the Messages faster?

the variable fetchedchannel is a list of every channel already fetched, so the Bot don't need to fetch every Channel one by one when he wants to send a Message

Upvotes: 2

Views: 1542

Answers (3)

Delta
Delta

Reputation: 370

I think this is the faster:

def _send_in_all_channels(ctx, embed):  # outside cog
  channels = ctx.guild.text_channels  # type: list[TextChannel]

  coroutines = (channel.send(embed=embed) for channel in channels)
  # types.Genetrator[typing.Awaitable[discord.Message], None, None]

  return asyncio.gather(*coroutines)  # type: typing.Awaitable

# usage in cog
@commands.command('big-send')
async def big_send(self, ctx, message: str):
  await _send_in_all_channels(ctx, discord.Embed(discerption=message))
  await ctx.send('done')

Upvotes: 0

FLAK-ZOSO
FLAK-ZOSO

Reputation: 4094

As I know, this is the fastest way:

@bot.command()
async def sendToAllChannels(ctx, *message):
    message = ' '.join(message)
    for guild in bot.guilds:
        for channel in guild.channels:
            await channel.send(message)

Notice that this way you are using a nested for loop, that obviously takes a lot of time, in particular when the outer loop (the one iterating over bot.guilds) is executed many times (you said 70, right?)


Since you only want to send messages to TextChannels, you can add this check:

if str(channel.type) == 'text':

EDIT: Since you already have a list of all the channels (fetchedchannel), assuming this list contains all the channels the bot can see, I would create a new list this way...

fetchedTextChannels = [channel for channel in fetchedchannel if str(channel.type) == 'text']

...in order to avoid the try/except block, once you know all the channel are of type 'text'.


Then, in order to make the messages not to wait each other, you should see the solution by @Loic that suggests you to use asynchronous coroutines, and will make everything much faster.

Upvotes: 0

Loïc
Loïc

Reputation: 11943

This should be much faster as all coroutines will be ran concurrently :

async def sendallchannel(self, embed):
  coroutines = [channel.send(embed=embed) for channel in fetchedchannel]   
  await asyncio.gather(*coroutines)

Upvotes: 4

Related Questions