]> Untitled Git - lemmy.git/commitdiff
pull in activitypub library
authorFelix <me@nutomic.com>
Sat, 29 Feb 2020 11:42:44 +0000 (12:42 +0100)
committerFelix <me@nutomic.com>
Sat, 29 Feb 2020 11:42:44 +0000 (12:42 +0100)
17 files changed:
README.md
server/Cargo.lock
server/Cargo.toml
server/src/activitypub/activity.rs [new file with mode: 0644]
server/src/activitypub/actor/mod.rs [new file with mode: 0644]
server/src/activitypub/actor/properties.rs [new file with mode: 0644]
server/src/activitypub/collection.rs [new file with mode: 0644]
server/src/activitypub/endpoint.rs [new file with mode: 0644]
server/src/activitypub/link.rs [new file with mode: 0644]
server/src/activitypub/mod.rs [new file with mode: 0644]
server/src/activitypub/object/mod.rs [new file with mode: 0644]
server/src/activitypub/object/properties.rs [new file with mode: 0644]
server/src/apub/community.rs
server/src/apub/post.rs
server/src/apub/puller.rs
server/src/apub/user.rs
server/src/lib.rs

index 81eceb74a63ac1dcf643052fb56d1139ce057cc8..fb99d301a270b3731d3410589d554ceb66ace7d9 100644 (file)
--- a/README.md
+++ b/README.md
@@ -165,3 +165,9 @@ ts-node translation_report.ts
 ## Credits
 
 Logo made by Andy Cuccaro (@andycuccaro) under the CC-BY-SA 4.0 license.
