-use activitystreams::public;
-
-use lemmy_api_common::{blocking, check_post_deleted_or_removed};
-use lemmy_apub_lib::{
- data::Data,
- traits::{ActivityHandler, ActorType, ApubObject},
- verify::verify_domains_match,
-};
-use lemmy_db_schema::{
- source::{community::Community, post::Post},
- traits::Crud,
-};
-use lemmy_utils::LemmyError;
-use lemmy_websocket::{send::send_comment_ws_message, LemmyContext, UserOperationCrud};
-
use crate::{
activities::{
check_community_deleted_or_removed,
objects::{comment::ApubComment, community::ApubCommunity, person::ApubPerson},
protocol::activities::{create_or_update::comment::CreateOrUpdateComment, CreateOrUpdateType},
};
+use activitystreams::public;
+use lemmy_api_common::{blocking, check_post_deleted_or_removed};
+use lemmy_apub_lib::{
+ data::Data,
+ traits::{ActivityHandler, ActorType, ApubObject},
+ verify::verify_domains_match,
+};
+use lemmy_db_schema::{
+ source::{community::Community, post::Post},
+ traits::Crud,
+};
+use lemmy_utils::LemmyError;
+use lemmy_websocket::{send::send_comment_ws_message, LemmyContext, UserOperationCrud};
impl CreateOrUpdateComment {
pub async fn send(
let post = self.object.get_parents(context, request_counter).await?.0;
let community = self.get_community(context, request_counter).await?;
- verify_activity(self, &context.settings())?;
+ verify_activity(&self.id, self.actor.inner(), &context.settings())?;
verify_person_in_community(&self.actor, &community, context, request_counter).await?;
verify_domains_match(self.actor.inner(), self.object.id.inner())?;
check_community_deleted_or_removed(&community)?;
request_counter: &mut i32,
) -> Result<(), LemmyError> {
verify_is_public(&self.to)?;
- verify_activity(self, &context.settings())?;
+ verify_activity(&self.id, self.actor.inner(), &context.settings())?;
let community = self.get_community(context, request_counter).await?;
verify_person_in_community(&self.actor, &community, context, request_counter).await?;
verify_mod_action(&self.actor, &community, context, request_counter).await?;
activities::{generate_activity_id, send_lemmy_activity, verify_activity, verify_is_public},
activity_lists::AnnouncableActivities,
fetcher::object_id::ObjectId,
- http::is_activity_already_known,
+ http::{is_activity_already_known, ActivityCommonFields},
insert_activity,
objects::community::ApubCommunity,
protocol::activities::community::announce::AnnounceActivity,
use activitystreams::{activity::kind::AnnounceType, public};
use lemmy_apub_lib::{
data::Data,
- traits::{ActivityFields, ActivityHandler, ActorType},
+ traits::{ActivityHandler, ActorType},
};
use lemmy_utils::LemmyError;
use lemmy_websocket::LemmyContext;
request_counter: &mut i32,
) -> Result<(), LemmyError> {
verify_is_public(&self.to)?;
- verify_activity(self, &context.settings())?;
+ verify_activity(&self.id, self.actor.inner(), &context.settings())?;
self.object.verify(context, request_counter).await?;
Ok(())
}
context: &Data<LemmyContext>,
request_counter: &mut i32,
) -> Result<(), LemmyError> {
- if is_activity_already_known(context.pool(), self.object.id_unchecked()).await? {
+ // TODO: this is pretty ugly, but i cant think of a much better way
+ let object = serde_json::to_string(&self.object)?;
+ let object_data: ActivityCommonFields = serde_json::from_str(&object)?;
+
+ if is_activity_already_known(context.pool(), &object_data.id).await? {
return Ok(());
}
insert_activity(
- self.object.id_unchecked(),
+ &object_data.id,
self.object.clone(),
false,
true,
request_counter: &mut i32,
) -> Result<(), LemmyError> {
verify_is_public(&self.to)?;
- verify_activity(self, &context.settings())?;
+ verify_activity(&self.id, self.actor.inner(), &context.settings())?;
let community = self.get_community(context, request_counter).await?;
verify_person_in_community(&self.actor, &community, context, request_counter).await?;
verify_mod_action(&self.actor, &community, context, request_counter).await?;
request_counter: &mut i32,
) -> Result<(), LemmyError> {
verify_is_public(&self.to)?;
- verify_activity(self, &context.settings())?;
+ verify_activity(&self.id, self.actor.inner(), &context.settings())?;
let community = self.get_community(context, request_counter).await?;
verify_person_in_community(&self.actor, &community, context, request_counter).await?;
verify_mod_action(&self.actor, &community, context, request_counter).await?;
+use crate::{
+ activities::{
+ generate_activity_id,
+ send_lemmy_activity,
+ verify_activity,
+ verify_person_in_community,
+ },
+ fetcher::object_id::ObjectId,
+ objects::{community::ApubCommunity, person::ApubPerson},
+ protocol::activities::community::report::Report,
+ PostOrComment,
+};
use activitystreams::activity::kind::FlagType;
-
use lemmy_api_common::{blocking, comment::CommentReportResponse, post::PostReportResponse};
use lemmy_apub_lib::{
data::Data,
use lemmy_utils::LemmyError;
use lemmy_websocket::{messages::SendModRoomMessage, LemmyContext, UserOperation};
-use crate::{
- activities::{
- generate_activity_id,
- send_lemmy_activity,
- verify_activity,
- verify_person_in_community,
- },
- fetcher::object_id::ObjectId,
- objects::{community::ApubCommunity, person::ApubPerson},
- protocol::activities::community::report::Report,
- PostOrComment,
-};
-
impl Report {
pub async fn send(
object_id: ObjectId<PostOrComment>,
context: &Data<LemmyContext>,
request_counter: &mut i32,
) -> Result<(), LemmyError> {
- verify_activity(self, &context.settings())?;
+ verify_activity(&self.id, self.actor.inner(), &context.settings())?;
let community = self.to[0].dereference(context, request_counter).await?;
verify_person_in_community(&self.actor, &community, context, request_counter).await?;
Ok(())
request_counter: &mut i32,
) -> Result<(), LemmyError> {
verify_is_public(&self.to)?;
- verify_activity(self, &context.settings())?;
+ verify_activity(&self.id, self.actor.inner(), &context.settings())?;
let community = self.get_community(context, request_counter).await?;
verify_person_in_community(&self.actor, &community, context, request_counter).await?;
verify_mod_action(&self.actor, &community, context, request_counter).await?;
request_counter: &mut i32,
) -> Result<(), LemmyError> {
verify_is_public(&self.to)?;
- verify_activity(self, &context.settings())?;
+ verify_activity(&self.id, self.actor.inner(), &context.settings())?;
let community = self.get_community(context, request_counter).await?;
verify_person_in_community(&self.actor, &community, context, request_counter).await?;
verify_mod_action(&self.actor, &community, context, request_counter).await?;
+use crate::{
+ activities::{
+ community::{announce::GetCommunity, send_to_community},
+ deletion::{
+ receive_delete_action,
+ verify_delete_activity,
+ DeletableObjects,
+ },
+ generate_activity_id,
+ verify_activity,
+ verify_is_public,
+ },
+ activity_lists::AnnouncableActivities,
+ fetcher::object_id::ObjectId,
+ objects::{community::ApubCommunity, person::ApubPerson},
+ protocol::activities::deletion::delete::Delete,
+};
use activitystreams::{activity::kind::DeleteType, public};
use anyhow::anyhow;
-use url::Url;
-
use lemmy_api_common::blocking;
use lemmy_apub_lib::{
data::Data,
LemmyContext,
UserOperationCrud,
};
-
-use crate::{
- activities::{
- community::{announce::GetCommunity, send_to_community},
- deletion::{receive_delete_action, verify_delete_activity, DeletableObjects},
- generate_activity_id,
- verify_activity,
- verify_is_public,
- },
- activity_lists::AnnouncableActivities,
- fetcher::object_id::ObjectId,
- objects::{community::ApubCommunity, person::ApubPerson},
- protocol::activities::deletion::delete::Delete,
-};
+use url::Url;
#[async_trait::async_trait(?Send)]
impl ActivityHandler for Delete {
request_counter: &mut i32,
) -> Result<(), LemmyError> {
verify_is_public(&self.to)?;
- verify_activity(self, &context.settings())?;
+ verify_activity(&self.id, self.actor.inner(), &context.settings())?;
let community = self.get_community(context, request_counter).await?;
verify_delete_activity(
&self.object,
- self,
+ &self.actor,
&community,
self.summary.is_some(),
context,
-use url::Url;
-
+use crate::{
+ activities::{verify_mod_action, verify_person_in_community},
+ fetcher::object_id::ObjectId,
+ objects::{comment::ApubComment, community::ApubCommunity, person::ApubPerson, post::ApubPost},
+ protocol::activities::deletion::{delete::Delete, undo_delete::UndoDelete},
+};
use lemmy_api_common::blocking;
use lemmy_apub_lib::{
- traits::{ActivityFields, ActorType, ApubObject},
+ traits::{ActorType, ApubObject},
verify::verify_domains_match,
};
use lemmy_db_schema::source::{comment::Comment, community::Community, post::Post};
LemmyContext,
UserOperationCrud,
};
-
-use crate::{
- activities::{verify_mod_action, verify_person_in_community},
- fetcher::object_id::ObjectId,
- objects::{comment::ApubComment, community::ApubCommunity, person::ApubPerson, post::ApubPost},
- protocol::activities::deletion::{delete::Delete, undo_delete::UndoDelete},
-};
+use url::Url;
pub mod delete;
pub mod undo_delete;
pub(in crate::activities) async fn verify_delete_activity(
object: &Url,
- activity: &dyn ActivityFields,
+ actor: &ObjectId<ApubPerson>,
community: &ApubCommunity,
is_mod_action: bool,
context: &LemmyContext,
request_counter: &mut i32,
) -> Result<(), LemmyError> {
let object = DeletableObjects::read_from_db(object, context).await?;
- let actor = ObjectId::new(activity.actor().clone());
match object {
DeletableObjects::Community(community) => {
if community.local {
// can only do this check for local community, in remote case it would try to fetch the
// deleted community (which fails)
- verify_person_in_community(&actor, &community, context, request_counter).await?;
+ verify_person_in_community(actor, &community, context, request_counter).await?;
}
// community deletion is always a mod (or admin) action
- verify_mod_action(&actor, &community, context, request_counter).await?;
+ verify_mod_action(actor, &community, context, request_counter).await?;
}
DeletableObjects::Post(p) => {
verify_delete_activity_post_or_comment(
- activity,
+ actor,
&p.ap_id.clone().into(),
community,
is_mod_action,
}
DeletableObjects::Comment(c) => {
verify_delete_activity_post_or_comment(
- activity,
+ actor,
&c.ap_id.clone().into(),
community,
is_mod_action,
}
async fn verify_delete_activity_post_or_comment(
- activity: &dyn ActivityFields,
+ actor: &ObjectId<ApubPerson>,
object_id: &Url,
community: &ApubCommunity,
is_mod_action: bool,
context: &LemmyContext,
request_counter: &mut i32,
) -> Result<(), LemmyError> {
- let actor = ObjectId::new(activity.actor().clone());
- verify_person_in_community(&actor, community, context, request_counter).await?;
+ verify_person_in_community(actor, community, context, request_counter).await?;
if is_mod_action {
- verify_mod_action(&actor, community, context, request_counter).await?;
+ verify_mod_action(actor, community, context, request_counter).await?;
} else {
// domain of post ap_id and post.creator ap_id are identical, so we just check the former
- verify_domains_match(activity.actor(), object_id)?;
+ verify_domains_match(actor.inner(), object_id)?;
}
Ok(())
}
+use crate::{
+ activities::{
+ community::{announce::GetCommunity, send_to_community},
+ deletion::{receive_delete_action, verify_delete_activity, DeletableObjects},
+ generate_activity_id,
+ verify_activity,
+ verify_is_public,
+ },
+ activity_lists::AnnouncableActivities,
+ fetcher::object_id::ObjectId,
+ objects::{community::ApubCommunity, person::ApubPerson},
+ protocol::activities::deletion::{delete::Delete, undo_delete::UndoDelete},
+};
use activitystreams::{activity::kind::UndoType, public};
use anyhow::anyhow;
-use url::Url;
-
use lemmy_api_common::blocking;
use lemmy_apub_lib::{
data::Data,
LemmyContext,
UserOperationCrud,
};
-
-use crate::{
- activities::{
- community::{announce::GetCommunity, send_to_community},
- deletion::{receive_delete_action, verify_delete_activity, DeletableObjects},
- generate_activity_id,
- verify_activity,
- verify_is_public,
- },
- activity_lists::AnnouncableActivities,
- fetcher::object_id::ObjectId,
- objects::{community::ApubCommunity, person::ApubPerson},
- protocol::activities::deletion::{delete::Delete, undo_delete::UndoDelete},
-};
+use url::Url;
#[async_trait::async_trait(?Send)]
impl ActivityHandler for UndoDelete {
request_counter: &mut i32,
) -> Result<(), LemmyError> {
verify_is_public(&self.to)?;
- verify_activity(self, &context.settings())?;
+ verify_activity(&self.id, self.actor.inner(), &context.settings())?;
self.object.verify(context, request_counter).await?;
let community = self.get_community(context, request_counter).await?;
verify_delete_activity(
&self.object.object,
- self,
+ &self.actor,
&community,
self.object.summary.is_some(),
context,
use lemmy_api_common::blocking;
use lemmy_apub_lib::{
data::Data,
- traits::{ActivityFields, ActivityHandler, ActorType},
+ traits::{ActivityHandler, ActorType},
verify::verify_urls_match,
};
use lemmy_db_schema::{source::community::CommunityFollower, traits::Followable};
context: &Data<LemmyContext>,
request_counter: &mut i32,
) -> Result<(), LemmyError> {
- verify_activity(self, &context.settings())?;
- verify_urls_match(self.to[0].inner(), self.object.actor())?;
- verify_urls_match(self.actor(), self.object.to[0].inner())?;
+ verify_activity(&self.id, self.actor.inner(), &context.settings())?;
+ verify_urls_match(self.to[0].inner(), self.object.actor.inner())?;
+ verify_urls_match(self.actor.inner(), self.object.to[0].inner())?;
self.object.verify(context, request_counter).await?;
Ok(())
}
context: &Data<LemmyContext>,
request_counter: &mut i32,
) -> Result<(), LemmyError> {
- verify_activity(self, &context.settings())?;
+ verify_activity(&self.id, self.actor.inner(), &context.settings())?;
verify_urls_match(self.to[0].inner(), self.object.inner())?;
verify_person(&self.actor, context, request_counter).await?;
let community = self.to[0].dereference(context, request_counter).await?;
use lemmy_api_common::blocking;
use lemmy_apub_lib::{
data::Data,
- traits::{ActivityFields, ActivityHandler, ActorType},
+ traits::{ActivityHandler, ActorType},
verify::verify_urls_match,
};
use lemmy_db_schema::{
context: &Data<LemmyContext>,
request_counter: &mut i32,
) -> Result<(), LemmyError> {
- verify_activity(self, &context.settings())?;
+ verify_activity(&self.id, self.actor.inner(), &context.settings())?;
verify_urls_match(self.to[0].inner(), self.object.object.inner())?;
- verify_urls_match(self.actor(), self.object.actor())?;
+ verify_urls_match(self.actor.inner(), self.object.actor.inner())?;
verify_person(&self.actor, context, request_counter).await?;
self.object.verify(context, request_counter).await?;
Ok(())
use lemmy_api_common::blocking;
use lemmy_apub_lib::{
activity_queue::send_activity,
- traits::{ActivityFields, ActorType},
+ traits::ActorType,
verify::verify_domains_match,
};
use lemmy_db_schema::source::community::Community;
Ok(())
}
-fn verify_activity(activity: &dyn ActivityFields, settings: &Settings) -> Result<(), LemmyError> {
- check_is_apub_id_valid(activity.actor(), false, settings)?;
- verify_domains_match(activity.id_unchecked(), activity.actor())?;
+fn verify_activity(id: &Url, actor: &Url, settings: &Settings) -> Result<(), LemmyError> {
+ check_is_apub_id_valid(actor, false, settings)?;
+ verify_domains_match(id, actor)?;
Ok(())
}
-use activitystreams::public;
-use anyhow::anyhow;
-
-use lemmy_api_common::blocking;
-use lemmy_apub_lib::{
- data::Data,
- traits::{ActivityFields, ActivityHandler, ActorType, ApubObject},
- verify::{verify_domains_match, verify_urls_match},
-};
-use lemmy_db_schema::{source::community::Community, traits::Crud};
-use lemmy_utils::LemmyError;
-use lemmy_websocket::{send::send_post_ws_message, LemmyContext, UserOperationCrud};
-
use crate::{
activities::{
check_community_deleted_or_removed,
objects::{community::ApubCommunity, person::ApubPerson, post::ApubPost},
protocol::activities::{create_or_update::post::CreateOrUpdatePost, CreateOrUpdateType},
};
+use activitystreams::public;
+use anyhow::anyhow;
+use lemmy_api_common::blocking;
+use lemmy_apub_lib::{
+ data::Data,
+ traits::{ActivityHandler, ActorType, ApubObject},
+ verify::{verify_domains_match, verify_urls_match},
+};
+use lemmy_db_schema::{source::community::Community, traits::Crud};
+use lemmy_utils::LemmyError;
+use lemmy_websocket::{send::send_post_ws_message, LemmyContext, UserOperationCrud};
impl CreateOrUpdatePost {
pub(crate) async fn new(
request_counter: &mut i32,
) -> Result<(), LemmyError> {
verify_is_public(&self.to)?;
- verify_activity(self, &context.settings())?;
+ verify_activity(&self.id, self.actor.inner(), &context.settings())?;
let community = self.get_community(context, request_counter).await?;
verify_person_in_community(&self.actor, &community, context, request_counter).await?;
check_community_deleted_or_removed(&community)?;
match self.kind {
CreateOrUpdateType::Create => {
verify_domains_match(self.actor.inner(), self.object.id.inner())?;
- verify_urls_match(self.actor(), self.object.attributed_to.inner())?;
+ verify_urls_match(self.actor.inner(), self.object.attributed_to.inner())?;
// Check that the post isnt locked or stickied, as that isnt possible for newly created posts.
// However, when fetching a remote post we generate a new create activity with the current
// locked/stickied value, so this check may fail. So only check if its a local community,
verify_mod_action(&self.actor, &community, context, request_counter).await?;
} else {
verify_domains_match(self.actor.inner(), self.object.id.inner())?;
- verify_urls_match(self.actor(), self.object.attributed_to.inner())?;
+ verify_urls_match(self.actor.inner(), self.object.attributed_to.inner())?;
}
}
}
context: &Data<LemmyContext>,
request_counter: &mut i32,
) -> Result<(), LemmyError> {
- verify_activity(self, &context.settings())?;
+ verify_activity(&self.id, self.actor.inner(), &context.settings())?;
verify_person(&self.actor, context, request_counter).await?;
verify_domains_match(self.actor.inner(), self.object.id.inner())?;
self.object.verify(context, request_counter).await?;
context: &Data<LemmyContext>,
request_counter: &mut i32,
) -> Result<(), LemmyError> {
- verify_activity(self, &context.settings())?;
+ verify_activity(&self.id, self.actor.inner(), &context.settings())?;
verify_person(&self.actor, context, request_counter).await?;
verify_domains_match(self.actor.inner(), self.object.inner())?;
Ok(())
use lemmy_api_common::blocking;
use lemmy_apub_lib::{
data::Data,
- traits::{ActivityFields, ActivityHandler, ActorType},
+ traits::{ActivityHandler, ActorType},
verify::{verify_domains_match, verify_urls_match},
};
use lemmy_db_schema::{
context: &Data<LemmyContext>,
request_counter: &mut i32,
) -> Result<(), LemmyError> {
- verify_activity(self, &context.settings())?;
+ verify_activity(&self.id, self.actor.inner(), &context.settings())?;
verify_person(&self.actor, context, request_counter).await?;
- verify_urls_match(self.actor(), self.object.actor())?;
- verify_domains_match(self.actor(), self.object.object.inner())?;
+ verify_urls_match(self.actor.inner(), self.object.actor.inner())?;
+ verify_domains_match(self.actor.inner(), self.object.object.inner())?;
self.object.verify(context, request_counter).await?;
Ok(())
}
-use std::ops::Deref;
-
-use activitystreams::{activity::kind::UndoType, public};
-
-use lemmy_api_common::blocking;
-use lemmy_apub_lib::{
- data::Data,
- traits::{ActivityFields, ActivityHandler, ActorType},
- verify::verify_urls_match,
-};
-use lemmy_db_schema::{newtypes::CommunityId, source::community::Community, traits::Crud};
-use lemmy_utils::LemmyError;
-use lemmy_websocket::LemmyContext;
-
use crate::{
activities::{
community::{announce::GetCommunity, send_to_community},
},
PostOrComment,
};
+use activitystreams::{activity::kind::UndoType, public};
+use lemmy_api_common::blocking;
+use lemmy_apub_lib::{
+ data::Data,
+ traits::{ActivityHandler, ActorType},
+ verify::verify_urls_match,
+};
+use lemmy_db_schema::{newtypes::CommunityId, source::community::Community, traits::Crud};
+use lemmy_utils::LemmyError;
+use lemmy_websocket::LemmyContext;
+use std::ops::Deref;
impl UndoVote {
pub async fn send(
request_counter: &mut i32,
) -> Result<(), LemmyError> {
verify_is_public(&self.to)?;
- verify_activity(self, &context.settings())?;
+ verify_activity(&self.id, self.actor.inner(), &context.settings())?;
let community = self.get_community(context, request_counter).await?;
verify_person_in_community(&self.actor, &community, context, request_counter).await?;
- verify_urls_match(self.actor(), self.object.actor())?;
+ verify_urls_match(self.actor.inner(), self.object.actor.inner())?;
self.object.verify(context, request_counter).await?;
Ok(())
}
-use std::ops::Deref;
-
-use activitystreams::public;
-
-use lemmy_api_common::blocking;
-use lemmy_apub_lib::{
- data::Data,
- traits::{ActivityHandler, ActorType},
-};
-use lemmy_db_schema::{
- newtypes::CommunityId,
- source::{community::Community, post::Post},
- traits::Crud,
-};
-use lemmy_utils::LemmyError;
-use lemmy_websocket::LemmyContext;
-
use crate::{
activities::{
community::{announce::GetCommunity, send_to_community},
protocol::activities::voting::vote::{Vote, VoteType},
PostOrComment,
};
+use activitystreams::public;
+use lemmy_api_common::blocking;
+use lemmy_apub_lib::{
+ data::Data,
+ traits::{ActivityHandler, ActorType},
+};
+use lemmy_db_schema::{
+ newtypes::CommunityId,
+ source::{community::Community, post::Post},
+ traits::Crud,
+};
+use lemmy_utils::LemmyError;
+use lemmy_websocket::LemmyContext;
+use std::ops::Deref;
impl Vote {
pub(in crate::activities::voting) fn new(
request_counter: &mut i32,
) -> Result<(), LemmyError> {
verify_is_public(&self.to)?;
- verify_activity(self, &context.settings())?;
+ verify_activity(&self.id, self.actor.inner(), &context.settings())?;
let community = self.get_community(context, request_counter).await?;
verify_person_in_community(&self.actor, &community, context, request_counter).await?;
Ok(())
voting::{undo_vote::UndoVote, vote::Vote},
},
};
-use lemmy_apub_lib::traits::{ActivityFields, ActivityHandler};
+use lemmy_apub_lib::traits::ActivityHandler;
use lemmy_utils::LemmyError;
use lemmy_websocket::LemmyContext;
use serde::{Deserialize, Serialize};
-#[derive(Clone, Debug, Deserialize, Serialize, ActivityHandler, ActivityFields)]
+#[derive(Clone, Debug, Deserialize, Serialize, ActivityHandler)]
#[serde(untagged)]
#[activity_handler(LemmyContext)]
pub enum SharedInboxActivities {
PersonInboxActivities(PersonInboxActivities),
}
-#[derive(Clone, Debug, Deserialize, Serialize, ActivityHandler, ActivityFields)]
+#[derive(Clone, Debug, Deserialize, Serialize, ActivityHandler)]
#[serde(untagged)]
#[activity_handler(LemmyContext)]
pub enum GroupInboxActivities {
Report(Report),
}
-#[derive(Clone, Debug, Deserialize, Serialize, ActivityHandler, ActivityFields)]
+#[derive(Clone, Debug, Deserialize, Serialize, ActivityHandler)]
#[serde(untagged)]
#[activity_handler(LemmyContext)]
pub enum PersonInboxActivities {
AnnounceActivity(Box<AnnounceActivity>),
}
-#[derive(Clone, Debug, Deserialize, Serialize, ActivityHandler, ActivityFields)]
+#[derive(Clone, Debug, Deserialize, Serialize, ActivityHandler)]
#[serde(untagged)]
#[activity_handler(LemmyContext)]
pub enum AnnouncableActivities {
pub mod object_id;
pub mod post_or_comment;
pub mod search;
+pub mod user_or_community;
-use crate::{
- fetcher::object_id::ObjectId,
- objects::{community::ApubCommunity, person::ApubPerson},
-};
use chrono::NaiveDateTime;
-use lemmy_apub_lib::traits::ActorType;
use lemmy_db_schema::naive_now;
-use lemmy_utils::LemmyError;
-use lemmy_websocket::LemmyContext;
-use url::Url;
static ACTOR_REFETCH_INTERVAL_SECONDS: i64 = 24 * 60 * 60;
static ACTOR_REFETCH_INTERVAL_SECONDS_DEBUG: i64 = 10;
-/// Get a remote actor from its apub ID (either a person or a community). Thin wrapper around
-/// `get_or_fetch_and_upsert_person()` and `get_or_fetch_and_upsert_community()`.
-///
-/// If it exists locally and `!should_refetch_actor()`, it is returned directly from the database.
-/// Otherwise it is fetched from the remote instance, stored and returned.
-pub(crate) async fn get_or_fetch_and_upsert_actor(
- apub_id: Url,
- context: &LemmyContext,
- recursion_counter: &mut i32,
-) -> Result<Box<dyn ActorType>, LemmyError> {
- let community_id = ObjectId::<ApubCommunity>::new(apub_id.clone());
- let community = community_id.dereference(context, recursion_counter).await;
- let actor: Box<dyn ActorType> = match community {
- Ok(c) => Box::new(c),
- Err(_) => {
- let person_id = ObjectId::new(apub_id);
- let person: ApubPerson = person_id.dereference(context, recursion_counter).await?;
- Box::new(person)
- }
- };
- Ok(actor)
-}
-
/// Determines when a remote actor should be refetched from its instance. In release builds, this is
/// `ACTOR_REFETCH_INTERVAL_SECONDS` after the last refetch, in debug builds
/// `ACTOR_REFETCH_INTERVAL_SECONDS_DEBUG`.
-use chrono::NaiveDateTime;
-use serde::Deserialize;
-use url::Url;
-
-use lemmy_apub_lib::traits::ApubObject;
-use lemmy_db_schema::source::{comment::CommentForm, post::PostForm};
-use lemmy_utils::LemmyError;
-use lemmy_websocket::LemmyContext;
-
use crate::{
objects::{comment::ApubComment, post::ApubPost},
protocol::objects::{note::Note, page::Page},
};
+use chrono::NaiveDateTime;
+use lemmy_apub_lib::traits::ApubObject;
+use lemmy_utils::LemmyError;
+use lemmy_websocket::LemmyContext;
+use serde::Deserialize;
+use url::Url;
#[derive(Clone, Debug)]
pub enum PostOrComment {
Comment(ApubComment),
}
-pub enum PostOrCommentForm {
- PostForm(Box<PostForm>),
- CommentForm(CommentForm),
-}
-
#[derive(Deserialize)]
#[serde(untagged)]
pub enum PageOrNote {
async fn read_from_apub_id(
object_id: Url,
data: &Self::DataType,
- ) -> Result<Option<Self>, LemmyError>
- where
- Self: Sized,
- {
+ ) -> Result<Option<Self>, LemmyError> {
let post = ApubPost::read_from_apub_id(object_id.clone(), data).await?;
Ok(match post {
Some(o) => Some(PostOrComment::Post(Box::new(o))),
context: &LemmyContext,
expected_domain: &Url,
request_counter: &mut i32,
- ) -> Result<Self, LemmyError>
- where
- Self: Sized,
- {
+ ) -> Result<Self, LemmyError> {
Ok(match apub {
PageOrNote::Page(p) => PostOrComment::Post(Box::new(
ApubPost::from_apub(p, context, expected_domain, request_counter).await?,
--- /dev/null
+use crate::{
+ objects::{community::ApubCommunity, person::ApubPerson},
+ protocol::objects::{group::Group, person::Person},
+};
+use activitystreams::{chrono::NaiveDateTime, url::Url};
+use lemmy_apub_lib::traits::{ActorType, ApubObject};
+use lemmy_utils::LemmyError;
+use lemmy_websocket::LemmyContext;
+use serde::Deserialize;
+
+#[derive(Clone, Debug)]
+pub enum UserOrCommunity {
+ User(ApubPerson),
+ Community(ApubCommunity),
+}
+
+#[derive(Deserialize)]
+#[serde(untagged)]
+pub enum PersonOrGroup {
+ Person(Person),
+ Group(Group),
+}
+
+#[async_trait::async_trait(?Send)]
+impl ApubObject for UserOrCommunity {
+ type DataType = LemmyContext;
+ type ApubType = PersonOrGroup;
+ type TombstoneType = ();
+
+ fn last_refreshed_at(&self) -> Option<NaiveDateTime> {
+ Some(match self {
+ UserOrCommunity::User(p) => p.last_refreshed_at,
+ UserOrCommunity::Community(p) => p.last_refreshed_at,
+ })
+ }
+
+ async fn read_from_apub_id(
+ object_id: Url,
+ data: &Self::DataType,
+ ) -> Result<Option<Self>, LemmyError> {
+ let person = ApubPerson::read_from_apub_id(object_id.clone(), data).await?;
+ Ok(match person {
+ Some(o) => Some(UserOrCommunity::User(o)),
+ None => ApubCommunity::read_from_apub_id(object_id, data)
+ .await?
+ .map(UserOrCommunity::Community),
+ })
+ }
+
+ async fn delete(self, data: &Self::DataType) -> Result<(), LemmyError> {
+ match self {
+ UserOrCommunity::User(p) => p.delete(data).await,
+ UserOrCommunity::Community(p) => p.delete(data).await,
+ }
+ }
+
+ async fn to_apub(&self, _data: &Self::DataType) -> Result<Self::ApubType, LemmyError> {
+ unimplemented!()
+ }
+
+ fn to_tombstone(&self) -> Result<Self::TombstoneType, LemmyError> {
+ unimplemented!()
+ }
+
+ async fn from_apub(
+ apub: &Self::ApubType,
+ data: &Self::DataType,
+ expected_domain: &Url,
+ request_counter: &mut i32,
+ ) -> Result<Self, LemmyError> {
+ Ok(match apub {
+ PersonOrGroup::Person(p) => UserOrCommunity::User(
+ ApubPerson::from_apub(p, data, expected_domain, request_counter).await?,
+ ),
+ PersonOrGroup::Group(p) => UserOrCommunity::Community(
+ ApubCommunity::from_apub(p, data, expected_domain, request_counter).await?,
+ ),
+ })
+ }
+}
+
+impl ActorType for UserOrCommunity {
+ fn is_local(&self) -> bool {
+ todo!()
+ }
+
+ fn actor_id(&self) -> Url {
+ todo!()
+ }
+
+ fn name(&self) -> String {
+ todo!()
+ }
+
+ fn public_key(&self) -> Option<String> {
+ match self {
+ UserOrCommunity::User(p) => p.public_key(),
+ UserOrCommunity::Community(p) => p.public_key(),
+ }
+ }
+
+ fn private_key(&self) -> Option<String> {
+ todo!()
+ }
+
+ fn inbox_url(&self) -> Url {
+ todo!()
+ }
+
+ fn shared_inbox_url(&self) -> Option<Url> {
+ todo!()
+ }
+}
create_apub_tombstone_response,
payload_to_string,
receive_activity,
+ ActivityCommonFields,
},
objects::community::ApubCommunity,
protocol::{
};
use actix_web::{body::Body, web, web::Payload, HttpRequest, HttpResponse};
use lemmy_api_common::blocking;
-use lemmy_apub_lib::traits::{ActivityFields, ApubObject};
+use lemmy_apub_lib::traits::ApubObject;
use lemmy_db_schema::source::community::Community;
use lemmy_utils::LemmyError;
use lemmy_websocket::LemmyContext;
) -> Result<HttpResponse, LemmyError> {
let unparsed = payload_to_string(payload).await?;
info!("Received community inbox activity {}", unparsed);
+ let activity_data: ActivityCommonFields = serde_json::from_str(&unparsed)?;
let activity = serde_json::from_str::<WithContext<GroupInboxActivities>>(&unparsed)?;
- receive_group_inbox(activity.inner(), request, &context).await?;
+ receive_group_inbox(activity.inner(), activity_data, request, &context).await?;
Ok(HttpResponse::Ok().finish())
}
pub(in crate::http) async fn receive_group_inbox(
activity: GroupInboxActivities,
+ activity_data: ActivityCommonFields,
request: HttpRequest,
context: &LemmyContext,
) -> Result<HttpResponse, LemmyError> {
- let res = receive_activity(request, activity.clone(), context).await;
+ let actor_id = ObjectId::new(activity_data.actor.clone());
+ let res = receive_activity(request, activity.clone(), activity_data, context).await;
if let GroupInboxActivities::AnnouncableActivities(announcable) = activity {
let community = announcable.get_community(context, &mut 0).await?;
- let actor_id = ObjectId::new(announcable.actor().clone());
verify_person_in_community(&actor_id, &community, context, &mut 0).await?;
if community.local {
AnnounceActivity::send(announcable, &community, vec![], context).await?;
activity_lists::SharedInboxActivities,
check_is_apub_id_valid,
context::WithContext,
- fetcher::get_or_fetch_and_upsert_actor,
+ fetcher::{object_id::ObjectId, user_or_community::UserOrCommunity},
http::{community::receive_group_inbox, person::receive_person_inbox},
insert_activity,
};
use lemmy_apub_lib::{
data::Data,
signatures::verify_signature,
- traits::{ActivityFields, ActivityHandler},
+ traits::{ActivityHandler, ActorType},
APUB_JSON_CONTENT_TYPE,
};
use lemmy_db_schema::{source::activity::Activity, DbPool};
) -> Result<HttpResponse, LemmyError> {
let unparsed = payload_to_string(payload).await?;
info!("Received shared inbox activity {}", unparsed);
+ let activity_data: ActivityCommonFields = serde_json::from_str(&unparsed)?;
let activity = serde_json::from_str::<WithContext<SharedInboxActivities>>(&unparsed)?;
match activity.inner() {
SharedInboxActivities::GroupInboxActivities(g) => {
- receive_group_inbox(g, request, &context).await
+ receive_group_inbox(g, activity_data, request, &context).await
}
SharedInboxActivities::PersonInboxActivities(p) => {
- receive_person_inbox(p, request, &context).await
+ receive_person_inbox(p, activity_data, request, &context).await
}
}
}
Ok(unparsed)
}
+#[derive(Clone, Debug, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub(crate) struct ActivityCommonFields {
+ pub(crate) id: Url,
+ pub(crate) actor: Url,
+}
+
// TODO: move most of this code to library
async fn receive_activity<'a, T>(
request: HttpRequest,
activity: T,
+ activity_data: ActivityCommonFields,
context: &LemmyContext,
) -> Result<HttpResponse, LemmyError>
where
T: ActivityHandler<DataType = LemmyContext>
- + ActivityFields
+ Clone
+ Deserialize<'a>
+ Serialize
+ Send
+ 'static,
{
+ check_is_apub_id_valid(&activity_data.actor, false, &context.settings())?;
let request_counter = &mut 0;
- let actor =
- get_or_fetch_and_upsert_actor(activity.actor().clone(), context, request_counter).await?;
+ let actor = ObjectId::<UserOrCommunity>::new(activity_data.actor)
+ .dereference(context, request_counter)
+ .await?;
verify_signature(&request, &actor.public_key().context(location_info!())?)?;
// Do nothing if we received the same activity before
- if is_activity_already_known(context.pool(), activity.id_unchecked()).await? {
+ if is_activity_already_known(context.pool(), &activity_data.id).await? {
return Ok(HttpResponse::Ok().finish());
}
- check_is_apub_id_valid(activity.actor(), false, &context.settings())?;
- info!("Verifying activity {}", activity.id_unchecked().to_string());
+ info!("Verifying activity {}", activity_data.id.to_string());
activity
.verify(&Data::new(context.clone()), request_counter)
.await?;
- assert_activity_not_local(&activity, &context.settings().hostname)?;
+ assert_activity_not_local(&activity_data.id, &context.settings().hostname)?;
// Log the activity, so we avoid receiving and parsing it twice. Note that this could still happen
// if we receive the same activity twice in very quick succession.
insert_activity(
- activity.id_unchecked(),
+ &activity_data.id,
activity.clone(),
false,
true,
)
.await?;
- info!("Receiving activity {}", activity.id_unchecked().to_string());
+ info!("Receiving activity {}", activity_data.id.to_string());
activity
.receive(&Data::new(context.clone()), request_counter)
.await?;
}
}
-fn assert_activity_not_local<T: Debug + ActivityFields>(
- activity: &T,
- hostname: &str,
-) -> Result<(), LemmyError> {
- let activity_domain = activity.id_unchecked().domain().context(location_info!())?;
+fn assert_activity_not_local(id: &Url, hostname: &str) -> Result<(), LemmyError> {
+ let activity_domain = id.domain().context(location_info!())?;
if activity_domain == hostname {
return Err(
anyhow!(
"Error: received activity which was sent by local instance: {:?}",
- activity
+ id
)
.into(),
);
create_apub_tombstone_response,
payload_to_string,
receive_activity,
+ ActivityCommonFields,
},
objects::person::ApubPerson,
protocol::collections::person_outbox::PersonOutbox,
) -> Result<HttpResponse, LemmyError> {
let unparsed = payload_to_string(payload).await?;
info!("Received person inbox activity {}", unparsed);
+ let activity_data: ActivityCommonFields = serde_json::from_str(&unparsed)?;
let activity = serde_json::from_str::<WithContext<PersonInboxActivities>>(&unparsed)?;
- receive_person_inbox(activity.inner(), request, &context).await
+ receive_person_inbox(activity.inner(), activity_data, request, &context).await
}
pub(in crate::http) async fn receive_person_inbox(
activity: PersonInboxActivities,
+ activity_data: ActivityCommonFields,
request: HttpRequest,
context: &LemmyContext,
) -> Result<HttpResponse, LemmyError> {
- receive_activity(request, activity, context).await
+ receive_activity(request, activity, activity_data, context).await
}
pub(crate) async fn get_apub_person_outbox(
use crate::{fetcher::object_id::ObjectId, objects::person::ApubPerson};
use activitystreams::{activity::kind::AddType, unparsed::Unparsed};
-use lemmy_apub_lib::traits::ActivityFields;
use serde::{Deserialize, Serialize};
use url::Url;
-#[derive(Clone, Debug, Deserialize, Serialize, ActivityFields)]
+#[derive(Clone, Debug, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct AddMod {
pub(crate) actor: ObjectId<ApubPerson>,
objects::community::ApubCommunity,
};
use activitystreams::{activity::kind::AnnounceType, unparsed::Unparsed};
-use lemmy_apub_lib::traits::ActivityFields;
use serde::{Deserialize, Serialize};
use url::Url;
-#[derive(Clone, Debug, Deserialize, Serialize, ActivityFields)]
+#[derive(Clone, Debug, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct AnnounceActivity {
pub(crate) actor: ObjectId<ApubCommunity>,
objects::{community::ApubCommunity, person::ApubPerson},
};
use activitystreams::{activity::kind::BlockType, unparsed::Unparsed};
-use lemmy_apub_lib::traits::ActivityFields;
use serde::{Deserialize, Serialize};
use url::Url;
-#[derive(Clone, Debug, Deserialize, Serialize, ActivityFields)]
+#[derive(Clone, Debug, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct BlockUserFromCommunity {
pub(crate) actor: ObjectId<ApubPerson>,
use crate::{fetcher::object_id::ObjectId, objects::person::ApubPerson};
use activitystreams::{activity::kind::RemoveType, unparsed::Unparsed};
-use lemmy_apub_lib::traits::ActivityFields;
use serde::{Deserialize, Serialize};
use url::Url;
-#[derive(Clone, Debug, Deserialize, Serialize, ActivityFields)]
+#[derive(Clone, Debug, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct RemoveMod {
pub(crate) actor: ObjectId<ApubPerson>,
objects::{community::ApubCommunity, person::ApubPerson},
};
use activitystreams::{activity::kind::FlagType, unparsed::Unparsed};
-use lemmy_apub_lib::traits::ActivityFields;
use serde::{Deserialize, Serialize};
use url::Url;
-#[derive(Clone, Debug, Deserialize, Serialize, ActivityFields)]
+#[derive(Clone, Debug, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct Report {
pub(crate) actor: ObjectId<ApubPerson>,
protocol::activities::community::block_user::BlockUserFromCommunity,
};
use activitystreams::{activity::kind::UndoType, unparsed::Unparsed};
-use lemmy_apub_lib::traits::ActivityFields;
use serde::{Deserialize, Serialize};
use url::Url;
-#[derive(Clone, Debug, Deserialize, Serialize, ActivityFields)]
+#[derive(Clone, Debug, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct UndoBlockUserFromCommunity {
pub(crate) actor: ObjectId<ApubPerson>,
protocol::objects::group::Group,
};
use activitystreams::{activity::kind::UpdateType, unparsed::Unparsed};
-use lemmy_apub_lib::traits::ActivityFields;
use serde::{Deserialize, Serialize};
use url::Url;
/// This activity is received from a remote community mod, and updates the description or other
/// fields of a local community.
-#[derive(Clone, Debug, Deserialize, Serialize, ActivityFields)]
+#[derive(Clone, Debug, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct UpdateCommunity {
pub(crate) actor: ObjectId<ApubPerson>,
protocol::{activities::CreateOrUpdateType, objects::note::Note},
};
use activitystreams::{link::Mention, unparsed::Unparsed};
-use lemmy_apub_lib::traits::ActivityFields;
use serde::{Deserialize, Serialize};
use url::Url;
-#[derive(Clone, Debug, Deserialize, Serialize, ActivityFields)]
+#[derive(Clone, Debug, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct CreateOrUpdateComment {
pub(crate) actor: ObjectId<ApubPerson>,
protocol::{activities::CreateOrUpdateType, objects::page::Page},
};
use activitystreams::unparsed::Unparsed;
-use lemmy_apub_lib::traits::ActivityFields;
use serde::{Deserialize, Serialize};
use url::Url;
-#[derive(Clone, Debug, Deserialize, Serialize, ActivityFields)]
+#[derive(Clone, Debug, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct CreateOrUpdatePost {
pub(crate) actor: ObjectId<ApubPerson>,
use crate::{fetcher::object_id::ObjectId, objects::person::ApubPerson};
use activitystreams::{activity::kind::DeleteType, unparsed::Unparsed};
-use lemmy_apub_lib::traits::ActivityFields;
use serde::{Deserialize, Serialize};
use serde_with::skip_serializing_none;
use url::Url;
#[skip_serializing_none]
-#[derive(Clone, Debug, Deserialize, Serialize, ActivityFields)]
+#[derive(Clone, Debug, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct Delete {
pub(crate) actor: ObjectId<ApubPerson>,
-use activitystreams::{activity::kind::UndoType, unparsed::Unparsed};
-use serde::{Deserialize, Serialize};
-use url::Url;
-
-use lemmy_apub_lib::traits::ActivityFields;
-
use crate::{
fetcher::object_id::ObjectId,
objects::person::ApubPerson,
protocol::activities::deletion::delete::Delete,
};
+use activitystreams::{activity::kind::UndoType, unparsed::Unparsed};
+use serde::{Deserialize, Serialize};
+use url::Url;
-#[derive(Clone, Debug, Deserialize, Serialize, ActivityFields)]
+#[derive(Clone, Debug, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct UndoDelete {
pub(crate) actor: ObjectId<ApubPerson>,
protocol::activities::following::follow::FollowCommunity,
};
use activitystreams::{activity::kind::AcceptType, unparsed::Unparsed};
-use lemmy_apub_lib::traits::ActivityFields;
use serde::{Deserialize, Serialize};
use url::Url;
-#[derive(Clone, Debug, Deserialize, Serialize, ActivityFields)]
+#[derive(Clone, Debug, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct AcceptFollowCommunity {
pub(crate) actor: ObjectId<ApubCommunity>,
objects::{community::ApubCommunity, person::ApubPerson},
};
use activitystreams::{activity::kind::FollowType, unparsed::Unparsed};
-use lemmy_apub_lib::traits::ActivityFields;
use serde::{Deserialize, Serialize};
use url::Url;
-#[derive(Clone, Debug, Deserialize, Serialize, ActivityFields)]
+#[derive(Clone, Debug, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct FollowCommunity {
pub(crate) actor: ObjectId<ApubPerson>,
protocol::activities::following::follow::FollowCommunity,
};
use activitystreams::{activity::kind::UndoType, unparsed::Unparsed};
-use lemmy_apub_lib::traits::ActivityFields;
use serde::{Deserialize, Serialize};
use url::Url;
-#[derive(Clone, Debug, Deserialize, Serialize, ActivityFields)]
+#[derive(Clone, Debug, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct UndoFollowCommunity {
pub(crate) actor: ObjectId<ApubPerson>,
protocol::{activities::CreateOrUpdateType, objects::chat_message::ChatMessage},
};
use activitystreams::unparsed::Unparsed;
-use lemmy_apub_lib::traits::ActivityFields;
use serde::{Deserialize, Serialize};
use url::Url;
-#[derive(Clone, Debug, Deserialize, Serialize, ActivityFields)]
+#[derive(Clone, Debug, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct CreateOrUpdatePrivateMessage {
pub(crate) id: Url,
objects::{person::ApubPerson, private_message::ApubPrivateMessage},
};
use activitystreams::{activity::kind::DeleteType, unparsed::Unparsed};
-use lemmy_apub_lib::traits::ActivityFields;
use serde::{Deserialize, Serialize};
use url::Url;
-#[derive(Clone, Debug, Deserialize, Serialize, ActivityFields)]
+#[derive(Clone, Debug, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct DeletePrivateMessage {
pub(crate) actor: ObjectId<ApubPerson>,
protocol::activities::private_message::delete::DeletePrivateMessage,
};
use activitystreams::{activity::kind::UndoType, unparsed::Unparsed};
-use lemmy_apub_lib::traits::ActivityFields;
use serde::{Deserialize, Serialize};
use url::Url;
-#[derive(Clone, Debug, Deserialize, Serialize, ActivityFields)]
+#[derive(Clone, Debug, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct UndoDeletePrivateMessage {
pub(crate) actor: ObjectId<ApubPerson>,
-use activitystreams::{activity::kind::UndoType, unparsed::Unparsed};
-use serde::{Deserialize, Serialize};
-use url::Url;
-
-use lemmy_apub_lib::traits::ActivityFields;
-
use crate::{
fetcher::object_id::ObjectId,
objects::person::ApubPerson,
protocol::activities::voting::vote::Vote,
};
+use activitystreams::{activity::kind::UndoType, unparsed::Unparsed};
+use serde::{Deserialize, Serialize};
+use url::Url;
-#[derive(Clone, Debug, Deserialize, Serialize, ActivityFields)]
+#[derive(Clone, Debug, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct UndoVote {
pub(crate) actor: ObjectId<ApubPerson>,
};
use activitystreams::unparsed::Unparsed;
use anyhow::anyhow;
-use lemmy_apub_lib::traits::ActivityFields;
use lemmy_utils::LemmyError;
use serde::{Deserialize, Serialize};
use std::convert::TryFrom;
use strum_macros::ToString;
use url::Url;
-#[derive(Clone, Debug, Deserialize, Serialize, ActivityFields)]
+#[derive(Clone, Debug, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct Vote {
pub(crate) actor: ObjectId<ApubPerson>,
use lemmy_utils::{location_info, LemmyError};
use url::Url;
-pub trait ActivityFields {
- fn id_unchecked(&self) -> &Url;
- fn actor(&self) -> &Url;
-}
-
#[async_trait::async_trait(?Send)]
pub trait ActivityHandler {
type DataType;
_ => unimplemented!(),
}
}
-
-#[proc_macro_derive(ActivityFields)]
-pub fn derive_activity_fields(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
- let input = parse_macro_input!(input as DeriveInput);
-
- let name = input.ident;
-
- let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl();
-
- let expanded = match input.data {
- Data::Enum(e) => {
- let variants = e.variants;
- let impl_id = variants
- .iter()
- .map(|v| generate_match_arm(&name, v, "e! {a.id_unchecked()}));
- let impl_actor = variants
- .iter()
- .map(|v| generate_match_arm(&name, v, "e! {a.actor()}));
- quote! {
- impl #impl_generics lemmy_apub_lib::traits::ActivityFields for #name #ty_generics #where_clause {
- fn id_unchecked(&self) -> &url::Url { match self { #(#impl_id)* } }
- fn actor(&self) -> &url::Url { match self { #(#impl_actor)* } }
- }
- }
- }
- Data::Struct(_) => {
- quote! {
- impl #impl_generics lemmy_apub_lib::traits::ActivityFields for #name #ty_generics #where_clause {
- fn id_unchecked(&self) -> &url::Url { &self.id }
- fn actor(&self) -> &url::Url { &self.actor.inner() }
- }
- }
- }
- _ => unimplemented!(),
- };
- expanded.into()
-}