Skip to content

Commit

Permalink
Enforce required fields for builders (serenity-rs#2087)
Browse files Browse the repository at this point in the history
This commit adds enforcement for unconditionally required fields on builders.
It does so by removing the implementation of `Default` on those builders and
adding a `new` method that takes the required fields as argument.
  • Loading branch information
mkrasnitski committed May 30, 2023
1 parent 9b471ec commit 08711cd
Show file tree
Hide file tree
Showing 66 changed files with 704 additions and 472 deletions.
2 changes: 1 addition & 1 deletion examples/e03_struct_utilities/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ impl EventHandler for Handler {
// In this case, you can direct message a User directly by simply
// calling a method on its instance, with the content of the
// message.
let builder = CreateMessage::default().content("Hello!");
let builder = CreateMessage::new().content("Hello!");
let dm = msg.author.dm(&context, builder).await;

if let Err(why) = dm {
Expand Down
2 changes: 1 addition & 1 deletion examples/e05_command_framework/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -565,7 +565,7 @@ async fn am_i_admin(ctx: &Context, msg: &Message, _args: Args) -> CommandResult
#[command]
async fn slow_mode(ctx: &Context, msg: &Message, mut args: Args) -> CommandResult {
let say_content = if let Ok(slow_mode_rate_seconds) = args.single::<u64>() {
let builder = EditChannel::default().rate_limit_per_user(slow_mode_rate_seconds);
let builder = EditChannel::new().rate_limit_per_user(slow_mode_rate_seconds);
if let Err(why) = msg.channel_id.edit(&ctx.http, builder).await {
println!("Error setting channel's slow mode rate: {:?}", why);

Expand Down
6 changes: 3 additions & 3 deletions examples/e09_create_message_builder/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@ impl EventHandler for Handler {
// using a builder syntax.
// This example will create a message that says "Hello, World!", with an embed that has
// a title, description, an image, three fields, and a footer.
let footer = CreateEmbedFooter::default().text("This is a footer");
let embed = CreateEmbed::default()
let footer = CreateEmbedFooter::new("This is a footer");
let embed = CreateEmbed::new()
.title("This is a title")
.description("This is a description")
.image("attachment://ferris_eyes.png")
Expand All @@ -31,7 +31,7 @@ impl EventHandler for Handler {
// Add a timestamp for the current time
// This also accepts a rfc3339 Timestamp
.timestamp(Timestamp::now());
let builder = CreateMessage::default()
let builder = CreateMessage::new()
.content("Hello, World!")
.embed(embed)
.add_file("./ferris_eyes.png");
Expand Down
4 changes: 2 additions & 2 deletions examples/e13_parallel_loops/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ async fn log_system_load(ctx: &Context) {

// We can use ChannelId directly to send a message to a specific channel; in this case, the
// message would be sent to the #testing channel on the discord server.
let embed = CreateEmbed::default()
let embed = CreateEmbed::new()
.title("System Resource Load")
.field("CPU Load Average", &format!("{:.2}%", cpu_load.one * 10.0), false)
.field(
Expand All @@ -90,7 +90,7 @@ async fn log_system_load(ctx: &Context) {
),
false,
);
let builder = CreateMessage::default().embed(embed);
let builder = CreateMessage::new().embed(embed);
let message = ChannelId::new(381926291785383946).send_message(&ctx, builder).await;
if let Err(why) = message {
eprintln!("Error sending message: {:?}", why);
Expand Down
15 changes: 7 additions & 8 deletions examples/e14_slash_commands/src/commands/attachmentinput.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,13 @@ pub fn run(options: &[ResolvedOption]) -> String {
}

pub fn register() -> CreateApplicationCommand {
CreateApplicationCommand::default()
.name("attachmentinput")
.description("Test command for attachment input")
CreateApplicationCommand::new("attachmentinput", "Test command for attachment input")
.add_option(
CreateApplicationCommandOption::default()
.name("attachment")
.description("A file")
.kind(CommandOptionType::Attachment)
.required(true),
CreateApplicationCommandOption::new(
CommandOptionType::Attachment,
"attachment",
"A file",
)
.required(true),
)
}
7 changes: 2 additions & 5 deletions examples/e14_slash_commands/src/commands/id.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,8 @@ pub fn run(options: &[ResolvedOption]) -> String {
}

pub fn register() -> CreateApplicationCommand {
CreateApplicationCommand::default().name("id").description("Get a user id").add_option(
CreateApplicationCommandOption::default()
.name("id")
.description("The user to lookup")
.kind(CommandOptionType::User)
CreateApplicationCommand::new("id", "Get a user id").add_option(
CreateApplicationCommandOption::new(CommandOptionType::User, "id", "The user to lookup")
.required(true),
)
}
34 changes: 17 additions & 17 deletions examples/e14_slash_commands/src/commands/numberinput.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,25 +2,25 @@ use serenity::builder::{CreateApplicationCommand, CreateApplicationCommandOption
use serenity::model::prelude::command::CommandOptionType;

pub fn register() -> CreateApplicationCommand {
CreateApplicationCommand::default()
.name("numberinput")
.description("Test command for number input")
CreateApplicationCommand::new("numberinput", "Test command for number input")
.add_option(
CreateApplicationCommandOption::default()
.name("int")
.description("An integer from 5 to 10")
.kind(CommandOptionType::Integer)
.min_int_value(5)
.max_int_value(10)
.required(true),
CreateApplicationCommandOption::new(
CommandOptionType::Integer,
"int",
"An integer from 5 to 10",
)
.min_int_value(5)
.max_int_value(10)
.required(true),
)
.add_option(
CreateApplicationCommandOption::default()
.name("number")
.description("A float from -3.3 to 234.5")
.kind(CommandOptionType::Number)
.min_number_value(-3.3)
.max_number_value(234.5)
.required(true),
CreateApplicationCommandOption::new(
CommandOptionType::Number,
"number",
"A float from -3.3 to 234.5",
)
.min_number_value(-3.3)
.max_number_value(234.5)
.required(true),
)
}
2 changes: 1 addition & 1 deletion examples/e14_slash_commands/src/commands/ping.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,5 @@ pub fn run(_options: &[ResolvedOption]) -> String {
}

pub fn register() -> CreateApplicationCommand {
CreateApplicationCommand::default().name("ping").description("A ping command")
CreateApplicationCommand::new("ping", "A ping command")
}
79 changes: 38 additions & 41 deletions examples/e14_slash_commands/src/commands/welcome.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,52 +2,49 @@ use serenity::builder::{CreateApplicationCommand, CreateApplicationCommandOption
use serenity::model::prelude::command::CommandOptionType;

pub fn register() -> CreateApplicationCommand {
CreateApplicationCommand::default()
.name("welcome")
CreateApplicationCommand::new("welcome", "Welcome a user")
.name_localized("de", "begrüßen")
.description("Welcome a user")
.description_localized("de", "Einen Nutzer begrüßen")
.add_option(
CreateApplicationCommandOption::default()
.name("user")
.name_localized("de", "nutzer")
.description("The user to welcome")
.description_localized("de", "Der zu begrüßende Nutzer")
.kind(CommandOptionType::User)
.required(true),
CreateApplicationCommandOption::new(
CommandOptionType::User,
"user",
"The user to welcome",
)
.name_localized("de", "nutzer")
.description_localized("de", "Der zu begrüßende Nutzer")
.required(true),
)
.add_option(
CreateApplicationCommandOption::default()
.name("message")
.name_localized("de", "nachricht")
.description("The message to send")
.description_localized("de", "Die versendete Nachricht")
.kind(CommandOptionType::String)
.required(true)
.add_string_choice_localized(
"Welcome to our cool server! Ask me if you need help",
"pizza",
[(
"de",
"Willkommen auf unserem coolen Server! Frag mich, falls du Hilfe brauchst",
)],
)
.add_string_choice_localized("Hey, do you want a coffee?", "coffee", [(
CreateApplicationCommandOption::new(
CommandOptionType::String,
"message",
"The message to send",
)
.name_localized("de", "nachricht")
.description_localized("de", "Die versendete Nachricht")
.required(true)
.add_string_choice_localized(
"Welcome to our cool server! Ask me if you need help",
"pizza",
[(
"de",
"Hey, willst du einen Kaffee?",
)])
.add_string_choice_localized(
"Welcome to the club, you're now a good person. Well, I hope.",
"club",
[(
"de",
"Willkommen im Club, du bist jetzt ein guter Mensch. Naja, hoffentlich.",
)],
)
.add_string_choice_localized(
"I hope that you brought a controller to play together!",
"game",
[("de", "Ich hoffe du hast einen Controller zum Spielen mitgebracht!")],
),
"Willkommen auf unserem coolen Server! Frag mich, falls du Hilfe brauchst",
)],
)
.add_string_choice_localized("Hey, do you want a coffee?", "coffee", [(
"de",
"Hey, willst du einen Kaffee?",
)])
.add_string_choice_localized(
"Welcome to the club, you're now a good person. Well, I hope.",
"club",
[("de", "Willkommen im Club, du bist jetzt ein guter Mensch. Naja, hoffentlich.")],
)
.add_string_choice_localized(
"I hope that you brought a controller to play together!",
"game",
[("de", "Ich hoffe du hast einen Controller zum Spielen mitgebracht!")],
),
)
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use serenity::builder::CreateApplicationCommand;

pub fn register() -> CreateApplicationCommand {
CreateApplicationCommand::default().name("wonderful_command").description("An amazing command")
CreateApplicationCommand::new("wonderful_command", "An amazing command")
}
4 changes: 2 additions & 2 deletions examples/e14_slash_commands/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@ impl EventHandler for Handler {
_ => "not implemented :(".to_string(),
};

let data = CreateInteractionResponseData::default().content(content);
let builder = CreateInteractionResponse::default()
let data = CreateInteractionResponseData::new().content(content);
let builder = CreateInteractionResponse::new()
.kind(InteractionResponseType::ChannelMessageWithSource)
.interaction_response_data(data);
if let Err(why) = command.create_interaction_response(&ctx.http, builder).await {
Expand Down
26 changes: 13 additions & 13 deletions examples/e17_message_components/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,21 +40,21 @@ impl EventHandler for Handler {
.channel_id
.send_message(
&ctx,
CreateMessage::default().content("Please select your favorite animal").components(
CreateComponents::default().set_action_row(CreateActionRow::default()
CreateMessage::new().content("Please select your favorite animal").components(
CreateComponents::new().set_action_row(
// An action row can only contain one select menu!
.add_select_menu(CreateSelectMenu::default()
.custom_id("animal_select")
.placeholder("No animal selected")
.options(vec![
CreateSelectMenuOption::default().label("🐈 meow").value("Cat"),
CreateSelectMenuOption::default().label("🐕 woof").value("Dog"),
CreateSelectMenuOption::default().label("🐎 neigh").value("Horse"),
CreateSelectMenuOption::default().label("🦙 hoooooooonk").value("Alpaca"),
CreateSelectMenuOption::default().label("🦀 crab rave").value("Ferris"),
CreateActionRow::new().add_select_menu(
CreateSelectMenu::new("animal_select", vec![
CreateSelectMenuOption::new("🐈 meow", "Cat"),
CreateSelectMenuOption::new("🐕 woof", "Dog"),
CreateSelectMenuOption::new("🐎 neigh", "Horse"),
CreateSelectMenuOption::new("🦙 hoooooooonk", "Alpaca"),
CreateSelectMenuOption::new("🦀 crab rave", "Ferris"),
])
)
)
.custom_id("animal_select")
.placeholder("No animal selected"),
),
),
),
)
.await
Expand Down
2 changes: 1 addition & 1 deletion examples/e18_webhook/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,6 @@ async fn main() {
let http = Http::new("");
let webhook = Webhook::from_url(&http, "https://discord.com/api/webhooks/133742013374206969/hello-there-oPNtRN5UY5DVmBe7m1N0HE-replace-me-Dw9LRkgq3zI7LoW3Rb-k-q").await.expect("Replace the webhook with your own");

let builder = ExecuteWebhook::default().content("hello there").username("Webhook test");
let builder = ExecuteWebhook::new().content("hello there").username("Webhook test");
webhook.execute(&http, false, builder).await.expect("Could not execute webhook.");
}
20 changes: 15 additions & 5 deletions src/builder/add_member.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,10 @@ use crate::model::prelude::*;
/// A builder to add parameters when using [`GuildId::add_member`].
///
/// [`GuildId::add_member`]: crate::model::id::GuildId::add_member
#[derive(Clone, Debug, Default, Serialize)]
#[derive(Clone, Debug, Serialize)]
#[must_use]
pub struct AddMember {
#[serde(skip_serializing_if = "Option::is_none")]
access_token: Option<String>,
access_token: String,
#[serde(skip_serializing_if = "Option::is_none")]
nick: Option<String>,
#[serde(skip_serializing_if = "Vec::is_empty")]
Expand All @@ -23,6 +22,17 @@ pub struct AddMember {
}

impl AddMember {
/// Constructs a new builder with the given access token, leaving all other fields empty.
pub fn new(access_token: String) -> Self {
Self {
access_token,
nick: None,
roles: Vec::new(),
mute: None,
deaf: None,
}
}

/// Adds a [`User`] to this guild with a valid OAuth2 access token.
///
/// Returns the created [`Member`] object, or nothing if the user is already a member of the
Expand All @@ -42,11 +52,11 @@ impl AddMember {
http.as_ref().add_guild_member(guild_id.into(), user_id.into(), &self).await
}

/// Sets the OAuth2 access token for this request.
/// Sets the OAuth2 access token for this request, replacing the current one.
///
/// Requires the access token to have the `guilds.join` scope granted.
pub fn access_token(mut self, access_token: impl Into<String>) -> Self {
self.access_token = Some(access_token.into());
self.access_token = access_token.into();
self
}

Expand Down
5 changes: 5 additions & 0 deletions src/builder/bot_auth_parameters.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,11 @@ pub struct CreateBotAuthParameters {
}

impl CreateBotAuthParameters {
/// Equivalent to [`Self::default`].
pub fn new() -> Self {
Self::default()
}

/// Builds the url with the provided data.
#[must_use]
pub fn build(self) -> String {
Expand Down
Loading

0 comments on commit 08711cd

Please sign in to comment.