KotlinでDiscord Botを始めてみる2 ~シンプルなコマンド実装編~

# はじめに
この記事は[KotlinでDiscord Botを始めてみる](https://qiita.com/hisuie08/items/264456e505ab75f75bbe)の第二弾です。
前回の記事でKotlin/Gradleの開発環境構築、依存ライブラリJDAを使ったBotの起動までやってみました。
今回は更にBotらしい(?)、**コマンドの実装**をやっていきましょう。
前回よりは文量は少なめになると思いますのでご安心ください。
それでは今回も宜しくおねがいします。

###Gitリポジトリ
前回と同じリポジトリの[Chapter2ブランチ](https://github.com/hisuie08/kotlin-tutorial-bot/tree/chapter2)で今回のコードの実例を紹介しています。

#コマンドを使うための追加ライブラリ
JDAを使ったBotでコマンドを実装するには追加のライブラリ**jda-chewtils**が必要になります。
これはJDAの作者とは別の方が開発していて、JDAとは別に導入する必要があります。

```kotlin:build.gradle.kts
...
repositories {
    ...
    maven("https://m2.chew.pro/releases")
}

dependencies {
    ...
    implementation("com.jagrosh:jda-utilities:3.0.5")
    implementation("pw.chew:jda-chewtils:1.21.0")
}
```
以上の内容を追記してください。

Gradleの変更を読み込んで、`BUILD SUCCESSFUL in ...`定期。

#コマンドを実装したBot
今回も御託は抜きにしてコードを紹介しましょう。
## シンプルなコマンド
挙動は前回と同じ、`/neko`→`にゃーん`の応答です。

```kotlin:main.kt
package ...
import net.dv8tion.jda.api.JDA
import net.dv8tion.jda.api.JDABuilder
import net.dv8tion.jda.api.requests.GatewayIntent
/*ここから下の3つのimportが今回初めて使うコマンド用ライブラリ*/
import com.jagrosh.jdautilities.command.Command
import com.jagrosh.jdautilities.command.CommandClientBuilder
import com.jagrosh.jdautilities.command.CommandEvent

class Neko:Command(){/*Commandクラスを継承してコマンドを定義*/
    init {
        this.name = "neko" /*コマンド文字列の定義はinitブロックの中に書く必要があります。*/
    }
    override fun execute(event: CommandEvent?){
/*executeメソッドはコマンドを叩かれたイベントをキャッチして対応する処理を実行する中核部分です*/
        event?.reply("にゃーん")
/*
ここで使われているreplyメソッドは
event?.message?.channel?.sendMessageFormat("")?.queue()
の簡易呼び出しです。Discordの「返信」とは異なりますのでご注意ください。
*/
    }
}

class BotClient{
    lateinit var jda: JDA
    private val commandPrefix = "/" /*コマンドプレフィックスの指定
                                     空文字列にするとBotへのメンションがプレフィックスとして機能します。
　　　　　　　　　　　　　　　　　　　　このほうがいいかも。*/
    
    fun main(token: String) {
        val commandClient = CommandClientBuilder()
            .setPrefix(commandPrefix)
            .setOwnerId("") /*本来であれば開発者のIDを入れますが、空文字列でもOKです。*/
            .addCommand(Neko())
            /*複数コマンドを登録するときには
              .addCommands(Hoge(),Fuga(),Piyo())
              となります。
            */
            .build()
        
        jda = JDABuilder.createLight(token,
            GatewayIntent.GUILD_MESSAGES)
            .addEventListeners(commandClient)
            .build()
    }
}


fun main() {
    val bot = BotClient()
    bot.main("トークン文字列")
}
```

さあ動かしてみてください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/398976/a27de710-ca81-83c3-7fe8-67cb9e2136d7.png)

## 引数を取るコマンド
`Command`クラスを継承して作成したコマンドはデフォルトで引数を受け付ける事ができます。
渡した文字列の先頭を大文字にするだけのシンプルなコマンドを動かしてみましょう。

```kotlin
class Capitalize:Command(){
    init {
        this.name = "capitalize"
    }
    
    override fun execute(event : CommandEvent?) {
        if(event?.args?.isEmpty()==false){
        /*argsはコマンドに引数が与えられたとき自動的にここに文字列として格納されます。
        空でなかったとき、つまりコマンドに引数がついて呼び出されたときの分岐を記述することになります。
        複数の引数を与えたいときはargsに格納された文字列をスペース毎に区切る等の処理が必要になるでしょう。*/
            event.reply(event.args.capitalize())
        }
    }
}
```

```
.addCommand(Capitalize())
```
を忘れずに。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/398976/f0d9f19e-87f5-c4b6-3468-003f795e9a99.png)

こうなります。

# 最後に
~~余力があれば続きます。~~
次回はEmbedか、より高度なコマンドのカスタマイズを予定しています。
今回もお付き合いいただきありがとうございました。
次回: [Embed実装編](https://qiita.com/hisuie08/items/43e9b48ed02c8f4d40bd)