Как получить сообщение на которое ответили? discord.py
Как получить сообщение, в ответ на которое была отправлена команда, и ответить на него же. То-есть например:
User1 - text User2 - reply user1: !command Bot - reply user1: text2
Отслеживать
задан 28 дек 2022 в 14:54
130 2 2 серебряных знака 17 17 бронзовых знаков
1 ответ 1
Сортировка: Сброс на вариант по умолчанию
Для этого создайте команду. Пусть будет .say
@client.command() async def say(ctx, text):
Добавляем проверку для сообщения. То есть если пользователь ответил на сообщение командой .say
if ctx.message.reference: original = await ctx.fetch_message(ctx.message.reference.message_id) await original.reply(f'Вам сообщение: ')
Таким образом бот ответит на сообщение на которое ответили Вы.
Бот для Discord API на Python (discord.py) с командами

Сегодня разберём создание бота для популярной соцсети Discord. Эта платформа предназначена для общения посредством голосовых чатов и сообщений и чем-то схожа с телеграмом.
Недавно я столкнулся с задачей написания подобного бота. Поскольку на просторах интернета, нет внятных гайдов, решил сделать свой. Про официальную документацию можно не говорить, там чёрт ногу сломит. В YouTube охватывают лишь самое начало. Я постараюсь более детально погрузиться в discord.py и работу с Discord API.
Структура проекта и установка библиотек
- Компьютер или ноутбук
- Редактор кода (Notepad++ тоже подойдет).
- Python версии 3.9 и выше.
- Соединение с интернетом
Установка для Windows:
pip install discord.py
Установка для MacOS:
pip3 install discord.py
+---discord | +---cogs | | +---everyone.py | | +---logs.py | | \---moder.py | +---config.py | \---main.py
Структура максимально простая, все модули для обработки команд будут храниться в директории cogs. Остальное можно структурировать как угодно.
Создание бота и получение токена
Заходим на этот сайт https://discord.com/developers/docs/intro и нажимаем на «applications». После проходим авторизацию (видео инструкция тут ).

Создаем новое приложение:

Дальше переходим во вкладку Bot и создаем бота. Тут вы сможет создать и скопировать токен:

После всех манипуляций выбираем уровень доступа для бота — administrator.
Как добавить бота на сервер
Переходим во вкладку OAuth2 General, ставим такие настройки и сохраняем:

Потом переходим в URL General, выбираем те же самые настройки и копируем ссылку ниже:

Переходим по ссылке и выбираем на какой сервер хотим добавить бота. Добавлять можно только на тот сервер, который вы администрируете (у вас есть права администратора на нем). Дальше следуем иструкциям Discord.

