RustでDiscordボットを作る

2024年04月30日

RustでDiscordに投稿するCLIを作ります。

実行環境

  • M2 Mac
  • Rust 1.76

準備

Discordの設定からwebhookを作成します。

1

ウェブフックURLが発行されるのでコピーします。 このURLが投稿のPOST先となります。

https://discord.com/api/webhooks/xxxxxxxx/xxx

ライブラリをインストールする

httpリクエストはreqwestを使います。POSTデータはjsonにシリアライズする必要があるのでserde_jsonもインストールしておきます。

[dependencies]
reqwest = { workspace = true, features = ["json"] }
clap = { workspace = true, features = ["derive"] }
tokio = { workspace = true, features = ["full"] }
serde = { workspace = true, features = ["derive"] }
serde_json = { workspace = true }

実装する

まずは投稿データのリクエストDTOを定義します。

#[derive(Debug, Clone, Serialize)]
struct Message {
    content: String,
}

impl Message {
    fn new(message: &str) -> Self {
        Self {
            content: message.to_string(),
        }
    }
}

文字列を投稿する関数を定義します。 WEBHOOK_URLには準備で作成したwebhookのURLを指定します。

async fn send_message(s: &str) -> Result<(), Box<dyn std::error::Error>> {
    let mut headers = HeaderMap::new();
    headers.append(
        "Content-Type",
        "application/json"
            .parse()
            .expect("application/jsonがパースできない"),
    );

    let message = Message::new(s);
    let message = serde_json::to_vec(&message).expect("jsonにserializeできません");
    let response = reqwest::Client::new()
        .post(WEBHOOK_URL)
        .headers(headers)
        .body(Body::from(message))
        .send()
        .await
        .expect("エラー");
    if !response.status().is_success() {
        tracing::error!("discordがエラーを応答しました, {:?}", response.text().await);
    }
    Ok(())
}

メイン関数を定義します。

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    send_message("いぇい").await
}

URLにjsonをpostするだけなのでとても簡単!


Profile picture

Written by なまちゃ Web系エンジニアPython好き。バックエンド/フロントエンド問わずマルチな方面でエンジニアリングしています。