Рубрики
Без рубрики

Создание бота раздора с Discord4J и весенней загрузкой

Изучите все необходимые шаги для создания бота Discord с помощью библиотеки Discord4J и Spring Boot

Автор оригинала: Jordan Simpson.

1. Обзор

Дискорд4J — это библиотека Java с открытым исходным кодом, которая может быть использована в первую очередь для быстрого доступа к Дискорд Бот API . Он сильно интегрируется с Проект Реактор обеспечить полностью не блокирующий реактивный API.

Мы будем использовать Discord4J в этом учебнике, чтобы создать простого бота Discord, способного реагировать на предопределенную команду. Мы построим бота поверх Spring Boot, чтобы продемонстрировать, как легко было бы масштабировать нашего бота во многих других функциях, включенных Spring Boot.

Когда мы закончите, этот бот сможет прослушать команду под названием “!todo” и распечатать статически определенный список дел.

2. Создать приложение раздора

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

Вот шаги для создания нового приложения:

  • Войдите в Портал разработчиков Discord
  • Во вкладке Приложения нажмите кнопку “Новое приложение”
  • Введите имя для нашего бота и нажмите кнопку “Создать”
  • Загрузите значок приложения и описание и нажмите кнопку “Сохранить изменения”

Теперь, когда приложение существует, мы просто должны добавить бот функциональность к нему. Это позволит создать токен бота, который требует Discord4J.

Вот шаги по преобразованию приложения в бота:

  • Во вкладке Приложения выберите наше приложение (если оно еще не выбрано).
  • Во вкладке Bot нажмите кнопку “Добавить бота” и подтвердите, что мы хотим это сделать.

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

Теперь мы готовы написать код!

3. Создайте приложение для весенней загрузки

После создания нового приложения Spring Boot, мы должны быть уверены, чтобы включить Основной Discord4J зависимость:


    com.discord4j
    discord4j-core
    3.1.1

Discord4J работает путем инициализации GatewayDiscordClient с маркером бота, который мы создали ранее. Этот клиентский объект позволяет нам регистрировать слушателей событий и настраивать многие вещи, но как минимум, мы должны по крайней мере позвонить войти в систему () метод. Это будет отображать наш бот как онлайн.

Во-первых, давайте добавим наш токен бота в наш application.yml файл:

token: 'our-token-here'

Далее, давайте ввести его в @Configuration класс, где мы можем мгновенно наши GatewayDiscordClient :

@Configuration
public class BotConfiguration {

    @Value("${token}")
    private String token;

    @Bean
    public GatewayDiscordClient gatewayDiscordClient() {
        return DiscordClientBuilder.create(token)
          .build()
          .login()
          .block();
    }
}

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

4. Добавить событие Слушатели

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

Есть много типов событий, для которых мы можем слушать. Тем не менее, регистрация слушателя одинакова для всех из них, так что давайте сначала создадим интерфейс для всех наших слушателей событий:

import discord4j.core.event.domain.Event;

public interface EventListener {

    Logger LOG = LoggerFactory.getLogger(EventListener.class);
    
    Class getEventType();
    Mono execute(T event);
    
    default Mono handleError(Throwable error) {
        LOG.error("Unable to process " + getEventType().getSimpleName(), error);
        return Mono.empty();
    }
}

Теперь мы можем реализовать этот интерфейс для как можно большего discord4j.core.event.domain.Event расширения, как мы хотим.

Прежде чем реализовать наш первый слушатель событий, давайте изменим наш клиент @Bean конфигурации, чтобы ожидать список EventListener так что он может зарегистрировать каждый найденный в Весеннее приложениеКонтекст :

@Bean
public  GatewayDiscordClient gatewayDiscordClient(List> eventListeners) {
    GatewayDiscordClient client = DiscordClientBuilder.create(token)
      .build()
      .login()
      .block();

    for(EventListener listener : eventListeners) {
        client.on(listener.getEventType())
          .flatMap(listener::execute)
          .onErrorResume(listener::handleError)
          .subscribe();
    }

    return client;
}

Теперь, все, что нам нужно сделать, чтобы зарегистрировать событие слушателей заключается в том, чтобы реализовать наш интерфейс и аннотировать его с @Component стереотипные аннотации . Регистрация теперь будет происходить автоматически для нас!

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

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

4.1. Обработка команд

Чтобы получить команду пользователя, мы можем прослушать два разных типа событий: СообщениеСоздаемоеСозда для новых сообщений и СообщениеUpdateEvent для обновленных сообщений. Мы можем только хотеть слушать для новых сообщений, но как учя возможность, препятствуйте нам предположить что мы хочет поддержать оба вида случаев для нашего bot. Это обеспечит дополнительный уровень надежности, что наши пользователи могут оценить.

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

