merge in old new type defs
This commit is contained in:
parent
de12258368
commit
5473512787
|
@ -1,24 +1,63 @@
|
|||
use async_trait::async_trait;
|
||||
use flabk_derive::IRI;
|
||||
use std::collections::HashMap;
|
||||
|
||||
use flabk_derive::{Resolvable, IRI};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use self::{
|
||||
context::Context,
|
||||
note::Note,
|
||||
context::APContext,
|
||||
resolve::ResolveError,
|
||||
serde_ext::{expand_partial, pull_single_into_vec},
|
||||
serde_ext::{expand_partial, into_vec},
|
||||
};
|
||||
|
||||
pub mod context;
|
||||
pub mod note;
|
||||
pub mod resolve;
|
||||
mod serde_ext;
|
||||
|
||||
#[derive(Clone, Copy, Serialize, Deserialize, Debug)]
|
||||
pub enum ActivityKind {
|
||||
Create,
|
||||
Like,
|
||||
pub enum ObjectKind {
|
||||
Article,
|
||||
Audio,
|
||||
Document,
|
||||
Event,
|
||||
Image,
|
||||
Note,
|
||||
Page,
|
||||
Place,
|
||||
Profile,
|
||||
Relationship,
|
||||
Tombstone,
|
||||
Video,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Serialize, Deserialize, Debug)]
|
||||
pub enum ActivityKind {
|
||||
Accept,
|
||||
Add,
|
||||
Announce,
|
||||
Arrive,
|
||||
Block,
|
||||
Create,
|
||||
Delete,
|
||||
Dislike,
|
||||
Flag,
|
||||
Follow,
|
||||
Invite,
|
||||
Join,
|
||||
Leave,
|
||||
Like,
|
||||
Listen,
|
||||
Move,
|
||||
Offer,
|
||||
Question,
|
||||
Reject,
|
||||
Read,
|
||||
Remove,
|
||||
TentativeReject,
|
||||
TentativeAccept,
|
||||
Travel,
|
||||
Undo,
|
||||
Update,
|
||||
View,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
|
@ -35,45 +74,211 @@ impl From<ResolveError> for ExpandError {
|
|||
}
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
pub trait ExpandLD<T> {
|
||||
async fn expand(obj: &ObjectLD) -> Result<T, ExpandError>;
|
||||
}
|
||||
|
||||
#[derive(Clone, Serialize, Deserialize)]
|
||||
pub struct ActivityLD {
|
||||
#[serde(rename = "@context")]
|
||||
pub context_uri: String,
|
||||
pub kind: ActivityKind,
|
||||
#[serde(rename = "actor")]
|
||||
pub actor_uri: String,
|
||||
#[serde(rename = "to")]
|
||||
pub to_uris: Vec<String>,
|
||||
pub object: Option<ObjectLD>,
|
||||
/// A Collection is a subtype of Object that
|
||||
/// represents ordered or unordered sets of
|
||||
/// Object or Link instances.
|
||||
#[derive(Debug, Clone, Deserialize)]
|
||||
pub struct Collection<T> {
|
||||
pub summary: Option<String>,
|
||||
#[serde(rename = "type")]
|
||||
pub kind: String,
|
||||
#[serde(rename = "totalItems")]
|
||||
pub total_items: Vec<T>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct Activity {
|
||||
// #[serde(rename = "@context")]
|
||||
// #[serde(deserialize_with = "expand_partial")]
|
||||
// pub ap_context: Context,
|
||||
pub id: String,
|
||||
pub struct Attachment {
|
||||
#[serde(rename = "type")]
|
||||
pub kind: ActivityKind,
|
||||
#[serde(deserialize_with = "expand_partial")]
|
||||
pub attributed_to: Actor,
|
||||
pub kind: String,
|
||||
pub content: Option<String>,
|
||||
pub context: Option<String>,
|
||||
#[serde(deserialize_with = "pull_single_into_vec")]
|
||||
pub to: Vec<String>,
|
||||
pub url: Option<String>,
|
||||
pub url: String,
|
||||
}
|
||||
|
||||
#[derive(Clone, Serialize, Deserialize, Debug)]
|
||||
pub struct ObjectLD {
|
||||
// TODO: maybe this can work as attachment w/ the ID being more like
|
||||
// the LD IDs?
|
||||
#[derive(Debug, Clone, Deserialize)]
|
||||
pub struct Image {
|
||||
#[serde(flatten)]
|
||||
pub base: ObjectBase,
|
||||
#[serde(rename = "type")]
|
||||
pub kind: Option<ObjectKind>,
|
||||
pub id: String,
|
||||
#[serde(deserialize_with = "into_vec")]
|
||||
pub url: Vec<Link>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Deserialize)]
|
||||
pub struct Audience {
|
||||
#[serde(rename = "type")]
|
||||
pub kind: String,
|
||||
pub name: String,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Deserialize)]
|
||||
pub enum Unit {
|
||||
#[serde(rename = "m")]
|
||||
Meters,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Deserialize)]
|
||||
pub struct Location {
|
||||
#[serde(rename = "type")]
|
||||
pub kind: String,
|
||||
pub name: String,
|
||||
pub longitude: Option<f64>,
|
||||
pub latitude: Option<f64>,
|
||||
pub altitude: Option<f64>,
|
||||
pub units: Unit,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Deserialize)]
|
||||
pub struct Preview {
|
||||
#[serde(rename = "type")]
|
||||
pub kind: String,
|
||||
pub name: String,
|
||||
pub duration: Option<String>,
|
||||
pub url: Link,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Deserialize)]
|
||||
pub struct APResult {
|
||||
#[serde(rename = "type")]
|
||||
pub kind: String,
|
||||
pub name: String,
|
||||
}
|
||||
|
||||
/// ObjectBase contains base Activity Streams
|
||||
/// members that all objects should have. Except kind.
|
||||
///
|
||||
/// This object is intended to be used by inlining it into
|
||||
/// other serializable/deserializable objects.
|
||||
#[derive(Debug, Clone, Deserialize, Default)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct ObjectBase {
|
||||
#[serde(rename = "@context")]
|
||||
pub context_uri: Option<String>,
|
||||
#[serde(deserialize_with = "expand_partial")]
|
||||
pub ap_context: APContext,
|
||||
pub name: Option<String>,
|
||||
pub name_map: Option<HashMap<String, String>>,
|
||||
#[serde(deserialize_with = "into_vec")]
|
||||
pub attachment: Vec<Attachment>,
|
||||
#[serde(deserialize_with = "into_vec")]
|
||||
pub attributed_to: Vec<Actor>,
|
||||
pub audience: Option<Audience>,
|
||||
pub media_type: Option<String>,
|
||||
pub content: Option<String>,
|
||||
pub content_map: Option<HashMap<String, String>>,
|
||||
pub context: Option<String>,
|
||||
pub start_time: Option<String>,
|
||||
pub end_time: Option<String>,
|
||||
pub generator: Option<Actor>,
|
||||
#[serde(deserialize_with = "into_vec")]
|
||||
pub icon: Vec<Link>,
|
||||
// omit in_reply_to
|
||||
pub location: Option<Location>,
|
||||
pub preview: Option<Preview>,
|
||||
pub published: Option<String>,
|
||||
pub updated: Option<String>,
|
||||
pub replies: Option<Collection<()>>, // TODO: type
|
||||
pub summary: Option<String>,
|
||||
pub summary_map: Option<HashMap<String, String>>,
|
||||
#[serde(deserialize_with = "into_vec")]
|
||||
pub tag: Vec<Actor>,
|
||||
// omit url for now: need to merge into_vec & expand_partial
|
||||
#[serde(deserialize_with = "into_vec")]
|
||||
pub to: Vec<String>,
|
||||
#[serde(deserialize_with = "into_vec")]
|
||||
pub bto: Vec<String>,
|
||||
#[serde(deserialize_with = "into_vec")]
|
||||
pub cc: Vec<String>,
|
||||
#[serde(deserialize_with = "into_vec")]
|
||||
pub bcc: Vec<String>,
|
||||
pub duration: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Deserialize, Resolvable, IRI, Default)]
|
||||
pub struct Object {
|
||||
#[serde(flatten)]
|
||||
pub base: ObjectBase,
|
||||
#[serde(rename = "type")]
|
||||
pub kind: Option<ObjectKind>,
|
||||
pub id: String,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Deserialize)]
|
||||
pub struct Link {
|
||||
#[serde(rename = "type")]
|
||||
pub kind: Option<ActivityKind>,
|
||||
pub name: Option<String>,
|
||||
pub href: String,
|
||||
#[serde(rename = "hreflang")]
|
||||
pub href_lang: Option<String>,
|
||||
#[serde(rename = "mediaType")]
|
||||
pub media_type: Option<String>,
|
||||
pub height: u32,
|
||||
pub width: u32,
|
||||
}
|
||||
|
||||
/// An Activity is a subtype of Object that describes
|
||||
/// some form of action that may happen,
|
||||
/// is currently happening, or has already happened.
|
||||
///
|
||||
/// The Activity type itself serves as an abstract base type
|
||||
/// for all types of activities.
|
||||
/// It is important to note that the Activity type itself
|
||||
/// does not carry any specific semantics about the kind of action being taken.
|
||||
#[derive(Debug, Clone, Deserialize, Resolvable)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct Activity {
|
||||
#[serde(flatten)]
|
||||
pub base: ObjectBase,
|
||||
#[serde(rename = "type")]
|
||||
pub kind: Option<ActivityKind>,
|
||||
pub id: String,
|
||||
#[serde(deserialize_with = "expand_partial")]
|
||||
pub actor: Option<Actor>,
|
||||
#[serde(deserialize_with = "expand_partial")]
|
||||
pub object: Option<Object>,
|
||||
pub result: Option<APResult>,
|
||||
pub target: Option<Basic>,
|
||||
pub origin: Option<Basic>,
|
||||
pub instrument: Option<Basic>,
|
||||
}
|
||||
|
||||
/// Instances of IntransitiveActivity are a subtype of Activity
|
||||
/// representing intransitive actions.
|
||||
#[derive(Debug, Clone, Deserialize, Resolvable)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct IntransitiveActivity {
|
||||
#[serde(flatten)]
|
||||
pub base: ObjectBase,
|
||||
#[serde(rename = "type")]
|
||||
pub kind: Option<ActivityKind>,
|
||||
pub id: String,
|
||||
#[serde(deserialize_with = "expand_partial")]
|
||||
pub actor: Option<Actor>,
|
||||
pub result: Option<APResult>,
|
||||
pub target: Option<Basic>,
|
||||
pub origin: Option<Basic>,
|
||||
pub instrument: Option<Basic>,
|
||||
}
|
||||
pub enum ActorType {
|
||||
Application,
|
||||
Group,
|
||||
Organization,
|
||||
Person,
|
||||
Service,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Deserialize)]
|
||||
pub struct Basic {
|
||||
#[serde(rename = "type")]
|
||||
pub kind: Option<ActivityKind>,
|
||||
pub name: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Deserialize, IRI, Default, Resolvable)]
|
||||
pub struct Actor {
|
||||
pub id: String,
|
||||
#[serde(rename = "type")]
|
||||
pub kind: Option<ActivityKind>,
|
||||
|
@ -117,7 +322,7 @@ pub async fn test() {
|
|||
"url": "https://localhost/u/test/h/6Q8BFF8W6PZT2ddngZ"
|
||||
}"#;
|
||||
|
||||
let obj = serde_json::from_str::<Activity>(obj).unwrap();
|
||||
let obj = serde_json::from_str::<Object>(obj).unwrap();
|
||||
println!();
|
||||
println!("{:#?}", obj);
|
||||
}
|
||||
|
|
|
@ -1,64 +0,0 @@
|
|||
use async_trait::async_trait;
|
||||
|
||||
use super::{
|
||||
context::{self, Context},
|
||||
resolve, ActivityKind, Actor, ExpandError, ExpandLD, ObjectLD,
|
||||
};
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Note {
|
||||
pub id: String,
|
||||
pub content: Option<String>,
|
||||
pub context: Option<String>,
|
||||
pub published_at: Option<String>,
|
||||
pub author: Actor,
|
||||
pub to: Vec<Actor>,
|
||||
pub url: Option<String>,
|
||||
pub conversation: Option<String>,
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl ExpandLD<Note> for Note {
|
||||
async fn expand(obj: &ObjectLD) -> Result<Note, ExpandError> {
|
||||
let obj = obj.clone();
|
||||
let resolver = resolve::Resolver::new();
|
||||
if let Some(kind) = obj.kind {
|
||||
if let ActivityKind::Note = kind {
|
||||
Ok(Note {
|
||||
id: obj.id,
|
||||
content: obj.content,
|
||||
published_at: obj.published,
|
||||
author: obj
|
||||
.attributed_to
|
||||
.map(|id| Actor { id })
|
||||
.ok_or(ExpandError::NoAttribution)?,
|
||||
to: obj.to_uris.into_iter().map(|id| Actor { id }).collect(),
|
||||
url: obj.url,
|
||||
context: obj.context,
|
||||
conversation: obj.conversation,
|
||||
})
|
||||
} else {
|
||||
Err(ExpandError::InvalidKind(Some(kind)))
|
||||
}
|
||||
} else {
|
||||
Err(ExpandError::InvalidKind(None))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Into<ObjectLD> for Note {
|
||||
fn into(self) -> ObjectLD {
|
||||
ObjectLD {
|
||||
context_uri: Some(context::CONTEXT_ID.to_string()),
|
||||
id: self.id.clone(),
|
||||
kind: Some(ActivityKind::Note),
|
||||
attributed_to: Some(self.author.id),
|
||||
published: self.published_at,
|
||||
content: self.content,
|
||||
context: self.context,
|
||||
conversation: self.conversation,
|
||||
url: Some(self.id),
|
||||
to_uris: self.to.into_iter().map(|a| a.id).collect(),
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue