atelier:mitsuba

i love UI/UX, Blend, XAML, Behavior, P5, oF, Web, Tangible Bits and Physical computing. なにかあればお気軽にご連絡ください。atelier@c-mitsuba.com

メメントモリの所属ギルドを支える技術、あるいはDiscord botをC#とAzureで作った話。中編。

この内容で3/3にオンラインでお話します。
meetupapp.connpass.com


前編の続き。
c-mitsuba.hatenablog.com

で、割と必要に駆られてbot作ろうと決めたわけだけど、bot作るのは幾年月前のIRC以来。
しかもDiscordのbotは大体Pythonで作る風潮があるらしく、ちょっとぐぐるとすぐPythonって言われる。。。

discordpy.readthedocs.io
dev.classmethod.jp

Pythonはnot for meなのだけど、botをサーバーに登録する方法は一緒だから、このへんみてもらうってことで割愛ー。




やっぱC#で書きたいし、調べるとDiscord.Netを見つけたから、これを使うことにする。
discordnet.dev

Nugetでサクッとインポートすると使えるみたい。
www.nuget.org


ちょっと前までSlashCommandが未実装だったりしてPythonより枯れてないっぽいんだけど、V3になって割と使えるものになったかなー。

この辺りを読むと始め方が書いてあるのだけど、
discordnet.dev

とりあえず公式のSampleを丸コピ。
github.com

軽く読んでいくと、Program()が呼ばれて、MainAsyncが呼ばれて、

   static void Main(string[] args)
            => new Program()
                .MainAsync()
                .GetAwaiter()
                .GetResult();

tokenでログイン処理をしたあと、StartAsync呼んで、あとはずっと放置しっぱなし。

       public async Task MainAsync()
        {
            // Tokens should be considered secret data, and never hard-coded.
            await _client.LoginAsync(TokenType.Bot, Environment.GetEnvironmentVariable("token"));
            // Different approaches to making your token a secret is by putting them in local .json, .yaml, .xml or .txt files, then reading them on startup.

            await _client.StartAsync();

            // Block the program until it is closed.
            await Task.Delay(Timeout.Infinite);
        }

Program()ではconfigでbotにつけた権限をコードでも使えるようにして、
ReadyAsyncで起動前の初期化イベントをつけたり、MessageReceivedで流れてきたメッセージをキャッチして処理するためのイベントをつけたりしてるっぽい。

    public Program()
        {
            // Config used by DiscordSocketClient
            // Define intents for the client
            var config = new DiscordSocketConfig
            {
                GatewayIntents = GatewayIntents.AllUnprivileged | GatewayIntents.MessageContent
            };

            // It is recommended to Dispose of a client when you are finished
            // using it, at the end of your app's lifetime.
            _client = new DiscordSocketClient(config);

            // Subscribing to client events, so that we may receive them whenever they're invoked.
            _client.Log += LogAsync;
            _client.Ready += ReadyAsync;
            _client.MessageReceived += MessageReceivedAsync;
            _client.InteractionCreated += InteractionCreatedAsync;
        }

とりあえずこのサンプルでは!pingってどっかのチャンネルで検知すると、そのチャンネルでボタンだして、ボタン押したらpong!って帰ってくるサンプルみたい。

    public Program()
        {
            // Config used by DiscordSocketClient
            // Define intents for the client
            var config = new DiscordSocketConfig
            {
                GatewayIntents = GatewayIntents.AllUnprivileged | GatewayIntents.MessageContent
            };

            // It is recommended to Dispose of a client when you are finished
            // using it, at the end of your app's lifetime.
            _client = new DiscordSocketClient(config);

            // Subscribing to client events, so that we may receive them whenever they're invoked.
            _client.Log += LogAsync;
            _client.Ready += ReadyAsync;
            _client.MessageReceived += MessageReceivedAsync;
            _client.InteractionCreated += InteractionCreatedAsync;
        }

SlashCommandがなかったり、定期メッセージを送ったりはないけど、とりあえず自分のサーバーにbotがこれで生えてくればOK!

デプロイに関しては、かずきさんのブログを参考に、Azure WebJobsを使いました。
blog.okazuki.jp

じゃあこのサンプルからどう手を加えていったか、は次回にします。