mirror of
https://github.com/LemmyNet/activitypub-federation-rust.git
synced 2024-05-20 18:08:04 +00:00
Option to include published
timestamp for sent activities
This commit is contained in:
parent
1b46dd6f80
commit
05ab30a1b9
|
@ -15,7 +15,7 @@ axum = ["dep:axum", "dep:tower", "dep:hyper", "dep:http-body-util"]
|
||||||
diesel = ["dep:diesel"]
|
diesel = ["dep:diesel"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
chrono = { version = "0.4.34", features = ["clock"], default-features = false }
|
chrono = { version = "0.4.34", features = ["clock", "serde"], default-features = false }
|
||||||
serde = { version = "1.0.197", features = ["derive"] }
|
serde = { version = "1.0.197", features = ["derive"] }
|
||||||
async-trait = "0.1.77"
|
async-trait = "0.1.77"
|
||||||
url = { version = "2.5.0", features = ["serde"] }
|
url = { version = "2.5.0", features = ["serde"] }
|
||||||
|
|
|
@ -119,7 +119,7 @@ impl DbUser {
|
||||||
if use_queue {
|
if use_queue {
|
||||||
queue_activity(&activity, self, recipients, data).await?;
|
queue_activity(&activity, self, recipients, data).await?;
|
||||||
} else {
|
} else {
|
||||||
let sends = SendActivityTask::prepare(&activity, self, recipients, data).await?;
|
let sends = SendActivityTask::prepare(&activity, self, recipients, None, data).await?;
|
||||||
for send in sends {
|
for send in sends {
|
||||||
send.sign_and_send(data).await?;
|
send.sign_and_send(data).await?;
|
||||||
}
|
}
|
||||||
|
|
|
@ -49,7 +49,7 @@ where
|
||||||
ActorType: Actor,
|
ActorType: Actor,
|
||||||
{
|
{
|
||||||
let config = &data.config;
|
let config = &data.config;
|
||||||
let tasks = build_tasks(activity, actor, inboxes, data).await?;
|
let tasks = build_tasks(activity, actor, inboxes, None, data).await?;
|
||||||
|
|
||||||
for task in tasks {
|
for task in tasks {
|
||||||
// Don't use the activity queue if this is in debug mode, send and wait directly
|
// Don't use the activity queue if this is in debug mode, send and wait directly
|
||||||
|
|
|
@ -19,10 +19,10 @@ use reqwest::header::{HeaderMap, HeaderName, HeaderValue};
|
||||||
use reqwest_middleware::ClientWithMiddleware;
|
use reqwest_middleware::ClientWithMiddleware;
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
use std::{
|
use std::{
|
||||||
self,
|
|
||||||
fmt::{Debug, Display},
|
fmt::{Debug, Display},
|
||||||
time::{Duration, SystemTime},
|
time::{Duration, SystemTime},
|
||||||
};
|
};
|
||||||
|
use chrono::{DateTime, Utc};
|
||||||
use tracing::debug;
|
use tracing::debug;
|
||||||
use url::Url;
|
use url::Url;
|
||||||
|
|
||||||
|
@ -51,10 +51,13 @@ impl SendActivityTask {
|
||||||
/// - `inboxes`: List of remote actor inboxes that should receive the activity. Ignores local actor
|
/// - `inboxes`: List of remote actor inboxes that should receive the activity. Ignores local actor
|
||||||
/// inboxes. Should be built by calling [crate::traits::Actor::shared_inbox_or_inbox]
|
/// inboxes. Should be built by calling [crate::traits::Actor::shared_inbox_or_inbox]
|
||||||
/// for each target actor.
|
/// for each target actor.
|
||||||
|
/// - `published`: Time when the activity was created, so that recipient can apply activities
|
||||||
|
/// in correct order.
|
||||||
pub async fn prepare<Activity, Datatype, ActorType>(
|
pub async fn prepare<Activity, Datatype, ActorType>(
|
||||||
activity: &Activity,
|
activity: &Activity,
|
||||||
actor: &ActorType,
|
actor: &ActorType,
|
||||||
inboxes: Vec<Url>,
|
inboxes: Vec<Url>,
|
||||||
|
published: Option<DateTime<Utc>>,
|
||||||
data: &Data<Datatype>,
|
data: &Data<Datatype>,
|
||||||
) -> Result<Vec<SendActivityTask>, Error>
|
) -> Result<Vec<SendActivityTask>, Error>
|
||||||
where
|
where
|
||||||
|
@ -62,7 +65,7 @@ impl SendActivityTask {
|
||||||
Datatype: Clone,
|
Datatype: Clone,
|
||||||
ActorType: Actor,
|
ActorType: Actor,
|
||||||
{
|
{
|
||||||
build_tasks(activity, actor, inboxes, data).await
|
build_tasks(activity, actor, inboxes, published, data).await
|
||||||
}
|
}
|
||||||
|
|
||||||
/// convert a sendactivitydata to a request, signing and sending it
|
/// convert a sendactivitydata to a request, signing and sending it
|
||||||
|
@ -117,6 +120,7 @@ pub(crate) async fn build_tasks<'a, Activity, Datatype, ActorType>(
|
||||||
activity: &'a Activity,
|
activity: &'a Activity,
|
||||||
actor: &ActorType,
|
actor: &ActorType,
|
||||||
inboxes: Vec<Url>,
|
inboxes: Vec<Url>,
|
||||||
|
published: Option<DateTime<Utc>>,
|
||||||
data: &Data<Datatype>,
|
data: &Data<Datatype>,
|
||||||
) -> Result<Vec<SendActivityTask>, Error>
|
) -> Result<Vec<SendActivityTask>, Error>
|
||||||
where
|
where
|
||||||
|
@ -127,7 +131,10 @@ where
|
||||||
let config = &data.config;
|
let config = &data.config;
|
||||||
let actor_id = activity.actor();
|
let actor_id = activity.actor();
|
||||||
let activity_id = activity.id();
|
let activity_id = activity.id();
|
||||||
let activity_serialized: Bytes = serde_json::to_vec(activity)
|
let activity_serialized: Bytes = match published {
|
||||||
|
Some(published) => serde_json::to_vec(&WithPublished::new(activity, published)),
|
||||||
|
None => serde_json::to_vec(activity)
|
||||||
|
}
|
||||||
.map_err(|e| Error::SerializeOutgoingActivity(e, format!("{:?}", activity)))?
|
.map_err(|e| Error::SerializeOutgoingActivity(e, format!("{:?}", activity)))?
|
||||||
.into();
|
.into();
|
||||||
let private_key = get_pkey_cached(data, actor).await?;
|
let private_key = get_pkey_cached(data, actor).await?;
|
||||||
|
@ -210,6 +217,24 @@ pub(crate) fn generate_request_headers(inbox_url: &Url) -> HeaderMap {
|
||||||
headers
|
headers
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Wrapper struct that adds `published` field with timestamp to outgoing activities. Important that
|
||||||
|
/// the timestamp includes milliseconds and timezone.
|
||||||
|
#[derive(Serialize)]
|
||||||
|
struct WithPublished<T> {
|
||||||
|
published: DateTime<Utc>,
|
||||||
|
#[serde(flatten)]
|
||||||
|
inner: T,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> WithPublished<T> {
|
||||||
|
pub fn new(inner: T, published: DateTime<Utc>) -> WithPublished<T> {
|
||||||
|
Self {
|
||||||
|
published,
|
||||||
|
inner,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
|
@ -343,7 +343,7 @@ pub mod tests {
|
||||||
error::Error,
|
error::Error,
|
||||||
fetch::object_id::ObjectId,
|
fetch::object_id::ObjectId,
|
||||||
http_signatures::{generate_actor_keypair, Keypair},
|
http_signatures::{generate_actor_keypair, Keypair},
|
||||||
protocol::{public_key::PublicKey, verification::verify_domains_match},
|
protocol::{verification::verify_domains_match},
|
||||||
};
|
};
|
||||||
use activitystreams_kinds::{activity::FollowType, actor::PersonType};
|
use activitystreams_kinds::{activity::FollowType, actor::PersonType};
|
||||||
use once_cell::sync::Lazy;
|
use once_cell::sync::Lazy;
|
||||||
|
|
Loading…
Reference in a new issue