🤖

[Rust] DiscordのBOT作成 < serenity > - ①

2022/08/31に公開

簡単なメッセージに応答する

「!hello」対して「Hello」を返す

  • 下記のように簡単なメッセージに対し、BOTが応答してメッセージを返す


「!hello」対して「Hello」を返す

ソースコード全文

main.rs
//******************************クレート等のパス******************************
use serenity::async_trait;                  // 非同期処理のトレイト
use serenity::model::channel::Message;      // メッセージのオブジェクト
use serenity::model::gateway::Ready;        // ゲートウェイ(Bot)の初期パラメータ
use serenity::prelude::*;                   // 各種オブジェクト類のセット

//******************************イベントハンドラ******************************
struct Handler;     // オブジェクト定義

#[async_trait]
impl EventHandler for Handler {     // イベントハンドラの中身を実装

    //====================BOTの起動時の応答====================
    async fn ready(&self, _: Context, ready: Ready) {
        println!("{} が起動しました\n\n[CTRL + C] で BOT を終了", ready.user.name);
    }

    //====================メッセージへの応答====================
    async fn message(&self, ctx: Context, msg: Message) {

        if msg.content == "!hello" {        // !hello 対する応答
            if let Err(why) = msg.channel_id.say(&ctx.http, "\u{1f600} Hello!").await {
                println!("メッセージ送信エラー : {:?}", why);
            }
        }
    }
}

//******************************メイン関数******************************
#[tokio::main]
async fn main() {

    //====================インテントの設定====================
    let intents = GatewayIntents::GUILD_MESSAGES
        | GatewayIntents::MESSAGE_CONTENT;

    //====================BOTの生成====================
    let mut client = Client::builder("ここにトークンを書く", intents)
        .event_handler(Handler)
        .await
        .expect("BOTの生成エラー");

    //====================BOTの起動====================
    if let Err(why) = client.start().await {
        println!("BOTの起動エラー : {:?}", why);
    }
}

ソースコード解説

クレートの設定

  • Cargo.tomlファイル内のdependenciesに、非同期処理クレートのtokioとDiscordクレートのserenityを追加する
Cargo.toml
[package]
name = "自由な名前"
version = "0.1.0"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
tokio = { version = "1.0", features = ["macros", "rt-multi-thread"] }       # 非同期処理
serenity = { version = "0.11.5", default-features = false, features = ["client", "gateway", "rustls_backend", "model"] }       # Discord

パス宣言部

  • 関数等のパスを省略したい場合はuseを用いる
  • ソースを改変する際は適宜必要なものを追加すること
main.rs
//******************************クレート等のパス******************************
use serenity::async_trait;                  // 非同期処理のトレイト
use serenity::model::channel::Message;      // メッセージのオブジェクト
use serenity::model::gateway::Ready;        // ゲートウェイ(Bot)の初期パラメータ
use serenity::prelude::*;                   // 各種オブジェクト類のセット

イベントハンドラ部

  • async fn ready(&self, _: Context, ready: Ready)
    • BOTが起動した際の動作を設定する
    • ここではBOTが起動通知をprintln!()でターミナルへ表示
    • ready.user.nameはBOT自身の名前

  • async fn message(&self, ctx: Context, msg: Message)
    • メッセージがサーバーに送信された際の動作を設定する
    • メッセージ内容に無関係に応答するので、このあとに条件分岐の追加が必要
    • ここではif文でメッセージ内容が!helloの時のみ応答するように設定
    • msg.contentはメッセージ内容

  • if let Err(why) = msg.channel_id.say(&ctx.http, "").await
    • !helloと同じサーバーチャンネルにメッセージを送信する
    • 送信に失敗した場合、エラー内容を取り出しprintln!()でをターミナルへ表示
main.rs
//******************************イベントハンドラ******************************
struct Handler;     // オブジェクト定義

#[async_trait]
impl EventHandler for Handler {     // イベントハンドラの中身を実装

    //====================BOTの起動時の応答====================
    async fn ready(&self, _: Context, ready: Ready) {
        println!("{} が起動しました\n\n[CTRL + C] で BOT を終了", ready.user.name);
    }

    //====================メッセージへの応答====================
    async fn message(&self, ctx: Context, msg: Message) {

        if msg.content == "!hello" {        // !hello 対する応答
            if let Err(why) = msg.channel_id.say(&ctx.http, "\u{1f600} Hello!").await {
                println!("メッセージ送信エラー : {:?}", why);
            }
        }
    }
}

main関数部

  • let intents =
    • BOTが行動可能な権限を与える
    • GatewayIntents::GUILD_MESSAGESはサーバーメッセージの作成関連
    • GatewayIntents::MESSAGE_CONTENTはメッセージ全般
    • 特権のインテントはDiscord Developer Portal側の設定も必要

  • let mut client =
    • BOTのオブジェクトを生成する
    • Client::builder("", intents)でBOTのトークンとインテントをセット
    • .event_handler(Handler)でイベントハンドラをセット

  • if let Err(why) = client.start().await
    • BOTを起動する
    • 起動に失敗した場合、エラー内容を取り出しprintln!()でをターミナルへ表示
main.rs
//******************************メイン関数******************************
#[tokio::main]
async fn main() {

    //====================インテントの設定====================
    let intents = GatewayIntents::GUILD_MESSAGES
        | GatewayIntents::MESSAGE_CONTENT;

    //====================BOTの生成====================
    let mut client = Client::builder("ここにトークンを書く", intents)
        .event_handler(Handler)
        .await
        .expect("BOTの生成エラー");

    //====================BOTの起動====================
    if let Err(why) = client.start().await {
        println!("BOTの起動エラー : {:?}", why);
    }
}

Discussion