mod activity; mod actor; pub mod ap_content; mod blocklist; mod federated_profile; mod follow; mod follow_repository; pub mod remote_goals; mod review; mod social; mod watchlist; pub use ap_content::PostgresApContentQuery; pub use remote_goals::PostgresRemoteGoalRepository; use k_ap::{FollowerStatus, RemoteActor}; use sqlx::{PgPool, Row}; pub(crate) fn status_to_str(status: &FollowerStatus) -> &'static str { match status { FollowerStatus::Pending => "pending", FollowerStatus::Accepted => "accepted", FollowerStatus::Rejected => "rejected", } } pub(crate) fn str_to_status(s: &str) -> FollowerStatus { match s { "accepted" => FollowerStatus::Accepted, "rejected" => FollowerStatus::Rejected, _ => FollowerStatus::Pending, } } pub(crate) fn pg_remote_actor(row: &sqlx::postgres::PgRow, url_col: &str) -> RemoteActor { RemoteActor { url: row.get(url_col), handle: row.try_get("handle").unwrap_or_default(), inbox_url: row.try_get("inbox_url").unwrap_or_default(), shared_inbox_url: row.try_get("shared_inbox_url").ok().flatten(), display_name: row.try_get("display_name").ok().flatten(), avatar_url: row.try_get("avatar_url").ok().flatten(), outbox_url: row.try_get("outbox_url").ok().flatten(), bio: row.try_get("bio").ok().flatten(), banner_url: row.try_get("banner_url").ok().flatten(), followers_url: row.try_get("followers_url").ok().flatten(), following_url: row.try_get("following_url").ok().flatten(), also_known_as: row .try_get::, _>("also_known_as") .ok() .flatten() .map(|s| { serde_json::from_str::>(&s).unwrap_or_else(|e| { tracing::warn!(raw = %s, error = %e, "failed to parse also_known_as JSON"); vec![s] }) }) .unwrap_or_default(), fetched_at: row.try_get("fetched_at").ok(), } } pub(crate) const PG_ACTOR_COLS: &str = "a.handle, a.inbox_url, a.shared_inbox_url, a.display_name, a.avatar_url, a.outbox_url, a.bio, a.banner_url, a.followers_url, a.following_url, a.also_known_as, a.fetched_at"; pub struct PostgresFederationRepository { pub(crate) pool: PgPool, } impl PostgresFederationRepository { pub fn new(pool: PgPool) -> Self { Self { pool } } } pub fn create_federated_profile_query( pool: PgPool, ) -> std::sync::Arc { std::sync::Arc::new(PostgresFederationRepository::new(pool)) } pub fn wire(pool: PgPool) -> activitypub::FederationRepos { let fed = std::sync::Arc::new(PostgresFederationRepository::new(pool)); activitypub::FederationRepos { activity: std::sync::Arc::clone(&fed) as _, follow: std::sync::Arc::clone(&fed) as _, actor: std::sync::Arc::clone(&fed) as _, blocklist: std::sync::Arc::clone(&fed) as _, admin_query: std::sync::Arc::clone(&fed) as _, review_store: std::sync::Arc::clone(&fed) as _, remote_watchlist: std::sync::Arc::clone(&fed) as _, follow_command: std::sync::Arc::clone(&fed) as _, follow_query: fed as _, } }