2025, Oct 31 16:17

Запускаем Discord-бота в ЛС и GDM: slash‑команды и User Install

Руководство по запуску Discord-бота в ЛС и GDM: переход на slash-команды, User Install и настройка allowed_installs/allowed_contexts для работы в личных чатах.

Создать бота Discord, который работает в личных сообщениях, кажется простым — пока вы не пытаетесь запустить его в приватном чате с другим пользователем. Классические команды с префиксом ведут себя по‑разному в разных контекстах, и без корректной подготовки ваша команда тихо «промолчит» в диалоге один на один или в групповом ЛС. Ниже — как заставить всё работать так, как задумано, используя поддерживаемые Discord механизмы.

Что не работает в ЛС

Представьте простую команду, которая должна запускаться только в ЛС. Она логирует, кто её вызвал, выбирает значение и отправляет ответ. На вид всё правильно, но в ветке диалога с другим пользователем она не срабатывает.

@core.command()
@commands.dm_only()
async def purr(ev: discord.ApplicationContext):
    audit.info(f"{ev.author} meows")
    max_count=len(catlines)
    idx=random.randint(1,max_count)
    msg=catlines[idx][0]
    audit.info(msg)
    await ev.send(msg)

Даже при ограничении команды ЛС, вызов в приватной переписке с другом не даст видимого результата.

Почему так происходит

Дело в том, как Discord предоставляет взаимодействия в личных и групповых беседах. Обычных префиксных команд недостаточно, чтобы бот работал внутри пользовательских ЛС или GDM. Это реализуется только через slash‑команды в сочетании с возможностью установки приложения пользователем в свой профиль, чтобы вызывать его где угодно. Проще говоря, контекст и модель установки важны не меньше, чем сама команда.

Правильный подход

Начиная с discord.py 2.4+, slash‑команды можно включить для ЛС и групповых ЛС при выполнении двух условий. Во‑первых, разрешите установку команды в профиль пользователя. Во‑вторых, явно разрешите исполнение в контекстах DM и GDM. GDM в API обозначаются как private_channels. Ниже — минимальная настройка:

@discord.app_commands.allowed_installs(guilds=False, users=True)
@discord.app_commands.allowed_contexts(guilds=False, dms=True, private_channels=True)
@app.tree.command()
async def purr(inter):
    ...

Чтобы завершить настройку, включите “User Install” на вкладке “Installation” вашего приложения в Developer Portal. Тогда при авторизации появится опция “Add to My Apps”, необходимая для установок на уровне пользователя. Официальные ссылки: @discord.app_commands.allowed_installs и @discord.app_commands.allowed_contexts.

Собираем всё вместе

Перейдите на slash‑взаимодействия, разрешите пользовательские установки и откройте нужные контексты. Ниже — адаптированная версия, повторяющая прежнюю логику, но доступная для вызова в ЛС и GDM после установки пользователем:

@discord.app_commands.allowed_installs(guilds=False, users=True)
@discord.app_commands.allowed_contexts(guilds=False, dms=True, private_channels=True)
@app.tree.command()
async def purr(inter):
    audit.info(f"{inter.user} meows")
    max_count=len(catlines)
    idx=random.randint(1,max_count)
    msg=catlines[idx][0]
    audit.info(msg)
    await inter.response.send_message(msg)

После включения “User Install” в Developer Portal и повторной авторизации приложения с этим скоупом, slash‑команда станет доступна прямо в ЛС с другим человеком или в GDM — в зависимости от места вызова.

Почему это важно для архитектуры бота

Доступность в ЛС и GDM — это не просто переключатель, а возможность, привязанная к системе slash‑команд и сценарию установки пользователем. Если вашему продукту нужны приватные взаимодействия вне серверов, проектируйте команды как app commands и управляйте тем, где их можно устанавливать и выполнять. Такой подход обеспечивает предсказуемое поведение в любых контекстах и помогает избежать «тихих» сбоёв.

Итоги

Если команда срабатывает в личном диалоге с ботом, но не работает в переписке с другим человеком, переходите на slash‑команды и включайте пользовательские установки. Настройте @discord.app_commands.allowed_installs для установок на уровне пользователя и задайте @discord.app_commands.allowed_contexts, чтобы разрешить ЛС и private_channels. Включите “User Install” в Dev Portal. При такой конфигурации функции бота стабильно доступны в приватных разговорах — там, где пользователи их и ожидают.

Статья основана на вопросе на StackOverflow от Firemix и ответе Lia Milenakos.