From dad993390c08681491c8e6f975798e8df3995606 Mon Sep 17 00:00:00 2001 From: HexPandaa <47880094+HexPandaa@users.noreply.github.com> Date: Tue, 25 Jul 2023 11:14:33 +0200 Subject: [PATCH 1/4] Accept canary webhook domain Add canary.discord.com to the list of valid webhook domains --- src/utils/mod.rs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/utils/mod.rs b/src/utils/mod.rs index 7e14814fc31..e2925593698 100644 --- a/src/utils/mod.rs +++ b/src/utils/mod.rs @@ -431,7 +431,7 @@ pub fn parse_quotes(s: impl AsRef) -> Vec { pub fn parse_webhook(url: &Url) -> Option<(u64, &str)> { let (webhook_id, token) = url.path().strip_prefix("/api/webhooks/")?.split_once('/')?; if !["http", "https"].contains(&url.scheme()) - || !["discord.com", "discordapp.com"].contains(&url.domain()?) + || !["discord.com", "canary.discord.com", "discordapp.com"].contains(&url.domain()?) || !(17..=20).contains(&webhook_id.len()) || !(60..=68).contains(&token.len()) { @@ -508,5 +508,10 @@ mod test { let (id, token) = parse_webhook(&url).unwrap(); assert_eq!(id, 245037420704169985); assert_eq!(token, "ig5AO-wdVWpCBtUUMxmgsWryqgsW3DChbKYOINftJ4DCrUbnkedoYZD0VOH1QLr-S3sV"); + + let url_canary = "https://canary.discord.com/api/webhooks/245037420704169985/ig5AO-wdVWpCBtUUMxmgsWryqgsW3DChbKYOINftJ4DCrUbnkedoYZD0VOH1QLr-S3sV".parse().unwrap(); + let (id_canary, token_canary) = parse_webhook(&url_canary).unwrap(); + assert_eq!(id_canary, 245037420704169985); + assert_eq!(token_canary, "ig5AO-wdVWpCBtUUMxmgsWryqgsW3DChbKYOINftJ4DCrUbnkedoYZD0VOH1QLr-S3sV"); } } From e6d840b87e7b526007c067e9b94c2577da6a5180 Mon Sep 17 00:00:00 2001 From: HexPandaa <47880094+HexPandaa@users.noreply.github.com> Date: Tue, 25 Jul 2023 15:46:39 +0200 Subject: [PATCH 2/4] Add more valid webhook domains --- src/utils/mod.rs | 38 ++++++++++++++++++++++++++++---------- 1 file changed, 28 insertions(+), 10 deletions(-) diff --git a/src/utils/mod.rs b/src/utils/mod.rs index e2925593698..79fa930efd1 100644 --- a/src/utils/mod.rs +++ b/src/utils/mod.rs @@ -429,9 +429,18 @@ pub fn parse_quotes(s: impl AsRef) -> Vec { /// ``` #[must_use] pub fn parse_webhook(url: &Url) -> Option<(u64, &str)> { + const DOMAINS: &'static [&'static str] = &[ + "discord.com", + "canary.discord.com", + "ptb.discord.com", + "discordapp.com", + "canary.discordapp.com", + "ptb.discordapp.com", + ]; + let (webhook_id, token) = url.path().strip_prefix("/api/webhooks/")?.split_once('/')?; if !["http", "https"].contains(&url.scheme()) - || !["discord.com", "canary.discord.com", "discordapp.com"].contains(&url.domain()?) + || !DOMAINS.contains(&url.domain()?) || !(17..=20).contains(&webhook_id.len()) || !(60..=68).contains(&token.len()) { @@ -504,14 +513,23 @@ mod test { #[test] fn test_webhook_parser() { - let url = "https://discord.com/api/webhooks/245037420704169985/ig5AO-wdVWpCBtUUMxmgsWryqgsW3DChbKYOINftJ4DCrUbnkedoYZD0VOH1QLr-S3sV".parse().unwrap(); - let (id, token) = parse_webhook(&url).unwrap(); - assert_eq!(id, 245037420704169985); - assert_eq!(token, "ig5AO-wdVWpCBtUUMxmgsWryqgsW3DChbKYOINftJ4DCrUbnkedoYZD0VOH1QLr-S3sV"); - - let url_canary = "https://canary.discord.com/api/webhooks/245037420704169985/ig5AO-wdVWpCBtUUMxmgsWryqgsW3DChbKYOINftJ4DCrUbnkedoYZD0VOH1QLr-S3sV".parse().unwrap(); - let (id_canary, token_canary) = parse_webhook(&url_canary).unwrap(); - assert_eq!(id_canary, 245037420704169985); - assert_eq!(token_canary, "ig5AO-wdVWpCBtUUMxmgsWryqgsW3DChbKYOINftJ4DCrUbnkedoYZD0VOH1QLr-S3sV"); + const DOMAINS: &'static [&'static str] = &[ + "discord.com", + "canary.discord.com", + "ptb.discord.com", + "discordapp.com", + "canary.discordapp.com", + "ptb.discordapp.com", + ]; + + for domain in DOMAINS { + let url = format!("https://{}/api/webhooks/245037420704169985/ig5AO-wdVWpCBtUUMxmgsWryqgsW3DChbKYOINftJ4DCrUbnkedoYZD0VOH1QLr-S3sV", domain).parse().unwrap(); + let (id, token) = parse_webhook(&url).unwrap(); + assert_eq!(id, 245037420704169985); + assert_eq!( + token, + "ig5AO-wdVWpCBtUUMxmgsWryqgsW3DChbKYOINftJ4DCrUbnkedoYZD0VOH1QLr-S3sV" + ); + } } } From 1a5e08825b54cd113e1a7d9032a0bc25d55487e8 Mon Sep 17 00:00:00 2001 From: "Alex M. M" Date: Sun, 6 Aug 2023 23:46:02 +0200 Subject: [PATCH 3/4] Reuse Discord's list of domains in the webhook parser and its test --- src/utils/mod.rs | 28 ++++++++++------------------ 1 file changed, 10 insertions(+), 18 deletions(-) diff --git a/src/utils/mod.rs b/src/utils/mod.rs index 79fa930efd1..95271cc3c41 100644 --- a/src/utils/mod.rs +++ b/src/utils/mod.rs @@ -413,6 +413,16 @@ pub fn parse_quotes(s: impl AsRef) -> Vec { args } +/// Discord's official domains. This is used in [`parse_webhook`] and in its corresponding test. +const DOMAINS: &'static [&'static str] = &[ + "discord.com", + "canary.discord.com", + "ptb.discord.com", + "discordapp.com", + "canary.discordapp.com", + "ptb.discordapp.com", +]; + /// Parses the id and token from a webhook url. Expects a [`url::Url`] object rather than a [`&str`]. /// /// # Examples @@ -429,15 +439,6 @@ pub fn parse_quotes(s: impl AsRef) -> Vec { /// ``` #[must_use] pub fn parse_webhook(url: &Url) -> Option<(u64, &str)> { - const DOMAINS: &'static [&'static str] = &[ - "discord.com", - "canary.discord.com", - "ptb.discord.com", - "discordapp.com", - "canary.discordapp.com", - "ptb.discordapp.com", - ]; - let (webhook_id, token) = url.path().strip_prefix("/api/webhooks/")?.split_once('/')?; if !["http", "https"].contains(&url.scheme()) || !DOMAINS.contains(&url.domain()?) @@ -513,15 +514,6 @@ mod test { #[test] fn test_webhook_parser() { - const DOMAINS: &'static [&'static str] = &[ - "discord.com", - "canary.discord.com", - "ptb.discord.com", - "discordapp.com", - "canary.discordapp.com", - "ptb.discordapp.com", - ]; - for domain in DOMAINS { let url = format!("https://{}/api/webhooks/245037420704169985/ig5AO-wdVWpCBtUUMxmgsWryqgsW3DChbKYOINftJ4DCrUbnkedoYZD0VOH1QLr-S3sV", domain).parse().unwrap(); let (id, token) = parse_webhook(&url).unwrap(); From 59b60570adf27f6222c3479883ddc733eb7b0c3a Mon Sep 17 00:00:00 2001 From: "Alex M. M" Date: Sun, 6 Aug 2023 23:47:21 +0200 Subject: [PATCH 4/4] Remove explicit mention of the `'static` lifetime on `DOMAINS` This lifetime is inferrible for quite some time now. --- src/utils/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/utils/mod.rs b/src/utils/mod.rs index 95271cc3c41..018eb1dd90e 100644 --- a/src/utils/mod.rs +++ b/src/utils/mod.rs @@ -414,7 +414,7 @@ pub fn parse_quotes(s: impl AsRef) -> Vec { } /// Discord's official domains. This is used in [`parse_webhook`] and in its corresponding test. -const DOMAINS: &'static [&'static str] = &[ +const DOMAINS: &[&str] = &[ "discord.com", "canary.discord.com", "ptb.discord.com",