implemented some more

This commit is contained in:
Felix Ableitner 2021-06-24 03:21:05 +02:00
parent d24f274cb7
commit b605057e85
9 changed files with 167 additions and 167 deletions

View File

@ -1,6 +1,6 @@
use crate::activities::receive::get_actor_as_person;
use activitystreams::{
activity::{ActorAndObjectRefExt, Create, Dislike, Like, Update},
activity::{ActorAndObjectRefExt, Dislike, Like, Update},
base::ExtendsExt,
};
use anyhow::Context;
@ -15,71 +15,6 @@ use lemmy_db_views::comment_view::CommentView;
use lemmy_utils::{location_info, utils::scrape_text_for_mentions, LemmyError};
use lemmy_websocket::{messages::SendComment, LemmyContext, UserOperation, UserOperationCrud};
// TODO:
// - define traits for all activity types
// - implement inbox routing with these traits
// - replace context with actix style Data struct (actix_web::web::Data)
pub(crate) trait ReceiveCreate {
fn receive_create(self, create: Create, context: LemmyContext, request_counter: &mut i32);
}
impl ReceiveCreate for Comment {
fn receive_create(self, _create: Create, _context: LemmyContext, _request_counter: &mut i32) {
unimplemented!()
}
}
pub(crate) async fn receive_create_comment(
create: Create,
context: &LemmyContext,
request_counter: &mut i32,
) -> Result<(), LemmyError> {
let person = get_actor_as_person(&create, context, request_counter).await?;
let note = NoteExt::from_any_base(create.object().to_owned().one().context(location_info!())?)?
.context(location_info!())?;
let comment =
Comment::from_apub(&note, context, person.actor_id(), request_counter, false).await?;
let post_id = comment.post_id;
let post = blocking(context.pool(), move |conn| Post::read(conn, post_id)).await??;
// Note:
// Although mentions could be gotten from the post tags (they are included there), or the ccs,
// Its much easier to scrape them from the comment body, since the API has to do that
// anyway.
let mentions = scrape_text_for_mentions(&comment.content);
let recipient_ids = send_local_notifs(
mentions,
comment.clone(),
person,
post,
context.pool(),
true,
)
.await?;
// Refetch the view
let comment_view = blocking(context.pool(), move |conn| {
CommentView::read(conn, comment.id, None)
})
.await??;
let res = CommentResponse {
comment_view,
recipient_ids,
form_id: None,
};
context.chat_server().do_send(SendComment {
op: UserOperationCrud::CreateComment,
comment: res,
websocket_id: None,
});
Ok(())
}
pub(crate) async fn receive_update_comment(
update: Update,
context: &LemmyContext,

View File

@ -1,6 +1,6 @@
use crate::activities::receive::verify_activity_domains_valid;
use activitystreams::{
activity::{ActorAndObjectRefExt, Create, Delete, Undo, Update},
activity::{ActorAndObjectRefExt, Delete, Undo, Update},
base::{AsBase, ExtendsExt},
object::AsObject,
public,
@ -21,54 +21,6 @@ use lemmy_utils::{location_info, LemmyError};
use lemmy_websocket::{messages::SendUserRoomMessage, LemmyContext, UserOperationCrud};
use url::Url;
pub(crate) async fn receive_create_private_message(
context: &LemmyContext,
create: Create,
expected_domain: Url,
request_counter: &mut i32,
) -> Result<(), LemmyError> {
check_private_message_activity_valid(&create, context, request_counter).await?;
let note = NoteExt::from_any_base(
create
.object()
.as_one()
.context(location_info!())?
.to_owned(),
)?
.context(location_info!())?;
let private_message =
PrivateMessage::from_apub(&note, context, expected_domain, request_counter, false).await?;
let message = blocking(&context.pool(), move |conn| {
PrivateMessageView::read(conn, private_message.id)
})
.await??;
let res = PrivateMessageResponse {
private_message_view: message,
};
// Send notifications to the local recipient, if one exists
let recipient_id = res.private_message_view.recipient.id;
let local_recipient_id = blocking(context.pool(), move |conn| {
LocalUserView::read_person(conn, recipient_id)
})
.await??
.local_user
.id;
context.chat_server().do_send(SendUserRoomMessage {
op: UserOperationCrud::CreatePrivateMessage,
response: res,
local_recipient_id,
websocket_id: None,
});
Ok(())
}
pub(crate) async fn receive_update_private_message(
context: &LemmyContext,
update: Update,

View File

@ -0,0 +1,74 @@
use crate::inbox::new_inbox_routing::{ReceiveActivity, Activity, PublicUrl};
use url::Url;
use lemmy_apub::NoteExt;
use activitystreams::
activity::kind::{CreateType};
use lemmy_websocket::{LemmyContext, UserOperationCrud};
use lemmy_utils::LemmyError;
use lemmy_db_views::comment_view::CommentView;
use lemmy_api_common::comment::CommentResponse;
use lemmy_websocket::messages::SendComment;
use lemmy_api_common::{send_local_notifs, blocking};
use lemmy_db_schema::source::comment::Comment;
use lemmy_apub::objects::FromApub;
use lemmy_utils::utils::scrape_text_for_mentions;
use lemmy_db_schema::source::post::Post;
use lemmy_db_queries::Crud;
use lemmy_apub::fetcher::person::get_or_fetch_and_upsert_person;
#[derive(Clone, Debug, serde::Deserialize, serde::Serialize)]
#[serde(rename_all = "camelCase")]
pub struct CreateComment {
actor: Url,
to: PublicUrl,
object: NoteExt,
#[serde(rename = "type")]
kind: CreateType,
}
#[async_trait::async_trait(?Send)]
impl ReceiveActivity for Activity<CreateComment> {
async fn receive(&self, context: &LemmyContext, request_counter: &mut i32) -> Result<(), LemmyError> {
let comment =
Comment::from_apub(&self.inner.object, context, self.inner.actor.clone(), request_counter, false).await?;
let post_id = comment.post_id;
let post = blocking(context.pool(), move |conn| Post::read(conn, post_id)).await??;
let actor = get_or_fetch_and_upsert_person(&self.inner.actor, context, request_counter).await?;
// Note:
// Although mentions could be gotten from the post tags (they are included there), or the ccs,
// Its much easier to scrape them from the comment body, since the API has to do that
// anyway.
let mentions = scrape_text_for_mentions(&comment.content);
let recipient_ids = send_local_notifs(
mentions,
comment.clone(),
actor,
post,
context.pool(),
true,
)
.await?;
// Refetch the view
let comment_view = blocking(context.pool(), move |conn| {
CommentView::read(conn, comment.id, None)
})
.await??;
let res = CommentResponse {
comment_view,
recipient_ids,
form_id: None,
};
context.chat_server().do_send(SendComment {
op: UserOperationCrud::CreateComment,
comment: res,
websocket_id: None,
});
Ok(())
}
}

View File

@ -1,12 +1,9 @@
use crate::{
activities::receive::verify_activity_domains_valid,
inbox::new_inbox_routing::{verify_domains_match, Activity, ReceiveActivity},
};
use activitystreams::{
activity::kind::{AcceptType, FollowType},
base::ExtendsExt,
};
use anyhow::Context;
use lemmy_api_common::blocking;
use lemmy_apub::fetcher::{
community::get_or_fetch_and_upsert_community,
@ -14,14 +11,13 @@ use lemmy_apub::fetcher::{
};
use lemmy_db_queries::Followable;
use lemmy_db_schema::source::community::CommunityFollower;
use lemmy_utils::{location_info, LemmyError};
use lemmy_utils::{LemmyError};
use lemmy_websocket::LemmyContext;
use url::Url;
#[derive(Clone, Debug, serde::Deserialize, serde::Serialize)]
#[serde(rename_all = "camelCase")]
pub struct Follow {
// todo: implement newtypes PersonUrl, GroupUrl etc (with deref function)
actor: Url,
to: Url,
object: Url,
@ -33,8 +29,8 @@ pub struct Follow {
impl ReceiveActivity for Activity<Follow> {
async fn receive(
&self,
context: &LemmyContext,
request_counter: &mut i32,
_context: &LemmyContext,
_request_counter: &mut i32,
) -> Result<(), LemmyError> {
println!("receive follow");
todo!()
@ -44,7 +40,6 @@ impl ReceiveActivity for Activity<Follow> {
#[derive(Clone, Debug, serde::Deserialize, serde::Serialize)]
#[serde(rename_all = "camelCase")]
pub struct Accept {
// todo: implement newtypes PersonUrl, GroupUrl etc (with deref function)
actor: Url,
to: Url,
object: Activity<Follow>,
@ -60,6 +55,7 @@ impl ReceiveActivity for Activity<Accept> {
context: &LemmyContext,
request_counter: &mut i32,
) -> Result<(), LemmyError> {
// TODO: move check for id.domain == actor.domain to library and do it automatically
verify_domains_match(&self.inner.actor, self.id_unchecked())?;
let follow = &self.inner.object;
verify_domains_match(&follow.inner.actor, &follow.id_unchecked())?;

View File

@ -1 +1,3 @@
pub mod comment;
pub mod follow;
pub mod private_message;

View File

@ -0,0 +1,64 @@
use crate::inbox::new_inbox_routing::{Activity, ReceiveActivity};
use activitystreams::activity::kind::CreateType;
use lemmy_api_common::{blocking, person::PrivateMessageResponse};
use lemmy_apub::{objects::FromApub, NoteExt};
use lemmy_db_schema::source::private_message::PrivateMessage;
use lemmy_db_views::{local_user_view::LocalUserView, private_message_view::PrivateMessageView};
use lemmy_utils::LemmyError;
use lemmy_websocket::{messages::SendUserRoomMessage, LemmyContext, UserOperationCrud};
use url::Url;
#[derive(Clone, Debug, serde::Deserialize, serde::Serialize)]
#[serde(rename_all = "camelCase")]
pub struct CreatePrivateMessage {
actor: Url,
to: Url,
object: NoteExt,
#[serde(rename = "type")]
kind: CreateType,
}
#[async_trait::async_trait(?Send)]
impl ReceiveActivity for Activity<CreatePrivateMessage> {
async fn receive(
&self,
context: &LemmyContext,
request_counter: &mut i32,
) -> Result<(), LemmyError> {
let private_message = PrivateMessage::from_apub(
&self.inner.object,
context,
self.inner.actor.clone(),
request_counter,
false,
)
.await?;
let message = blocking(&context.pool(), move |conn| {
PrivateMessageView::read(conn, private_message.id)
})
.await??;
let res = PrivateMessageResponse {
private_message_view: message,
};
// Send notifications to the local recipient, if one exists
let recipient_id = res.private_message_view.recipient.id;
let local_recipient_id = blocking(context.pool(), move |conn| {
LocalUserView::read_person(conn, recipient_id)
})
.await??
.local_user
.id;
context.chat_server().do_send(SendUserRoomMessage {
op: UserOperationCrud::CreatePrivateMessage,
response: res,
local_recipient_id,
websocket_id: None,
});
Ok(())
}
}

View File

@ -9,6 +9,8 @@ use lemmy_utils::LemmyError;
use lemmy_websocket::LemmyContext;
use std::marker::PhantomData;
use url::Url;
use crate::activities_new::private_message::CreatePrivateMessage;
use crate::activities_new::comment::CreateComment;
// for now, limit it to activity routing only, no http sigs, parsing or any of that
// need to route in this order:
@ -24,16 +26,22 @@ use url::Url;
// .checkHttpSig::<RequestType>()
// .fetchObject() - for custom http client
// .checkActivity() - for common validity checks
struct InboxConfig {
pub struct InboxConfig {
//actors: Vec<ActorConfig>,
}
impl InboxConfig {
fn shared_inbox_handler() {
pub fn shared_inbox_handler() {
todo!()
}
}
#[derive(Debug, Clone, serde::Deserialize, serde::Serialize)]
pub enum PublicUrl {
#[serde(rename = "https://www.w3.org/ns/activitystreams#Public")]
Public,
}
pub fn verify_domains_match(a: &Url, b: &Url) -> Result<(), LemmyError> {
if a.domain() != b.domain() {
return Err(DomainError.into());
@ -94,6 +102,8 @@ impl<Kind> Activity<Kind> {
#[derive(Clone, Debug, serde::Deserialize, serde::Serialize)]
pub enum PersonAcceptedActivitiesNew {
Accept(Accept),
CreatePrivateMessage(CreatePrivateMessage),
CreateComment(CreateComment)
}
// todo: there should be a better way to do this (maybe needs a derive macro)
@ -104,7 +114,6 @@ impl ReceiveActivity for PersonAcceptedActivitiesNew {
context: &LemmyContext,
request_counter: &mut i32,
) -> Result<(), LemmyError> {
use PersonAcceptedActivitiesNew::*;
self.receive(context, request_counter).await
}
}

View File

@ -1,6 +1,6 @@
use crate::{
activities::receive::{
comment::{receive_create_comment, receive_update_comment},
comment::receive_update_comment,
community::{
receive_delete_community,
receive_remove_community,
@ -8,7 +8,6 @@ use crate::{
receive_undo_remove_community,
},
private_message::{
receive_create_private_message,
receive_delete_private_message,
receive_undo_delete_private_message,
receive_update_private_message,
@ -17,9 +16,6 @@ use crate::{
verify_activity_domains_valid,
},
inbox::{
assert_activity_not_local,
get_activity_id,
inbox_verify_http_signature,
is_activity_already_known,
is_addressed_to_community_followers,
is_addressed_to_local_person,
@ -39,7 +35,7 @@ use crate::{
},
};
use activitystreams::{
activity::{Accept, ActorAndObject, Announce, Create, Delete, Follow, Remove, Undo, Update},
activity::{ActorAndObject, Announce, Delete, Remove, Undo, Update},
base::AnyBase,
prelude::*,
};
@ -49,12 +45,10 @@ use diesel::NotFound;
use lemmy_api_common::blocking;
use lemmy_apub::{
check_is_apub_id_valid,
fetcher::community::get_or_fetch_and_upsert_community,
get_activity_to_and_cc,
insert_activity,
ActorType,
};
use lemmy_db_queries::{source::person::Person_, ApubObject, Followable};
use lemmy_db_queries::{ApubObject, Followable};
use lemmy_db_schema::source::{
community::{Community, CommunityFollower},
person::Person,
@ -85,14 +79,14 @@ pub type PersonAcceptedActivities = ActorAndObject<PersonValidTypes>;
/// Handler for all incoming activities to person inboxes.
pub async fn person_inbox(
request: HttpRequest,
_request: HttpRequest,
input: web::Json<Activity<PersonAcceptedActivitiesNew>>,
path: web::Path<String>,
_path: web::Path<String>,
context: web::Data<LemmyContext>,
) -> Result<HttpResponse, LemmyError> {
let activity = input.into_inner();
let request_counter = &mut 0;
activity.inner.receive(&context, request_counter);
activity.inner.receive(&context, request_counter).await?;
todo!()
/*
// First of all check the http signature
@ -134,7 +128,7 @@ pub async fn person_inbox(
/// Receives Accept/Follow, Announce, private messages and community (undo) remove, (undo) delete
pub(crate) async fn person_receive_message(
activity: PersonAcceptedActivities,
to_person: Option<Person>,
_to_person: Option<Person>,
actor: &dyn ActorType,
context: &LemmyContext,
request_counter: &mut i32,
@ -158,15 +152,7 @@ pub(crate) async fn person_receive_message(
PersonValidTypes::Announce => {
Box::pin(receive_announce(&context, any_base, actor, request_counter)).await?
}
PersonValidTypes::Create => {
Box::pin(receive_create(
&context,
any_base,
actor_url,
request_counter,
))
.await?
}
PersonValidTypes::Create => {}
PersonValidTypes::Update => {
Box::pin(receive_update(
&context,
@ -326,23 +312,6 @@ pub async fn receive_announce(
}
}
/// Receive either a new private message, or a new comment mention. We distinguish them by checking
/// whether the activity is public.
async fn receive_create(
context: &LemmyContext,
activity: AnyBase,
expected_domain: Url,
request_counter: &mut i32,
) -> Result<(), LemmyError> {
let create = Create::from_any_base(activity)?.context(location_info!())?;
verify_activity_domains_valid(&create, &expected_domain, true)?;
if verify_is_addressed_to_public(&create).is_ok() {
receive_create_comment(create, context, request_counter).await
} else {
receive_create_private_message(&context, create, expected_domain, request_counter).await
}
}
/// Receive either an updated private message, or an updated comment mention. We distinguish
/// them by checking whether the activity is public.
async fn receive_update(

View File

@ -1,7 +1,6 @@
use crate::{
activities::receive::{
comment::{
receive_create_comment,
receive_delete_comment,
receive_dislike_comment,
receive_like_comment,
@ -137,7 +136,7 @@ pub(in crate::inbox) async fn receive_create_for_community(
.and_then(|s| s.parse().ok());
match kind {
Some(ObjectTypes::Page) => receive_create_post(create, context, request_counter).await,
Some(ObjectTypes::Note) => receive_create_comment(create, context, request_counter).await,
Some(ObjectTypes::Note) => todo!(),
_ => receive_unhandled_activity(create),
}
}