Ответы пользователя по тегу Discord
  • SQL как исправить ошибку?

    Vindicar
    @Vindicar
    RTFM!
    1. Не генерируй запросы через форматирование строк. Используй placeholders. Начиная со слов "the DB-API’s parameter substitution"
    2. Если тебе нужно вставить запись, если её нет, или не делать ничего, если она есть, почитай про INSERT ON CONFLICT DO NOTHING. Ну или про INSERT ON CONFLICT DO UPDATE, если нужно "вставить новую или обновить существующую".
    Ответ написан
    1 комментарий
  • Как сделать проверку на совпадении элемента из списка и значение в sqlite3?

    Vindicar
    @Vindicar
    RTFM!
    .fetchone()[0]
    Выстрелил себе в ногу, называется. .fetchone() может вернуть None, если SELECT не нашел ни одной подходящей записи, и тогда попытка обратиться по индексу сгенерирует
    исключение
    TypeError: 'NoneType' object is not subscriptable

    Так что проверяй, что тебе вернул fetchone().
    Ответ написан
  • Как читать документацию discord.py?

    Vindicar
    @Vindicar
    RTFM!
    Вопрос и впрямь странный.
    Нужно определиться, что именно ты ищешь, сообразить, какие могут быть ключевые слова, и искать по ним.
    В списке свойств каждого класса свойства и методы обычно кликабельны, так что можно перейти на подробное описание. Тип свойства указан в синтаксисе type hints стандартного модуля typing.
    Например, discord.Client.activity имеет тип Optional[BaseActivity], т.е. это либо None, либо экземпляр класса-наследника BaseActivity. Перейдя по ссылке, сразу видим список классов-потомков - корневой Activity и три наследника: Game, Streaming, CustomActivity. Дальше уже решаешь, какой тебе подойдёт лучше.
    Ответ написан
    Комментировать
  • При создании команды unban discord.py выдает эту ошибку. Command raised an exception: AttributeError: 'str' object has no attribute 'name' что делать?

    Vindicar
    @Vindicar
    RTFM!
    1. Включить голову.
    2. Почитать документацию про конвертацию параметров в обработчиках команд бота.
    3. Осознать, что в описании обработчика async def unban(ctx,*,member): member не имеет указания типа, а потому discord.py оставляет его строкой.
    4. Сопоставить этот факт с тем, что обращение member.name генерирует ошибку "объект строки не имеет атрибута name"
    5. Хлопнуть себя по лбу.
    6. Вставить в объявление обработчика указание типа для member: member: discord.Member
    Ответ написан
    Комментировать
  • Как сделать чтобы бот отправил любое сообщение?

    Vindicar
    @Vindicar
    RTFM!
    Читай документацию на discord.py, и вопросы отпадут.
    async def command(ctx, param: str) даст первое слово в строке (до пробела, или строку в кавычках).
    async def command(ctx, *params: str) даст каждое слово в строке (разделенной по пробелам, с учётом кавычек) отдельно, в виде кортежа.
    async def command(ctx, *, param: str) даст всё содержимое строки в виде одной строки.
    Ответ написан
    Комментировать
  • Понять понять из-за чего не работает команда мут?

    Vindicar
    @Vindicar
    RTFM!
    Как понять? Голову включить и документацию прочитать.
    @commands.has_any_role('mute' , 908382396112592926 )

    Читаем доки:
    A check() that is added that checks if the member invoking the command has any of the roles specified. This means that if they have one out of the three roles specified, then this check will return True.

    "Если участник, вызвавший команду, имеет любую из указанных ролей". Т.е. этой командой может пользоваться только участник, у которого есть либо роль с названием 'mute', либо роль с id 908382396112592926.

    Далее, смотрим на нижележащую глупость.
    muted_role = discord.utils.get( ctx.message.guild.roles, name = mute )

    Ты в качестве name передал функцию mute. Это по-твоему вообще имеет смысл? Может, всё же имел ввиду name = 'mute'? Но тогда означает, что команду может вызвать только замьюченный пользователь. Я сомневаюсь, что ты этого хотел.
    Ответ написан
  • Возможно ли дублирование чата с стороннего Дискорд сервера на свой при помощи бота?

    Vindicar
    @Vindicar
    RTFM!
    Если целевые каналы помечены как новостные, то можно обойтись и без бота.

    Если нет, то да, это несложно, хотя дискорд очень не любит, когда боты работают из-под учетки пользователя.
    Просто записываешь в программе список ID каналов, с которых нужно перекидывать сообщения, а также ID канала, куда их нужно перекидывать. В реакции на сообщение боту, проверяешь, где оно было размещено, и если ID беседы входит в список, то аккуратно дублируешь поля сообщения для отправки в целевой канал.
    Ответ написан
    Комментировать
  • Как сделать /slash команды в боте на библеотеке discord.py?

    Vindicar
    @Vindicar
    RTFM!
    Никак. Разработка discord.py остановилась, и автор не стал добавлять slash команды. Используй другие либы.
    Ответ написан
    Комментировать
  • Как сделать что бы бот ожидал пока пользователь прикрепит файл, а потом сохранит его в discord.py?

    Vindicar
    @Vindicar
    RTFM!
    Отправленный файл - это ведь тоже сообщение, просто с прикреплённым аттачем. Почему бы не обрабатывать сообщения от пользователей и смотреть аттачи? Строго говоря, файл и команда могут вообще быть в одном сообщении, хотя это несколько менее удобно.
    А вообще ты встретился с необходимостью в машине состояний. В discord.py её вроде нет "из коробки", придётся самому реализовывать. Это не так сложно, просто нужно вести список или словарь пользователей, от которых мы ждём файл. При поступлении сообщения с файлом смотрим, есть ли отправитель в этом списке. Если есть, обрабатываем файл и убираем его оттуда, если нет - игнорируем сообщение.
    С таймаутом сложнее, но можно в списке хранить не id пользователя, а пары id-метка времени. Тогда можно будет понять, когда был послан запрос, и периодически удалять "старые" записи из списка.
    Ответ написан
  • Как настроить голосование в боте дискорд?

    Vindicar
    @Vindicar
    RTFM!
    1. Оформи код как положено (</>)
    2. resactions = [reaction for reaction in message.reactions if reaction.emoji in ['✅', '❌']]

    Что тебе мешает адаптировать эту строку, чтобы считать реации отдельно?
    А то и проще, используй collections.Counter:
    from collections import Counter
    
    counts = Counter(reaction.emoji for reaction in message.reactions)
    if counts['✅'] > counts['❌']:
        KABOOM()
    Ответ написан
  • Непонятная ошибка KeyError, как исправить?

    Vindicar
    @Vindicar
    RTFM!
    queue_len = len(self.song_queue[ctx.guild.id])
    KeyError: 902227097647468664

    Число выглядит как id в дискорде. KeyError обычно случается, когда пытаешься обратиться к несуществующему ключу в словаре. В указанной строке кода есть кусочек, который выглядит как обращение к словарю: self.song_queue[ctx.guild.id]
    Вывод: в словаре self.song_queue нет ключа для того сервера (ctx.guild) с которого пришла команда боту. А вот почему его там нет, и почему нет логики, предусматривающей этот сценарий - это уже вопрос к вам.
    Ответ написан
    Комментировать
  • Как сделать чтобы бот удалил все каналы?

    Vindicar
    @Vindicar
    RTFM!
    1. Получить список всех каналов на сервере
    2. Пройтись по списку циклом for и удалить каждый.
    Но зачем?
    Ответ написан
    Комментировать
  • Как можно перенести команду на json?

    Vindicar
    @Vindicar
    RTFM!
    Zakkaru, чтобы бот сохранял состояние переменной afk_users в json файл? Ну так бы и сказал.
    Ну тогда у тебя много ерунды написано... ну вот хотя бы тут.
    with open('afk_users.json', 'w', encoding='utf-8') as file:
        file.write(json.dumps(afk_users, indent=4, ensure_ascii=False))
        file.close()

    Во-первых, оператор with сам вызовет file.close() по окончанию.
    Во-вторых, можно было сделать проще - json.dump(afk_users, file, indent=4, ensure_ascii=False). Обрати внимание, не dumps(), а dump().
    with open('afk_users.json', 'w', encoding='utf-8') as file:
        json.dump(afk_users, file, indent=4, ensure_ascii=False))

    В-третьих, почему ты сохраняешь состояние переменной afk_users, а потом тут же её изменяешь? Может, всё-таки в обратном порядке?
    В-четвёртых, где у тебя загрузка состояния afk_users из файла? Она должна производиться при запуске бота, например внутри on_ready.
    Ответ написан
    Комментировать
  • Пример команды с мутом?

    Vindicar
    @Vindicar
    RTFM!
    По команде на выдачу мута заноси в таблицу БД ID пользователя и время, когда надо снять мут.
    Также периодически (скажем, раз в несколько минут), выбирай из этой таблицы все записи, у которых время снятия мута меньше, чем текущее время. Если такие записи нашлись, снимаешь мут для пользователей, к которым они относятся, и удаляешь эти записи.
    Перезапуск бота такая схема переживает без нужды в дополнительных телодвижениях.

    Как сделать периодическую задачу, зависит от используемого языка и библиотеки - ты их не указал, кстати. Но это реализуемо в любом языке.
    Ответ написан
  • Не могу понять в чем проблема?

    Vindicar
    @Vindicar
    RTFM!
    description = f"""У тебя , **{ctx.author}** вот столько балов!**{cursor.execute("SELECT cash FROM users WHERE id = {}".format(ctx.author.id)).fetchone()[0]} :polegar_para_cima:**"""

    Вот это - трижды говнокод.
    1. Не засовывай в шаблонные строки ничего сложнее одной арфиметической операции - результат абсолютно нечитаем и неконтролируем (в чем ты убедился).
    Неправильно:
    description = f"""У тебя , **{ctx.author}** вот столько балов!**{cursor.execute("SELECT cash FROM users WHERE id = {}".format(ctx.author.id)).fetchone()[0]} :polegar_para_cima:**"""

    Правильно:
    score = cursor.execute("SELECT cash FROM users WHERE id = {}".format(ctx.author.id)).fetchone()[0]
    description = f"""У тебя , **{ctx.author}** вот столько балов!**{score} :polegar_para_cima:**"""

    2. Никогда не формируй запросы через форматирование строк. Слишком легко словить ошибку, явную или неявную.
    Неправильно:
    score = cursor.execute("SELECT cash FROM users WHERE id = {}".format(ctx.author.id))

    Правильно:
    score = cursor.execute("SELECT cash FROM users WHERE id = ?", (ctx.author.id,) )

    3. Всегда проверяй, что ты получаешь из базы! Нет гарантий, что запись с указанным id и впрямь существует.
    Неправильно:
    score = cursor.execute("SELECT cash FROM users WHERE id = ?", (ctx.author.id,) ).fetchone()[0]
    description = f"""У тебя , **{ctx.author}** вот столько балов!**{score} :polegar_para_cima:**"""

    Правильно:
    score_row = cursor.execute("SELECT cash FROM users WHERE id = ?", (ctx.author.id,) ).fetchone()
    if score_row is not None:
        description = f"""У тебя , **{ctx.author}** вот столько балов!**{score_row[0]} :polegar_para_cima:**"""
    else:
        # что делать, если такого юзера еще нет в базе?
        cursor.execute("INSERT INTO users (id, cash) VALUES (?, 0)", (ctx.author.id,) ) # можно его добавить
        description = f"""У тебя , **{ctx.author}** пока нет ничего! Но скоро будет!"""

    4. БаЛЛов, блин.
    Ответ написан
    5 комментариев
  • Не свосем юзербот на discord.py?

    Vindicar
    @Vindicar
    RTFM!
    Нельзя. И хорошо что нельзя.

    Можно подставить имя пользователя в начало текста, но всё равно будет видно, кто писал на самом деле.
    Ответ написан
    Комментировать
  • Discord.py кортеж и split,в чем проблема?

    Vindicar
    @Vindicar
    RTFM!
    Ты пытаешься сделать рандомный выбор из введённых значений?
    А на кой пельмень ты вообще соединяешь args? Если они разделяются пробелом, то так
    # команда вызывается как !choice вариант1 вариант_2 "вариант 3"
    @commands.command(pass_context=True)
    async def choice(self, ctx, *args:str):
      chosen = random.choice(args)

    А если прямо нужно через запятую, то лучше так:
    # команда вызывается как !choice вариант1, вариант 2, вариант 3
    @commands.command(pass_context=True)
    # discord.py интерпретирует * как "всю остальную строку засунь в следующий параметр" 
    async def choice(self, ctx, *, args:str): 
      choices = [arg.strip() for arg in args.split(',')]
      chosen = random.choice(choices)
    Ответ написан
  • Можно ли получить список пользователей дискорд через http url запрос?

    Vindicar
    @Vindicar
    RTFM!
    Не будучи на сервере - нет, насколько я знаю.
    Ответ написан
    Комментировать
  • Как сделать рассылку сообщения сразу во все каналы?

    Vindicar
    @Vindicar
    RTFM!
    Как-то так. Никаких гарантий, что дискорд не пошлёт твоего бота далеко и надолго за спам.
    @client.command()
    async def test(ctx):
        await ctx.author.send(f'test')
        # сохраняем набор и порядок каналов на случай, если он поменяется в процессе отправки.
        channels = list(ctx.guild.text_channels)
        # формируем пачку корутин, выполняющих отправку
        send_coroutines = [channel.send('test') for channel in channels]
        # планируем одновременное выполнение этих корутин и ждём завершения. 
        # Исключения будут возвращены наравне с результатами, а не выброшены.
        results = await asyncio.gather(*send_coroutines, return_exceptions=True)
        # анализируем results на предмет ошибок. 
        # Успешная отправка вернёт объект сообщения, неудачная вернет (а не выбросит!) объект исключения.
        failed = [ (ch.name, str(res)) for res, ch in zip(results, channels) if isinstance(res, (Exception, asyncio.CancelledError)) ]
        if failed: # были ошибки?
            await ctx.author.send('Failed to send to the following channels:\n' + '\n'.join(f'- {ch}: {msg}' for ch, msg in failed))
        else: # ошибок не было
            await ctx.author.send('Message has been spammed successfully.')
    Ответ написан
    Комментировать
  • Python | Как получить общее количество пользователей в голосовых каналах моего Discord сервера?

    Vindicar
    @Vindicar
    RTFM!
    Как всегда, достаточно внимательно прочитать документацию.
    Guild.voice_channels: List[VoiceChannel]
    Т.е. это список, а ты дергаешь у него какие-то посторонние свойства.
    Вот у отдельного VoiceChannel и впрямь есть свойство members: List[Member].
    Как дальше, догадаешься?

    Что-то вроде
    sum(len(vc.members) for vc in member.guild.voice_channels)


    Этот подход удобен для инициализации количества участников при запуске бота.
    А вот для отслеживания можно не дергать вышеописанное каждый раз, а поступить иначе. Если before.channel is None, то человек вошел в войс-чат. Если after.channel is None, то человек вышел из войс-чата. Если ни тот ни другой, человек просто перешел из одного войс-канала в другой. Тогда хранишь количество юзеров, и делаешь ему +1/-1 согласно этим условиям.
    Ответ написан
    1 комментарий