Skip to content

Commit

Permalink
fix activitypub crate
Browse files Browse the repository at this point in the history
  • Loading branch information
aumetra committed Nov 25, 2023
1 parent 288980d commit b36e273
Show file tree
Hide file tree
Showing 7 changed files with 67 additions and 42 deletions.
42 changes: 31 additions & 11 deletions crates/kitsune-activitypub/src/deliverer/mod.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use crate::{
error::{Error, Result},
mapping::IntoActivity,
mapping::{self, IntoActivity},
InboxResolver,
};
use diesel::{
Expand All @@ -16,6 +16,7 @@ use kitsune_db::{
schema::{accounts, posts, users},
PgPool,
};
use kitsune_service::{attachment::AttachmentService, url::UrlService};
use kitsune_type::ap::{ap_context, helper::StringOrObject, Activity, ActivityType, ObjectField};
use kitsune_util::try_join;
use scoped_futures::ScopedFutureExt;
Expand All @@ -26,15 +27,34 @@ pub mod core;

const MAX_CONCURRENT_REQUESTS: usize = 10;

#[derive(TypedBuilder)]
pub struct Service {
attachment: AttachmentService,
url: UrlService,
}

#[derive(TypedBuilder)]
#[builder(build_method(into = Arc<Deliverer>))]
pub struct Deliverer {
core: core::Deliverer,
db_pool: PgPool,
inbox_resolver: InboxResolver,
service: Service,
}

impl Deliverer {
fn mapping_state(&self) -> mapping::State<'_> {
let service = mapping::Service::builder()
.attachment(&self.service.attachment)
.url(&self.service.url)
.build();

mapping::State::builder()
.db_pool(&self.db_pool)
.service(service)
.build()
}

async fn accept_follow(&self, follow: Follow) -> Result<()> {
let (follower_inbox_url, (followed_account, followed_user)): (String, _) = self
.db_pool
Expand All @@ -57,7 +77,7 @@ impl Deliverer {
})
.await?;

let followed_account_url = ctx.state.service.url.user_url(followed_account.id);
let followed_account_url = self.service.url.user_url(followed_account.id);

// Constructing this here is against our idea of the `IntoActivity` and `IntoObject` traits
// But I'm not sure how I could encode these into the form of these two traits
Expand Down Expand Up @@ -105,7 +125,7 @@ impl Deliverer {
.try_chunks(MAX_CONCURRENT_REQUESTS)
.map_err(|err| err.1);

let activity = post.into_activity(&ctx.state).await?;
let activity = post.into_activity(self.mapping_state()).await?;

// TODO: Should we deliver to the inboxes that are contained inside a `TryChunksError`?
self.core
Expand Down Expand Up @@ -143,7 +163,7 @@ impl Deliverer {
.try_chunks(MAX_CONCURRENT_REQUESTS)
.map_err(|err| err.1);

let delete_activity = post.into_negate_activity(&ctx.state).await?;
let delete_activity = post.into_negate_activity(self.mapping_state()).await?;

// TODO: Should we deliver to the inboxes that are contained inside a `TryChunksError`?
self.core
Expand Down Expand Up @@ -177,7 +197,7 @@ impl Deliverer {
.await?;

if let Some(ref inbox_url) = inbox_url {
let activity = favourite.into_activity(&ctx.state).await?;
let activity = favourite.into_activity(self.mapping_state()).await?;

self.core
.deliver(inbox_url, &account, &user, &activity)
Expand Down Expand Up @@ -210,7 +230,7 @@ impl Deliverer {
.await?;

if let Some(followed_inbox) = followed_inbox {
let follow_activity = follow.into_activity(&ctx.state).await?;
let follow_activity = follow.into_activity(self.mapping_state()).await?;

self.core
.deliver(&followed_inbox, &follower, &follower_user, &follow_activity)
Expand Down Expand Up @@ -244,7 +264,7 @@ impl Deliverer {
})
.await?;

let followed_account_url = ctx.state.service.url.user_url(followed_account.id);
let followed_account_url = self.service.url.user_url(followed_account.id);

// Constructing this here is against our idea of the `IntoActivity` and `IntoObject` traits
// But I'm not sure how I could encode these into the form of these two traits
Expand Down Expand Up @@ -296,7 +316,7 @@ impl Deliverer {
.await?;

if let Some(ref inbox_url) = inbox_url {
let activity = favourite.into_negate_activity(&ctx.state).await?;
let activity = favourite.into_negate_activity(self.mapping_state()).await?;
self.core
.deliver(inbox_url, &account, &user, &activity)
.await?;
Expand Down Expand Up @@ -328,7 +348,7 @@ impl Deliverer {
.await?;

if let Some(ref followed_account_inbox_url) = followed_account_inbox_url {
let follow_activity = follow.into_negate_activity(&ctx.state).await?;
let follow_activity = follow.into_negate_activity(self.mapping_state()).await?;

self.core
.deliver(
Expand Down Expand Up @@ -363,7 +383,7 @@ impl Deliverer {
return Ok(());
};

let activity = account.clone().into_activity(&ctx.state).await?;
let activity = account.clone().into_activity(self.mapping_state()).await?;
let inbox_stream = self
.inbox_resolver
.resolve_followers(&account)
Expand Down Expand Up @@ -407,7 +427,7 @@ impl Deliverer {
.try_chunks(MAX_CONCURRENT_REQUESTS)
.map_err(|err| err.1);

let mut activity = post.into_activity(&ctx.state).await?;
let mut activity = post.into_activity(self.mapping_state()).await?;

// Patch in the update
activity.r#type = ActivityType::Update;
Expand Down
6 changes: 6 additions & 0 deletions crates/kitsune-activitypub/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,9 @@ pub enum Error {
#[error("Missing host")]
MissingHost,

#[error("Not found")]
NotFound,

#[error(transparent)]
Resolver(BoxError),

Expand All @@ -63,6 +66,9 @@ pub enum Error {
#[error(transparent)]
SimdJson(#[from] simd_json::Error),

#[error("Unsupported media type")]
UnsupportedMediaType,

#[error(transparent)]
UrlParse(#[from] url::ParseError),
}
Expand Down
2 changes: 1 addition & 1 deletion crates/kitsune-activitypub/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#![forbid(rust_2018_idioms)]
#![warn(clippy::all, clippy::pedantic)]
#![allow(clippy::missing_errors_doc)]
#![allow(clippy::missing_errors_doc, clippy::module_name_repetitions)]

#[macro_use]
extern crate tracing;
Expand Down
20 changes: 10 additions & 10 deletions crates/kitsune-activitypub/src/mapping/activity.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,18 +16,18 @@ pub trait IntoActivity {
type Output;
type NegateOutput;

fn into_activity(self, state: &State) -> impl Future<Output = Result<Self::Output>> + Send;
fn into_activity(self, state: State<'_>) -> impl Future<Output = Result<Self::Output>> + Send;
fn into_negate_activity(
self,
state: &State,
state: State<'_>,
) -> impl Future<Output = Result<Self::NegateOutput>> + Send;
}

impl IntoActivity for Account {
type Output = Activity;
type NegateOutput = Activity;

async fn into_activity(self, state: &State) -> Result<Self::Output> {
async fn into_activity(self, state: State<'_>) -> Result<Self::Output> {
let account_url = state.service.url.user_url(self.id);

Ok(Activity {
Expand All @@ -40,7 +40,7 @@ impl IntoActivity for Account {
})
}

async fn into_negate_activity(self, _state: &State) -> Result<Self::NegateOutput> {
async fn into_negate_activity(self, _state: State<'_>) -> Result<Self::NegateOutput> {
todo!();
}
}
Expand All @@ -49,7 +49,7 @@ impl IntoActivity for Favourite {
type Output = Activity;
type NegateOutput = Activity;

async fn into_activity(self, state: &State) -> Result<Self::Output> {
async fn into_activity(self, state: State<'_>) -> Result<Self::Output> {
let (account_url, post_url) = state
.db_pool
.with_connection(|db_conn| {
Expand Down Expand Up @@ -80,7 +80,7 @@ impl IntoActivity for Favourite {
})
}

async fn into_negate_activity(self, state: &State) -> Result<Self::NegateOutput> {
async fn into_negate_activity(self, state: State<'_>) -> Result<Self::NegateOutput> {
let account_url = state
.db_pool
.with_connection(|db_conn| {
Expand All @@ -107,7 +107,7 @@ impl IntoActivity for Follow {
type Output = Activity;
type NegateOutput = Activity;

async fn into_activity(self, state: &State) -> Result<Self::Output> {
async fn into_activity(self, state: State<'_>) -> Result<Self::Output> {
let (attributed_to, object) = state
.db_pool
.with_connection(|db_conn| {
Expand Down Expand Up @@ -138,7 +138,7 @@ impl IntoActivity for Follow {
})
}

async fn into_negate_activity(self, state: &State) -> Result<Self::NegateOutput> {
async fn into_negate_activity(self, state: State<'_>) -> Result<Self::NegateOutput> {
let attributed_to = state
.db_pool
.with_connection(|db_conn| {
Expand All @@ -165,7 +165,7 @@ impl IntoActivity for Post {
type Output = Activity;
type NegateOutput = Activity;

async fn into_activity(self, state: &State) -> Result<Self::Output> {
async fn into_activity(self, state: State<'_>) -> Result<Self::Output> {
let account_url = state.service.url.user_url(self.account_id);

if let Some(reposted_post_id) = self.reposted_post_id {
Expand Down Expand Up @@ -203,7 +203,7 @@ impl IntoActivity for Post {
}
}

async fn into_negate_activity(self, state: &State) -> Result<Self::NegateOutput> {
async fn into_negate_activity(self, state: State<'_>) -> Result<Self::NegateOutput> {
let account_url = state.service.url.user_url(self.account_id);

let activity = if self.reposted_post_id.is_some() {
Expand Down
16 changes: 8 additions & 8 deletions crates/kitsune-activitypub/src/mapping/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,14 @@ mod util;
pub use self::activity::IntoActivity;
pub use self::object::IntoObject;

#[derive(TypedBuilder)]
pub struct Service {
attachment: AttachmentService,
url: UrlService,
#[derive(Clone, Copy, TypedBuilder)]
pub struct Service<'a> {
attachment: &'a AttachmentService,
url: &'a UrlService,
}

#[derive(TypedBuilder)]
pub struct State {
db_pool: PgPool,
service: Service,
#[derive(Clone, Copy, TypedBuilder)]
pub struct State<'a> {
db_pool: &'a PgPool,
service: Service<'a>,
}
19 changes: 9 additions & 10 deletions crates/kitsune-activitypub/src/mapping/object.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,20 +28,19 @@ use std::{future::Future, str::FromStr};
pub trait IntoObject {
type Output;

fn into_object(self, state: &State) -> impl Future<Output = Result<Self::Output>> + Send;
fn into_object(self, state: State<'_>) -> impl Future<Output = Result<Self::Output>> + Send;
}

impl IntoObject for DbMediaAttachment {
type Output = MediaAttachment;

async fn into_object(self, state: &State) -> Result<Self::Output> {
let mime =
Mime::from_str(&self.content_type).map_err(|_| ApiError::UnsupportedMediaType)?;
async fn into_object(self, state: State<'_>) -> Result<Self::Output> {
let mime = Mime::from_str(&self.content_type).map_err(|_| Error::UnsupportedMediaType)?;
let r#type = match mime.type_() {
mime::AUDIO => MediaAttachmentType::Audio,
mime::IMAGE => MediaAttachmentType::Image,
mime::VIDEO => MediaAttachmentType::Video,
_ => return Err(ApiError::UnsupportedMediaType.into()),
_ => return Err(Error::UnsupportedMediaType),
};
let url = state.service.attachment.get_url(self.id).await?;

Expand Down Expand Up @@ -94,12 +93,12 @@ fn build_post_tags(
impl IntoObject for Post {
type Output = Object;

async fn into_object(self, state: &State) -> Result<Self::Output> {
async fn into_object(self, state: State<'_>) -> Result<Self::Output> {
// Right now a repost can't have content
// Therefore it's also not an object
// We just return en error here
if self.reposted_post_id.is_some() {
return Err(ApiError::NotFound.into());
return Err(Error::NotFound);
}

let (account, in_reply_to, mentions, emojis, attachment_stream) = state
Expand Down Expand Up @@ -197,7 +196,7 @@ impl IntoObject for Post {
impl IntoObject for Account {
type Output = Actor;

async fn into_object(self, state: &State) -> Result<Self::Output> {
async fn into_object(self, state: State<'_>) -> Result<Self::Output> {
let (icon, image) = state
.db_pool
.with_connection(|db_conn| {
Expand Down Expand Up @@ -262,12 +261,12 @@ impl IntoObject for Account {
impl IntoObject for CustomEmoji {
type Output = Emoji;

async fn into_object(self, state: &State) -> Result<Self::Output> {
async fn into_object(self, state: State<'_>) -> Result<Self::Output> {
// Officially we don't have any info about remote emojis as we're not the origin
// Let's pretend we're not home and do not answer
let name = match self.domain {
None => Ok(format!(":{}:", self.shortcode)),
Some(_) => Err(ApiError::NotFound),
Some(_) => Err(Error::NotFound),
}?;

let icon = state
Expand Down
4 changes: 2 additions & 2 deletions crates/kitsune-activitypub/src/mapping/util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@ use kitsune_db::model::{account::Account, post::Visibility};
use kitsune_type::ap::PUBLIC_IDENTIFIER;

pub trait BaseToCc {
fn base_to_cc(&self, state: &State, account: &Account) -> (Vec<String>, Vec<String>);
fn base_to_cc(&self, state: State<'_>, account: &Account) -> (Vec<String>, Vec<String>);
}

impl BaseToCc for Visibility {
#[inline]
fn base_to_cc(&self, state: &State, account: &Account) -> (Vec<String>, Vec<String>) {
fn base_to_cc(&self, state: State<'_>, account: &Account) -> (Vec<String>, Vec<String>) {
let followers_url = state.service.url.followers_url(account.id);

match self {
Expand Down

0 comments on commit b36e273

Please sign in to comment.