diff --git a/src/activitypub/user/following.rs b/src/activitypub/user/following.rs index 8b66c7e0..ff75f610 100644 --- a/src/activitypub/user/following.rs +++ b/src/activitypub/user/following.rs @@ -1,114 +1,58 @@ -use axum::{extract::{Path, Query, State}, http::StatusCode, Json}; +use axum::{extract::{Path, Query, State}, http::StatusCode}; use sea_orm::{ColumnTrait, Condition, EntityTrait, PaginatorTrait, QueryFilter, QuerySelect, SelectColumns}; -use crate::{activitypub::{JsonLD, Pagination}, activitystream::{object::{activity::{Activity, ActivityMut, ActivityType}, collection::{page::CollectionPageMut, CollectionMut, CollectionType}, ObjectType}, Base, BaseMut, BaseType, Node}, errors::LoggableError, model::{self, activity, object, user}, server::Context, url}; +use crate::{activitypub::{jsonld::LD, JsonLD, Pagination}, activitystream::{object::collection::{page::CollectionPageMut, CollectionMut, CollectionType}, BaseMut, Node}, model, server::Context, url}; -pub async fn following( +pub async fn follow___( State(ctx): State, Path(id): Path, Query(page): Query, ) -> Result, StatusCode> { - let follow = if out { "following" } else { "followers" }; + let follow___ = if out { "following" } else { "followers" }; let limit = page.batch.unwrap_or(20).min(50); let offset = page.offset.unwrap_or(0); if let Some(true) = page.page { + + use model::relation::Column::{Following, Follower}; match model::relation::Entity::find() - .filter(Condition::all().add(model::relation::Column::Follower.eq(id.clone()))) - .select_column(model::relation::Column::Following) - .limit(limit) // TODO allow customizing, with boundaries + .filter(Condition::all().add(if out { Follower } else { Following }.eq(id.clone()))) + .select_column(if out { Following } else { Follower }) + .limit(limit) .offset(page.offset.unwrap_or(0)) .all(ctx.db()).await { Err(e) => { - tracing::error!("error queriying who {id} is following: {e}"); + tracing::error!("error queriying {follow___} for {id}: {e}"); Err(StatusCode::INTERNAL_SERVER_ERROR) }, Ok(following) => { Ok(JsonLD( serde_json::Value::new_object() .set_collection_type(Some(CollectionType::OrderedCollectionPage)) - .set_part_of(Node::link(url!(ctx, "/users/{id}/following"))) - .set_next(Node::link(url!(ctx, "/users/{id}/following?page=true&offset={}", offset+limit))) + .set_part_of(Node::link(url!(ctx, "/users/{id}/{follow___}"))) + .set_next(Node::link(url!(ctx, "/users/{id}/{follow___}?page=true&offset={}", offset+limit))) .set_ordered_items(Node::array(following.into_iter().map(|x| x.following).collect())) .ld_context() )) }, } + } else { + let count = model::relation::Entity::find() .filter(Condition::all().add(model::relation::Column::Follower.eq(id.clone()))) .count(ctx.db()).await.unwrap_or_else(|e| { - tracing::error!("failed counting following for {id}: {e}"); + tracing::error!("failed counting {follow___} for {id}: {e}"); 0 }); Ok(JsonLD( serde_json::Value::new_object() - .set_id(Some(&format!("{}/users/{}/following", ctx.base(), id))) + .set_id(Some(&format!("{}/users/{id}/{follow___}", ctx.base()))) .set_collection_type(Some(CollectionType::OrderedCollection)) .set_total_items(Some(count)) - .set_first(Node::link(format!("{}/users/{}/following?page=true", ctx.base(), id))) - .ld_context() - )) - } -} - - - - - - - - - - - - - - -pub async fn followers( - State(ctx): State, - Path(id): Path, - Query(page): Query, -) -> Result, StatusCode> { - let limit = page.batch.unwrap_or(20).min(50); - let offset = page.offset.unwrap_or(0); - if let Some(true) = page.page { - match model::relation::Entity::find() - .filter(Condition::all().add(model::relation::Column::Following.eq(id.clone()))) - .select_column(model::relation::Column::Follower) - .limit(limit) // TODO allow customizing, with boundaries - .offset(page.offset.unwrap_or(0)) - .all(ctx.db()).await - { - Err(e) => { - tracing::error!("error queriying who {id} is following: {e}"); - Err(StatusCode::INTERNAL_SERVER_ERROR) - }, - Ok(following) => { - Ok(JsonLD( - serde_json::Value::new_object() - .set_collection_type(Some(CollectionType::OrderedCollectionPage)) - .set_part_of(Node::link(url!(ctx, "/users/{id}/followers"))) - .set_next(Node::link(url!(ctx, "/users/{id}/followers?page=true&offset={}", offset+limit))) - .set_ordered_items(Node::array(following.into_iter().map(|x| x.follower).collect())) - .ld_context() - )) - }, - } - } else { - let count = model::relation::Entity::find() - .filter(Condition::all().add(model::relation::Column::Following.eq(id.clone()))) - .count(ctx.db()).await.unwrap_or_else(|e| { - tracing::error!("failed counting followers for {id}: {e}"); - 0 - }); - Ok(JsonLD( - serde_json::Value::new_object() - .set_id(Some(&format!("{}/users/{}/followers", ctx.base(), id))) - .set_collection_type(Some(CollectionType::OrderedCollection)) - .set_total_items(Some(count)) - .set_first(Node::link(format!("{}/users/{}/followers?page=true", ctx.base(), id))) + .set_first(Node::link(format!("{}/users/{id}/{follow___}?page=true", ctx.base()))) .ld_context() )) + } } diff --git a/src/server.rs b/src/server.rs index 831eb49a..9647781d 100644 --- a/src/server.rs +++ b/src/server.rs @@ -87,8 +87,8 @@ pub async fn serve(db: DatabaseConnection, domain: String) { .route("/users/:id", get(ap::user::view)) .route("/users/:id/inbox", post(ap::user::inbox)) .route("/users/:id/outbox", get(ap::user::outbox)) - .route("/users/:id/followers", get(ap::user::followers)) - .route("/users/:id/following", get(ap::user::following)) + .route("/users/:id/followers", get(ap::user::follow___::)) + .route("/users/:id/following", get(ap::user::follow___::)) // specific object routes .route("/activities/:id", get(ap::activity::view)) .route("/objects/:id", get(ap::object::view))