From 815fdcd883d0158e884f25e36f0868c7cb3b30d9 Mon Sep 17 00:00:00 2001 From: alemi Date: Thu, 9 Jan 2025 20:13:25 +0100 Subject: [PATCH] feat: add fetch_outbox on folreq and outbox?fetch --- upub/core/src/traits/fetch.rs | 18 ++++++++++++++++++ upub/core/src/traits/process.rs | 1 + upub/routes/src/activitypub/actor/outbox.rs | 11 +++++++++-- 3 files changed, 28 insertions(+), 2 deletions(-) diff --git a/upub/core/src/traits/fetch.rs b/upub/core/src/traits/fetch.rs index 4def445..f03cfa9 100644 --- a/upub/core/src/traits/fetch.rs +++ b/upub/core/src/traits/fetch.rs @@ -101,6 +101,7 @@ pub trait Fetcher { async fn resolve_object(&self, object: serde_json::Value, tx: &impl ConnectionTrait) -> Result; async fn fetch_thread(&self, id: &str, tx: &impl ConnectionTrait) -> Result<(), RequestError>; + async fn fetch_outbox(&self, id: &str, tx: &impl ConnectionTrait) -> Result<(), RequestError>; fn client(domain: &str) -> reqwest::Client { reqwest::Client::builder() @@ -447,6 +448,8 @@ impl Fetcher for crate::Context { page = page.first().into_inner()?; } + // TODO parallelize these + for obj in page.items().flat() { if let Err(e) = self.fetch_object(&obj.id()?, tx).await { tracing::warn!("error fetching reply: {e}"); @@ -466,6 +469,21 @@ impl Fetcher for crate::Context { Ok(()) } + async fn fetch_outbox(&self, id: &str, tx: &impl ConnectionTrait) -> Result<(), RequestError> { + let actor = self.pull(id).await?.actor()?; + let outbox = actor + .outbox().resolve(self).await? + .first().resolve(self).await?; + + // TODO parallelize these + + for item in outbox.ordered_items().all_ids() { + self.fetch_object(&item, tx).await?; + } + + Ok(()) + } + async fn fetch_object(&self, id: &str, tx: &impl ConnectionTrait) -> Result { fetch_object_r(self, id, 0, tx).await } diff --git a/upub/core/src/traits/process.rs b/upub/core/src/traits/process.rs index 29e0464..d664bff 100644 --- a/upub/core/src/traits/process.rs +++ b/upub/core/src/traits/process.rs @@ -203,6 +203,7 @@ pub async fn follow(ctx: &crate::Context, activity: impl apb::Activity, tx: &Dat ctx.address(Some(&activity_model), None, tx).await?; if ctx.is_local(&target_actor.id) { + ctx.fetch_outbox(&target_actor.id, tx).await?; crate::Query::notify(activity_model.internal, target_actor.internal) .exec(tx) .await?; diff --git a/upub/routes/src/activitypub/actor/outbox.rs b/upub/routes/src/activitypub/actor/outbox.rs index d5a8d8d..97b6fb8 100644 --- a/upub/routes/src/activitypub/actor/outbox.rs +++ b/upub/routes/src/activitypub/actor/outbox.rs @@ -1,14 +1,21 @@ use axum::{extract::{Path, Query, State}, http::StatusCode, Json}; use sea_orm::{ActiveValue::{NotSet, Set}, ColumnTrait, Condition, EntityTrait, QueryFilter, QueryOrder, QuerySelect}; -use upub::{model, selector::{RichActivity, RichFillable}, Context}; +use upub::{model, selector::{RichActivity, RichFillable}, traits::Fetcher, Context}; -use crate::{activitypub::{CreationResult, Pagination}, builders::JsonLD, AuthIdentity, Identity}; +use crate::{activitypub::{CreationResult, Pagination, TryFetch}, builders::JsonLD, AuthIdentity, Identity}; pub async fn get( State(ctx): State, + AuthIdentity(auth): AuthIdentity, Path(id): Path, + Query(query): Query, ) -> crate::ApiResult> { + let uid = ctx.uid(&id); + if auth.is_local() && query.fetch && !ctx.is_local(&uid) { + ctx.fetch_outbox(&uid, ctx.db()).await?; + } + crate::builders::collection(upub::url!(ctx, "/actors/{id}/outbox"), None) }