feat: mut traits, getter/setters for base+object
This commit is contained in:
parent
35f85695ba
commit
680c61ff9a
22 changed files with 302 additions and 204 deletions
|
@ -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"
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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 }
|
||||||
}
|
}
|
||||||
|
|
|
@ -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(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
|
@ -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 {
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
}
|
||||||
|
|
|
@ -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 {}
|
||||||
|
|
||||||
|
|
|
@ -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;
|
getter! { object_type -> type ObjectType }
|
||||||
match self.base_type() {
|
getter! { attachment -> node impl Object }
|
||||||
Some(super::BaseType::Object(o)) => Some(o),
|
getter! { attributed_to::attributedTo -> node impl Actor }
|
||||||
_ => None,
|
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 attachment(&self) -> Node<impl Object> {
|
fn url(&self) -> Option<Vec<impl super::Link>> {
|
||||||
self.node_vec("attachment")
|
|
||||||
}
|
|
||||||
|
|
||||||
fn attributed_to(&self) -> Node<impl Actor> {
|
|
||||||
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!()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -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)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
Loading…
Reference in a new issue