Ответы пользователя по тегу Discord
  • Очень странная ошибка в Discord.py связанная с "ctx"?

    Поярдковые аргументы со стандартными значениями могут находиться только перед такими же аргументами со стандартными значениями.

    def func(a, b: int = 0, c) - не работает, так как a, b и c являются порядковым аргументом.
    def func(a, b: int = 0, c = 0) - работает

    В вашем случае, если вы хотите чтобы аргумент member был опциональным, используйте typing.Optional:
    from typing import Optional
    
    ...
    
    @commands.command()
    async def cmd(ctx, member: Optional[discord.Member], count: int): ...
    Ответ написан
    Комментировать
  • Как правильно реализовать удаление сообщения через некоторое время?

    Используйте аргумент delete_after функции send.
    @client.command(aliases = ['очистить', 'клеар', 'clr' ,'клр'])
    @commands.has_permissions(administrator = True)
    async def clear( ctx, amount : int):
        await ctx.message.delete()
        await ctx.channel.purge(limit = amount)
        await ctx.send(embed = discord.Embed(description = f':white_check_mark: удалено {amount} сообщений(я)'), delete_after=5)
    Ответ написан
    1 комментарий
  • Почему не запускается бот на discord.py?

    Обновите библиотеку. Дискорд добавил два новых поля в API, что не было предусмотренно библиотекой. Это исправлено в версии 1.3.4.
    Подробнее: discord.py#5109
    Ответ написан
  • Discord.py как сделать глобальный чат?

    Через discord.utils.get вы получаете канал того сервера, в котором было написано сообщение.

    Он принадлежит тому серверу, в котором написано сообщение. Объект канала с таким же названием на других серверах будет другим.

    Следовательно: вам нужно искать канал на том сервере, на который сообщение отправляется
    GLOBAL_CHAT = 'глобальный-чат'  # PEP8: Названия констант пишутся капсом
    
    @client.event
    async def on_message(message):
        channel = discord.utils.get(message.guild.text_channels, name=GLOBAL_CHAT)
        if message.author.id == client.user.id:
            return  # return предотвратит выполнение следующего кода
        if message.channel.id != channel.id:
            return
        await message.delete()  # удаляем сообщение один раз
        for guild in client.guilds:
            if channel := discord.utils.get(guild.text_channels, name=GLOBAL_CHAT):
                # py3.8: walrus operator ("моржовый" оператор)
                # равносильно следующему:
                # channel = discord.utils.get(guild.text_channels, name=GLOBAL_CHAT)
                # if channel: ...
                try:
                    await channel.send('**{0.author}:** {0.content}'.format(message))
                except discord.Forbidden:
                    print(f"Невозможно отправить сообщение на сервер {guild.name}: Недостаточно прав")
                except discord.HTTPException as e:
                    print(f"Невозможно отправить сообщение на сервер {guild.name}: {e}")
    Ответ написан
    1 комментарий
  • Как сделать "раздельные команды" в discord.py?

    Для обычных "вложенных" команд используйте группы команд

    Впрочем, в ситуации в изложенной в вашем вопросе это не поможет.

    В вашей ситуации я вижу два варианта:
    1. Отказаться от встроенной команды help и создать свою, с методом группы команд
    bot.remove_command("help")
    
    @bot.group(invoke_without_command=True)
    async def help(ctx, ...):
        ...  # вручную построенная/собирающая команда help.
    
    @help.command()
    async def islam(ctx, ...):
        ...  # подкоманда help

    2. Просто использовать docstring в методе команды для вывода нужной информации
    @bot.command()
    async def islam(ctx):
        """Описание команды"""
        ...

    2.1 Так же можно использовать аргументы декоратора:
    @bot.command(
        help="Данный текст будет использоваться в полноразмерной помощи (help islam)", 
        brief="Данный текст будет отображаться в help рядом с командой", 
        usage="Данный текст будет отображаться вместо автоматического построенного текста для аргументов (таких как <arg> [arg] и т.д.)"
    )
    async def islam(ctx):
        ...
    Ответ написан
    Комментировать
  • Как перенаправлять сообщения от пользователи, в embed бота?

    Два варианта:
    1. То как предложил Александр, использовать параметры команды:
    @bot.command()
    async def report(ctx, user: discord.Membmer, *, reason: str):  # первый kwarg используется как "собирающий" аргумент
    # https://discordpy.readthedocs.io/en/v1.3.4/ext/commands/commands.html#keyword-only-arguments
        ...

    Команда в таком случае будет вызываться следующим образом: [p]report User#0000 Нарушение правила 42
    2. Ждать ответа:
    Для этого вам понадобиться ждать события сообщения:
    https://discordpy.readthedocs.io/en/v1.3.4/api.htm...
    from asyncio import TimeoutError as AsyncTimeoutError
    
    @bot.command()
    async def report(ctx):
        ...
        try:
            member = await bot.wait_for("message", check=lambda m: m.author == ctx.author, timeout = 60)  # Базовая проверка - будет ловить сообщения от пользователя запустившего команду везде.
        except AsyncTimeoutError:
            await ctx.send("Вы уснули, я ушёл")
            return
         # На данный момент переменная "member" является лишь строкой, и не факт что это реальный пользователь
         # Используем конвертер для перевода из строки в пользователя
         # https://discordpy.readthedocs.io/en/v1.3.4/ext/commands/api.html#discord.ext.commands.MemberConverter
         try:
             member = commands.MemberConverter().convert(ctx, member)
         except commands.BadArgument:
             await ctx.send("Это не пользователь, кого вы пытаетесь ~~на...~~ обмануть")
             return
          # и тоже самое для причины
    Ответ написан
    4 комментария
  • Как исправить то что не работает await и код выполняется дальше без данных с DB?

    Выполнение синхронного кода в пулах треда или процесса

    Как говорит import this:
    Simple is better than complex.

    Я чисто не вижу смысла во всех этих sync_to_asyncи прочих.
    database_sync_to_async вовсе не используется в данном коде.

    Используйте расширение discord.py называемое "commands". Оно идёт вместе с библиотекой и значительно упрощает жизнь при написании команд.
    Errors should never pass silently.
    Unless explicitly silenced.


    Переподключать бота при любой ошибке - смахивает на ОЧЕНЬ плохую идею.

    import asyncio
    import os
    from functools import partial
    
    import discord
    from discord.ext import commands
    from allauth.socialaccount.models import SocialAccount
    
    from main.models import Game, Purchase, Key
    
    
    bot = commands.Bot()
    
    
    @bot.event
    async def on_ready():
        print('We have logged in as {0.user}'.format(bot))
    
    @commands.command()
    async def hello(ctx):
        game = (await bot.loop.run_in_executor(None, Game.objects.all))[0]
        await ctx.send(game.name)
    
    @bot.event
    async def on_member_join(member):
        allAccounts = await bot.loop.run_in_executor(None, SocialAccount.objects.all)
        for acc in allAccounts:
            if acc.extra_data['id'] == str(member.id):
                account_id = acc.extra_data['id']
                purchases = await bot.loop.run_in_executor(None, partial(Key.objects.filter, user__id=account_id))
                keys = [await bot.loop.run_in_executor(None, partial(Key.objects.filter, purchase__id=purchase.id)) for purchase in purchases]
        for key in keys:
            role = discord.utils.get(member.guild.roles, id=key.cheat.ds_role_id)
            print(str(key.cheat.ds_role_id))
            await member.add_roles(role)
            break
    
    
    bot.run(os.environ.get('DS_BOT_TOKEN'))

    Возможно данный код вам чем-то поможет. Написано без учёта содержимого SocialAccount и main.models, поэтому код затрагивающий их остался примерно неизменным.
    Отступы так же были угаданы чисто по коду.
    Ответ написан
    2 комментария
  • Как сделать так, чтобы бот считал сообщения различных пользователей и выводил их отдельно?

    Использовать Counter из стандартной библиотеки collections: https://docs.python.org/3/library/collections.html...

    from collections import Counter
    
    ...
    
    msg_count = Counter()
    
    @client.event
    async def on_message(msg):
        if msg.author == client.user:
            return
        global msg_count
        msg_count[msg.author.id] += 1
        print(f"Message by {msg.author}: {msg.content}")
    
    ...
    Ответ написан
    Комментировать
  • Как установить статус игры в discord?

    Статус игры устанавливается через WebSocket'ы: https://discord.com/developers/docs/topics/gateway...
    Ответ написан
    Комментировать
  • Как определить кол-во различный реакций, которые находятся на последнем сообщении бота?

    Всё что в данном коде неверно:
    1. @Bot.event только у события добавления реакции. Декоратор события должен быть у всех событий.
    2. Аргумент self у событий есть только в модулях (cogs). И представляет собой сам модуль
    3. if Y > N: ... выполняется только один раз - при запуске файла. Необходимо сделать чтобы оно либо менялось при обновлении (получении/удалении реакции), либо непосредственно перед выводом результата
    4. Ключевой (kwarg) аргумент pass_context не существует в текущей версии discord.py. Контекст передаётся в функцию команды первым аргументом всегда (за исключением момента с нахождением команды в вышеупомянутом "модуле")
    5. Объект "сообщение" не итерируемый
    6. PEP8 Naming Conventions: "CamelCase" названия переменных обозначают classы.


    Один из вариантов решения:
    voting_message = None
    @Bot.command()
    @commands.has_permissions(administrator=True)
    async def startvote(ctx):
        embed = discord.Embed(...)  # embed goes here
        voting_message = await ctx.send(embed=embed)
    
    @Bot.command()
    @commands.has_permissions(administrator=True)
    async def endvote(ctx):
        msg = await bot.get_channel(voting_message.channel.id).fetch_message(voting_message.id)
        y = discord.utils.get(msg.reactions, emoji="\N{WHITE HEAVY CHECK MARK}").count
        n = discord.utils.get(msg.reactions, emoji="\N{CROSS MARK}").count
        if y>n:
            result = "Принято"
        elif y==n:
            result = "Отказано (да = нет)"
        else:
            result = "Отказано"
        emb = discord.Embed(title=f'Окончено голосование.', description = 'Результат: ' + result, colour=discord.Color.purple())
        return await ctx.send(embed=emb) # **Возвращаем** сообщение после отправки.
        y, n = 0, 0
    Ответ написан
    Комментировать
  • Как сделать проверку на роль?

    Проверять нужно на наличие объекта роли:
    @commands.command()
    async def role(ctx):
        role = ctx.bot.get_role(719997201283022879)  # Получаем объект роли по ID
        if role in ctx.author.roles:
            await ctx.send("\N{WHITE HEAVY CHECK MARK}"}  # ✅
        else:
            await ctx.send("\N{CROSS MARK}")  # ❌
    Ответ написан
    Комментировать
  • Discord.py bot ошибка роли?

    MissingRequiredArgument означает что команда не получила необходимый аргумент.

    Для команды написанной в вашем примере требуется указать пользователя.

    Примечание: [p] - префикс указанный для вашего бота
    [p]вип - вернет ошибку
    [p]вип DiscordTag#0000 - не вернет, в случае если пользователь с тегом DiscordTag#0000 существует на сервере

    Примечание: pass_context=True - устаревший кусок кода, на текущей версии Discord.py такого аргумента у конструктора команд нет, Context передаётся в команду всегда
    Примечание: await ctx.channel.purge(limit = 1) - я так предполагаю, этот участок кода вами используется для удаления сообщения с командой. Если это так, рекомендую заменить его на await ctx.message.delete() во избежание (возможного) "racing condition"

    Примечание
    Почему у меня создается ощущение, что где-то появился очень кривой русскоязычный туториал по ботам на discord.py?
    Кривой - потому что с упоминанием pass_context и purge для удаления сообщений автора
    Ответ написан
    Комментировать
  • Как сделать рассылку сообщений дискорд ботом?

    Просто используйте метод "send" на пользователе

    @commands.has_permissions(administrator = True)
    @client.command()
    async def unban(ctx, *):
        await ctx.message.delete() # Для удаления сообщения с командой, если в оригинале подразумевалось это
     
        banned_users = await ctx.guild.bans()
     
        for ban_entry in banned_users:
            user = ban_entry.user
            await ctx.guild.unban(user)
            await ctx.send(f"Добро пожаловать. Снова. {user.mention}")
            await user.send("Божество услышало твой зов, теперь снова можешь вернуться :3")


    Примечание: Бот сможет отправить сообщение пользователю только если с пользователем у бота есть общий сервер
    Примечание: "pass_context=True" - устаревший кусок кода, на текущей версии Discord.py такого аргумента у конструктора команд нет, Context передаётся в команду всегда
    Ответ написан
    Комментировать
  • Discord.ext.commands.errors.MissingRequiredArgument: users is a required argument that is missing, что делать?

    discord.ext.commands первым аргументом в команду всегда передает commands.Context.

    Вся суть расширения commands в отсутствии необходимости работы с обработкой сообщений и аргументов команд в них

    Сделайте переменную users глобальной.

    Например, объявив её после os.chdir(r'D:\Sublime Text 3\testbot-master'):
    users = {}

    В итоге, код команды должен выглядеть примерно так:
    @bot.command()
    async def Rank(ctx, user: discord.Member):
        experience = users[str(user.id)]['experience']
        lvl_start = users[str(user.id)]['level']
        lvl_end = int(experience ** (1/50))
        await ctx.send(':thumbsup: {}, Ваш уровень: {} :thumbsup:'.format(user.mention, lvl_end))
        users[str(user.id)]['level'] = lvl_end


    Ошибка MissingRequiredArgument будет возникать в случае, если введенной команде не хватает аргументов:
    !Rank вызовет в данном случае ошибку
    !Rank @DiscordTag#0000 - нет

    Если вам необходимо чтобы команда срабатывала без аргумента - сделайте его необязательным, задав стандартное значение, например "None" (не забудьте в данном случае обработать это самое None в коде самой команды):
    @bot.command()
    async def Rank(ctx, user: discord.Member = None):
        if not user:
            user = ctx.author
        ...


    А так же:
    В текущей версии discord.py аргумента pass_context у команд нет, аргумент контекста передается первым автоматически всегда

    from discord.ext.commands import Bot - неиспользуемый импорт в этом коде
    Ответ написан
    1 комментарий
  • Discord.ext.commands.errors.CommandInvokeError: Command raised an exception: KeyError: '293396418834464768', что делать?

    Ошибка KeyError означает что указанного ключа в указанном словаре не существует.

    Что делать?

    Обновить словарь, добавив необходимый ключ если его не существует:
    async def add_coins(users, user, coin):
        if str(user.id) not in users:
            users[str(user.id)]['coins'] = 0
        users[str(user.id)]['coins'] += coin
    Ответ написан
    1 комментарий
  • Как сделать так, чтобы бот упомянул роль?

    Заголовки полей в embed'ах Discord'а поддерживают не весь Markdown.
    nTMbPA2.png

    Вы можете поместить упоминание роли в значение поля (.addField("Field name", "<@&ROLEID>").

    Помните: Упоминания в embed'ах не работают. Даже если они будут кликабельны, они не будут никого призывать. Призывание упоминаниями работает только в теле сообщения (content)
    Ответ написан
  • Какой метод API переносит пользователя с канала на канал?

    Перемещение участников выполняется через редактирование участников ("Modify Guild Member"), а конкретно, через поле JSON "channel_id".

    Если Вы используете какую-либо библиотеку, смотрите её документацию, скорее всего там уже есть обёртка для данного метода. https://discordapp.com/developers/docs/topics/comm...
    Ответ написан
    Комментировать
  • Какие необходимо соблюсти условия для приглашения бота на сервер Discord?

    Для добавления бота на сервер, вы должны иметь права "Управление сервером" на данном сервере
    AQFYbWn.png

    У владельца сервера все права есть вне зависимости от ролей. Проверьте в тот ли аккаунт вы залогинены в браузере.
    Ответ написан
    Комментировать
  • Почему при mentions в сообщениях id пользователей отображаются с восклицательным знаком?

    Восклицательный знак добавляется, если у участника есть серверный никнейм. Подробнее о форматировании сообщений можно прочитать в документации API: https://discordapp.com/developers/docs/reference#m...
    Ответ написан
    Комментировать
  • Как упомянуть пользователя через discord.js в embed?

    Для создания упоминания достаточно преобразовать объект пользователя в строку.

    Вы так же можете построить уведомление вручную используя схему, <@80351110224678912> если пользователь не имеет установленного "серверного" никнейма, или <@!80351110224678912>, если никнейм установлен (по сути, не имеет никакой разницы на практике)

    Однако необходимо заметить: упоминания в теле embed'ов не работают:
    87Qedsk.png Для того что бы упоминание создало уведомление, необходимо чтобы упоминание находилось в теле сообщения
    Ответ написан
    Комментировать