Skip to content

Commit

Permalink
feat(model, cache): add support for join raid and mention raid protec…
Browse files Browse the repository at this point in the history
…tion (#2204)

API documentation: discord/discord-api-docs#5778

Co-authored-by: Jens Reidel <adrian@travitia.xyz>
  • Loading branch information
suneettipirneni and Gelbpunkt authored Jun 13, 2023
1 parent f248e6f commit c992f93
Show file tree
Hide file tree
Showing 8 changed files with 53 additions and 4 deletions.
3 changes: 3 additions & 0 deletions twilight-cache-inmemory/src/event/guild.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ impl InMemoryCache {
public_updates_channel_id,
roles,
rules_channel_id,
safety_alerts_channel_id,
splash,
stage_instances,
stickers,
Expand Down Expand Up @@ -151,6 +152,7 @@ impl InMemoryCache {
premium_tier,
public_updates_channel_id,
rules_channel_id,
safety_alerts_channel_id,
splash,
system_channel_id,
system_channel_flags,
Expand Down Expand Up @@ -432,6 +434,7 @@ mod tests {
public_updates_channel_id: None,
roles: Vec::new(),
rules_channel_id: None,
safety_alerts_channel_id: Some(Id::new(789)),
splash: None,
stage_instances: Vec::new(),
stickers: Vec::new(),
Expand Down
6 changes: 6 additions & 0 deletions twilight-cache-inmemory/src/model/guild.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ pub struct CachedGuild {
pub(crate) premium_tier: PremiumTier,
pub(crate) public_updates_channel_id: Option<Id<ChannelMarker>>,
pub(crate) rules_channel_id: Option<Id<ChannelMarker>>,
pub(crate) safety_alerts_channel_id: Option<Id<ChannelMarker>>,
pub(crate) splash: Option<ImageHash>,
pub(crate) system_channel_id: Option<Id<ChannelMarker>>,
pub(crate) system_channel_flags: SystemChannelFlags,
Expand Down Expand Up @@ -222,6 +223,11 @@ impl CachedGuild {
self.rules_channel_id
}

/// The ID of the channel where admins and moderators of Community guilds receive safety alerts from Discord.
pub const fn safety_alerts_channel_id(&self) -> Option<Id<ChannelMarker>> {
self.safety_alerts_channel_id
}

/// Splash hash.
///
/// See [Discord Docs/Image Formatting].
Expand Down
4 changes: 4 additions & 0 deletions twilight-cache-inmemory/src/permission.rs
Original file line number Diff line number Diff line change
Expand Up @@ -703,6 +703,9 @@ mod tests {
/// ID of a thread created in the general channel.
const THREAD_ID: Id<ChannelMarker> = Id::new(5);

/// ID of the safety alerts channel.
const SAFETY_ALERTS_CHANNEL_ID: Id<ChannelMarker> = Id::new(6);

fn base_guild() -> Guild {
Guild {
id: GUILD_ID,
Expand Down Expand Up @@ -744,6 +747,7 @@ mod tests {
Permissions::CREATE_INVITE | Permissions::VIEW_AUDIT_LOG,
),
]),
safety_alerts_channel_id: Some(SAFETY_ALERTS_CHANNEL_ID),
splash: None,
stage_instances: Vec::new(),
stickers: Vec::new(),
Expand Down
1 change: 1 addition & 0 deletions twilight-cache-inmemory/src/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -403,6 +403,7 @@ pub fn guild(id: Id<GuildMarker>, member_count: Option<u64>) -> Guild {
public_updates_channel_id: None,
roles: Vec::new(),
rules_channel_id: None,
safety_alerts_channel_id: Some(Id::new(2)),
splash: None,
stage_instances: Vec::new(),
stickers: Vec::new(),
Expand Down
8 changes: 6 additions & 2 deletions twilight-model/src/guild/auto_moderation/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -147,8 +147,9 @@ mod tests {
allow_list: None,
keyword_filter: Some(Vec::from(["shoot".into(), "darn".into()])),
presets: None,
regex_patterns: Some(Vec::from(["[a-z]+".into(), "[0-9]+".into()])),
mention_raid_protection_enabled: Some(true),
mention_total_limit: None,
regex_patterns: Some(Vec::from(["[a-z]+".into(), "[0-9]+".into()])),
},
trigger_type: AutoModerationTriggerType::Keyword,
};
Expand Down Expand Up @@ -233,14 +234,17 @@ mod tests {
Token::Str("trigger_metadata"),
Token::Struct {
name: "AutoModerationTriggerMetadata",
len: 2,
len: 3,
},
Token::Str("keyword_filter"),
Token::Some,
Token::Seq { len: Some(2) },
Token::Str("shoot"),
Token::Str("darn"),
Token::SeqEnd,
Token::Str("mention_raid_protection_enabled"),
Token::Some,
Token::Bool(true),
Token::Str("regex_patterns"),
Token::Some,
Token::Seq { len: Some(2) },
Expand Down
9 changes: 8 additions & 1 deletion twilight-model/src/guild/auto_moderation/trigger_metadata.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@ pub struct AutoModerationTriggerMetadata {
/// [Discord Docs/Keyword Matching Strategies]: https://discord.com/developers/docs/resources/auto-moderation#auto-moderation-rule-object-keyword-matching-strategies
#[serde(skip_serializing_if = "Option::is_none")]
pub presets: Option<Vec<AutoModerationKeywordPresetType>>,
/// Whether to automatically detect mention raids.
#[serde(skip_serializing_if = "Option::is_none")]
pub mention_raid_protection_enabled: Option<bool>,
/// Total number of unique role and user mentions allowed per message (Maximum of 50).
#[serde(skip_serializing_if = "Option::is_none")]
pub mention_total_limit: Option<u8>,
Expand Down Expand Up @@ -63,6 +66,7 @@ mod tests {
AutoModerationKeywordPresetType::SexualContent,
AutoModerationKeywordPresetType::Slurs,
])),
mention_raid_protection_enabled: Some(true),
mention_total_limit: Some(5),
regex_patterns: Some(Vec::from(["^\\d+$".into()])),
};
Expand All @@ -72,7 +76,7 @@ mod tests {
&[
Token::Struct {
name: "AutoModerationTriggerMetadata",
len: 5,
len: 6,
},
Token::Str("allow_list"),
Token::Some,
Expand All @@ -92,6 +96,9 @@ mod tests {
Token::U8(u8::from(AutoModerationKeywordPresetType::SexualContent)),
Token::U8(u8::from(AutoModerationKeywordPresetType::Slurs)),
Token::SeqEnd,
Token::Str("mention_raid_protection_enabled"),
Token::Some,
Token::Bool(true),
Token::Str("mention_total_limit"),
Token::Some,
Token::U8(5),
Expand Down
4 changes: 4 additions & 0 deletions twilight-model/src/guild/feature.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,8 @@ pub enum GuildFeature {
PreviewEnabled,
/// Has access to create private threads.
PrivateThreads,
/// Guild has disabled alerts for join raids in the configured safety alerts channel.
RaidAlertsDisabled,
/// Is able to set role icons.
RoleIcons,
/// Guild has role subscriptions that can be purchased.
Expand Down Expand Up @@ -100,6 +102,7 @@ impl From<GuildFeature> for Cow<'static, str> {
GuildFeature::Partnered => "PARTNERED".into(),
GuildFeature::PreviewEnabled => "PREVIEW_ENABLED".into(),
GuildFeature::PrivateThreads => "PRIVATE_THREADS".into(),
GuildFeature::RaidAlertsDisabled => "RAID_ALERTS_DISABLED".into(),
GuildFeature::RoleIcons => "ROLE_ICONS".into(),
GuildFeature::RoleSubscriptionsAvailableForPurchase => {
"ROLE_SUBSCRIPTIONS_AVAILABLE_FOR_PURCHASE".into()
Expand Down Expand Up @@ -138,6 +141,7 @@ impl From<String> for GuildFeature {
"PARTNERED" => Self::Partnered,
"PREVIEW_ENABLED" => Self::PreviewEnabled,
"PRIVATE_THREADS" => Self::PrivateThreads,
"RAID_ALERTS_DISABLED" => Self::RaidAlertsDisabled,
"ROLE_ICONS" => Self::RoleIcons,
"ROLE_SUBSCRIPTIONS_AVAILABLE_FOR_PURCHASE" => {
GuildFeature::RoleSubscriptionsAvailableForPurchase
Expand Down
22 changes: 21 additions & 1 deletion twilight-model/src/guild/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,9 @@ pub struct Guild {
pub public_updates_channel_id: Option<Id<ChannelMarker>>,
pub roles: Vec<Role>,
pub rules_channel_id: Option<Id<ChannelMarker>>,
/// The ID of the channel where admins and moderators of Community guilds receive safety alerts from Discord.
#[serde(skip_serializing_if = "Option::is_none")]
pub safety_alerts_channel_id: Option<Id<ChannelMarker>>,
pub splash: Option<ImageHash>,
#[serde(skip_serializing_if = "Vec::is_empty")]
pub stage_instances: Vec<StageInstance>,
Expand Down Expand Up @@ -192,6 +195,7 @@ impl<'de> Deserialize<'de> for Guild {
Presences,
PublicUpdatesChannelId,
Roles,
SafetyAlertsChannelId,
Splash,
StageInstances,
Stickers,
Expand Down Expand Up @@ -253,6 +257,7 @@ impl<'de> Deserialize<'de> for Guild {
let mut presences = None;
let mut public_updates_channel_id = None::<Option<_>>;
let mut roles = None;
let mut safety_alerts_channel_id = None::<Option<_>>;
let mut splash = None::<Option<_>>;
let mut stage_instances = None::<Vec<StageInstance>>;
let mut stickers = None::<Vec<Sticker>>;
Expand Down Expand Up @@ -543,6 +548,13 @@ impl<'de> Deserialize<'de> for Guild {

roles = Some(map.next_value()?);
}
Field::SafetyAlertsChannelId => {
if safety_alerts_channel_id.is_some() {
return Err(DeError::duplicate_field("safety_alerts_channel_id"));
}

safety_alerts_channel_id = Some(map.next_value()?);
}
Field::Splash => {
if splash.is_some() {
return Err(DeError::duplicate_field("splash"));
Expand Down Expand Up @@ -683,6 +695,7 @@ impl<'de> Deserialize<'de> for Guild {
let mut presences = presences.unwrap_or_default();
let public_updates_channel_id = public_updates_channel_id.unwrap_or_default();
let rules_channel_id = rules_channel_id.unwrap_or_default();
let safety_alerts_channel_id = safety_alerts_channel_id.unwrap_or_default();
let splash = splash.unwrap_or_default();
let stage_instances = stage_instances.unwrap_or_default();
let stickers = stickers.unwrap_or_default();
Expand Down Expand Up @@ -734,6 +747,7 @@ impl<'de> Deserialize<'de> for Guild {
?public_updates_channel_id,
?rules_channel_id,
?roles,
?safety_alerts_channel_id,
?splash,
?stage_instances,
?stickers,
Expand Down Expand Up @@ -801,6 +815,7 @@ impl<'de> Deserialize<'de> for Guild {
public_updates_channel_id,
roles,
rules_channel_id,
safety_alerts_channel_id,
splash,
stage_instances,
stickers,
Expand Down Expand Up @@ -926,6 +941,7 @@ mod tests {
public_updates_channel_id: None,
roles: Vec::new(),
rules_channel_id: Some(Id::new(6)),
safety_alerts_channel_id: Some(Id::new(9)),
splash: Some(image_hash::SPLASH),
stage_instances: Vec::new(),
stickers: Vec::new(),
Expand All @@ -945,7 +961,7 @@ mod tests {
&[
Token::Struct {
name: "Guild",
len: 46,
len: 47,
},
Token::Str("afk_channel_id"),
Token::Some,
Expand Down Expand Up @@ -1049,6 +1065,10 @@ mod tests {
Token::Some,
Token::NewtypeStruct { name: "Id" },
Token::Str("6"),
Token::Str("safety_alerts_channel_id"),
Token::Some,
Token::NewtypeStruct { name: "Id" },
Token::Str("9"),
Token::Str("splash"),
Token::Some,
Token::Str(image_hash::SPLASH_INPUT),
Expand Down

0 comments on commit c992f93

Please sign in to comment.