WIP: alternative way to handle non-local object parsing
This commit is contained in:
parent
2bdb15b06d
commit
9cbb80ca8e
20 changed files with 156 additions and 57 deletions
|
@ -2,7 +2,6 @@ use crate::{
|
|||
activities::receive::get_actor_as_user,
|
||||
fetcher::get_or_fetch_and_insert_comment,
|
||||
ActorType,
|
||||
FromApub,
|
||||
NoteExt,
|
||||
};
|
||||
use activitystreams::{
|
||||
|
@ -20,6 +19,7 @@ use lemmy_db::{
|
|||
use lemmy_structs::{blocking, comment::CommentResponse, send_local_notifs};
|
||||
use lemmy_utils::{location_info, utils::scrape_text_for_mentions, LemmyError};
|
||||
use lemmy_websocket::{messages::SendComment, LemmyContext, UserOperation};
|
||||
use crate::objects::FromApub;
|
||||
|
||||
pub(crate) async fn receive_create_comment(
|
||||
create: Create,
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
use crate::{
|
||||
activities::receive::get_actor_as_user,
|
||||
fetcher::get_or_fetch_and_insert_comment,
|
||||
FromApub,
|
||||
NoteExt,
|
||||
};
|
||||
use crate::objects::FromApub;
|
||||
use activitystreams::{activity::*, prelude::*};
|
||||
use anyhow::Context;
|
||||
use lemmy_db::{
|
||||
|
|
|
@ -2,9 +2,9 @@ use crate::{
|
|||
activities::receive::get_actor_as_user,
|
||||
fetcher::get_or_fetch_and_insert_post,
|
||||
ActorType,
|
||||
FromApub,
|
||||
PageExt,
|
||||
};
|
||||
use crate::objects::FromApub;
|
||||
use activitystreams::{
|
||||
activity::{Create, Dislike, Like, Remove, Update},
|
||||
prelude::*,
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
use crate::{
|
||||
activities::receive::get_actor_as_user,
|
||||
fetcher::get_or_fetch_and_insert_post,
|
||||
FromApub,
|
||||
PageExt,
|
||||
};
|
||||
use crate::objects::FromApub;
|
||||
use activitystreams::{activity::*, prelude::*};
|
||||
use anyhow::Context;
|
||||
use lemmy_db::{
|
||||
|
|
|
@ -3,9 +3,9 @@ use crate::{
|
|||
check_is_apub_id_valid,
|
||||
fetcher::get_or_fetch_and_upsert_user,
|
||||
inbox::get_activity_to_and_cc,
|
||||
FromApub,
|
||||
NoteExt,
|
||||
};
|
||||
use crate::objects::FromApub;
|
||||
use activitystreams::{
|
||||
activity::{ActorAndObjectRefExt, Create, Delete, Undo, Update},
|
||||
base::{AsBase, ExtendsExt},
|
||||
|
|
|
@ -6,7 +6,6 @@ use crate::{
|
|||
ActorType,
|
||||
ApubLikeableType,
|
||||
ApubObjectType,
|
||||
ToApub,
|
||||
};
|
||||
use activitystreams::{
|
||||
activity::{
|
||||
|
@ -39,6 +38,7 @@ use log::debug;
|
|||
use reqwest::Client;
|
||||
use serde_json::Error;
|
||||
use url::Url;
|
||||
use crate::objects::ToApub;
|
||||
|
||||
#[async_trait::async_trait(?Send)]
|
||||
impl ApubObjectType for Comment {
|
||||
|
|
|
@ -5,8 +5,8 @@ use crate::{
|
|||
ActorType,
|
||||
ApubLikeableType,
|
||||
ApubObjectType,
|
||||
ToApub,
|
||||
};
|
||||
use crate::objects::ToApub;
|
||||
use activitystreams::{
|
||||
activity::{
|
||||
kind::{CreateType, DeleteType, DislikeType, LikeType, RemoveType, UndoType, UpdateType},
|
||||
|
|
|
@ -4,8 +4,8 @@ use crate::{
|
|||
extensions::context::lemmy_context,
|
||||
ActorType,
|
||||
ApubObjectType,
|
||||
ToApub,
|
||||
};
|
||||
use crate::objects::ToApub;
|
||||
use activitystreams::{
|
||||
activity::{
|
||||
kind::{CreateType, DeleteType, UndoType, UpdateType},
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
use crate::{
|
||||
check_is_apub_id_valid,
|
||||
ActorType,
|
||||
FromApub,
|
||||
GroupExt,
|
||||
NoteExt,
|
||||
PageExt,
|
||||
|
@ -39,6 +38,7 @@ use reqwest::Client;
|
|||
use serde::Deserialize;
|
||||
use std::{fmt::Debug, time::Duration};
|
||||
use url::Url;
|
||||
use crate::objects::FromApub;
|
||||
|
||||
static ACTOR_REFETCH_INTERVAL_SECONDS: i64 = 24 * 60 * 60;
|
||||
static ACTOR_REFETCH_INTERVAL_SECONDS_DEBUG: i64 = 10;
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
use crate::{
|
||||
http::{create_apub_response, create_apub_tombstone_response},
|
||||
ToApub,
|
||||
};
|
||||
use actix_web::{body::Body, web, web::Path, HttpResponse};
|
||||
use diesel::result::Error::NotFound;
|
||||
|
@ -9,6 +8,7 @@ use lemmy_structs::blocking;
|
|||
use lemmy_utils::LemmyError;
|
||||
use lemmy_websocket::LemmyContext;
|
||||
use serde::Deserialize;
|
||||
use crate::objects::ToApub;
|
||||
|
||||
#[derive(Deserialize)]
|
||||
pub struct CommentQuery {
|
||||
|
|
|
@ -2,7 +2,6 @@ use crate::{
|
|||
extensions::context::lemmy_context,
|
||||
http::{create_apub_response, create_apub_tombstone_response},
|
||||
ActorType,
|
||||
ToApub,
|
||||
};
|
||||
use activitystreams::{
|
||||
base::{AnyBase, BaseExt, ExtendsExt},
|
||||
|
@ -14,6 +13,7 @@ use lemmy_structs::blocking;
|
|||
use lemmy_utils::LemmyError;
|
||||
use lemmy_websocket::LemmyContext;
|
||||
use serde::Deserialize;
|
||||
use crate::objects::ToApub;
|
||||
|
||||
#[derive(Deserialize)]
|
||||
pub struct CommunityQuery {
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
use crate::{
|
||||
http::{create_apub_response, create_apub_tombstone_response},
|
||||
ToApub,
|
||||
};
|
||||
use actix_web::{body::Body, web, HttpResponse};
|
||||
use diesel::result::Error::NotFound;
|
||||
|
@ -9,6 +8,7 @@ use lemmy_structs::blocking;
|
|||
use lemmy_utils::LemmyError;
|
||||
use lemmy_websocket::LemmyContext;
|
||||
use serde::Deserialize;
|
||||
use crate::objects::ToApub;
|
||||
|
||||
#[derive(Deserialize)]
|
||||
pub struct PostQuery {
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
use crate::{extensions::context::lemmy_context, http::create_apub_response, ActorType, ToApub};
|
||||
use crate::{extensions::context::lemmy_context, http::create_apub_response, ActorType};
|
||||
use activitystreams::{
|
||||
base::BaseExt,
|
||||
collection::{CollectionExt, OrderedCollection},
|
||||
};
|
||||
use crate::objects::ToApub;
|
||||
use actix_web::{body::Body, web, HttpResponse};
|
||||
use lemmy_db::user::User_;
|
||||
use lemmy_structs::blocking;
|
||||
|
|
|
@ -18,7 +18,7 @@ use activitystreams::{
|
|||
activity::Follow,
|
||||
actor::{ApActor, Group, Person},
|
||||
base::AnyBase,
|
||||
object::{ApObject, Note, Page, Tombstone},
|
||||
object::{ApObject, Note, Page},
|
||||
};
|
||||
use activitystreams_ext::{Ext1, Ext2};
|
||||
use anyhow::{anyhow, Context};
|
||||
|
@ -109,33 +109,6 @@ fn check_is_apub_id_valid(apub_id: &Url) -> Result<(), LemmyError> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Trait for converting an object or actor into the respective ActivityPub type.
|
||||
#[async_trait::async_trait(?Send)]
|
||||
pub(crate) trait ToApub {
|
||||
type ApubType;
|
||||
async fn to_apub(&self, pool: &DbPool) -> Result<Self::ApubType, LemmyError>;
|
||||
fn to_tombstone(&self) -> Result<Tombstone, LemmyError>;
|
||||
}
|
||||
|
||||
#[async_trait::async_trait(?Send)]
|
||||
pub(crate) trait FromApub {
|
||||
type ApubType;
|
||||
/// Converts an object from ActivityPub type to Lemmy internal type.
|
||||
///
|
||||
/// * `apub` The object to read from
|
||||
/// * `context` LemmyContext which holds DB pool, HTTP client etc
|
||||
/// * `expected_domain` If present, ensure that the domains of this and of the apub object ID are
|
||||
/// identical
|
||||
async fn from_apub(
|
||||
apub: &Self::ApubType,
|
||||
context: &LemmyContext,
|
||||
expected_domain: Option<Url>,
|
||||
request_counter: &mut i32,
|
||||
) -> Result<Self, LemmyError>
|
||||
where
|
||||
Self: Sized;
|
||||
}
|
||||
|
||||
/// Common functions for ActivityPub objects, which are implemented by most (but not all) objects
|
||||
/// and actors in Lemmy.
|
||||
#[async_trait::async_trait(?Send)]
|
||||
|
|
|
@ -11,9 +11,7 @@ use crate::{
|
|||
get_source_markdown_value,
|
||||
set_content_and_source,
|
||||
},
|
||||
FromApub,
|
||||
NoteExt,
|
||||
ToApub,
|
||||
};
|
||||
use activitystreams::{
|
||||
object::{kind::NoteType, ApObject, Note, Tombstone},
|
||||
|
@ -36,6 +34,8 @@ use lemmy_utils::{
|
|||
};
|
||||
use lemmy_websocket::LemmyContext;
|
||||
use url::Url;
|
||||
use crate::objects::{FromApub, ToApub, FromApubToForm};
|
||||
use lemmy_utils::settings::Settings;
|
||||
|
||||
#[async_trait::async_trait(?Send)]
|
||||
impl ToApub for Comment {
|
||||
|
@ -87,12 +87,41 @@ impl ToApub for Comment {
|
|||
}
|
||||
|
||||
#[async_trait::async_trait(?Send)]
|
||||
impl FromApub for CommentForm {
|
||||
impl FromApub for Comment {
|
||||
type ApubType = NoteExt;
|
||||
|
||||
/// Converts a `Note` to `CommentForm`.
|
||||
/// Converts a `Note` to `Comment`.
|
||||
///
|
||||
/// If the parent community, post and comment(s) are not known locally, these are also fetched.
|
||||
async fn from_apub(
|
||||
note: &NoteExt,
|
||||
context: &LemmyContext,
|
||||
expected_domain: Option<Url>,
|
||||
request_counter: &mut i32,
|
||||
) -> Result<Comment, LemmyError> {
|
||||
let comment_id = note.id_unchecked().context(location_info!())?;
|
||||
let domain = comment_id.domain().context(location_info!())?;
|
||||
if domain == Settings::get().hostname {
|
||||
let comment = blocking(context.pool(), move |conn| {
|
||||
Comment::read_from_apub_id(conn, comment_id.as_str())
|
||||
})
|
||||
.await??;
|
||||
Ok(comment)
|
||||
} else {
|
||||
let comment_form = CommentForm::from_apub(note, context, expected_domain, request_counter)?;
|
||||
let comment = blocking(context.pool(), move |conn| {
|
||||
Comment::upsert(conn, comment_form)
|
||||
})
|
||||
.await??;
|
||||
Ok(comment)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait::async_trait(?Send)]
|
||||
impl FromApubToForm for CommentForm {
|
||||
type ApubType = NoteExt;
|
||||
|
||||
async fn from_apub(
|
||||
note: &NoteExt,
|
||||
context: &LemmyContext,
|
||||
|
|
|
@ -8,9 +8,7 @@ use crate::{
|
|||
set_content_and_source,
|
||||
},
|
||||
ActorType,
|
||||
FromApub,
|
||||
GroupExt,
|
||||
ToApub,
|
||||
};
|
||||
use activitystreams::{
|
||||
actor::{kind::GroupType, ApActor, Endpoints, Group},
|
||||
|
@ -32,6 +30,7 @@ use lemmy_utils::{
|
|||
utils::{check_slurs, check_slurs_opt, convert_datetime},
|
||||
LemmyError,
|
||||
};
|
||||
use crate::objects::{FromApub, ToApub, FromApubToForm};
|
||||
use lemmy_websocket::LemmyContext;
|
||||
use url::Url;
|
||||
|
||||
|
@ -106,8 +105,24 @@ impl ToApub for Community {
|
|||
create_tombstone(self.deleted, &self.actor_id, self.updated, GroupType::Group)
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait::async_trait(?Send)]
|
||||
impl FromApub for CommunityForm {
|
||||
impl FromApub for Community {
|
||||
type ApubType = GroupExt;
|
||||
|
||||
/// Converts a `Group` to `Community`.
|
||||
async fn from_apub(
|
||||
group: &GroupExt,
|
||||
context: &LemmyContext,
|
||||
expected_domain: Option<Url>,
|
||||
request_counter: &mut i32,
|
||||
) -> Result<Community, LemmyError> {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait::async_trait(?Send)]
|
||||
impl FromApubToForm for CommunityForm {
|
||||
type ApubType = GroupExt;
|
||||
|
||||
async fn from_apub(
|
||||
|
|
|
@ -9,6 +9,8 @@ use anyhow::{anyhow, Context};
|
|||
use chrono::NaiveDateTime;
|
||||
use lemmy_utils::{location_info, utils::convert_datetime, LemmyError};
|
||||
use url::Url;
|
||||
use lemmy_websocket::LemmyContext;
|
||||
use lemmy_db::DbPool;
|
||||
|
||||
pub(crate) mod comment;
|
||||
pub(crate) mod community;
|
||||
|
@ -16,6 +18,46 @@ pub(crate) mod post;
|
|||
pub(crate) mod private_message;
|
||||
pub(crate) mod user;
|
||||
|
||||
/// Trait for converting an object or actor into the respective ActivityPub type.
|
||||
#[async_trait::async_trait(?Send)]
|
||||
pub(crate) trait ToApub {
|
||||
type ApubType;
|
||||
async fn to_apub(&self, pool: &DbPool) -> Result<Self::ApubType, LemmyError>;
|
||||
fn to_tombstone(&self) -> Result<Tombstone, LemmyError>;
|
||||
}
|
||||
|
||||
#[async_trait::async_trait(?Send)]
|
||||
pub(crate) trait FromApub {
|
||||
type ApubType;
|
||||
/// Converts an object from ActivityPub type to Lemmy internal type.
|
||||
///
|
||||
/// * `apub` The object to read from
|
||||
/// * `context` LemmyContext which holds DB pool, HTTP client etc
|
||||
/// * `expected_domain` If present, ensure that the domains of this and of the apub object ID are
|
||||
/// identical
|
||||
async fn from_apub(
|
||||
apub: &Self::ApubType,
|
||||
context: &LemmyContext,
|
||||
expected_domain: Option<Url>,
|
||||
request_counter: &mut i32,
|
||||
) -> Result<Self, LemmyError>
|
||||
where
|
||||
Self: Sized;
|
||||
}
|
||||
|
||||
#[async_trait::async_trait(?Send)]
|
||||
pub(in crate::objects) trait FromApubToForm {
|
||||
type ApubType;
|
||||
async fn from_apub(
|
||||
apub: &Self::ApubType,
|
||||
context: &LemmyContext,
|
||||
expected_domain: Option<Url>,
|
||||
request_counter: &mut i32,
|
||||
) -> Result<Self, LemmyError>
|
||||
where
|
||||
Self: Sized;
|
||||
}
|
||||
|
||||
/// Updated is actually the deletion time
|
||||
fn create_tombstone<T>(
|
||||
deleted: bool,
|
||||
|
|
|
@ -7,9 +7,7 @@ use crate::{
|
|||
get_source_markdown_value,
|
||||
set_content_and_source,
|
||||
},
|
||||
FromApub,
|
||||
PageExt,
|
||||
ToApub,
|
||||
};
|
||||
use activitystreams::{
|
||||
object::{kind::PageType, ApObject, Image, Page, Tombstone},
|
||||
|
@ -35,6 +33,7 @@ use lemmy_utils::{
|
|||
use lemmy_websocket::LemmyContext;
|
||||
use log::error;
|
||||
use url::Url;
|
||||
use crate::objects::{FromApubToForm, ToApub, FromApub};
|
||||
|
||||
#[async_trait::async_trait(?Send)]
|
||||
impl ToApub for Post {
|
||||
|
@ -98,12 +97,26 @@ impl ToApub for Post {
|
|||
}
|
||||
|
||||
#[async_trait::async_trait(?Send)]
|
||||
impl FromApub for PostForm {
|
||||
impl FromApub for Post {
|
||||
type ApubType = PageExt;
|
||||
|
||||
/// Converts a `PageExt` to `PostForm`.
|
||||
///
|
||||
/// If the post's community or creator are not known locally, these are also fetched.
|
||||
async fn from_apub(
|
||||
note: &PageExt,
|
||||
context: &LemmyContext,
|
||||
expected_domain: Option<Url>,
|
||||
request_counter: &mut i32,
|
||||
) -> Result<Post, LemmyError> {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait::async_trait(?Send)]
|
||||
impl FromApubToForm for PostForm {
|
||||
type ApubType = PageExt;
|
||||
|
||||
async fn from_apub(
|
||||
page: &PageExt,
|
||||
context: &LemmyContext,
|
||||
|
|
|
@ -8,10 +8,9 @@ use crate::{
|
|||
get_source_markdown_value,
|
||||
set_content_and_source,
|
||||
},
|
||||
FromApub,
|
||||
NoteExt,
|
||||
ToApub,
|
||||
};
|
||||
use crate::objects::{FromApubToForm, ToApub, FromApub};
|
||||
use activitystreams::{
|
||||
object::{kind::NoteType, ApObject, Note, Tombstone},
|
||||
prelude::*,
|
||||
|
@ -63,7 +62,21 @@ impl ToApub for PrivateMessage {
|
|||
}
|
||||
|
||||
#[async_trait::async_trait(?Send)]
|
||||
impl FromApub for PrivateMessageForm {
|
||||
impl FromApub for PrivateMessage {
|
||||
type ApubType = NoteExt;
|
||||
|
||||
async fn from_apub(
|
||||
note: &NoteExt,
|
||||
context: &LemmyContext,
|
||||
expected_domain: Option<Url>,
|
||||
request_counter: &mut i32,
|
||||
) -> Result<PrivateMessage, LemmyError> {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait::async_trait(?Send)]
|
||||
impl FromApubToForm for PrivateMessageForm {
|
||||
type ApubType = NoteExt;
|
||||
|
||||
async fn from_apub(
|
||||
|
|
|
@ -2,10 +2,9 @@ use crate::{
|
|||
extensions::context::lemmy_context,
|
||||
objects::{check_object_domain, get_source_markdown_value, set_content_and_source},
|
||||
ActorType,
|
||||
FromApub,
|
||||
PersonExt,
|
||||
ToApub,
|
||||
};
|
||||
use crate::objects::{FromApubToForm, ToApub, FromApub};
|
||||
use activitystreams::{
|
||||
actor::{ApActor, Endpoints, Person},
|
||||
object::{ApObject, Image, Tombstone},
|
||||
|
@ -81,7 +80,21 @@ impl ToApub for User_ {
|
|||
}
|
||||
|
||||
#[async_trait::async_trait(?Send)]
|
||||
impl FromApub for UserForm {
|
||||
impl FromApub for User_ {
|
||||
type ApubType = PersonExt;
|
||||
|
||||
async fn from_apub(
|
||||
note: &PersonExt,
|
||||
context: &LemmyContext,
|
||||
expected_domain: Option<Url>,
|
||||
request_counter: &mut i32,
|
||||
) -> Result<User_, LemmyError> {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait::async_trait(?Send)]
|
||||
impl FromApubToForm for UserForm {
|
||||
type ApubType = PersonExt;
|
||||
|
||||
async fn from_apub(
|
||||
|
|
Loading…
Reference in a new issue