diff --git a/upub/core/src/selector/batch.rs b/upub/core/src/selector/batch.rs index 230ef01..0918475 100644 --- a/upub/core/src/selector/batch.rs +++ b/upub/core/src/selector/batch.rs @@ -3,6 +3,27 @@ use std::collections::{hash_map::Entry, HashMap}; use sea_orm::{ConnectionTrait, DbErr, EntityTrait, FromQueryResult, ModelTrait, QueryFilter}; use super::{RichActivity, RichObject}; +#[allow(async_fn_in_trait)] +pub trait RichFillable: Sized { + async fn load_batched_models(self, tx: &impl ConnectionTrait) -> Result; +} + +impl RichFillable for T +where + T: BatchFillable +{ + async fn load_batched_models(self, tx: &impl ConnectionTrait) -> Result { + self + .with_batched::(tx) + .await? + .with_batched::(tx) + .await? + .with_batched::(tx) + .await + } +} + + #[allow(async_fn_in_trait)] pub trait BatchFillable: Sized { async fn with_batched(self, tx: &impl ConnectionTrait) -> Result diff --git a/upub/core/src/selector/mod.rs b/upub/core/src/selector/mod.rs index 05c1fd8..8bf6bda 100644 --- a/upub/core/src/selector/mod.rs +++ b/upub/core/src/selector/mod.rs @@ -1,5 +1,5 @@ mod batch; -pub use batch::BatchFillable; +pub use batch::{BatchFillable, RichFillable}; mod query; pub use query::Query; diff --git a/upub/core/src/selector/query.rs b/upub/core/src/selector/query.rs index 8fdf63f..02acf18 100644 --- a/upub/core/src/selector/query.rs +++ b/upub/core/src/selector/query.rs @@ -4,7 +4,7 @@ use crate::model; pub struct Query; impl Query { - pub fn feed(my_id: Option) -> Select { + pub fn feed(my_id: Option, with_replies: bool) -> Select { let mut select = model::addressing::Entity::find() .distinct_on([ (model::addressing::Entity, model::addressing::Column::Published).into_column_ref(), @@ -45,10 +45,14 @@ impl Query { .select_column_as(model::like::Column::Actor, format!("{}{}", model::like::Entity.table_name(), model::like::Column::Actor.to_string())); } + if !with_replies { + select = select.filter(model::object::Column::InReplyTo.is_null()); + } + select } - pub fn objects(my_id: Option) -> Select { + pub fn objects(my_id: Option, with_replies: bool) -> Select { let mut select = model::addressing::Entity::find() .distinct() .join(sea_orm::JoinType::InnerJoin, model::addressing::Relation::Objects.def()) @@ -68,6 +72,10 @@ impl Query { .select_column_as(model::like::Column::Actor, format!("{}{}", model::like::Entity.table_name(), model::like::Column::Actor.to_string())); } + if !with_replies { + select = select.filter(model::object::Column::InReplyTo.is_null()); + } + select } diff --git a/upub/routes/src/activitypub/activity.rs b/upub/routes/src/activitypub/activity.rs index 7f371c0..39285b5 100644 --- a/upub/routes/src/activitypub/activity.rs +++ b/upub/routes/src/activitypub/activity.rs @@ -1,6 +1,6 @@ use axum::extract::{Path, Query, State}; -use sea_orm::{ColumnTrait, QueryFilter, TransactionTrait}; -use upub::{model, selector::{BatchFillable, RichActivity}, traits::Fetcher, Context}; +use sea_orm::{ColumnTrait, Condition, QueryFilter, TransactionTrait}; +use upub::{model, selector::{RichActivity, RichFillable}, traits::Fetcher, Context}; use apb::LD; use crate::{builders::JsonLD, AuthIdentity}; @@ -23,20 +23,19 @@ pub async fn view( } } - let row = upub::Query::feed(auth.my_id()) - .filter(auth.filter_activities()) - .filter(model::activity::Column::Id.eq(&aid)) + let filter = Condition::all() + .add(auth.filter_activities()) + .add(model::activity::Column::Id.eq(&aid)); + + let activity = upub::Query::feed(auth.my_id(), true) + .filter(filter) .into_model::() .one(ctx.db()) .await? .ok_or_else(crate::ApiError::not_found)? - .with_batched::(ctx.db()) - .await? - .with_batched::(ctx.db()) - .await? - .with_batched::(ctx.db()) + .load_batched_models(ctx.db()) .await?; - Ok(JsonLD(ctx.ap(row).ld_context())) + Ok(JsonLD(ctx.ap(activity).ld_context())) } diff --git a/upub/routes/src/activitypub/actor/following.rs b/upub/routes/src/activitypub/actor/following.rs index 707bb70..e745285 100644 --- a/upub/routes/src/activitypub/actor/following.rs +++ b/upub/routes/src/activitypub/actor/following.rs @@ -59,7 +59,7 @@ pub async fn page( use upub::model::relation::Column::{Follower, Following, FollowerInstance, FollowingInstance}; let follow___ = if OUTGOING { "following" } else { "followers" }; - let (limit, offset) = page.pagination(); + let (limit, _offset) = page.pagination(); let (user, config) = model::actor::Entity::find_by_ap_id(&ctx.uid(&id)) .find_also_related(model::config::Entity) @@ -117,7 +117,7 @@ pub async fn page( crate::builders::collection_page( &upub::url!(ctx, "/actors/{id}/{follow___}/page"), - offset, limit, + page, apb::Node::links(following), ) } diff --git a/upub/routes/src/activitypub/actor/inbox.rs b/upub/routes/src/activitypub/actor/inbox.rs index 5f70961..52330b0 100644 --- a/upub/routes/src/activitypub/actor/inbox.rs +++ b/upub/routes/src/activitypub/actor/inbox.rs @@ -1,7 +1,7 @@ use axum::{http::StatusCode, extract::{Path, Query, State}, Json}; -use sea_orm::{ColumnTrait, Condition}; +use sea_orm::{ColumnTrait, Condition, QueryFilter, QuerySelect}; -use upub::Context; +use upub::{selector::{RichActivity, RichFillable}, Context}; use crate::{activitypub::Pagination, builders::JsonLD, AuthIdentity, Identity}; @@ -35,18 +35,26 @@ pub async fn page( return Err(crate::ApiError::forbidden()); } - crate::builders::paginate_feed( - upub::url!(ctx, "/actors/{id}/inbox/page"), - Condition::any() - .add(upub::model::addressing::Column::Actor.eq(*internal)) - .add(upub::model::activity::Column::Actor.eq(uid)) - .add(upub::model::object::Column::AttributedTo.eq(uid)), - &ctx, - page, - auth.my_id(), - false, - ) - .await + let filter = Condition::any() + .add(upub::model::addressing::Column::Actor.eq(*internal)) + .add(upub::model::activity::Column::Actor.eq(uid)) + .add(upub::model::object::Column::AttributedTo.eq(uid)); + + let (limit, offset) = page.pagination(); + let items = upub::Query::feed(auth.my_id(), page.replies.unwrap_or(true)) + .filter(filter) + .limit(limit) + .offset(offset) + .into_model::() + .all(ctx.db()) + .await? + .load_batched_models(ctx.db()) + .await? + .into_iter() + .map(|item| ctx.ap(item)) + .collect(); + + crate::builders::collection_page(&upub::url!(ctx, "/actors/{id}/inbox/page"), page, apb::Node::array(items)) } pub async fn post( diff --git a/upub/routes/src/activitypub/actor/likes.rs b/upub/routes/src/activitypub/actor/likes.rs index a20eb52..121db2d 100644 --- a/upub/routes/src/activitypub/actor/likes.rs +++ b/upub/routes/src/activitypub/actor/likes.rs @@ -31,15 +31,13 @@ pub async fn page( let (limit, offset) = page.pagination(); - let mut select = upub::Query::objects(auth.my_id()) + let items : Vec = upub::Query::objects(auth.my_id(), true) .join(sea_orm::JoinType::InnerJoin, upub::model::object::Relation::Likes.def()) .filter(auth.filter_objects()) .filter(upub::model::like::Column::Actor.eq(user.internal)) .order_by_desc(upub::model::like::Column::Published) .limit(limit) - .offset(offset); - - let items : Vec = select + .offset(offset) .into_model::() .all(ctx.db()) .await? @@ -52,14 +50,6 @@ pub async fn page( .into_iter() .map(|x| ctx.ap(x)) .collect(); - - crate::builders::paginate_feed( - upub::url!(ctx, "/actors/{id}/outbox/page"), - auth.filter_objects(), - &ctx, - page, - auth.my_id(), - false, - ) - .await + + crate::builders::collection_page(&upub::url!(ctx, "/actors/{id}/outbox/page"), page, apb::Node::array(items)) } diff --git a/upub/routes/src/activitypub/actor/notifications.rs b/upub/routes/src/activitypub/actor/notifications.rs index 30ac8c0..61010a3 100644 --- a/upub/routes/src/activitypub/actor/notifications.rs +++ b/upub/routes/src/activitypub/actor/notifications.rs @@ -51,6 +51,6 @@ pub async fn page( .map(|x| ctx.ap(x)) .collect(); - crate::builders::collection_page(&upub::url!(ctx, "/actors/{id}/notifications/page"), offset, limit, apb::Node::array(activities)) + crate::builders::collection_page(&upub::url!(ctx, "/actors/{id}/notifications/page"), page, apb::Node::array(activities)) } diff --git a/upub/routes/src/activitypub/actor/outbox.rs b/upub/routes/src/activitypub/actor/outbox.rs index f7e4c51..4cfb83d 100644 --- a/upub/routes/src/activitypub/actor/outbox.rs +++ b/upub/routes/src/activitypub/actor/outbox.rs @@ -1,7 +1,7 @@ use axum::{extract::{Path, Query, State}, http::StatusCode, Json}; -use sea_orm::{ActiveValue::{NotSet, Set}, ColumnTrait, Condition, EntityTrait}; +use sea_orm::{ActiveValue::{NotSet, Set}, ColumnTrait, Condition, EntityTrait, QueryFilter, QuerySelect}; -use upub::{model, Context}; +use upub::{model, selector::{RichActivity, RichFillable}, Context}; use crate::{activitypub::{CreationResult, Pagination}, builders::JsonLD, AuthIdentity, Identity}; @@ -28,15 +28,23 @@ pub async fn page( .add(model::object::Column::Audience.eq(&uid)) ); - crate::builders::paginate_feed( - upub::url!(ctx, "/actors/{id}/outbox/page"), - filter, - &ctx, - page, - auth.my_id(), - false, - ) - .await + let (limit, offset) = page.pagination(); + // by default we want replies because servers don't know about our api and need to see everything + let items = upub::Query::feed(auth.my_id(), page.replies.unwrap_or(true)) + .filter(filter) + // TODO also limit to only local activities + .limit(limit) + .offset(offset) + .into_model::() + .all(ctx.db()) + .await? + .load_batched_models(ctx.db()) + .await? + .into_iter() + .map(|item| ctx.ap(item)) + .collect(); + + crate::builders::collection_page(&upub::url!(ctx, "/actors/{id}/outbox/page"), page, apb::Node::array(items)) } pub async fn post( diff --git a/upub/routes/src/activitypub/application.rs b/upub/routes/src/activitypub/application.rs index 76e0f59..22653a0 100644 --- a/upub/routes/src/activitypub/application.rs +++ b/upub/routes/src/activitypub/application.rs @@ -1,8 +1,8 @@ use apb::{LD, ActorMut, BaseMut, ObjectMut, PublicKeyMut}; use axum::{extract::{Path, Query, State}, http::HeaderMap, response::{IntoResponse, Redirect, Response}}; use reqwest::Method; -use sea_orm::{Condition, ColumnTrait}; -use upub::{traits::{Cloaker, Fetcher}, Context}; +use sea_orm::{ColumnTrait, Condition, QueryFilter, QuerySelect}; +use upub::{selector::{RichFillable, RichObject}, traits::{Cloaker, Fetcher}, Context}; use crate::{builders::JsonLD, ApiError, AuthIdentity}; @@ -57,21 +57,28 @@ pub async fn search( // TODO lmao rethink this all // still haven't redone this gg me + // have redone it but didnt rethink it properly so we're stuck with this bahahaha let page = Pagination { offset: page.offset, batch: page.batch, replies: Some(true), }; - crate::builders::paginate_feed( - upub::url!(ctx, "/search"), - filter, - &ctx, - page, - auth.my_id(), - false, - ) - .await + let (limit, offset) = page.pagination(); + let items = upub::Query::feed(auth.my_id(), true) + .filter(filter) + .limit(limit) + .offset(offset) + .into_model::() + .all(ctx.db()) + .await? + .load_batched_models(ctx.db()) + .await? + .into_iter() + .map(|item| ctx.ap(item)) + .collect(); + + crate::builders::collection_page(&upub::url!(ctx, "/search"), page, apb::Node::array(items)) } #[derive(Debug, serde::Deserialize)] diff --git a/upub/routes/src/activitypub/inbox.rs b/upub/routes/src/activitypub/inbox.rs index 24a4c28..ae57d0b 100644 --- a/upub/routes/src/activitypub/inbox.rs +++ b/upub/routes/src/activitypub/inbox.rs @@ -1,7 +1,7 @@ use apb::{Activity, ActivityType, Base}; use axum::{extract::{Query, State}, http::StatusCode, Json}; -use sea_orm::{sea_query::IntoCondition, ActiveValue::{NotSet, Set}, ColumnTrait, EntityTrait}; -use upub::{model::job::JobType, Context}; +use sea_orm::{sea_query::IntoCondition, ActiveValue::{NotSet, Set}, ColumnTrait, EntityTrait, QueryFilter, QuerySelect}; +use upub::{model::job::JobType, selector::{RichActivity, RichFillable}, Context}; use crate::{AuthIdentity, Identity, builders::JsonLD}; @@ -19,24 +19,23 @@ pub async fn page( AuthIdentity(auth): AuthIdentity, Query(page): Query, ) -> crate::ApiResult> { - crate::builders::paginate_feed( - upub::url!(ctx, "/inbox/page"), - upub::model::addressing::Column::Actor.is_null().into_condition(), - &ctx, - page, - auth.my_id(), - false, - ) - .await + let filter = upub::model::addressing::Column::Actor.is_null().into_condition(); + let (limit, offset) = page.pagination(); + let items = upub::Query::feed(auth.my_id(), page.replies.unwrap_or(true)) + .filter(filter) + .limit(limit) + .offset(offset) + .into_model::() + .all(ctx.db()) + .await? + .load_batched_models(ctx.db()) + .await? + .into_iter() + .map(|item| ctx.ap(item)) + .collect(); + crate::builders::collection_page(&upub::url!(ctx, "/inbox/page"), page, apb::Node::array(items)) } -macro_rules! pretty_json { - ($json:ident) => { - serde_json::to_string_pretty(&$json).expect("failed serializing to string serde_json::Value") - } -} - - pub async fn post( State(ctx): State, AuthIdentity(auth): AuthIdentity, @@ -52,7 +51,10 @@ pub async fn post( // would be cool if mastodon played nicer with the network... return Ok(StatusCode::OK); } - tracing::warn!("refusing unauthorized activity: {}", pretty_json!(activity)); + tracing::warn!( + "refusing unauthorized activity: {}", + serde_json::to_string_pretty(&activity).expect("failed serializing to string serde_json::Value?") + ); if matches!(auth, Identity::Anonymous) { return Err(crate::ApiError::unauthorized()); } else { diff --git a/upub/routes/src/activitypub/mod.rs b/upub/routes/src/activitypub/mod.rs index 53c03ba..e556620 100644 --- a/upub/routes/src/activitypub/mod.rs +++ b/upub/routes/src/activitypub/mod.rs @@ -88,7 +88,7 @@ pub struct TryFetch { pub fetch: bool, } -#[derive(Debug, serde::Deserialize)] +#[derive(Debug, Clone, Copy, serde::Deserialize)] // TODO i don't really like how pleroma/mastodon do it actually, maybe change this? pub struct Pagination { pub offset: Option, diff --git a/upub/routes/src/activitypub/object/context.rs b/upub/routes/src/activitypub/object/context.rs index c9a94c6..9c99462 100644 --- a/upub/routes/src/activitypub/object/context.rs +++ b/upub/routes/src/activitypub/object/context.rs @@ -1,6 +1,6 @@ use axum::extract::{Path, Query, State}; -use sea_orm::{ColumnTrait, PaginatorTrait, QueryFilter, QueryOrder, QuerySelect}; -use upub::{model, selector::{BatchFillable, RichObject}, Context}; +use sea_orm::{ColumnTrait, Condition, PaginatorTrait, QueryFilter, QuerySelect}; +use upub::{model, selector::{RichFillable, RichObject}, Context}; use crate::{activitypub::Pagination, builders::JsonLD, AuthIdentity}; @@ -11,7 +11,7 @@ pub async fn get( ) -> crate::ApiResult> { let context = ctx.oid(&id); - let count = upub::Query::objects(auth.my_id()) + let count = upub::Query::objects(auth.my_id(), true) .filter(auth.filter_objects()) .filter(model::object::Column::Context.eq(&context)) .count(ctx.db()) @@ -23,33 +23,30 @@ pub async fn get( pub async fn page( State(ctx): State, Path(id): Path, - Query(page): Query, + Query(mut page): Query, AuthIdentity(auth): AuthIdentity, ) -> crate::ApiResult> { let context = ctx.oid(&id); + + let filter = Condition::all() + .add(auth.filter_objects()) + .add(model::object::Column::Context.eq(context)); + + page.replies = Some(true); // TODO ugly that we have to force set it this way... let (limit, offset) = page.pagination(); - let items = upub::Query::objects(auth.my_id()) - .filter(auth.filter_objects()) - .filter(model::object::Column::Context.eq(context)) - // note that this should be ASC so we get replies somewhat ordered - .order_by_asc(model::object::Column::Published) + let items = upub::Query::feed(auth.my_id(), page.replies.unwrap_or(true)) + .filter(filter) .limit(limit) .offset(offset) .into_model::() .all(ctx.db()) .await? - .with_batched::(ctx.db()) + .load_batched_models(ctx.db()) .await? - .with_batched::(ctx.db()) - .await? - .with_batched::(ctx.db()) - .await?; - - let items : Vec = items .into_iter() .map(|item| ctx.ap(item)) .collect(); - crate::builders::collection_page(&upub::url!(ctx, "/objects/{id}/context/page"), offset, limit, apb::Node::array(items)) + crate::builders::collection_page(&upub::url!(ctx, "/objects/{id}/context/page"), page, apb::Node::array(items)) } diff --git a/upub/routes/src/activitypub/object/mod.rs b/upub/routes/src/activitypub/object/mod.rs index bcc79dc..92a403f 100644 --- a/upub/routes/src/activitypub/object/mod.rs +++ b/upub/routes/src/activitypub/object/mod.rs @@ -3,8 +3,8 @@ pub mod context; use apb::LD; use axum::extract::{Path, Query, State}; -use sea_orm::{ColumnTrait, QueryFilter, TransactionTrait}; -use upub::{model, selector::{BatchFillable, RichObject}, traits::Fetcher, Context}; +use sea_orm::{ColumnTrait, Condition, QueryFilter, TransactionTrait}; +use upub::{model, selector::{RichFillable, RichObject}, traits::Fetcher, Context}; use crate::{builders::JsonLD, AuthIdentity}; @@ -27,19 +27,18 @@ pub async fn view( } } - let item = upub::Query::objects(auth.my_id()) - .filter(auth.filter_objects()) - .filter(model::object::Column::Id.eq(&oid)) + let filter = Condition::all() + .add(auth.filter_objects()) + .add(model::object::Column::Id.eq(&oid)); + + let object = upub::Query::feed(auth.my_id(), true) + .filter(filter) .into_model::() .one(ctx.db()) .await? .ok_or_else(crate::ApiError::not_found)? - .with_batched::(ctx.db()) - .await? - .with_batched::(ctx.db()) - .await? - .with_batched::(ctx.db()) + .load_batched_models(ctx.db()) .await?; - Ok(JsonLD(ctx.ap(item).ld_context())) + Ok(JsonLD(ctx.ap(object).ld_context())) } diff --git a/upub/routes/src/activitypub/object/replies.rs b/upub/routes/src/activitypub/object/replies.rs index d1d1ca1..ef3a1dc 100644 --- a/upub/routes/src/activitypub/object/replies.rs +++ b/upub/routes/src/activitypub/object/replies.rs @@ -1,7 +1,7 @@ use apb::{BaseMut, CollectionMut, LD}; use axum::extract::{Path, Query, State}; -use sea_orm::{ColumnTrait, PaginatorTrait, QueryFilter, QueryOrder, QuerySelect}; -use upub::{model, selector::RichObject, traits::Fetcher, Context}; +use sea_orm::{ColumnTrait, Condition, PaginatorTrait, QueryFilter, QuerySelect}; +use upub::{model, selector::{RichFillable, RichObject}, traits::Fetcher, Context}; use crate::{activitypub::{Pagination, TryFetch}, builders::JsonLD, AuthIdentity}; @@ -21,7 +21,7 @@ pub async fn get( ctx.fetch_thread(&oid, ctx.db()).await?; } - let total_replies = upub::Query::objects(None) + let total_replies = upub::Query::objects(None, true) .filter(auth.filter_objects()) .filter(model::object::Column::InReplyTo.eq(&oid)) .count(ctx.db()) @@ -43,30 +43,29 @@ pub async fn page( Query(mut page): Query, AuthIdentity(auth): AuthIdentity, ) -> crate::ApiResult> { - let page_id = upub::url!(ctx, "/objects/{id}/replies/page"); let oid = ctx.oid(&id); - let (limit, offset) = page.pagination(); // TODO kinda weird ignoring this but its weirder to exclude replies from replies view... page.replies = Some(true); - let res = upub::Query::objects(auth.my_id()) + let filter = Condition::all() + .add(auth.filter_objects()) + .add(model::object::Column::InReplyTo.eq(oid)); + + let (limit, offset) = page.pagination(); + let items = upub::Query::feed(auth.my_id(), page.replies.unwrap_or(true)) + .filter(filter) + // TODO also limit to only local activities .limit(limit) .offset(offset) - .filter(auth.filter_objects()) - .filter(model::object::Column::InReplyTo.eq(oid)) - .order_by_desc(model::object::Column::Published) .into_model::() .all(ctx.db()) .await? + .load_batched_models(ctx.db()) + .await? .into_iter() - .map(|x| ctx.ap(x)) + .map(|item| ctx.ap(item)) .collect(); - crate::builders::collection_page( - &page_id, - offset, - limit, - apb::Node::array(res) - ) + crate::builders::collection_page(&upub::url!(ctx, "/objects/{id}/replies/page"), page, apb::Node::array(items)) } diff --git a/upub/routes/src/activitypub/outbox.rs b/upub/routes/src/activitypub/outbox.rs index cb7213f..1d1e9aa 100644 --- a/upub/routes/src/activitypub/outbox.rs +++ b/upub/routes/src/activitypub/outbox.rs @@ -1,6 +1,6 @@ use axum::{extract::{Query, State}, http::StatusCode, Json}; -use sea_orm::{ColumnTrait, Condition}; -use upub::Context; +use sea_orm::{ColumnTrait, Condition, QueryFilter, QuerySelect}; +use upub::{selector::{RichActivity, RichFillable}, Context}; use crate::{activitypub::{CreationResult, Pagination}, AuthIdentity, builders::JsonLD}; @@ -13,17 +13,25 @@ pub async fn page( Query(page): Query, AuthIdentity(auth): AuthIdentity, ) -> crate::ApiResult> { - crate::builders::paginate_feed( - upub::url!(ctx, "/outbox/page"), - Condition::all() - .add(upub::model::addressing::Column::Actor.is_null()) - .add(upub::model::actor::Column::Domain.eq(ctx.domain().to_string())), - &ctx, - page, - auth.my_id(), - true, - ) - .await + let filter = Condition::all() + .add(upub::model::addressing::Column::Actor.is_null()) + .add(upub::model::actor::Column::Domain.eq(ctx.domain().to_string())); + + let (limit, offset) = page.pagination(); + let items = upub::Query::feed(auth.my_id(), page.replies.unwrap_or(true)) + .filter(filter) + .limit(limit) + .offset(offset) + .into_model::() + .all(ctx.db()) + .await? + .load_batched_models(ctx.db()) + .await? + .into_iter() + .map(|item| ctx.ap(item)) + .collect(); + + crate::builders::collection_page(&upub::url!(ctx, "/outbox/page"), page, apb::Node::array(items)) } pub async fn post( diff --git a/upub/routes/src/activitypub/tags.rs b/upub/routes/src/activitypub/tags.rs index ff6082b..934402c 100644 --- a/upub/routes/src/activitypub/tags.rs +++ b/upub/routes/src/activitypub/tags.rs @@ -1,7 +1,7 @@ use axum::extract::{Path, Query, State}; use sea_orm::{QueryFilter, QuerySelect, ColumnTrait}; -use upub::{selector::{BatchFillable, RichActivity}, Context}; +use upub::{selector::{RichFillable, RichActivity}, Context}; use crate::{activitypub::Pagination, builders::JsonLD, AuthIdentity}; @@ -31,11 +31,7 @@ pub async fn page( .into_model::() .all(ctx.db()) .await? - .with_batched::(ctx.db()) - .await? - .with_batched::(ctx.db()) - .await? - .with_batched::(ctx.db()) + .load_batched_models(ctx.db()) .await? .into_iter() .map(|x| ctx.ap(x)) @@ -43,8 +39,7 @@ pub async fn page( crate::builders::collection_page( &upub::url!(ctx, "/tags/{id}/page"), - offset, - limit, + page, apb::Node::array(objects), ) diff --git a/upub/routes/src/builders.rs b/upub/routes/src/builders.rs index 6892b5c..fd57efe 100644 --- a/upub/routes/src/builders.rs +++ b/upub/routes/src/builders.rs @@ -1,61 +1,10 @@ use apb::{BaseMut, CollectionMut, CollectionPageMut, LD}; -use sea_orm::{Condition, QueryFilter, QuerySelect, RelationTrait, ColumnTrait}; use axum::response::{IntoResponse, Response}; -use upub::selector::{BatchFillable, RichActivity}; use crate::activitypub::Pagination; -#[deprecated = "use upub::Query directly"] -pub async fn paginate_feed( - id: String, - filter: Condition, - ctx: &upub::Context, - page: Pagination, - my_id: Option, - with_users: bool, // TODO ewww too many arguments for this weird function... -) -> crate::ApiResult> { +pub fn collection_page(id: &str, page: Pagination, items: apb::Node) -> crate::ApiResult> { let (limit, offset) = page.pagination(); - - let mut conditions = Condition::all() - .add(filter); - - // by default we want replies because servers don't know about our api and want everything - if !page.replies.unwrap_or(true) { - conditions = conditions.add(upub::model::object::Column::InReplyTo.is_null()); - } - - let mut select = upub::Query::feed(my_id); - - if with_users { - select = select - .join(sea_orm::JoinType::InnerJoin, upub::model::activity::Relation::Actors.def()); - } - - let db = ctx.db(); - let items = select - .filter(conditions) - // TODO also limit to only local activities - .limit(limit) - .offset(offset) - .into_model::() - .all(db) - .await? - .with_batched::(db) - .await? - .with_batched::(db) - .await? - .with_batched::(db) - .await?; - - let items : Vec = items - .into_iter() - .map(|item| ctx.ap(item)) - .collect(); - - collection_page(&id, offset, limit, apb::Node::array(items)) -} - -pub fn collection_page(id: &str, offset: u64, limit: u64, items: apb::Node) -> crate::ApiResult> { let next = if items.len() < limit as usize { apb::Node::Empty } else {