upub/core/src/ext.rs

152 lines
4 KiB
Rust
Raw Normal View History

use sea_orm::{ConnectionTrait, PaginatorTrait};
pub trait IntoActivityPub {
fn into_activity_pub_json(self, ctx: &crate::Context) -> serde_json::Value;
}
2024-09-19 16:51:20 +02:00
#[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> {
2024-08-11 12:55:27 +02:00
// 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())
}
}
2024-07-15 20:57:48 +02:00
// 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()
}
}
2024-12-31 17:10:05 +01:00
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))
}