feat: mut traits, getter/setters for base+object

This commit is contained in:
əlemi 2024-03-20 05:44:10 +01:00
parent 35f85695ba
commit 680c61ff9a
Signed by: alemi
GPG key ID: A4895B84D311642C
22 changed files with 302 additions and 204 deletions

View file

@ -9,6 +9,7 @@ edition = "2021"
axum = "0.7.3" axum = "0.7.3"
chrono = { version = "0.4.31", features = ["serde"] } chrono = { version = "0.4.31", features = ["serde"] }
clap = { version = "4.5.3", features = ["derive"] } clap = { version = "4.5.3", features = ["derive"] }
paste = "1.0.14"
reqwest = { version = "0.11.26", features = ["json"] } reqwest = { version = "0.11.26", features = ["json"] }
sea-orm = { version = "0.12.14", features = ["macros", "sqlx-sqlite", "runtime-tokio-rustls"] } sea-orm = { version = "0.12.14", features = ["macros", "sqlx-sqlite", "runtime-tokio-rustls"] }
sea-orm-migration = "0.12.15" sea-orm-migration = "0.12.15"

View file

@ -18,6 +18,17 @@ pub trait Link : super::Base {
fn preview(&self) -> Option<&str> { None } // also in obj 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 { impl Link for String {
fn href(&self) -> &str { fn href(&self) -> &str {
self self

View file

@ -1,5 +1,3 @@
pub mod types;
pub mod link; pub mod link;
pub use link::{Link, LinkType}; pub use link::{Link, LinkType};
@ -9,7 +7,9 @@ pub use object::{Object, ObjectType};
pub mod node; pub mod node;
pub use node::Node; pub use node::Node;
use crate::strenum; pub mod macros;
use crate::{getter, setter, strenum};
strenum! { strenum! {
pub enum BaseType { pub enum BaseType {
@ -22,9 +22,18 @@ strenum! {
pub trait Base { pub trait Base {
fn id(&self) -> Option<&str> { None } fn id(&self) -> Option<&str> { None }
fn base_type(&self) -> Option<BaseType> { None } fn base_type(&self) -> Option<BaseType> { 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<BaseType>) -> &mut Self;
} }
impl Base for () {}
impl Base for String { impl Base for String {
fn id(&self) -> Option<&str> { fn id(&self) -> Option<&str> {
@ -34,14 +43,22 @@ impl Base for String {
fn base_type(&self) -> Option<BaseType> { fn base_type(&self) -> Option<BaseType> {
Some(BaseType::Link(LinkType::Link)) Some(BaseType::Link(LinkType::Link))
} }
fn underlying_json_object(self) -> serde_json::Value {
serde_json::Value::String(self)
}
} }
impl Base for serde_json::Value { impl Base for serde_json::Value {
fn id(&self) -> Option<&str> { fn underlying_json_object(self) -> serde_json::Value {
self.get("id")?.as_str() self
} }
fn base_type(&self) -> Option<BaseType> { getter! { id -> &str }
self.get("type")?.as_str()?.try_into().ok() getter! { base_type -> type BaseType }
} }
impl BaseMut for serde_json::Value {
setter! { id -> &str }
setter! { base_type -> type BaseType }
} }

View file

@ -1,22 +1,20 @@
use super::Object; pub enum Node<T : super::Base> {
Array(Vec<Node<T>>), // TODO would be cool to make it Box<[Node<T>]> so that Node is just a ptr
pub enum Node<T> { Object(Box<T>),
Array(Vec<Node<T>>),
Object(T),
Link(Box<dyn super::Link>), Link(Box<dyn super::Link>),
Empty, Empty,
} }
impl<T> From<Option<T>> for Node<T> { impl<T : super::Base> From<Option<T>> for Node<T> {
fn from(value: Option<T>) -> Self { fn from(value: Option<T>) -> Self {
match value { match value {
Some(x) => Node::Object(x), Some(x) => Node::Object(Box::new(x)),
None => Node::Empty, None => Node::Empty,
} }
} }
} }
impl<T> Node<T> { impl<T : super::Base> Node<T> {
pub fn get(&self) -> Option<&T> { pub fn get(&self) -> Option<&T> {
match self { match self {
Node::Empty | Node::Link(_) => None, Node::Empty | Node::Link(_) => None,
@ -37,7 +35,7 @@ impl<T> Node<T> {
Node::Object(x) => Some(vec![x]), Node::Object(x) => Some(vec![x]),
Node::Array(v) => Node::Array(v) =>
Some(v.iter().filter_map(|x| match x { Some(v.iter().filter_map(|x| match x {
Node::Object(x) => Some(x), Node::Object(x) => Some(&**x),
_ => None, _ => None,
}).collect()), }).collect()),
} }
@ -58,12 +56,24 @@ impl<T> Node<T> {
Node::Array(v) => v.len(), Node::Array(v) => v.len(),
} }
} }
}
impl<T> Node<T> pub fn flat(self) -> Vec<serde_json::Value> {
where match self {
T : Object 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> { pub fn id(&self) -> Option<&str> {
match self { match self {
Node::Empty => None, Node::Empty => None,
@ -74,6 +84,22 @@ where
} }
} }
impl Node<serde_json::Value>{
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::<serde_json::Value>()
.await?
.into();
}
Ok(())
}
}
impl From<Option<&str>> for Node<serde_json::Value> { impl From<Option<&str>> for Node<serde_json::Value> {
fn from(value: Option<&str>) -> Self { fn from(value: Option<&str>) -> Self {
match value { match value {
@ -94,7 +120,7 @@ impl From<serde_json::Value> for Node<serde_json::Value> {
match value { match value {
serde_json::Value::String(uri) => Node::Link(Box::new(uri)), serde_json::Value::String(uri) => Node::Link(Box::new(uri)),
serde_json::Value::Object(_) => match value.get("href") { serde_json::Value::Object(_) => match value.get("href") {
None => Node::Object(value), None => Node::Object(Box::new(value)),
Some(_) => Node::Link(Box::new(value)), Some(_) => Node::Link(Box::new(value)),
}, },
serde_json::Value::Array(arr) => Node::Array( serde_json::Value::Array(arr) => Node::Array(
@ -108,23 +134,6 @@ impl From<serde_json::Value> for Node<serde_json::Value> {
} }
} }
impl Node<serde_json::Value>{
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::<serde_json::Value>()
.await?
.into();
}
Ok(())
}
}

View file

@ -8,5 +8,9 @@ strenum! {
} }
pub trait Accept : super::Activity { pub trait Accept : super::Activity {
fn accept_type(&self) -> Option<AcceptType>; fn accept_type(&self) -> Option<AcceptType> { None }
}
pub trait AcceptMut : super::ActivityMut {
fn set_accept_type(&mut self, val: Option<AcceptType>) -> &mut Self;
} }

View file

@ -8,5 +8,9 @@ strenum! {
} }
pub trait Ignore : super::Activity { pub trait Ignore : super::Activity {
fn ignore_type(&self) -> Option<IgnoreType>; fn ignore_type(&self) -> Option<IgnoreType> { None }
}
pub trait IgnoreMut : super::ActivityMut {
fn set_ignore_type(&mut self, val: Option<IgnoreType>) -> &mut Self;
} }

View file

@ -10,5 +10,9 @@ strenum! {
} }
pub trait IntransitiveActivity : super::Activity { pub trait IntransitiveActivity : super::Activity {
fn intransitive_activity_type(&self) -> Option<IntransitiveActivityType>; fn intransitive_activity_type(&self) -> Option<IntransitiveActivityType> { None }
}
pub trait IntransitiveActivityMut : super::ActivityMut {
fn set_intransitive_activity_type(&mut self, val: Option<IntransitiveActivityType>) -> &mut Self;
} }

View file

@ -1,21 +1,16 @@
pub mod accept; pub mod accept;
pub use accept::{Accept, AcceptType};
pub mod ignore; pub mod ignore;
pub use ignore::{Ignore, IgnoreType};
pub mod intransitive; pub mod intransitive;
pub use intransitive::{IntransitiveActivity, IntransitiveActivityType};
pub mod offer; pub mod offer;
pub use offer::{Offer, OfferType};
pub mod reject; pub mod reject;
pub use reject::{Reject, RejectType};
use crate::activitystream::node::NodeExtractor;
use crate::activitystream::Node; use crate::activitystream::Node;
use crate::strenum; use crate::strenum;
use accept::AcceptType;
use reject::RejectType;
use offer::OfferType;
use intransitive::IntransitiveActivityType;
use ignore::IgnoreType;
strenum! { strenum! {
pub enum ActivityType { pub enum ActivityType {
@ -56,17 +51,19 @@ pub trait Activity : super::Object {
fn instrument(&self) -> Node<impl super::Object> { Node::Empty::<serde_json::Value> } fn instrument(&self) -> Node<impl super::Object> { Node::Empty::<serde_json::Value> }
} }
pub trait ActivityMut : super::ObjectMut {
fn set_activity_type(&mut self, val: Option<ActivityType>) -> &mut Self;
fn set_actor(&mut self, val: Node<impl super::Actor>) -> &mut Self;
fn set_object(&mut self, val: Node<impl super::Object>) -> &mut Self;
fn set_target(&mut self, val: Option<&str>) -> &mut Self;
fn set_result(&mut self, val: Node<impl super::Object>) -> &mut Self;
fn set_origin(&mut self, val: Node<impl super::Object>) -> &mut Self;
fn set_instrument(&mut self, val: Node<impl super::Object>) -> &mut Self;
}
impl Activity for serde_json::Value { impl Activity for serde_json::Value {
fn activity_type(&self) -> Option<ActivityType> { fn activity_type(&self) -> Option<ActivityType> {
let serde_json::Value::String(t) = self.get("type")? else { return None }; let serde_json::Value::String(t) = self.get("type")? else { return None };
ActivityType::try_from(t.as_str()).ok() ActivityType::try_from(t.as_str()).ok()
} }
fn object(&self) -> Node<impl super::Object> {
self.node_vec("object")
}
fn actor(&self) -> Node<impl super::Actor> {
self.node_vec("actor")
}
} }

View file

@ -8,5 +8,9 @@ strenum! {
} }
pub trait Offer : super::Activity { pub trait Offer : super::Activity {
fn offer_type(&self) -> Option<OfferType>; fn offer_type(&self) -> Option<OfferType> { None }
}
pub trait OfferMut : super::ActivityMut {
fn set_offer_type(&mut self, val: Option<OfferType>) -> &mut Self;
} }

View file

@ -8,5 +8,9 @@ strenum! {
} }
pub trait Reject : super::Activity { pub trait Reject : super::Activity {
fn reject_type(&self) -> Option<RejectType>; fn reject_type(&self) -> Option<RejectType> { None }
}
pub trait RejectMut : super::ActivityMut {
fn set_reject_type(&mut self, val: Option<RejectType>) -> &mut Self;
} }

View file

@ -12,15 +12,14 @@ strenum! {
}; };
} }
pub trait Profile : super::Object {
// not a Node because it's always embedded and one
fn describes(&self) -> Option<impl super::Object> { None::<serde_json::Value> }
}
pub trait Actor : super::Object { pub trait Actor : super::Object {
fn actor_type(&self) -> Option<ActorType> { None } fn actor_type(&self) -> Option<ActorType> { None }
} }
pub trait ActorMut : super::ObjectMut {
fn set_actor_type(&mut self, val: Option<ActorType>) -> &mut Self;
}
impl Actor for serde_json::Value { impl Actor for serde_json::Value {
fn actor_type(&self) -> Option<ActorType> { fn actor_type(&self) -> Option<ActorType> {
match self.base_type()? { match self.base_type()? {
@ -29,7 +28,3 @@ impl Actor for serde_json::Value {
} }
} }
} }
impl Profile for serde_json::Value {
}

View file

@ -23,10 +23,16 @@ pub trait Collection : super::Object {
fn items(&self) -> Node<impl super::Object> { Node::Empty::<serde_json::Value> } fn items(&self) -> Node<impl super::Object> { Node::Empty::<serde_json::Value> }
} }
pub trait CollectionMut : super::ObjectMut {
fn set_collection_type(&mut self, val: Option<CollectionType>) -> &mut Self;
fn set_total_items(&mut self, val: Option<u32>) -> &mut Self;
fn set_current(&mut self, val: Node<impl CollectionPage>) -> &mut Self;
fn set_first(&mut self, val: Node<impl CollectionPage>) -> &mut Self;
fn set_last(&mut self, val: Node<impl CollectionPage>) -> &mut Self;
fn set_items(&mut self, val: Node<impl super::Object>) -> &mut Self;
}
impl Collection for serde_json::Value { impl Collection for serde_json::Value {
// ... TODO
}
impl CollectionPage for serde_json::Value {
} }

View file

@ -5,3 +5,13 @@ pub trait CollectionPage : super::Collection {
fn next(&self) -> Node<impl CollectionPage> { Node::Empty::<serde_json::Value> } fn next(&self) -> Node<impl CollectionPage> { Node::Empty::<serde_json::Value> }
fn prev(&self) -> Node<impl CollectionPage> { Node::Empty::<serde_json::Value> } fn prev(&self) -> Node<impl CollectionPage> { Node::Empty::<serde_json::Value> }
} }
pub trait CollectionPageMut : super::CollectionMut {
fn set_part_of(&mut self, val: Node<impl super::Collection>) -> &mut Self;
fn set_next(&mut self, val: Node<impl CollectionPage>) -> &mut Self;
fn set_prev(&mut self, val: Node<impl CollectionPage>) -> &mut Self;
}
impl CollectionPage for serde_json::Value {
// ... TODO
}

View file

@ -14,21 +14,14 @@ pub trait Document : super::Object {
fn document_type(&self) -> Option<DocumentType> { None } fn document_type(&self) -> Option<DocumentType> { None }
} }
pub trait DocumentMut : super::ObjectMut {
pub trait Place : super::Object { fn set_document_type(&mut self, val: Option<DocumentType>) -> &mut Self;
fn accuracy(&self) -> Option<f32> { None }
fn altitude(&self) -> Option<f32> { None }
fn latitude(&self) -> Option<f32> { None }
fn longitude(&self) -> Option<f32> { None }
fn radius(&self) -> Option<f32> { None }
fn units(&self) -> Option<&str> { None }
} }
pub trait Image : Document {} pub trait Image : Document {}
impl Document for serde_json::Value {
}
impl Document for serde_json::Value {}
impl Image for serde_json::Value {} impl Image for serde_json::Value {}

View file

@ -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 mod activity;
pub use activity::{Activity, ActivityType}; pub mod actor;
pub mod collection;
pub mod document;
pub mod tombstone; pub mod tombstone;
pub use tombstone::Tombstone; pub mod place;
pub mod profile;
pub mod relationship; 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! { strenum! {
pub enum ObjectType { pub enum ObjectType {
@ -68,63 +64,105 @@ pub trait Object : super::Base {
fn duration(&self) -> Option<&str> { None } // TODO how to parse xsd:duration ? 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<ObjectType>) -> &mut Self;
fn set_attachment(&mut self, val: Node<impl Object>) -> &mut Self;
fn set_attributed_to(&mut self, val: Node<impl Actor>) -> &mut Self;
fn set_audience(&mut self, val: Node<impl Actor>) -> &mut Self;
fn set_content(&mut self, val: Option<&str>) -> &mut Self; // TODO handle language maps
fn set_context(&mut self, val: Node<impl Object>) -> &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<chrono::DateTime<chrono::Utc>>) -> &mut Self;
fn set_generator(&mut self, val: Node<impl Actor>) -> &mut Self;
fn set_icon(&mut self, val: Node<impl Image>) -> &mut Self;
fn set_image(&mut self, val: Node<impl Image>) -> &mut Self;
fn set_in_reply_to(&mut self, val: Node<impl Object>) -> &mut Self;
fn set_location(&mut self, val: Node<impl Object>) -> &mut Self;
fn set_preview(&mut self, val: Node<impl Object>) -> &mut Self; // also in link
fn set_published(&mut self, val: Option<chrono::DateTime<chrono::Utc>>) -> &mut Self;
fn set_replies(&mut self, val: Node<impl Collection>) -> &mut Self;
fn set_start_time(&mut self, val: Option<chrono::DateTime<chrono::Utc>>) -> &mut Self;
fn set_summary(&mut self, val: Option<&str>) -> &mut Self;
fn set_tag(&mut self, val: Node<impl Object>) -> &mut Self;
fn set_updated(&mut self, val: Option<chrono::DateTime<chrono::Utc>>) -> &mut Self;
fn set_url(&mut self, val: Option<Vec<impl super::Link>>) -> &mut Self;
fn set_to(&mut self, val: Node<impl Object>) -> &mut Self;
fn set_bto(&mut self, val: Node<impl Object>) -> &mut Self;
fn set_cc(&mut self, val: Node<impl Object>) -> &mut Self;
fn set_bcc(&mut self, val: Node<impl Object>) -> &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 { impl Object for serde_json::Value {
fn object_type(&self) -> Option<ObjectType> {
use super::Base;
match self.base_type() {
Some(super::BaseType::Object(o)) => Some(o),
_ => None,
}
}
fn attachment(&self) -> Node<impl Object> { getter! { object_type -> type ObjectType }
self.node_vec("attachment") 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<chrono::Utc> }
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<chrono::Utc> }
getter! { replies -> node impl Collection }
getter! { start_time::startTime -> chrono::DateTime<chrono::Utc> }
getter! { summary -> &str }
getter! { tag -> node impl Object }
getter! { updated -> chrono::DateTime<chrono::Utc> }
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 attributed_to(&self) -> Node<impl Actor> { fn url(&self) -> Option<Vec<impl super::Link>> {
self.node_vec("attributedTo")
}
fn audience(&self) -> Node<impl Actor> {
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<chrono::DateTime<chrono::Utc>> {
Some( Some(
chrono::DateTime::parse_from_rfc3339( self.get("url")?
self .as_array()?
.get("endTime")? .iter()
.as_str()? .filter_map(|x| Some(x.as_str()?.to_string()))
) .collect()
.ok()? )
.with_timezone(&chrono::Utc)) }
} }
fn generator(&self) -> Node<impl Actor> { impl ObjectMut for serde_json::Value {
self.node_vec("generator") setter! { object_type -> type ObjectType }
} setter! { attachment -> node impl Object }
setter! { attributed_to::attributedTo -> node impl Actor }
fn icon(&self) -> Node<impl Image> { setter! { audience -> node impl Actor }
self.node_vec("icon") setter! { content -> &str }
} setter! { context -> node impl Object }
setter! { name -> &str }
fn image(&self) -> Node<impl Image> { setter! { end_time::endTime -> chrono::DateTime<chrono::Utc> }
self.node_vec("image") setter! { generator -> node impl Actor }
} setter! { icon -> node impl Image }
setter! { image -> node impl Image }
fn in_reply_to(&self) -> Node<impl Object> { setter! { in_reply_to::inReplyTo -> node impl Object }
self.node_vec("inReplyTo") setter! { location -> node impl Object }
} setter! { preview -> node impl Object }
setter! { published -> chrono::DateTime<chrono::Utc> }
fn location(&self) -> Node<impl Object> { setter! { replies -> node impl Collection }
self.node_vec("location") setter! { start_time::startTime -> chrono::DateTime<chrono::Utc> }
setter! { summary -> &str }
setter! { tag -> node impl Object }
setter! { updated -> chrono::DateTime<chrono::Utc> }
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<Vec<impl super::Link>>) -> &mut Self {
todo!()
} }
} }

View file

@ -6,6 +6,12 @@ pub trait Relationship : super::Object {
fn object(&self) -> Node<impl super::Object> { Node::Empty::<serde_json::Value> } fn object(&self) -> Node<impl super::Object> { Node::Empty::<serde_json::Value> }
} }
pub trait RelationshipMut : super::ObjectMut {
fn set_subject(&mut self, val: Node<impl super::Object>) -> &mut Self;
fn set_relationship(&mut self, val: Option<&str>) -> &mut Self; // TODO what does this mean???
fn set_object(&mut self, val: Node<impl super::Object>) -> &mut Self;
}
impl Relationship for serde_json::Value { impl Relationship for serde_json::Value {
// ... TODO // ... TODO
} }

View file

@ -3,6 +3,11 @@ pub trait Tombstone : super::Object {
fn deleted(&self) -> Option<chrono::DateTime<chrono::Utc>> { None } fn deleted(&self) -> Option<chrono::DateTime<chrono::Utc>> { None }
} }
pub trait TombstoneMut : super::ObjectMut {
fn set_former_type(&mut self, val: Option<super::super::BaseType>) -> &mut Self;
fn set_deleted(&mut self, val: Option<chrono::DateTime<chrono::Utc>>) -> &mut Self;
}
impl Tombstone for serde_json::Value { impl Tombstone for serde_json::Value {
// ... TODO // ... TODO
} }

View file

@ -1,6 +1,7 @@
pub mod model; pub mod model;
pub mod migrations; pub mod migrations;
pub mod activitystream; pub mod activitystream;
pub mod activitypub;
pub mod server; pub mod server;
use clap::{Parser, Subcommand}; 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::Object(t)) => tracing::warn!("not implemented: {:?}", t),
Some(BaseType::Link(_)) => tracing::error!("fetched another link?"), 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"), None => tracing::error!("no type on object"),
} }
} }

View file

@ -1,6 +1,6 @@
use sea_orm::entity::prelude::*; 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)] #[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)]
#[sea_orm(table_name = "activities")] #[sea_orm(table_name = "activities")]
@ -31,6 +31,17 @@ impl Base for Model {
fn base_type(&self) -> Option<BaseType> { fn base_type(&self) -> Option<BaseType> {
Some(BaseType::Object(ObjectType::Activity(self.activity_type))) 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 { 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)
}
}

View file

@ -2,10 +2,6 @@ pub mod user;
pub mod object; pub mod object;
pub mod activity; pub mod activity;
pub trait ToJson {
fn json(&self) -> serde_json::Value;
}
#[derive(Debug, Clone, thiserror::Error)] #[derive(Debug, Clone, thiserror::Error)]
#[error("missing required field: '{0}'")] #[error("missing required field: '{0}'")]
pub struct FieldError(pub &'static str); pub struct FieldError(pub &'static str);

View file

@ -1,6 +1,6 @@
use sea_orm::entity::prelude::*; 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)] #[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)]
#[sea_orm(table_name = "objects")] #[sea_orm(table_name = "objects")]
@ -29,6 +29,18 @@ impl Base for Model {
fn base_type(&self) -> Option<BaseType> { fn base_type(&self) -> Option<BaseType> {
Some(BaseType::Object(self.object_type)) 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 { 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)
}
}

View file

@ -1,6 +1,6 @@
use sea_orm::entity::prelude::*; 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)] #[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)]
#[sea_orm(table_name = "users")] #[sea_orm(table_name = "users")]
@ -27,6 +27,14 @@ impl Base for Model {
fn base_type(&self) -> Option<BaseType> { fn base_type(&self) -> Option<BaseType> {
Some(BaseType::Object(ObjectType::Actor(self.actor_type))) 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 { 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)
}
}