diff --git a/crates/api_apub/src/lib.rs b/crates/api_apub/src/lib.rs index 92f29f7..b589d17 100644 --- a/crates/api_apub/src/lib.rs +++ b/crates/api_apub/src/lib.rs @@ -1,8 +1,11 @@ use hatsu_apub::{ actors::{PublicKeySchema, User, UserAttachment, UserImage}, + collections::{Collection, CollectionOrPage, CollectionPage}, links::{Emoji, EmojiIcon, Hashtag, Mention, Tag}, objects::Note, }; +use serde_json::Value; +use url::Url; use utoipa::OpenApi; use utoipa_axum::router::OpenApiRouter; @@ -23,6 +26,10 @@ pub const TAG: &str = "apub"; User, UserAttachment, UserImage, + Collection, + CollectionOrPage, + CollectionPage, + CollectionPage, Emoji, EmojiIcon, Hashtag, diff --git a/crates/api_apub/src/users/user_followers.rs b/crates/api_apub/src/users/user_followers.rs index 8bea360..bb5fa4a 100644 --- a/crates/api_apub/src/users/user_followers.rs +++ b/crates/api_apub/src/users/user_followers.rs @@ -11,12 +11,11 @@ use axum::{ }; use hatsu_apub::{ actors::ApubUser, - collections::{Collection, CollectionPage}, + collections::{Collection, CollectionOrPage, CollectionPage}, }; use hatsu_db_schema::{prelude::ReceivedFollow, received_follow}; use hatsu_utils::{AppData, AppError}; use sea_orm::{ModelTrait, PaginatorTrait, QueryOrder}; -use serde_json::Value; use url::Url; use crate::{users::Pagination, TAG}; @@ -27,8 +26,7 @@ use crate::{users::Pagination, TAG}; tag = TAG, path = "/users/{user}/followers", responses( - // TODO: strict types - (status = OK, description = "Followers", body = Value), + (status = OK, description = "Followers", body = CollectionOrPage), (status = NOT_FOUND, description = "User does not exist", body = AppError) ), params( @@ -41,8 +39,7 @@ pub async fn handler( Path(name): Path, pagination: Query, data: Data, - // TODO: strict types -) -> Result>, AppError> { +) -> Result>, AppError> { let user_id: ObjectId = hatsu_utils::url::generate_user_url(data.domain(), &name)?.into(); let user = user_id.dereference_local(&data).await?; @@ -58,12 +55,12 @@ pub async fn handler( match pagination.page { None => Ok(FederationJson(WithContext::new_default( - serde_json::to_value(Collection::new( + CollectionOrPage::Collection(Collection::new( &hatsu_utils::url::generate_user_url(data.domain(), &name)? .join(&format!("{name}/followers"))?, total.number_of_items, Some(total.number_of_pages), - )?)?, + )?), ))), Some(page) => if page > 1 && page > total.number_of_pages { @@ -73,7 +70,7 @@ pub async fn handler( )) } else { Ok(FederationJson(WithContext::new_default( - serde_json::to_value(CollectionPage::::new( + CollectionOrPage::CollectionPageUrl(CollectionPage::::new( hatsu_utils::url::generate_user_url(data.domain(), &name)? .join(&format!("{name}/followers"))?, total.number_of_items, @@ -86,7 +83,7 @@ pub async fn handler( .collect(), total.number_of_pages, page, - )?)?, + )?), ))) }, } diff --git a/crates/api_apub/src/users/user_following.rs b/crates/api_apub/src/users/user_following.rs index 7ef11a0..ba64783 100644 --- a/crates/api_apub/src/users/user_following.rs +++ b/crates/api_apub/src/users/user_following.rs @@ -8,9 +8,8 @@ use axum::{ extract::{Path, Query}, response::Redirect, }; -use hatsu_apub::collections::{Collection, CollectionPage}; +use hatsu_apub::collections::{Collection, CollectionOrPage, CollectionPage}; use hatsu_utils::{AppData, AppError}; -use serde_json::Value; use url::Url; use crate::{users::Pagination, TAG}; @@ -21,8 +20,7 @@ use crate::{users::Pagination, TAG}; tag = TAG, path = "/users/{user}/following", responses( - // TODO: strict types - (status = OK, description = "Following", body = Value), + (status = OK, description = "Following", body = CollectionOrPage), (status = NOT_FOUND, description = "User does not exist", body = AppError) ), params( @@ -35,26 +33,25 @@ pub async fn handler( Path(name): Path, pagination: Query, data: Data, - // TODO: strict types -) -> Result>, AppError> { +) -> Result>, AppError> { match pagination.page { None => Ok(FederationJson(WithContext::new_default( - serde_json::to_value(Collection::new( + CollectionOrPage::Collection(Collection::new( &hatsu_utils::url::generate_user_url(data.domain(), &name)? .join(&format!("{name}/following"))?, 0, Some(0), - )?)?, + )?), ))), Some(page) => Ok(FederationJson(WithContext::new_default( - serde_json::to_value(CollectionPage::::new( + CollectionOrPage::CollectionPageUrl(CollectionPage::::new( hatsu_utils::url::generate_user_url(data.domain(), &name)? .join(&format!("{name}/following"))?, 0, vec![], 0, page, - )?)?, + )?), ))), } } diff --git a/crates/api_apub/src/users/user_outbox.rs b/crates/api_apub/src/users/user_outbox.rs index 5f90000..806923e 100644 --- a/crates/api_apub/src/users/user_outbox.rs +++ b/crates/api_apub/src/users/user_outbox.rs @@ -12,7 +12,7 @@ use axum::{ use hatsu_apub::{ activities::ApubActivity, actors::ApubUser, - collections::{Collection, CollectionPage}, + collections::{Collection, CollectionOrPage, CollectionPage}, }; use hatsu_db_schema::{activity, prelude::Activity}; use hatsu_utils::{AppData, AppError}; @@ -27,8 +27,7 @@ use crate::{users::Pagination, TAG}; tag = TAG, path = "/users/{user}/outbox", responses( - // TODO: strict types - (status = OK, description = "Outbox", body = Value), + (status = OK, description = "Outbox", body = CollectionOrPage), (status = NOT_FOUND, description = "User does not exist", body = AppError) ), params( @@ -41,8 +40,7 @@ pub async fn handler( Path(name): Path, pagination: Query, data: Data, - // TODO: strict types -) -> Result>, AppError> { +) -> Result>, AppError> { let user_id: ObjectId = hatsu_utils::url::generate_user_url(data.domain(), &name)?.into(); let user = user_id.dereference_local(&data).await?; @@ -60,12 +58,12 @@ pub async fn handler( match pagination.page { None => Ok(FederationJson(WithContext::new_default( - serde_json::to_value(Collection::new( + CollectionOrPage::Collection(Collection::new( &hatsu_utils::url::generate_user_url(data.domain(), &name)? .join(&format!("{name}/outbox"))?, total.number_of_items, Some(total.number_of_pages), - )?)?, + )?), ))), Some(page) => if page > 1 && page > total.number_of_pages { @@ -75,7 +73,7 @@ pub async fn handler( )) } else { Ok(FederationJson(WithContext::new_default( - serde_json::to_value(CollectionPage::::new( + CollectionOrPage::CollectionPageValue(CollectionPage::::new( hatsu_utils::url::generate_user_url(data.domain(), &name)? .join(&format!("{name}/outbox"))?, total.number_of_items, @@ -91,7 +89,7 @@ pub async fn handler( .collect(), total.number_of_pages, page, - )?)?, + )?), ))) }, } diff --git a/crates/apub/src/collections/collection.rs b/crates/apub/src/collections/collection.rs index 2fa4ac3..0b296c4 100644 --- a/crates/apub/src/collections/collection.rs +++ b/crates/apub/src/collections/collection.rs @@ -2,10 +2,11 @@ use activitypub_federation::kinds::collection::OrderedCollectionType; use hatsu_utils::AppError; use serde::{Deserialize, Serialize}; use url::Url; +use utoipa::ToSchema; use crate::collections::generate_collection_page_url; -#[derive(Clone, Debug, Deserialize, Serialize)] +#[derive(Clone, Debug, Deserialize, Serialize, ToSchema)] #[serde(rename_all = "camelCase")] pub struct Collection { #[serde(rename = "type")] diff --git a/crates/apub/src/collections/collection_page.rs b/crates/apub/src/collections/collection_page.rs index ee26c16..f70510c 100644 --- a/crates/apub/src/collections/collection_page.rs +++ b/crates/apub/src/collections/collection_page.rs @@ -2,10 +2,11 @@ use activitypub_federation::kinds::collection::OrderedCollectionPageType; use hatsu_utils::AppError; use serde::{Deserialize, Serialize}; use url::Url; +use utoipa::ToSchema; use crate::collections::generate_collection_page_url; -#[derive(Clone, Debug, Deserialize, Serialize)] +#[derive(Clone, Debug, Deserialize, Serialize, ToSchema)] #[serde(rename_all = "camelCase")] pub struct CollectionPage { #[serde(rename = "type")] diff --git a/crates/apub/src/collections/mod.rs b/crates/apub/src/collections/mod.rs index aad252c..705c2cb 100644 --- a/crates/apub/src/collections/mod.rs +++ b/crates/apub/src/collections/mod.rs @@ -1,5 +1,8 @@ use hatsu_utils::AppError; +use serde::{Deserialize, Serialize}; +use serde_json::Value; use url::Url; +use utoipa::ToSchema; mod collection; mod collection_page; @@ -13,3 +16,11 @@ pub fn generate_collection_page_url(collection_id: &Url, page: u64) -> Result), + CollectionPageValue(CollectionPage), +}