ruma_events/room/message/
location.rs

1#[cfg(feature = "unstable-msc3488")]
2use ruma_common::MilliSecondsSinceUnixEpoch;
3use serde::{Deserialize, Serialize};
4
5use crate::room::{MediaSource, ThumbnailInfo};
6#[cfg(feature = "unstable-msc3488")]
7use crate::{
8    location::{AssetContent, AssetType, LocationContent},
9    message::{TextContentBlock, TextRepresentation},
10};
11
12/// The payload for a location message.
13#[derive(Clone, Debug, Deserialize, Serialize)]
14#[cfg_attr(not(ruma_unstable_exhaustive_types), non_exhaustive)]
15#[serde(tag = "msgtype", rename = "m.location")]
16#[cfg_attr(
17    feature = "unstable-msc3488",
18    serde(
19        from = "super::content_serde::msc3488::LocationMessageEventContentSerDeHelper",
20        into = "super::content_serde::msc3488::LocationMessageEventContentSerDeHelper"
21    )
22)]
23pub struct LocationMessageEventContent {
24    /// A description of the location e.g. "Big Ben, London, UK", or some kind of content
25    /// description for accessibility, e.g. "location attachment".
26    pub body: String,
27
28    /// A geo URI representing the location.
29    pub geo_uri: String,
30
31    /// Info about the location being represented.
32    #[serde(skip_serializing_if = "Option::is_none")]
33    pub info: Option<Box<LocationInfo>>,
34
35    /// Extensible-event text representation of the message.
36    ///
37    /// If present, this should be preferred over the `body` field.
38    #[cfg(feature = "unstable-msc3488")]
39    pub message: Option<TextContentBlock>,
40
41    /// Extensible-event location info of the message.
42    ///
43    /// If present, this should be preferred over the `geo_uri` field.
44    #[cfg(feature = "unstable-msc3488")]
45    pub location: Option<LocationContent>,
46
47    /// Extensible-event asset this message refers to.
48    #[cfg(feature = "unstable-msc3488")]
49    pub asset: Option<AssetContent>,
50
51    /// Extensible-event timestamp this message refers to.
52    #[cfg(feature = "unstable-msc3488")]
53    pub ts: Option<MilliSecondsSinceUnixEpoch>,
54}
55
56impl LocationMessageEventContent {
57    /// Creates a new `LocationMessageEventContent` with the given body and geo URI.
58    pub fn new(body: String, geo_uri: String) -> Self {
59        Self {
60            #[cfg(feature = "unstable-msc3488")]
61            message: Some(vec![TextRepresentation::plain(&body)].into()),
62            #[cfg(feature = "unstable-msc3488")]
63            location: Some(LocationContent::new(geo_uri.clone())),
64            #[cfg(feature = "unstable-msc3488")]
65            asset: Some(AssetContent::default()),
66            #[cfg(feature = "unstable-msc3488")]
67            ts: None,
68            body,
69            geo_uri,
70            info: None,
71        }
72    }
73
74    /// Set the asset type of this `LocationMessageEventContent`.
75    #[cfg(feature = "unstable-msc3488")]
76    pub fn with_asset_type(mut self, asset: AssetType) -> Self {
77        self.asset = Some(AssetContent { type_: asset });
78        self
79    }
80
81    /// Set the timestamp of this `LocationMessageEventContent`.
82    #[cfg(feature = "unstable-msc3488")]
83    pub fn with_ts(mut self, ts: MilliSecondsSinceUnixEpoch) -> Self {
84        self.ts = Some(ts);
85        self
86    }
87
88    /// Get the `geo:` URI of this `LocationMessageEventContent`.
89    pub fn geo_uri(&self) -> &str {
90        #[cfg(feature = "unstable-msc3488")]
91        if let Some(uri) = self.location.as_ref().map(|l| &l.uri) {
92            return uri;
93        }
94
95        &self.geo_uri
96    }
97
98    /// Get the plain text representation of this `LocationMessageEventContent`.
99    pub fn plain_text_representation(&self) -> &str {
100        #[cfg(feature = "unstable-msc3488")]
101        if let Some(text) = self.message.as_ref().and_then(|m| m.find_plain()) {
102            return text;
103        }
104
105        &self.body
106    }
107
108    /// Get the asset type of this `LocationMessageEventContent`.
109    #[cfg(feature = "unstable-msc3488")]
110    pub fn asset_type(&self) -> AssetType {
111        self.asset.as_ref().map(|a| a.type_.clone()).unwrap_or_default()
112    }
113}
114
115/// Thumbnail info associated with a location.
116#[derive(Clone, Debug, Default, Deserialize, Serialize)]
117#[cfg_attr(not(ruma_unstable_exhaustive_types), non_exhaustive)]
118pub struct LocationInfo {
119    /// The source of a thumbnail of the location.
120    #[serde(
121        flatten,
122        with = "crate::room::thumbnail_source_serde",
123        skip_serializing_if = "Option::is_none"
124    )]
125    pub thumbnail_source: Option<MediaSource>,
126
127    /// Metadata about the image referred to in `thumbnail_source.
128    #[serde(skip_serializing_if = "Option::is_none")]
129    pub thumbnail_info: Option<Box<ThumbnailInfo>>,
130}
131
132impl LocationInfo {
133    /// Creates an empty `LocationInfo`.
134    pub fn new() -> Self {
135        Self::default()
136    }
137}