diff --git a/readme.md b/readme.md index 7923962..134c71c 100644 --- a/readme.md +++ b/readme.md @@ -53,6 +53,8 @@ params = [ 'utm_medium', # Identifies what type of link was used 'utm_term', # Identifies search terms 'utm_content', # Identifies what specifically was clicked to bring the user to the site + "youtube.com``si", # YouTube specific Source identifier using "{domain}``{param}" pattern + "youtu.be``si", # YouTube specific Source identifier using "{domain}``{param}" pattern ] # Which exit params in URL should be unwrapped exit = [ diff --git a/src/clink.rs b/src/clink.rs index 45ccf9e..228bb09 100644 --- a/src/clink.rs +++ b/src/clink.rs @@ -35,7 +35,13 @@ impl Clink { let mut res = str.to_string(); for link in self.finder.links(str) { let mut l = Url::parse(self.unwrap_exit_params(link.as_str()).as_str()).unwrap(); - let query: Vec<(_, _)> = self.process_query(l.query_pairs(),l.domain()); + let query: Vec<(_, _)> = self.process_query( + l.query_pairs(), + l.domain() + .unwrap_or_default() + .strip_prefix("www.") + .or(l.domain()), + ); l.set_query(None); for pair in query { l.query_pairs_mut() @@ -46,7 +52,11 @@ impl Clink { res } - fn process_query(&self, query: url::form_urlencoded::Parse<'_>, domain: Option<&str>) -> Vec<(String, String)> { + fn process_query( + &self, + query: url::form_urlencoded::Parse<'_>, + domain: Option<&str>, + ) -> Vec<(String, String)> { match self.config.mode { Mode::Remove => self.filter(query, domain), Mode::Replace => self.replace(query, domain), @@ -82,21 +92,31 @@ impl Clink { } } - fn filter(&self, query: url::form_urlencoded::Parse<'_>, domain: Option<&str>) -> Vec<(String, String)> { + fn filter( + &self, + query: url::form_urlencoded::Parse<'_>, + domain: Option<&str>, + ) -> Vec<(String, String)> { query .filter(|p| { let global_absent = !self.config.params.contains::>(&p.0.clone().into()); - return global_absent && - if let Some(domain_val) = domain { + global_absent + && if let Some(domain_val) = domain { let param_name = format!("{}``{}", domain_val, p.0); return !self.config.params.contains::>(¶m_name.into()); - } else {true} + } else { + true + } }) .map(|p| (p.0.to_string(), p.1.to_string())) .collect() } - fn replace(&self, query: url::form_urlencoded::Parse<'_>, domain: Option<&str>) -> Vec<(String, String)> { + fn replace( + &self, + query: url::form_urlencoded::Parse<'_>, + domain: Option<&str>, + ) -> Vec<(String, String)> { query .map(|p| { if self.config.params.contains::>(&p.0.clone().into()) { @@ -291,13 +311,20 @@ mod find_and_replace { "https://youtu.be/dQw4w9WgXcQ" ); + assert_eq!( + clink.find_and_replace("https://www.youtu.be/dQw4w9WgXcQ?si=NblIBgit-qHN7MoH",), + "https://www.youtu.be/dQw4w9WgXcQ" + ); + assert_eq!( clink.find_and_replace("https://youtu.be/dQw4w9WgXcQ?si=NblIBgit-qHN7MoH&t=69",), "https://youtu.be/dQw4w9WgXcQ?t=69" ); assert_eq!( - clink.find_and_replace("https://youtu.be/dQw4w9WgXcQ?si=NblIBgit-qHN7MoH&t=69&fbclid=clid",), + clink.find_and_replace( + "https://youtu.be/dQw4w9WgXcQ?si=NblIBgit-qHN7MoH&t=69&fbclid=clid", + ), "https://youtu.be/dQw4w9WgXcQ?t=69" ); @@ -323,16 +350,12 @@ mod find_and_replace { let clink = Clink::new(ClinkConfig::new(Mode::YourMom)); assert_eq!( - clink.find_and_replace( - "https://test.test/?si=dsadsa", - ), + clink.find_and_replace("https://test.test/?si=dsadsa",), "https://test.test/?si=dsadsa&utm_source=your_mom" ); assert_eq!( - clink.find_and_replace( - "https://youtu.be/?si=dsadsa", - ), + clink.find_and_replace("https://youtu.be/?si=dsadsa",), "https://youtu.be/?utm_source=your_mom" ); } diff --git a/src/config.rs b/src/config.rs index 125fa24..3ebeda7 100644 --- a/src/config.rs +++ b/src/config.rs @@ -9,6 +9,9 @@ use serde::{Deserialize, Serialize}; use crate::mode::Mode; +/// add query param, that must be replaced within any domain +/// to specify domain specific params use format +/// "{domain}``{param}" fn get_default_params() -> HashSet> { HashSet::from([ "fbclid".into(),