diff --git a/include/matrix/client.hpp b/include/matrix/client.hpp index bd0b8c1..d89bbce 100644 --- a/include/matrix/client.hpp +++ b/include/matrix/client.hpp @@ -31,49 +31,125 @@ #include //size_t namespace matrix{ - //main class + //Class to interact with the homeserver of the logged in user. + //Shares state with the spawning session. class client : public connection { public: client(const std::shared_ptr&); + + //Copy and move ctor client(const client& b) = default; client(client&& b) = default; + //Dtor ~client(void) = default; + //Copy and move assignment client& operator=(const client&) = default; client& operator=(client&&) = default; - //local getter + /* + * NOT thread safe. + * Returns: the current access token. + */ const raii::rjp_string& access_token(void)const; + /* + * NOT thread safe + * Returns: the logged in user's userid. + */ const raii::rjp_string& userid(void)const; + /* + * NOT thread safe + * Returns: the current useragent. + */ const raii::string& useragent(void)const; - //networked setter - void set_display_name(const raii::string_base&); - void set_profile_picture(const raii::string_base&); - //networked getter + /* + * Sets the display name on the homeserver. + * Note name must be safe to be placed in a json string. + * Returns: true if the operation was successful. + */ + bool set_display_name(const raii::string_base&); + /* + * Sets the url of the user's profile picture on the homeserver. + * Note url must be safe to be placed in a json string. + * Returns: true if the operation was successful. + */ + bool set_profile_picture(const raii::string_base&); + + + /* + * Gets the display name of the logged in user from the homeserver. + * Returns: the display name on success, an empty string on failure. + */ raii::rjp_string get_display_name(void)const; + /* + * Gets the profile picture url of the logged in user from the homeserver. + * Returns: the profile picture url on success, an empty string on failure. + */ raii::rjp_string get_profile_picture(void)const; + /* + * Lookup a room id given a room alias. + * Returns: the room id of the associated room on success, empty string on failure. + */ raii::rjp_string room_alias_to_id(const raii::string_base& alias)const; + + /* + * Get a list of rooms the logged in user is a member of. + * Returns: a vector of room id strings. + */ std::vector list_rooms(void)const; - //room membership - raii::string create_room(const raii::string_base& name, const raii::string_base& alias)const; + /* + * Create a new room on the logged in user's homeserver. Assign an alias to the room. + * Returns: the room id of the newly created room on success, an empty string on failure. + */ + raii::rjp_string create_room(const raii::string_base& name, const raii::string_base& alias)const; + /* + * Create a new matrix::roomcxn object for the given roomid. + * The roomcxn will share login information with this client. Note that changing useragent, + * access token, or homeserver after creating a roomcxn MUST be synchronized between threads. + * Returns: a new matrix::roomcxn for the given roomid. + */ roomcxn spawn_room(const raii::string_base& roomid)const; roomcxn spawn_room(raii::string&& roomid)const; - //other network - void logout(void); - //upload media + //NOTE alias equivalents just give the uploaded file a name other than the filename. + /* + * Upload a file as a raw file. + * Takes filename as argument. + * Returns: file_info struct containing the url of the file on the homeserver. + * Note check the file_info::fileurl field to check if the upload succeeded. + */ file_info upload_file(const raii::string_base& filename)const; file_info upload_file(const raii::string_base& filename, const raii::string_base& alias)const; + + /* + * Upload a file as an image. + * Note: requires FreeImagePlus to treat the file as an image, otherwise will just upload as a raw file. + * Returns: image_info struct containing the url of the image on the homeserver. + * Note check the image_info::fileurl field to check if the upload succeeded. + */ image_info upload_image(const raii::string_base& filename)const; image_info upload_image(const raii::string_base& filename, const raii::string_base& alias)const; + + /* + * Upload a file as a video. + * Note: requires ffmpeg to treat the file as a video, otherwise will just upload as a raw file. + * Returns: video_info struct containing the url of the image on the homeserver. + * Note check the video_info::fileurl field to check if the upload succeeded. + */ video_info upload_video(const raii::string_base& filename)const; video_info upload_video(const raii::string_base& filename, const raii::string_base& alias)const; + /* + * Upload a file as an audio file. + * Note: requires ffmpeg to treat the file as a audio, otherwise will just upload as a raw file. + * Returns: audio_info struct containing the url of the image on the homeserver. + * Note check the audio_info::fileurl field to check if the upload succeeded. + */ audio_info upload_audio(const raii::string_base& filename)const; audio_info upload_audio(const raii::string_base& filename, const raii::string_base& alias)const; diff --git a/include/matrix/connection.hpp b/include/matrix/connection.hpp index ee3311a..1798064 100644 --- a/include/matrix/connection.hpp +++ b/include/matrix/connection.hpp @@ -27,6 +27,7 @@ namespace matrix{ + //Base class of all interactive network classes. class connection { protected: @@ -42,6 +43,9 @@ namespace matrix{ public: ~connection(void) = default; + /* + * Returns: the http status code of the last operation performed. + */ long http_status(void)const; protected: diff --git a/include/matrix/session.hpp b/include/matrix/session.hpp index eeb84e3..7a0b404 100644 --- a/include/matrix/session.hpp +++ b/include/matrix/session.hpp @@ -29,34 +29,107 @@ #include //pair namespace matrix{ + //Manages connection to homeserver and user login. + //Shares states with any spawned clients and syncers. class session : protected connection { private: bool m_valid = false; public: + /* + * Create a session object that does not initialize a connection to a homeserver + * User will need to create a connection manually through the local setter interface, then call login() + */ session(void); + /* + * Create a session object that will attempt to initialize a connection to a homeserver + * using the details in the auth_data structure. If the access token given is invalid, a + * new one will be retrieved. Use valid() to check if the session is successfully created. + */ session(const auth_data&); + //Copy and move constructors session(const session&) = default; session(session&&) = default; + + /* + * NOT thread safe. + * Invalidates the session. All spawned clients and syncers will be invalidated as well. + */ ~session(void); + //Copy and move assignment session& operator=(const session&) = default; session& operator=(session&&) = default; + /* + * NOT thread safe. + * Set the useragent for the session and all spawned clients and syncers. + */ void set_useragent(const raii::string_base&); void set_useragent(raii::string&&); + + /* + * NOT thread safe. + * Set the access token for the session and all spawned clients and syncers. + * Note this will not check if the access token is valid or not, nor will urls be updated. + */ void set_access_token(const raii::string_base&); void set_access_token(raii::string&&); + /* + * NOT thread safe. + * Set the homeserver for the session and all spawned clients and syncers. + * Note this will not check if the homeserver is valid or not, nor will urs be updated. + */ void set_homeserver(const raii::string_base&); void set_homeserver(raii::string&&); + /* + * NOT thread safe. + * Manually log in to a homeserver using the current access token. + * This will regenerate the urls and ensure access token and homeserver are valid. + * Returns: true if success, false otherwise. + */ bool login(void); + /* + * NOT thread safe. + * Manually log in to a homeserver first using the current access token, then trying the + * username and password as a backup. This will regenerate the urls and ensure access token and + * homeserver are valid. + * Returns: true if success, false otherwise. + */ bool login(const raii::string_base& username, const raii::string_base& pass); + + /* + * Logout of the current connection to the homeserver. Will invalidate the access token on the server side. + * Returns: true if the logout was successful, false otherwise. + */ + bool logout(void); + /* + * Returns: true if the session is successfully connected to the homeserver. + */ bool valid(void)const; + /* + * Create a matrix::client which shares login details with this session. + * Note the client and session will share memory for generated urls, homeserver, access_token, and + * useragent. Changing any of these fields after spawning a client MUST be synchronized across threads. + * Returns: a new matrix::client. + */ client spawn_client(void)const; + /* + * Create a matrix::syncer which shares login details with this session. + * Note the syncer and session will share memory for generated urls, homeserver, access_token, and + * useragent. Changing any of these fields after spawning a syncer MUST be synchronized across threads. + * Returns: a new matrix::syncer. + */ syncer spawn_syncer(void)const; + /* + * NOT thread safe. + * Invalidates the session and all spawned clients and syncers. + * All generated urls will be discarded; homeserver, access token, and useragent will be discarded; + * and valid() will return false. + */ void invalidate(void); private: bool _do_login(const raii::string_base& username, const raii::string_base& pass); diff --git a/include/matrix/syncer.hpp b/include/matrix/syncer.hpp index 1f43adb..f21eddb 100644 --- a/include/matrix/syncer.hpp +++ b/include/matrix/syncer.hpp @@ -28,6 +28,10 @@ #include //shared_ptr namespace matrix{ + + //Specialized class used for syncing up with homeserver. + //Designed to be run on a dedicated thread. + //Shares state with spawning session. class syncer : public connection { private: @@ -35,13 +39,21 @@ namespace matrix{ public: syncer(const std::shared_ptr&); + + //Copy and move ctor syncer(const syncer& b) = default; syncer(syncer&& b) = default; + //Dtor ~syncer(void) = default; + //Copy and move assignment syncer& operator=(const syncer&) = default; syncer& operator=(syncer&&) = default; + /* + * Sync state with the homeserver. Will wait for up to timeout ms. + * Returns: the raw json response from the homeserver. + */ raii::string sync(size_t timeout); }; } diff --git a/src/matrix/client.cpp b/src/matrix/client.cpp index 7e691c0..ba362b8 100644 --- a/src/matrix/client.cpp +++ b/src/matrix/client.cpp @@ -50,11 +50,13 @@ namespace matrix{ } //networked setter - void client::set_display_name(const raii::string_base& newname){ - raii::string reply = _put_curl(raii::string("{\"displayname\":\"" + newname + "\"}"), m_ses->urls.displayname(), raii::curl_llist()); + bool client::set_display_name(const raii::string_base& newname){ + _put_curl(raii::string("{\"displayname\":\"" + newname + "\"}"), m_ses->urls.displayname(), raii::curl_llist()); + return http_status() == 200; } - void client::set_profile_picture(const raii::string_base& media_url){ - raii::string reply = _put_curl(raii::string("{\"avatar_url\":\"" + media_url + "\"}"), m_ses->urls.profile_picture(), raii::curl_llist()); + bool client::set_profile_picture(const raii::string_base& media_url){ + _put_curl(raii::string("{\"avatar_url\":\"" + media_url + "\"}"), m_ses->urls.profile_picture(), raii::curl_llist()); + return http_status() == 200; } //networked getter @@ -89,14 +91,14 @@ namespace matrix{ } //room membership - raii::string client::create_room(const raii::string_base& name, const raii::string_base& alias)const{ + raii::rjp_string client::create_room(const raii::string_base& name, const raii::string_base& alias)const{ raii::string postdata; if(alias) postdata = "{\"name\": \"" + raii::json_escape(name) + "\",\"room_alias_name\": \"" + raii::json_escape(alias) + "\"}"; else postdata = "{\"name\": \"" + raii::json_escape(name) + "\"}"; - return _post_curl(postdata, m_ses->urls.create_room(), raii::curl_llist()); + return _post_and_find(postdata, m_ses->urls.create_room(), raii::curl_llist(), "room_id"_ss); } roomcxn client::spawn_room(const raii::string_base& roomid)const{ return roomcxn(m_ses, roomid); @@ -105,12 +107,6 @@ namespace matrix{ return roomcxn(m_ses, std::move(roomid)); } - //other network - void client::logout(void){ - _get_curl(m_ses->urls.logout(m_ses->homeserver, m_ses->access_token)); - } - - //upload media file_info client::upload_file(const raii::string_base& filename)const{ return upload_file(filename, raii::static_string()); diff --git a/src/matrix/session.cpp b/src/matrix/session.cpp index 5d4d7d1..5aaecde 100644 --- a/src/matrix/session.cpp +++ b/src/matrix/session.cpp @@ -20,6 +20,7 @@ #include "raii/rjp_ptr.hpp" #include "raii/curler.hpp" #include "raii/util.hpp" +#include "raii/static_string.hpp" namespace matrix{ @@ -60,6 +61,10 @@ namespace matrix{ bool session::login(const raii::string_base& username, const raii::string_base& pass){ return _do_login(username, pass); } + bool session::logout(void){ + _post_curl(""_ss, m_ses->urls.logout(m_ses->homeserver, m_ses->access_token), raii::curl_llist()); + return http_status() == 200; + } bool session::valid(void)const{ return m_valid; @@ -71,6 +76,7 @@ namespace matrix{ return syncer(m_ses); } void session::invalidate(void){ + m_valid = false; m_ses->useragent.reset(); m_ses->homeserver.reset(); m_ses->access_token.reset();