fix(routes): proper replies collection
also don't include replies in first object fetch: needless work since most of the AP world doesn't use them. if you do, explicitly dereference /replies!
This commit is contained in:
parent
cc090ccb19
commit
9f8b6b8280
2 changed files with 61 additions and 53 deletions
|
@ -1,9 +1,9 @@
|
|||
pub mod replies;
|
||||
pub mod context;
|
||||
|
||||
use apb::{BaseMut, CollectionMut, ObjectMut, LD};
|
||||
use apb::{BaseMut, Object, ObjectMut, LD};
|
||||
use axum::extract::{Path, Query, State};
|
||||
use sea_orm::{ColumnTrait, QueryFilter, QuerySelect, SelectColumns, TransactionTrait};
|
||||
use sea_orm::{ColumnTrait, QueryFilter, TransactionTrait};
|
||||
use upub::{model, selector::{BatchFillable, RichActivity}, traits::Fetcher, Context};
|
||||
|
||||
use crate::{builders::JsonLD, AuthIdentity};
|
||||
|
@ -27,7 +27,9 @@ pub async fn view(
|
|||
}
|
||||
}
|
||||
|
||||
let item = upub::Query::objects(auth.my_id())
|
||||
let replies_url = upub::url!(ctx, "/objects/{id}/replies");
|
||||
|
||||
let item_model = upub::Query::objects(auth.my_id())
|
||||
.filter(auth.filter_objects())
|
||||
.filter(model::object::Column::Id.eq(&oid))
|
||||
.into_model::<RichActivity>()
|
||||
|
@ -41,31 +43,17 @@ pub async fn view(
|
|||
.with_batched::<upub::model::hashtag::Entity>(ctx.db())
|
||||
.await?;
|
||||
|
||||
let mut replies = apb::Node::Empty;
|
||||
let mut item = ctx.ap(item_model);
|
||||
|
||||
if ctx.cfg().security.show_reply_ids {
|
||||
let replies_ids = upub::Query::objects(auth.my_id())
|
||||
.filter(auth.filter_objects())
|
||||
.filter(model::object::Column::InReplyTo.eq(oid))
|
||||
.select_only()
|
||||
.select_column(model::object::Column::Id)
|
||||
.into_tuple::<String>()
|
||||
.all(ctx.db())
|
||||
.await?;
|
||||
let replies_patched =
|
||||
apb::Node::object(
|
||||
item.replies()
|
||||
.into_inner()
|
||||
.unwrap()
|
||||
.set_id(Some(replies_url))
|
||||
);
|
||||
|
||||
replies = apb::Node::object(
|
||||
apb::new()
|
||||
.set_id(Some(upub::url!(ctx, "/objects/{id}/replies")))
|
||||
.set_first(apb::Node::link(upub::url!(ctx, "/objects/{id}/replies/page")))
|
||||
.set_collection_type(Some(apb::CollectionType::Collection))
|
||||
.set_total_items(item.object.as_ref().map(|x| x.replies as u64))
|
||||
.set_items(apb::Node::links(replies_ids))
|
||||
);
|
||||
}
|
||||
item = item.set_replies(replies_patched);
|
||||
|
||||
Ok(JsonLD(
|
||||
item.object_ap()
|
||||
.set_replies(replies)
|
||||
.ld_context()
|
||||
))
|
||||
Ok(JsonLD(item.ld_context()))
|
||||
}
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
use apb::{BaseMut, CollectionMut, LD};
|
||||
use apb::{BaseMut, CollectionMut, CollectionPageMut, LD};
|
||||
use axum::extract::{Path, Query, State};
|
||||
use sea_orm::{ColumnTrait, Condition, QueryFilter, QuerySelect, SelectColumns};
|
||||
use sea_orm::{ColumnTrait, ConnectionTrait, PaginatorTrait, QueryFilter, QuerySelect, SelectColumns};
|
||||
use upub::{model, traits::Fetcher, Context};
|
||||
|
||||
use crate::{activitypub::{Pagination, TryFetch}, builders::JsonLD, AuthIdentity};
|
||||
use crate::{activitypub::{Pagination, TryFetch}, builders::JsonLD, ApiResult, AuthIdentity, Identity};
|
||||
|
||||
pub async fn get(
|
||||
State(ctx): State<Context>,
|
||||
|
@ -21,22 +21,21 @@ pub async fn get(
|
|||
ctx.fetch_thread(&oid, ctx.db()).await?;
|
||||
}
|
||||
|
||||
let replies_ids = upub::Query::objects(auth.my_id())
|
||||
.filter(auth.filter_objects())
|
||||
.filter(model::object::Column::InReplyTo.eq(ctx.oid(&id)))
|
||||
.select_only()
|
||||
.select_column(model::object::Column::Id)
|
||||
.into_tuple::<String>()
|
||||
.all(ctx.db())
|
||||
.await?;
|
||||
let replies_count = total_replies(&oid, &auth, ctx.db()).await?;
|
||||
let replies_ids = replies_ids(&oid, &auth, ctx.db(), 20, 0).await?;
|
||||
|
||||
let first = apb::new()
|
||||
.set_id(Some(upub::url!(ctx, "/objects/{id}/replies/page")))
|
||||
.set_collection_type(Some(apb::CollectionType::OrderedCollectionPage))
|
||||
.set_next(apb::Node::link(upub::url!(ctx, "/objects/{id}/replies/page?offset=20")))
|
||||
.set_ordered_items(apb::Node::links(replies_ids));
|
||||
|
||||
Ok(JsonLD(
|
||||
apb::new()
|
||||
.set_id(Some(upub::url!(ctx, "/objects/{id}/replies")))
|
||||
.set_collection_type(Some(apb::CollectionType::Collection))
|
||||
.set_first(apb::Node::link(upub::url!(ctx, "/objects/{id}/replies/page")))
|
||||
.set_total_items(Some(replies_ids.len() as u64))
|
||||
.set_items(apb::Node::links(replies_ids))
|
||||
.set_total_items(Some(replies_count))
|
||||
.set_first(apb::Node::object(first))
|
||||
.ld_context()
|
||||
))
|
||||
}
|
||||
|
@ -49,19 +48,40 @@ pub async fn page(
|
|||
) -> crate::ApiResult<JsonLD<serde_json::Value>> {
|
||||
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);
|
||||
|
||||
crate::builders::paginate_feed(
|
||||
page_id,
|
||||
Condition::all()
|
||||
.add(auth.filter_activities())
|
||||
.add(model::object::Column::InReplyTo.eq(oid)),
|
||||
ctx.db(),
|
||||
page,
|
||||
auth.my_id(),
|
||||
false,
|
||||
let replies_ids = replies_ids(&oid, &auth, ctx.db(), limit, offset).await?;
|
||||
|
||||
crate::builders::collection_page(
|
||||
&page_id,
|
||||
offset,
|
||||
limit,
|
||||
apb::Node::links(replies_ids)
|
||||
)
|
||||
.await
|
||||
}
|
||||
|
||||
async fn replies_ids(oid: &str, auth: &Identity, db: &impl ConnectionTrait, limit: u64, offset: u64) -> ApiResult<Vec<String>> {
|
||||
let res = upub::Query::objects(auth.my_id())
|
||||
.limit(limit)
|
||||
.offset(offset)
|
||||
.filter(auth.filter_objects())
|
||||
.filter(model::object::Column::InReplyTo.eq(oid))
|
||||
.select_only()
|
||||
.select_column(model::object::Column::Id)
|
||||
.into_tuple::<String>()
|
||||
.all(db)
|
||||
.await?;
|
||||
Ok(res)
|
||||
}
|
||||
|
||||
async fn total_replies(oid: &str, auth: &Identity, db: &impl ConnectionTrait) -> ApiResult<u64> {
|
||||
let count = upub::Query::objects(None)
|
||||
.filter(auth.filter_objects())
|
||||
.filter(model::object::Column::InReplyTo.eq(oid))
|
||||
.count(db)
|
||||
.await?;
|
||||
Ok(count)
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue