Messir Astaroth
Messir Astaroth

Reputation: 11

Discord mass DM bot: 403 Forbidden

I created my mass DM bot for my discord to send everyone at once messages with the right information. But every time the bot tries to send DM to everyone on the server - I get 403 Forbidden error. I don't understand what is the problem, in Discord API or in my bot?

import disnake
from disnake.ext import commands
from disnake import Permissions

allowed_role_id = 725585509023350794

class DMCog(commands.Cog):
    @classmethod
    def setup(cls, bot, allowed_role_id):
        bot.add_cog(cls(bot, allowed_role_id))

    def __init__(self, bot, allowed_role_id):
        self.bot = bot
        self.allowed_role_id = allowed_role_id

    @commands.Cog.listener()
    async def on_message(self, message):
        try:
            if message.author.bot or message.author == self.bot.user:
                return

            if isinstance(message.channel, disnake.DMChannel):
                # Обработка сообщений в личных сообщениях
                recipients_names = ', '.join([recipient.display_name for recipient in message.channel.recipients])
                log_message = f"{message.author.display_name} ({message.author.id}) отправил сообщение в приватный канал с {recipients_names}: {message.content}"
                print(log_message)
                print(f"Получено личное сообщение от {message.author.name} ({message.author.id}): {message.content}")
            else:
                # Обработка сообщений на сервере
                allowed_role = message.guild.get_role(self.allowed_role_id)
                if allowed_role and allowed_role in message.author.roles:
                    log_message = f"{message.author.display_name} ({message.author.id}) отправил сообщение в #{message.channel.name} ({message.channel.id}): {message.content}"
                    print(log_message)
                else:
                    print(
                        f"Сообщение от {message.author.display_name} не отправлено из-за отсутствия необходимой роли.")
        except Exception as e:
            print(f"Произошла ошибка в on_message: {e}")

    @commands.command(name="send_dm")
    async def send_dm_command(self, ctx, member: disnake.Member, *, message: str):
        """
        Команда для отправки личного сообщения пользователю.
        Пример использования: !send_dm @username <message>
        """
        try:
            # Отправляем личное сообщение
            await member.send(message)

            await ctx.send(f"Личное сообщение отправлено пользователю {member.mention}.")
        except disnake.Forbidden:
            await ctx.send("Невозможно отправить личное сообщение. Возможно, у пользователя закрыты личные сообщения.")
        except Exception as e:
            await ctx.send(f"Произошла ошибка при отправке личного сообщения: {e}")

    @commands.command(name='mass_dm', aliases=['massdm'])
    async def mass_dm(self, ctx, *, message):
        try:
            success_count = 0
            failure_count = 0

            for member in ctx.guild.members:
                if member != ctx.author:
                    try:
                        await member.send(message)
                        success_count += 1
                        print(f"Отправлено сообщение {success_count} пользователю {member.display_name} ({member.id})")
                    except disnake.Forbidden:
                        failure_count += 1
                        print(
                            f"Ошибка 403 Forbidden: Невозможно отправить сообщение {failure_count} пользователю {member.display_name} ({member.id})")
                    except Exception as e:
                        failure_count += 1
                        print(
                            f"Произошла ошибка при отправке сообщения {failure_count} пользователю {member.display_name} ({member.id}): {e}")

            await ctx.send(
                f'Массовая рассылка завершена успешно. Отправлено: {success_count}, не отправлено из-за ошибок: {failure_count}')
        except Exception as e:
            await ctx.send(f'Произошла ошибка при массовой рассылке личных сообщений: {e}')


def setup(bot):
    DMCog.setup(bot, allowed_role_id)

I am trying to lower the amount of requests sent to Discord API atm, because I kinda feel that its the anti-ddos is getting triggered.

Update: I rebooted my router, got a new ip, added 'await asyncio.sleep(1)' after each request, and it's still getting "403 Forbidden" when !massdm command is being used. At the same time the bot is able to send messages to text channel on the server.

Upvotes: 1

Views: 235

Answers (1)

ThePenguin
ThePenguin

Reputation: 41

Look at https://discord.com/developers/docs/topics/rate-limits#global-rate-limit.

All bots can make up to 50 requests per second to our API. If no authorization header is provided, then the limit is applied to the IP address. This is independent of any individual rate limit on a route.

Error 403 means that the request you have sent to the server is understood but the server refuses to execute it.

If your bot is big enough you can ask for an increased rate limit by https://dis.gd/contact

I recommend changing your code so that it does DM's in groups less than 50 (maybe 45 to allow other API requests in the same second) and then waits 1 second before going to the next group so you don't get rate limited.

Hope this helped.

Edit: This is if you absolutely want to DM everyone in the server, if you can please use @everyone or create a channel for announcements.

Upvotes: 0

Related Questions