WIP: implement ActivitySender actor
This commit is contained in:
parent
e007006daf
commit
35649032c0
10 changed files with 218 additions and 84 deletions
|
@ -1,20 +1,11 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
apub::{
|
apub::{activity_sender::SendUserActivity, community::do_announce, insert_activity},
|
||||||
check_is_apub_id_valid,
|
|
||||||
community::do_announce,
|
|
||||||
extensions::signatures::sign,
|
|
||||||
insert_activity,
|
|
||||||
ActorType,
|
|
||||||
},
|
|
||||||
request::retry_custom,
|
|
||||||
LemmyContext,
|
LemmyContext,
|
||||||
LemmyError,
|
LemmyError,
|
||||||
};
|
};
|
||||||
use activitystreams::base::AnyBase;
|
use activitystreams::base::AnyBase;
|
||||||
use actix_web::client::Client;
|
|
||||||
use lemmy_db::{community::Community, user::User_};
|
use lemmy_db::{community::Community, user::User_};
|
||||||
use lemmy_utils::{get_apub_protocol_string, settings::Settings};
|
use lemmy_utils::{get_apub_protocol_string, settings::Settings};
|
||||||
use log::debug;
|
|
||||||
use url::{ParseError, Url};
|
use url::{ParseError, Url};
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
|
||||||
|
@ -31,42 +22,12 @@ pub async fn send_activity_to_community(
|
||||||
if community.local {
|
if community.local {
|
||||||
do_announce(activity, &community, creator, context).await?;
|
do_announce(activity, &community, creator, context).await?;
|
||||||
} else {
|
} else {
|
||||||
send_activity(context.client(), &activity, creator, to).await?;
|
let message = SendUserActivity {
|
||||||
}
|
activity,
|
||||||
|
actor: creator.to_owned(),
|
||||||
Ok(())
|
to,
|
||||||
}
|
};
|
||||||
|
context.activity_sender().send(message).await??;
|
||||||
/// Send an activity to a list of recipients, using the correct headers etc.
|
|
||||||
pub async fn send_activity(
|
|
||||||
client: &Client,
|
|
||||||
activity: &AnyBase,
|
|
||||||
actor: &dyn ActorType,
|
|
||||||
to: Vec<Url>,
|
|
||||||
) -> Result<(), LemmyError> {
|
|
||||||
if !Settings::get().federation.enabled {
|
|
||||||
return Ok(());
|
|
||||||
}
|
|
||||||
|
|
||||||
let activity = serde_json::to_string(&activity)?;
|
|
||||||
debug!("Sending activitypub activity {} to {:?}", activity, to);
|
|
||||||
|
|
||||||
for to_url in to {
|
|
||||||
check_is_apub_id_valid(&to_url)?;
|
|
||||||
|
|
||||||
let res = retry_custom(|| async {
|
|
||||||
let request = client
|
|
||||||
.post(to_url.as_str())
|
|
||||||
.header("Content-Type", "application/json");
|
|
||||||
|
|
||||||
match sign(request, actor, activity.clone()).await {
|
|
||||||
Ok(signed) => Ok(signed.send().await),
|
|
||||||
Err(e) => Err(e),
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.await?;
|
|
||||||
|
|
||||||
debug!("Result for activity send: {:?}", res);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
95
server/src/apub/activity_sender.rs
Normal file
95
server/src/apub/activity_sender.rs
Normal file
|
@ -0,0 +1,95 @@
|
||||||
|
use crate::{
|
||||||
|
apub::{check_is_apub_id_valid, extensions::signatures::sign, ActorType},
|
||||||
|
LemmyError,
|
||||||
|
};
|
||||||
|
use activitystreams::base::AnyBase;
|
||||||
|
use actix::prelude::*;
|
||||||
|
use awc::Client;
|
||||||
|
use lemmy_db::{community::Community, user::User_};
|
||||||
|
use lemmy_utils::settings::Settings;
|
||||||
|
use log::debug;
|
||||||
|
use url::Url;
|
||||||
|
|
||||||
|
// We cant use ActorType here, because it doesnt implement Sized
|
||||||
|
#[derive(Message)]
|
||||||
|
#[rtype(result = "Result<(), LemmyError>")]
|
||||||
|
pub struct SendUserActivity {
|
||||||
|
pub activity: AnyBase,
|
||||||
|
pub actor: User_,
|
||||||
|
pub to: Vec<Url>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Message)]
|
||||||
|
#[rtype(result = "Result<(), LemmyError>")]
|
||||||
|
pub struct SendCommunityActivity {
|
||||||
|
pub activity: AnyBase,
|
||||||
|
pub actor: Community,
|
||||||
|
pub to: Vec<Url>,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct ActivitySender {
|
||||||
|
client: Client,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ActivitySender {
|
||||||
|
pub fn startup(client: Client) -> ActivitySender {
|
||||||
|
ActivitySender { client }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Actor for ActivitySender {
|
||||||
|
type Context = Context<Self>;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Handler<SendUserActivity> for ActivitySender {
|
||||||
|
type Result = Result<(), LemmyError>;
|
||||||
|
|
||||||
|
fn handle(&mut self, msg: SendUserActivity, _ctx: &mut Context<Self>) -> Self::Result {
|
||||||
|
send_activity(msg.activity, &msg.actor, msg.to, &self.client)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Handler<SendCommunityActivity> for ActivitySender {
|
||||||
|
type Result = Result<(), LemmyError>;
|
||||||
|
|
||||||
|
fn handle(&mut self, msg: SendCommunityActivity, _ctx: &mut Context<Self>) -> Self::Result {
|
||||||
|
send_activity(msg.activity, &msg.actor, msg.to, &self.client)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn send_activity(
|
||||||
|
activity: AnyBase,
|
||||||
|
actor: &dyn ActorType,
|
||||||
|
to: Vec<Url>,
|
||||||
|
client: &Client,
|
||||||
|
) -> Result<(), LemmyError> {
|
||||||
|
if !Settings::get().federation.enabled {
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
|
let serialised_activity = serde_json::to_string(&activity)?;
|
||||||
|
debug!(
|
||||||
|
"Sending activitypub activity {} to {:?}",
|
||||||
|
&serialised_activity, &to
|
||||||
|
);
|
||||||
|
|
||||||
|
for to_url in &to {
|
||||||
|
check_is_apub_id_valid(&to_url)?;
|
||||||
|
|
||||||
|
let request = client
|
||||||
|
.post(to_url.as_str())
|
||||||
|
.header("Content-Type", "application/json");
|
||||||
|
|
||||||
|
let serialised_activity = serialised_activity.clone();
|
||||||
|
Box::pin(async move {
|
||||||
|
// TODO: need to remove the unwrap, but ? causes compile errors
|
||||||
|
// TODO: if the sending fails, it should retry with exponential backoff
|
||||||
|
let signed = sign(request, actor, serialised_activity).await.unwrap();
|
||||||
|
let res = signed.send().await;
|
||||||
|
debug!("Result for activity send: {:?}", res);
|
||||||
|
Ok::<(), LemmyError>(())
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
|
@ -1,7 +1,8 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
api::{check_slurs, check_slurs_opt},
|
api::{check_slurs, check_slurs_opt},
|
||||||
apub::{
|
apub::{
|
||||||
activities::{generate_activity_id, send_activity},
|
activities::generate_activity_id,
|
||||||
|
activity_sender::{SendCommunityActivity, SendUserActivity},
|
||||||
check_actor_domain,
|
check_actor_domain,
|
||||||
create_apub_response,
|
create_apub_response,
|
||||||
create_apub_tombstone_response,
|
create_apub_tombstone_response,
|
||||||
|
@ -155,7 +156,12 @@ impl ActorType for Community {
|
||||||
|
|
||||||
insert_activity(self.creator_id, accept.clone(), true, context.pool()).await?;
|
insert_activity(self.creator_id, accept.clone(), true, context.pool()).await?;
|
||||||
|
|
||||||
send_activity(context.client(), &accept.into_any_base()?, self, vec![to]).await?;
|
let message = SendCommunityActivity {
|
||||||
|
activity: accept.into_any_base()?,
|
||||||
|
actor: self.to_owned(),
|
||||||
|
to: vec![to],
|
||||||
|
};
|
||||||
|
context.activity_sender().send(message).await??;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -176,7 +182,12 @@ impl ActorType for Community {
|
||||||
// Note: For an accept, since it was automatic, no one pushed a button,
|
// Note: For an accept, since it was automatic, no one pushed a button,
|
||||||
// the community was the actor.
|
// the community was the actor.
|
||||||
// But for delete, the creator is the actor, and does the signing
|
// But for delete, the creator is the actor, and does the signing
|
||||||
send_activity(context.client(), &delete.into_any_base()?, creator, inboxes).await?;
|
let message = SendUserActivity {
|
||||||
|
activity: delete.into_any_base()?,
|
||||||
|
actor: creator.to_owned(),
|
||||||
|
to: inboxes,
|
||||||
|
};
|
||||||
|
context.activity_sender().send(message).await??;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -208,7 +219,12 @@ impl ActorType for Community {
|
||||||
// Note: For an accept, since it was automatic, no one pushed a button,
|
// Note: For an accept, since it was automatic, no one pushed a button,
|
||||||
// the community was the actor.
|
// the community was the actor.
|
||||||
// But for delete, the creator is the actor, and does the signing
|
// But for delete, the creator is the actor, and does the signing
|
||||||
send_activity(context.client(), &undo.into_any_base()?, creator, inboxes).await?;
|
let message = SendUserActivity {
|
||||||
|
activity: undo.into_any_base()?,
|
||||||
|
actor: creator.to_owned(),
|
||||||
|
to: inboxes,
|
||||||
|
};
|
||||||
|
context.activity_sender().send(message).await??;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -229,7 +245,12 @@ impl ActorType for Community {
|
||||||
// Note: For an accept, since it was automatic, no one pushed a button,
|
// Note: For an accept, since it was automatic, no one pushed a button,
|
||||||
// the community was the actor.
|
// the community was the actor.
|
||||||
// But for delete, the creator is the actor, and does the signing
|
// But for delete, the creator is the actor, and does the signing
|
||||||
send_activity(context.client(), &remove.into_any_base()?, mod_, inboxes).await?;
|
let message = SendUserActivity {
|
||||||
|
activity: remove.into_any_base()?,
|
||||||
|
actor: mod_.to_owned(),
|
||||||
|
to: inboxes,
|
||||||
|
};
|
||||||
|
context.activity_sender().send(message).await??;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -258,7 +279,12 @@ impl ActorType for Community {
|
||||||
// Note: For an accept, since it was automatic, no one pushed a button,
|
// Note: For an accept, since it was automatic, no one pushed a button,
|
||||||
// the community was the actor.
|
// the community was the actor.
|
||||||
// But for remove , the creator is the actor, and does the signing
|
// But for remove , the creator is the actor, and does the signing
|
||||||
send_activity(context.client(), &undo.into_any_base()?, mod_, inboxes).await?;
|
let message = SendUserActivity {
|
||||||
|
activity: undo.into_any_base()?,
|
||||||
|
actor: mod_.to_owned(),
|
||||||
|
to: inboxes,
|
||||||
|
};
|
||||||
|
context.activity_sender().send(message).await??;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -511,7 +537,12 @@ pub async fn do_announce(
|
||||||
let community_shared_inbox = community.get_shared_inbox_url()?;
|
let community_shared_inbox = community.get_shared_inbox_url()?;
|
||||||
to.retain(|x| x != &community_shared_inbox);
|
to.retain(|x| x != &community_shared_inbox);
|
||||||
|
|
||||||
send_activity(context.client(), &announce.into_any_base()?, community, to).await?;
|
let message = SendCommunityActivity {
|
||||||
|
activity: announce.into_any_base()?,
|
||||||
|
actor: community.to_owned(),
|
||||||
|
to,
|
||||||
|
};
|
||||||
|
context.activity_sender().send(message).await??;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
pub mod activity_sender;
|
||||||
pub mod activities;
|
pub mod activities;
|
||||||
pub mod comment;
|
pub mod comment;
|
||||||
pub mod community;
|
pub mod community;
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
apub::{
|
apub::{
|
||||||
activities::{generate_activity_id, send_activity},
|
activities::generate_activity_id,
|
||||||
|
activity_sender::SendUserActivity,
|
||||||
check_actor_domain,
|
check_actor_domain,
|
||||||
check_is_apub_id_valid,
|
check_is_apub_id_valid,
|
||||||
create_tombstone,
|
create_tombstone,
|
||||||
|
@ -134,13 +135,12 @@ impl ApubObjectType for PrivateMessage {
|
||||||
|
|
||||||
insert_activity(creator.id, create.clone(), true, context.pool()).await?;
|
insert_activity(creator.id, create.clone(), true, context.pool()).await?;
|
||||||
|
|
||||||
send_activity(
|
let message = SendUserActivity {
|
||||||
context.client(),
|
activity: create.into_any_base()?,
|
||||||
&create.into_any_base()?,
|
actor: creator.to_owned(),
|
||||||
creator,
|
to: vec![to],
|
||||||
vec![to],
|
};
|
||||||
)
|
context.activity_sender().send(message).await??;
|
||||||
.await?;
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -160,13 +160,12 @@ impl ApubObjectType for PrivateMessage {
|
||||||
|
|
||||||
insert_activity(creator.id, update.clone(), true, context.pool()).await?;
|
insert_activity(creator.id, update.clone(), true, context.pool()).await?;
|
||||||
|
|
||||||
send_activity(
|
let message = SendUserActivity {
|
||||||
context.client(),
|
activity: update.into_any_base()?,
|
||||||
&update.into_any_base()?,
|
actor: creator.to_owned(),
|
||||||
creator,
|
to: vec![to],
|
||||||
vec![to],
|
};
|
||||||
)
|
context.activity_sender().send(message).await??;
|
||||||
.await?;
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -185,13 +184,12 @@ impl ApubObjectType for PrivateMessage {
|
||||||
|
|
||||||
insert_activity(creator.id, delete.clone(), true, context.pool()).await?;
|
insert_activity(creator.id, delete.clone(), true, context.pool()).await?;
|
||||||
|
|
||||||
send_activity(
|
let message = SendUserActivity {
|
||||||
context.client(),
|
activity: delete.into_any_base()?,
|
||||||
&delete.into_any_base()?,
|
actor: creator.to_owned(),
|
||||||
creator,
|
to: vec![to],
|
||||||
vec![to],
|
};
|
||||||
)
|
context.activity_sender().send(message).await??;
|
||||||
.await?;
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -221,7 +219,12 @@ impl ApubObjectType for PrivateMessage {
|
||||||
|
|
||||||
insert_activity(creator.id, undo.clone(), true, context.pool()).await?;
|
insert_activity(creator.id, undo.clone(), true, context.pool()).await?;
|
||||||
|
|
||||||
send_activity(context.client(), &undo.into_any_base()?, creator, vec![to]).await?;
|
let message = SendUserActivity {
|
||||||
|
activity: undo.into_any_base()?,
|
||||||
|
actor: creator.to_owned(),
|
||||||
|
to: vec![to],
|
||||||
|
};
|
||||||
|
context.activity_sender().send(message).await??;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
api::{check_slurs, check_slurs_opt},
|
api::{check_slurs, check_slurs_opt},
|
||||||
apub::{
|
apub::{
|
||||||
activities::{generate_activity_id, send_activity},
|
activities::generate_activity_id,
|
||||||
|
activity_sender::SendUserActivity,
|
||||||
check_actor_domain,
|
check_actor_domain,
|
||||||
create_apub_response,
|
create_apub_response,
|
||||||
fetcher::get_or_fetch_and_upsert_actor,
|
fetcher::get_or_fetch_and_upsert_actor,
|
||||||
|
@ -127,7 +128,12 @@ impl ActorType for User_ {
|
||||||
|
|
||||||
insert_activity(self.id, follow.clone(), true, context.pool()).await?;
|
insert_activity(self.id, follow.clone(), true, context.pool()).await?;
|
||||||
|
|
||||||
send_activity(context.client(), &follow.into_any_base()?, self, vec![to]).await?;
|
let message = SendUserActivity {
|
||||||
|
activity: follow.into_any_base()?,
|
||||||
|
actor: self.to_owned(),
|
||||||
|
to: vec![to],
|
||||||
|
};
|
||||||
|
context.activity_sender().send(message).await??;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -152,7 +158,12 @@ impl ActorType for User_ {
|
||||||
|
|
||||||
insert_activity(self.id, undo.clone(), true, context.pool()).await?;
|
insert_activity(self.id, undo.clone(), true, context.pool()).await?;
|
||||||
|
|
||||||
send_activity(context.client(), &undo.into_any_base()?, self, vec![to]).await?;
|
let message = SendUserActivity {
|
||||||
|
activity: undo.into_any_base()?,
|
||||||
|
actor: self.to_owned(),
|
||||||
|
to: vec![to],
|
||||||
|
};
|
||||||
|
context.activity_sender().send(message).await??;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -33,6 +33,8 @@ use crate::{
|
||||||
request::{retry, RecvError},
|
request::{retry, RecvError},
|
||||||
websocket::server::ChatServer,
|
websocket::server::ChatServer,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use crate::apub::activity_sender::ActivitySender;
|
||||||
use actix::Addr;
|
use actix::Addr;
|
||||||
use actix_web::{client::Client, dev::ConnectionInfo};
|
use actix_web::{client::Client, dev::ConnectionInfo};
|
||||||
use anyhow::anyhow;
|
use anyhow::anyhow;
|
||||||
|
@ -75,14 +77,21 @@ pub struct LemmyContext {
|
||||||
pub pool: DbPool,
|
pub pool: DbPool,
|
||||||
pub chat_server: Addr<ChatServer>,
|
pub chat_server: Addr<ChatServer>,
|
||||||
pub client: Client,
|
pub client: Client,
|
||||||
|
pub activity_sender: Addr<ActivitySender>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LemmyContext {
|
impl LemmyContext {
|
||||||
pub fn create(pool: DbPool, chat_server: Addr<ChatServer>, client: Client) -> LemmyContext {
|
pub fn create(
|
||||||
|
pool: DbPool,
|
||||||
|
chat_server: Addr<ChatServer>,
|
||||||
|
client: Client,
|
||||||
|
activity_sender: Addr<ActivitySender>,
|
||||||
|
) -> LemmyContext {
|
||||||
LemmyContext {
|
LemmyContext {
|
||||||
pool,
|
pool,
|
||||||
chat_server,
|
chat_server,
|
||||||
client,
|
client,
|
||||||
|
activity_sender,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn pool(&self) -> &DbPool {
|
pub fn pool(&self) -> &DbPool {
|
||||||
|
@ -94,6 +103,9 @@ impl LemmyContext {
|
||||||
pub fn client(&self) -> &Client {
|
pub fn client(&self) -> &Client {
|
||||||
&self.client
|
&self.client
|
||||||
}
|
}
|
||||||
|
pub fn activity_sender(&self) -> &Addr<ActivitySender> {
|
||||||
|
&self.activity_sender
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Clone for LemmyContext {
|
impl Clone for LemmyContext {
|
||||||
|
@ -102,6 +114,7 @@ impl Clone for LemmyContext {
|
||||||
pool: self.pool.clone(),
|
pool: self.pool.clone(),
|
||||||
chat_server: self.chat_server.clone(),
|
chat_server: self.chat_server.clone(),
|
||||||
client: self.client.clone(),
|
client: self.client.clone(),
|
||||||
|
activity_sender: self.activity_sender.clone(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,6 +20,7 @@ use diesel::{
|
||||||
};
|
};
|
||||||
use lemmy_db::get_database_url_from_env;
|
use lemmy_db::get_database_url_from_env;
|
||||||
use lemmy_server::{
|
use lemmy_server::{
|
||||||
|
apub::activity_sender::ActivitySender,
|
||||||
blocking,
|
blocking,
|
||||||
code_migrations::run_advanced_migrations,
|
code_migrations::run_advanced_migrations,
|
||||||
rate_limit::{rate_limiter::RateLimiter, RateLimit},
|
rate_limit::{rate_limiter::RateLimiter, RateLimit},
|
||||||
|
@ -76,9 +77,20 @@ async fn main() -> Result<(), LemmyError> {
|
||||||
|
|
||||||
// Create Http server with websocket support
|
// Create Http server with websocket support
|
||||||
HttpServer::new(move || {
|
HttpServer::new(move || {
|
||||||
let chat_server =
|
let activity_sender = ActivitySender::startup(Client::default()).start();
|
||||||
ChatServer::startup(pool.clone(), rate_limiter.clone(), Client::default()).start();
|
let chat_server = ChatServer::startup(
|
||||||
let context = LemmyContext::create(pool.clone(), chat_server, Client::default());
|
pool.clone(),
|
||||||
|
rate_limiter.clone(),
|
||||||
|
Client::default(),
|
||||||
|
activity_sender.clone(),
|
||||||
|
)
|
||||||
|
.start();
|
||||||
|
let context = LemmyContext::create(
|
||||||
|
pool.clone(),
|
||||||
|
chat_server,
|
||||||
|
Client::default(),
|
||||||
|
activity_sender,
|
||||||
|
);
|
||||||
let settings = Settings::get();
|
let settings = Settings::get();
|
||||||
let rate_limiter = rate_limiter.clone();
|
let rate_limiter = rate_limiter.clone();
|
||||||
App::new()
|
App::new()
|
||||||
|
|
|
@ -19,7 +19,7 @@ where
|
||||||
retry_custom(|| async { Ok((f)().await) }).await
|
retry_custom(|| async { Ok((f)().await) }).await
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn retry_custom<F, Fut, T>(f: F) -> Result<T, LemmyError>
|
async fn retry_custom<F, Fut, T>(f: F) -> Result<T, LemmyError>
|
||||||
where
|
where
|
||||||
F: Fn() -> Fut,
|
F: Fn() -> Fut,
|
||||||
Fut: Future<Output = Result<Result<T, actix_web::client::SendRequestError>, LemmyError>>,
|
Fut: Future<Output = Result<Result<T, actix_web::client::SendRequestError>, LemmyError>>,
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::{
|
use crate::{
|
||||||
api::{comment::*, community::*, post::*, site::*, user::*, *},
|
api::{comment::*, community::*, post::*, site::*, user::*, *},
|
||||||
|
apub::activity_sender::ActivitySender,
|
||||||
rate_limit::RateLimit,
|
rate_limit::RateLimit,
|
||||||
websocket::UserOperation,
|
websocket::UserOperation,
|
||||||
CommunityId,
|
CommunityId,
|
||||||
|
@ -181,6 +182,8 @@ pub struct ChatServer {
|
||||||
|
|
||||||
/// An HTTP Client
|
/// An HTTP Client
|
||||||
client: Client,
|
client: Client,
|
||||||
|
|
||||||
|
activity_sender: Addr<ActivitySender>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ChatServer {
|
impl ChatServer {
|
||||||
|
@ -188,6 +191,7 @@ impl ChatServer {
|
||||||
pool: Pool<ConnectionManager<PgConnection>>,
|
pool: Pool<ConnectionManager<PgConnection>>,
|
||||||
rate_limiter: RateLimit,
|
rate_limiter: RateLimit,
|
||||||
client: Client,
|
client: Client,
|
||||||
|
activity_sender: Addr<ActivitySender>,
|
||||||
) -> ChatServer {
|
) -> ChatServer {
|
||||||
ChatServer {
|
ChatServer {
|
||||||
sessions: HashMap::new(),
|
sessions: HashMap::new(),
|
||||||
|
@ -199,6 +203,7 @@ impl ChatServer {
|
||||||
rate_limiter,
|
rate_limiter,
|
||||||
captchas: Vec::new(),
|
captchas: Vec::new(),
|
||||||
client,
|
client,
|
||||||
|
activity_sender,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -455,6 +460,7 @@ impl ChatServer {
|
||||||
};
|
};
|
||||||
|
|
||||||
let client = self.client.clone();
|
let client = self.client.clone();
|
||||||
|
let activity_sender = self.activity_sender.clone();
|
||||||
async move {
|
async move {
|
||||||
let msg = msg;
|
let msg = msg;
|
||||||
let json: Value = serde_json::from_str(&msg.msg)?;
|
let json: Value = serde_json::from_str(&msg.msg)?;
|
||||||
|
@ -469,6 +475,7 @@ impl ChatServer {
|
||||||
pool,
|
pool,
|
||||||
chat_server: addr,
|
chat_server: addr,
|
||||||
client,
|
client,
|
||||||
|
activity_sender,
|
||||||
};
|
};
|
||||||
let args = Args {
|
let args = Args {
|
||||||
context: &context,
|
context: &context,
|
||||||
|
|
Loading…
Reference in a new issue