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 replies;
|
||||||
pub mod context;
|
pub mod context;
|
||||||
|
|
||||||
use apb::{BaseMut, CollectionMut, ObjectMut, LD};
|
use apb::{BaseMut, Object, ObjectMut, LD};
|
||||||
use axum::extract::{Path, Query, State};
|
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 upub::{model, selector::{BatchFillable, RichActivity}, traits::Fetcher, Context};
|
||||||
|
|
||||||
use crate::{builders::JsonLD, AuthIdentity};
|
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(auth.filter_objects())
|
||||||
.filter(model::object::Column::Id.eq(&oid))
|
.filter(model::object::Column::Id.eq(&oid))
|
||||||
.into_model::<RichActivity>()
|
.into_model::<RichActivity>()
|
||||||
|
@ -41,31 +43,17 @@ pub async fn view(
|
||||||
.with_batched::<upub::model::hashtag::Entity>(ctx.db())
|
.with_batched::<upub::model::hashtag::Entity>(ctx.db())
|
||||||
.await?;
|
.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?;
|
|
||||||
|
|
||||||
replies = apb::Node::object(
|
let replies_patched =
|
||||||
apb::new()
|
apb::Node::object(
|
||||||
.set_id(Some(upub::url!(ctx, "/objects/{id}/replies")))
|
item.replies()
|
||||||
.set_first(apb::Node::link(upub::url!(ctx, "/objects/{id}/replies/page")))
|
.into_inner()
|
||||||
.set_collection_type(Some(apb::CollectionType::Collection))
|
.unwrap()
|
||||||
.set_total_items(item.object.as_ref().map(|x| x.replies as u64))
|
.set_id(Some(replies_url))
|
||||||
.set_items(apb::Node::links(replies_ids))
|
);
|
||||||
);
|
|
||||||
}
|
item = item.set_replies(replies_patched);
|
||||||
|
|
||||||
Ok(JsonLD(
|
Ok(JsonLD(item.ld_context()))
|
||||||
item.object_ap()
|
|
||||||
.set_replies(replies)
|
|
||||||
.ld_context()
|
|
||||||
))
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
use apb::{BaseMut, CollectionMut, LD};
|
use apb::{BaseMut, CollectionMut, CollectionPageMut, LD};
|
||||||
use axum::extract::{Path, Query, State};
|
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 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(
|
pub async fn get(
|
||||||
State(ctx): State<Context>,
|
State(ctx): State<Context>,
|
||||||
|
@ -21,22 +21,21 @@ pub async fn get(
|
||||||
ctx.fetch_thread(&oid, ctx.db()).await?;
|
ctx.fetch_thread(&oid, ctx.db()).await?;
|
||||||
}
|
}
|
||||||
|
|
||||||
let replies_ids = upub::Query::objects(auth.my_id())
|
let replies_count = total_replies(&oid, &auth, ctx.db()).await?;
|
||||||
.filter(auth.filter_objects())
|
let replies_ids = replies_ids(&oid, &auth, ctx.db(), 20, 0).await?;
|
||||||
.filter(model::object::Column::InReplyTo.eq(ctx.oid(&id)))
|
|
||||||
.select_only()
|
let first = apb::new()
|
||||||
.select_column(model::object::Column::Id)
|
.set_id(Some(upub::url!(ctx, "/objects/{id}/replies/page")))
|
||||||
.into_tuple::<String>()
|
.set_collection_type(Some(apb::CollectionType::OrderedCollectionPage))
|
||||||
.all(ctx.db())
|
.set_next(apb::Node::link(upub::url!(ctx, "/objects/{id}/replies/page?offset=20")))
|
||||||
.await?;
|
.set_ordered_items(apb::Node::links(replies_ids));
|
||||||
|
|
||||||
Ok(JsonLD(
|
Ok(JsonLD(
|
||||||
apb::new()
|
apb::new()
|
||||||
.set_id(Some(upub::url!(ctx, "/objects/{id}/replies")))
|
.set_id(Some(upub::url!(ctx, "/objects/{id}/replies")))
|
||||||
.set_collection_type(Some(apb::CollectionType::Collection))
|
.set_collection_type(Some(apb::CollectionType::Collection))
|
||||||
.set_first(apb::Node::link(upub::url!(ctx, "/objects/{id}/replies/page")))
|
.set_total_items(Some(replies_count))
|
||||||
.set_total_items(Some(replies_ids.len() as u64))
|
.set_first(apb::Node::object(first))
|
||||||
.set_items(apb::Node::links(replies_ids))
|
|
||||||
.ld_context()
|
.ld_context()
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
@ -49,19 +48,40 @@ pub async fn page(
|
||||||
) -> crate::ApiResult<JsonLD<serde_json::Value>> {
|
) -> crate::ApiResult<JsonLD<serde_json::Value>> {
|
||||||
let page_id = upub::url!(ctx, "/objects/{id}/replies/page");
|
let page_id = upub::url!(ctx, "/objects/{id}/replies/page");
|
||||||
let oid = ctx.oid(&id);
|
let oid = ctx.oid(&id);
|
||||||
|
let (limit, offset) = page.pagination();
|
||||||
|
|
||||||
// TODO kinda weird ignoring this but its weirder to exclude replies from replies view...
|
// TODO kinda weird ignoring this but its weirder to exclude replies from replies view...
|
||||||
page.replies = Some(true);
|
page.replies = Some(true);
|
||||||
|
|
||||||
crate::builders::paginate_feed(
|
let replies_ids = replies_ids(&oid, &auth, ctx.db(), limit, offset).await?;
|
||||||
page_id,
|
|
||||||
Condition::all()
|
crate::builders::collection_page(
|
||||||
.add(auth.filter_activities())
|
&page_id,
|
||||||
.add(model::object::Column::InReplyTo.eq(oid)),
|
offset,
|
||||||
ctx.db(),
|
limit,
|
||||||
page,
|
apb::Node::links(replies_ids)
|
||||||
auth.my_id(),
|
|
||||||
false,
|
|
||||||
)
|
)
|
||||||
.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