Skip to main content

ruma_client_api/presence/
set_presence.rs

1//! `PUT /_matrix/client/*/presence/{userId}/status`
2//!
3//! Set presence status for this user.
4
5pub mod v3 {
6    //! `/v3/` ([spec])
7    //!
8    //! [spec]: https://spec.matrix.org/v1.19/client-server-api/#put_matrixclientv3presenceuseridstatus
9
10    #[cfg(feature = "unstable-msc4532")]
11    use ruma_common::presence::PresenceStatus;
12    use ruma_common::{
13        OwnedUserId,
14        api::{auth_scheme::AccessToken, request, response},
15        metadata,
16        presence::PresenceState,
17    };
18    use serde::{Deserialize, Deserializer, Serialize, Serializer};
19
20    metadata! {
21        method: PUT,
22        rate_limited: true,
23        authentication: AccessToken,
24        history: {
25            1.0 => "/_matrix/client/r0/presence/{user_id}/status",
26            1.1 => "/_matrix/client/v3/presence/{user_id}/status",
27        }
28    }
29
30    /// Request type for the `set_presence` endpoint.
31    #[request]
32    #[ruma_api(manual_body_serde)]
33    pub struct Request {
34        /// The user whose presence state will be updated.
35        #[ruma_api(path)]
36        pub user_id: OwnedUserId,
37
38        /// The new presence state.
39        pub presence: PresenceState,
40
41        /// The status message to attach to this state.
42        ///
43        /// If the `unstable-msc4532` feature is enabled, this field will
44        /// be populated with the value of `status.msg` if not set.
45        #[cfg_attr(
46            feature = "unstable-msc4532",
47            deprecated(note = "Deprecated when MSC4532 is enabled, use `status` instead")
48        )]
49        pub status_msg: Option<String>,
50
51        /// The status information to attach to this state.
52        ///
53        /// This field uses the unstable prefix defined in [MSC4532].
54        ///
55        /// [MSC4532]: https://github.com/matrix-org/matrix-spec-proposals/pull/4532
56        #[cfg(feature = "unstable-msc4532")]
57        pub status: PresenceStatus,
58    }
59
60    /// Wire representation of the request body for `set_presence`.
61    #[derive(Serialize, Deserialize)]
62    struct RequestBodyRepr {
63        /// The new presence state.
64        pub presence: PresenceState,
65
66        /// The status message to attach to this state.
67        ///
68        /// If the `unstable-msc4532` feature is enabled, this field will
69        /// be populated with the value of `status.msg` if not set.
70        #[serde(skip_serializing_if = "Option::is_none")]
71        pub status_msg: Option<String>,
72
73        /// The status information to attach to this state.
74        ///
75        /// This field uses the unstable prefix defined in [MSC4532].
76        ///
77        /// [MSC4532]: https://github.com/matrix-org/matrix-spec-proposals/pull/4532
78        #[cfg(feature = "unstable-msc4532")]
79        #[serde(
80            skip_serializing_if = "ruma_common::serde::is_default",
81            rename = "org.continuwuity.presence_v2.msc4532.status",
82            default
83        )]
84        pub status: PresenceStatus,
85    }
86
87    // Servers accept the data from clients as-is
88    impl<'de> Deserialize<'de> for RequestBody {
89        #[allow(deprecated)]
90        fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
91        where
92            D: Deserializer<'de>,
93        {
94            let RequestBodyRepr {
95                presence,
96                status_msg,
97                #[cfg(feature = "unstable-msc4532")]
98                status,
99            } = RequestBodyRepr::deserialize(deserializer)?;
100
101            Ok(Self {
102                presence,
103                status_msg,
104                #[cfg(feature = "unstable-msc4532")]
105                status,
106            })
107        }
108    }
109
110    impl Serialize for RequestBody {
111        #[allow(deprecated)]
112        fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
113        where
114            S: Serializer,
115        {
116            let RequestBody {
117                presence,
118                status_msg,
119                #[cfg(feature = "unstable-msc4532")]
120                status,
121            } = self.clone();
122
123            #[cfg(feature = "unstable-msc4532")]
124            let status = if status == PresenceStatus::default() {
125                PresenceStatus::new(status_msg)
126            } else {
127                status
128            };
129
130            #[cfg(feature = "unstable-msc4532")]
131            let status_msg = status.msg.clone();
132
133            RequestBodyRepr {
134                presence,
135                status_msg,
136                #[cfg(feature = "unstable-msc4532")]
137                status,
138            }
139            .serialize(serializer)
140        }
141    }
142
143    /// Response type for the `set_presence` endpoint.
144    #[response]
145    #[derive(Default)]
146    pub struct Response {}
147
148    impl Request {
149        /// Creates a new `Request` with the given user ID and presence state.
150        pub fn new(user_id: OwnedUserId, presence: PresenceState) -> Self {
151            Self {
152                user_id,
153                presence,
154                #[allow(deprecated)]
155                status_msg: None,
156                #[cfg(feature = "unstable-msc4532")]
157                status: PresenceStatus::default(),
158            }
159        }
160    }
161
162    impl Response {
163        /// Creates an empty `Response`.
164        pub fn new() -> Self {
165            Self {}
166        }
167    }
168}