0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Discord.Net 備忘録

Last updated at Posted at 2021-03-03

前置き

 作りながら得た知識の備忘録なので、一部不正確な情報があるかもしれません。本記事の内容をうのみにするのではなく、API開発者のドキュメントを確認するようお願いします。なお本記事は1から作ってみよう!といった内容ではなく、APIの解説寄りになっています。
 感想、指摘等コメントお待ちしております。

Discord Botとは

 Discordを使う上でロールの変更など、手動でやるのは面倒な操作がありますよね。そんな時はプログラムに働いてもらいましょう!
 こちらのDeveloper PortalからBotを簡単に作成できます。詳細の手順が気になる場合は、他の方の記事を確認してみてください。

Discord.Netについて

 Discord Botを作るためのAPIは様々なものが公開されています。Discord.pyやDiscord.jsがとくに有名なようです。
 今回はMicrosoftの.NETで動くDiscord.Netを採用することにします。理由は私が.NET好きだというのと、Linqなど扱いやすいライブラリが多い(個人差あり)からです。
 ちなみに同じく.NET用APIでDSharpPlusというものも公開されています。

0. サンプル

1. 初期設定

 Visual Studio 2019で.NET Frameworkもしくは.NET Coreのコンソールアプリケーション用プロジェクトを作成します。本記事執筆時点でフレームワークのバージョンは.NET Core 3.1を採用しています。
 Discord.NETのライブラリはNuGetから落とせます。NuGetパッケージマネージャーを開き、Discord.NetMicrosoft.Extensions.DependencyInjectionをプロジェクトにインポートします。

2. 初期化

 Botを動かすために必要なものは大きく分けて3種類あります。順を追って説明していきます。

1. Bot本体

 Discord.WebSocket.DiscordSocketClientクラスはユーザーとしての基本機能を提供します。基本的にこのクラスのインスタンスを通してBot自身への操作をしていくことになります。

2. コマンド

 Discord.Commands.CommandServiceクラスは後述するコマンド群を管理するために使用されます。コマンドの登録はDependency Injection(依存性注入)を利用して自動で行われます。

3. サービスプロバイダー

 Dependency Injectionによってコマンドを登録、取得するために使用されます。

 これらをコードにすると以下のようになります。

private DiscordSocketClient client;
private CommandService commands;
private IServiceProvider serviceProvider;

public async Task MainAsync(){
    serviceProvider = new ServiceCollection().BuildServiceProvider();
    commands = new CommandService();
    await commands.AddModulesAsync(Assembly.GetEntryAssembly(), serviceProvider);
    client = new DiscordSocketClient();
}

3. 処理の登録

 クライアントにはメッセージ受信時をはじめ、様々なタイミングで呼ばれるイベントが実装されています。ここに処理を登録することでBotに固有の処理をさせることができます。

public async MainAsync(){
    client.Log += Log;
    client.MessageReceived += CommandReceived;
}

private async Task Log(LogMessage message){
    Console.WriteLine(message.ToString());
}

private async Task CommandReceived(SocketMessage message){
    var msg = msg as SocketUserMessage;
    if(message == null) return;
    if(message.Author.IsBot) return;

    int argPos = 0;
    var command = new CommandContext(client, msg);
    await commands.ExecuteAsync(command, argPos, serviceProvider);
}

4. コマンドの作成

 Discord.Commands.ModuleBaseを継承したクラスにメソッドを追加することで、独自のコマンドを実装することができます。

public class CommandModule : ModuleBase{
    /// <summary>
    /// Helloと返す
    /// </summary>
    [Commands("hello")]    //コマンドとして使用する文字列をアトリビュートで設定
    public async Task SayHelloAsync(){
        await ReplyAsync("Hello!");
    }
}

 引数付きのコマンドを作成する場合は以下のようにします。

public class CommandModule : ModuleBase{
    /// <summary>
    /// 入力したロールが付与されたユーザー名を列挙する。
    /// </summary>
    [Commands("show")]
    public async Task EchoAsync([Summary("対象のロール名")] string rollName){
        var role = Context.Guild.Roles.FirstOrDefault(rl => rl.ToString() == rollName);
        var users = Context.Guild.GetUsersAsync();

        foreach(var _user in users){
            var user = _user as SocketGuildUser;
            if(user.Roles.Contains(role)){
                await ReplyAsync(user.Username);
            }
        }
    }
}

詳細設定

 一部API機能の使用にはDiscord Gateway Intentを有効にする必要があります。例えば上記のコマンド例で使用した、ユーザーリストを取得するメソッドを有効化するには、これらのインテントを有効化が必要です。
 Discord Developer Portalの個別アプリケーションのページから設定を操作できます。

その他

 コマンドの登録のために使用しているDependency Injection(依存性注入)は、クラス間の依存関係を疎結合にし、単体テストをしやすくするためにしばしば使われます。詳細はDependency Injectionについてまとめている記事をご確認ください。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?