diff --git a/Cargo.toml b/Cargo.toml index 3f02d12a..7d7770ae 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,6 +9,7 @@ edition = "2021" axum = "0.7.3" chrono = { version = "0.4.31", features = ["serde"] } clap = { version = "4.5.3", features = ["derive"] } +paste = "1.0.14" reqwest = { version = "0.11.26", features = ["json"] } sea-orm = { version = "0.12.14", features = ["macros", "sqlx-sqlite", "runtime-tokio-rustls"] } sea-orm-migration = "0.12.15" diff --git a/src/activitystream/link.rs b/src/activitystream/link.rs index bf52e840..1dbf4204 100644 --- a/src/activitystream/link.rs +++ b/src/activitystream/link.rs @@ -18,6 +18,17 @@ pub trait Link : super::Base { fn preview(&self) -> Option<&str> { None } // also in obj } +pub trait LinkMut : super::BaseMut { + fn set_href(&mut self, href: &str) -> &mut Self; + fn set_rel(&mut self, val: Option<&str>) -> &mut Self; + fn set_media_type(&mut self, val: Option<&str>) -> &mut Self; // also in obj + fn set_name(&mut self, val: Option<&str>) -> &mut Self; // also in obj + fn set_hreflang(&mut self, val: Option<&str>) -> &mut Self; + fn set_height(&mut self, val: Option<&str>) -> &mut Self; + fn set_width(&mut self, val: Option<&str>) -> &mut Self; + fn set_preview(&mut self, val: Option<&str>) -> &mut Self; // also in obj +} + impl Link for String { fn href(&self) -> &str { self diff --git a/src/activitystream/mod.rs b/src/activitystream/mod.rs index 1e72c6bf..c76fc70f 100644 --- a/src/activitystream/mod.rs +++ b/src/activitystream/mod.rs @@ -1,5 +1,3 @@ -pub mod types; - pub mod link; pub use link::{Link, LinkType}; @@ -9,7 +7,9 @@ pub use object::{Object, ObjectType}; pub mod node; pub use node::Node; -use crate::strenum; +pub mod macros; + +use crate::{getter, setter, strenum}; strenum! { pub enum BaseType { @@ -22,9 +22,18 @@ strenum! { pub trait Base { fn id(&self) -> Option<&str> { None } fn base_type(&self) -> Option { None } + + // TODO this is a dirty fix because my trait model is flawed and leads to circular resolution + // errors, basically can't downcast back to serde_json::Value once i've updasted it to + // impl Object/Actor/whatever... ask me to infodump+bikeshed about this!!! :3 + fn underlying_json_object(self) -> serde_json::Value; +} + +pub trait BaseMut { + fn set_id(&mut self, val: Option<&str>) -> &mut Self; + fn set_base_type(&mut self, val: Option) -> &mut Self; } -impl Base for () {} impl Base for String { fn id(&self) -> Option<&str> { @@ -34,14 +43,22 @@ impl Base for String { fn base_type(&self) -> Option { Some(BaseType::Link(LinkType::Link)) } + + fn underlying_json_object(self) -> serde_json::Value { + serde_json::Value::String(self) + } } impl Base for serde_json::Value { - fn id(&self) -> Option<&str> { - self.get("id")?.as_str() + fn underlying_json_object(self) -> serde_json::Value { + self } - fn base_type(&self) -> Option { - self.get("type")?.as_str()?.try_into().ok() - } + getter! { id -> &str } + getter! { base_type -> type BaseType } +} + +impl BaseMut for serde_json::Value { + setter! { id -> &str } + setter! { base_type -> type BaseType } } diff --git a/src/activitystream/node.rs b/src/activitystream/node.rs index b288a8c9..4ebdffb0 100644 --- a/src/activitystream/node.rs +++ b/src/activitystream/node.rs @@ -1,22 +1,20 @@ -use super::Object; - -pub enum Node { - Array(Vec>), - Object(T), +pub enum Node { + Array(Vec>), // TODO would be cool to make it Box<[Node]> so that Node is just a ptr + Object(Box), Link(Box), Empty, } -impl From> for Node { +impl From> for Node { fn from(value: Option) -> Self { match value { - Some(x) => Node::Object(x), + Some(x) => Node::Object(Box::new(x)), None => Node::Empty, } } } -impl Node { +impl Node { pub fn get(&self) -> Option<&T> { match self { Node::Empty | Node::Link(_) => None, @@ -37,7 +35,7 @@ impl Node { Node::Object(x) => Some(vec![x]), Node::Array(v) => Some(v.iter().filter_map(|x| match x { - Node::Object(x) => Some(x), + Node::Object(x) => Some(&**x), _ => None, }).collect()), } @@ -58,12 +56,24 @@ impl Node { Node::Array(v) => v.len(), } } -} -impl Node -where - T : Object -{ + pub fn flat(self) -> Vec { + match self { + Node::Empty => vec![], + Node::Link(l) => vec![serde_json::Value::String(l.href().to_string())], + Node::Object(x) => vec![x.underlying_json_object()], + Node::Array(arr) => { + arr + .into_iter() + .filter_map(|node| match node { + Node::Empty | Node::Link(_) => None, + Node::Object(o) => Some(o.underlying_json_object()), + Node::Array(_) => Some(serde_json::Value::Array(node.flat())), + }).collect() + } + } + } + pub fn id(&self) -> Option<&str> { match self { Node::Empty => None, @@ -74,6 +84,22 @@ where } } +impl Node{ + pub async fn fetch(&mut self) -> reqwest::Result<()> { + if let Node::Link(link) = self { + *self = reqwest::Client::new() + .get(link.href()) + .header("Accept", "application/json") + .send() + .await? + .json::() + .await? + .into(); + } + Ok(()) + } +} + impl From> for Node { fn from(value: Option<&str>) -> Self { match value { @@ -94,7 +120,7 @@ impl From for Node { match value { serde_json::Value::String(uri) => Node::Link(Box::new(uri)), serde_json::Value::Object(_) => match value.get("href") { - None => Node::Object(value), + None => Node::Object(Box::new(value)), Some(_) => Node::Link(Box::new(value)), }, serde_json::Value::Array(arr) => Node::Array( @@ -108,23 +134,6 @@ impl From for Node { } } -impl Node{ - pub async fn fetch(&mut self) -> reqwest::Result<()> { - if let Node::Link(link) = self { - *self = reqwest::Client::new() - .get(link.href()) - .header("Accept", "application/json") - .send() - .await? - .json::() - .await? - .into(); - } - Ok(()) - } -} - - diff --git a/src/activitystream/object/activity/accept.rs b/src/activitystream/object/activity/accept.rs index aebbae4c..ce394905 100644 --- a/src/activitystream/object/activity/accept.rs +++ b/src/activitystream/object/activity/accept.rs @@ -8,5 +8,9 @@ strenum! { } pub trait Accept : super::Activity { - fn accept_type(&self) -> Option; + fn accept_type(&self) -> Option { None } +} + +pub trait AcceptMut : super::ActivityMut { + fn set_accept_type(&mut self, val: Option) -> &mut Self; } diff --git a/src/activitystream/object/activity/ignore.rs b/src/activitystream/object/activity/ignore.rs index 5c93a9c1..efd52ee7 100644 --- a/src/activitystream/object/activity/ignore.rs +++ b/src/activitystream/object/activity/ignore.rs @@ -8,5 +8,9 @@ strenum! { } pub trait Ignore : super::Activity { - fn ignore_type(&self) -> Option; + fn ignore_type(&self) -> Option { None } +} + +pub trait IgnoreMut : super::ActivityMut { + fn set_ignore_type(&mut self, val: Option) -> &mut Self; } diff --git a/src/activitystream/object/activity/intransitive.rs b/src/activitystream/object/activity/intransitive.rs index f0bafbbf..299ea335 100644 --- a/src/activitystream/object/activity/intransitive.rs +++ b/src/activitystream/object/activity/intransitive.rs @@ -10,5 +10,9 @@ strenum! { } pub trait IntransitiveActivity : super::Activity { - fn intransitive_activity_type(&self) -> Option; + fn intransitive_activity_type(&self) -> Option { None } +} + +pub trait IntransitiveActivityMut : super::ActivityMut { + fn set_intransitive_activity_type(&mut self, val: Option) -> &mut Self; } diff --git a/src/activitystream/object/activity/mod.rs b/src/activitystream/object/activity/mod.rs index 6f394c41..7d5db04a 100644 --- a/src/activitystream/object/activity/mod.rs +++ b/src/activitystream/object/activity/mod.rs @@ -1,21 +1,16 @@ pub mod accept; -pub use accept::{Accept, AcceptType}; - pub mod ignore; -pub use ignore::{Ignore, IgnoreType}; - pub mod intransitive; -pub use intransitive::{IntransitiveActivity, IntransitiveActivityType}; - pub mod offer; -pub use offer::{Offer, OfferType}; - pub mod reject; -pub use reject::{Reject, RejectType}; -use crate::activitystream::node::NodeExtractor; use crate::activitystream::Node; use crate::strenum; +use accept::AcceptType; +use reject::RejectType; +use offer::OfferType; +use intransitive::IntransitiveActivityType; +use ignore::IgnoreType; strenum! { pub enum ActivityType { @@ -56,17 +51,19 @@ pub trait Activity : super::Object { fn instrument(&self) -> Node { Node::Empty:: } } +pub trait ActivityMut : super::ObjectMut { + fn set_activity_type(&mut self, val: Option) -> &mut Self; + fn set_actor(&mut self, val: Node) -> &mut Self; + fn set_object(&mut self, val: Node) -> &mut Self; + fn set_target(&mut self, val: Option<&str>) -> &mut Self; + fn set_result(&mut self, val: Node) -> &mut Self; + fn set_origin(&mut self, val: Node) -> &mut Self; + fn set_instrument(&mut self, val: Node) -> &mut Self; +} + impl Activity for serde_json::Value { fn activity_type(&self) -> Option { let serde_json::Value::String(t) = self.get("type")? else { return None }; ActivityType::try_from(t.as_str()).ok() } - - fn object(&self) -> Node { - self.node_vec("object") - } - - fn actor(&self) -> Node { - self.node_vec("actor") - } } diff --git a/src/activitystream/object/activity/offer.rs b/src/activitystream/object/activity/offer.rs index 142cbacb..a9d36184 100644 --- a/src/activitystream/object/activity/offer.rs +++ b/src/activitystream/object/activity/offer.rs @@ -8,5 +8,9 @@ strenum! { } pub trait Offer : super::Activity { - fn offer_type(&self) -> Option; + fn offer_type(&self) -> Option { None } +} + +pub trait OfferMut : super::ActivityMut { + fn set_offer_type(&mut self, val: Option) -> &mut Self; } diff --git a/src/activitystream/object/activity/reject.rs b/src/activitystream/object/activity/reject.rs index 1f430be2..01e49a36 100644 --- a/src/activitystream/object/activity/reject.rs +++ b/src/activitystream/object/activity/reject.rs @@ -8,5 +8,9 @@ strenum! { } pub trait Reject : super::Activity { - fn reject_type(&self) -> Option; + fn reject_type(&self) -> Option { None } +} + +pub trait RejectMut : super::ActivityMut { + fn set_reject_type(&mut self, val: Option) -> &mut Self; } diff --git a/src/activitystream/object/actor.rs b/src/activitystream/object/actor.rs index 066fc271..172da51c 100644 --- a/src/activitystream/object/actor.rs +++ b/src/activitystream/object/actor.rs @@ -12,15 +12,14 @@ strenum! { }; } -pub trait Profile : super::Object { - // not a Node because it's always embedded and one - fn describes(&self) -> Option { None:: } -} - pub trait Actor : super::Object { fn actor_type(&self) -> Option { None } } +pub trait ActorMut : super::ObjectMut { + fn set_actor_type(&mut self, val: Option) -> &mut Self; +} + impl Actor for serde_json::Value { fn actor_type(&self) -> Option { match self.base_type()? { @@ -29,7 +28,3 @@ impl Actor for serde_json::Value { } } } - -impl Profile for serde_json::Value { - -} diff --git a/src/activitystream/object/collection/mod.rs b/src/activitystream/object/collection/mod.rs index f9acbbf3..33eb0f83 100644 --- a/src/activitystream/object/collection/mod.rs +++ b/src/activitystream/object/collection/mod.rs @@ -23,10 +23,16 @@ pub trait Collection : super::Object { fn items(&self) -> Node { Node::Empty:: } } +pub trait CollectionMut : super::ObjectMut { + fn set_collection_type(&mut self, val: Option) -> &mut Self; + + fn set_total_items(&mut self, val: Option) -> &mut Self; + fn set_current(&mut self, val: Node) -> &mut Self; + fn set_first(&mut self, val: Node) -> &mut Self; + fn set_last(&mut self, val: Node) -> &mut Self; + fn set_items(&mut self, val: Node) -> &mut Self; +} + impl Collection for serde_json::Value { - -} - -impl CollectionPage for serde_json::Value { - + // ... TODO } diff --git a/src/activitystream/object/collection/page.rs b/src/activitystream/object/collection/page.rs index a2b01c9f..1d9aa17b 100644 --- a/src/activitystream/object/collection/page.rs +++ b/src/activitystream/object/collection/page.rs @@ -5,3 +5,13 @@ pub trait CollectionPage : super::Collection { fn next(&self) -> Node { Node::Empty:: } fn prev(&self) -> Node { Node::Empty:: } } + +pub trait CollectionPageMut : super::CollectionMut { + fn set_part_of(&mut self, val: Node) -> &mut Self; + fn set_next(&mut self, val: Node) -> &mut Self; + fn set_prev(&mut self, val: Node) -> &mut Self; +} + +impl CollectionPage for serde_json::Value { + // ... TODO +} diff --git a/src/activitystream/object/document.rs b/src/activitystream/object/document.rs index 1743d6be..632105d8 100644 --- a/src/activitystream/object/document.rs +++ b/src/activitystream/object/document.rs @@ -14,21 +14,14 @@ pub trait Document : super::Object { fn document_type(&self) -> Option { None } } - -pub trait Place : super::Object { - fn accuracy(&self) -> Option { None } - fn altitude(&self) -> Option { None } - fn latitude(&self) -> Option { None } - fn longitude(&self) -> Option { None } - fn radius(&self) -> Option { None } - fn units(&self) -> Option<&str> { None } +pub trait DocumentMut : super::ObjectMut { + fn set_document_type(&mut self, val: Option) -> &mut Self; } pub trait Image : Document {} -impl Document for serde_json::Value { -} +impl Document for serde_json::Value {} impl Image for serde_json::Value {} diff --git a/src/activitystream/object/mod.rs b/src/activitystream/object/mod.rs index 6402477e..815f8c33 100644 --- a/src/activitystream/object/mod.rs +++ b/src/activitystream/object/mod.rs @@ -1,24 +1,20 @@ -pub mod actor; -pub use actor::{Actor, Profile, ActorType}; - -pub mod collection; -pub use collection::{Collection, CollectionPage, CollectionType}; - -pub mod document; -pub use document::{Document, Image, Place, DocumentType}; - pub mod activity; -pub use activity::{Activity, ActivityType}; - +pub mod actor; +pub mod collection; +pub mod document; pub mod tombstone; -pub use tombstone::Tombstone; - +pub mod place; +pub mod profile; pub mod relationship; -pub use relationship::Relationship; -use crate::strenum; +use crate::{getter, setter, strenum}; -use super::{node::NodeExtractor, Node}; +use super::Node; + +use actor::{Actor, ActorType}; +use document::{Image, DocumentType}; +use activity::ActivityType; +use collection::{Collection, CollectionType}; strenum! { pub enum ObjectType { @@ -68,63 +64,105 @@ pub trait Object : super::Base { fn duration(&self) -> Option<&str> { None } // TODO how to parse xsd:duration ? } +pub trait ObjectMut : super::BaseMut { + fn set_object_type(&mut self, val: Option) -> &mut Self; + fn set_attachment(&mut self, val: Node) -> &mut Self; + fn set_attributed_to(&mut self, val: Node) -> &mut Self; + fn set_audience(&mut self, val: Node) -> &mut Self; + fn set_content(&mut self, val: Option<&str>) -> &mut Self; // TODO handle language maps + fn set_context(&mut self, val: Node) -> &mut Self; + fn set_name(&mut self, val: Option<&str>) -> &mut Self; // also in link // TODO handle language maps + fn set_end_time(&mut self, val: Option>) -> &mut Self; + fn set_generator(&mut self, val: Node) -> &mut Self; + fn set_icon(&mut self, val: Node) -> &mut Self; + fn set_image(&mut self, val: Node) -> &mut Self; + fn set_in_reply_to(&mut self, val: Node) -> &mut Self; + fn set_location(&mut self, val: Node) -> &mut Self; + fn set_preview(&mut self, val: Node) -> &mut Self; // also in link + fn set_published(&mut self, val: Option>) -> &mut Self; + fn set_replies(&mut self, val: Node) -> &mut Self; + fn set_start_time(&mut self, val: Option>) -> &mut Self; + fn set_summary(&mut self, val: Option<&str>) -> &mut Self; + fn set_tag(&mut self, val: Node) -> &mut Self; + fn set_updated(&mut self, val: Option>) -> &mut Self; + fn set_url(&mut self, val: Option>) -> &mut Self; + fn set_to(&mut self, val: Node) -> &mut Self; + fn set_bto(&mut self, val: Node) -> &mut Self; + fn set_cc(&mut self, val: Node) -> &mut Self; + fn set_bcc(&mut self, val: Node) -> &mut Self; + fn set_media_type(&mut self, val: Option<&str>) -> &mut Self; // also in link + fn set_duration(&mut self, val: Option<&str>) -> &mut Self; // TODO how to parse xsd:duration ? +} + impl Object for serde_json::Value { - fn object_type(&self) -> Option { - use super::Base; - match self.base_type() { - Some(super::BaseType::Object(o)) => Some(o), - _ => None, - } - } + + getter! { object_type -> type ObjectType } + getter! { attachment -> node impl Object } + getter! { attributed_to::attributedTo -> node impl Actor } + getter! { audience -> node impl Actor } + getter! { content -> &str } + getter! { context -> node impl Object } + getter! { name -> &str } + getter! { end_time::endTime -> chrono::DateTime } + getter! { generator -> node impl Actor } + getter! { icon -> node impl Image } + getter! { image -> node impl Image } + getter! { in_reply_to::inReplyTo -> node impl Object } + getter! { location -> node impl Object } + getter! { preview -> node impl Object } + getter! { published -> chrono::DateTime } + getter! { replies -> node impl Collection } + getter! { start_time::startTime -> chrono::DateTime } + getter! { summary -> &str } + getter! { tag -> node impl Object } + getter! { updated -> chrono::DateTime } + getter! { to -> node impl Object } + getter! { bto -> node impl Object } + getter! { cc -> node impl Object } + getter! { bcc -> node impl Object } + getter! { media_type -> &str } + getter! { duration -> &str } - fn attachment(&self) -> Node { - self.node_vec("attachment") - } - - fn attributed_to(&self) -> Node { - self.node_vec("attributedTo") - } - - fn audience(&self) -> Node { - self.node_vec("audience") - } - - fn content(&self) -> Option<&str> { - self.get("content")?.as_str() - } - - fn name(&self) -> Option<&str> { - self.get("name")?.as_str() - } - - fn end_time(&self) -> Option> { + fn url(&self) -> Option> { Some( - chrono::DateTime::parse_from_rfc3339( - self - .get("endTime")? - .as_str()? - ) - .ok()? - .with_timezone(&chrono::Utc)) - } - - fn generator(&self) -> Node { - self.node_vec("generator") - } - - fn icon(&self) -> Node { - self.node_vec("icon") - } - - fn image(&self) -> Node { - self.node_vec("image") - } - - fn in_reply_to(&self) -> Node { - self.node_vec("inReplyTo") - } - - fn location(&self) -> Node { - self.node_vec("location") + self.get("url")? + .as_array()? + .iter() + .filter_map(|x| Some(x.as_str()?.to_string())) + .collect() + ) + } +} + +impl ObjectMut for serde_json::Value { + setter! { object_type -> type ObjectType } + setter! { attachment -> node impl Object } + setter! { attributed_to::attributedTo -> node impl Actor } + setter! { audience -> node impl Actor } + setter! { content -> &str } + setter! { context -> node impl Object } + setter! { name -> &str } + setter! { end_time::endTime -> chrono::DateTime } + setter! { generator -> node impl Actor } + setter! { icon -> node impl Image } + setter! { image -> node impl Image } + setter! { in_reply_to::inReplyTo -> node impl Object } + setter! { location -> node impl Object } + setter! { preview -> node impl Object } + setter! { published -> chrono::DateTime } + setter! { replies -> node impl Collection } + setter! { start_time::startTime -> chrono::DateTime } + setter! { summary -> &str } + setter! { tag -> node impl Object } + setter! { updated -> chrono::DateTime } + setter! { to -> node impl Object } + setter! { bto -> node impl Object} + setter! { cc -> node impl Object } + setter! { bcc -> node impl Object } + setter! { media_type -> &str } + setter! { duration -> &str } + + fn set_url(&mut self, _val: Option>) -> &mut Self { + todo!() } } diff --git a/src/activitystream/object/relationship.rs b/src/activitystream/object/relationship.rs index ccd9abe6..52aa6de9 100644 --- a/src/activitystream/object/relationship.rs +++ b/src/activitystream/object/relationship.rs @@ -6,6 +6,12 @@ pub trait Relationship : super::Object { fn object(&self) -> Node { Node::Empty:: } } +pub trait RelationshipMut : super::ObjectMut { + fn set_subject(&mut self, val: Node) -> &mut Self; + fn set_relationship(&mut self, val: Option<&str>) -> &mut Self; // TODO what does this mean??? + fn set_object(&mut self, val: Node) -> &mut Self; +} + impl Relationship for serde_json::Value { // ... TODO } diff --git a/src/activitystream/object/tombstone.rs b/src/activitystream/object/tombstone.rs index 39dc2861..368e8135 100644 --- a/src/activitystream/object/tombstone.rs +++ b/src/activitystream/object/tombstone.rs @@ -3,6 +3,11 @@ pub trait Tombstone : super::Object { fn deleted(&self) -> Option> { None } } +pub trait TombstoneMut : super::ObjectMut { + fn set_former_type(&mut self, val: Option) -> &mut Self; + fn set_deleted(&mut self, val: Option>) -> &mut Self; +} + impl Tombstone for serde_json::Value { // ... TODO } diff --git a/src/main.rs b/src/main.rs index affebe7b..c2d14069 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,6 +1,7 @@ pub mod model; pub mod migrations; pub mod activitystream; +pub mod activitypub; pub mod server; use clap::{Parser, Subcommand}; @@ -112,7 +113,6 @@ async fn fetch(db: &sea_orm::DatabaseConnection, uri: &str, save: bool) -> reqwe }, Some(BaseType::Object(t)) => tracing::warn!("not implemented: {:?}", t), Some(BaseType::Link(_)) => tracing::error!("fetched another link?"), - Some(BaseType::Invalid) => tracing::error!("making this was a mistake"), None => tracing::error!("no type on object"), } } diff --git a/src/model/activity.rs b/src/model/activity.rs index 047ce4ab..25de7b21 100644 --- a/src/model/activity.rs +++ b/src/model/activity.rs @@ -1,6 +1,6 @@ use sea_orm::entity::prelude::*; -use crate::activitystream::{node::{InsertStr, Node}, object::{activity::{Activity, ActivityType}, actor::Actor, Object, ObjectType}, Base, BaseType}; +use crate::activitystream::{Node, macros::InsertValue, object::{activity::{Activity, ActivityType}, actor::Actor, Object, ObjectType}, Base, BaseType}; #[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)] #[sea_orm(table_name = "activities")] @@ -31,6 +31,17 @@ impl Base for Model { fn base_type(&self) -> Option { Some(BaseType::Object(ObjectType::Activity(self.activity_type))) } + + fn underlying_json_object(self) -> serde_json::Value { + let mut map = serde_json::Map::new(); + map.insert_str("id", Some(&self.id)); + map.insert_str("type", Some(self.activity_type.as_ref())); + map.insert_str("actor", Some(&self.actor)); + map.insert_str("object", self.object.as_deref()); + map.insert_str("target", self.target.as_deref()); + map.insert_timestr("published", Some(self.published)); + serde_json::Value::Object(map) + } } impl Object for Model { @@ -72,16 +83,3 @@ impl Model { }) } } - -impl super::ToJson for Model { - fn json(&self) -> serde_json::Value { - let mut map = serde_json::Map::new(); - map.insert_str("id", Some(&self.id)); - map.insert_str("type", Some(self.activity_type.as_ref())); - map.insert_str("actor", Some(&self.actor)); - map.insert_str("object", self.object.as_deref()); - map.insert_str("target", self.target.as_deref()); - map.insert_timestr("published", Some(self.published)); - serde_json::Value::Object(map) - } -} diff --git a/src/model/mod.rs b/src/model/mod.rs index 3b0d1464..3b10905c 100644 --- a/src/model/mod.rs +++ b/src/model/mod.rs @@ -2,10 +2,6 @@ pub mod user; pub mod object; pub mod activity; -pub trait ToJson { - fn json(&self) -> serde_json::Value; -} - #[derive(Debug, Clone, thiserror::Error)] #[error("missing required field: '{0}'")] pub struct FieldError(pub &'static str); diff --git a/src/model/object.rs b/src/model/object.rs index 3ded3d79..08ffa447 100644 --- a/src/model/object.rs +++ b/src/model/object.rs @@ -1,6 +1,6 @@ use sea_orm::entity::prelude::*; -use crate::activitystream::{node::InsertStr, object::{Actor, Object, ObjectType}, Base, BaseType, Node}; +use crate::activitystream::{macros::InsertValue, object::{actor::Actor, Object, ObjectType}, Base, BaseType, Node}; #[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)] #[sea_orm(table_name = "objects")] @@ -29,6 +29,18 @@ impl Base for Model { fn base_type(&self) -> Option { Some(BaseType::Object(self.object_type)) } + + fn underlying_json_object(self) -> serde_json::Value { + let mut map = serde_json::Map::new(); + map.insert_str("id", Some(&self.id)); + map.insert_str("type", Some(self.object_type.as_ref())); + map.insert_str("attributedTo", self.attributed_to.as_deref()); + map.insert_str("name", self.name.as_deref()); + map.insert_str("summary", self.summary.as_deref()); + map.insert_str("content", self.content.as_deref()); + map.insert_timestr("published", Some(self.published)); + serde_json::Value::Object(map) + } } impl Object for Model { @@ -70,17 +82,3 @@ impl Model { }) } } - -impl super::ToJson for Model { - fn json(&self) -> serde_json::Value { - let mut map = serde_json::Map::new(); - map.insert_str("id", Some(&self.id)); - map.insert_str("type", Some(self.object_type.as_ref())); - map.insert_str("attributedTo", self.attributed_to.as_deref()); - map.insert_str("name", self.name.as_deref()); - map.insert_str("summary", self.summary.as_deref()); - map.insert_str("content", self.content.as_deref()); - map.insert_timestr("published", Some(self.published)); - serde_json::Value::Object(map) - } -} diff --git a/src/model/user.rs b/src/model/user.rs index b2059d29..02b92229 100644 --- a/src/model/user.rs +++ b/src/model/user.rs @@ -1,6 +1,6 @@ use sea_orm::entity::prelude::*; -use crate::activitystream::{node::InsertStr, object::{Actor, ActorType}, Base, BaseType, Object, ObjectType}; +use crate::activitystream::{macros::InsertValue, object::actor::{Actor, ActorType}, Base, BaseType, Object, ObjectType}; #[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)] #[sea_orm(table_name = "users")] @@ -27,6 +27,14 @@ impl Base for Model { fn base_type(&self) -> Option { Some(BaseType::Object(ObjectType::Actor(self.actor_type))) } + + fn underlying_json_object(self) -> serde_json::Value { + let mut map = serde_json::Map::new(); + map.insert_str("id", Some(&self.id)); + map.insert_str("type", Some(self.actor_type.as_ref())); + map.insert_str("name", Some(&self.name)); + serde_json::Value::Object(map) + } } impl Object for Model { @@ -50,13 +58,3 @@ impl Model { }) } } - -impl super::ToJson for Model { - fn json(&self) -> serde_json::Value { - let mut map = serde_json::Map::new(); - map.insert_str("id", Some(&self.id)); - map.insert_str("type", Some(self.actor_type.as_ref())); - map.insert_str("name", Some(&self.name)); - serde_json::Value::Object(map) - } -}