+
+## License
+
+All code is licensed under AGPLv3 unless otherwise indicated.
+
+The code in `server/src/activitypub` is taken from the [Aardwolf/activitypub](https://crates.io/crates/activitypub) crate and licensed under GPLv3.
index 125319206ec789f28e249ed9dca09390548154f8..242fa789354de29e9338981f726b27724288afc8 100644 (file)
@@ -1493,11 +1493,15 @@ name = "lemmy_server"
 version = "0.0.1"
 dependencies = [
  "activitypub 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "activitystreams-derive 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "activitystreams-traits 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "activitystreams-types 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "actix 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "actix-files 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "actix-rt 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "actix-web 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "actix-web-actors 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "anyhow 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)",
  "bcrypt 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "chrono 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)",
  "config 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1517,6 +1521,7 @@ dependencies = [
  "reqwest 0.9.24 (registry+https://github.com/rust-lang/crates.io-index)",
  "rss 1.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_derive 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_json 1.0.45 (registry+https://github.com/rust-lang/crates.io-index)",
  "sha2 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "strum 0.17.1 (registry+https://github.com/rust-lang/crates.io-index)",
index 828230572fba57264ed16cefc06bff5d30c668d8..1b6ea3053f3057747eb5d91afa97ee31c4d26d21 100644 (file)
@@ -13,6 +13,7 @@ activitypub = "0.2.0"
 chrono = { version = "0.4.7", features = ["serde"] }
 failure = "0.1.5"
 serde_json = { version = "1.0.45", features = ["preserve_order"]}
+serde_derive = "1.0"
 serde = { version = "1.0.94", features = ["derive"] }
 actix = "0.9.0"
 actix-web = "2.0.0"
@@ -33,4 +34,11 @@ rss = "1.9.0"
 htmlescape = "0.3.1"
 config = "0.10.1"
 hjson = "0.8.2"
-reqwest = "0.9.24"
\ No newline at end of file
+reqwest = "0.9.24"
+activitystreams-derive = "0.2"
+activitystreams-traits = "0.2"
+activitystreams-types = "0.3"
+
+
+[dev-dependencies]
+anyhow = "1.0"
diff --git a/server/src/activitypub/activity.rs b/server/src/activitypub/activity.rs
new file mode 100644 (file)
index 0000000..c92b6ea
--- /dev/null
@@ -0,0 +1,1496 @@
+/*
+ * This file is part of ActivityPub.
+ *
+ * Copyright © 2018 Riley Trautman
+ *
+ * ActivityPub is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * ActivityPub is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with ActivityPub.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+//! Activity traits and types
+
+pub use activitystreams_traits::{Activity, IntransitiveActivity};
+pub use activitystreams_types::activity::{kind, properties, ActivityExt};
+use serde_derive::{Deserialize, Serialize};
+
+use self::{kind::*, properties::*};
+use activitypub::object::{
+  properties::{ApObjectProperties, ObjectProperties},
+  ApObjectExt, Object, ObjectExt,
+};
+
+/// Indicates that the actor accepts the object.
+///
+/// The target property can be used in certain circumstances to indicate the context into which the
+/// object has been accepted.
+#[derive(Clone, Debug, Default, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct Accept {
+  #[serde(rename = "type")]
+  kind: AcceptType,
+
+  #[serde(flatten)]
+  pub accept_props: AcceptProperties,
+
+  #[serde(flatten)]
+  pub object_props: ObjectProperties,
+
+  #[serde(flatten)]
+  pub ap_object_props: ApObjectProperties,
+
+  #[serde(flatten)]
+  pub activity_props: ActivityProperties,
+}
+
+impl Object for Accept {}
+impl ObjectExt for Accept {
+  fn props(&self) -> &ObjectProperties {
+    &self.object_props
+  }
+
+  fn props_mut(&mut self) -> &mut ObjectProperties {
+    &mut self.object_props
+  }
+}
+impl ApObjectExt for Accept {
+  fn props(&self) -> &ApObjectProperties {
+    &self.ap_object_props
+  }
+
+  fn props_mut(&mut self) -> &mut ApObjectProperties {
+    &mut self.ap_object_props
+  }
+}
+impl Activity for Accept {}
+impl ActivityExt for Accept {
+  fn props(&self) -> &ActivityProperties {
+    &self.activity_props
+  }
+
+  fn props_mut(&mut self) -> &mut ActivityProperties {
+    &mut self.activity_props
+  }
+}
+
+/// Indicates that the actor has added the object to the target.
+///
+/// If the target property is not explicitly specified, the target would need to be determined
+/// implicitly by context. The origin can be used to identify the context from which the object
+/// originated.
+#[derive(Clone, Debug, Default, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct Add {
+  #[serde(rename = "type")]
+  kind: AddType,
+
+  #[serde(flatten)]
+  pub add_props: AddProperties,
+
+  #[serde(flatten)]
+  pub object_props: ObjectProperties,
+
+  #[serde(flatten)]
+  pub ap_object_props: ApObjectProperties,
+
+  #[serde(flatten)]
+  pub activity_props: ActivityProperties,
+}
+
+impl Object for Add {}
+impl ObjectExt for Add {
+  fn props(&self) -> &ObjectProperties {
+    &self.object_props
+  }
+
+  fn props_mut(&mut self) -> &mut ObjectProperties {
+    &mut self.object_props
+  }
+}
+impl ApObjectExt for Add {
+  fn props(&self) -> &ApObjectProperties {
+    &self.ap_object_props
+  }
+
+  fn props_mut(&mut self) -> &mut ApObjectProperties {
+    &mut self.ap_object_props
+  }
+}
+impl Activity for Add {}
+impl ActivityExt for Add {
+  fn props(&self) -> &ActivityProperties {
+    &self.activity_props
+  }
+
+  fn props_mut(&mut self) -> &mut ActivityProperties {
+    &mut self.activity_props
+  }
+}
+
+/// Indicates that the actor has moved object from origin to target.
+///
+/// If the origin or target are not specified, either can be determined by context.
+#[derive(Clone, Debug, Default, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct AMove {
+  #[serde(rename = "type")]
+  kind: MoveType,
+
+  #[serde(flatten)]
+  pub move_props: MoveProperties,
+
+  #[serde(flatten)]
+  pub object_props: ObjectProperties,
+
+  #[serde(flatten)]
+  pub ap_object_props: ApObjectProperties,
+
+  #[serde(flatten)]
+  pub activity_props: ActivityProperties,
+}
+
+impl Object for AMove {}
+impl ObjectExt for AMove {
+  fn props(&self) -> &ObjectProperties {
+    &self.object_props
+  }
+
+  fn props_mut(&mut self) -> &mut ObjectProperties {
+    &mut self.object_props
+  }
+}
+impl ApObjectExt for AMove {
+  fn props(&self) -> &ApObjectProperties {
+    &self.ap_object_props
+  }
+
+  fn props_mut(&mut self) -> &mut ApObjectProperties {
+    &mut self.ap_object_props
+  }
+}
+impl Activity for AMove {}
+impl ActivityExt for AMove {
+  fn props(&self) -> &ActivityProperties {
+    &self.activity_props
+  }
+
+  fn props_mut(&mut self) -> &mut ActivityProperties {
+    &mut self.activity_props
+  }
+}
+
+/// Indicates that the actor is calling the target's attention the object.
+///
+/// The origin typically has no defined meaning.
+#[derive(Clone, Debug, Default, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct Announce {
+  #[serde(rename = "type")]
+  kind: AnnounceType,
+
+  #[serde(flatten)]
+  pub announce_props: AnnounceProperties,
+
+  #[serde(flatten)]
+  pub object_props: ObjectProperties,
+
+  #[serde(flatten)]
+  pub ap_object_props: ApObjectProperties,
+
+  #[serde(flatten)]
+  pub activity_props: ActivityProperties,
+}
+
+impl Object for Announce {}
+impl ObjectExt for Announce {
+  fn props(&self) -> &ObjectProperties {
+    &self.object_props
+  }
+
+  fn props_mut(&mut self) -> &mut ObjectProperties {
+    &mut self.object_props
+  }
+}
+impl ApObjectExt for Announce {
+  fn props(&self) -> &ApObjectProperties {
+    &self.ap_object_props
+  }
+
+  fn props_mut(&mut self) -> &mut ApObjectProperties {
+    &mut self.ap_object_props
+  }
+}
+impl Activity for Announce {}
+impl ActivityExt for Announce {
+  fn props(&self) -> &ActivityProperties {
+    &self.activity_props
+  }
+
+  fn props_mut(&mut self) -> &mut ActivityProperties {
+    &mut self.activity_props
+  }
+}
+
+/// An IntransitiveActivity that indicates that the actor has arrived at the location.
+///
+/// The origin can be used to identify the context from which the actor originated. The target
+/// typically has no defined meaning.
+#[derive(Clone, Debug, Default, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct Arrive {
+  #[serde(rename = "type")]
+  kind: ArriveType,
+
+  #[serde(flatten)]
+  pub arrive_props: ArriveProperties,
+
+  #[serde(flatten)]
+  pub object_props: ObjectProperties,
+
+  #[serde(flatten)]
+  pub ap_object_props: ApObjectProperties,
+
+  #[serde(flatten)]
+  pub activity_props: ActivityProperties,
+}
+
+impl Object for Arrive {}
+impl ObjectExt for Arrive {
+  fn props(&self) -> &ObjectProperties {
+    &self.object_props
+  }
+
+  fn props_mut(&mut self) -> &mut ObjectProperties {
+    &mut self.object_props
+  }
+}
+impl ApObjectExt for Arrive {
+  fn props(&self) -> &ApObjectProperties {
+    &self.ap_object_props
+  }
+
+  fn props_mut(&mut self) -> &mut ApObjectProperties {
+    &mut self.ap_object_props
+  }
+}
+impl Activity for Arrive {}
+impl ActivityExt for Arrive {
+  fn props(&self) -> &ActivityProperties {
+    &self.activity_props
+  }
+
+  fn props_mut(&mut self) -> &mut ActivityProperties {
+    &mut self.activity_props
+  }
+}
+impl IntransitiveActivity for Arrive {}
+
+/// Indicates that the actor is blocking the object.
+///
+/// Blocking is a stronger form of Ignore. The typical use is to support social systems that allow
+/// one user to block activities or content of other users. The target and origin typically have no
+/// defined meaning.
+#[derive(Clone, Debug, Default, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct Block {
+  #[serde(rename = "type")]
+  kind: BlockType,
+
+  #[serde(flatten)]
+  pub block_props: BlockProperties,
+
+  #[serde(flatten)]
+  pub object_props: ObjectProperties,
+
+  #[serde(flatten)]
+  pub ap_object_props: ApObjectProperties,
+
+  #[serde(flatten)]
+  pub activity_props: ActivityProperties,
+}
+
+impl Object for Block {}
+impl ObjectExt for Block {
+  fn props(&self) -> &ObjectProperties {
+    &self.object_props
+  }
+
+  fn props_mut(&mut self) -> &mut ObjectProperties {
+    &mut self.object_props
+  }
+}
+impl ApObjectExt for Block {
+  fn props(&self) -> &ApObjectProperties {
+    &self.ap_object_props
+  }
+
+  fn props_mut(&mut self) -> &mut ApObjectProperties {
+    &mut self.ap_object_props
+  }
+}
+impl Activity for Block {}
+impl ActivityExt for Block {
+  fn props(&self) -> &ActivityProperties {
+    &self.activity_props
+  }
+
+  fn props_mut(&mut self) -> &mut ActivityProperties {
+    &mut self.activity_props
+  }
+}
+
+/// Indicates that the actor has created the object.
+#[derive(Clone, Debug, Default, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct Create {
+  #[serde(rename = "type")]
+  kind: CreateType,
+
+  #[serde(flatten)]
+  pub create_props: CreateProperties,
+
+  #[serde(flatten)]
+  pub object_props: ObjectProperties,
+
+  #[serde(flatten)]
+  pub ap_object_props: ApObjectProperties,
+
+  #[serde(flatten)]
+  pub activity_props: ActivityProperties,
+}
+
+impl Object for Create {}
+impl ObjectExt for Create {
+  fn props(&self) -> &ObjectProperties {
+    &self.object_props
+  }
+
+  fn props_mut(&mut self) -> &mut ObjectProperties {
+    &mut self.object_props
+  }
+}
+impl ApObjectExt for Create {
+  fn props(&self) -> &ApObjectProperties {
+    &self.ap_object_props
+  }
+
+  fn props_mut(&mut self) -> &mut ApObjectProperties {
+    &mut self.ap_object_props
+  }
+}
+impl Activity for Create {}
+impl ActivityExt for Create {
+  fn props(&self) -> &ActivityProperties {
+    &self.activity_props
+  }
+
+  fn props_mut(&mut self) -> &mut ActivityProperties {
+    &mut self.activity_props
+  }
+}
+
+/// Indicates that the actor has deleted the object.
+///
+/// If specified, the origin indicates the context from which the object was deleted.
+#[derive(Clone, Debug, Default, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct Delete {
+  #[serde(rename = "type")]
+  kind: DeleteType,
+
+  #[serde(flatten)]
+  pub delete_props: DeleteProperties,
+
+  #[serde(flatten)]
+  pub object_props: ObjectProperties,
+
+  #[serde(flatten)]
+  pub ap_object_props: ApObjectProperties,
+
+  #[serde(flatten)]
+  pub activity_props: ActivityProperties,
+}
+
+impl Object for Delete {}
+impl ObjectExt for Delete {
+  fn props(&self) -> &ObjectProperties {
+    &self.object_props
+  }
+
+  fn props_mut(&mut self) -> &mut ObjectProperties {
+    &mut self.object_props
+  }
+}
+impl ApObjectExt for Delete {
+  fn props(&self) -> &ApObjectProperties {
+    &self.ap_object_props
+  }
+
+  fn props_mut(&mut self) -> &mut ApObjectProperties {
+    &mut self.ap_object_props
+  }
+}
+impl Activity for Delete {}
+impl ActivityExt for Delete {
+  fn props(&self) -> &ActivityProperties {
+    &self.activity_props
+  }
+
+  fn props_mut(&mut self) -> &mut ActivityProperties {
+    &mut self.activity_props
+  }
+}
+
+/// Indicates that the actor dislikes the object.
+#[derive(Clone, Debug, Default, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct Dislike {
+  #[serde(rename = "type")]
+  kind: DislikeType,
+
+  #[serde(flatten)]
+  pub dislike_props: DislikeProperties,
+
+  #[serde(flatten)]
+  pub object_props: ObjectProperties,
+
+  #[serde(flatten)]
+  pub ap_object_props: ApObjectProperties,
+
+  #[serde(flatten)]
+  pub activity_props: ActivityProperties,
+}
+
+impl Object for Dislike {}
+impl ObjectExt for Dislike {
+  fn props(&self) -> &ObjectProperties {
+    &self.object_props
+  }
+
+  fn props_mut(&mut self) -> &mut ObjectProperties {
+    &mut self.object_props
+  }
+}
+impl ApObjectExt for Dislike {
+  fn props(&self) -> &ApObjectProperties {
+    &self.ap_object_props
+  }
+
+  fn props_mut(&mut self) -> &mut ApObjectProperties {
+    &mut self.ap_object_props
+  }
+}
+impl Activity for Dislike {}
+impl ActivityExt for Dislike {
+  fn props(&self) -> &ActivityProperties {
+    &self.activity_props
+  }
+
+  fn props_mut(&mut self) -> &mut ActivityProperties {
+    &mut self.activity_props
+  }
+}
+
+/// Indicates that the actor is "flagging" the object.
+///
+/// Flagging is defined in the sense common to many social platforms as reporting content as being
+/// inappropriate for any number of reasons.
+#[derive(Clone, Debug, Default, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct Flag {
+  #[serde(rename = "type")]
+  kind: FlagType,
+
+  #[serde(flatten)]
+  pub flag_props: FlagProperties,
+
+  #[serde(flatten)]
+  pub object_props: ObjectProperties,
+
+  #[serde(flatten)]
+  pub ap_object_props: ApObjectProperties,
+
+  #[serde(flatten)]
+  pub activity_props: ActivityProperties,
+}
+
+impl Object for Flag {}
+impl ObjectExt for Flag {
+  fn props(&self) -> &ObjectProperties {
+    &self.object_props
+  }
+
+  fn props_mut(&mut self) -> &mut ObjectProperties {
+    &mut self.object_props
+  }
+}
+impl ApObjectExt for Flag {
+  fn props(&self) -> &ApObjectProperties {
+    &self.ap_object_props
+  }
+
+  fn props_mut(&mut self) -> &mut ApObjectProperties {
+    &mut self.ap_object_props
+  }
+}
+impl Activity for Flag {}
+impl ActivityExt for Flag {
+  fn props(&self) -> &ActivityProperties {
+    &self.activity_props
+  }
+
+  fn props_mut(&mut self) -> &mut ActivityProperties {
+    &mut self.activity_props
+  }
+}
+
+/// Indicates that the actor is "following" the object.
+///
+/// Following is defined in the sense typically used within Social systems in which the actor is
+/// interested in any activity performed by or on the object. The target and origin typically have
+/// no defined meaning.
+#[derive(Clone, Debug, Default, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct Follow {
+  #[serde(rename = "type")]
+  kind: FollowType,
+
+  #[serde(flatten)]
+  pub follow_props: FollowProperties,
+
+  #[serde(flatten)]
+  pub object_props: ObjectProperties,
+
+  #[serde(flatten)]
+  pub ap_object_props: ApObjectProperties,
+
+  #[serde(flatten)]
+  pub activity_props: ActivityProperties,
+}
+
+impl Object for Follow {}
+impl ObjectExt for Follow {
+  fn props(&self) -> &ObjectProperties {
+    &self.object_props
+  }
+
+  fn props_mut(&mut self) -> &mut ObjectProperties {
+    &mut self.object_props
+  }
+}
+impl ApObjectExt for Follow {
+  fn props(&self) -> &ApObjectProperties {
+    &self.ap_object_props
+  }
+
+  fn props_mut(&mut self) -> &mut ApObjectProperties {
+    &mut self.ap_object_props
+  }
+}
+impl Activity for Follow {}
+impl ActivityExt for Follow {
+  fn props(&self) -> &ActivityProperties {
+    &self.activity_props
+  }
+
+  fn props_mut(&mut self) -> &mut ActivityProperties {
+    &mut self.activity_props
+  }
+}
+
+/// Indicates that the actor is ignoring the object.
+///
+/// The target and origin typically have no defined meaning.
+#[derive(Clone, Debug, Default, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct Ignore {
+  #[serde(rename = "type")]
+  kind: IgnoreType,
+
+  #[serde(flatten)]
+  pub ignore_props: IgnoreProperties,
+
+  #[serde(flatten)]
+  pub object_props: ObjectProperties,
+
+  #[serde(flatten)]
+  pub ap_object_props: ApObjectProperties,
+
+  #[serde(flatten)]
+  pub activity_props: ActivityProperties,
+}
+
+impl Object for Ignore {}
+impl ObjectExt for Ignore {
+  fn props(&self) -> &ObjectProperties {
+    &self.object_props
+  }
+
+  fn props_mut(&mut self) -> &mut ObjectProperties {
+    &mut self.object_props
+  }
+}
+impl ApObjectExt for Ignore {
+  fn props(&self) -> &ApObjectProperties {
+    &self.ap_object_props
+  }
+
+  fn props_mut(&mut self) -> &mut ApObjectProperties {
+    &mut self.ap_object_props
+  }
+}
+impl Activity for Ignore {}
+impl ActivityExt for Ignore {
+  fn props(&self) -> &ActivityProperties {
+    &self.activity_props
+  }
+
+  fn props_mut(&mut self) -> &mut ActivityProperties {
+    &mut self.activity_props
+  }
+}
+
+/// A specialization of Offer in which the actor is extending an invitation for the object to the
+/// target.
+#[derive(Clone, Debug, Default, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct Invite {
+  #[serde(rename = "type")]
+  kind: InviteType,
+
+  #[serde(flatten)]
+  pub invite_props: InviteProperties,
+
+  #[serde(flatten)]
+  pub object_props: ObjectProperties,
+
+  #[serde(flatten)]
+  pub ap_object_props: ApObjectProperties,
+
+  #[serde(flatten)]
+  pub activity_props: ActivityProperties,
+}
+
+impl Object for Invite {}
+impl ObjectExt for Invite {
+  fn props(&self) -> &ObjectProperties {
+    &self.object_props
+  }
+
+  fn props_mut(&mut self) -> &mut ObjectProperties {
+    &mut self.object_props
+  }
+}
+impl ApObjectExt for Invite {
+  fn props(&self) -> &ApObjectProperties {
+    &self.ap_object_props
+  }
+
+  fn props_mut(&mut self) -> &mut ApObjectProperties {
+    &mut self.ap_object_props
+  }
+}
+impl Activity for Invite {}
+impl ActivityExt for Invite {
+  fn props(&self) -> &ActivityProperties {
+    &self.activity_props
+  }
+
+  fn props_mut(&mut self) -> &mut ActivityProperties {
+    &mut self.activity_props
+  }
+}
+
+/// Indicates that the actor has joined the object.
+///
+/// The target and origin typically have no defined meaning
+#[derive(Clone, Debug, Default, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct Join {
+  #[serde(rename = "type")]
+  kind: JoinType,
+
+  #[serde(flatten)]
+  pub join_props: JoinProperties,
+
+  #[serde(flatten)]
+  pub object_props: ObjectProperties,
+
+  #[serde(flatten)]
+  pub ap_object_props: ApObjectProperties,
+
+  #[serde(flatten)]
+  pub activity_props: ActivityProperties,
+}
+
+impl Object for Join {}
+impl ObjectExt for Join {
+  fn props(&self) -> &ObjectProperties {
+    &self.object_props
+  }
+
+  fn props_mut(&mut self) -> &mut ObjectProperties {
+    &mut self.object_props
+  }
+}
+impl ApObjectExt for Join {
+  fn props(&self) -> &ApObjectProperties {
+    &self.ap_object_props
+  }
+
+  fn props_mut(&mut self) -> &mut ApObjectProperties {
+    &mut self.ap_object_props
+  }
+}
+impl Activity for Join {}
+impl ActivityExt for Join {
+  fn props(&self) -> &ActivityProperties {
+    &self.activity_props
+  }
+
+  fn props_mut(&mut self) -> &mut ActivityProperties {
+    &mut self.activity_props
+  }
+}
+
+/// Indicates that the actor has left the object.
+///
+/// The target and origin typically have no meaning.
+#[derive(Clone, Debug, Default, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct Leave {
+  #[serde(rename = "type")]
+  kind: LeaveType,
+
+  #[serde(flatten)]
+  pub leave_props: LeaveProperties,
+
+  #[serde(flatten)]
+  pub object_props: ObjectProperties,
+
+  #[serde(flatten)]
+  pub ap_object_props: ApObjectProperties,
+
+  #[serde(flatten)]
+  pub activity_props: ActivityProperties,
+}
+
+impl Object for Leave {}
+impl ObjectExt for Leave {
+  fn props(&self) -> &ObjectProperties {
+    &self.object_props
+  }
+
+  fn props_mut(&mut self) -> &mut ObjectProperties {
+    &mut self.object_props
+  }
+}
+impl ApObjectExt for Leave {
+  fn props(&self) -> &ApObjectProperties {
+    &self.ap_object_props
+  }
+
+  fn props_mut(&mut self) -> &mut ApObjectProperties {
+    &mut self.ap_object_props
+  }
+}
+impl Activity for Leave {}
+impl ActivityExt for Leave {
+  fn props(&self) -> &ActivityProperties {
+    &self.activity_props
+  }
+
+  fn props_mut(&mut self) -> &mut ActivityProperties {
+    &mut self.activity_props
+  }
+}
+
+/// Indicates that the actor likes, recommends or endorses the object.
+///
+/// The target and origin typically have no defined meaning.
+#[derive(Clone, Debug, Default, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct Like {
+  #[serde(rename = "type")]
+  kind: LikeType,
+
+  #[serde(flatten)]
+  pub like_props: LikeProperties,
+
+  #[serde(flatten)]
+  pub object_props: ObjectProperties,
+
+  #[serde(flatten)]
+  pub ap_object_props: ApObjectProperties,
+
+  #[serde(flatten)]
+  pub activity_props: ActivityProperties,
+}
+
+impl Object for Like {}
+impl ObjectExt for Like {
+  fn props(&self) -> &ObjectProperties {
+    &self.object_props
+  }
+
+  fn props_mut(&mut self) -> &mut ObjectProperties {
+    &mut self.object_props
+  }
+}
+impl ApObjectExt for Like {
+  fn props(&self) -> &ApObjectProperties {
+    &self.ap_object_props
+  }
+
+  fn props_mut(&mut self) -> &mut ApObjectProperties {
+    &mut self.ap_object_props
+  }
+}
+impl Activity for Like {}
+impl ActivityExt for Like {
+  fn props(&self) -> &ActivityProperties {
+    &self.activity_props
+  }
+
+  fn props_mut(&mut self) -> &mut ActivityProperties {
+    &mut self.activity_props
+  }
+}
+
+/// Indicates that the actor has listened to the object.
+#[derive(Clone, Debug, Default, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct Listen {
+  #[serde(rename = "type")]
+  kind: ListenType,
+
+  #[serde(flatten)]
+  pub listen_props: ListenProperties,
+
+  #[serde(flatten)]
+  pub object_props: ObjectProperties,
+
+  #[serde(flatten)]
+  pub ap_object_props: ApObjectProperties,
+
+  #[serde(flatten)]
+  pub activity_props: ActivityProperties,
+}
+
+impl Object for Listen {}
+impl ObjectExt for Listen {
+  fn props(&self) -> &ObjectProperties {
+    &self.object_props
+  }
+
+  fn props_mut(&mut self) -> &mut ObjectProperties {
+    &mut self.object_props
+  }
+}
+impl ApObjectExt for Listen {
+  fn props(&self) -> &ApObjectProperties {
+    &self.ap_object_props
+  }
+
+  fn props_mut(&mut self) -> &mut ApObjectProperties {
+    &mut self.ap_object_props
+  }
+}
+impl Activity for Listen {}
+impl ActivityExt for Listen {
+  fn props(&self) -> &ActivityProperties {
+    &self.activity_props
+  }
+
+  fn props_mut(&mut self) -> &mut ActivityProperties {
+    &mut self.activity_props
+  }
+}
+
+/// Indicates that the actor is offering the object.
+///
+/// If specified, the target indicates the entity to which the object is being offered.
+#[derive(Clone, Debug, Default, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct Offer {
+  #[serde(rename = "type")]
+  kind: OfferType,
+
+  #[serde(flatten)]
+  pub offer_props: OfferProperties,
+
+  #[serde(flatten)]
+  pub object_props: ObjectProperties,
+
+  #[serde(flatten)]
+  pub ap_object_props: ApObjectProperties,
+
+  #[serde(flatten)]
+  pub activity_props: ActivityProperties,
+}
+
+impl Object for Offer {}
+impl ObjectExt for Offer {
+  fn props(&self) -> &ObjectProperties {
+    &self.object_props
+  }
+
+  fn props_mut(&mut self) -> &mut ObjectProperties {
+    &mut self.object_props
+  }
+}
+impl ApObjectExt for Offer {
+  fn props(&self) -> &ApObjectProperties {
+    &self.ap_object_props
+  }
+
+  fn props_mut(&mut self) -> &mut ApObjectProperties {
+    &mut self.ap_object_props
+  }
+}
+impl Activity for Offer {}
+impl ActivityExt for Offer {
+  fn props(&self) -> &ActivityProperties {
+    &self.activity_props
+  }
+
+  fn props_mut(&mut self) -> &mut ActivityProperties {
+    &mut self.activity_props
+  }
+}
+
+/// Represents a question being asked.
+///
+/// Question objects are an extension of IntransitiveActivity. That is, the Question object is an
+/// Activity, but the direct object is the question itself and therefore it would not contain an
+/// object property.
+///
+/// Either of the anyOf and oneOf properties MAY be used to express possible answers, but a
+/// Question object MUST NOT have both properties.
+#[derive(Clone, Debug, Default, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct Question {
+  #[serde(rename = "type")]
+  kind: QuestionType,
+
+  #[serde(flatten)]
+  pub question_props: QuestionProperties,
+
+  #[serde(flatten)]
+  pub object_props: ObjectProperties,
+
+  #[serde(flatten)]
+  pub ap_object_props: ApObjectProperties,
+
+  #[serde(flatten)]
+  pub activity_props: ActivityProperties,
+}
+
+impl Object for Question {}
+impl ObjectExt for Question {
+  fn props(&self) -> &ObjectProperties {
+    &self.object_props
+  }
+
+  fn props_mut(&mut self) -> &mut ObjectProperties {
+    &mut self.object_props
+  }
+}
+impl ApObjectExt for Question {
+  fn props(&self) -> &ApObjectProperties {
+    &self.ap_object_props
+  }
+
+  fn props_mut(&mut self) -> &mut ApObjectProperties {
+    &mut self.ap_object_props
+  }
+}
+impl Activity for Question {}
+impl ActivityExt for Question {
+  fn props(&self) -> &ActivityProperties {
+    &self.activity_props
+  }
+
+  fn props_mut(&mut self) -> &mut ActivityProperties {
+    &mut self.activity_props
+  }
+}
+impl IntransitiveActivity for Question {}
+
+/// Indicates that the actor has read the object.
+#[derive(Clone, Debug, Default, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct Read {
+  #[serde(rename = "type")]
+  kind: ReadType,
+
+  #[serde(flatten)]
+  pub read_props: ReadProperties,
+
+  #[serde(flatten)]
+  pub object_props: ObjectProperties,
+
+  #[serde(flatten)]
+  pub ap_object_props: ApObjectProperties,
+
+  #[serde(flatten)]
+  pub activity_props: ActivityProperties,
+}
+
+impl Object for Read {}
+impl ObjectExt for Read {
+  fn props(&self) -> &ObjectProperties {
+    &self.object_props
+  }
+
+  fn props_mut(&mut self) -> &mut ObjectProperties {
+    &mut self.object_props
+  }
+}
+impl ApObjectExt for Read {
+  fn props(&self) -> &ApObjectProperties {
+    &self.ap_object_props
+  }
+
+  fn props_mut(&mut self) -> &mut ApObjectProperties {
+    &mut self.ap_object_props
+  }
+}
+impl Activity for Read {}
+impl ActivityExt for Read {
+  fn props(&self) -> &ActivityProperties {
+    &self.activity_props
+  }
+
+  fn props_mut(&mut self) -> &mut ActivityProperties {
+    &mut self.activity_props
+  }
+}
+
+/// Indicates that the actor is rejecting the object.
+///
+/// The target and origin typically have no defined meaning.
+#[derive(Clone, Debug, Default, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct Reject {
+  #[serde(rename = "type")]
+  kind: RejectType,
+
+  #[serde(flatten)]
+  pub reject_props: RejectProperties,
+
+  #[serde(flatten)]
+  pub object_props: ObjectProperties,
+
+  #[serde(flatten)]
+  pub ap_object_props: ApObjectProperties,
+
+  #[serde(flatten)]
+  pub activity_props: ActivityProperties,
+}
+
+impl Object for Reject {}
+impl ObjectExt for Reject {
+  fn props(&self) -> &ObjectProperties {
+    &self.object_props
+  }
+
+  fn props_mut(&mut self) -> &mut ObjectProperties {
+    &mut self.object_props
+  }
+}
+impl ApObjectExt for Reject {
+  fn props(&self) -> &ApObjectProperties {
+    &self.ap_object_props
+  }
+
+  fn props_mut(&mut self) -> &mut ApObjectProperties {
+    &mut self.ap_object_props
+  }
+}
+impl Activity for Reject {}
+impl ActivityExt for Reject {
+  fn props(&self) -> &ActivityProperties {
+    &self.activity_props
+  }
+
+  fn props_mut(&mut self) -> &mut ActivityProperties {
+    &mut self.activity_props
+  }
+}
+
+/// Indicates that the actor is removing the object.
+///
+/// If specified, the origin indicates the context from which the object is being removed.
+#[derive(Clone, Debug, Default, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct Remove {
+  #[serde(rename = "type")]
+  kind: RemoveType,
+
+  #[serde(flatten)]
+  pub remove_props: RemoveProperties,
+
+  #[serde(flatten)]
+  pub object_props: ObjectProperties,
+
+  #[serde(flatten)]
+  pub ap_object_props: ApObjectProperties,
+
+  #[serde(flatten)]
+  pub activity_props: ActivityProperties,
+}
+
+impl Object for Remove {}
+impl ObjectExt for Remove {
+  fn props(&self) -> &ObjectProperties {
+    &self.object_props
+  }
+
+  fn props_mut(&mut self) -> &mut ObjectProperties {
+    &mut self.object_props
+  }
+}
+impl ApObjectExt for Remove {
+  fn props(&self) -> &ApObjectProperties {
+    &self.ap_object_props
+  }
+
+  fn props_mut(&mut self) -> &mut ApObjectProperties {
+    &mut self.ap_object_props
+  }
+}
+impl Activity for Remove {}
+impl ActivityExt for Remove {
+  fn props(&self) -> &ActivityProperties {
+    &self.activity_props
+  }
+
+  fn props_mut(&mut self) -> &mut ActivityProperties {
+    &mut self.activity_props
+  }
+}
+
+/// A specialization of Accept indicating that the acceptance is tentative.
+#[derive(Clone, Debug, Default, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct TentativeAccept {
+  #[serde(rename = "type")]
+  kind: TentativeAcceptType,
+
+  #[serde(flatten)]
+  pub tentative_accept_props: TentativeAcceptProperties,
+
+  #[serde(flatten)]
+  pub object_props: ObjectProperties,
+
+  #[serde(flatten)]
+  pub ap_object_props: ApObjectProperties,
+
+  #[serde(flatten)]
+  pub activity_props: ActivityProperties,
+}
+
+impl Object for TentativeAccept {}
+impl ObjectExt for TentativeAccept {
+  fn props(&self) -> &ObjectProperties {
+    &self.object_props
+  }
+
+  fn props_mut(&mut self) -> &mut ObjectProperties {
+    &mut self.object_props
+  }
+}
+impl ApObjectExt for TentativeAccept {
+  fn props(&self) -> &ApObjectProperties {
+    &self.ap_object_props
+  }
+
+  fn props_mut(&mut self) -> &mut ApObjectProperties {
+    &mut self.ap_object_props
+  }
+}
+impl Activity for TentativeAccept {}
+impl ActivityExt for TentativeAccept {
+  fn props(&self) -> &ActivityProperties {
+    &self.activity_props
+  }
+
+  fn props_mut(&mut self) -> &mut ActivityProperties {
+    &mut self.activity_props
+  }
+}
+
+/// A specialization of Reject in which the rejection is considered tentative.
+#[derive(Clone, Debug, Default, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct TentativeReject {
+  #[serde(rename = "type")]
+  kind: TentativeRejectType,
+
+  #[serde(flatten)]
+  pub tentative_reject_props: TentativeRejectProperties,
+
+  #[serde(flatten)]
+  pub object_props: ObjectProperties,
+
+  #[serde(flatten)]
+  pub ap_object_props: ApObjectProperties,
+
+  #[serde(flatten)]
+  pub activity_props: ActivityProperties,
+}
+
+impl Object for TentativeReject {}
+impl ObjectExt for TentativeReject {
+  fn props(&self) -> &ObjectProperties {
+    &self.object_props
+  }
+
+  fn props_mut(&mut self) -> &mut ObjectProperties {
+    &mut self.object_props
+  }
+}
+impl ApObjectExt for TentativeReject {
+  fn props(&self) -> &ApObjectProperties {
+    &self.ap_object_props
+  }
+
+  fn props_mut(&mut self) -> &mut ApObjectProperties {
+    &mut self.ap_object_props
+  }
+}
+impl Activity for TentativeReject {}
+impl ActivityExt for TentativeReject {
+  fn props(&self) -> &ActivityProperties {
+    &self.activity_props
+  }
+
+  fn props_mut(&mut self) -> &mut ActivityProperties {
+    &mut self.activity_props
+  }
+}
+
+/// Indicates that the actor is traveling to target from origin.
+///
+/// Travel is an IntransitiveObject whose actor specifies the direct object. If the target or
+/// origin are not specified, either can be determined by context.
+#[derive(Clone, Debug, Default, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct Travel {
+  #[serde(rename = "type")]
+  kind: TravelType,
+
+  #[serde(flatten)]
+  pub travel_props: TravelProperties,
+
+  #[serde(flatten)]
+  pub object_props: ObjectProperties,
+
+  #[serde(flatten)]
+  pub ap_object_props: ApObjectProperties,
+
+  #[serde(flatten)]
+  pub activity_props: ActivityProperties,
+}
+
+impl Object for Travel {}
+impl ObjectExt for Travel {
+  fn props(&self) -> &ObjectProperties {
+    &self.object_props
+  }
+
+  fn props_mut(&mut self) -> &mut ObjectProperties {
+    &mut self.object_props
+  }
+}
+impl ApObjectExt for Travel {
+  fn props(&self) -> &ApObjectProperties {
+    &self.ap_object_props
+  }
+
+  fn props_mut(&mut self) -> &mut ApObjectProperties {
+    &mut self.ap_object_props
+  }
+}
+impl Activity for Travel {}
+impl ActivityExt for Travel {
+  fn props(&self) -> &ActivityProperties {
+    &self.activity_props
+  }
+
+  fn props_mut(&mut self) -> &mut ActivityProperties {
+    &mut self.activity_props
+  }
+}
+impl IntransitiveActivity for Travel {}
+
+/// Indicates that the actor is undoing the object.
+///
+/// In most cases, the object will be an Activity describing some previously performed action (for
+/// instance, a person may have previously "liked" an article but, for whatever reason, might
+/// choose to undo that like at some later point in time).
+///
+/// The target and origin typically have no defined meaning.
+#[derive(Clone, Debug, Default, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct Undo {
+  #[serde(rename = "type")]
+  kind: UndoType,
+
+  #[serde(flatten)]
+  pub undo_props: UndoProperties,
+
+  #[serde(flatten)]
+  pub object_props: ObjectProperties,
+
+  #[serde(flatten)]
+  pub ap_object_props: ApObjectProperties,
+
+  #[serde(flatten)]
+  pub activity_props: ActivityProperties,
+}
+
+impl Object for Undo {}
+impl ObjectExt for Undo {
+  fn props(&self) -> &ObjectProperties {
+    &self.object_props
+  }
+
+  fn props_mut(&mut self) -> &mut ObjectProperties {
+    &mut self.object_props
+  }
+}
+impl ApObjectExt for Undo {
+  fn props(&self) -> &ApObjectProperties {
+    &self.ap_object_props
+  }
+
+  fn props_mut(&mut self) -> &mut ApObjectProperties {
+    &mut self.ap_object_props
+  }
+}
+impl Activity for Undo {}
+impl ActivityExt for Undo {
+  fn props(&self) -> &ActivityProperties {
+    &self.activity_props
+  }
+
+  fn props_mut(&mut self) -> &mut ActivityProperties {
+    &mut self.activity_props
+  }
+}
+
+/// Indicates that the actor has updated the object.
+///
+/// Note, however, that this vocabulary does not define a mechanism for describing the actual set
+/// of modifications made to object.
+///
+/// The target and origin typically have no defined meaning.
+#[derive(Clone, Debug, Default, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct Update {
+  #[serde(rename = "type")]
+  kind: UpdateType,
+
+  #[serde(flatten)]
+  pub update_props: UpdateProperties,
+
+  #[serde(flatten)]
+  pub object_props: ObjectProperties,
+
+  #[serde(flatten)]
+  pub ap_object_props: ApObjectProperties,
+
+  #[serde(flatten)]
+  pub activity_props: ActivityProperties,
+}
+
+impl Object for Update {}
+impl ObjectExt for Update {
+  fn props(&self) -> &ObjectProperties {
+    &self.object_props
+  }
+
+  fn props_mut(&mut self) -> &mut ObjectProperties {
+    &mut self.object_props
+  }
+}
+impl ApObjectExt for Update {
+  fn props(&self) -> &ApObjectProperties {
+    &self.ap_object_props
+  }
+
+  fn props_mut(&mut self) -> &mut ApObjectProperties {
+    &mut self.ap_object_props
+  }
+}
+impl Activity for Update {}
+impl ActivityExt for Update {
+  fn props(&self) -> &ActivityProperties {
+    &self.activity_props
+  }
+
+  fn props_mut(&mut self) -> &mut ActivityProperties {
+    &mut self.activity_props
+  }
+}
+
+/// Indicates that the actor has viewed the object.
+#[derive(Clone, Debug, Default, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct View {
+  #[serde(rename = "type")]
+  kind: ViewType,
+
+  #[serde(flatten)]
+  pub view_props: ViewProperties,
+
+  #[serde(flatten)]
+  pub object_props: ObjectProperties,
+
+  #[serde(flatten)]
+  pub ap_object_props: ApObjectProperties,
+
+  #[serde(flatten)]
+  pub activity_props: ActivityProperties,
+}
+
+impl Object for View {}
+impl ObjectExt for View {
+  fn props(&self) -> &ObjectProperties {
+    &self.object_props
+  }
+
+  fn props_mut(&mut self) -> &mut ObjectProperties {
+    &mut self.object_props
+  }
+}
+impl ApObjectExt for View {
+  fn props(&self) -> &ApObjectProperties {
+    &self.ap_object_props
+  }
+
+  fn props_mut(&mut self) -> &mut ApObjectProperties {
+    &mut self.ap_object_props
+  }
+}
+impl Activity for View {}
+impl ActivityExt for View {
+  fn props(&self) -> &ActivityProperties {
+    &self.activity_props
+  }
+
+  fn props_mut(&mut self) -> &mut ActivityProperties {
+    &mut self.activity_props
+  }
+}
diff --git a/server/src/activitypub/actor/mod.rs b/server/src/activitypub/actor/mod.rs
new file mode 100644 (file)
index 0000000..adb0b2d
--- /dev/null
@@ -0,0 +1,291 @@
+/*
+ * This file is part of ActivityPub.
+ *
+ * Copyright © 2018 Riley Trautman
+ *
+ * ActivityPub is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * ActivityPub is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with ActivityPub.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+//! Actor traits and types
+
+use activitystreams_derive::Properties;
+pub use activitystreams_traits::Actor;
+pub use activitystreams_types::actor::kind;
+use serde_derive::{Deserialize, Serialize};
+
+pub mod properties;
+
+use self::{kind::*, properties::*};
+use activitypub::object::{
+  properties::{ApObjectProperties, ObjectProperties},
+  ApObjectExt, Object, ObjectExt,
+};
+
+/// The ActivityPub Actor Extension Trait
+///
+/// This trait provides generic access to an activitypub actor's properties
+pub trait ApActorExt: Actor {
+  fn props(&self) -> &ApActorProperties;
+  fn props_mut(&mut self) -> &mut ApActorProperties;
+}
+
+/// Describes a software application.
+#[derive(Clone, Debug, Default, Deserialize, Serialize, Properties)]
+#[serde(rename_all = "camelCase")]
+pub struct Application {
+  #[serde(rename = "type")]
+  kind: ApplicationType,
+
+  /// Adds all valid object properties to this struct
+  #[serde(flatten)]
+  pub object_props: ObjectProperties,
+
+  /// Adds all valid activitypub object properties to this struct
+  #[serde(flatten)]
+  pub ap_object_props: ApObjectProperties,
+
+  /// Adds all valid activitypub actor properties to this struct
+  #[serde(flatten)]
+  pub ap_actor_props: ApActorProperties,
+}
+
+impl Object for Application {}
+impl ObjectExt for Application {
+  fn props(&self) -> &ObjectProperties {
+    &self.object_props
+  }
+
+  fn props_mut(&mut self) -> &mut ObjectProperties {
+    &mut self.object_props
+  }
+}
+impl ApObjectExt for Application {
+  fn props(&self) -> &ApObjectProperties {
+    &self.ap_object_props
+  }
+
+  fn props_mut(&mut self) -> &mut ApObjectProperties {
+    &mut self.ap_object_props
+  }
+}
+impl Actor for Application {}
+impl ApActorExt for Application {
+  fn props(&self) -> &ApActorProperties {
+    &self.ap_actor_props
+  }
+
+  fn props_mut(&mut self) -> &mut ApActorProperties {
+    &mut self.ap_actor_props
+  }
+}
+
+/// Represents a formal or informal collective of Actors.
+#[derive(Clone, Debug, Default, Deserialize, Serialize, Properties)]
+#[serde(rename_all = "camelCase")]
+pub struct Group {
+  #[serde(rename = "type")]
+  kind: GroupType,
+
+  /// Adds all valid object properties to this struct
+  #[serde(flatten)]
+  pub object_props: ObjectProperties,
+
+  /// Adds all valid activitypub object properties to this struct
+  #[serde(flatten)]
+  pub ap_object_props: ApObjectProperties,
+
+  /// Adds all valid activitypub actor properties to this struct
+  #[serde(flatten)]
+  pub ap_actor_props: ApActorProperties,
+}
+
+impl Object for Group {}
+impl ObjectExt for Group {
+  fn props(&self) -> &ObjectProperties {
+    &self.object_props
+  }
+
+  fn props_mut(&mut self) -> &mut ObjectProperties {
+    &mut self.object_props
+  }
+}
+impl ApObjectExt for Group {
+  fn props(&self) -> &ApObjectProperties {
+    &self.ap_object_props
+  }
+
+  fn props_mut(&mut self) -> &mut ApObjectProperties {
+    &mut self.ap_object_props
+  }
+}
+impl Actor for Group {}
+impl ApActorExt for Group {
+  fn props(&self) -> &ApActorProperties {
+    &self.ap_actor_props
+  }
+
+  fn props_mut(&mut self) -> &mut ApActorProperties {
+    &mut self.ap_actor_props
+  }
+}
+
+/// Represents an organization.
+#[derive(Clone, Debug, Default, Deserialize, Serialize, Properties)]
+#[serde(rename_all = "camelCase")]
+pub struct Organization {
+  #[serde(rename = "type")]
+  kind: OrganizationType,
+
+  /// Adds all valid object properties to this struct
+  #[serde(flatten)]
+  pub object_props: ObjectProperties,
+
+  /// Adds all valid activitypub object properties to this struct
+  #[serde(flatten)]
+  pub ap_object_props: ApObjectProperties,
+
+  /// Adds all valid activitypub actor properties to this struct
+  #[serde(flatten)]
+  pub ap_actor_props: ApActorProperties,
+}
+
+impl Object for Organization {}
+impl ObjectExt for Organization {
+  fn props(&self) -> &ObjectProperties {
+    &self.object_props
+  }
+
+  fn props_mut(&mut self) -> &mut ObjectProperties {
+    &mut self.object_props
+  }
+}
+impl ApObjectExt for Organization {
+  fn props(&self) -> &ApObjectProperties {
+    &self.ap_object_props
+  }
+
+  fn props_mut(&mut self) -> &mut ApObjectProperties {
+    &mut self.ap_object_props
+  }
+}
+impl Actor for Organization {}
+impl ApActorExt for Organization {
+  fn props(&self) -> &ApActorProperties {
+    &self.ap_actor_props
+  }
+
+  fn props_mut(&mut self) -> &mut ApActorProperties {
+    &mut self.ap_actor_props
+  }
+}
+
+/// Represents an individual person.
+#[derive(Clone, Debug, Default, Deserialize, Serialize, Properties)]
+#[serde(rename_all = "camelCase")]
+pub struct Person {
+  #[serde(rename = "type")]
+  kind: PersonType,
+
+  /// Adds all valid object properties to this struct
+  #[serde(flatten)]
+  pub object_props: ObjectProperties,
+
+  /// Adds all valid activitypub object properties to this struct
+  #[serde(flatten)]
+  pub ap_object_props: ApObjectProperties,
+
+  /// Adds all valid activitypub actor properties to this struct
+  #[serde(flatten)]
+  pub ap_actor_props: ApActorProperties,
+}
+
+impl Object for Person {}
+impl ObjectExt for Person {
+  fn props(&self) -> &ObjectProperties {
+    &self.object_props
+  }
+
+  fn props_mut(&mut self) -> &mut ObjectProperties {
+    &mut self.object_props
+  }
+}
+impl ApObjectExt for Person {
+  fn props(&self) -> &ApObjectProperties {
+    &self.ap_object_props
+  }
+
+  fn props_mut(&mut self) -> &mut ApObjectProperties {
+    &mut self.ap_object_props
+  }
+}
+impl Actor for Person {}
+impl ApActorExt for Person {
+  fn props(&self) -> &ApActorProperties {
+    &self.ap_actor_props
+  }
+
+  fn props_mut(&mut self) -> &mut ApActorProperties {
+    &mut self.ap_actor_props
+  }
+}
+
+/// Represents a service of any kind.
+#[derive(Clone, Debug, Default, Deserialize, Serialize, Properties)]
+#[serde(rename_all = "camelCase")]
+pub struct Service {
+  #[serde(rename = "type")]
+  kind: ServiceType,
+
+  /// Adds all valid object properties to this struct
+  #[serde(flatten)]
+  pub object_props: ObjectProperties,
+
+  /// Adds all valid activitypub object properties to this struct
+  #[serde(flatten)]
+  pub ap_object_props: ApObjectProperties,
+
+  /// Adds all valid activitypub actor properties to this struct
+  #[serde(flatten)]
+  pub ap_actor_props: ApActorProperties,
+}
+
+impl Object for Service {}
+impl ObjectExt for Service {
+  fn props(&self) -> &ObjectProperties {
+    &self.object_props
+  }
+
+  fn props_mut(&mut self) -> &mut ObjectProperties {
+    &mut self.object_props
+  }
+}
+impl ApObjectExt for Service {
+  fn props(&self) -> &ApObjectProperties {
+    &self.ap_object_props
+  }
+
+  fn props_mut(&mut self) -> &mut ApObjectProperties {
+    &mut self.ap_object_props
+  }
+}
+impl Actor for Service {}
+impl ApActorExt for Service {
+  fn props(&self) -> &ApActorProperties {
+    &self.ap_actor_props
+  }
+
+  fn props_mut(&mut self) -> &mut ApActorProperties {
+    &mut self.ap_actor_props
+  }
+}
diff --git a/server/src/activitypub/actor/properties.rs b/server/src/activitypub/actor/properties.rs
new file mode 100644 (file)
index 0000000..9b7f38a
--- /dev/null
@@ -0,0 +1,129 @@
+/*
+ * This file is part of ActivityPub.
+ *
+ * Copyright © 2018 Riley Trautman
+ *
+ * ActivityPub is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * ActivityPub is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with ActivityPub.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+//! Namespace for properties of standard Actor types
+//!
+//! To use these properties in your own types, you can flatten them into your struct with serde:
+//!
+//! ```rust
+//! use activitypub::{Object, Actor, actor::properties::ApActorProperties};
+//! use serde_derive::{Deserialize, Serialize};
+//!
+//! #[derive(Clone, Debug, Serialize, Deserialize)]
+//! #[serde(rename_all = "camelCase")]
+//! pub struct MyActor {
+//!     #[serde(rename = "type")]
+//!     pub kind: String,
+//!
+//!     /// Define a require property for the MyActor type
+//!     pub my_property: String,
+//!
+//!     #[serde(flatten)]
+//!     pub actor_props: ApActorProperties,
+//! }
+//!
+//! impl Object for MyActor {}
+//! impl Actor for MyActor {}
+//! #
+//! # fn main() {}
+//! ```
+
+use activitystreams_derive::Properties;
+use serde_derive::{Deserialize, Serialize};
+
+use crate::activitypub::endpoint::Endpoint;
+
+/// Define activitypub properties for the Actor type as described by the Activity Pub vocabulary.
+#[derive(Clone, Debug, Default, Deserialize, Properties, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct ApActorProperties {
+  // TODO: IRI
+  /// A reference to an [[ActivityStreams](https://www.w3.org/ns/activitystreams)]
+  /// OrderedCollection comprised of all the messages received by the actor.
+  ///
+  /// - Range: `anyUri`
+  /// - Functional: true
+  #[activitystreams(concrete(String), functional)]
+  pub inbox: serde_json::Value,
+
+  // TODO: IRI
+  /// An [ActivityStreams](https://www.w3.org/ns/activitystreams)] OrderedCollection comprised of
+  /// all the messages produced by the actor.
+  ///
+  /// - Range: `anyUri`
+  /// - Functional: true
+  #[activitystreams(concrete(String), functional)]
+  pub outbox: serde_json::Value,
+
+  // TODO: IRI
+  /// A link to an [[ActivityStreams](https://www.w3.org/ns/activitystreams)] collection of the
+  /// actors that this actor is following.
+  ///
+  /// - Range: `anyUri`
+  /// - Functional: true
+  #[activitystreams(concrete(String), functional)]
+  pub following: Option<serde_json::Value>,
+
+  // TODO: IRI
+  /// A link to an [[ActivityStreams](https://www.w3.org/ns/activitystreams)] collection of the
+  /// actors that follow this actor.
+  ///
+  /// - Range: `anyUri`
+  /// - Functional: true
+  #[activitystreams(concrete(String), functional)]
+  pub followers: Option<serde_json::Value>,
+
+  // TODO: IRI
+  /// A link to an [[ActivityStreams](https://www.w3.org/ns/activitystreams)] collection of
+  /// objects this actor has liked.
+  ///
+  /// - Range: `anyUri`
+  /// - Functional: true
+  #[activitystreams(concrete(String), functional)]
+  pub liked: Option<serde_json::Value>,
+
+  // TODO: IRI
+  /// A list of supplementary Collections which may be of interest.
+  ///
+  /// - Range: `anyUri`
+  /// - Functional: false
+  #[serde(skip_serializing_if = "Option::is_none")]
+  #[activitystreams(concrete(String))]
+  pub streams: Option<serde_json::Value>,
+
+  /// A short username which may be used to refer to the actor, with no uniqueness guarantees.
+  ///
+  /// - Range: `anyUri`
+  /// - Functional: true
+  #[serde(skip_serializing_if = "Option::is_none")]
+  #[activitystreams(concrete(String), functional)]
+  pub preferred_username: Option<serde_json::Value>,
+
+  /// A json object which maps additional (typically server/domain-wide) endpoints which may be
+  /// useful either for this actor or someone referencing this actor.
+  ///
+  /// This mapping may be nested inside the actor document as the value or may be a link to a
+  /// JSON-LD document with these properties.
+  ///
+  /// - Range: `Endpoint`
+  /// - Functional: true
+  #[serde(skip_serializing_if = "Option::is_none")]
+  #[activitystreams(concrete(Endpoint), functional)]
+  pub endpoints: Option<serde_json::Value>,
+}
diff --git a/server/src/activitypub/collection.rs b/server/src/activitypub/collection.rs
new file mode 100644 (file)
index 0000000..8a25cce
--- /dev/null
@@ -0,0 +1,264 @@
+/*
+ * This file is part of ActivityPub.
+ *
+ * Copyright © 2018 Riley Trautman
+ *
+ * ActivityPub is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * ActivityPub is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with ActivityPub.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+//! Collection traits and types
+
+use activitystreams_derive::Properties;
+pub use activitystreams_traits::{Collection, CollectionPage};
+pub use activitystreams_types::collection::{kind, properties, CollectionExt, CollectionPageExt};
+use serde_derive::{Deserialize, Serialize};
+
+use self::{kind::*, properties::*};
+use activitypub::object::{
+  properties::{ApObjectProperties, ObjectProperties},
+  ApObjectExt, Object, ObjectExt,
+};
+
+/// The default `Collection` type.
+#[derive(Clone, Debug, Default, Deserialize, Serialize, Properties)]
+#[serde(rename_all = "camelCase")]
+pub struct UnorderedCollection {
+  #[serde(rename = "type")]
+  kind: CollectionType,
+
+  /// Adds all valid object properties to this struct
+  #[serde(flatten)]
+  pub object_props: ObjectProperties,
+
+  /// Adds all valid ap object properties to this struct
+  #[serde(flatten)]
+  pub ap_object_props: ApObjectProperties,
+
+  /// Adds all valid collection properties to this struct
+  #[serde(flatten)]
+  pub collection_props: CollectionProperties,
+}
+
+impl Object for UnorderedCollection {}
+impl ObjectExt for UnorderedCollection {
+  fn props(&self) -> &ObjectProperties {
+    &self.object_props
+  }
+
+  fn props_mut(&mut self) -> &mut ObjectProperties {
+    &mut self.object_props
+  }
+}
+impl ApObjectExt for UnorderedCollection {
+  fn props(&self) -> &ApObjectProperties {
+    &self.ap_object_props
+  }
+
+  fn props_mut(&mut self) -> &mut ApObjectProperties {
+    &mut self.ap_object_props
+  }
+}
+impl Collection for UnorderedCollection {}
+impl CollectionExt for UnorderedCollection {
+  fn props(&self) -> &CollectionProperties {
+    &self.collection_props
+  }
+
+  fn props_mut(&mut self) -> &mut CollectionProperties {
+    &mut self.collection_props
+  }
+}
+
+/// Used to represent distinct subsets of items from a `Collection`.
+#[derive(Clone, Debug, Default, Deserialize, Serialize, Properties)]
+#[serde(rename_all = "camelCase")]
+pub struct UnorderedCollectionPage {
+  #[serde(rename = "type")]
+  kind: CollectionPageType,
+
+  /// Adds all valid object properties to this struct
+  #[serde(flatten)]
+  pub object_props: ObjectProperties,
+
+  /// Adds all valid ap object properties to this struct
+  #[serde(flatten)]
+  pub ap_object_props: ApObjectProperties,
+
+  /// Adds all valid collection properties to this struct
+  #[serde(flatten)]
+  pub collection_props: CollectionProperties,
+
+  /// Adds all valid collection page properties to this struct
+  #[serde(flatten)]
+  pub collection_page_props: CollectionPageProperties,
+}
+
+impl Object for UnorderedCollectionPage {}
+impl ObjectExt for UnorderedCollectionPage {
+  fn props(&self) -> &ObjectProperties {
+    &self.object_props
+  }
+
+  fn props_mut(&mut self) -> &mut ObjectProperties {
+    &mut self.object_props
+  }
+}
+impl ApObjectExt for UnorderedCollectionPage {
+  fn props(&self) -> &ApObjectProperties {
+    &self.ap_object_props
+  }
+
+  fn props_mut(&mut self) -> &mut ApObjectProperties {
+    &mut self.ap_object_props
+  }
+}
+impl Collection for UnorderedCollectionPage {}
+impl CollectionExt for UnorderedCollectionPage {
+  fn props(&self) -> &CollectionProperties {
+    &self.collection_props
+  }
+
+  fn props_mut(&mut self) -> &mut CollectionProperties {
+    &mut self.collection_props
+  }
+}
+impl CollectionPage for UnorderedCollectionPage {}
+impl CollectionPageExt for UnorderedCollectionPage {
+  fn props(&self) -> &CollectionPageProperties {
+    &self.collection_page_props
+  }
+
+  fn props_mut(&mut self) -> &mut CollectionPageProperties {
+    &mut self.collection_page_props
+  }
+}
+
+/// A subtype of `Collection` in which members of the logical collection are assumed to always be
+/// strictly ordered.
+#[derive(Clone, Debug, Default, Deserialize, Serialize, Properties)]
+#[serde(rename_all = "camelCase")]
+pub struct OrderedCollection {
+  #[serde(rename = "type")]
+  kind: OrderedCollectionType,
+
+  /// Adds all valid object properties to this struct
+  #[serde(flatten)]
+  pub object_props: ObjectProperties,
+
+  /// Adds all valid ap object properties to this struct
+  #[serde(flatten)]
+  pub ap_object_props: ApObjectProperties,
+
+  /// Adds all valid collection properties to this struct
+  #[serde(flatten)]
+  pub collection_props: CollectionProperties,
+}
+
+impl Object for OrderedCollection {}
+impl ObjectExt for OrderedCollection {
+  fn props(&self) -> &ObjectProperties {
+    &self.object_props
+  }
+
+  fn props_mut(&mut self) -> &mut ObjectProperties {
+    &mut self.object_props
+  }
+}
+impl ApObjectExt for OrderedCollection {
+  fn props(&self) -> &ApObjectProperties {
+    &self.ap_object_props
+  }
+
+  fn props_mut(&mut self) -> &mut ApObjectProperties {
+    &mut self.ap_object_props
+  }
+}
+impl Collection for OrderedCollection {}
+impl CollectionExt for OrderedCollection {
+  fn props(&self) -> &CollectionProperties {
+    &self.collection_props
+  }
+
+  fn props_mut(&mut self) -> &mut CollectionProperties {
+    &mut self.collection_props
+  }
+}
+
+/// Used to represent ordered subsets of items from an `OrderedCollection`.
+#[derive(Clone, Debug, Default, Deserialize, Serialize, Properties)]
+#[serde(rename_all = "camelCase")]
+pub struct OrderedCollectionPage {
+  #[serde(rename = "type")]
+  kind: OrderedCollectionPageType,
+
+  /// Adds all valid object properties to this struct
+  #[serde(flatten)]
+  pub object_props: ObjectProperties,
+
+  /// Adds all valid ap object properties to this struct
+  #[serde(flatten)]
+  pub ap_object_props: ApObjectProperties,
+
+  /// Adds all valid collection properties to this struct
+  #[serde(flatten)]
+  pub collection_props: CollectionProperties,
+
+  /// Adds all valid collection page properties to this struct
+  #[serde(flatten)]
+  pub collection_page_props: CollectionPageProperties,
+
+  /// Adds all valid ordered collection page properties to this struct
+  #[serde(flatten)]
+  pub ordered_collection_page_props: OrderedCollectionPageProperties,
+}
+
+impl Object for OrderedCollectionPage {}
+impl ObjectExt for OrderedCollectionPage {
+  fn props(&self) -> &ObjectProperties {
+    &self.object_props
+  }
+
+  fn props_mut(&mut self) -> &mut ObjectProperties {
+    &mut self.object_props
+  }
+}
+impl ApObjectExt for OrderedCollectionPage {
+  fn props(&self) -> &ApObjectProperties {
+    &self.ap_object_props
+  }
+
+  fn props_mut(&mut self) -> &mut ApObjectProperties {
+    &mut self.ap_object_props
+  }
+}
+impl Collection for OrderedCollectionPage {}
+impl CollectionExt for OrderedCollectionPage {
+  fn props(&self) -> &CollectionProperties {
+    &self.collection_props
+  }
+
+  fn props_mut(&mut self) -> &mut CollectionProperties {
+    &mut self.collection_props
+  }
+}
+impl CollectionPage for OrderedCollectionPage {}
+impl CollectionPageExt for OrderedCollectionPage {
+  fn props(&self) -> &CollectionPageProperties {
+    &self.collection_page_props
+  }
+
+  fn props_mut(&mut self) -> &mut CollectionPageProperties {
+    &mut self.collection_page_props
+  }
+}
diff --git a/server/src/activitypub/endpoint.rs b/server/src/activitypub/endpoint.rs
new file mode 100644 (file)
index 0000000..639860c
--- /dev/null
@@ -0,0 +1,107 @@
+/*
+ * This file is part of ActivityPub.
+ *
+ * Copyright © 2018 Riley Trautman
+ *
+ * ActivityPub is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * ActivityPub is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with ActivityPub.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+//! Endpoint traits and types
+
+use activitystreams_derive::Properties;
+use serde_derive::{Deserialize, Serialize};
+
+/// A json object which maps additional (typically server/domain-wide) endpoints which may be
+/// useful either for this actor or someone referencing this actor.
+///
+/// This mapping may be nested inside the actor document as the value or may be a link to a JSON-LD
+/// document with these properties.
+#[derive(Clone, Debug, Default, Deserialize, Properties, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct Endpoint {
+  // TODO: IRI
+  /// Endpoint URI so this actor's clients may access remote ActivityStreams objects which
+  /// require authentication to access.
+  ///
+  /// To use this endpoint, the client posts an x-www-form-urlencoded id parameter with the value
+  /// being the id of the requested ActivityStreams object.
+  ///
+  /// - Range: `anyUri`
+  /// - Functional: true
+  #[serde(skip_serializing_if = "Option::is_none")]
+  #[activitystreams(concrete(String))]
+  pub proxy_url: Option<serde_json::Value>,
+
+  // TODO: IRI
+  /// If OAuth 2.0 bearer tokens [[RFC6749](https://tools.ietf.org/html/rfc6749)]
+  /// [[RFC6750](https://tools.ietf.org/html/rfc6750)] are being used for authenticating client
+  /// to server interactions, this endpoint specifies a URI at which a browser-authenticated user
+  /// may obtain a new authorization grant.
+  ///
+  /// - Range: `anyUri`
+  /// - Functional: true
+  #[serde(skip_serializing_if = "Option::is_none")]
+  #[activitystreams(concrete(String))]
+  pub oauth_authorization_endpoint: Option<serde_json::Value>,
+
+  // TODO: IRI
+  /// If OAuth 2.0 bearer tokens [[RFC6749](https://tools.ietf.org/html/rfc6749)]
+  /// [[RFC6750](https://tools.ietf.org/html/rfc6750)] are being used for authenticating client
+  /// to server interactions, this endpoint specifies a URI at which a client may acquire an
+  /// access token.
+  ///
+  /// - Range: `anyUri`
+  /// - Functional: true
+  #[serde(skip_serializing_if = "Option::is_none")]
+  #[activitystreams(concrete(String))]
+  pub oauth_token_endpoint: Option<serde_json::Value>,
+
+  // TODO: IRI
+  /// If Linked Data Signatures and HTTP Signatures are being used for authentication and
+  /// authorization, this endpoint specifies a URI at which browser-authenticated users may
+  /// authorize a client's public key for client to server interactions.
+  ///
+  /// - Range: `anyUri`
+  /// - Functional: true
+  #[serde(skip_serializing_if = "Option::is_none")]
+  #[activitystreams(concrete(String))]
+  pub provide_client_key: Option<serde_json::Value>,
+
+  // TODO: IRI
+  /// If Linked Data Signatures and HTTP Signatures are being used for authentication and
+  /// authorization, this endpoint specifies a URI at which a client key may be signed by the
+  /// actor's key for a time window to act on behalf of the actor in interacting with foreign
+  /// servers.
+  ///
+  /// - Range: `anyUri`
+  /// - Functional: true
+  #[serde(skip_serializing_if = "Option::is_none")]
+  #[activitystreams(concrete(String))]
+  pub sign_client_key: Option<serde_json::Value>,
+
+  // TODO: IRI
+  /// An optional endpoint used for wide delivery of publicly addressed activities and activities
+  /// sent to followers.
+  ///
+  /// `shared_inbox`endpoints SHOULD also be publicly readable `OrderedCollection` objects
+  /// containing objects addressed to the Public special collection. Reading from the
+  /// `shared_inbox` endpoint MUST NOT present objects which are not addressed to the Public
+  /// endpoint.
+  ///
+  /// - Range: `anyUri`
+  /// - Functional: true
+  #[serde(skip_serializing_if = "Option::is_none")]
+  #[activitystreams(concrete(String))]
+  pub shared_inbox: Option<serde_json::Value>,
+}
diff --git a/server/src/activitypub/link.rs b/server/src/activitypub/link.rs
new file mode 100644 (file)
index 0000000..5de09fd
--- /dev/null
@@ -0,0 +1,23 @@
+/*
+ * This file is part of ActivityPub.
+ *
+ * Copyright © 2018 Riley Trautman
+ *
+ * ActivityPub is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * ActivityPub is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with ActivityPub.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+//! Link traits and types
+
+pub use activitystreams_traits::Link;
+pub use activitystreams_types::link::{kind, properties, LinkExt, Mention};
diff --git a/server/src/activitypub/mod.rs b/server/src/activitypub/mod.rs
new file mode 100644 (file)
index 0000000..9e99032
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ * This file is part of ActivityPub.
+ *
+ * Copyright © 2018 Riley Trautman
+ *
+ * ActivityPub is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * ActivityPub is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with ActivityPub.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+//! ActivityPub
+//!
+//! This crate defines the base set of types from the ActivityPub specification.
+//!
+//! ## Example Usage
+//! ```rust
+//! use activitypub::{context, object::Video};
+//! use anyhow::Error;
+//!
+//! fn run() -> Result<(), Error> {
+//!     let mut video = Video::default();
+//!     video.object_props.set_context_object(context())?;
+//!     video.ap_object_props.set_likes_string("https://my-instance.com/likes".to_owned());
+//!
+//!     let video_string = serde_json::to_string(&video)?;
+//!
+//!     let video: Video = serde_json::from_str(&video_string)?;
+//!
+//!     Ok(())
+//! }
+//! ```
+pub mod activity;
+pub mod actor;
+pub mod collection;
+mod endpoint;
+pub mod link;
+pub mod object;
+
+pub use self::{
+  activity::{Activity, IntransitiveActivity},
+  actor::Actor,
+  collection::{Collection, CollectionPage},
+  endpoint::Endpoint,
+  link::Link,
+  object::Object,
+};
+pub use activitystreams_traits::{properties, Error, Result};
+pub use activitystreams_types::{context, ContextObject, CustomLink, CustomObject};
diff --git a/server/src/activitypub/object/mod.rs b/server/src/activitypub/object/mod.rs
new file mode 100644 (file)
index 0000000..07aa99e
--- /dev/null
@@ -0,0 +1,444 @@
+/*
+ * This file is part of ActivityPub.
+ *
+ * Copyright © 2018 Riley Trautman
+ *
+ * ActivityPub is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * ActivityPub is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with ActivityPub.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+//! Object traits and types
+
+pub use activitystreams_traits::Object;
+pub use activitystreams_types::object::{kind, ObjectExt};
+use serde_derive::{Deserialize, Serialize};
+
+pub mod properties;
+
+use self::{kind::*, properties::*};
+
+/// The ActivityPub Object Extension Trait
+///
+/// This trait provides generic access to an activitypub object's properties
+pub trait ApObjectExt: Object {
+  fn props(&self) -> &ApObjectProperties;
+  fn props_mut(&mut self) -> &mut ApObjectProperties;
+}
+
+#[derive(Clone, Debug, Default, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct Article {
+  #[serde(rename = "type")]
+  kind: ArticleType,
+
+  #[serde(flatten)]
+  pub object_props: ObjectProperties,
+
+  #[serde(flatten)]
+  pub ap_object_props: ApObjectProperties,
+}
+
+impl Object for Article {}
+impl ObjectExt for Article {
+  fn props(&self) -> &ObjectProperties {
+    &self.object_props
+  }
+
+  fn props_mut(&mut self) -> &mut ObjectProperties {
+    &mut self.object_props
+  }
+}
+impl ApObjectExt for Article {
+  fn props(&self) -> &ApObjectProperties {
+    &self.ap_object_props
+  }
+
+  fn props_mut(&mut self) -> &mut ApObjectProperties {
+    &mut self.ap_object_props
+  }
+}
+
+#[derive(Clone, Debug, Default, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct Audio {
+  #[serde(rename = "type")]
+  kind: AudioType,
+
+  #[serde(flatten)]
+  pub object_props: ObjectProperties,
+
+  #[serde(flatten)]
+  pub ap_object_props: ApObjectProperties,
+}
+
+impl Object for Audio {}
+impl ObjectExt for Audio {
+  fn props(&self) -> &ObjectProperties {
+    &self.object_props
+  }
+
+  fn props_mut(&mut self) -> &mut ObjectProperties {
+    &mut self.object_props
+  }
+}
+impl ApObjectExt for Audio {
+  fn props(&self) -> &ApObjectProperties {
+    &self.ap_object_props
+  }
+
+  fn props_mut(&mut self) -> &mut ApObjectProperties {
+    &mut self.ap_object_props
+  }
+}
+
+#[derive(Clone, Debug, Default, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct Document {
+  #[serde(rename = "type")]
+  kind: DocumentType,
+
+  #[serde(flatten)]
+  pub object_props: ObjectProperties,
+
+  #[serde(flatten)]
+  pub ap_object_props: ApObjectProperties,
+}
+
+impl Object for Document {}
+impl ObjectExt for Document {
+  fn props(&self) -> &ObjectProperties {
+    &self.object_props
+  }
+
+  fn props_mut(&mut self) -> &mut ObjectProperties {
+    &mut self.object_props
+  }
+}
+impl ApObjectExt for Document {
+  fn props(&self) -> &ApObjectProperties {
+    &self.ap_object_props
+  }
+
+  fn props_mut(&mut self) -> &mut ApObjectProperties {
+    &mut self.ap_object_props
+  }
+}
+
+#[derive(Clone, Debug, Default, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct Event {
+  #[serde(rename = "type")]
+  kind: EventType,
+
+  #[serde(flatten)]
+  pub object_props: ObjectProperties,
+
+  #[serde(flatten)]
+  pub ap_object_props: ApObjectProperties,
+}
+
+impl Object for Event {}
+impl ObjectExt for Event {
+  fn props(&self) -> &ObjectProperties {
+    &self.object_props
+  }
+
+  fn props_mut(&mut self) -> &mut ObjectProperties {
+    &mut self.object_props
+  }
+}
+impl ApObjectExt for Event {
+  fn props(&self) -> &ApObjectProperties {
+    &self.ap_object_props
+  }
+
+  fn props_mut(&mut self) -> &mut ApObjectProperties {
+    &mut self.ap_object_props
+  }
+}
+
+#[derive(Clone, Debug, Default, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct Image {
+  #[serde(rename = "type")]
+  kind: ImageType,
+
+  #[serde(flatten)]
+  pub object_props: ObjectProperties,
+
+  #[serde(flatten)]
+  pub ap_object_props: ApObjectProperties,
+}
+
+impl Object for Image {}
+impl ObjectExt for Image {
+  fn props(&self) -> &ObjectProperties {
+    &self.object_props
+  }
+
+  fn props_mut(&mut self) -> &mut ObjectProperties {
+    &mut self.object_props
+  }
+}
+impl ApObjectExt for Image {
+  fn props(&self) -> &ApObjectProperties {
+    &self.ap_object_props
+  }
+
+  fn props_mut(&mut self) -> &mut ApObjectProperties {
+    &mut self.ap_object_props
+  }
+}
+
+#[derive(Clone, Debug, Default, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct Note {
+  #[serde(rename = "type")]
+  kind: NoteType,
+
+  #[serde(flatten)]
+  pub object_props: ObjectProperties,
+
+  #[serde(flatten)]
+  pub ap_object_props: ApObjectProperties,
+}
+
+impl Object for Note {}
+impl ObjectExt for Note {
+  fn props(&self) -> &ObjectProperties {
+    &self.object_props
+  }
+
+  fn props_mut(&mut self) -> &mut ObjectProperties {
+    &mut self.object_props
+  }
+}
+impl ApObjectExt for Note {
+  fn props(&self) -> &ApObjectProperties {
+    &self.ap_object_props
+  }
+
+  fn props_mut(&mut self) -> &mut ApObjectProperties {
+    &mut self.ap_object_props
+  }
+}
+
+#[derive(Clone, Debug, Default, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct Page {
+  #[serde(rename = "type")]
+  kind: PageType,
+
+  #[serde(flatten)]
+  pub object_props: ObjectProperties,
+
+  #[serde(flatten)]
+  pub ap_object_props: ApObjectProperties,
+}
+
+impl Object for Page {}
+impl ObjectExt for Page {
+  fn props(&self) -> &ObjectProperties {
+    &self.object_props
+  }
+
+  fn props_mut(&mut self) -> &mut ObjectProperties {
+    &mut self.object_props
+  }
+}
+impl ApObjectExt for Page {
+  fn props(&self) -> &ApObjectProperties {
+    &self.ap_object_props
+  }
+
+  fn props_mut(&mut self) -> &mut ApObjectProperties {
+    &mut self.ap_object_props
+  }
+}
+
+#[derive(Clone, Debug, Default, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct Place {
+  #[serde(rename = "type")]
+  kind: PlaceType,
+
+  #[serde(flatten)]
+  pub object_props: ObjectProperties,
+
+  #[serde(flatten)]
+  pub ap_object_props: ApObjectProperties,
+
+  #[serde(flatten)]
+  pub place_props: PlaceProperties,
+}
+
+impl Object for Place {}
+impl ObjectExt for Place {
+  fn props(&self) -> &ObjectProperties {
+    &self.object_props
+  }
+
+  fn props_mut(&mut self) -> &mut ObjectProperties {
+    &mut self.object_props
+  }
+}
+impl ApObjectExt for Place {
+  fn props(&self) -> &ApObjectProperties {
+    &self.ap_object_props
+  }
+
+  fn props_mut(&mut self) -> &mut ApObjectProperties {
+    &mut self.ap_object_props
+  }
+}
+
+#[derive(Clone, Debug, Default, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct Profile {
+  #[serde(rename = "type")]
+  kind: ProfileType,
+
+  #[serde(flatten)]
+  pub object_props: ObjectProperties,
+
+  #[serde(flatten)]
+  pub ap_object_props: ApObjectProperties,
+
+  #[serde(flatten)]
+  pub profile_props: ProfileProperties,
+}
+
+impl Object for Profile {}
+impl ObjectExt for Profile {
+  fn props(&self) -> &ObjectProperties {
+    &self.object_props
+  }
+
+  fn props_mut(&mut self) -> &mut ObjectProperties {
+    &mut self.object_props
+  }
+}
+impl ApObjectExt for Profile {
+  fn props(&self) -> &ApObjectProperties {
+    &self.ap_object_props
+  }
+
+  fn props_mut(&mut self) -> &mut ApObjectProperties {
+    &mut self.ap_object_props
+  }
+}
+
+#[derive(Clone, Debug, Default, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct Relationship {
+  #[serde(rename = "type")]
+  kind: RelationshipType,
+
+  #[serde(flatten)]
+  pub object_props: ObjectProperties,
+
+  #[serde(flatten)]
+  pub ap_object_props: ApObjectProperties,
+
+  #[serde(flatten)]
+  pub relationship_props: RelationshipProperties,
+}
+
+impl Object for Relationship {}
+impl ObjectExt for Relationship {
+  fn props(&self) -> &ObjectProperties {
+    &self.object_props
+  }
+
+  fn props_mut(&mut self) -> &mut ObjectProperties {
+    &mut self.object_props
+  }
+}
+impl ApObjectExt for Relationship {
+  fn props(&self) -> &ApObjectProperties {
+    &self.ap_object_props
+  }
+
+  fn props_mut(&mut self) -> &mut ApObjectProperties {
+    &mut self.ap_object_props
+  }
+}
+
+#[derive(Clone, Debug, Default, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct Tombstone {
+  #[serde(rename = "type")]
+  kind: TombstoneType,
+
+  #[serde(flatten)]
+  pub object_props: ObjectProperties,
+
+  #[serde(flatten)]
+  pub ap_object_props: ApObjectProperties,
+
+  #[serde(flatten)]
+  pub tombstone_props: TombstoneProperties,
+}
+
+impl Object for Tombstone {}
+impl ObjectExt for Tombstone {
+  fn props(&self) -> &ObjectProperties {
+    &self.object_props
+  }
+
+  fn props_mut(&mut self) -> &mut ObjectProperties {
+    &mut self.object_props
+  }
+}
+impl ApObjectExt for Tombstone {
+  fn props(&self) -> &ApObjectProperties {
+    &self.ap_object_props
+  }
+
+  fn props_mut(&mut self) -> &mut ApObjectProperties {
+    &mut self.ap_object_props
+  }
+}
+
+#[derive(Clone, Debug, Default, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct Video {
+  #[serde(rename = "type")]
+  kind: VideoType,
+
+  #[serde(flatten)]
+  pub object_props: ObjectProperties,
+
+  #[serde(flatten)]
+  pub ap_object_props: ApObjectProperties,
+}
+
+impl Object for Video {}
+impl ObjectExt for Video {
+  fn props(&self) -> &ObjectProperties {
+    &self.object_props
+  }
+
+  fn props_mut(&mut self) -> &mut ObjectProperties {
+    &mut self.object_props
+  }
+}
+impl ApObjectExt for Video {
+  fn props(&self) -> &ApObjectProperties {
+    &self.ap_object_props
+  }
+
+  fn props_mut(&mut self) -> &mut ApObjectProperties {
+    &mut self.ap_object_props
+  }
+}
diff --git a/server/src/activitypub/object/properties.rs b/server/src/activitypub/object/properties.rs
new file mode 100644 (file)
index 0000000..ea4f004
--- /dev/null
@@ -0,0 +1,111 @@
+/*
+ * This file is part of ActivityPub.
+ *
+ * Copyright © 2018 Riley Trautman
+ *
+ * ActivityPub is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * ActivityPub is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with ActivityPub.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+//! Namespace for properties of standard Object types
+//!
+//! To use these properties in your own types, you can flatten them into your struct with serde:
+//!
+//! ```rust
+//! use activitypub::{Object, object::properties::ApObjectProperties};
+//! use serde_derive::{Deserialize, Serialize};
+//!
+//! #[derive(Clone, Debug, Serialize, Deserialize)]
+//! #[serde(rename_all = "camelCase")]
+//! pub struct MyObject {
+//!     #[serde(rename = "type")]
+//!     pub kind: String,
+//!
+//!     /// Define a require property for the MyObject type
+//!     pub my_property: String,
+//!
+//!     #[serde(flatten)]
+//!     pub object_props: ApObjectProperties,
+//! }
+//!
+//! impl Object for MyObject {}
+//! #
+//! # fn main() {}
+//! ```
+
+use super::Object;
+
+use activitystreams_derive::Properties;
+pub use activitystreams_types::object::properties::{
+  ObjectProperties, PlaceProperties, ProfileProperties, RelationshipProperties, TombstoneProperties,
+};
+use serde_derive::{Deserialize, Serialize};
+
+/// Define activitypub properties for the Object type as described by the Activity Pub vocabulary.
+#[derive(Clone, Debug, Default, Deserialize, Properties, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct ApObjectProperties {
+  // TODO: IRI
+  /// This is a list of all Announce activities with this object as the object property, added as
+  /// a side effect.
+  ///
+  /// The shares collection MUST be either an OrderedCollection or a Collection and MAY be
+  /// filtered on privileges of an authenticated user or as appropriate when no authentication is
+  /// given.
+  ///
+  /// - Range: `anyUri`
+  /// - Functional: true
+  #[serde(skip_serializing_if = "Option::is_none")]
+  #[activitystreams(concrete(String), functional)]
+  pub shares: Option<serde_json::Value>,
+
+  /// This is a list of all Like activities with this object as the object property, added as a
+  /// side effect.
+  ///
+  /// The likes collection MUST be either an OrderedCollection or a Collection and MAY be
+  /// filtered on privileges of an authenticated user or as appropriate when no authentication is
+  /// given.
+  ///
+  /// - Range: `anyUri`
+  /// - Functional: true
+  #[serde(skip_serializing_if = "Option::is_none")]
+  #[activitystreams(concrete(String), functional)]
+  pub likes: Option<serde_json::Value>,
+
+  /// The source property is intended to convey some sort of source from which the content markup
+  /// was derived, as a form of provenance, or to support future editing by clients.
+  ///
+  /// In general, clients do the conversion from source to content, not the other way around.
+  ///
+  /// The value of source is itself an object which uses its own content and mediaType fields to
+  /// supply source information.
+  ///
+  /// - Range: `Object`
+  /// - Functional: true
+  #[serde(skip_serializing_if = "Option::is_none")]
+  #[activitystreams(ab(Object), concrete(String), functional)]
+  pub source: Option<serde_json::Value>,
+
+  /// Servers MAY support uploading document types to be referenced in activites, such as images,
+  /// video or other binary data, but the precise mechanism is out of scope for this version of
+  /// `ActivityPub`.
+  ///
+  /// The Social Web Community Group is refining the protocol in the
+  /// [`ActivityPub` Media Upload report](https://www.w3.org/wiki/SocialCG/ActivityPub/MediaUpload).
+  ///
+  /// - Range: `anyUri`
+  /// - Functional: false
+  #[serde(skip_serializing_if = "Option::is_none")]
+  #[activitystreams(concrete(String))]
+  pub upload_media: Option<serde_json::Value>,
+}
index 621d410215fdd0f94057df2b2ff829b681d4f4a8..bc07b3190d7ea973c306a2b5ee5752333886294d 100644 (file)
@@ -1,9 +1,9 @@
+use crate::activitypub::{actor::Group, collection::UnorderedCollection, context};
 use crate::apub::make_apub_endpoint;
 use crate::db::community::Community;
 use crate::db::community_view::CommunityFollowerView;
 use crate::db::establish_unpooled_connection;
 use crate::to_datetime_utc;
-use activitypub::{actor::Group, collection::UnorderedCollection, context};
 use actix_web::body::Body;
 use actix_web::web::Path;
 use actix_web::HttpResponse;
@@ -36,8 +36,7 @@ impl Community {
     }
 
     if let Some(description) = &self.description {
-      group
-        .object_props.summary = Some(json!(description.to_string()));
+      group.object_props.summary = Some(json!(description.to_string()));
     }
 
     group
index ebb17129037eb0b6f30e1b383f46e9baa2d1a83b..50b87c873eeb12b829728677da56fb1663bef1d2 100644 (file)
@@ -1,7 +1,7 @@
+use crate::activitypub::{context, object::Page};
 use crate::apub::make_apub_endpoint;
 use crate::db::post::Post;
 use crate::to_datetime_utc;
-use activitypub::{context, object::Page};
 
 impl Post {
   pub fn as_page(&self) -> Page {
index b6647060e304df6a419664f9508bf75e04922006..b3177183c5eafcb0297a0e15ce1b6429cb27c1e6 100644 (file)
@@ -1,12 +1,12 @@
 extern crate reqwest;
 
 use self::reqwest::Error;
+use crate::activitypub::actor::Group;
 use crate::api::community::{GetCommunityResponse, ListCommunitiesResponse};
 use crate::api::post::GetPosts;
 use crate::db::community_view::CommunityView;
 use crate::naive_now;
 use crate::settings::Settings;
-use activitypub::actor::Group;
 
 // TODO: right now all of the data is requested on demand, for production we will need to store
 //       things in the local database to not ruin the performance
@@ -50,14 +50,34 @@ pub fn get_remote_community(identifier: String) -> Result<GetCommunityResponse,
       // TODO: why does the stupid library have everything stored as value without working autocomplete for methods???
       //       i want to pull that whole lib in here and treat it as part of lemmy so we can fix this shit
       // TODO: we need to merge id and name into a single thing (stuff like @user@instance.com)
-      id: community.object_props.id.unwrap().as_str().unwrap().parse::<i32>().unwrap(),
-      name: name,
-      title: community.object_props.name.unwrap().as_str().unwrap().to_string(), // TODO: why does it still show !main@lemmy_beta:8541
+      id: community
+        .object_props
+        .id
+        .unwrap()
+        .as_str()
+        .unwrap()
+        .parse::<i32>()
+        .unwrap(),
+      name,
+      title: community
+        .object_props
+        .name
+        .unwrap()
+        .as_str()
+        .unwrap()
+        .to_string(), // TODO: why does it still show !main@lemmy_beta:8541
       description: community.object_props.summary.map(|c| c.to_string()), // TODO: this has an extra quote somehow
       category_id: -1,
-      creator_id: community.object_props.attributed_to.unwrap().as_str().unwrap().parse::<i32>().unwrap(),
+      creator_id: community
+        .object_props
+        .attributed_to
+        .unwrap()
+        .as_str()
+        .unwrap()
+        .parse::<i32>()
+        .unwrap(),
       removed: false,
-      published: naive_now(),     // TODO: need to handle time conversion (or handle it in apub lib)
+      published: naive_now(), // TODO: need to handle time conversion (or handle it in apub lib)
       updated: Some(naive_now()), // TODO: community.object_props.updated
       deleted: false,
       nsfw: false,
index 5f2421f11cdb57c9ae6b7997a6f993859b3c8111..fb31e4b687bf06df768891e1a30bdbe95fe566ed 100644 (file)
@@ -1,8 +1,8 @@
+use crate::activitypub::{actor::Person, context};
 use crate::apub::make_apub_endpoint;
 use crate::db::establish_unpooled_connection;
 use crate::db::user::User_;
 use crate::to_datetime_utc;
-use activitypub::{actor::Person, context};
 use actix_web::body::Body;
 use actix_web::web::Path;
 use actix_web::HttpResponse;
index 3e22585de7b85d5a40639027740025b379ac8ea9..5b37a08e6d69802db887bd9866c8934ab5be976a 100644 (file)
@@ -22,6 +22,7 @@ pub extern crate serde_json;
 pub extern crate sha2;
 pub extern crate strum;
 
+pub mod activitypub;
 pub mod api;
 pub mod apub;
 pub mod db;