🤖
[Rust] DiscordのBOT作成 < serenity > - ⑥
セレクトメニュー作成と応答
選択された項目名を返す
- 下記のようなセレクトメニューを作成し、選ばれた項目の値を返す
セレクトメニュー
ソースコード
- このサンプルではセレクトメニューの選択肢項目を各々作成しているが、項目の数が多い場合は列挙型などでまとめると管理しやすい
- 項目を一度選ぶと変更することができないため、場合によっては確定用のボタンなどを別途追加してもよい
main.rs
use serenity::builder::{CreateActionRow, CreateSelectMenu, CreateSelectMenuOption}; // アクション関係のモジュール
use std::time::Duration; // タイムアウト用
~~~~~~~~~~中略~~~~~~~~~~
if msg.content == "!menu" {
//----------項目1の作成----------
let mut opt1 = CreateSelectMenuOption::default();
opt1.label(format!("{} {}", '\u{1F170}', "A型"));
opt1.value("Atype");
//----------項目2の作成----------
let mut opt2 = CreateSelectMenuOption::default();
opt2.label(format!("{} {}", '\u{1F171}', "B型"));
opt2.value("Btype");
//----------項目3の作成----------
let mut opt3 = CreateSelectMenuOption::default();
opt3.label(format!("{} {}", '\u{1F17E}', "O型"));
opt3.value("Otype");
//----------項目4の作成----------
let mut opt4 = CreateSelectMenuOption::default();
opt4.label(format!("{} {}", '\u{1F18E}', "AB型"));
opt4.value("ABtype");
//----------セレクトメニューの作成----------
let mut menu = CreateSelectMenu::default();
menu.custom_id("menu");
menu.placeholder("選んでください");
menu.options(|f| {
f.add_option(opt1)
.add_option(opt2)
.add_option(opt3)
.add_option(opt4)
});
//----------アクションにセレクトメニューを追加----------
let mut act = CreateActionRow::default();
act.add_select_menu(menu);
//----------メッセージ(セレクトメニュー)の送信----------
let m = msg.channel_id.send_message(&ctx, |m| {
m.content("項目を選択してください")
.components(|c| c.add_action_row(act))
})
.await
.expect("エラー");
//----------インタラクションとタイムアウトの設定----------
let mi = match m
.await_component_interaction(&ctx)
.timeout(Duration::from_secs(10))
.await
{
Some(interaction) => interaction,
None => {
m.delete(&ctx).await.expect("エラー");
msg.reply(&ctx, "タイムアウト").await.expect("エラー");
return
}
};
//----------インタラクションに対する応答----------
m.delete(&ctx).await.expect("エラー");
match &*mi.data.values[0] {
"Atype" => msg.reply(&ctx.http, "A型").await.expect("エラー"),
"Btype" => msg.reply(&ctx.http, "B型").await.expect("エラー"),
"Otype" => msg.reply(&ctx.http, "O型").await.expect("エラー"),
"ABtype" => msg.reply(&ctx.http, "AB型").await.expect("エラー"),
_ => {
println!("エラー");
return
}
};
}
クレートの設定
- 前述のボタンの作成と同じ
Cargo.toml
serenity = { version = "0.11.5", default-features = false, features = ["cache", "client", "collector", "gateway", "rustls_backend", "model"] }
ソースコード解説
項目の作成
-
CreateSelectMenuOption::default()
- 項目のオブジェクトを作成する
- 項目のオブジェクトを作成する
-
.label()
- 項目に表示するテキスト等を設定する
- 項目に表示するテキスト等を設定する
-
.value()
- 項目に持たせる値を設定する
セレクトメニューの作成
let mut opt1 = CreateSelectMenuOption::default();
opt1.label(format!("{} {}", '\u{1F170}', "A型"));
opt1.value("Atype");
opt1.description("これは血液型です");
- 項目の作成時に
.description()
を追加すると、セレクトメニューの説明文を追加できる - 複数の項目で設定した場合、最新のものが反映される
説明文を追加する
let mut opt1 = CreateSelectMenuOption::default();
opt1.label(format!("{} {}", '\u{1F170}', "A型"));
opt1.value("Atype");
opt1.description("これは血液型です"); // 説明文を追加する
説明文を追加する
- 項目の作成時に
.default_selection(true)
を追加すると、セレクトメニュー未選択時のデフォルトの項目に設定できる
セレクトメニューのデフォルト項目
let mut opt1 = CreateSelectMenuOption::default();
opt1.label(format!("{} {}", '\u{1F170}', "A型"));
opt1.value("Atype");
opt1.description("これは血液型です");
opt1.default_selection(true); // デフォルトの項目に設定する
セレクトメニューのデフォルト項目
セレクトメニューの作成
-
CreateSelectMenu::default()
- セレクトメニューのオブジェクトを作成する
- セレクトメニューのオブジェクトを作成する
-
.custom_id()
- セレクトメニューのID(名前)を設定する
- セレクトメニューのID(名前)を設定する
-
.placeholder()
- セレクトメニュー未選択時の表示を設定する
- セレクトメニュー未選択時の表示を設定する
-
.options()
- セレクトメニューの項目を設定する
- セレクトメニューの項目を設定する
-
.add_option()
- セレクトメニューのオブジェクトに作成した項目を追加する
セレクトメニューの作成
let mut menu = CreateSelectMenu::default();
menu.custom_id("menu");
menu.placeholder("選んでください");
menu.options(|f| {
f.add_option(opt1)
.add_option(opt2)
.add_option(opt3)
.add_option(opt4)
});
アクションにセレクトメニューを追加
-
CreateActionRow::default()
- アクションのオブジェクトを作成する
- アクションのオブジェクトを作成する
-
.add_select_menu()
- アクションのオブジェクトに作成したセレクトメニューを追加する
アクションにセレクトメニューを追加
let mut act = CreateActionRow::default();
act.add_select_menu(menu);
メッセージ(セレクトメニュー)の送信
- セレクトメニューの送信には
.send_message()
を使う
-
.components()
-
.send_message()
で送信するテキスト以外のコンポーネント(ここではセレクトメニュー)をセットする
-
-
.add_action_row()
- コンポーネントにアクションのオブジェクトを追加する
メッセージ(セレクトメニュー)の送信
let m = msg.channel_id.send_message(&ctx, |m| {
m.content("ボタンを選択してください")
.components(|c| c.add_action_row(act))
})
.await
.expect("エラー");
インタラクションとタイムアウトの設定
-
.await_component_interaction()
- 送信したメッセージ(ここではセレクトメニュー)に対してのインタラクション(ユーザーが項目を選ぶ動作)を待つ
- 送信したメッセージ(ここではセレクトメニュー)に対してのインタラクション(ユーザーが項目を選ぶ動作)を待つ
-
.timeout()
- インタラクションの待機時間を設定する
-
Duration::from_secs(10)
によって10秒が設定される
- インタラクションが時間内に行われた場合、
Some(interaction)
が返されmi
にインタラクション結果(interaction
)を取り込む - インタラクションがタイムアウトした場合、
None
が返されNone => { }
を実行する
インタラクションとタイムアウトの設定
let mi = match m
.await_component_interaction(&ctx)
.timeout(Duration::from_secs(10))
.await
{
Some(interaction) => interaction,
None => {
m.delete(&ctx).await.expect("エラー");
msg.reply(&ctx, "タイムアウト").await.expect("エラー");
return
}
};
インタラクションに対する応答
-
.delete()
を使用して送信したメッセージ(ここではセレクトメニュー)を削除し、選ばれた項目の値(mi.data.values[0]
)に合わせたリプライを返す
インタラクションに対する応答
m.delete(&ctx).await.expect("エラー");
match &*mi.data.values[0] {
"Atype" => msg.reply(&ctx.http, "A型").await.expect("エラー"),
"Btype" => msg.reply(&ctx.http, "B型").await.expect("エラー"),
"Otype" => msg.reply(&ctx.http, "O型").await.expect("エラー"),
"ABtype" => msg.reply(&ctx.http, "AB型").await.expect("エラー"),
_ => {
println!("エラー");
return
}
};
Discussion