mirror of
https://github.com/LemmyNet/lemmy.git
synced 2024-06-02 06:51:51 +00:00
d4dccd17ae
Merge pull request 'Adding unique ap_ids. Fixes #1100' (#90) from unique_ap_ids into activity-sender Reviewed-on: https://yerbamate.dev/LemmyNet/lemmy/pulls/90 Adding back in on_conflict. Trying to add back in the on_conflict_do_nothing. Trying to reduce delay time. Removing createFakes. Removing some unit tests. Adding comment jest timeout. Fixing tests again. Fixing tests again. Merge branch 'activity-sender' into unique_ap_ids_2 Replace actix client with reqwest to speed up federation tests Trying to fix tests again. Fixing unit tests. Fixing some broken unit tests, not done yet. Adding uniques. Adding unique ap_ids. Fixes #1100 use proper sql functionality for upsert added logging in fetcher, replace post/comment::create with upsert no need to do an actual update in post/comment::upsert Merge branch 'main' into activity-sender implement upsert for user/community reuse http client got it working attempt to use background-jobs crate rewrite with proper error handling and less boilerplate remove do_send, dont return errors from activity_sender WIP: implement ActivitySender actor Co-authored-by: dessalines <dessalines@noreply.yerbamate.dev> Co-authored-by: Dessalines <tyhou13@gmx.com> Co-authored-by: Felix Ableitner <me@nutomic.com> Reviewed-on: https://yerbamate.dev/LemmyNet/lemmy/pulls/89
223 lines
6.8 KiB
Rust
223 lines
6.8 KiB
Rust
use crate::{
|
|
apub::{
|
|
activities::generate_activity_id,
|
|
activity_queue::send_activity,
|
|
check_actor_domain,
|
|
check_is_apub_id_valid,
|
|
create_tombstone,
|
|
fetcher::get_or_fetch_and_upsert_user,
|
|
insert_activity,
|
|
ActorType,
|
|
ApubObjectType,
|
|
FromApub,
|
|
ToApub,
|
|
},
|
|
blocking,
|
|
DbPool,
|
|
LemmyContext,
|
|
LemmyError,
|
|
};
|
|
use activitystreams::{
|
|
activity::{
|
|
kind::{CreateType, DeleteType, UndoType, UpdateType},
|
|
Create,
|
|
Delete,
|
|
Undo,
|
|
Update,
|
|
},
|
|
object::{kind::NoteType, Note, Tombstone},
|
|
prelude::*,
|
|
};
|
|
use anyhow::Context;
|
|
use lemmy_db::{
|
|
private_message::{PrivateMessage, PrivateMessageForm},
|
|
user::User_,
|
|
Crud,
|
|
};
|
|
use lemmy_utils::{convert_datetime, location_info};
|
|
use url::Url;
|
|
|
|
#[async_trait::async_trait(?Send)]
|
|
impl ToApub for PrivateMessage {
|
|
type Response = Note;
|
|
|
|
async fn to_apub(&self, pool: &DbPool) -> Result<Note, LemmyError> {
|
|
let mut private_message = Note::new();
|
|
|
|
let creator_id = self.creator_id;
|
|
let creator = blocking(pool, move |conn| User_::read(conn, creator_id)).await??;
|
|
|
|
let recipient_id = self.recipient_id;
|
|
let recipient = blocking(pool, move |conn| User_::read(conn, recipient_id)).await??;
|
|
|
|
private_message
|
|
.set_context(activitystreams::context())
|
|
.set_id(Url::parse(&self.ap_id.to_owned())?)
|
|
.set_published(convert_datetime(self.published))
|
|
.set_content(self.content.to_owned())
|
|
.set_to(recipient.actor_id)
|
|
.set_attributed_to(creator.actor_id);
|
|
|
|
if let Some(u) = self.updated {
|
|
private_message.set_updated(convert_datetime(u));
|
|
}
|
|
|
|
Ok(private_message)
|
|
}
|
|
|
|
fn to_tombstone(&self) -> Result<Tombstone, LemmyError> {
|
|
create_tombstone(self.deleted, &self.ap_id, self.updated, NoteType::Note)
|
|
}
|
|
}
|
|
|
|
#[async_trait::async_trait(?Send)]
|
|
impl FromApub for PrivateMessageForm {
|
|
type ApubType = Note;
|
|
|
|
/// Parse an ActivityPub note received from another instance into a Lemmy Private message
|
|
async fn from_apub(
|
|
note: &Note,
|
|
context: &LemmyContext,
|
|
expected_domain: Option<Url>,
|
|
) -> Result<PrivateMessageForm, LemmyError> {
|
|
let creator_actor_id = note
|
|
.attributed_to()
|
|
.context(location_info!())?
|
|
.clone()
|
|
.single_xsd_any_uri()
|
|
.context(location_info!())?;
|
|
|
|
let creator = get_or_fetch_and_upsert_user(&creator_actor_id, context).await?;
|
|
let recipient_actor_id = note
|
|
.to()
|
|
.context(location_info!())?
|
|
.clone()
|
|
.single_xsd_any_uri()
|
|
.context(location_info!())?;
|
|
let recipient = get_or_fetch_and_upsert_user(&recipient_actor_id, context).await?;
|
|
let ap_id = note.id_unchecked().context(location_info!())?.to_string();
|
|
check_is_apub_id_valid(&Url::parse(&ap_id)?)?;
|
|
|
|
Ok(PrivateMessageForm {
|
|
creator_id: creator.id,
|
|
recipient_id: recipient.id,
|
|
content: note
|
|
.content()
|
|
.context(location_info!())?
|
|
.as_single_xsd_string()
|
|
.context(location_info!())?
|
|
.to_string(),
|
|
published: note.published().map(|u| u.to_owned().naive_local()),
|
|
updated: note.updated().map(|u| u.to_owned().naive_local()),
|
|
deleted: None,
|
|
read: None,
|
|
ap_id: Some(check_actor_domain(note, expected_domain)?),
|
|
local: false,
|
|
})
|
|
}
|
|
}
|
|
|
|
#[async_trait::async_trait(?Send)]
|
|
impl ApubObjectType for PrivateMessage {
|
|
/// Send out information about a newly created private message
|
|
async fn send_create(&self, creator: &User_, context: &LemmyContext) -> Result<(), LemmyError> {
|
|
let note = self.to_apub(context.pool()).await?;
|
|
|
|
let recipient_id = self.recipient_id;
|
|
let recipient = blocking(context.pool(), move |conn| User_::read(conn, recipient_id)).await??;
|
|
|
|
let mut create = Create::new(creator.actor_id.to_owned(), note.into_any_base()?);
|
|
let to = recipient.get_inbox_url()?;
|
|
create
|
|
.set_context(activitystreams::context())
|
|
.set_id(generate_activity_id(CreateType::Create)?)
|
|
.set_to(to.clone());
|
|
|
|
insert_activity(creator.id, create.clone(), true, context.pool()).await?;
|
|
|
|
send_activity(context.activity_queue(), create, creator, vec![to])?;
|
|
Ok(())
|
|
}
|
|
|
|
/// Send out information about an edited post, to the followers of the community.
|
|
async fn send_update(&self, creator: &User_, context: &LemmyContext) -> Result<(), LemmyError> {
|
|
let note = self.to_apub(context.pool()).await?;
|
|
|
|
let recipient_id = self.recipient_id;
|
|
let recipient = blocking(context.pool(), move |conn| User_::read(conn, recipient_id)).await??;
|
|
|
|
let mut update = Update::new(creator.actor_id.to_owned(), note.into_any_base()?);
|
|
let to = recipient.get_inbox_url()?;
|
|
update
|
|
.set_context(activitystreams::context())
|
|
.set_id(generate_activity_id(UpdateType::Update)?)
|
|
.set_to(to.clone());
|
|
|
|
insert_activity(creator.id, update.clone(), true, context.pool()).await?;
|
|
|
|
send_activity(context.activity_queue(), update, creator, vec![to])?;
|
|
Ok(())
|
|
}
|
|
|
|
async fn send_delete(&self, creator: &User_, context: &LemmyContext) -> Result<(), LemmyError> {
|
|
let note = self.to_apub(context.pool()).await?;
|
|
|
|
let recipient_id = self.recipient_id;
|
|
let recipient = blocking(context.pool(), move |conn| User_::read(conn, recipient_id)).await??;
|
|
|
|
let mut delete = Delete::new(creator.actor_id.to_owned(), note.into_any_base()?);
|
|
let to = recipient.get_inbox_url()?;
|
|
delete
|
|
.set_context(activitystreams::context())
|
|
.set_id(generate_activity_id(DeleteType::Delete)?)
|
|
.set_to(to.clone());
|
|
|
|
insert_activity(creator.id, delete.clone(), true, context.pool()).await?;
|
|
|
|
send_activity(context.activity_queue(), delete, creator, vec![to])?;
|
|
Ok(())
|
|
}
|
|
|
|
async fn send_undo_delete(
|
|
&self,
|
|
creator: &User_,
|
|
context: &LemmyContext,
|
|
) -> Result<(), LemmyError> {
|
|
let note = self.to_apub(context.pool()).await?;
|
|
|
|
let recipient_id = self.recipient_id;
|
|
let recipient = blocking(context.pool(), move |conn| User_::read(conn, recipient_id)).await??;
|
|
|
|
let mut delete = Delete::new(creator.actor_id.to_owned(), note.into_any_base()?);
|
|
let to = recipient.get_inbox_url()?;
|
|
delete
|
|
.set_context(activitystreams::context())
|
|
.set_id(generate_activity_id(DeleteType::Delete)?)
|
|
.set_to(to.clone());
|
|
|
|
// Undo that fake activity
|
|
let mut undo = Undo::new(creator.actor_id.to_owned(), delete.into_any_base()?);
|
|
undo
|
|
.set_context(activitystreams::context())
|
|
.set_id(generate_activity_id(UndoType::Undo)?)
|
|
.set_to(to.clone());
|
|
|
|
insert_activity(creator.id, undo.clone(), true, context.pool()).await?;
|
|
|
|
send_activity(context.activity_queue(), undo, creator, vec![to])?;
|
|
Ok(())
|
|
}
|
|
|
|
async fn send_remove(&self, _mod_: &User_, _context: &LemmyContext) -> Result<(), LemmyError> {
|
|
unimplemented!()
|
|
}
|
|
|
|
async fn send_undo_remove(
|
|
&self,
|
|
_mod_: &User_,
|
|
_context: &LemmyContext,
|
|
) -> Result<(), LemmyError> {
|
|
unimplemented!()
|
|
}
|
|
}
|