use sea_orm::{ConnectionTrait, PaginatorTrait}; pub trait IntoActivityPub { fn into_activity_pub_json(self, ctx: &crate::Context) -> serde_json::Value; } #[allow(async_fn_in_trait)] pub trait AnyQuery { async fn any(self, db: &impl ConnectionTrait) -> Result<bool, sea_orm::DbErr>; } impl<T : sea_orm::EntityTrait> AnyQuery for sea_orm::Select<T> where T::Model : Sync, { async fn any(self, db: &impl ConnectionTrait) -> Result<bool, sea_orm::DbErr> { // TODO ConnectionTrait became an iterator?? self.count(db) gives error now Ok(PaginatorTrait::count(self, db).await? > 0) } } impl<T : sea_orm::SelectorTrait + Send + Sync> AnyQuery for sea_orm::Selector<T> { async fn any(self, db: &impl ConnectionTrait) -> Result<bool, sea_orm::DbErr> { Ok(self.count(db).await? > 0) } } pub trait LoggableError { fn info_failed(self, msg: &str); fn warn_failed(self, msg: &str); fn err_failed(self, msg: &str); } impl<T, E: std::error::Error> LoggableError for Result<T, E> { fn info_failed(self, msg: &str) { if let Err(e) = self { tracing::info!("{} : {}", msg, e); } } fn warn_failed(self, msg: &str) { if let Err(e) = self { tracing::warn!("{} : {}", msg, e); } } fn err_failed(self, msg: &str) { if let Err(e) = self { tracing::error!("{} : {}", msg, e); } } } #[derive(Clone, Debug, PartialEq, Eq, serde::Serialize, serde::Deserialize)] pub struct JsonVec<T>(pub Vec<T>); impl<T> From<Vec<T>> for JsonVec<T> { fn from(value: Vec<T>) -> Self { JsonVec(value) } } impl<T> Default for JsonVec<T> { fn default() -> Self { JsonVec(Vec::new()) } } // TODO we need this dummy to access the default implementation, which needs to be wrapped to catch // nulls. is there a way to directly call super::try_get_from_json ?? i think this gets // compiled into a lot of variants... #[derive(serde::Deserialize)] struct DummyVec<T>(pub Vec<T>); impl<T: serde::de::DeserializeOwned> sea_orm::TryGetableFromJson for DummyVec<T> {} impl<T: serde::de::DeserializeOwned> sea_orm::TryGetableFromJson for JsonVec<T> { fn try_get_from_json<I: sea_orm::ColIdx>(res: &sea_orm::QueryResult, idx: I) -> Result<Self, sea_orm::TryGetError> { match DummyVec::try_get_from_json(res, idx) { Ok(DummyVec(x)) => Ok(Self(x)), Err(sea_orm::TryGetError::Null(_)) => Ok(Self::default()), Err(e) => Err(e), } } fn from_json_vec(value: serde_json::Value) -> Result<Vec<Self>, sea_orm::TryGetError> { match DummyVec::from_json_vec(value) { Ok(x) => Ok(x.into_iter().map(|x| JsonVec(x.0)).collect()), Err(sea_orm::TryGetError::Null(_)) => Ok(vec![]), Err(e) => Err(e), } } } impl<T: serde::ser::Serialize> std::convert::From<JsonVec<T>> for sea_orm::Value { fn from(source: JsonVec<T>) -> Self { sea_orm::Value::Json(serde_json::to_value(&source).ok().map(std::boxed::Box::new)) } } impl<T: serde::de::DeserializeOwned + TypeName> sea_orm::sea_query::ValueType for JsonVec<T> { fn try_from(v: sea_orm::Value) -> Result<Self, sea_orm::sea_query::ValueTypeErr> { match v { sea_orm::Value::Json(Some(json)) => Ok( serde_json::from_value(*json).map_err(|_| sea_orm::sea_query::ValueTypeErr)?, ), sea_orm::Value::Json(None) => Ok(JsonVec::default()), _ => Err(sea_orm::sea_query::ValueTypeErr), } } fn type_name() -> String { format!("JsonVec_{}", T::type_name()) } fn array_type() -> sea_orm::sea_query::ArrayType { sea_orm::sea_query::ArrayType::Json } fn column_type() -> sea_orm::sea_query::ColumnType { sea_orm::sea_query::ColumnType::Json } } impl<T> sea_orm::sea_query::Nullable for JsonVec<T> { fn null() -> sea_orm::Value { sea_orm::Value::Json(None) } } pub trait TypeName { fn type_name() -> String; } impl TypeName for String { fn type_name() -> String { "String".to_string() } } pub fn strip_proto(url: &str) -> &str { url .strip_prefix("https://") .unwrap_or(url) .strip_prefix("http://") .unwrap_or(url) } pub fn is_blacklisted(id: &str, blacklist: &[String]) -> bool { let stripped = strip_proto(id); blacklist.iter().any(|x| stripped.starts_with(x)) }