1 #pragma once
2 
3 /// @file
4 /// @brief Primary header to access the http API.
5 
6 #if __has_include(<nlohmann/json_fwd.hpp>)
7 #include <nlohmann/json_fwd.hpp>
8 #else
9 #include <nlohmann/json.hpp>
10 #endif
11 
12 #include "mtx/errors.hpp"             // for Error
13 #include "mtx/events.hpp"             // for EventType, to_string, json
14 #include "mtx/events/collections.hpp" // for TimelineEvents
15 #include "mtx/identifiers.hpp"        // for User
16 #include "mtx/identifiers.hpp"        // for Class user
17 #include "mtx/pushrules.hpp"
18 #include "mtx/requests.hpp"
19 #include "mtx/responses/empty.hpp" // for Empty, Logout, RoomInvite
20 #include "mtx/secret_storage.hpp"
21 #include "mtxclient/http/errors.hpp" // for ClientError
22 #include "mtxclient/utils.hpp"       // for random_token, url_encode, des...
23 // #include "mtx/common.hpp"
24 
25 #include <cstdint>    // for uint16_t, uint64_t
26 #include <functional> // for function
27 #include <memory>     // for allocator, shared_ptr, enable...
28 #include <optional>   // for optional
29 #include <string>     // for string, operator+, char_traits
30 #include <utility>    // for move
31 #include <vector>     // for vector
32 
33 #include <coeurl/headers.hpp>
34 
35 // forward declarations
36 namespace mtx {
37 namespace http {
38 struct ClientPrivate;
39 struct Session;
40 }
41 namespace requests {
42 struct CreateRoom;
43 struct KeySignaturesUpload;
44 struct Login;
45 struct QueryKeys;
46 struct ClaimKeys;
47 struct UploadKeys;
48 struct PublicRoomVisibility;
49 struct PublicRooms;
50 struct PushersData;
51 struct SetPushers;
52 }
53 namespace responses {
54 struct AvatarUrl;
55 struct ClaimKeys;
56 struct ContentURI;
57 struct CreateRoom;
58 struct Device;
59 struct EventId;
60 struct FilterId;
61 struct GroupId;
62 struct GroupProfile;
63 struct JoinedGroups;
64 struct KeyChanges;
65 struct KeySignaturesUpload;
66 struct Login;
67 struct LoginFlows;
68 struct Messages;
69 struct Notifications;
70 struct Profile;
71 struct PublicRoomVisibility;
72 struct PublicRooms;
73 struct QueryDevices;
74 struct QueryKeys;
75 struct Register;
76 struct RegistrationTokenValidity;
77 struct RequestToken;
78 struct RoomId;
79 struct Success;
80 struct Sync;
81 struct TurnServer;
82 struct UploadKeys;
83 struct Version;
84 struct Versions;
85 struct WellKnown;
86 namespace backup {
87 struct SessionBackup;
88 struct RoomKeysBackup;
89 struct KeysBackup;
90 struct BackupVersion;
91 }
92 }
93 }
94 
95 namespace mtx {
96 //! Types related to invoking the actual HTTP requests
97 namespace http {
98 
99 enum class PaginationDirection
100 {
101     Backwards,
102     Forwards,
103 };
104 
105 inline std::string
to_string(PaginationDirection dir)106 to_string(PaginationDirection dir)
107 {
108     if (dir == PaginationDirection::Backwards)
109         return "b";
110 
111     return "f";
112 }
113 
114 using RequestErr   = const std::optional<mtx::http::ClientError> &;
115 using HeaderFields = const std::optional<coeurl::Headers> &;
116 using ErrCallback  = std::function<void(RequestErr)>;
117 
118 template<class Response>
119 using Callback = std::function<void(const Response &, RequestErr)>;
120 
121 template<class Response>
122 using HeadersCallback    = std::function<void(const Response &, HeaderFields, RequestErr)>;
123 using TypeErasedCallback = std::function<void(HeaderFields, const std::string_view &, int, int)>;
124 
125 //! A helper to handle user interactive authentication. This will cache the request and call the
126 //! prompt every time there is a new stage. Advance the flow by calling next().
127 class UIAHandler
128 {
129 public:
130     //! The callback for when a new UIA stage needs to be completed
131     using UIAPrompt =
132       std::function<void(const UIAHandler &, const user_interactive::Unauthorized &)>;
133 
134     //! Create a new UIA handler. Pass a callback for when a new stage needs to be completed.
UIAHandler(UIAPrompt prompt_)135     UIAHandler(UIAPrompt prompt_)
136       : prompt(std::move(prompt_))
137     {}
138 
139     void next(const user_interactive::Auth &auth) const;
140 
141 private:
142     UIAPrompt prompt;
143 
144     std::function<void(const UIAHandler &, const nlohmann::json &)> next_;
145 
146     friend class Client;
147 };
148 
149 //! Sync configuration options.
150 struct SyncOpts
151 {
152     //! Filter to apply.
153     std::string filter;
154     //! Sync pagination token.
155     std::string since;
156     //! The amount of msecs to wait for long polling.
157     uint16_t timeout = 30'000;
158     //! Wheter to include the full state of each room.
159     bool full_state = false;
160     //! Explicitly set the presence of the user
161     std::optional<mtx::presence::PresenceState> set_presence;
162 };
163 
164 //! Configuration for the /messages endpoint.
165 struct MessagesOpts
166 {
167     std::string room_id;
168     std::string from;
169     std::string to;
170     std::string filter;
171 
172     PaginationDirection dir = PaginationDirection::Backwards;
173 
174     uint16_t limit = 30;
175 };
176 
177 //! Configuration for thumbnail retrieving.
178 struct ThumbOpts
179 {
180     //! The desired width of the thumbnail.
181     uint16_t width = 128;
182     //! The desired height of the thumbnail.
183     uint16_t height = 128;
184     //! The desired resizing method. One of: ["crop", "scale"]
185     std::string method = "crop";
186     //! A mxc URI which points to the content.
187     std::string mxc_url;
188 };
189 
190 struct ClientPrivate;
191 struct Session;
192 
193 //! The main object that the user will interact.
194 class Client : public std::enable_shared_from_this<Client>
195 {
196 public:
197     Client(const std::string &server = "", uint16_t port = 443);
198     ~Client();
199 
200     //! Wait for the client to close.
201     void close(bool force = false);
202     //! Enable or disable certificate verification. On by default
203     void verify_certificates(bool enabled = true);
204     //! Set the homeserver domain name.
set_user(const mtx::identifiers::User & user)205     void set_user(const mtx::identifiers::User &user) { user_id_ = user; }
206     //! Set the device ID.
set_device_id(const std::string & device_id)207     void set_device_id(const std::string &device_id) { device_id_ = device_id; }
208     //! Set the homeserver domain name.
209     void set_server(const std::string &server);
210     //! Retrieve the homeserver domain name.
server()211     std::string server() { return server_; };
212     //! Set the homeserver port.
set_port(uint16_t port)213     void set_port(uint16_t port) { port_ = port; };
214     //! Retrieve the homeserver port.
port()215     uint16_t port() { return port_; };
216     //! Add an access token.
set_access_token(const std::string & token)217     void set_access_token(const std::string &token) { access_token_ = token; }
218     //! Retrieve the access token.
access_token() const219     std::string access_token() const { return access_token_; }
220     //! Update the next batch token.
set_next_batch_token(const std::string & token)221     void set_next_batch_token(const std::string &token) { next_batch_token_ = token; }
222     //! Retrieve the current next batch token.
next_batch_token() const223     std::string next_batch_token() const { return next_batch_token_; }
224     //! Retrieve the user_id.
user_id() const225     mtx::identifiers::User user_id() const { return user_id_; }
226     //! Retrieve the device_id.
device_id() const227     std::string device_id() const { return device_id_; }
228     //! Generate a new transaction id.
generate_txn_id()229     std::string generate_txn_id() { return client::utils::random_token(32, false); }
230     //! Abort all active pending requests.
231     void shutdown();
232     //! Remove all saved configuration.
clear()233     void clear()
234     {
235         device_id_.clear();
236         access_token_.clear();
237         next_batch_token_.clear();
238         server_.clear();
239         port_ = 443;
240     }
241 
242     //! Perfom login.
243     void login(const std::string &username,
244                const std::string &password,
245                Callback<mtx::responses::Login> cb);
246     void login(const std::string &username,
247                const std::string &password,
248                const std::string &device_name,
249                Callback<mtx::responses::Login> cb);
250     void login(const mtx::requests::Login &req, Callback<mtx::responses::Login> cb);
251 
252     //! Get the supported login flows
253     void get_login(Callback<mtx::responses::LoginFlows> cb);
254     //! Get url to navigate to for sso login flow
255     //! Open this in a browser
256     std::string login_sso_redirect(std::string redirectUrl);
257     //! Lookup real server to connect to.
258     //! Call set_server with the returned homeserver url after this
259     void well_known(Callback<mtx::responses::WellKnown> cb);
260 
261     //! Register with an UIA handler so you don't need to repeat the request manually.
262     void registration(const std::string &user,
263                       const std::string &pass,
264                       UIAHandler uia_handler,
265                       Callback<mtx::responses::Register> cb);
266 
267     //! Check the validity of a registration token
268     void registration_token_validity(const std::string token,
269                                      Callback<mtx::responses::RegistrationTokenValidity> cb);
270 
271     //! Validate an unused email address.
272     void register_email_request_token(const requests::RequestEmailToken &r,
273                                       Callback<mtx::responses::RequestToken> cb);
274     //! Validate a used email address.
275     void verify_email_request_token(const requests::RequestEmailToken &r,
276                                     Callback<mtx::responses::RequestToken> cb);
277 
278     //! Validate an unused phone number.
279     void register_phone_request_token(const requests::RequestMSISDNToken &r,
280                                       Callback<mtx::responses::RequestToken> cb);
281     //! Validate a used phone number.
282     void verify_phone_request_token(const requests::RequestMSISDNToken &r,
283                                     Callback<mtx::responses::RequestToken> cb);
284 
285     //! Validate ownership of an email address/phone number.
286     void validate_submit_token(const std::string &url,
287                                const requests::IdentitySubmitToken &r,
288                                Callback<mtx::responses::Success>);
289 
290     //! Paginate through the list of events that the user has been,
291     //! or would have been notified about.
292     void notifications(uint64_t limit,
293                        const std::string &from,
294                        const std::string &only,
295                        Callback<mtx::responses::Notifications> cb);
296 
297     //! Retrieve all push rulesets for this user.
298     void get_pushrules(Callback<pushrules::GlobalRuleset> cb);
299 
300     //! Retrieve a single specified push rule.
301     void get_pushrules(const std::string &scope,
302                        const std::string &kind,
303                        const std::string &ruleId,
304                        Callback<pushrules::PushRule> cb);
305 
306     //! This endpoint removes the push rule defined in the path.
307     void delete_pushrules(const std::string &scope,
308                           const std::string &kind,
309                           const std::string &ruleId,
310                           ErrCallback cb);
311 
312     //! This endpoint allows the creation, modification and deletion of pushers for this user
313     //! ID.
314     void put_pushrules(const std::string &scope,
315                        const std::string &kind,
316                        const std::string &ruleId,
317                        const pushrules::PushRule &rule,
318                        ErrCallback cb,
319                        const std::string &before = "",
320                        const std::string &after  = "");
321 
322     //! Retrieve a single specified push rule.
323     void get_pushrules_enabled(const std::string &scope,
324                                const std::string &kind,
325                                const std::string &ruleId,
326                                Callback<pushrules::Enabled> cb);
327 
328     //! This endpoint allows clients to enable or disable the specified push rule.
329     void put_pushrules_enabled(const std::string &scope,
330                                const std::string &kind,
331                                const std::string &ruleId,
332                                bool enabled,
333                                ErrCallback cb);
334 
335     //! This endpoint get the actions for the specified push rule.
336     void get_pushrules_actions(const std::string &scope,
337                                const std::string &kind,
338                                const std::string &ruleId,
339                                Callback<pushrules::actions::Actions> cb);
340 
341     //! This endpoint allows clients to change the actions of a push rule. This can be used to
342     //! change the actions of builtin rules.
343     void put_pushrules_actions(const std::string &scope,
344                                const std::string &kind,
345                                const std::string &ruleId,
346                                const pushrules::actions::Actions &actions,
347                                ErrCallback cb);
348 
349     //! Perform logout.
350     void logout(Callback<mtx::responses::Logout> cb);
351     //! Change avatar.
352     void set_avatar_url(const std::string &avatar_url, ErrCallback cb);
353     //! Change displayname.
354     void set_displayname(const std::string &displayname, ErrCallback cb);
355     //! Get user profile.
356     void get_profile(const std::string &user_id, Callback<mtx::responses::Profile> cb);
357     //! Get user avatar URL.
358     void get_avatar_url(const std::string &user_id, Callback<mtx::responses::AvatarUrl> cb);
359 
360     //! List the tags set by a user on a room.
361     void get_tags(const std::string &room_id, Callback<mtx::events::account_data::Tags> cb);
362     //! Add a tag to the room.
363     void put_tag(const std::string &room_id,
364                  const std::string &tag_name,
365                  const mtx::events::account_data::Tag &tag,
366                  ErrCallback cb);
367     //! Remove a tag from the room.
368     void delete_tag(const std::string &room_id, const std::string &tag_name, ErrCallback cb);
369 
370     //! Create a room with the given options.
371     void create_room(const mtx::requests::CreateRoom &room_options,
372                      Callback<mtx::responses::CreateRoom> cb);
373     //! Join a room by an alias or a room_id.
374     void join_room(const std::string &room, Callback<mtx::responses::RoomId> cb);
375     //! Join a room by an alias or a room_id. `via` are other servers, that may know about this
376     //! room.
377     void join_room(const std::string &room,
378                    const std::vector<std::string> &via,
379                    Callback<mtx::responses::RoomId> cb);
380     //! Leave a room by its room_id.
381     void leave_room(const std::string &room_id, Callback<mtx::responses::Empty> cb);
382     //! Knock on a room.
383     void knock_room(const std::string &room_id,
384                     const std::vector<std::string> &via,
385                     Callback<mtx::responses::RoomId> cb,
386                     const std::string &reason = "");
387 
388     //! Invite a user to a room.
389     void invite_user(const std::string &room_id,
390                      const std::string &user_id,
391                      Callback<mtx::responses::RoomInvite> cb,
392                      const std::string &reason = "");
393     //! Kick a user from a room.
394     void kick_user(const std::string &room_id,
395                    const std::string &user_id,
396                    Callback<mtx::responses::Empty> cb,
397                    const std::string &reason = "");
398     //! Ban a user from a room.
399     void ban_user(const std::string &room_id,
400                   const std::string &user_id,
401                   Callback<mtx::responses::Empty> cb,
402                   const std::string &reason = "");
403     //! Unban a user from a room.
404     void unban_user(const std::string &room_id,
405                     const std::string &user_id,
406                     Callback<mtx::responses::Empty> cb,
407                     const std::string &reason = "");
408 
409     //! Perform sync.
410     void sync(const SyncOpts &opts, Callback<mtx::responses::Sync> cb);
411 
412     //! Paginate through room messages.
413     void messages(const MessagesOpts &opts, Callback<mtx::responses::Messages> cb);
414 
415     //! Get the supported versions from the server.
416     void versions(Callback<mtx::responses::Versions> cb);
417 
418     //! Mark an event as read.
419     void read_event(const std::string &room_id, const std::string &event_id, ErrCallback cb);
420 
421     //! Redact an event from a room.
422     void redact_event(const std::string &room_id,
423                       const std::string &event_id,
424                       Callback<mtx::responses::EventId> cb);
425 
426     //! Upload a filter
427     void upload_filter(const nlohmann::json &j, Callback<mtx::responses::FilterId> cb);
428 
429     //! Upload data to the content repository.
430     void upload(const std::string &data,
431                 const std::string &content_type,
432                 const std::string &filename,
433                 Callback<mtx::responses::ContentURI> cb);
434     //! Retrieve data from the content repository.
435     void download(const std::string &mxc_url,
436                   std::function<void(const std::string &data,
437                                      const std::string &content_type,
438                                      const std::string &original_filename,
439                                      RequestErr err)> cb);
440     void download(const std::string &server,
441                   const std::string &media_id,
442                   std::function<void(const std::string &data,
443                                      const std::string &content_type,
444                                      const std::string &original_filename,
445                                      RequestErr err)> cb);
446 
447     //! Retrieve a thumbnail from the given mxc url.
448     //! If the thumbnail isn't found and `try_download` is `true` it will try
449     //! to use the `/download` endpoint to retrieve the media.
450     void get_thumbnail(const ThumbOpts &opts, Callback<std::string> cb, bool try_download = true);
451 
452     //! Send typing notifications to the room.
453     void start_typing(const std::string &room_id, uint64_t timeout, ErrCallback cb);
454     //! Remove typing notifications from the room.
455     void stop_typing(const std::string &room_id, ErrCallback cb);
456 
457     //! Get presence of a user
458     void presence_status(const std::string &user_id, Callback<mtx::events::presence::Presence> cb);
459     //! Set presence of the user
460     void put_presence_status(mtx::presence::PresenceState state,
461                              std::optional<std::string> status_msg,
462                              ErrCallback cb);
463 
464     //! Get a single event.
465     void get_event(const std::string &room_id,
466                    const std::string &event_id,
467                    Callback<mtx::events::collections::TimelineEvents> cb);
468 
469     //! Retrieve a single state event.
470     template<class Payload>
471     void get_state_event(const std::string &room_id,
472                          const std::string &type,
473                          const std::string &state_key,
474                          Callback<Payload> payload);
475     //! Retrieve a single state event.
476     template<class Payload>
477     void get_state_event(const std::string &room_id,
478                          const std::string &state_key,
479                          Callback<Payload> cb);
480 
481     //! Store a room account_data event.
482     template<class Payload>
483     void put_room_account_data(const std::string &room_id,
484                                const std::string &type,
485                                const Payload &payload,
486                                ErrCallback cb);
487     //! Store a room account_data event.
488     template<class Payload>
489     void put_room_account_data(const std::string &room_id, const Payload &payload, ErrCallback cb);
490 
491     //! Store an account_data event.
492     template<class Payload>
493     void put_account_data(const std::string &type, const Payload &payload, ErrCallback cb);
494     //! Store an account_data event.
495     template<class Payload>
496     void put_account_data(const Payload &payload, ErrCallback cb);
497 
498     //! Retrieve a room account_data event.
499     template<class Payload>
500     void get_room_account_data(const std::string &room_id,
501                                const std::string &type,
502                                Callback<Payload> payload);
503     //! Retrieve a room account_data event.
504     template<class Payload>
505     void get_room_account_data(const std::string &room_id, Callback<Payload> cb);
506 
507     //! Retrieve an account_data event.
508     template<class Payload>
509     void get_account_data(const std::string &type, Callback<Payload> payload);
510     //! Retrieve an account_data event.
511     template<class Payload>
512     void get_account_data(Callback<Payload> cb);
513 
514     //! Send a room message with auto-generated transaction id.
515     template<class Payload>
516     void send_room_message(const std::string &room_id,
517                            const Payload &payload,
518                            Callback<mtx::responses::EventId> cb);
519     //! Send a room message by providing transaction id.
520     template<class Payload>
521     void send_room_message(const std::string &room_id,
522                            const std::string &txn_id,
523                            const Payload &payload,
524                            Callback<mtx::responses::EventId> cb);
525     //! Send a state event by providing the state key.
526     void send_state_event(const std::string &room_id,
527                           const std::string &event_type,
528                           const std::string &state_key,
529                           const nlohmann::json &payload,
530                           Callback<mtx::responses::EventId> callback);
531     template<class Payload>
532     void send_state_event(const std::string &room_id,
533                           const std::string &state_key,
534                           const Payload &payload,
535                           Callback<mtx::responses::EventId> cb);
536     //! Send a state event with an empty state key.
537     template<class Payload>
538     void send_state_event(const std::string &room_id,
539                           const Payload &payload,
540                           Callback<mtx::responses::EventId> cb);
541 
542     //! Send send-to-device events to a set of client devices with a specified transaction id.
543     void send_to_device(const std::string &event_type,
544                         const std::string &txid,
545                         const nlohmann::json &body,
546                         ErrCallback cb);
547 
548     //! Send send-to-device events to a set of client devices with a generated transaction id.
send_to_device(const std::string & event_type,const nlohmann::json & body,ErrCallback cb)549     void send_to_device(const std::string &event_type, const nlohmann::json &body, ErrCallback cb)
550     {
551         send_to_device(event_type, generate_txn_id(), body, cb);
552     }
553     //! Send send-to-device events to a set of client devices with a specified transaction id.
554     template<typename EventContent>
555     void send_to_device(
556       const std::string &txid,
557       const std::map<mtx::identifiers::User, std::map<std::string, EventContent>> &messages,
558       ErrCallback callback);
559 
560     //! Gets the visibility of a given room on the server's public room directory.
561     void get_room_visibility(const std::string &room_id,
562                              Callback<mtx::responses::PublicRoomVisibility> cb);
563 
564     //! Sets the visibility of a given room in the server's public room directory.
565     void put_room_visibility(const std::string &room_id,
566                              const mtx::requests::PublicRoomVisibility &req,
567                              ErrCallback cb);
568 
569     //! Lists the public rooms on the server. This API returns paginated responses.
570     //! The rooms are ordered by the number of joined members, with the largest rooms first.
571     void get_public_rooms(Callback<mtx::responses::PublicRooms> cb,
572                           const std::string &server = "",
573                           size_t limit              = 0,
574                           const std::string &since  = "");
575 
576     //! Lists the public rooms on the server, with optional filter. POST Request.
577     void post_public_rooms(const mtx::requests::PublicRooms &req,
578                            Callback<mtx::responses::PublicRooms> cb,
579                            const std::string &server = "");
580 
581     //
582     // Group related endpoints.
583     //
584 
585     void create_group(const std::string &localpart, Callback<mtx::responses::GroupId> cb);
586     void joined_groups(Callback<mtx::responses::JoinedGroups> cb);
587     void group_profile(const std::string &group_id, Callback<mtx::responses::GroupProfile> cb);
588     void group_rooms(const std::string &group_id, Callback<nlohmann::json> cb);
589     void set_group_profile(const std::string &group_id,
590                            nlohmann::json &req,
591                            Callback<nlohmann::json> cb);
592     void add_room_to_group(const std::string &room_id, const std::string &group_id, ErrCallback cb);
593 
594     //
595     // Device related endpoints.
596     //
597 
598     //! List devices
599     void query_devices(Callback<mtx::responses::QueryDevices> cb);
600 
601     //! Gets information on a single device, by device id.
602     void get_device(const std::string &device_id, Callback<mtx::responses::Device> cb);
603 
604     //! Updates the display name of the given device id.
605     void set_device_name(const std::string &device_id,
606                          const std::string &display_name,
607                          ErrCallback callback);
608 
609     //! Delete device
610     void delete_device(const std::string &device_id, UIAHandler uia_handler, ErrCallback cb);
611 
612     //! Delete devices
613     void delete_devices(const std::vector<std::string> &device_ids,
614                         UIAHandler uia_handler,
615                         ErrCallback cb);
616 
617     //
618     // Encryption related endpoints.
619     //
620 
621     //! Enable encryption in a room by sending a `m.room.encryption` state event.
622     void enable_encryption(const std::string &room, Callback<mtx::responses::EventId> cb);
623 
624     //! Upload identity keys & one time keys.
625     void upload_keys(const mtx::requests::UploadKeys &req, Callback<mtx::responses::UploadKeys> cb);
626 
627     //! Upload signatures for cross-signing keys
628     void keys_signatures_upload(const mtx::requests::KeySignaturesUpload &req,
629                                 Callback<mtx::responses::KeySignaturesUpload> cb);
630 
631     //! Upload cross signing keys
632     void device_signing_upload(const mtx::requests::DeviceSigningUpload,
633                                UIAHandler uia_handler,
634                                ErrCallback cb);
635 
636     //! Returns the current devices and identity keys for the given users.
637     void query_keys(const mtx::requests::QueryKeys &req, Callback<mtx::responses::QueryKeys> cb);
638 
639     /// @brief Claims one-time keys for use in pre-key messages.
640     ///
641     /// Pass in a map from userid to device_keys
642     void claim_keys(const mtx::requests::ClaimKeys &req, Callback<mtx::responses::ClaimKeys> cb);
643 
644     /// @brief Gets a list of users who have updated their device identity keys since a previous
645     /// sync token.
646     void key_changes(const std::string &from,
647                      const std::string &to,
648                      Callback<mtx::responses::KeyChanges> cb);
649 
650     //
651     // Key backup endpoints
652     //
653     void backup_version(Callback<mtx::responses::backup::BackupVersion> cb);
654     void backup_version(const std::string &version,
655                         Callback<mtx::responses::backup::BackupVersion> cb);
656     void update_backup_version(const std::string &version,
657                                const mtx::responses::backup::BackupVersion &data,
658                                ErrCallback cb);
659     void post_backup_version(const std::string &algorithm,
660                              const std::string &auth_data,
661                              Callback<mtx::responses::Version> cb);
662 
663     void room_keys(const std::string &version, Callback<mtx::responses::backup::KeysBackup> cb);
664     void room_keys(const std::string &version,
665                    const std::string &room_id,
666                    Callback<mtx::responses::backup::RoomKeysBackup> cb);
667     void room_keys(const std::string &version,
668                    const std::string &room_id,
669                    const std::string &session_id,
670                    Callback<mtx::responses::backup::SessionBackup> cb);
671     void put_room_keys(const std::string &version,
672                        const mtx::responses::backup::KeysBackup &keys,
673                        ErrCallback cb);
674     void put_room_keys(const std::string &version,
675                        const std::string &room_id,
676                        const mtx::responses::backup::RoomKeysBackup &keys,
677                        ErrCallback cb);
678     void put_room_keys(const std::string &version,
679                        const std::string &room_id,
680                        const std::string &session_id,
681                        const mtx::responses::backup::SessionBackup &keys,
682                        ErrCallback cb);
683 
684     //
685     // Secret storage endpoints
686     //
687 
688     //! Retrieve a specific secret
689     void secret_storage_secret(const std::string &secret_id,
690                                Callback<mtx::secret_storage::Secret> cb);
691     //! Retrieve information about a key
692     void secret_storage_key(const std::string &key_id,
693                             Callback<mtx::secret_storage::AesHmacSha2KeyDescription> cb);
694 
695     //! Upload a specific secret
696     void upload_secret_storage_secret(const std::string &secret_id,
697                                       const mtx::secret_storage::Secret &secret,
698                                       ErrCallback cb);
699     //! Upload information about a key
700     void upload_secret_storage_key(const std::string &key_id,
701                                    const mtx::secret_storage::AesHmacSha2KeyDescription &desc,
702                                    ErrCallback cb);
703 
704     //! Set the default key for the secret storage
705     void set_secret_storage_default_key(const std::string &key_id, ErrCallback cb);
706 
707     //! Gets any TURN server URIs and authentication credentials
708     void get_turn_server(Callback<mtx::responses::TurnServer> cb);
709 
710     //! Sets, updates, or deletes a pusher
711     void set_pusher(const mtx::requests::SetPusher &req, Callback<mtx::responses::Empty> cb);
712 
713 private:
714     template<class Request, class Response>
715     void post(const std::string &endpoint,
716               const Request &req,
717               Callback<Response> cb,
718               bool requires_auth              = true,
719               const std::string &content_type = "application/json");
720 
721     // put function for the PUT HTTP requests that send responses
722     template<class Request, class Response>
723     void put(const std::string &endpoint,
724              const Request &req,
725              Callback<Response> cb,
726              bool requires_auth = true);
727 
728     template<class Request>
729     void put(const std::string &endpoint,
730              const Request &req,
731              ErrCallback cb,
732              bool requires_auth = true);
733 
734     template<class Response>
735     void get(const std::string &endpoint,
736              HeadersCallback<Response> cb,
737              bool requires_auth                    = true,
738              const std::string &endpoint_namespace = "/_matrix",
739              int num_redirects                     = 0);
740 
741     // type erased versions of http verbs
742     void post(const std::string &endpoint,
743               const std::string &req,
744               TypeErasedCallback cb,
745               bool requires_auth,
746               const std::string &content_type);
747 
748     void put(const std::string &endpoint,
749              const std::string &req,
750              TypeErasedCallback cb,
751              bool requires_auth);
752 
753     void get(const std::string &endpoint,
754              TypeErasedCallback cb,
755              bool requires_auth,
756              const std::string &endpoint_namespace,
757              int num_redirects = 0);
758 
759     void delete_(const std::string &endpoint, ErrCallback cb, bool requires_auth = true);
760 
761     coeurl::Headers prepare_headers(bool requires_auth);
762     std::string endpoint_to_url(const std::string &endpoint,
763                                 const char *endpoint_namespace = "/_matrix");
764 
765     template<class Response>
766     TypeErasedCallback prepare_callback(HeadersCallback<Response> callback);
767 
768     //! The protocol used, i.e. https or http
769     std::string protocol_;
770     //! The homeserver to connect to.
771     std::string server_;
772     //! The access token that would be used for authentication.
773     std::string access_token_;
774     //! The user ID associated with the client.
775     mtx::identifiers::User user_id_;
776     //! The device that this session is associated with.
777     std::string device_id_;
778     //! The token that will be used as the 'since' parameter on the next sync request.
779     std::string next_batch_token_;
780     //! The homeserver port to connect.
781     uint16_t port_ = 443;
782 
783     std::unique_ptr<ClientPrivate> p;
784 };
785 }
786 }
787 
788 // Template instantiations for the various send functions
789 
790 #define MTXCLIENT_SEND_STATE_EVENT_FWD(Content)                                                    \
791     extern template void mtx::http::Client::send_state_event<mtx::events::Content>(                \
792       const std::string &,                                                                         \
793       const std::string &state_key,                                                                \
794       const mtx::events::Content &,                                                                \
795       Callback<mtx::responses::EventId> cb);                                                       \
796     extern template void mtx::http::Client::send_state_event<mtx::events::Content>(                \
797       const std::string &, const mtx::events::Content &, Callback<mtx::responses::EventId> cb);
798 
799 MTXCLIENT_SEND_STATE_EVENT_FWD(state::Aliases)
800 MTXCLIENT_SEND_STATE_EVENT_FWD(state::Avatar)
801 MTXCLIENT_SEND_STATE_EVENT_FWD(state::CanonicalAlias)
802 MTXCLIENT_SEND_STATE_EVENT_FWD(state::Create)
803 MTXCLIENT_SEND_STATE_EVENT_FWD(state::Encryption)
804 MTXCLIENT_SEND_STATE_EVENT_FWD(state::GuestAccess)
805 MTXCLIENT_SEND_STATE_EVENT_FWD(state::HistoryVisibility)
806 MTXCLIENT_SEND_STATE_EVENT_FWD(state::JoinRules)
807 MTXCLIENT_SEND_STATE_EVENT_FWD(state::Member)
808 MTXCLIENT_SEND_STATE_EVENT_FWD(state::Name)
809 MTXCLIENT_SEND_STATE_EVENT_FWD(state::PinnedEvents)
810 MTXCLIENT_SEND_STATE_EVENT_FWD(state::PowerLevels)
811 MTXCLIENT_SEND_STATE_EVENT_FWD(state::Tombstone)
812 MTXCLIENT_SEND_STATE_EVENT_FWD(state::Topic)
813 MTXCLIENT_SEND_STATE_EVENT_FWD(state::space::Child)
814 MTXCLIENT_SEND_STATE_EVENT_FWD(state::space::Parent)
815 MTXCLIENT_SEND_STATE_EVENT_FWD(msc2545::ImagePack)
816 
817 #define MTXCLIENT_SEND_ROOM_MESSAGE_FWD(Content)                                                   \
818     extern template void mtx::http::Client::send_room_message<Content>(                            \
819       const std::string &,                                                                         \
820       const std::string &,                                                                         \
821       const Content &,                                                                             \
822       Callback<mtx::responses::EventId> cb);                                                       \
823     extern template void mtx::http::Client::send_room_message<Content>(                            \
824       const std::string &, const Content &, Callback<mtx::responses::EventId> cb);
825 
826 MTXCLIENT_SEND_ROOM_MESSAGE_FWD(mtx::events::msg::Encrypted)
827 MTXCLIENT_SEND_ROOM_MESSAGE_FWD(mtx::events::msg::StickerImage)
828 MTXCLIENT_SEND_ROOM_MESSAGE_FWD(mtx::events::msg::Reaction)
829 MTXCLIENT_SEND_ROOM_MESSAGE_FWD(mtx::events::msg::Audio)
830 MTXCLIENT_SEND_ROOM_MESSAGE_FWD(mtx::events::msg::Emote)
831 MTXCLIENT_SEND_ROOM_MESSAGE_FWD(mtx::events::msg::File)
832 MTXCLIENT_SEND_ROOM_MESSAGE_FWD(mtx::events::msg::Image)
833 MTXCLIENT_SEND_ROOM_MESSAGE_FWD(mtx::events::msg::Notice)
834 MTXCLIENT_SEND_ROOM_MESSAGE_FWD(mtx::events::msg::Text)
835 MTXCLIENT_SEND_ROOM_MESSAGE_FWD(mtx::events::msg::Video)
836 // MTXCLIENT_SEND_ROOM_MESSAGE(mtx::events::msg::KeyVerificationRequest)
837 // MTXCLIENT_SEND_ROOM_MESSAGE(mtx::events::msg::KeyVerificationStart)
838 // MTXCLIENT_SEND_ROOM_MESSAGE(mtx::events::msg::KeyVerificationReady)
839 // MTXCLIENT_SEND_ROOM_MESSAGE(mtx::events::msg::KeyVerificationDone)
840 // MTXCLIENT_SEND_ROOM_MESSAGE(mtx::events::msg::KeyVerificationAccept)
841 // MTXCLIENT_SEND_ROOM_MESSAGE(mtx::events::msg::KeyVerificationCancel)
842 // MTXCLIENT_SEND_ROOM_MESSAGE(mtx::events::msg::KeyVerificationKey)
843 // MTXCLIENT_SEND_ROOM_MESSAGE(mtx::events::msg::KeyVerificationMac)
844 MTXCLIENT_SEND_ROOM_MESSAGE_FWD(mtx::events::msg::CallInvite)
845 MTXCLIENT_SEND_ROOM_MESSAGE_FWD(mtx::events::msg::CallCandidates)
846 MTXCLIENT_SEND_ROOM_MESSAGE_FWD(mtx::events::msg::CallAnswer)
847 MTXCLIENT_SEND_ROOM_MESSAGE_FWD(mtx::events::msg::CallHangUp)
848 
849 #define MTXCLIENT_SEND_TO_DEVICE_FWD(Content)                                                      \
850     extern template void mtx::http::Client::send_to_device<Content>(                               \
851       const std::string &txid,                                                                     \
852       const std::map<mtx::identifiers::User, std::map<std::string, Content>> &messages,            \
853       ErrCallback callback);
854 
855 MTXCLIENT_SEND_TO_DEVICE_FWD(mtx::events::msg::RoomKey)
856 MTXCLIENT_SEND_TO_DEVICE_FWD(mtx::events::msg::ForwardedRoomKey)
857 MTXCLIENT_SEND_TO_DEVICE_FWD(mtx::events::msg::KeyRequest)
858 MTXCLIENT_SEND_TO_DEVICE_FWD(mtx::events::msg::OlmEncrypted)
859 MTXCLIENT_SEND_TO_DEVICE_FWD(mtx::events::msg::Encrypted)
860 MTXCLIENT_SEND_TO_DEVICE_FWD(mtx::events::msg::Dummy)
861 MTXCLIENT_SEND_TO_DEVICE_FWD(mtx::events::msg::KeyVerificationRequest)
862 MTXCLIENT_SEND_TO_DEVICE_FWD(mtx::events::msg::KeyVerificationStart)
863 MTXCLIENT_SEND_TO_DEVICE_FWD(mtx::events::msg::KeyVerificationReady)
864 MTXCLIENT_SEND_TO_DEVICE_FWD(mtx::events::msg::KeyVerificationDone)
865 MTXCLIENT_SEND_TO_DEVICE_FWD(mtx::events::msg::KeyVerificationAccept)
866 MTXCLIENT_SEND_TO_DEVICE_FWD(mtx::events::msg::KeyVerificationCancel)
867 MTXCLIENT_SEND_TO_DEVICE_FWD(mtx::events::msg::KeyVerificationKey)
868 MTXCLIENT_SEND_TO_DEVICE_FWD(mtx::events::msg::KeyVerificationMac)
869 MTXCLIENT_SEND_TO_DEVICE_FWD(mtx::events::msg::SecretSend)
870 MTXCLIENT_SEND_TO_DEVICE_FWD(mtx::events::msg::SecretRequest)
871 
872 #define MTXCLIENT_ACCOUNT_DATA_FWD(Payload)                                                        \
873     extern template void mtx::http::Client::put_room_account_data<Payload>(                        \
874       const std::string &room_id,                                                                  \
875       const std::string &type,                                                                     \
876       const Payload &payload,                                                                      \
877       ErrCallback cb);                                                                             \
878     extern template void mtx::http::Client::put_room_account_data<Payload>(                        \
879       const std::string &room_id, const Payload &payload, ErrCallback cb);                         \
880     extern template void mtx::http::Client::put_account_data<Payload>(                             \
881       const std::string &type, const Payload &payload, ErrCallback cb);                            \
882     extern template void mtx::http::Client::put_account_data<Payload>(const Payload &payload,      \
883                                                                       ErrCallback cb);             \
884     extern template void mtx::http::Client::get_room_account_data<Payload>(                        \
885       const std::string &room_id, const std::string &type, Callback<Payload> payload);             \
886     extern template void mtx::http::Client::get_room_account_data<Payload>(                        \
887       const std::string &room_id, Callback<Payload> cb);                                           \
888     extern template void mtx::http::Client::get_account_data<Payload>(const std::string &type,     \
889                                                                       Callback<Payload> payload);  \
890     extern template void mtx::http::Client::get_account_data<Payload>(Callback<Payload> cb);
891 
892 MTXCLIENT_ACCOUNT_DATA_FWD(mtx::events::msc2545::ImagePack)
893 MTXCLIENT_ACCOUNT_DATA_FWD(mtx::events::msc2545::ImagePackRooms)
894 MTXCLIENT_ACCOUNT_DATA_FWD(mtx::events::account_data::nheko_extensions::HiddenEvents)
895 MTXCLIENT_ACCOUNT_DATA_FWD(mtx::events::account_data::Tags)
896