Разработка бота
Main.py
import asyncio import os import discord from discord.ext import commands import config
Подробнее остановимся на commands и config .
В commands будет инициализироваться и храниться бот. В дальнейшем через этот объект класса будем обращаться к методам.
Config – там будут храниться все глобальные переменные — токены, ID каналов, ID ролей и т д.
discord_intents = discord.Intents.all() discord_intents.members = True
discord_intents – мы наделяем бота полными правами доступа (когда будем добавлять его, то он запросит разрешение для управления)
bot – тут собирается бот. Аргументы: command_prefix — на какой спец символ будет откликаться бот; intents — права доступа.
discord_intents = discord.Intents.all() discord_intents.members = True bot = commands.Bot(command_prefix=config.prefix, intents=discord_intents) bot.remove_command("help") @bot.event @commands.has_any_role(*config.admin_id_role) async def on_ready(): await bot.change_presence(status=discord.Status.idle, activity=discord.Game(config.prefix+"info")) await bot.wait_until_ready() @bot.command() @commands.has_any_role(*config.admin_id_role) async def load(ctx, extension): bot.load_extension(f"cogs.") print(f"load module: cogs.") @bot.command() @commands.has_any_role(*config.admin_id_role) async def unload(ctx, extension): bot.unload_extension(f"cogs.") print(f"unload module: cogs.") @bot.command() @commands.has_any_role(*config.admin_id_role) async def reload(ctx, extension): bot.unload_extension(f"cogs.") bot.load_extension(f"cogs.") print(f"reload module: cogs.") async def load_extensions(): for filename in os.listdir("./cogs"): if filename.endswith(".py"): await bot.load_extension(f"cogs.") async def main(): print('zit goot') await load_extensions() await bot.start(config.token) if __name__ == "__main__": # bot.run(config.token) asyncio.run(main())
Пробежимся по функциям.
On_ready – срабатывает при загрузке бота. bot.change_presence — тут мы устанавливаем активность (Discord может показывать во что вы сейчас играете).
Дальше подгружаются все винтики. Почему пакеты в Discord называют винтики? Потому что в официальной документации разработчики назвали именно так;)
Load и unload — позволяют отключить и подключить винтики. Загрузка происходит с помощью обращения к методам объекта бота.
Reload — по сути вызывает по очереди unload и load.
Цикл for перебирает все файлы и загружает их в первый раз.
Ну и в конце мы запускаем бота, передавая в него токен.
Config.py
token = '12345' prefix = '!' recurring_guild_id = 1234 admin_id_role = '938435735701311538' id_mute_role = '938437343751319613' id_user_role = '938437452920672327'
Этот файл будет хранить в себе только служебные переменные — токены, ID ролей, ID серверов.
Директория cogs
Everyone.py
import discord import time import config from discord.ext import commands class Everyone(commands.Cog): def __init__(self, bot): self.bot = bot @commands.Cog.listener() async def on_ready(self): print('everyone is ready') @commands.command() async def info(self, ctx): embed = discord.Embed(title=f">> Команды ", icon_url=f"") embed.add_field(name=f"***mute*** --- отключить возможность говорить и писать человеку", value=f"Пример: mute @1234", inline=False) embed.add_field(name=f"***unmute*** --- вернуть все возможности человку", value=f"Пример: unmute @1234", inline=False) embed.add_field(name=f"***ban*** --- добавить человека в черный список и выгнать", value=f"Пример: ban @1234", inline=False) embed.add_field(name=f"***unban*** --- убрать человека из чероного списка", value=f"Пример: unban @1234", inline=False) embed.add_field(name=f"***kick*** --- выгрнать человека", value=f"Пример: kick @1234", inline=False) embed.add_field(name=f"***clear*** --- удалить последние сообщения", value=f"Пример: clear 40", inline=False) embed.set_footer(text=f"BOT • ") await ctx.channel.purge(limit=1) await ctx.send(embed=embed) async def setup(bot): await bot.add_cog(Everyone(bot))
В этом файле будут храниться все команды доступные обычному пользователю. Импорты отдельно разбирать не буду, там и так все понятно.
Вероятно, вы спросите что это за класс. Everyone наследуется от commands.Cog . Винтики работают за счёт объектов — когда мы запускаем бота, то перебираем все объекты и собираем всё вместе.
Для отслеживания команд мы используем декоратор commands.command() . Для корректной работы при создании класса мы передаём в него нашего бота. Дальше описываем в методах логику.
Функция info будет высылать пользователю embed (сообщение) с указанием доступных команд. Внутрь функции передаем ctx (полное его название context) — это полученное сообщение.
Мы создаем объект, в который передаем: заголовок, свет линии с краю, подпись автора и ссылку на изображение. Дальше, обращаясь к методу add_field , добавляем строки с именем и значением — можно их назвать заголовок и текст.
Метод set_footer добавляет маленькую подпись в конце сообщения. В завершение мы обращаемся к await ctx.channel.purge(limit=1) , что удаляет одно сообщение (можно указать любое количество в limit). Await позволяет нам дождаться окончания асинхронного метода.
После этого отправляем сообщение с помощью await ctx.send(embed=embed) , передавая внутрь сформированное сообщение. Или можно просто отправить текст await ctx.send(text=”your message”) .
Эта конструкция нужна библиотеке, что бы она могла увидеть и загрузить винтик:
async def setup(bot): await bot.add_cog(Everyone(bot))
Удобный конструктор embed, который сразу выдает python код, находится тут .
Moder.py
import discord import time from discord.ext import commands import config class Moder(commands.Cog): def __init__(self, bot): self.bot = bot @commands.Cog.listener() async def on_ready(self): print('moder is ready') @commands.command() @commands.has_any_role(config.admin_id_role) async def mute(self, ctx, user: discord.Member, reason=None): channel = self.bot.get_channel(config.log_mes_channel_id) guild = self.bot.get_guild(config.recurring_guild_id) role = guild.get_role(config.id_mute_role) embed = discord.Embed(title=f"Пользователя заглушили", color=0xfac400) embed.set_author(name=f"", icon_url=f"") embed.add_field(name="Причина:", value=f"", inline=True) embed.set_footer(text=f"BOT • ") await user.add_roles(role) await channel.send(embed=embed) await ctx.channel.purge(limit=1) await ctx.send(embed=embed, delete_after=30) @commands.command() @commands.has_any_role(config.admin_id_role) async def unmute(self, ctx, user: discord.Member): channel = self.bot.get_channel(config.log_mes_channel_id) guild = self.bot.get_guild(config.recurring_guild_id) role = guild.get_role(config.id_mute_role) embed = discord.Embed(title=f"Пользователя разглушили", color=0xfac400) embed.set_author(name=f"", icon_url=f"") embed.set_footer(text=f"BOT • ") await user.remove_roles(role) await channel.send(embed=embed) await ctx.channel.purge(limit=1) await ctx.send(embed=embed, delete_after=30) @commands.command() @commands.has_any_role(config.admin_id_role) async def ban(self, ctx, user: discord.Member, *, reason=None): channel = self.bot.get_channel(config.log_mes_channel_id) embed = discord.Embed(title=f"Пользователя забанили", color=0xfac400) embed.set_author(name=f"", icon_url=f"") embed.add_field(name="Причина:", value=f"", inline=True) embed.set_footer(text=f"BOT • ") await channel.send(embed=embed) await user.ban(reason=reason) await ctx.channel.purge(limit=1) await ctx.send(embed=embed, delete_after=30) @commands.command() @commands.has_any_role(config.admin_id_role) async def unban(self, ctx, *, member): banned_users = await ctx.guild.bans() channel = self.bot.get_channel(config.log_mes_channel_id) member_name, member_discriminator = member.split("#") for ban_entry in banned_users: user = ban_entry.user if (user.name, user.discriminator) == (member_name, member_discriminator): await ctx.guild.unban(user) embed = discord.Embed(title=f"Пользователя разбанили", color=0xfac400) embed.set_author(name=f"", icon_url=f"") embed.set_footer(text=f"Silence. • ") await channel.send(embed=embed) await ctx.channel.purge(limit=1) await ctx.send(embed=embed, delete_after=30) return @commands.command() @commands.has_any_role(config.admin_id_role) async def kick(self, ctx, user: discord.Member, *, reason=""): channel = self.bot.get_channel(config.log_mes_channel_id) embed = discord.Embed(title=f"Пользователя выгнали из сервера", color=0xfac400) embed.set_author(name=f"", icon_url=f"") embed.add_field(name="Причина:", value=f"", inline=True) embed.set_footer(text=f"BOT • ") await channel.send(embed=embed) await ctx.channel.purge(limit=1) await ctx.send(embed=embed, delete_after=30) await user.kick() @commands.command() @commands.has_any_role(config.admin_id_role) async def clear(self, ctx, amount=20): channel = self.bot.get_channel(config.log_mes_channel_id) if amount < 200: embed = discord.Embed(title=f"Очистил чат \"\" на сообщений(ия)", color=0xfac400) embed.set_author(name=f"", icon_url=f"") embed.set_footer(text=f"BOT • ") await ctx.channel.purge(limit=int(amount)) await channel.send(embed=embed) await ctx.send(embed=discord.Embed(description=f":wheelchair: удалено сообщений(я)"), delete_after=30) else: await ctx.send(embed=discord.Embed(description=f":Вы не можете удалить больше 200 сообщений"), delete_after=30) async def setup(bot): await bot.add_cog(Moder(bot))
Пройдёмся по функциям сверху вниз.
@commands.has_any_role(config.admin_id_role) - это новый декоратор, он проверяет есть ли у пользователя роль (нужен ID роли). Также можно указывать перечень ролей в массиве (для этого распаковывайте массив).
Mute принимает в себя само сообщение, пользователя (пример @user), и причину. Первым делом мы заготавливаем объект чата, в который будем присылать действия администратора. Потом сам сервер (в документации discord.py сервер называется гильдия). И в конце получаем роль, которую будем давать пользователю.
Когда всё готово, собираем сообщение-уведомление (не забывайте пользоваться конструктором embed тут ). Дальше к объекту пользователя добавляем роль. И отправляем сообщение в логи и в чат, откуда пришла команда. Не забываем удалять отправленную команду.
Unmute зеркальна с функций mute, только для пользователя мы используем метод remove role .
Ban - выгоняет пользователя с сервера и добавляет его в черный список (в дальнейшем его не смогут пригласить на сервер пока он в ЧС).
Для работы в переменных нам потребуется только канал для системы логов. Следом проходим процедуру сборки красивого сообщения и отправляем его как в mute.
Unban - не просто зеркальная функция, потому что тут нам потребуется обращаться к списку ЧС. banned_users делает запрос к ЧС сервера. Дальше мы делаем полный перебор всех заблокированных и сравниваем с нашим пользователем. Как только находим его, убираем юзера из списка и выводим сообщение о разблокировке.
Kick - с этой функций дела обстоят намного проще, так как у пользователя есть метод для изгнания user.kick .
Clear - последняя возможность для администрирования. В нее поступает не только сообщение, но и количество сообщений, которое нужно удалить. Дальше идет защита от опечатки.
ctx.channel.purge(limit=int(amount)) отвечает за удаление сообщений, в limit передаем полученное значение.
Заключение
Библиотека discord.py не проста в понимании и требует много времени на разбор. Но лучших аналогов для Python не найти из-за обширности API.
Если захотите разобраться глубже, самостоятельно изучайте новые методы и классы. Производите глубокий анализ, что откуда исходит (какой вы получаете объект в ответе и как его можно получить еще).
Для дальнейшего развития советую попытаться добавить в бота интеграцию с базой данных. Например есть хорошая БД MongoDB - на ней можно простроить мощную многоуровневую систему администрирования сервера.
Вопросы с меткой [discord.py]
у меня есть код: import discord from discord.ext import commands Bot = commands.Bot(command_prefix="") @Bot.command(pass_context=True) async def go_say(ctx): say_at_me = input(".
задан 15 апр 2021 в 16:38
569 показов
Как проверить указанные аргументы discord py?
Я перерыл весь интернет, но не нашел нужного мне ответа. Простую проверку аргументов я знаю как делать. Но, как сделать проверку аргументов, когда их очень много и они разного типа, или указан ли id .
задан 1 мая 2022 в 15:38
Список юзеров на сервере
Всем привет! Решил сделать генератор таблицы юзеров на сервере. Начал с обычного получения ников юзеров. @client.command() async def members(ctx): guild = ctx.guild for member in guild.member.
задан 3 дек 2020 в 17:51
2k показов
Как сделать определение мата в чате? Discord.py
Я делаю бота модератора чата. Основная его фишка определение мата в слове и удаление. Я смог сделать и улучшить свой код, однако при тестах возникла проблема которую решить я не в силах. Суть проблемы .
задан 23 окт 2021 в 12:08
8k показов
[discord.py]Удаление сообщение после выполнениыя команды
Поменялась версия и теперь не понимаю как удалить сообщение после выполнения команды client.delete_message() Раньше было так, но теперь поменялась команда. await ctx.message.delete(ctx) Вроде так, .
задан 11 дек 2019 в 19:40
727 показов
Декораторы event и command в discord.py
Возникла вот такая проблема в процессе написания бота для дискорда на Python. Написал функцию, чтобы при отправлении сообщения производились какие-то действия с базой данных. Вот сама функция с .
задан 17 авг 2020 в 14:17
665 показов
discord.py Копирование ID всех участников сервера
Я делал функцию для своего бота копирующую ID всех участников сервера, однако копирует лишь один ID. В чем проблема? По циклу же вроде всё сделано правильно. Вот код: @client.command(aliases=['id_copy'.
задан 5 янв 2022 в 7:07
3k показов
авто выдача роли и приветствие Discord.py
Написал код. должен писать приветствие и выдавать роль. так же сделал пометки мне в батнике пишет действия которые написаны в принте. и при выполнение действия выдачи роли должно, мне не роль не .
задан 6 мая 2021 в 11:07
Какую функцию random надо использовать для списков?
Код: @bot.command() async def ball(ctx): await ctx.send(role) roles = ["конечно", "скорей всего нет", "точно нет!", "шар не уверен :thinking:", "шар .
задан 7 апр 2023 в 9:34
3k показов
Как считать время проведенное в голосовом канале? | discord.py
У меня есть код, который реагирует на вход в голосовой, и выход из него. При входе пишется "1", при выходе "0". Как мне его изменить, чтобы он еще и считал время проведенное в .
задан 21 дек 2020 в 11:50
780 показов
Как сделать выбор действия в слеш командах discord.py?
Увидел в чьёмто боте реализован выбор варианта, т.е участник при вводе аргументов видет что что-то вылезло, и выберает то что ему нужно, возможно ли это реализовать?
задан 15 сен 2022 в 18:19
5k показов
Discord BOT, авторазадача ролей
Пишу своего бота в дискорде на питоне. Столкнулся с проблемой: посмотрев видос, решил сделать автовыдачу роли по реакции. При запуске в консоль не выводятся ошибки, но при добавлении реакции ничего не .
задан 18 фев 2020 в 16:08
5k показов
Ошибка IndexError: tuple index out of range
Пытался написать магазин для Discord-бота на Python и столкнулся с ошибкой IndexError: tuple index out of range В БД уже есть несколько товаров. Вот код: client = commands.Bot( command_prefix = '%') .
задан 14 июл 2020 в 18:49
5k показов
Смена префикса команды discord.py
Как я могу поменять префикс бота через команду в discord.py? Пробовал использовать этот код, но говорит что не найдена команда setprefix, понимаю что она идёт после bot.run но в коде так и было. Если .
задан 13 мая 2020 в 8:36
6k показов
discord.py и youtube_dl воспроизведение аудио без скачки
как можно воспроизвести аудио в боте при помощи библиотеки youtube_dl, но без установки самого аудио в директорию бота (из-за этой установки невозможно запустить стримы с музыкой по типу lo-fi) и если .
задан 6 дек 2020 в 13:33
15 30 50 на странице
-
Важное на Мете
Связанные метки
Подписаться на ленту
Лента последних активных вопросов с меткой [discord.py]
Для подписки на ленту скопируйте и вставьте эту ссылку в вашу программу для чтения RSS.
Дизайн сайта / логотип © 2024 Stack Exchange Inc; пользовательские материалы лицензированы в соответствии с CC BY-SA . rev 2024.1.3.2953
Нажимая «Принять все файлы cookie» вы соглашаетесь, что Stack Exchange может хранить файлы cookie на вашем устройстве и раскрывать информацию в соответствии с нашей Политикой в отношении файлов cookie.
Discord.py

Для этого вам придётся зайти на сайт Discord'а по разработки приложений. Далее создаём приложение с помощью кнопки New Application.
Нужно дополнить этот отдел информацией и изображениями
Шаг 2 - Hello World! [ ]
Напишем сначала просто код для того чтобы бот запускался.
import discord client = discord.Client() client.run("Insert here token of bot")
Кстати, токен бота обычно хранят в отдельном файле. Далее создаём событие через @client.event и пишем асинхронную функцию on_message.
@client.event async def on_message(message): if message.content.startswith(".hello"): await message.channel.send("Hello World!")
Также в разработке Discord ботов пример Hello World заменяется "Ping Pong". Выглядит так: пишешь команду ping, получаешь ответ Pong! Теперь напишем событие во время запуска. Оно необязательно, но благодаря ему можно узнать когда можно использовать бота + некоторые команды (например client.change_presence()) лучше использовать именно в этом событии.
@client.event async def on_ready(): print("I'm ready!")
Шаг 2.1 - Создание бота через commands.Bot() [ ]
Особо ничем не отличается т.к. является классом-наследником от Client, однако имеет возможности которые значительно облегчают разработку. Вот так выглядит обычный код с запуском бота и Ping Pong:
import discord from discord.ext import commands client = commands.Bot() @client.command() async def ping(ctx): await ctx.send("Pong!") client.run("Insert here token of bot")
В командах необходимо писать ctx даже если он не используется!