C#でDiscordのBotを作ろう

Table of Content

Discordはとても素晴らしいコミュニケーションツールです。
今回はそんなDiscordでBotを作る時のための自分用の備忘録も兼ねて書き残しておこうと思います。
ある程度C#はわかっている前提です


今回の環境

  • windows10 Pro 64bit
  • Visual Studio 2017 Community
  • Discord.Net 1.0.2 – 以下環境依存パッケージ

 

1.Discordアカウント登録

とにもかくにもDicordアカウントを作らなければ話になりません。

  1. ここから新規登録をしましょう。
  2. ログインをして、サーバーを作成してください。
  3. windowsにDiscordのクライアントを導入することを強くお勧めします。

 

2.Botの登録

  1. ここを開いてNew Appをクリック。
  2. APP NAMEにBot名を入力(日本語可)
    APP DESCRIPTIONにBotの説明を入力(日本語可)
    APP ICONにBotのアイコン画像を登録。
  3. Create Appをクリック。
  4. Botの詳細ページが表示されるので、
    Create a Bot Userをクリック。
  5. 表示されたClient IDtokenをメモしておく。
  6. discordapp.com/oauth2/authorize?client_id=コピーしたClient ID&scope=bot&permissions=0
    をブラウザのURL欄に入力し開く。
    するとサーバー選択が表示されるので、Botを追加したいサーバーを選択して認証をクリック。
  7. サーバーにBotが追加されたことを確認する。

 

3.プログラムの作成

Botのプログラムをなんとなくで作成する。

  1. プロジェクトから新規作成。
    今回はコンソールアプリ(.NETFramework)を選択
  2. ソリューションエクスプローラーからプロジェクトを右クリック。
    アプリケーションタブからターゲットフレームワーク.NETFramework4.6.2に選択。
  3. ソリューションエクスプローラーからプロジェクトを右クリック。
    Nugetパッケージの管理を選択。
    参照タブの検索入力欄にDiscord.Netを入力、見つかったパッケージをインストール。
  4. とりあえず説明が面倒なので以下を参考にプログラムしてみてほしい(ごめん)
    このようにすればとりあえずユーザーがサーバーにログインしたときやログアウトしたとき、また何か発言したときのイベントを拾うことができる。
using Discord;
using Discord.Commands;
using Discord.WebSocket;
using Microsoft.Extensions.DependencyInjection;
using System;
using System.Reflection;

namespace TestProgram
{
    class Program
    {
        public static DiscordSocketClient client;
        public static CommandService commands;
        public static IServiceProvider services;
        private const ulong channelid = チャンネルID;


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


        public async Task MainAsync()
        {

            client = new DiscordSocketClient();
            commands = new CommandService();
            services = new ServiceCollection().BuildServiceProvider();
            client.MessageReceived += CommandRecieved;
            client.UserJoined += UserJoined;
            client.UserLeft += UserLeft;
            client.Log += Log;

            string token = "さっきコピーしたToken";
            await commands.AddModulesAsync(Assembly.GetEntryAssembly());
            await client.LoginAsync(TokenType.Bot, token);
            await client.StartAsync();


            var twitter = new API.Twitter.Streaming(client);
            twitter.StartStreaming();

            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);
            //メッセージがnullの場合
            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="user"></param>
        /// <returns></returns>
        private async Task UserJoined(SocketGuildUser user)
        {
            var chatchannnel = client.GetChannel(channelid) as SocketTextChannel;
            string welcome = string.Format("{0}様、ようこそ!", user.Username);
            await chatchannnel.SendMessageAsync(welcome);
        }

        /// <summary>
        /// ユーザーが会議から抜けたときの処理
        /// </summary>
        /// <param name="user"></param>
        /// <returns></returns>
        private async Task UserLeft(SocketGuildUser user)
        {
            var chatchannnel = client.GetChannel(channelid) as SocketTextChannel;
            string bye = string.Format("{0}様さようなら、またのお越しをお待ちしております", user.Username);
            await chatchannnel.SendMessageAsync(bye);
        }
        

        private Task Log(LogMessage msg)
        {
            Console.WriteLine(msg.ToString());
            return Task.CompletedTask;
        }
    }
}

4.コマンドの実装

今回は簡単に!pingと打つとpongと帰ってくるだけのコマンドを実装してみることにする。

  1. ソリューションエクスプローラーからプロジェクトを右クリックして適当なクラスファイルを作成する。
  2. 作成したクラスに
    using System.Threading.Tasks;
    using Discord.Commands;
    を追記
  3. class クラス名となっているところをpublic class クラス名 : ModuleBaseに書き換え。
  4. 処理を書く。
using Discord.Commands;
using System.Threading.Tasks;

namespace TestProgram
{
    public class TestClass : ModuleBase
    {
        [Command("ping")]
        public async Task Ping()
        {
            await ReplyAsync("pong");
        }
    }
}

あとはビルドしてBotがいるサーバーに!pingと打ってみてpongと返ってくれば成功。

5.Discordを開発者モードにしよう

Discordを開発者モードにすることで、各チャンネルやサーバーのIDを取得できるようになるので非常に便利。

  1. Discordアプリケーションの自分の名前の横にある歯車マークをクリック。
  2. テーマタブをクリックして下の方に行くと詳細設定の欄に開発者モードというのがあるのでそれを有効にする。
  3. IDを調べたいサーバーやチャンネルを右クリックするとIDをコピーが表示されていると思うので、それをクリックすれば取得できます。
2017年11月
 12345
6789101112
13141516171819
20212223242526
27282930  

ブログ統計情報

統計情報の取得中に問題が発生しました。後ほど、もう一度お試しください。

6 Comments

  1. 匿名

    pingと入力してもUnknown が出ます。

    1. クラスをpublicにしてないのではないでしょうか
      public クラス名 : ModuleBaseです。
      再度ご確認ください

      1. 訂正
        public class クラス名 : ModuleBaseです。

  2. cartier men replica ring

    Wow. He would be the first Christian I have ever seen that thinks Israel becoming a nation is not significant. Gotta wonder if someone is truly saved with that P.O.V.

  3. 匿名

    var twitter = new API.Twitter.Streaming(client);
    の ↑↑↑のAPIという部分が
    エラーになります。どのように対処すればよろしいでしょうか。

  4. peyang server

    var twitter (ryでえらーでる

コメントを残す

%d人のブロガーが「いいね」をつけました。