activitystreams_types/object/
properties.rs

1/*
2 * This file is part of ActivityStreams Types.
3 *
4 * Copyright © 2018 Riley Trautman
5 *
6 * ActivityStreams Types is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * ActivityStreams Types is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with ActivityStreams Types.  If not, see <http://www.gnu.org/licenses/>.
18 */
19
20//! Namespace for properties of standard object types
21//!
22//! To use these properties in your own types, you can flatten them into your struct with serde:
23//!
24//! ```rust
25//! use activitystreams_traits::Object;
26//! use activitystreams_types::object::properties::ObjectProperties;
27//! use serde_derive::{Deserialize, Serialize};
28//!
29//! #[derive(Clone, Debug, Serialize, Deserialize)]
30//! #[serde(rename_all = "camelCase")]
31//! pub struct MyObject {
32//!     #[serde(rename = "type")]
33//!     pub kind: String,
34//!
35//!     /// Define a require property for the MyObject type
36//!     pub my_property: String,
37//!
38//!     #[serde(flatten)]
39//!     pub object_properties: ObjectProperties,
40//! }
41//!
42//! impl Object for MyObject {}
43//! #
44//! # fn main() {}
45//! ```
46
47use activitystreams_derive::Properties;
48use activitystreams_traits::{Collection, Error, Link, Object, Result};
49use chrono::{offset::Utc, DateTime};
50use serde_derive::{Deserialize, Serialize};
51
52use crate::object::Image;
53
54/// Alias chrono::DateTime<Utc> for use in derive macros
55pub type UtcTime = DateTime<Utc>;
56
57/// Define all the properties of the Object base type as described by the Activity Streams
58/// vocabulary.
59///
60/// In addition to having a global identifier (expressed as an absolute IRI using the id property)
61/// and an "object type" (expressed using the type property), all instances of the Object type share
62/// a common set of properties normatively defined by the Activity Vocabulary.
63///
64/// This struct does not provide an optional `type` property, if you are implementing your own
65/// object type, you must supply your own type. This crate's provided object types all supply their
66/// own `type` properties as Unit Structs with custom serde behaviour.
67///
68/// All properties are optional (including the id and type).
69#[derive(Clone, Debug, Default, Deserialize, Serialize, Properties)]
70#[serde(rename_all = "camelCase")]
71pub struct ObjectProperties {
72    // TODO: IRI type
73    /// Provides the globally unique identifier for an Object or Link.
74    ///
75    /// The `id` property is expressed as an absolute IRI in the spec, but for now is represented
76    /// as a string.
77    ///
78    /// - Range: `anyUri`
79    /// - Functional: true
80    #[serde(skip_serializing_if = "Option::is_none")]
81    #[serde(alias = "@id")]
82    #[activitystreams(concrete(String), functional)]
83    pub id: Option<serde_json::Value>,
84
85    /// Identifies a resource attached or related to an object that potentially requires special
86    /// handling.
87    ///
88    /// The intent is to provide a model that is at least semantically similar to attachments in
89    /// email.
90    ///
91    /// - Range: `Object` | `Link`
92    /// - Functional: false
93    #[serde(skip_serializing_if = "Option::is_none")]
94    #[activitystreams(ab(Object, Link), concrete(String))]
95    pub attachment: Option<serde_json::Value>,
96
97    /// Identifies one or more entities to which this object is attributed.
98    ///
99    /// The attributed entities might not be Actors. For instance, an object might be attributed to
100    /// the completion of another activity.
101    ///
102    /// - Range: `Object` | `Link`
103    /// - Functional: false
104    #[serde(skip_serializing_if = "Option::is_none")]
105    #[activitystreams(ab(Object, Link), concrete(String))]
106    pub attributed_to: Option<serde_json::Value>,
107
108    /// Identifies one or more entities that represent the total population of entities for which
109    /// the object can considered to be relevant.
110    ///
111    /// - Range: `Object` | `Link`
112    /// - Functional: false
113    #[serde(skip_serializing_if = "Option::is_none")]
114    #[activitystreams(ab(Object, Link), concrete(String))]
115    pub audience: Option<serde_json::Value>,
116
117    // TODO: rdf:langString
118    /// The content or textual representation of the Object encoded as a JSON string.
119    ///
120    /// By default, the value of content is HTML. The mediaType property can be used in the object
121    /// to indicate a different content type.
122    ///
123    /// The content MAY be expressed using multiple language-tagged values.
124    ///
125    /// - Range: `xsd:string` | `rdf:langString`
126    /// - Functional: false
127    #[serde(skip_serializing_if = "Option::is_none")]
128    #[activitystreams(concrete(String))]
129    pub content: Option<serde_json::Value>,
130
131    /// Identifies the context within which the object exists or an activity was performed.
132    ///
133    /// The notion of "context" used is intentionally vague. The intended function is to serve as a
134    /// means of grouping objects and activities that share a common originating context or purpose.
135    /// An example could be all activities relating to a common project or event.
136    ///
137    /// - Range: `Object` | `Link`
138    /// - Functional: false
139    #[serde(skip_serializing_if = "Option::is_none", rename = "@context")]
140    #[activitystreams(ab(Object, Link), concrete(String))]
141    pub context: Option<serde_json::Value>,
142
143    // TODO: rdf:langString
144    /// A simple, human-readable, plain-text name for the object.
145    ///
146    /// HTML markup MUST NOT be included. The name MAY be expressed using multiple language-tagged
147    /// values.
148    ///
149    /// - Range: `xsd:string` | `rdf:langString`
150    /// - Functional: false
151    #[serde(skip_serializing_if = "Option::is_none")]
152    #[serde(alias = "displayName")]
153    #[activitystreams(concrete(String))]
154    pub name: Option<serde_json::Value>,
155
156    /// The date and time describing the actual or expected ending time of the object.
157    ///
158    /// When used with an Activity object, for instance, the endTime property specifies the moment
159    /// the activity concluded or is expected to conclude.
160    ///
161    /// - Range: `xsd:dateTime`
162    /// - Functional: true
163    #[serde(skip_serializing_if = "Option::is_none")]
164    #[activitystreams(concrete(String, UtcTime), functional)]
165    pub end_time: Option<serde_json::Value>,
166
167    /// Identifies the entity (e.g. an application) that generated the object.
168    ///
169    /// - Range: `Object` | `Link`
170    /// - Functional: false
171    #[serde(skip_serializing_if = "Option::is_none")]
172    #[activitystreams(ab(Object, Link), concrete(String))]
173    pub generator: Option<serde_json::Value>,
174
175    /// Indicates an entity that describes an icon for this object.
176    ///
177    /// The image should have an aspect ratio of one (horizontal) to one (vertical) and should be
178    /// suitable for presentation at a small size.
179    ///
180    /// - Range: `Image` | `Link`
181    /// - Functional: false
182    #[serde(skip_serializing_if = "Option::is_none")]
183    #[activitystreams(ab(Object, Link), concrete(Image, String))]
184    pub icon: Option<serde_json::Value>,
185
186    /// Indicates an entity that describes an image for this object.
187    ///
188    /// Unlike the icon property, there are no aspect ratio or display size limitations assumed.
189    ///
190    /// - Range: `Image` | `Link`
191    /// - Functional: false
192    #[serde(skip_serializing_if = "Option::is_none")]
193    #[activitystreams(ab(Object, Link), concrete(Image, String))]
194    pub image: Option<serde_json::Value>,
195
196    /// Indicates one or more entities for which this object is considered a response.
197    ///
198    /// - Range: `Object` | `Link`
199    /// - Functional: false
200    #[serde(skip_serializing_if = "Option::is_none")]
201    #[activitystreams(ab(Object, Link), concrete(String))]
202    pub in_reply_to: Option<serde_json::Value>,
203
204    /// Indicates one or more physical or logical locations associated with the object.
205    ///
206    /// - Range: `Object` | `Link`
207    /// - Functional: false
208    #[serde(skip_serializing_if = "Option::is_none")]
209    #[activitystreams(ab(Object, Link), concrete(String))]
210    pub location: Option<serde_json::Value>,
211
212    /// Identifies an entity that provides a preview of this object.
213    ///
214    /// - Range: `Object` | `Link`
215    /// - Functional: false
216    #[serde(skip_serializing_if = "Option::is_none")]
217    #[activitystreams(ab(Object, Link), concrete(String))]
218    pub preview: Option<serde_json::Value>,
219
220    /// The date and time at which the object was published.
221    ///
222    /// - Range: `xsd:dateTime`
223    /// - Functional: true
224    #[serde(skip_serializing_if = "Option::is_none")]
225    #[activitystreams(concrete(String, UtcTime), functional)]
226    pub published: Option<serde_json::Value>,
227
228    /// Identifies a `Collection` containing objects considered to be responses to this object.
229    ///
230    /// - Range: `Object` | `Link`
231    /// - Functional: false
232    #[serde(skip_serializing_if = "Option::is_none")]
233    #[activitystreams(ab(Collection), concrete(String), functional)]
234    pub replies: Option<serde_json::Value>,
235
236    /// The date and time describing the actual or expected starting time of the object.
237    ///
238    /// When used with an `Activity` object, for instance, the `start_time` property specifies the
239    /// moment the activity began or is scheduled to begin.
240    ///
241    /// - Range: `Object` | `Link`
242    /// - Functional: true
243    #[serde(skip_serializing_if = "Option::is_none")]
244    #[activitystreams(concrete(String, UtcTime), functional)]
245    pub start_time: Option<serde_json::Value>,
246
247    // TODO: rdf:langString
248    /// A natural language summarization of the object encoded as HTML.
249    ///
250    /// Multiple language tagged summaries MAY be provided.
251    ///
252    /// - Range: `xsd:string` | `rdf:langString`
253    /// - Functional: false
254    #[serde(skip_serializing_if = "Option::is_none")]
255    #[activitystreams(concrete(String))]
256    pub summary: Option<serde_json::Value>,
257
258    /// One or more "tags" that have been associated with an objects. A tag can be any kind of
259    /// `Object`.
260    ///
261    /// The key difference between attachment and tag is that the former implies association by
262    /// inclusion, while the latter implies associated by reference.
263    ///
264    /// - Range: `Object` | `Link`
265    /// - Functional: false
266    #[serde(skip_serializing_if = "Option::is_none")]
267    #[activitystreams(ab(Object, Link), concrete(String))]
268    pub tag: Option<serde_json::Value>,
269
270    /// The date and time at which the object was updated,
271    ///
272    /// - Range: `xsd:dateTime`
273    /// - Functional: true
274    #[serde(skip_serializing_if = "Option::is_none")]
275    #[activitystreams(concrete(String, UtcTime), functional)]
276    pub updated: Option<serde_json::Value>,
277
278    /// Identifies one or more links to representations of the object.
279    ///
280    /// - Range: `xsd:anyUri` | `Link`
281    /// - Functional: false
282    #[serde(skip_serializing_if = "Option::is_none")]
283    #[activitystreams(concrete(String), ab(Link))]
284    pub url: Option<serde_json::Value>,
285
286    /// Identifies an entity considered to be part of the public primary audience of an `Object`.
287    ///
288    /// - Range: `Object` | `Link`
289    /// - Functional: false
290    #[serde(skip_serializing_if = "Option::is_none")]
291    #[activitystreams(ab(Object, Link), concrete(String))]
292    pub to: Option<serde_json::Value>,
293
294    /// Identifies an `Object` that is part of the private primary audience of this `Object`.
295    ///
296    /// - Range: `Object` | `Link`
297    /// - Functional: false
298    #[serde(skip_serializing_if = "Option::is_none")]
299    #[activitystreams(ab(Object, Link), concrete(String))]
300    pub bto: Option<serde_json::Value>,
301
302    /// Identifies an `Object` that is part of the public secondary audience of this `Object`.
303    ///
304    /// - Range: `Object` | `Link`
305    /// - Functional: false
306    #[serde(skip_serializing_if = "Option::is_none")]
307    #[activitystreams(ab(Object, Link), concrete(String))]
308    pub cc: Option<serde_json::Value>,
309
310    /// Identifies one or more `Objects` that are part of the private secondary audience of this
311    /// `Object`.
312    ///
313    /// - Range: `Object` | `Link`
314    /// - Functional: false
315    #[serde(skip_serializing_if = "Option::is_none")]
316    #[activitystreams(ab(Object, Link), concrete(String))]
317    pub bcc: Option<serde_json::Value>,
318
319    /// When used on an `Object`, identifies the MIME media type of the value of the content
320    /// property.
321    ///
322    /// If not specified, the content property is assumed to contain text/html content.
323    ///
324    /// - Range: `Mime Media Type`
325    /// - Functional: true
326    #[serde(skip_serializing_if = "Option::is_none")]
327    #[activitystreams(concrete(String), functional)]
328    pub media_type: Option<serde_json::Value>,
329
330    // TODO: xsd:duration
331    /// When the object describes a time-bound resource, such as an audio or video, a meeting, etc,
332    /// the duration property indicates the object's approximate duration.
333    ///
334    /// The value MUST be expressed as an xsd:duration as defined by
335    /// [[xmlschema11-2](https://www.w3.org/TR/xmlschema11-2/)], section
336    /// 3.3.6 (e.g. a period of 5 seconds is represented as "PT5S").
337    ///
338    /// - Range: `xsd:duration`
339    /// - Functional: true
340    #[serde(skip_serializing_if = "Option::is_none")]
341    #[activitystreams(concrete(String), functional)]
342    pub duration: Option<serde_json::Value>,
343}
344
345impl ObjectProperties {
346    /// Fetch a typed `Mime` struct from the `media_type` field.
347    pub fn media_type(&self) -> Result<mime::Mime> {
348        self.media_type_string()
349            .and_then(|s| s.parse().map_err(|_| Error::Deserialize))
350    }
351}
352
353/// Define all the properties of the Location type as described by the Activity Streams vocabulary.
354#[derive(Clone, Debug, Default, Deserialize, Serialize, Properties)]
355#[serde(rename_all = "camelCase")]
356pub struct PlaceProperties {
357    /// Indicates the accuracy of position coordinates on a `Place` objects.
358    ///
359    /// Expressed in properties of percentage. e.g. "94.0" means "94.0% accurate".
360    ///
361    /// - Range: `xsd:float` [>= 0.0f, <= 100.0f]
362    /// - Functional: true
363    #[serde(skip_serializing_if = "Option::is_none")]
364    #[activitystreams(concrete(f64), functional)]
365    pub accuracy: Option<serde_json::Value>,
366
367    /// Indicates the altitude of a place. The measurement units is indicated using the units
368    /// property.
369    ///
370    /// If units is not specified, the default is assumed to be "m" indicating meters.
371    ///
372    /// - Range: `xsd:float`
373    /// - Functional: true
374    #[serde(skip_serializing_if = "Option::is_none")]
375    #[activitystreams(concrete(f64), functional)]
376    pub altitude: Option<serde_json::Value>,
377
378    /// The latitude of a place.
379    ///
380    /// - Range: `xsd:float`
381    /// - Functional: true
382    #[serde(skip_serializing_if = "Option::is_none")]
383    #[activitystreams(concrete(f64), functional)]
384    pub latitude: Option<serde_json::Value>,
385
386    /// The longitude of a place.
387    ///
388    /// - Range: `xsd:float`
389    /// - Functional: true
390    #[serde(skip_serializing_if = "Option::is_none")]
391    #[activitystreams(concrete(f64), functional)]
392    pub longitude: Option<serde_json::Value>,
393
394    /// The radius from the given latitude and longitude for a Place.
395    ///
396    /// The units is expressed by the units property. If units is not specified, the default is
397    /// assumed to be "m" indicating "meters".
398    ///
399    /// - Range: `xsd:float`
400    /// - Functional: true
401    #[serde(skip_serializing_if = "Option::is_none")]
402    #[activitystreams(concrete(f64), functional)]
403    pub radius: Option<serde_json::Value>,
404
405    /// Specifies the measurement units for the radius and altitude properties on a `Place` object.
406    ///
407    /// If not specified, the default is assumed to be "m" for "meters".
408    ///
409    /// - Range: `xsd:float`
410    /// - Functional: true
411    #[serde(skip_serializing_if = "Option::is_none")]
412    #[activitystreams(concrete(String), functional)]
413    pub units: Option<serde_json::Value>,
414}
415
416/// Define all the properties of the Profile type as described by the Activity Streams vocabulary.
417#[derive(Clone, Debug, Default, Deserialize, Serialize, Properties)]
418#[serde(rename_all = "camelCase")]
419pub struct ProfileProperties {
420    /// On a `Profile` object, the describes property identifies the object described by the
421    /// `Profile`.
422    ///
423    /// - Range: `Object`
424    /// - Functional: true
425    #[activitystreams(ab(Object), concrete(String), functional)]
426    pub describes: serde_json::Value,
427}
428
429/// Define all the properties of the Relationship type as described by the Activity Streams
430/// vocabulary.
431#[derive(Clone, Debug, Default, Deserialize, Serialize, Properties)]
432#[serde(rename_all = "camelCase")]
433pub struct RelationshipProperties {
434    /// On a `Relationship` object, the subject property identifies one of the connected
435    /// individuals.
436    ///
437    /// For instance, for a `Relationship` object describing "John is related to Sally", subject
438    /// would refer to John.
439    ///
440    /// - Range: `Object` | `Link`
441    /// - Functional: true
442    #[activitystreams(ab(Object, Link), concrete(String), functional)]
443    subject: serde_json::Value,
444
445    /// When used within a `Relationship` describes the entity to which the subject is related.
446    ///
447    /// - Range: `Object` | `Link`
448    /// - Functional: false
449    #[activitystreams(ab(Object, Link), concrete(String))]
450    object: serde_json::Value,
451
452    /// On a `Relationship` object, the relationship property identifies the kind of relationship
453    /// that exists between subject and object.
454    ///
455    /// - Range: `Object`
456    /// - Functional: false
457    #[activitystreams(ab(Object), concrete(String))]
458    relationship: serde_json::Value,
459}
460
461/// Define all the properties of the Tombstone type as described by the Activity Streams vocabulary.
462#[derive(Clone, Debug, Default, Deserialize, Serialize, Properties)]
463#[serde(rename_all = "camelCase")]
464pub struct TombstoneProperties {
465    /// On a `Tombstone` object, the formerType property identifies the type of the object that was
466    /// deleted.
467    ///
468    /// - Range: `Object`
469    /// - Functional: false
470    #[serde(skip_serializing_if = "Option::is_none")]
471    #[activitystreams(ab(Object), concrete(String))]
472    pub former_type: Option<serde_json::Value>,
473
474    /// On a `Tombstone` object, the deleted property is a timestamp for when the object was
475    /// deleted.
476    ///
477    /// - Range: `xsd:dateTime`
478    /// - Functional: true
479    #[serde(skip_serializing_if = "Option::is_none")]
480    #[activitystreams(concrete(String, UtcTime), functional)]
481    pub deleted: Option<serde_json::Value>,
482}