Skip to main content

Намерения шлюза

Примечание

Это содержание было взято непосредственно из документации и унаследовано от discord.py. Скорее всего, в будущем оно будет переписано.

Намерения в основном позволяет боту подписываться на определенные группы событий. События, соответствующие каждому намерению, документируются в отдельном атрибуте Intents.

Эти намерения передаются конструктору commands.Bot или его подклассов (AutoShardedClient, AutoShardedBot или Bot) с аргументом intents.

Если намерения не переданы, то библиотека по умолчанию включает все намерения, кроме привилегированных намерений, в настоящее время Intents.members, Intents.presences и Intents.message_content .

Какие намерения необходимы?

Намерения, необходимые для вашего бота, могут быть продиктованы только вами. Каждый атрибут в Intents класс документирует, каким событиям он соответствует и какой тип кэша он включает.

Например, если вам нужен бот, который работает без спам-событий, таких как присутствие или ввод текста, мы могли бы сделать следующее:

intents.py
import disnake
from disnake.ext import commands

intents = disnake.Intents.default()
intents.typing = False
intents.presences = False

bot = commands.Bot(command_prefix=commands.when_mentioned_or("!"), intents=intents)
Примечание

Это не позволяет включить Intents.members, поскольку это привилегированное намерение.

Другой пример, показывающий бота, который обрабатывает только сообщения и информацию о сервере:

intents.py
import disnake
from disnake.ext import commands

intents = disnake.Intents(messages=True, guilds=True)
# Если вы также хотите, чтобы события реакции были включены:
# intents.reactions = True

bot = commands.Bot(command_prefix=commands.when_mentioned, intents=intents)

Привилегированные намерения

С изменением API, требующим, чтобы оба автора указывали намерения, некоторые намерения были дополнительно ограничены и требуют больше ручных действий. Эти намерения называются привилегированными.

Привилегированное намерение - это намерение, которое требует, чтобы вы зашли на портал разработчика и вручную включили его. Чтобы включить привилегированные намерения, выполните следующие действия:

  1. Убедитесь, что вы авторизированы в Discord.

  2. Перейдите на страницу приложений.

  3. Выберите бота, для которого вы хотите включить привилегированные намерения.

  4. Перейдите на вкладку Bot.

    The bot tab in the application page.
  5. Прокрутите вниз до раздела "Privileged Gateway Intents" и включите те, которые вы хотите.

    The privileged gateway intents selector.
Предупреждение

Включение привилегированных намерений, когда ваш бот состоит в более чем 100 гильдиях, требует прохождения проверки бота. Если ваш бот уже проверен, и вы хотели бы включить привилегированное намерение, вы должны пройти через поддержку Discord и поговорите с ней об этом.

Примечание

Даже если вы включите намерения через портал разработчика, вам все равно придется включить их и через код.

Нужны ли мне привилегированные намерения?

Это краткий контрольный список, чтобы узнать, нужны ли вам конкретные привилегированные намерения.

Намерение на контент сообщений

  • Хотите ли вы использовать префикс, который не является упоминанием бота.
  • Хотите ли вы увидеть, каково было содержание сообщения. Это включает в себя содержимое, вложения, вложения и компоненты.

Намерение присутствия

  • Когда вы используете Member.status для отслеживания статусов пользователей.
  • Когда вы используете Member.activity или Member.activities для отслеживания активности пользователей.

Намерение на участников

  • Когда вы отслеживаете вход и выход учатников в событиях on_member_join и Member.on_member_remove.
  • Когда вам нужно отслеживать изменения участников, таких как никнейм, роли и т.п.
  • Когда вам нужно отслеживать изменения участников, таких как некнейм пользоваля, аватар, тег и т.п.
  • Когда вам нужно получать информацию об участниках Guild.chunk или Guild.fetch_members.
  • Когда вам нужно кэшировать список пользователей на серверах Guild.members.

Кэш участников

Наряду с намерениями, Discord теперь дополнительно ограничивает возможность кэширования участников и ожидает, что авторы ботов будут кэшировать столько, сколько необходимо. Однако для правильного поддержания кэша Intents.members намерение требуется для того, чтобы отслеживать участников, которые вышли, и должным образом выселять их.

Чтобы помочь с кэшированием элементов, где нам не нужно кэшировать элементы, в библиотеке теперь есть MemberCacheFlags флаг для управления кэшем участников. На странице документации для класса перечислены конкретные возможные политики.

Следует отметить, что для некоторых вещей не требуется кэш участника, поскольку Discord предоставит полную информацию о пользователе, если это возможно. Например:

  • Событие on_message() возвращает Message.author, даже если кэширование отключено.
  • Событие on_voice_state_update() передаст параметр member, даже если кэширование отключено.
  • Событие on_reaction_add передаст параметр user, даже если кэширование отключено.
  • Событие on_raw_reaction_add передаст RawReactionActionEvent.member, даже если кэширование отключено.
  • События добавления реакции не содержат дополнительной информации при отправке прямых сообщений. Это ограничение Discord.
  • События удаления реакции не содержат информации о членах. Это ограничение Discord.

