1#pragma once
2
3/// @file
4/// @brief Structs for for requests to the Matrix API.
5
6#include <string>
7#include <variant>
8
9#include <mtx/common.hpp>
10#include <mtx/events/collections.hpp>
11#if __has_include(<nlohmann/json_fwd.hpp>)
12#include <nlohmann/json_fwd.hpp>
13#else
14#include <nlohmann/json.hpp>
15#endif
16
17namespace mtx {
18//! Namespace for request structs
19namespace requests {
20//! Convenience parameter for setting various default state events based on a preset.
21enum class Preset
22{
23 //! `join_rules` is set to `invite`. `history_visibility` is set to `shared`.
24 PrivateChat,
25 //! `join_rules` is set to `public`. `history_visibility` is set to `shared`.
26 PublicChat,
27 //! `join_rules` is set to `invite`. `history_visibility` is set to `shared`.
28 //! All invitees are given the same power level as the room creator.
29 TrustedPrivateChat,
30};
31
32//! Request payload for the `POST /_matrix/client/r0/createRoom` endpoint.
33struct CreateRoom
34{
35 //! If this is included, an `m.room.name` event will
36 //! be sent into the room to indicate the name of the room.
37 std::string name;
38 //! If this is included, an `m.room.topic` event will be sent
39 //! into the room to indicate the topic for the room.
40 std::string topic;
41 //! The desired room alias local part. e.g `#foo:example.com`.
42 std::string room_alias_name;
43 //! A list of user IDs to invite to the room.
44 std::vector<std::string> invite;
45 //! This flag makes the server set the is_direct flag on the
46 //! `m.room.member` events sent to the users in @p invite and @p invite_3pid.
47 bool is_direct = false;
48 //! Convenience parameter for setting various default state events.
49 Preset preset = Preset::PrivateChat;
50 //! Whether or not the room will be visible by non members.
51 common::RoomVisibility visibility = common::RoomVisibility::Private;
52
53 //! A list of state events to set in the new room. This allows the user to override the default
54 //! state events set in the new room. The expected format of the state events are an object with
55 //! type, state_key and content keys set.
56 std::vector<events::collections::StrippedEvents> initial_state;
57
58 //! The room version to set for the room. If not provided, the homeserver is to use its
59 //! configured default. If provided, the homeserver will return a 400 error with the errcode
60 //! M_UNSUPPORTED_ROOM_VERSION if it does not support the room version.
61 std::string room_version;
62
63 //! Extra keys, such as m.federate, to be added to the content of the m.room.create event. The
64 //! server will overwrite the following keys: creator, room_version. Future versions of the
65 //! specification may allow the server to overwrite other keys.
66 std::optional<events::state::Create> creation_content;
67
68 friend void to_json(nlohmann::json &obj, const CreateRoom &request);
69};
70
71namespace login_identifier {
72//! The user is identified by their Matrix ID.
73struct User
74{
75 //! A client can identify a user using their Matrix ID. This can either be the fully
76 //! qualified Matrix user ID, or just the localpart of the user ID.
77 std::string user;
78};
79//! The user is identified by a third-party identifier in canonicalised form.
80struct Thirdparty
81{
82 //! The medium of the third party identifier
83 std::string medium;
84 //! The canonicalised third party address of the user
85 std::string address;
86};
87//! The user is identified by a phone number.
88struct PhoneNumber
89{
90 //! The country is the two-letter uppercase ISO-3166-1 alpha-2 country code that the number
91 //! in phone should be parsed as if it were dialled from.
92 std::string country;
93 //! The phone number. If the client wishes to canonicalise the phone number, then it can use
94 //! the m.id.thirdparty identifier type with a medium of msisdn instead.
95 std::string phone;
96};
97}
98
99//! Request payload for the `POST /_matrix/client/r0/login` endpoint.
100struct Login
101{
102 //! The login type being used. One of ["m.login.password", "m.login.token"]
103 std::string type = "m.login.password";
104 //! Identification information for the user. Usually you use `login_identifier::User` with
105 //! an mxid. Required.
106 std::
107 variant<login_identifier::User, login_identifier::Thirdparty, login_identifier::PhoneNumber>
108 identifier;
109 //! Required when type is m.login.token. The login token.
110 std::string token;
111 //! Required when type is m.login.password. The user's password.
112 std::string password;
113 //! ID of the client device. If this does not correspond to a known client device,
114 //! a new device will be created.
115 //! The server will auto-generate a device_id if this is not specified.
116 std::string device_id;
117 //! A display name to assign to the newly-created device.
118 //! Ignored if device_id corresponds to a known device.
119 std::string initial_device_display_name;
120
121 friend void to_json(nlohmann::json &obj, const Login &request);
122};
123
124/// @brief Request payload for
125/// `POST /_matrix/client/r0/{register,account/password}/email/requestToken`
126///
127/// The homeserver should validate the email itself, either by sending a validation email itself or
128/// by using a service it has control over.
129struct RequestEmailToken
130{
131 //! Required. A unique string generated by the client, and used to identify the validation
132 //! attempt. It must be a string consisting of the characters [0-9a-zA-Z.=_-]. Its length must
133 //! not exceed 255 characters and it must not be empty.
134 std::string client_secret;
135 //! Required. The email address to validate.
136 std::string email;
137
138 //! Required. The server will only send an email if the send_attempt is a number greater than
139 //! the most recent one which it has seen, scoped to that email + client_secret pair. This is to
140 //! avoid repeatedly sending the same email in the case of request retries between the POSTing
141 //! user and the identity server. The client should increment this value if they desire a new
142 //! email (e.g. a reminder) to be sent. If they do not, the server should respond with success
143 //! but not resend the email.
144 int send_attempt = 0;
145
146 friend void to_json(nlohmann::json &obj, const RequestEmailToken &request);
147};
148
149/// @brief Request payload for
150/// `POST /_matrix/client/r0/{register,account/password}/msisdn/requestToken`
151///
152/// The homeserver should validate the email itself, either by sending a validation email itself or
153/// by using a service it has control over.
154struct RequestMSISDNToken
155{
156 //! Required. A unique string generated by the client, and used to identify the validation
157 //! attempt. It must be a string consisting of the characters [0-9a-zA-Z.=_-]. Its length must
158 //! not exceed 255 characters and it must not be empty.
159 std::string client_secret;
160 //! Required. The two-letter uppercase ISO-3166-1 alpha-2 country code that the number in
161 //! phone_number should be parsed as if it were dialled from.
162 std::string country;
163 //! Required. The phone number to validate.
164 std::string phone_number;
165
166 //! Required. The server will only send an SMS if the send_attempt is a number greater than the
167 //! most recent one which it has seen, scoped to that country + phone_number + client_secret
168 //! triple. This is to avoid repeatedly sending the same SMS in the case of request retries
169 //! between the POSTing user and the identity server. The client should increment this value if
170 //! they desire a new SMS (e.g. a reminder) to be sent.
171 int send_attempt = 0;
172};
173
174void
175to_json(nlohmann::json &obj, const RequestMSISDNToken &request);
176
177//! Validate ownership of an email address/phone number.
178struct IdentitySubmitToken
179{
180 //! Required. The session ID, generated by the requestToken call.
181 std::string sid;
182 //! Required. The client secret that was supplied to the requestToken call.
183 std::string client_secret;
184 //! Required. The token generated by the requestToken call and emailed to the user.
185 std::string token;
186
187 friend void to_json(nlohmann::json &obj, const IdentitySubmitToken &request);
188};
189
190//! Request payload for the `PUT /_matrix/client/r0/sendToDevice/{eventType}/{transcationID}`
191template<typename EventContent>
192using ToDeviceMessages = std::map<mtx::identifiers::User, std::map<std::string, EventContent>>;
193
194//! Request payload for the `POST /_matrix/client/r0/profile/{userId}/avatar_url` endpoint.
195struct AvatarUrl
196{
197 std::string avatar_url;
198
199 friend void to_json(nlohmann::json &obj, const AvatarUrl &request);
200};
201
202//! Request payload for the `PUT /_matrix/client/r0/profile/{userId}/displayname` endpoint.
203struct DisplayName
204{
205 //! The new display name for this device. If not given, the display name is unchanged.
206 std::string displayname;
207
208 friend void to_json(nlohmann::json &obj, const DisplayName &request);
209};
210
211//! Request payload for the `POST /_matrix/client/r0/rooms/{roomId}/invite` endpoint as well as ban,
212//! unban and kick.
213struct RoomMembershipChange
214{
215 std::string user_id;
216
217 //! optional kick, invite or ban reason
218 std::string reason;
219
220 friend void to_json(nlohmann::json &obj, const RoomMembershipChange &request);
221};
222
223//! Request payload for the `PUT /_matrix/client/r0/rooms/{roomId}/typing/{userId}` endpoint.
224struct TypingNotification
225{
226 //! Whether the user is typing or not.
227 bool typing = false;
228 //! The length of time in milliseconds to mark this user as typing.
229 uint64_t timeout = 0;
230
231 friend void to_json(nlohmann::json &obj, const TypingNotification &request);
232};
233
234//! Request payload for the `PUT /_matrix/client/r0/devices/{deviceId}` endpoint.
235struct DeviceUpdate
236{
237 std::string display_name;
238
239 friend void to_json(nlohmann::json &obj, const DeviceUpdate &request);
240};
241
242//! Request payload for the `PUT /_matrix/client/r0/directory/list/room/{roomId}` endpoint
243struct PublicRoomVisibility
244{
245 //! The new visibility setting for the room. Defaults to 'public'. One of: ["private",
246 //! "public"]
247 common::RoomVisibility visibility;
248
249 friend void to_json(nlohmann::json &obj, const PublicRoomVisibility &request);
250};
251
252struct PublicRoomsFilter
253{
254 //! A string to search for in the room metadata,
255 //! e.g. name, topic, canonical alias etc. (Optional).
256 std::string generic_search_term;
257
258 friend void to_json(nlohmann::json &obj, const PublicRoomsFilter &req);
259};
260
261//! Request payload for the `POST /_matrix/client/r0/publicRooms` endpoint.
262struct PublicRooms
263{
264 //! Limit the number of results returned.
265 int limit;
266 //! A pagination token from a previous request, allowing clients
267 //! to get the next (or previous) batch of rooms. The direction of
268 //! pagination is specified solely by which token is supplied,
269 //! rather than via an explicit flag.
270 std::string since;
271 //! Filter to apply to the results.
272 PublicRoomsFilter filter;
273 //! Whether or not to include all known networks/protocols from
274 //! application services on the homeserver. Defaults to false.
275 bool include_all_networks = false;
276 //! The specific third party network/protocol to request from
277 //! the homeserver. Can only be used if include_all_networks is false.
278 std::string third_party_instance_id;
279
280 friend void to_json(nlohmann::json &obj, const PublicRooms &request);
281};
282
283//! An empty response.
284///
285/// Some endpoints return this on success.
286struct Empty
287{
288 friend inline void to_json(nlohmann::json &, const Empty &) {}
289};
290
291//! A successfull logout.
292using Logout = Empty;
293
294//! A signed onetime key. Usually curve25519.
295struct SignedOneTimeKey
296{
297 //! Required. The unpadded Base64-encoded 32-byte Curve25519 public key.
298 std::string key;
299 //! When uploading a signed key, an additional fallback: true key should be included to denote
300 //! that the key is a fallback key.
301 bool fallback = false;
302 //! Required. Signatures of the key object.
303 //! The signature is calculated using the process described at Signing JSON.
304 std::map<std::string, std::map<std::string, std::string>> signatures;
305
306 friend void to_json(nlohmann::json &obj, const SignedOneTimeKey &);
307};
308
309//! Upload a mix of device, one time and fallback keys.
310struct UploadKeys
311{
312 //! Identity keys for the device.
313 //! May be absent if no new identity keys are required.
314 mtx::crypto::DeviceKeys device_keys;
315 //! One-time public keys for "pre-key" messages.
316 //! The names of the properties should be in the format `<algorithm>:<key_id>`.
317 //! The format of the key is determined by the key algorithm.
318 std::map<std::string, std::variant<std::string, SignedOneTimeKey>> one_time_keys;
319
320 //! The public key which should be used if the device’s one-time keys are exhausted. The
321 //! fallback key is not deleted once used, but should be replaced when additional one-time keys
322 //! are being uploaded. The server will notify the client of the fallback key being used through
323 //! /sync.
324 //!
325 //! There can only be at most one key per algorithm uploaded, and the server will only persist
326 //! one key per algorithm.
327 //!
328 //! When uploading a signed key, an additional fallback: true key should be included to denote
329 //! that the key is a fallback key.
330 //!
331 //! May be absent if a new fallback key is not required.
332 std::map<std::string, std::variant<std::string, SignedOneTimeKey>> fallback_keys;
333
334 friend void to_json(nlohmann::json &obj, const UploadKeys &);
335};
336
337//! The default timeout for a download.
338inline constexpr uint64_t DEFAULT_DOWNLOAD_TIMEOUT = 10UL * 1000; // 10 seconds
339
340//! Query the keys of devices of specific users.
341struct QueryKeys
342{
343 //! The time (in milliseconds) to wait when downloading keys from remote servers.
344 uint64_t timeout = DEFAULT_DOWNLOAD_TIMEOUT;
345 //! The keys to be downloaded.
346 //! A map from user ID, to a list of device IDs, or to an empty
347 //! list to indicate all devices for the corresponding user.
348 std::map<std::string, std::vector<std::string>> device_keys;
349 //! If the client is fetching keys as a result of a device update
350 //! received in a sync request, this should be the 'since' token of
351 //! that sync request, or any later sync token.
352 //! This allows the server to ensure its response contains the keys
353 //! advertised by the notification in that sync.
354 std::string token;
355
356 friend void to_json(nlohmann::json &obj, const QueryKeys &);
357};
358
359//! Claim onetime keys of devices of specific users.
360struct ClaimKeys
361{
362 //! The time (in milliseconds) to wait when downloading keys from remote servers.
363 uint64_t timeout = DEFAULT_DOWNLOAD_TIMEOUT;
364 //! The keys to be claimed. A map from user ID, to a map from device ID to algorithm name.
365 std::map<std::string, std::map<std::string, std::string>> one_time_keys;
366
367 friend void to_json(nlohmann::json &obj, const ClaimKeys &request);
368};
369
370//! Upload new signatures for a device or cross-signing key.
371struct KeySignaturesUpload
372{
373 //! map from user_id to either a map of device id to DeviceKey with new signatures or the
374 //! key id to CrossSigningKeys with new signatures
375 std::map<
376 std::string,
377 std::map<std::string, std::variant<mtx::crypto::DeviceKeys, mtx::crypto::CrossSigningKeys>>>
378 signatures;
379
380 friend void to_json(nlohmann::json &obj, const KeySignaturesUpload &req);
381};
382
383//! Upload cross signing keys
384struct DeviceSigningUpload
385{
386 //! Optional. The user's master key.
387 std::optional<mtx::crypto::CrossSigningKeys> master_key;
388 //! Optional. The user's self-signing key. Must be signed by the accompanying master key, or by
389 //! the user's most recently uploaded master key if no master key is included in the request.
390 std::optional<mtx::crypto::CrossSigningKeys> self_signing_key;
391 //! Optional. The user's user-signing key. Must be signed by the accompanying master key, or by
392 //! the user's most recently uploaded master key if no master key is included in the request.
393 std::optional<mtx::crypto::CrossSigningKeys> user_signing_key;
394
395 friend void to_json(nlohmann::json &obj, const DeviceSigningUpload &req);
396};
397
398//! Information about a pusher.
399struct PusherData
400{
401 //! Required if `kind` is http. The URL to use to send notifications to.
402 //! MUST be an HTTPS URL with a path of /_matrix/push/v1/notify.
403 std::string url;
404 //! The format to send notifications in to Push Gateways if the kind is http.
405 //! The details about what fields the homeserver should send to the push gateway are
406 //! defined in the Push Gateway Specification. Currently the only format available is
407 //! 'event_id_only'.
408 std::string format;
409
410 friend void to_json(nlohmann::json &obj, const PusherData &data);
411};
412
413//! Request payload for the `POST /_matrix/client/r0/pushers/set` endpoint.
414struct SetPusher
415{
416 //! Required. Unique identifier for this pusher.
417 std::string pushkey;
418 //! Required. The kind of pusher to configure. "http" makes a pusher that sends HTTP pokes.
419 //! "email" makes a pusher that emails the user with unread notifications.
420 //! null deletes the pusher.
421 std::string kind;
422 //! Required. This is a reverse-DNS style identifier for the application.
423 //! If the `kind` is "email", this is "m.email".
424 std::string app_id;
425 //! Required. A string that will allow the user to identify what application owns this
426 //! pusher.
427 std::string app_display_name;
428 //! Required. A string that will allow the user to identify what device owns this pusher.
429 std::string device_display_name;
430 //! Determines which set of device specific rules this pusher executes.
431 std::string profile_tag;
432 //! Required. The preferred language for receiving notifications.
433 std::string lang;
434 //! Required. Data for the pusher implementation (for example, if `kind` is `http`, includes
435 //! the URL to push to).
436 PusherData data;
437 //! If true, add another pusher instead of updating an existing one.
438 bool append = false;
439
440 friend void to_json(nlohmann::json &obj, const SetPusher &req);
441};
442} // namespace requests
443} // namespace mtx
444