Ответы пользователя по тегу Боты
  • Как сделать так чтобы дискорд бот воспринимал команду из 2х слов?

    Используйте группы.
    @bot.group()
    async def clear(ctx):
        """Строка помощи к [p]clear"""
        ...
    
    @clear.command(name="all")
    async def _all(ctx):
        """Строка помощи для [p]clear all"""
        ...
    Ответ написан
    Комментировать
  • При вводе команды бот отправляет 2 сообщения. Как решить?

    У вас метод обработки команд (process_commands) в on_message вызывается дважды
    Ответ написан
    Комментировать
  • Как сделать так, чтобы бот пинговал случайного человека?

    from random import choice
    
    await ctx.send(choice(ctx.guild.members).mention)
    Ответ написан
    Комментировать
  • Discord py не работает help, почему?

    Аргумент arg у вас не имеет стандартного значения. Аргументы без стандартного значения считаются обязательными аргументами.

    Добавьте стандартное значение аргумента или сделайте аргумент типа Optional.

    @bot.command()  # pass_context НЕ существует в текущей версии discord.py: https://discordpy.readthedocs.io/en/v1.4.1/migrating.html#context-changes
    async def help(ctx, arg = None):
        emb = discord.Embed(title = 'Помощь', colour = 0x2e2d2d)
    
        if arg == 'poll':
            emb.add_field(name = f"{ctx.prefix}poll", value = f"Использовать:\nder poll (название голосования), (первый параметр), (второй параметр), (и так до 9 раз)\nПример создания голосования:\npoll test, 1, 2")
            await ctx.send(embed = emb)
    
        else:
            emb.add_field(name = f"{ctx.prefix}poll", value = f"Создание голосовния.")
            await ctx.send(embed = emb)


    или

    from typing import Optional
    
    @commands.command()
    async def cmd(ctx, arg: Optional[str]): ...
    Ответ написан
    Комментировать
  • Выдача прав доступа?

    Две основные проблемы:
    1. Переменная guild не определена. В данном случае Вы, скорее всего, хотите получить её из контекста - ctx.guild
    2. Guild.voice_channels и Guild.text_channels - "списки" (list) с каналами соответствующего типа. Списки не имеют атрибута set_permissions. Данный атрибут есть у каналов в списке. Для установки прав для каждого канала нужно данный список итерировать.


    @client.command()
    async def set_permissions(сtx, role: discord.Role):
        for textchannel in ctx.guild.text_channels:
            await alltext.set_permissions(
                role,
                read_messages=True,
                send_messages=True,
                manage_channels=True,
                manage_roles=True,
            )
        for voicechannel in ctx.guild.voice_channels:
            await allvoice.set_permissions(
                role, connect=True, manage_channels=True, manage_roles=True
            )
        await ctx.send(
            f"{ctx.author.mention}, вы успешно установили {role.mention} права доступа во всех текстовых/голосовых каналах"
        )
    Ответ написан
    Комментировать
  • Как сделать так, что бы event работал на одном сервере?

    Получайте сервер из объекта сообщения: discord.Message.guild

    if message.guild.id != 282480459897027773:
        return
    Ответ написан
    Комментировать
  • Как узнать всех пользователей которые поставили реакцию на выбранное сообщение в discord.py?

    Атрибут который вам нужен называется Message.reactions. discord.Reaction - тип возвращаемых объектов в reactions.

    discord.Message.reactions

    @bot.command()
    async def start(ctx):
        mess = await channel.send('Набор в игру')
        await asyncio.sleep(10)
        mess = await ctx.channel.fetch_message(mess.id)
        if yes_react := discord.utils.get(mess.reactions, emoji=ctx.guild.get_emoji(471483388532742130)):
            async for user in yes_react.users:
                print(str(user))  # выведет всех пользователей поставивших реакцию в консоль
    Ответ написан
    Комментировать
  • Почему не работает бот для Discord?

    Декоратор bot.event используется только для событий.

    Для команд необходим декоратор @bot.command() или @commands.command() в модулях.

    А так же: Сравнение текущей даты с датой рождения - некорректно. Дата с текущим годом != дате с годом рождения.

    from datetime import date
    
    import discord
    from datetime import date
    
    
    @bot.command()
    async def bdays4(ctx):
        cur_year = date.today().year
        bdays = {
            "Kenshi": date(day=12, month=8, year=1997),
            "Broody": date(day=11, month=11, year=1009),
            "Melanie": date(day=22, month=1, year=1941),
            "Blueface Baby": date(day=18, month=8, year=2020),
        }
    
        for bday_name, date in bdays.items():
            bday = date.update(year=cur_year)
            if bday == date.today():
                await ctx.send(
                    embed=discord.Embed(
                        description=f"Happy birthday {bday_name}",
                        colour=discord.Color.green(),
                    )
                )
    Ответ написан
    Комментировать
  • Как сделать страницы?

    Самый простой способ - использовать discord.ext.menus.

    Примеры постраничного вывода приведены в README.md
    Ответ написан
    Комментировать
  • Как сделать чтобы когда пишешь !avatar @ (без пользователя, просто с @), не выдавало ошибку?

    Ловить ошибку в событии on_error_command(context, error): https://discordpy.readthedocs.io/en/v1.4.1/ext/com...

    Либо в наследуемом классе:
    from discord.ext import commands
    from contextlib import suppress
    
    class MyBot(commands.Bot):
        async def on_command_error(self, ctx, error):
            if isinstance(error, commands.BadArgument):
                await ctx.send(f"Неверный аргумент: {error.message}")
            else:
                await super().on_command_error(ctx, error)  # вызывает изначальное поведение on_error_message
    
    bot = MyBot(command_prefix="!")


    Либо просто в функции-"слушателе":
    from discord.ext import commands
    from contextlib import suppress
    
    bot = commands.Bot(command_prefix="!")
    
    @bot.event
    async def on_command_error(ctx, error):
        if isinstance(error, commands.BadArgument):
            await ctx.send(f"Неверный аргумент: {error.message}")
    Ответ написан
    Комментировать
  • Как отправить embed типа object в дискорд используя webhook?

    По названию функции .post, рискну предположить что Disc - экземпляр объекта типа aiohttp.ClientSession. Он не знает что такое дискорд.

    Несколько вариантов развития событий решения:
    1. Вы продолжаете использовать сессию для подключения и отправки запросов вручную. В таком случае вам необходимо самостоятельно передавать json endpoint'у вебхука. Получить dict для передачи в аргумент json функции post можно через Embed.to_dict().
    import discord
    import aiohttp
    
    session = aiohttp.ClientSession()
    
    # Discord поддерживает только markdown для форматирования. html-теги (<i> и прочие) будут отображаться напрямую
    embed_obj = discord.Embed(
        title="*Заголовок*", colour=0x21D3CD, url="https://example.com"
    )  # Цвет в HEX более читаемый
    embed_obj.set_image(url="https://via.placeholder.com/140x100")
    embed_obj.set_thumbnail(url="https://via.placeholder.com/140x100")
    embed_obj.set_footer(text="*Текст*", icon_url="https://via.placeholder.com/140x100")
    embed_obj.set_author(
        name="*Текст*",
        url="https://example.com",
        icon_url="https://via.placeholder.com/140x100",
    )
    embed_obj.add_field(
        name="*Текст*", value="\N{Zero Width Space}"
    )  # Значение поля не может быть пустым, такой embed дискорд отклонит. Используем визуально пустой символ для этого.
    await session.post(
        "https://discord.com/api/webhooks/%WEBHOOK_ID%/%WEBHOOK_TOKEN",
        json={"embeds": [embed_obj.to_dict()]},
    )


    2. Использовать поддержку вебхуков из discord.py: https://discordpy.readthedocs.io/en/v1.4.1/api.htm....
    import aiohttp
    import discord
    
    session = aiohttp.ClientSession()
    webhook = discord.Webhook.from_url(
        "https://discord.com/api/webhooks/%WEBHOOK_ID%/%WEBHOOK_TOKEN",
        adapter=discord.AsyncWebhookAdapter(session),
    )
    embed_obj = ...
    await webhook.send(embed=embed_obj)
    Ответ написан
    Комментировать
  • Как вывести название дс сервера?

    В on_guild_join передаётся аргумент guild, который и является сервером, к которому присоединился бот.
    https://discordpy.readthedocs.io/en/v1.4.1/api.htm...

    import logging
    
    @listener  # client.event / commands.Cog.listener / etc...
    async def on_guild_join(guild):
        logging.info(f"Joined guild {guild.name} ({guild.id})"
    Ответ написан
    Комментировать
  • Очень странная ошибка в 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 как сделать глобальный чат?

    Через 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 комментария