Другие события, возвращающие Member требуют включения кэширования пользователей. Если желательна абсолютная точность по отношению к кэшу элементов, то желательно иметь включённое намерение Intents.members.

Извлечение элементов

Если кэш отключен или вы отключаете кэширование серверов при запуске, нам все равно может понадобиться способ загрузки участников. Библиотека предлагает несколько способов сделать это:

  • Guild.query_members
    • Используется для запроса участников по префиксу, соответствующему нику или имени пользователя.
    • Это также можно использовать для запроса участников по их ID пользователя.
    • При этом используется шлюз, а не HTTP.
  • Guild.chunk
    • Это может быть использовано для получения всего списка участников через шлюз.
  • Guild.fetch_member
    • Используется для извлечения участника по идентификатору через HTTP API.
  • Guild.fetch_members
    • Используется для получения большого количества участников через HTTP API.

Следует отметить, что шлюз имеет строгое ограничение скорости в 120 запросов за 60 секунд.

Диагностика

Некоторые общие проблемы, связанные с обязательным изменением намерения.

Куда подевались мои участники?

Из-за изменения API Discord теперь вынуждает разработчиков, которые хотят кэшировать участников, явно подписаться на него. Это изменение, требующее согласия, и обойти его невозможно. Чтобы вернуть участников, вы должны явно включить привилегированное намерение участников и изменить значение атрибута Intents.members на True.

Например:

intents.py
import disnake
from disnake.ext import commands

intents = disnake.Intents.default()
intents.members = True

bot = commands.Bot(command_prefix=commands.when_mentioned, intents=intents)

Почему большинство сообщений не имеют содержания?

После 31 августа 2022 года Discord начнет блокировать отправку содержимого сообщений ботам, у которых не включено намерение содержимого сообщения.

Если вы используете версию 2.4 или более раннюю, ваш бот сможет получить доступ к содержимому сообщения без включенного в коде намерения. Однако, начиная с версии 2.5, требуется включить message_content для получения содержимого сообщения через шлюз.

Примечание

Начиная с версии 2.5 или любой другой версии после истечения крайнего срока намерения вам необходимо будет включить намерение содержимого сообщения на портале разработчиков Discord также.

Содержимое сообщения ссылается на четыре атрибута в объекте Message:

Вы всегда будете получать содержимое сообщения в следующих случаях даже без намерения содержимого сообщения:

  • Сообщения, которые отправляет бот
  • Сообщения, которые бот получает в ЛС
  • Сообщения, в которых упоминается бот
  • Сообщения, полученные как часть взаимодействия (например, команда для сообщения)

Почему срабатывание события on_ready занимает так много времени?

В рамках изменения API, касающегося намерений, Discord также изменил способ загрузки элементов в начале. Первоначально библиотека могла запрашивать 75 гильдий одновременно и запрашивать членов только из гильдий, у которых есть ссылка Guild.large имеет значение True. С новыми изменениями намерений Discord предписывает, что мы можем отправлять только 1 сервер на запрос. Это приводит к замедлению в 75 раз, что еще больше усугубляется тем фактом, что запрашиваются все гильдии, а не только крупные гильдии.

Есть несколько решений, чтобы исправить это.

  1. Запросите намерение привилегированных присутствий вместе с намерением привилегированных участников и включите их оба. Это позволяет первоначальному списку участников содержать онлайн-участников точно так же, как в старом шлюзе. Обратите внимание, что мы по-прежнему ограничены 1 гильдией на запрос, но количество гильдий, которые мы запрашиваем, значительно сокращено.

  2. Отключите группирование элементов, установив для параметра chunk_guilds_at_startup значение False при создании клиента. Затем, когда необходимо проверить наличие гильдии, вы можете использовать различные методы для получения участников.

Чтобы проиллюстрировать замедление, вызванное изменением API, возьмем бота, который состоит в 840 гильдиях, и 95 из этих гильдий являются "крупными" (более 250 участников).

В оригинальной системе это привело бы к тому, что 2 запроса на получение списка участников (75 гильдий, 20 гильдий) заняли бы примерно 60 секунд. С помощью Intents.members, но не Intents.presences для этого требуется 840 запросов с ограничением скорости в 120 запросов за 60 секунд, что означает, что из-за ожидания ограничения скорости в общей сложности около 7 минут ожидания ограничения скорости для получения всех участников. С обоими Intents.members и Intents.presences в основном мы получаем старое поведение, поэтому нам требуется запрашивать только 95 крупных гильдий, это немного меньше нашего лимита ставок, так что время получения списка участников близко к первоначальному.

К сожалению, из-за того, что это изменение требуется от Discord, библиотека ничего не может сделать, чтобы смягчить это.