Как только у нас Сообщение , Мы можем проверить автора, чтобы убедиться, что это не бот, мы можем проверить содержимое сообщения, чтобы убедиться, что он соответствует нашей команде, и мы можем использовать канал сообщения для отправки ответа.

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

import discord4j.core.object.entity.Message;

public abstract class MessageListener {

    public Mono processCommand(Message eventMessage) {
        return Mono.just(eventMessage)
          .filter(message -> message.getAuthor().map(user -> !user.isBot()).orElse(false))
          .filter(message -> message.getContent().equalsIgnoreCase("!todo"))
          .flatMap(Message::getChannel)
          .flatMap(channel -> channel.createMessage("Things to do today:\n - write a bot\n - eat lunch\n - play a game"))
          .then();
    }
}

Многое здесь происходит, но это самая основная форма командования и ответа. Этот подход использует реактивный функциональный дизайн , но это можно написать более традиционным императивом, используя блок () .

Масштабирование нескольких команд ботов, вызов различных служб или репозиториев данных или даже использование ролей Discord в качестве авторизации для определенных команд являются общими частями хорошей архитектуры команды бота. Так как наши слушатели – это весенние @Service s, мы могли бы легко ввести другие весенние управляемые бобы, чтобы заботиться об этих задачах. Тем не менее, мы не будем решать все, что в этой статье.

4.2. EventListener

Чтобы получать новые сообщения от пользователя, мы должны слушать СообщениеСоздаемоеСозда . Так как логика обработки команд уже живет в СообщениеЛистенер , мы можем расширить его, чтобы унаследовать эту функциональность. Кроме того, мы должны реализовать наши EventListener интерфейс в соответствии с нашим дизайном регистрации:

@Service
public class MessageCreateListener extends MessageListener implements EventListener {

    @Override
    public Class getEventType() {
        return MessageCreateEvent.class;
    }

    @Override
    public Mono execute(MessageCreateEvent event) {
        return processCommand(event.getMessage());
    }
}

Через наследство сообщение передается нашему процессКоманд () метод, при котором происходит вся проверка и ответы.

На этом этапе наш бот получит команду “!todo”. Однако, если пользователь исправляет свою неправильно введенную команду, бот не отвечает. Давайте подготовим этот пример использования с другим слушателем события.

4.3. EventListener

СообщениеUpdateEvent излучается, когда пользователь редактирует сообщение. Мы можем слушать это событие, чтобы распознать команды, так же, как мы слушаем СообщениеСоздаемоеСозда .

Для наших целей мы заботимся об этом событии только в том случае, если содержание сообщения было изменено. Мы можем игнорировать другие экземпляры этого события. К счастью, мы можем использовать isContentChanged () метод фильтрации таких экземпляров:

@Service
public class MessageUpdateListener extends MessageListener implements EventListener {
    
    @Override
    public Class getEventType() {
        return MessageUpdateEvent.class;
    }

    @Override
    public Mono execute(MessageUpdateEvent event) {
        return Mono.just(event)
          .filter(MessageUpdateEvent::isContentChanged)
          .flatMap(MessageUpdateEvent::getMessage)
          .flatMap(super::processCommand);
    }
}

В этом случае, начиная с getMessage () возвращает Моно вместо сырого Сообщение , мы должны использовать flatMap () отправить его в наш суперкласс.

5. Тест Бот в discord

Теперь, когда у нас есть функционирующий бот Discord, мы можем пригласить его на сервер Discord и протестировать его.

Чтобы создать ссылку приглашения, мы должны указать, какие разрешения бот требует, чтобы функционировать должным образом. Популярный сторонний Калькулятор разрешений раздора часто используется для создания ссылки приглашения с необходимыми разрешениями. Хотя это не рекомендуется для производства, мы можем просто выбрать “Администратор” для целей тестирования и не беспокоиться о других разрешениях. Просто поставь идентификатор клиента для нашего бота (на портале разработчиков Discord) и используйте генерируемую ссылку, чтобы пригласить нашего бота серверная .

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

Бот теперь отвечает на сообщение “!todo” и когда сообщение редактируется, чтобы сказать “!todo”:

6. Обзор

В этом учебнике описаны все необходимые шаги для создания бота Discord с использованием библиотеки Discord4J и Spring Boot. Наконец, в нем описано, как настроить базовую масштабируемую структуру командования и реагирования для бота.

Для полного и работающего бота просмотрите исходный код более на GitHub . Для его запуска требуется действительный токен бота.