C#
bot
Splatoon
discord
VisualStudio2017

DiscordのBotをC#で作ってみる

DiscordのBotをC#で作ってみる

開発環境

  • Visual Studio 2017 (C#)
  • Discord.Net 1.0.2

初めに

スプラトゥーン2のAPIをコールするBotを@otuhs_dさんが作成されたのをみて、自分のチーム用に何かできないかを考えました。

そこで、チーム内プライベートマッチでルールとステージをランダムで決定できるものをC#コンソールアプリで作ってみました。

参考

@otuhs_dさんの記事
Splatoon2チーム向けDiscord Bot『Roboty』を公開しました
DiscordのBotにSplatoon2のステージ情報を教えてもらう

実装後のイメージ

WS000018.JPG

「.rl」とText Chatで入力すると、ルールとステージをランダムで表示するという簡単なBot

事前準備としてDiscordでBotの登録

※すでにディスコサーバを作成済みの手順です。

  • ディスコのWebページから More > Depelopers > My Apps を選択。 
  • もしくは、ここから

FireShot Capture 19 - Discord - Developer Documentat_ - https___discordapp.com_developers_docs_intro.png

  • 「New Apps」を押下する。

FireShot Capture 21 - Discord - My Apps - https___discordapp.com_developers_applications_me.png

  • 「App Name」にBotの名前を登録します。
  • 「App Icon」に画像ファイルを置くことで、アイコン化できます。
  • 「Create App」を押下します。

FireShot Capture 22 - Discord - Develope_ - https___discordapp.com_developers_applications_me_create.png

  • 「Create Bot User」を押下します。

FireShot Capture 23 - Discord - Developer Documentation_ - https___discordapp.com_developers_.png

  • 確認メッセージは、そのまま「Yes do it!」を押下します。

FireShot Capture 24 - Discord - Developer Documentation_ - https___discordapp.com_developers_.png

  • 「Public Bot」にチェックを入れます。

FireShot Capture 24 - Discord - Developer Documentation_ - https___discordapp.com_developers_.png

  • 「click to reveal」を押下します。
  • そこで、表示されるTokenをメモっておきます。
  • 画面最下部の「Save changes」を押下します。

FireShot Capture 29 - Discord - Developer Documentation_ - https___discordapp.com_developers_.png

  • 「Generate OAuth2 URL」を押下します。

FireShot Capture 26 - Discord - Developer Documentation_ - https___discordapp.com_developers_.png

  • 「Copy」を押下して、ブラウザで、そのURLを開きます。
  • この際、ClientIDをメモしておいてください。

FireShot Capture 27 - Discord - Developer Documentation_ - https___discordapp.com_developers_.png

  • Botを追加するサーバを選択し、「認証」を押下します。
  • 認証完了後、ブラウザを閉じます。

FireShot Capture 28 - アカウントへのアクセスを許可します_ - https___discordapp.com_oauth2_authorize.png

  • Discordを起動すると、作成したBotが表示されています。

WS000021.png

  • 自身のギアのアイコンから設定を開き > テーマ を選択します。
  • 開発者モードをトグルスイッチをオンにします。

WS000022.JPG

  • サーバのIDをコピーするのに、サーバーを右クリックし「IDのコピー」を選択しメモっておきます。

WS000023.JPG

準備完了!

これで、Botの準備ができたので、この後は、Visual Studioでの作業になります。

メモしたもの 場所 今回使用
ClientID Discord WebページでメモしたClientID ×
Token Discord WebページでメモしたToken
サーバーID Discordアプリの画面左上の「IDをコピー」 ×

今回の説明する機能まででは、○のものだけが必要です。

Visual Studio

プロジェクトの作成

  • Windowsクラシックデスクトップ > コンソールアプリ(.Net Framework) を選択して、「OK」を押下する。

WS000019.JPG

Nugetから「Discord.Net 1.0.2」インストール

  • 「プロジェクトエクスプローラ」>「参照設定」を右クリック >「NuGetパッケージ管理」
  • 「参照」タブを選択 > 検索欄に「Discord.Net」を入力します。
  • 「Discord.Net」を選択します。
  • 最新の安定版を選択して「インストール」ボタンを押下します。

WS000020.JPG

Messagesクラスを作成

  • コメントを受けとった処理を作成します。
:Messages.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Discord.Commands;
using System.Collections.Generic;

namespace Splatoo2ConsoleApp
{
    public class Messages : ModuleBase
    {
        /* ルール列挙 */
        Dictionary<int, string> rule = new Dictionary<int, string>()
        {
            {0, "ナワバリ"},
            {1, "エリア"},
            {2, "ホコ"},
            {3, "ヤグラ"},
            {4, "アサリ"},
        };

        /* ステージ列挙 */
        Dictionary<int, string> stage = new Dictionary<int, string>()
        {
            {0,   "バッテラストリート" },
            {1 ,  "フジツボスポーツクラブ"},
            {2 ,  "ガンガゼ野外音楽堂"},
            {3 ,  "チョウザメ造船"},
            {4 ,  "海女美術大学"},
            {5 ,  "コンブトラック"},
            {6 ,  "マンタマリア号"},
            {7 ,  "ホッケふ頭"},
            {8 ,  "タチウオパーキング"},
            {9 , "エンガワ河川敷"},
            {10, "モズク農園"},
            {11,  "Bバスパーク"},
            {12,  "デボン海洋博物館"},
            {13,  "ザトウマーケット"},
            {14,  "ハコフグ倉庫"},
            {15,  "アロワナモール"}
        };

        /// <summary>
        /// [rl]というコメントが来た際の処理
        /// </summary>
        /// <returns>Botのコメント</returns>
        [Command("rl")]
        public async Task rl()
        {


            Random random = new System.Random();
            int randomRule = random.Next(5);
            int randomStage = random.Next(16);

            string Messages = "次の試合のルールは、\n ・**" + rule[randomRule].ToString() + "**\n\n";
            Messages += "次の試合のステージは、\n ・**" + stage[randomStage].ToString() + "**\n";

            await ReplyAsync(Messages);
        }

    }
}

Program.csクラスを作成

Program.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

using Discord.Commands;
using Discord.WebSocket;
using Microsoft.Extensions.DependencyInjection;
using System.Reflection;
using Discord;

namespace Splatoo2ConsoleApp
{
    class Program
    {
        public static DiscordSocketClient client;
        public static CommandService commands;
        public static IServiceProvider services;

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

        /// <summary>
        /// 起動時処理
        /// </summary>
        /// <returns></returns>
        public async Task MainAsync()
        {
            client = new DiscordSocketClient();
            commands = new CommandService();
            services = new ServiceCollection().BuildServiceProvider();
            client.MessageReceived += CommandRecieved;

            client.Log += Log;
            string token = "メモしたTokeを指定";
            await commands.AddModulesAsync(Assembly.GetEntryAssembly());
            await client.LoginAsync(TokenType.Bot, token);
            await client.StartAsync();

            await Task.Delay(-1);
        }

        /// <summary>
        /// メッセージの受信処理
        /// </summary>
        /// <param name="msgParam"></param>
        /// <returns></returns>
        private async Task CommandRecieved(SocketMessage messageParam)
        {
            var message = messageParam as SocketUserMessage;
            Console.WriteLine("{0} {1}:{2}", message.Channel.Name, message.Author.Username, message);

            if (message == null) { return; }
            // コメントがユーザーかBotかの判定
            if (message.Author.IsBot) { return; }

            int argPos = 0;

            // コマンドかどうか判定(今回は、「.」で判定)
            if (!(message.HasCharPrefix('.', ref argPos) || message.HasMentionPrefix(client.CurrentUser, ref argPos))) { return; }

            var context = new CommandContext(client, message);

            // 実行
            var result = await commands.ExecuteAsync(context, argPos, services);

            //実行できなかった場合
            if (!result.IsSuccess) { await context.Channel.SendMessageAsync(result.ErrorReason); }

        }

        /// <summary>
        /// コンソール表示処理
        /// </summary>
        /// <param name="msg"></param>
        /// <returns></returns>
        private Task Log(LogMessage msg)
        {
            Console.WriteLine(msg.ToString());
            return Task.CompletedTask;
        }
    }
}

作成完了!

  • ビルドを実行します。

WS000024.JPG

  • Discordで「.rl」コメントしてみると、Botがランダムで返してくれます。

WS000025.JPG

まとめ

  • NuGetにDiscord .Netがあるので、比較的簡単に作成することができました。
  • 他にもDiscordの機能をいろいろと触れそうですが、とっかかりとしては、まずまずでした。