Skip to content

Commit

Permalink
feat(model, http): Add support for guild onboarding (twilight-rs#2130)
Browse files Browse the repository at this point in the history
Implements guild onboarding ref: discord/discord-api-docs#5915

This adds the following structures:

Onboarding
OnboardingPrompt
OnboardingPromptOption
OnboardingPromptType
As well as supporting the http GET for retrieving guild onboarding information.

Closes twilight-rs#2134
  • Loading branch information
suneettipirneni authored Jul 4, 2023
1 parent 899fefb commit 36f8377
Show file tree
Hide file tree
Showing 12 changed files with 490 additions and 13 deletions.
3 changes: 3 additions & 0 deletions twilight-http-ratelimiting/src/request.rs
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,8 @@ pub enum Path {
GuildsIdMembersSearch(u64),
/// Operating on one of the user's guilds' MFA level.
GuildsIdMfa(u64),
/// Operating on one of the user's guilds' onboarding.
GuildsIdOnboarding(u64),
/// Operating on one of the user's guilds' by previewing it.
GuildsIdPreview(u64),
/// Operating on one of the user's guilds' by pruning members.
Expand Down Expand Up @@ -400,6 +402,7 @@ impl FromStr for Path {
["guilds", id, "members", _] => GuildsIdMembersId(parse_id(id)?),
["guilds", id, "members", _, "roles", _] => GuildsIdMembersIdRolesId(parse_id(id)?),
["guilds", id, "members", "@me", "nick"] => GuildsIdMembersMeNick(parse_id(id)?),
["guilds", id, "onboarding"] => GuildsIdOnboarding(parse_id(id)?),
["guilds", id, "preview"] => GuildsIdPreview(parse_id(id)?),
["guilds", id, "prune"] => GuildsIdPrune(parse_id(id)?),
["guilds", id, "regions"] => GuildsIdRegions(parse_id(id)?),
Expand Down
7 changes: 6 additions & 1 deletion twilight-http/src/client/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ mod interaction;

pub use self::{builder::ClientBuilder, interaction::InteractionClient};

use crate::request::GetCurrentAuthorizationInformation;
use crate::request::{guild::GetGuildOnboarding, GetCurrentAuthorizationInformation};
#[allow(deprecated)]
use crate::{
client::connector::Connector,
Expand Down Expand Up @@ -1231,6 +1231,11 @@ impl Client {
RemoveRoleFromMember::new(self, guild_id, user_id, role_id)
}

/// Retrieves the onboarding data for a guild.
pub const fn guild_onboarding(&self, guild_id: Id<GuildMarker>) -> GetGuildOnboarding<'_> {
GetGuildOnboarding::new(self, guild_id)
}

/// For public guilds, get the guild preview.
///
/// This works even if the user is not in the guild.
Expand Down
69 changes: 69 additions & 0 deletions twilight-http/src/request/guild/get_guild_onboarding.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
use std::future::IntoFuture;

use twilight_model::{
guild::onboarding::Onboarding,
id::{marker::GuildMarker, Id},
};

use crate::{
request::{Request, TryIntoRequest},
response::ResponseFuture,
routing::Route,
Client, Error, Response,
};

/// Get the onboarding information for a guild.
///
/// # Examples
///
/// ```no_run
/// use twilight_http::Client;
/// use twilight_model::id::Id;
///
/// # #[tokio::main]
/// async fn main() -> Result<(), Box<dyn std::error::Error>> {
/// let client = Client::new("token".to_owned());
///
/// let guild_id = Id::new(101);
/// let onboarding = client.guild_onboarding(guild_id).await?.model().await?;
///
/// for prompt in onboarding.prompts {
/// println!("Prompt: {}", prompt.title);
/// }
/// # Ok(()) }
/// ```
pub struct GetGuildOnboarding<'a> {
guild_id: Id<GuildMarker>,
http: &'a Client,
}

impl<'a> GetGuildOnboarding<'a> {
pub(crate) const fn new(http: &'a Client, guild_id: Id<GuildMarker>) -> Self {
Self { guild_id, http }
}
}

impl IntoFuture for GetGuildOnboarding<'_> {
type Output = Result<Response<Onboarding>, Error>;

type IntoFuture = ResponseFuture<Onboarding>;

fn into_future(self) -> Self::IntoFuture {
let http = self.http;

match self.try_into_request() {
Ok(request) => http.request(request),
Err(source) => ResponseFuture::error(source),
}
}
}

impl TryIntoRequest for GetGuildOnboarding<'_> {
fn try_into_request(self) -> Result<Request, Error> {
let request = Request::from_route(&Route::GetGuildOnboarding {
guild_id: self.guild_id.get(),
});

Ok(request)
}
}
15 changes: 8 additions & 7 deletions twilight-http/src/request/guild/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ mod get_audit_log;
mod get_guild;
mod get_guild_channels;
mod get_guild_invites;
mod get_guild_onboarding;
mod get_guild_preview;
mod get_guild_prune_count;
mod get_guild_vanity_url;
Expand All @@ -36,12 +37,12 @@ pub use self::{
create_guild_prune::CreateGuildPrune, delete_guild::DeleteGuild,
get_active_threads::GetActiveThreads, get_audit_log::GetAuditLog, get_guild::GetGuild,
get_guild_channels::GetGuildChannels, get_guild_invites::GetGuildInvites,
get_guild_preview::GetGuildPreview, get_guild_prune_count::GetGuildPruneCount,
get_guild_vanity_url::GetGuildVanityUrl, get_guild_voice_regions::GetGuildVoiceRegions,
get_guild_webhooks::GetGuildWebhooks, get_guild_welcome_screen::GetGuildWelcomeScreen,
get_guild_widget::GetGuildWidget, get_guild_widget_settings::GetGuildWidgetSettings,
update_current_member::UpdateCurrentMember, update_guild::UpdateGuild,
update_guild_channel_positions::UpdateGuildChannelPositions, update_guild_mfa::UpdateGuildMfa,
update_guild_welcome_screen::UpdateGuildWelcomeScreen,
get_guild_onboarding::GetGuildOnboarding, get_guild_preview::GetGuildPreview,
get_guild_prune_count::GetGuildPruneCount, get_guild_vanity_url::GetGuildVanityUrl,
get_guild_voice_regions::GetGuildVoiceRegions, get_guild_webhooks::GetGuildWebhooks,
get_guild_welcome_screen::GetGuildWelcomeScreen, get_guild_widget::GetGuildWidget,
get_guild_widget_settings::GetGuildWidgetSettings, update_current_member::UpdateCurrentMember,
update_guild::UpdateGuild, update_guild_channel_positions::UpdateGuildChannelPositions,
update_guild_mfa::UpdateGuildMfa, update_guild_welcome_screen::UpdateGuildWelcomeScreen,
update_guild_widget_settings::UpdateGuildWidgetSettings,
};
11 changes: 6 additions & 5 deletions twilight-http/src/request/try_into_request.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,11 +65,11 @@ mod private {
},
user::{UpdateCurrentUserVoiceState, UpdateUserVoiceState},
CreateGuild, CreateGuildChannel, CreateGuildPrune, DeleteGuild, GetActiveThreads,
GetAuditLog, GetGuild, GetGuildChannels, GetGuildInvites, GetGuildPreview,
GetGuildPruneCount, GetGuildVanityUrl, GetGuildVoiceRegions, GetGuildWebhooks,
GetGuildWelcomeScreen, GetGuildWidget, GetGuildWidgetSettings, UpdateCurrentMember,
UpdateGuild, UpdateGuildChannelPositions, UpdateGuildMfa, UpdateGuildWelcomeScreen,
UpdateGuildWidgetSettings,
GetAuditLog, GetGuild, GetGuildChannels, GetGuildInvites, GetGuildOnboarding,
GetGuildPreview, GetGuildPruneCount, GetGuildVanityUrl, GetGuildVoiceRegions,
GetGuildWebhooks, GetGuildWelcomeScreen, GetGuildWidget, GetGuildWidgetSettings,
UpdateCurrentMember, UpdateGuild, UpdateGuildChannelPositions, UpdateGuildMfa,
UpdateGuildWelcomeScreen, UpdateGuildWidgetSettings,
},
scheduled_event::{
CreateGuildExternalScheduledEvent, CreateGuildStageInstanceScheduledEvent,
Expand Down Expand Up @@ -191,6 +191,7 @@ mod private {
impl Sealed for GetGuildIntegrations<'_> {}
impl Sealed for GetGuildInvites<'_> {}
impl Sealed for GetGuildMembers<'_> {}
impl Sealed for GetGuildOnboarding<'_> {}
impl Sealed for GetGuildPreview<'_> {}
impl Sealed for GetGuildPruneCount<'_> {}
impl Sealed for GetGuildRoles<'_> {}
Expand Down
19 changes: 19 additions & 0 deletions twilight-http/src/routing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -542,6 +542,11 @@ pub enum Route<'a> {
/// The maximum number of members to get.
limit: Option<u16>,
},
/// Route information to get a guild's onboarding information.
GetGuildOnboarding {
/// The ID of the guild to get onboarding information for.
guild_id: u64,
},
/// Route information to get a guild's preview.
GetGuildPreview {
/// The ID of the guild.
Expand Down Expand Up @@ -1176,6 +1181,7 @@ impl<'a> Route<'a> {
| Self::GetGuildIntegrations { .. }
| Self::GetGuildInvites { .. }
| Self::GetGuildMembers { .. }
| Self::GetGuildOnboarding { .. }
| Self::GetGuildPreview { .. }
| Self::GetGuildPruneCount { .. }
| Self::GetGuildRoles { .. }
Expand Down Expand Up @@ -1547,6 +1553,7 @@ impl<'a> Route<'a> {
Self::GetGuildMembers { guild_id, .. } | Self::UpdateCurrentMember { guild_id, .. } => {
Path::GuildsIdMembers(guild_id)
}
Self::GetGuildOnboarding { guild_id } => Path::GuildsIdOnboarding(guild_id),
Self::CreateGuildScheduledEvent { guild_id, .. }
| Self::GetGuildScheduledEvents { guild_id, .. } => {
Path::GuildsIdScheduledEvents(guild_id)
Expand Down Expand Up @@ -2406,6 +2413,12 @@ impl Display for Route<'_> {

Ok(())
}
Route::GetGuildOnboarding { guild_id } => {
f.write_str("guilds/")?;
Display::fmt(guild_id, f)?;

f.write_str("/onboarding")
}
Route::GetGuildPreview { guild_id } => {
f.write_str("guilds/")?;
Display::fmt(guild_id, f)?;
Expand Down Expand Up @@ -4672,4 +4685,10 @@ mod tests {
format!("guilds/{GUILD_ID}/auto-moderation/rules/{AUTO_MODERATION_RULE_ID}")
);
}

#[test]
fn get_guild_onboarding() {
let route = Route::GetGuildOnboarding { guild_id: GUILD_ID };
assert_eq!(route.to_string(), format!("guilds/{GUILD_ID}/onboarding"));
}
}
1 change: 1 addition & 0 deletions twilight-model/src/guild/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
pub mod audit_log;
pub mod auto_moderation;
pub mod invite;
pub mod onboarding;
pub mod scheduled_event;
pub mod template;
pub mod widget;
Expand Down
67 changes: 67 additions & 0 deletions twilight-model/src/guild/onboarding/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
//! Types for guild onboarding.

mod option;
mod prompt;
mod prompt_type;

use crate::id::{
marker::{ChannelMarker, GuildMarker},
Id,
};
use serde::{Deserialize, Serialize};

pub use self::{
option::OnboardingPromptOption, prompt::OnboardingPrompt, prompt_type::OnboardingPromptType,
};

/// The onboarding data for a guild.
#[derive(Clone, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
pub struct Onboarding {
/// Channel IDs that new members get opted into automatically
pub default_channel_ids: Vec<Id<ChannelMarker>>,
/// Whether the guild has enabled onboarding.
pub enabled: bool,
/// ID of the guild this onboarding is a part of.
pub guild_id: Id<GuildMarker>,
/// Array of [`OnboardingPrompt`]s for the guild onboarding flow.
pub prompts: Vec<OnboardingPrompt>,
}

#[cfg(test)]
mod tests {
use super::Onboarding;
use crate::id::Id;
use serde_test::Token;

#[test]
fn onboarding() {
let onboarding = Onboarding {
default_channel_ids: Vec::new(),
enabled: true,
guild_id: Id::new(123_456_789),
prompts: Vec::new(),
};

serde_test::assert_tokens(
&onboarding,
&[
Token::Struct {
name: "Onboarding",
len: 4,
},
Token::Str("default_channel_ids"),
Token::Seq { len: Some(0) },
Token::SeqEnd,
Token::Str("enabled"),
Token::Bool(true),
Token::Str("guild_id"),
Token::NewtypeStruct { name: "Id" },
Token::Str("123456789"),
Token::Str("prompts"),
Token::Seq { len: Some(0) },
Token::SeqEnd,
Token::StructEnd,
],
)
}
}
Loading

0 comments on commit 36f8377

Please sign in to comment.