From b32a966872fde6c01c7ea8e0b3cd7cbf118f31f5 Mon Sep 17 00:00:00 2001
From: jonaro00 <54029719+jonaro00@users.noreply.github.com>
Date: Wed, 24 Jan 2024 16:42:59 +0100
Subject: [PATCH] chore: update serenity examples after 0.37
---
examples/poise.mdx | 26 ++++---
examples/serenity-todo.mdx | 155 +++++++++++++++++++------------------
examples/serenity.mdx | 6 +-
3 files changed, 95 insertions(+), 92 deletions(-)
diff --git a/examples/poise.mdx b/examples/poise.mdx
index 405ad39..849ad51 100644
--- a/examples/poise.mdx
+++ b/examples/poise.mdx
@@ -14,9 +14,9 @@ This example shows how to build a Poise bot with Shuttle that responds to the `/
```rust src/main.rs
use anyhow::Context as _;
-use poise::serenity_prelude as serenity;
+use poise::serenity_prelude::{ClientBuilder, GatewayIntents};
use shuttle_secrets::SecretStore;
-use shuttle_poise::ShuttlePoise;
+use shuttle_serenity::ShuttleSerenity;
struct Data {} // User data, which is stored and accessible in all command invocations
type Error = Box;
@@ -30,7 +30,7 @@ async fn hello(ctx: Context<'_>) -> Result<(), Error> {
}
#[shuttle_runtime::main]
-async fn poise(#[shuttle_secrets::Secrets] secret_store: SecretStore) -> ShuttlePoise {
+async fn main(#[shuttle_secrets::Secrets] secret_store: SecretStore) -> ShuttleSerenity {
// Get the discord token set in `Secrets.toml`
let discord_token = secret_store
.get("DISCORD_TOKEN")
@@ -41,19 +41,20 @@ async fn poise(#[shuttle_secrets::Secrets] secret_store: SecretStore) -> Shuttle
commands: vec![hello()],
..Default::default()
})
- .token(discord_token)
- .intents(serenity::GatewayIntents::non_privileged())
.setup(|ctx, _ready, framework| {
Box::pin(async move {
poise::builtins::register_globally(ctx, &framework.options().commands).await?;
Ok(Data {})
})
})
- .build()
+ .build();
+
+ let client = ClientBuilder::new(discord_token, GatewayIntents::non_privileged())
+ .framework(framework)
.await
.map_err(shuttle_runtime::CustomError::new)?;
- Ok(framework.into())
+ Ok(client.into())
}
```
@@ -63,19 +64,20 @@ DISCORD_TOKEN = 'the contents of your discord token'
```toml Cargo.toml
[package]
-name = "hello-world"
+name = "hello-world-poise-bot"
version = "0.1.0"
edition = "2021"
publish = false
[dependencies]
-anyhow = "1.0.71"
-poise = "0.5.5"
-shuttle-poise = "0.37.0"
+anyhow = "1.0.68"
+poise = "0.6.1"
shuttle-runtime = "0.37.0"
shuttle-secrets = "0.37.0"
+# Since poise is a serenity command framework, it can run on Shuttle with shuttle-serenity
+shuttle-serenity = "0.37.0"
tracing = "0.1.37"
-tokio = "1.28.2"
+tokio = "1.26.0"
```
diff --git a/examples/serenity-todo.mdx b/examples/serenity-todo.mdx
index 252745a..a0ef024 100644
--- a/examples/serenity-todo.mdx
+++ b/examples/serenity-todo.mdx
@@ -28,12 +28,13 @@ For this example we also need a `GuildId`.
For more information please refer to the [Discord docs](https://discord.com/developers/docs/getting-started) as well as the [Serenity repo](https://github.com/serenity-rs/serenity) for more examples.
-```Rust src/main.rs
+```rust src/main.rs
use anyhow::Context as _;
use serenity::async_trait;
-use serenity::model::application::command::CommandOptionType;
-use serenity::model::application::interaction::application_command::CommandDataOptionValue;
-use serenity::model::application::interaction::{Interaction, InteractionResponseType};
+use serenity::builder::{
+ CreateCommand, CreateCommandOption, CreateInteractionResponse, CreateInteractionResponseMessage,
+};
+use serenity::model::application::{CommandDataOptionValue, CommandOptionType, Interaction};
use serenity::model::gateway::Ready;
use serenity::model::id::GuildId;
use serenity::prelude::*;
@@ -51,54 +52,52 @@ struct Bot {
#[async_trait]
impl EventHandler for Bot {
async fn interaction_create(&self, ctx: Context, interaction: Interaction) {
- let user_id: i64 = interaction
- .clone()
- .application_command()
- .unwrap()
- .user
- .id
- .into();
-
- if let Interaction::ApplicationCommand(command) = interaction {
+ if let Interaction::Command(command) = interaction {
info!("Received command interaction: {:#?}", command);
+ let user_id: i64 = command.user.id.into();
+
let content = match command.data.name.as_str() {
"todo" => {
- let command = command.data.options.get(0).expect("Expected command");
+ let command = command.data.options.first().expect("Expected command");
- // if the todo subcommand has a CommandOption the command is either `add` or `complete`
- if let Some(subcommand) = command.options.get(0) {
- match subcommand.resolved.as_ref().expect("Valid subcommand") {
- CommandDataOptionValue::String(note) => {
+ match command.name.as_str() {
+ "add" => match &command.value {
+ CommandDataOptionValue::SubCommand(opts) => {
+ let note = opts.first().unwrap().value.as_str().unwrap();
db::add(&self.database, note, user_id).await.unwrap()
}
- CommandDataOptionValue::Integer(index) => {
- db::complete(&self.database, index, user_id)
+ _ => "Command not implemented".to_string(),
+ },
+ "complete" => match &command.value {
+ CommandDataOptionValue::SubCommand(opts) => {
+ let index = opts.first().unwrap().value.as_i64().unwrap();
+ db::complete(&self.database, &index, user_id)
.await
.unwrap_or_else(|_| {
"Please submit a valid index from your todo list"
.to_string()
})
}
- _ => "Please enter a valid todo".to_string(),
- }
- // if the todo subcommand doesn't have a CommandOption the command is `list`
- } else {
- db::list(&self.database, user_id).await.unwrap()
+ _ => "Command not implemented".to_string(),
+ },
+ "list" => db::list(&self.database, user_id).await.unwrap(),
+ _ => "Command not implemented".to_string(),
}
}
_ => "Command not implemented".to_string(),
};
if let Err(why) = command
- .create_interaction_response(&ctx.http, |response| {
- response
- .kind(InteractionResponseType::ChannelMessageWithSource)
- .interaction_response_data(|message| message.content(content))
- })
+ .create_response(
+ &ctx.http,
+ CreateInteractionResponse::Message(
+ CreateInteractionResponseMessage::new().content(content),
+ ),
+ )
.await
{
- error!("Cannot respond to slash command: {}", why);
+ error!("Cannot respond to slash command: {why}");
}
}
}
@@ -106,51 +105,53 @@ impl EventHandler for Bot {
async fn ready(&self, ctx: Context, ready: Ready) {
info!("{} is connected!", ready.user.name);
- let guild_id = GuildId(self.guild_id.parse().unwrap());
+ let guild_id = GuildId::new(self.guild_id.parse().unwrap());
- let _ = GuildId::set_application_commands(&guild_id, &ctx.http, |commands| {
- commands.create_application_command(|command| {
- command
- .name("todo")
+ let _ = guild_id
+ .set_commands(
+ &ctx.http,
+ vec![CreateCommand::new("todo")
.description("Add, list and complete todos")
- .create_option(|option| {
- option
- .name("add")
- .description("Add a new todo")
- .kind(CommandOptionType::SubCommand)
- .create_sub_option(|option| {
- option
- .name("note")
- .description("The todo note to add")
- .kind(CommandOptionType::String)
- .min_length(2)
- .max_length(100)
- .required(true)
- })
- })
- .create_option(|option| {
- option
- .name("complete")
- .description("The todo to complete")
- .kind(CommandOptionType::SubCommand)
- .create_sub_option(|option| {
- option
- .name("index")
- .description("The index of the todo to complete")
- .kind(CommandOptionType::Integer)
- .min_int_value(1)
- .required(true)
- })
- })
- .create_option(|option| {
- option
- .name("list")
- .description("List your todos")
- .kind(CommandOptionType::SubCommand)
- })
- })
- })
- .await;
+ .add_option(
+ CreateCommandOption::new(
+ CommandOptionType::SubCommand,
+ "add",
+ "Add a new todo",
+ )
+ .add_sub_option(
+ CreateCommandOption::new(
+ CommandOptionType::String,
+ "note",
+ "The todo note to add",
+ )
+ .min_length(2)
+ .max_length(100)
+ .required(true),
+ ),
+ )
+ .add_option(
+ CreateCommandOption::new(
+ CommandOptionType::SubCommand,
+ "complete",
+ "The todo to complete",
+ )
+ .add_sub_option(
+ CreateCommandOption::new(
+ CommandOptionType::Integer,
+ "index",
+ "The index of the todo to complete",
+ )
+ .min_int_value(1)
+ .required(true),
+ ),
+ )
+ .add_option(CreateCommandOption::new(
+ CommandOptionType::SubCommand,
+ "list",
+ "List your todos",
+ ))],
+ )
+ .await;
}
}
@@ -260,17 +261,17 @@ GUILD_ID = "123456789"
```toml Cargo.toml
[package]
-name = "serenity-postgres"
+name = "postgres-serenity-bot"
version = "0.1.0"
edition = "2021"
[dependencies]
anyhow = "1.0.66"
serde = "1.0.148"
-serenity = { version = "0.11.5", default-features = false, features = ["client", "gateway", "rustls_backend", "model"] }
+serenity = { version = "0.12.0", default-features = false, features = ["client", "gateway", "rustls_backend", "model"] }
+shuttle-runtime = "0.37.0"
shuttle-secrets = "0.37.0"
shuttle-serenity = "0.37.0"
-shuttle-runtime = "0.37.0"
shuttle-shared-db = { version = "0.37.0", features = ["postgres", "sqlx"] }
sqlx = "0.7.1"
tokio = "1.26.0"
diff --git a/examples/serenity.mdx b/examples/serenity.mdx
index 4f88d50..4592349 100644
--- a/examples/serenity.mdx
+++ b/examples/serenity.mdx
@@ -84,16 +84,16 @@ DISCORD_TOKEN = 'the contents of your discord token'
```toml Cargo.toml
[package]
-name = "hello-world"
+name = "hello-world-serenity-bot"
version = "0.1.0"
edition = "2021"
[dependencies]
anyhow = "1.0.66"
-shuttle-serenity = "0.37.0"
+serenity = { version = "0.12.0", default-features = false, features = ["client", "gateway", "rustls_backend", "model"] }
shuttle-runtime = "0.37.0"
-serenity = { version = "0.11.5", default-features = false, features = ["client", "gateway", "rustls_backend", "model"] }
shuttle-secrets = "0.37.0"
+shuttle-serenity = "0.37.0"
tokio = "1.26.0"
tracing = "0.1.37"
```