Spring BootとJDAを連携させる：Discordボット開発【その①】

皆さん、こんにちは！今日はJavaを使ったプログラミングの楽しさを、Spring BootとJDAを使ってDiscordボットを作成する方法を通じてお伝えします。この記事は、プログラミング初心者やJavaに興味がある方々に向けて書いています。

# 1. 効率的なボット開発
Spring BootとJDAを組み合わせることで、効率的かつ簡単にDiscordボットを作成できます。この組み合わせは、コードの複雑さを減らし、開発者が本質的なロジックに集中できるようにします。

# 2. なぜSpring BootとJDAか？
- **Spring Boot:** 設定がシンプルで、迅速な開発を可能にします。Spring Bootは、依存関係管理やアプリケーションの構成を簡素化し、開発時間を大幅に短縮します。
- **JDA:** Discord APIとの連携を簡単にし、メッセージの送受信、ユーザー管理などをスムーズに行えます。JDAは、Discordの機能をフルに活用するための強力なツールです。

# 3. ソースコードの解説
### DiscordConfigクラス
このクラスは、Discordボットの基本設定を管理します。以下は主要な機能です：
- **トークンの注入:** `@Value`アノテーションを使用して、`discord.token`プロパティからDiscordボットのトークンを取得します。これにより、セキュリティが保たれ、簡単に設定を変更できます。
- **NobyBotの結線:** NobyBotクラスのインスタンスを`@Autowired`アノテーションを使って結線します。NobyBotはイベントリスナーとして機能し、Discordからのメッセージを処理します。
- **JDABuilderの設定:** JDABuilderを使用してDiscord APIとの接続を設定します。ここでは、トークンを指定し、NobyBotをイベントリスナーとして追加します。

```java:DiscordConfig.java
package jp.livlog.cotogoto.api;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;

import jp.livlog.cotogoto.api.discord.NobyBot;
import net.dv8tion.jda.api.JDABuilder;
import net.dv8tion.jda.api.requests.GatewayIntent;

@Component
public class DiscordConfig implements CommandLineRunner {

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

    @Autowired
    private NobyBot nobyBot;

    @Override
    public void run(final String... args) throws Exception {

        // DiscordボットのトークンをセットしてJDAインスタンスを作成
        final var builder = JDABuilder.createDefault(this.discordToken)
                .enableIntents(GatewayIntent.MESSAGE_CONTENT);

        // イベントリスナーを追加
        builder.addEventListeners(this.nobyBot);

        // JDAをビルドして接続
        builder.build();
    }
}
```

### NobyBotクラス
NobyBotクラスは、Discordからのメッセージをリッスンする主要なコンポーネントです。重要な機能には以下のものがあります：
- **メッセージの受信:** `onMessageReceived`メソッドは、メッセージを受信したときに呼び出されます。このメソッド内で、ボットがメッセージに応答する方法を定義します。
- **コマンドの処理:** メッセージが特定のコマンドで始まる場合（例えば"!"で始まる場合）、それに応じたアクションを実行します。

```java:NobyBot.java
package jp.livlog.cotogoto.api.discord;

import java.io.IOException;
import java.util.concurrent.ExecutionException;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import com.sedmelluq.discord.lavaplayer.player.AudioPlayerManager;
import com.sedmelluq.discord.lavaplayer.player.DefaultAudioPlayerManager;
import com.sedmelluq.discord.lavaplayer.source.AudioSourceManagers;

import jp.livlog.cotogoto.api.discord.source.CustomInputStreamSourceManager;
import jp.livlog.cotogoto.api.discord.speech2text.SpeechToTextService;
import lombok.extern.slf4j.Slf4j;
import net.dv8tion.jda.api.entities.channel.ChannelType;
import net.dv8tion.jda.api.events.message.MessageReceivedEvent;
import net.dv8tion.jda.api.hooks.ListenerAdapter;

@Service
@Slf4j
public class NobyBot extends ListenerAdapter {

    @Value ("${google.projectId}")
    private String googleProjectId;

    @Override
    public void onMessageReceived(final MessageReceivedEvent event) {

        try {
            if (event.getAuthor().isBot()) {
                return; // Ignore messages from bots
            }

            this.printMessage(event);

            final var message = event.getMessage().getContentDisplay();
            if (message.startsWith("!")) {
                this.handleCommand(event, message);
            } else {
                this.echoMessage(event, message);
            }
        } catch (final Exception e) {
            NobyBot.log.error(e.getMessage(), e);
        }

    }

}
```

# 4. ステップバイステップの開発プロセス
1. **プロジェクトの準備:** Spring Initializrを使用して、必要な依存関係を含むプロジェクトスケルトンを生成します。これにより、開発の基盤が整います。
2. **設定クラスの作成:** `DiscordConfig`クラスを作成し、Spring Bootの`CommandLineRunner`を実装します。
3. **トークンの注入:** `@Value`アノテーションでDiscordボットのトークンを注入します。
4. **NobyBotの結線:** `@Autowired`を使い、NobyBotインスタンスを結線します。
5. **JDABuilderの設定:** トークンを使ってJDABuilderを設定し、イベントリスナーを追加します。

# 5. Mavenの設定

JavaのプロジェクトでDiscord Botを開発する際には、Mavenを使った依存関係の管理が重要です。以下は、Spring BootとJDAを使用するための基本的なMaven設定です。

### pom.xmlの設定

`pom.xml`ファイルには、プロジェクトで必要となるライブラリの依存関係を定義します。以下は、Spring BootとJDAの依存関係を含む一例です。

```xml
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>jp.livlog.cotogoto</groupId>
    <artifactId>discord-bot</artifactId>
    <version>1.0-SNAPSHOT</version>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>3.1.4</version>
    </parent>

    <dependencies>
        <!-- Spring Bootの依存関係 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>

        <!-- JDA - Java Discord API -->
        <dependency>
            <groupId>net.dv8tion</groupId>
            <artifactId>JDA</artifactId>
            <version>5.0.0-beta.19</version>
        </dependency>

        <!-- その他必要な依存関係を追加 -->
    </dependencies>

</project>
```

この設定により、Spring BootとJDAを利用するための基盤が整います。`pom.xml`ファイルをプロジェクトのルートディレクトリに配置し、Mavenコマンドを使用して依存関係を解決します。

### Mavenコマンドの使用

プロジェクトディレクトリで以下のコマンドを実行することで、定義された依存関係がダウンロードされ、プロジェクトがビルドされます。

```bash
mvn clean install
```

このコマンドは、プロジェクトをクリーンし（以前のビルドを削除し）、新しい依存関係をダウンロードしてプロジェクトをビルドします。

# 6. CotoGotoとの連携について
最後に、この技術メモは、CotoGotoの機能拡張の一環としてDiscordを連携するためのものです。CotoGoto（コトゴト）は、人工知能を搭載した会話型アプリで、日常的な会話を通じて作業内容を分析し、タスク管理やスケジュール管理をサポートします。Discordボットの導入により、CotoGotoはより多くのユーザーとのインタラクションを実現し、日々の生活や作業に役立つ情報を提供できるようになります。

詳細は、以下をご覧ください。

https://cotogoto.ai/

# 7. まとめ
このガイドを通じて、皆さんもDiscordボットを作成し、Javaの世界での冒険を楽しんでください。Spring BootとJDAの組み合わせは、初心者にも優しい開発プロセスを提供し、効果的なボット作成を可能にします。


## 参考

https://stackoverflow.com/questions/70560372/constructor-injection-together-with-jda-and-spring-boot