use std::error::Error; use elefren::status_builder::Visibility; use crate::error::GroupError; pub trait LogError { fn log_error>(self, msg: S); } impl LogError for Result { fn log_error>(self, msg: S) { match self { Ok(_) => {} Err(e) => { error!("{}: {}", msg.as_ref(), e); } } } } pub(crate) fn acct_to_server(acct: &str) -> Option<&str> { acct.trim_start_matches('@').split('@').nth(1) } pub(crate) fn normalize_acct(acct: &str, group: &str) -> Result { let acct = acct.trim_start_matches('@').to_lowercase(); if acct_to_server(&acct).is_some() { // already has server Ok(acct) } else if let Some(gs) = acct_to_server(group) { // attach server from the group actor Ok(format!("{}@{}", acct, gs)) } else { Err(GroupError::BadConfig( format!("Group acct {} is missing server!", group).into(), )) } } #[cfg(test)] mod test { use crate::error::GroupError; use crate::utils::{acct_to_server, normalize_acct}; #[test] fn test_acct_to_server() { assert_eq!(Some("novak"), acct_to_server("pepa@novak")); assert_eq!(Some("banana.co.uk"), acct_to_server("@pepa@banana.co.uk")); assert_eq!(None, acct_to_server("probably_local")); } #[test] fn test_normalize_acct() { assert_eq!( Ok("piggo@piggo.space".into()), normalize_acct("piggo", "betty@piggo.space") ); assert_eq!( Ok("piggo@piggo.space".into()), normalize_acct("@piggo", "betty@piggo.space") ); assert_eq!( Ok("piggo@piggo.space".into()), normalize_acct("@piggo@piggo.space", "betty@piggo.space") ); assert_eq!( Ok("piggo@piggo.space".into()), normalize_acct("@piggo@piggo.space", "oggip@mastodon.social") ); assert_eq!( Ok("piggo@piggo.space".into()), normalize_acct("piggo@piggo.space", "oggip@mastodon.social") ); assert_eq!( Ok("piggo@mastodon.social".into()), normalize_acct("@piggo", "oggip@mastodon.social") ); assert_eq!( Ok("piggo@piggo.space".into()), normalize_acct("piggo@piggo.space", "uhh") ); assert_eq!( Ok("piggo@piggo.space".into()), normalize_acct("piGGgo@pIggo.spaCe", "uhh") ); assert_eq!( Ok("piggo@banana.nana".into()), normalize_acct("piGGgo", "foo@baNANA.nana") ); assert_eq!(Err(GroupError::BadConfig("_".into())), normalize_acct("piggo", "uhh")); } } pub trait VisExt: Copy { /// Check if is private or direct fn is_private(self) -> bool; fn make_unlisted(self) -> Self; } impl VisExt for Visibility { fn is_private(self) -> bool { self == Visibility::Direct || self == Visibility::Private } fn make_unlisted(self) -> Self { match self { Visibility::Public => { Visibility::Unlisted } other => other, } } } pub(crate) fn strip_html(content: &str) -> String { let content = content.replace("
", "
"); let content = content.replace("

", "

"); voca_rs::strip::strip_tags(&content) }