diff --git a/apb/src/server.rs b/apb/src/server.rs index 322e941..3089cf1 100644 --- a/apb/src/server.rs +++ b/apb/src/server.rs @@ -21,6 +21,7 @@ pub trait Inbox { async fn create(&self, activity: Self::Activity) -> Result<(), Self::Error>; async fn like(&self, activity: Self::Activity) -> Result<(), Self::Error>; async fn follow(&self, activity: Self::Activity) -> Result<(), Self::Error>; + async fn announce(&self, activity: Self::Activity) -> Result<(), Self::Error>; async fn accept(&self, activity: Self::Activity) -> Result<(), Self::Error>; async fn reject(&self, activity: Self::Activity) -> Result<(), Self::Error>; async fn undo(&self, activity: Self::Activity) -> Result<(), Self::Error>; diff --git a/src/routes/activitypub/inbox.rs b/src/routes/activitypub/inbox.rs index 038cf6c..3b2adde 100644 --- a/src/routes/activitypub/inbox.rs +++ b/src/routes/activitypub/inbox.rs @@ -78,7 +78,7 @@ pub async fn post( ActivityType::Create => Ok(ctx.create(activity).await?), ActivityType::Update => Ok(ctx.update(activity).await?), ActivityType::Undo => Ok(ctx.undo(activity).await?), - // ActivityType::Announce => Ok(ctx.announce(activity).await?), + ActivityType::Announce => Ok(ctx.announce(activity).await?), _x => { tracing::info!("received unimplemented activity on inbox: {}", pretty_json!(activity)); diff --git a/src/server/inbox.rs b/src/server/inbox.rs index 6eeb635..f293418 100644 --- a/src/server/inbox.rs +++ b/src/server/inbox.rs @@ -2,7 +2,7 @@ use apb::{target::Addressed, Activity, Base, Object}; use reqwest::StatusCode; use sea_orm::{sea_query::Expr, ColumnTrait, Condition, EntityTrait, IntoActiveModel, QueryFilter, Set}; -use crate::{errors::{LoggableError, UpubError}, model}; +use crate::{errors::{LoggableError, UpubError}, model::{self, object, FieldError}}; use super::{fetcher::Fetcher, Context}; @@ -50,7 +50,7 @@ impl apb::server::Inbox for Context { id: sea_orm::ActiveValue::NotSet, actor: sea_orm::Set(uid.clone()), likes: sea_orm::Set(oid.clone()), - date: sea_orm::Set(chrono::Utc::now()), + date: sea_orm::Set(activity.published().unwrap_or(chrono::Utc::now())), }; match model::like::Entity::insert(like).exec(self.db()).await { Err(sea_orm::DbErr::RecordNotInserted) => Err(UpubError::not_modified()), @@ -246,5 +246,36 @@ impl apb::server::Inbox for Context { model::activity::Entity::delete_by_id(undone_aid).exec(self.db()).await?; Ok(()) + + } + + async fn announce(&self, activity: serde_json::Value) -> crate::Result<()> { + let activity_model = model::activity::Model::new(&activity)?; + let Some(oid) = &activity_model.object else { + return Err(FieldError("object").into()); + }; + self.fetch_object(oid).await?; + let share = model::share::ActiveModel { + id: sea_orm::ActiveValue::NotSet, + actor: sea_orm::Set(activity_model.actor.clone()), + shares: sea_orm::Set(oid.clone()), + date: sea_orm::Set(activity.published().unwrap_or(chrono::Utc::now())), + }; + + let expanded_addressing = self.expand_addressing(activity.addressed()).await?; + self.address_to(&activity_model.id, None, &expanded_addressing).await?; + model::share::Entity::insert(share) + .exec(self.db()).await?; + model::activity::Entity::insert(activity_model.clone().into_active_model()) + .exec(self.db()) + .await?; + model::object::Entity::update_many() + .col_expr(model::object::Column::Shares, Expr::col(model::object::Column::Shares).add(1)) + .filter(model::object::Column::Id.eq(oid.clone())) + .exec(self.db()) + .await?; + + tracing::info!("{} shared {}", activity_model.actor, oid); + Ok(()) } }