use crate::{ errors::ApiError, extractors::OptionalAuthUser, handlers::feed::to_thought_response, state::AppState, }; use api_types::{ requests::PaginationQuery, responses::{ActorConnectionPageResponse, ActorConnectionResponse}, }; use application::use_cases::federation_management::{ get_actor_connections_page, get_remote_actor_posts, }; use axum::{ extract::{Path, Query, State}, Json, }; use domain::models::feed::PageParams; pub async fn remote_actor_posts_handler( State(s): State, Path(handle): Path, Query(q): Query, OptionalAuthUser(viewer): OptionalAuthUser, ) -> Result, ApiError> { let page = PageParams { page: q.page(), per_page: q.per_page(), }; let result = get_remote_actor_posts( &*s.federation, &*s.ap_repo, &*s.feed, &*s.federation_scheduler, &handle, page, viewer.as_ref(), ) .await?; Ok(Json(serde_json::json!({ "total": result.total, "page": result.page, "per_page": result.per_page, "items": result.items.iter().map(to_thought_response).collect::>(), }))) } pub async fn actor_followers_handler( State(s): State, Path(handle): Path, Query(q): Query, ) -> Result, ApiError> { actor_connections_handler(s, handle, "followers", q.page() as u32).await } pub async fn actor_following_handler( State(s): State, Path(handle): Path, Query(q): Query, ) -> Result, ApiError> { actor_connections_handler(s, handle, "following", q.page() as u32).await } async fn actor_connections_handler( s: AppState, handle: String, connection_type: &str, page: u32, ) -> Result, ApiError> { let (items, has_more) = get_actor_connections_page( &*s.federation, &*s.remote_actor_connections, &*s.federation_scheduler, &handle, connection_type, page, ) .await?; Ok(Json(ActorConnectionPageResponse { items: items .into_iter() .map(|a| ActorConnectionResponse { handle: a.handle, display_name: a.display_name, avatar_url: a.avatar_url, url: a.url, }) .collect(), page, has_more, })) } #[cfg(test)] mod tests { use super::*; use crate::testing::make_state; use axum::{body::Body, http::Request, routing::get, Router}; use tower::ServiceExt; fn app() -> Router { Router::new() .route( "/federation/actors/{handle}/posts", get(remote_actor_posts_handler), ) .with_state(make_state()) } #[tokio::test] async fn unknown_actor_returns_404() { let resp = app() .oneshot( Request::builder() .uri("/federation/actors/%40alice%40example.com/posts") .body(Body::empty()) .unwrap(), ) .await .unwrap(); assert_eq!(resp.status(), 404); } }