Skip to content

Commit

Permalink
Support automod regex patterns (serenity-rs#2276)
Browse files Browse the repository at this point in the history
  • Loading branch information
kangalio authored and mkrasnitski committed Feb 28, 2023
1 parent 50cb56d commit 4db8ed8
Show file tree
Hide file tree
Showing 3 changed files with 44 additions and 11 deletions.
13 changes: 12 additions & 1 deletion examples/testing/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ const IMAGE_URL_2: &str = "https://rustacean.net/assets/rustlogo.png";

async fn message(ctx: &Context, msg: Message) -> Result<(), serenity::Error> {
let channel_id = msg.channel_id;
let guild_id = msg.guild_id.unwrap();
if let Some(_args) = msg.content.strip_prefix("testmessage ") {
println!("command message: {:#?}", msg);
} else if msg.content == "globalcommand" {
Expand All @@ -23,7 +24,6 @@ async fn message(ctx: &Context, msg: Message) -> Result<(), serenity::Error> {
)
.await?;
} else if msg.content == "register" {
let guild_id = msg.guild_id.unwrap();
guild_id
.create_application_command(
&ctx,
Expand Down Expand Up @@ -143,6 +143,17 @@ async fn message(ctx: &Context, msg: Message) -> Result<(), serenity::Error> {
// Test new ReactionRemoveEmoji gateway event: https://github.com/serenity-rs/serenity/issues/2248
msg.react(ctx, '👍').await?;
msg.delete_reaction_emoji(ctx, '👍').await?;
} else if msg.content == "testautomodregex" {
guild_id
.create_automod_rule(
ctx,
EditAutoModRule::new().trigger(Trigger::Keyword {
strings: vec!["badword".into()],
regex_patterns: vec!["b[o0]{2,}b(ie)?s?".into()],
}),
)
.await?;
println!("new automod rules: {:?}", guild_id.automod_rules(ctx).await?);
} else {
return Ok(());
}
Expand Down
37 changes: 28 additions & 9 deletions src/model/guild/automod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ impl From<EventType> for u8 {
#[derive(Clone, Debug, PartialEq, Eq)]
#[non_exhaustive]
pub enum Trigger {
Keyword(Vec<String>),
Keyword { strings: Vec<String>, regex_patterns: Vec<String> },
HarmfulLink,
Spam,
KeywordPreset(Vec<KeywordPresetType>),
Expand All @@ -106,19 +106,26 @@ struct InterimTriggerMetadata<'a> {
#[serde(skip_serializing_if = "Option::is_none")]
keyword_filter: Option<Cow<'a, [String]>>,
#[serde(skip_serializing_if = "Option::is_none")]
regex_patterns: Option<Cow<'a, [String]>>,
#[serde(skip_serializing_if = "Option::is_none")]
presets: Option<Cow<'a, [KeywordPresetType]>>,
}

impl<'de> Deserialize<'de> for Trigger {
fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
let trigger = InterimTrigger::deserialize(deserializer)?;
let trigger = match trigger.kind {
TriggerType::Keyword => {
let keywords = trigger
TriggerType::Keyword => Self::Keyword {
strings: trigger
.metadata
.keyword_filter
.ok_or_else(|| Error::missing_field("keyword_filter"))?;
Self::Keyword(keywords.into_owned())
.ok_or_else(|| Error::missing_field("keyword_filter"))?
.into_owned(),
regex_patterns: trigger
.metadata
.regex_patterns
.ok_or_else(|| Error::missing_field("regex_patterns"))?
.into_owned(),
},
TriggerType::HarmfulLink => Self::HarmfulLink,
TriggerType::Spam => Self::Spam,
Expand All @@ -139,11 +146,18 @@ impl Serialize for Trigger {
kind: self.kind(),
metadata: InterimTriggerMetadata {
keyword_filter: None,
regex_patterns: None,
presets: None,
},
};
match self {
Self::Keyword(keywords) => trigger.metadata.keyword_filter = Some(keywords.into()),
Self::Keyword {
strings,
regex_patterns,
} => {
trigger.metadata.keyword_filter = Some(strings.into());
trigger.metadata.regex_patterns = Some(regex_patterns.into());
},
Self::KeywordPreset(presets) => trigger.metadata.presets = Some(presets.into()),
_ => {},
}
Expand All @@ -155,7 +169,9 @@ impl Trigger {
#[must_use]
pub fn kind(&self) -> TriggerType {
match self {
Self::Keyword(_) => TriggerType::Keyword,
Self::Keyword {
..
} => TriggerType::Keyword,
Self::HarmfulLink => TriggerType::HarmfulLink,
Self::Spam => TriggerType::Spam,
Self::KeywordPreset(_) => TriggerType::KeywordPreset,
Expand Down Expand Up @@ -466,9 +482,12 @@ mod tests {

assert_json(
&Rule {
trigger: Trigger::Keyword(vec![String::from("foo"), String::from("bar")]),
trigger: Trigger::Keyword {
strings: vec![String::from("foo"), String::from("bar")],
regex_patterns: vec![String::from("d[i1]ck")],
},
},
json!({"trigger_type": 1, "trigger_metadata": {"keyword_filter": ["foo", "bar"]}}),
json!({"trigger_type": 1, "trigger_metadata": {"keyword_filter": ["foo", "bar"], "regex_patterns": ["d[i1]ck"]}}),
);

assert_json(
Expand Down
5 changes: 4 additions & 1 deletion src/model/guild/guild_id.rs
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,10 @@ impl GuildId {
/// # let http = Http::new("token");
/// let builder = EditAutoModRule::new()
/// .name("foobar filter")
/// .trigger(Trigger::Keyword(vec!["foo*".to_string(), "*bar".to_string()]))
/// .trigger(Trigger::Keyword {
/// strings: vec!["foo*".to_string(), "*bar".to_string()],
/// regex_patterns: vec![],
/// })
/// .actions(vec![Action::BlockMessage, Action::Timeout(Duration::from_secs(60))]);
/// let _rule = GuildId::new(7).create_automod_rule(&http, builder).await;
/// # }
Expand Down

0 comments on commit 4db8ed8

Please sign in to comment.