diff --git a/CMakeLists.txt b/CMakeLists.txt index 2ebf1b039849189c1e8816ba2c62554b18d8bebe..0109464c6406fc0e45163a81228f3eca0013978c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,39 +1,43 @@ -cmake_minimum_required(VERSION 3.12) +cmake_minimum_required(VERSION 3.13) set( - CMAKE_TOOLCHAIN_FILE - "${CMAKE_CURRENT_LIST_DIR}/toolchain.cmake" - CACHE - FILEPATH - "Default toolchain" -) + CMAKE_TOOLCHAIN_FILE + "${CMAKE_CURRENT_LIST_DIR}/toolchain.cmake" + CACHE + FILEPATH + "Default toolchain" + ) option(HUNTER_ENABLED "Enable Hunter package manager" OFF) include("cmake/HunterGate.cmake") HunterGate( - URL "https://github.com/cpp-pm/hunter/archive/v0.23.244.tar.gz" - SHA1 "2c0f491fd0b80f7b09e3d21adb97237161ef9835" - LOCAL -) + URL "https://github.com/cpp-pm/hunter/archive/v0.23.244.tar.gz" + SHA1 "2c0f491fd0b80f7b09e3d21adb97237161ef9835" + LOCAL + ) option(USE_BUNDLED_BOOST "Use the bundled version of Boost." ${HUNTER_ENABLED}) option(USE_BUNDLED_SPDLOG "Use the bundled version of spdlog." - ${HUNTER_ENABLED}) + ${HUNTER_ENABLED}) option(USE_BUNDLED_OLM "Use the bundled version of libolm." ${HUNTER_ENABLED}) option(USE_BUNDLED_GTEST "Use the bundled version of Google Test." - ${HUNTER_ENABLED}) + ${HUNTER_ENABLED}) option(USE_BUNDLED_JSON "Use the bundled version of nlohmann json." - ${HUNTER_ENABLED}) + ${HUNTER_ENABLED}) option(USE_BUNDLED_OPENSSL "Use the bundled version of OpenSSL." - ${HUNTER_ENABLED}) + ${HUNTER_ENABLED}) option(USE_BUNDLED_SODIUM "Use the bundled version of libsodium." - ${HUNTER_ENABLED}) + ${HUNTER_ENABLED}) option(USE_BUNDLED_ZLIB "Use the bundled version of zlib." - ${HUNTER_ENABLED}) + ${HUNTER_ENABLED}) -project(matrix_client VERSION 0.3.0 LANGUAGES CXX C) +project(matrix_client + VERSION 0.3.0 + DESCRIPTION "Client API library for Matrix, built on top of Boost.Asio" + HOMEPAGE_URL https://github.com/Nheko-Reborn/mtxclient + LANGUAGES CXX C) option(ASAN "Compile with address sanitizers" OFF) option(BUILD_LIB_TESTS "Build tests" ON) @@ -42,56 +46,56 @@ option(COVERAGE "Calculate test coverage" OFF) option(IWYU "Check headers with include-what-you-use" OFF) option(BUILD_SHARED_LIBS "Specifies whether to build mtxclient as a shared library lib or not" ON) -set(CMAKE_MODULE_PATH "${CMAKE_MODULE_PATH};${CMAKE_CURRENT_SOURCE_DIR}/cmake") +list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake") if(NOT MSVC) - set( - CMAKE_CXX_FLAGS - "${CMAKE_CXX_FLAGS} \ - -Wall \ - -Wextra \ - -pipe \ - -pedantic \ - -fsized-deallocation \ - -fdiagnostics-color=always \ - -Wunreachable-code" - ) + set( + CMAKE_CXX_FLAGS + "${CMAKE_CXX_FLAGS} \ + -Wall \ + -Wextra \ + -pipe \ + -pedantic \ + -fsized-deallocation \ + -fdiagnostics-color=always \ + -Wunreachable-code" + ) endif() if(MSVC) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /bigobj -bigobj") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /bigobj -bigobj") endif() if(ASAN) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address,undefined") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address,undefined") endif() if(NOT MSVC AND NOT APPLE) - set(THREADS_PREFER_PTHREAD_FLAG ON) - find_package(Threads REQUIRED) + set(THREADS_PREFER_PTHREAD_FLAG ON) + find_package(Threads REQUIRED) endif() include(FeatureSummary) if(USE_BUNDLED_OPENSSL) - hunter_add_package(OpenSSL) + hunter_add_package(OpenSSL) endif() find_package(OpenSSL REQUIRED) set_package_properties(OpenSSL PROPERTIES - DESCRIPTION "Open source SSL and TLS implementation and cryptographic library" - URL "https://www.openssl.org/" - TYPE REQUIRED -) + DESCRIPTION "Open source SSL and TLS implementation and cryptographic library" + URL "https://www.openssl.org/" + TYPE REQUIRED + ) if(USE_BUNDLED_ZLIB) - hunter_add_package(ZLIB) + hunter_add_package(ZLIB) endif() find_package(ZLIB) set_package_properties(ZLIB PROPERTIES - DESCRIPTION "A free compression library unencumbered by patents" - URL "https://www.zlib.net/" - TYPE REQUIRED -) + DESCRIPTION "A free compression library unencumbered by patents" + URL "https://www.zlib.net/" + TYPE REQUIRED + ) if(USE_BUNDLED_OLM) include(FetchContent) @@ -111,7 +115,7 @@ else() endif() if(USE_BUNDLED_SODIUM) - hunter_add_package(libsodium) + hunter_add_package(libsodium) find_package(libsodium 1.0.14 REQUIRED) else() find_package(sodium 1.0.14 REQUIRED) @@ -123,75 +127,78 @@ else() endif() if(USE_BUNDLED_JSON) - hunter_add_package(nlohmann_json) + hunter_add_package(nlohmann_json) endif() find_package(nlohmann_json 3.2.0) set_package_properties(nlohmann_json PROPERTIES - DESCRIPTION "JSON for Modern C++, a C++11 header-only JSON class" - URL "https://nlohmann.github.io/json/" - TYPE REQUIRED -) + DESCRIPTION "JSON for Modern C++, a C++11 header-only JSON class" + URL "https://nlohmann.github.io/json/" + TYPE REQUIRED + ) if(USE_BUNDLED_BOOST) - hunter_add_package(Boost COMPONENTS iostreams system thread) + hunter_add_package(Boost COMPONENTS iostreams system thread) endif() -find_package(Boost 1.70 COMPONENTS iostreams system thread) +find_package(Boost 1.70 COMPONENTS REQUIRED iostreams system thread) set_package_properties(Boost PROPERTIES -DESCRIPTION "Free peer-reviewed portable C++ source libraries" -URL "https://www.boost.org/" -TYPE REQUIRED -) - -add_library(matrix_client - lib/http/client.cpp - lib/http/session.cpp - lib/crypto/client.cpp - lib/crypto/utils.cpp - lib/utils.cpp - lib/log.cpp - lib/structs/common.cpp - lib/structs/errors.cpp - lib/structs/events.cpp - lib/structs/requests.cpp - lib/structs/events/aliases.cpp - lib/structs/events/avatar.cpp - lib/structs/events/canonical_alias.cpp - lib/structs/events/common.cpp - lib/structs/events/collections.cpp - lib/structs/events/create.cpp - lib/structs/events/encrypted.cpp - lib/structs/events/encryption.cpp - lib/structs/events/guest_access.cpp - lib/structs/events/history_visibility.cpp - lib/structs/events/join_rules.cpp - lib/structs/events/member.cpp - lib/structs/events/name.cpp - lib/structs/events/pinned_events.cpp - lib/structs/events/power_levels.cpp - lib/structs/events/redaction.cpp - lib/structs/events/tag.cpp - lib/structs/events/tombstone.cpp - lib/structs/events/topic.cpp - lib/structs/events/messages/audio.cpp - lib/structs/events/messages/emote.cpp - lib/structs/events/messages/file.cpp - lib/structs/events/messages/image.cpp - lib/structs/events/messages/notice.cpp - lib/structs/events/messages/text.cpp - lib/structs/events/messages/video.cpp - lib/structs/responses/common.cpp - lib/structs/responses/create_room.cpp - lib/structs/responses/crypto.cpp - lib/structs/responses/empty.cpp - lib/structs/responses/login.cpp - lib/structs/responses/media.cpp - lib/structs/responses/messages.cpp - lib/structs/responses/notifications.cpp - lib/structs/responses/profile.cpp - lib/structs/responses/register.cpp - lib/structs/responses/sync.cpp - lib/structs/responses/version.cpp - lib/structs/responses/well-known.cpp) + DESCRIPTION "Free peer-reviewed portable C++ source libraries" + URL "https://www.boost.org/" + TYPE REQUIRED + ) + +add_library(matrix_client) + +target_sources(matrix_client + PRIVATE + lib/http/client.cpp + lib/http/session.cpp + lib/crypto/client.cpp + lib/crypto/utils.cpp + lib/utils.cpp + lib/log.cpp + lib/structs/common.cpp + lib/structs/errors.cpp + lib/structs/events.cpp + lib/structs/requests.cpp + lib/structs/events/aliases.cpp + lib/structs/events/avatar.cpp + lib/structs/events/canonical_alias.cpp + lib/structs/events/common.cpp + lib/structs/events/collections.cpp + lib/structs/events/create.cpp + lib/structs/events/encrypted.cpp + lib/structs/events/encryption.cpp + lib/structs/events/guest_access.cpp + lib/structs/events/history_visibility.cpp + lib/structs/events/join_rules.cpp + lib/structs/events/member.cpp + lib/structs/events/name.cpp + lib/structs/events/pinned_events.cpp + lib/structs/events/power_levels.cpp + lib/structs/events/redaction.cpp + lib/structs/events/tag.cpp + lib/structs/events/tombstone.cpp + lib/structs/events/topic.cpp + lib/structs/events/messages/audio.cpp + lib/structs/events/messages/emote.cpp + lib/structs/events/messages/file.cpp + lib/structs/events/messages/image.cpp + lib/structs/events/messages/notice.cpp + lib/structs/events/messages/text.cpp + lib/structs/events/messages/video.cpp + lib/structs/responses/common.cpp + lib/structs/responses/create_room.cpp + lib/structs/responses/crypto.cpp + lib/structs/responses/empty.cpp + lib/structs/responses/login.cpp + lib/structs/responses/media.cpp + lib/structs/responses/messages.cpp + lib/structs/responses/notifications.cpp + lib/structs/responses/profile.cpp + lib/structs/responses/register.cpp + lib/structs/responses/sync.cpp + lib/structs/responses/version.cpp + lib/structs/responses/well-known.cpp) add_library(MatrixClient::MatrixClient ALIAS matrix_client) target_include_directories( matrix_client @@ -224,35 +231,35 @@ else() endif() if(NOT MSVC AND NOT APPLE) - target_link_libraries(matrix_client PUBLIC Threads::Threads) + target_link_libraries(matrix_client PUBLIC Threads::Threads) endif() if(COVERAGE) - include(CodeCoverage) - add_custom_target(ctest COMMAND ${CMAKE_CTEST_COMMAND}) - target_compile_options(matrix_client PUBLIC - -O0 # no optimization - -g # generate debug info - --coverage # sets all required flags - -fprofile-arcs -ftest-coverage # just to be sure, for clang! - ) - target_link_options(matrix_client PUBLIC --coverage) - setup_target_for_coverage(test_coverage ctest coverage) + include(CodeCoverage) + add_custom_target(ctest COMMAND ${CMAKE_CTEST_COMMAND}) + target_compile_options(matrix_client PUBLIC + -O0 # no optimization + -g # generate debug info + --coverage # sets all required flags + -fprofile-arcs -ftest-coverage # just to be sure, for clang! + ) + target_link_options(matrix_client PUBLIC --coverage) + setup_target_for_coverage(test_coverage ctest coverage) endif() if(IWYU) - find_program(iwyu_path NAMES include-what-you-use iwyu) - if(iwyu_path) - set_property(TARGET matrix_client - PROPERTY CXX_INCLUDE_WHAT_YOU_USE ${iwyu_path}) - else() - message(WARNING "Could not find the program include-what-you-use") - endif() + find_program(iwyu_path NAMES include-what-you-use iwyu) + if(iwyu_path) + set_property(TARGET matrix_client + PROPERTY CXX_INCLUDE_WHAT_YOU_USE ${iwyu_path}) + else() + message(WARNING "Could not find the program include-what-you-use") + endif() endif() if(BUILD_LIB_EXAMPLES) - add_subdirectory(examples) + add_subdirectory(examples) endif() feature_summary(WHAT ALL INCLUDE_QUIET_PACKAGES FATAL_ON_MISSING_REQUIRED_PACKAGES) @@ -264,150 +271,150 @@ include(GNUInstallDirs) set(INSTALL_CONFIGDIR ${CMAKE_INSTALL_LIBDIR}/cmake/MatrixClient) install(TARGETS matrix_client - EXPORT matrix_client-targets - LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} - ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}) + EXPORT matrix_client-targets + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}) set_target_properties(matrix_client PROPERTIES EXPORT_NAME MatrixClient) install(DIRECTORY include/ DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) install(EXPORT matrix_client-targets - FILE - MatrixClientTargets.cmake - NAMESPACE - MatrixClient:: - DESTINATION - ${INSTALL_CONFIGDIR}) + FILE + MatrixClientTargets.cmake + NAMESPACE + MatrixClient:: + DESTINATION + ${INSTALL_CONFIGDIR}) include(CMakePackageConfigHelpers) write_basic_package_version_file( - ${CMAKE_CURRENT_BINARY_DIR}/MatrixClientConfigVersion.cmake - VERSION - ${PROJECT_VERSION} - COMPATIBILITY - AnyNewerVersion) + ${CMAKE_CURRENT_BINARY_DIR}/MatrixClientConfigVersion.cmake + VERSION + ${PROJECT_VERSION} + COMPATIBILITY + AnyNewerVersion) configure_package_config_file( - ${CMAKE_CURRENT_LIST_DIR}/cmake/MatrixClientConfig.cmake.in - ${CMAKE_CURRENT_BINARY_DIR}/MatrixClientConfig.cmake - INSTALL_DESTINATION - ${INSTALL_CONFIGDIR}) + ${CMAKE_CURRENT_LIST_DIR}/cmake/MatrixClientConfig.cmake.in + ${CMAKE_CURRENT_BINARY_DIR}/MatrixClientConfig.cmake + INSTALL_DESTINATION + ${INSTALL_CONFIGDIR}) install(FILES ${CMAKE_CURRENT_BINARY_DIR}/MatrixClientConfig.cmake - ${CMAKE_CURRENT_BINARY_DIR}/MatrixClientConfigVersion.cmake - DESTINATION - ${INSTALL_CONFIGDIR}) + ${CMAKE_CURRENT_BINARY_DIR}/MatrixClientConfigVersion.cmake + DESTINATION + ${INSTALL_CONFIGDIR}) export(EXPORT - matrix_client-targets - FILE - ${CMAKE_CURRENT_BINARY_DIR}/MatrixClientTargets.cmake - NAMESPACE - MatrixClient::) + matrix_client-targets + FILE + ${CMAKE_CURRENT_BINARY_DIR}/MatrixClientTargets.cmake + NAMESPACE + MatrixClient::) export(PACKAGE MatrixClient) set_property(TARGET matrix_client PROPERTY SOVERSION ${PROJECT_VERSION}) if(BUILD_LIB_TESTS) - enable_testing() - - if(USE_BUNDLED_GTEST) - hunter_add_package(GTest) - endif() - find_package(GTest REQUIRED) - - file(COPY tests/fixtures DESTINATION ${CMAKE_CURRENT_BINARY_DIR}) - - add_executable(client_api tests/client_api.cpp) - target_link_libraries(client_api - MatrixClient::MatrixClient - GTest::GTest - GTest::Main) - target_include_directories(client_api PRIVATE - ${CMAKE_CURRENT_SOURCE_DIR}/tests) - - add_executable(media_api tests/media_api.cpp) - target_link_libraries(media_api - MatrixClient::MatrixClient - GTest::GTest - GTest::Main) - target_include_directories(media_api PRIVATE - ${CMAKE_CURRENT_SOURCE_DIR}/tests) - - add_executable(e2ee tests/e2ee.cpp) - target_link_libraries(e2ee - MatrixClient::MatrixClient - GTest::GTest - GTest::Main) - target_include_directories(e2ee PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/tests) - - add_executable(utils tests/utils.cpp) - target_link_libraries(utils - MatrixClient::MatrixClient - GTest::GTest - GTest::Main) - target_include_directories(utils PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/tests) - - add_executable(connection tests/connection.cpp) - target_link_libraries(connection - MatrixClient::MatrixClient - GTest::GTest - GTest::Main) - target_include_directories(connection PRIVATE - ${CMAKE_CURRENT_SOURCE_DIR}/tests) - - add_executable(identifiers tests/identifiers.cpp) - target_link_libraries(identifiers - MatrixClient::MatrixClient - GTest::GTest - GTest::Main) - - add_executable(events tests/events.cpp) - target_link_libraries(events - MatrixClient::MatrixClient - GTest::GTest - GTest::Main) - - add_executable(messages tests/messages.cpp) - target_link_libraries(messages - MatrixClient::MatrixClient - GTest::GTest - GTest::Main) - - add_executable(responses tests/responses.cpp) - target_link_libraries(responses - MatrixClient::MatrixClient - GTest::GTest - GTest::Main) - - add_executable(requests tests/requests.cpp) - target_link_libraries(requests - MatrixClient::MatrixClient - GTest::GTest - GTest::Main) - - add_executable(errors tests/errors.cpp) - target_link_libraries(errors - MatrixClient::MatrixClient - GTest::GTest - GTest::Main) - - add_executable(crypto tests/crypto.cpp) - target_link_libraries(crypto - MatrixClient::MatrixClient - GTest::GTest - GTest::Main) - - add_test(BasicConnectivity connection) - add_test(ClientAPI client_api) - add_test(MediaAPI media_api) - add_test(Encryption e2ee) - add_test(Utilities utils) - add_test(Identifiers identifiers) - add_test(Errors errors) - add_test(CryptoStructs crypto) - add_test(StateEvents events) - add_test(RoomEvents messages) - add_test(Responses responses) - add_test(Requests requests) + enable_testing() + + if(USE_BUNDLED_GTEST) + hunter_add_package(GTest) + endif() + find_package(GTest REQUIRED) + + file(COPY tests/fixtures DESTINATION ${CMAKE_CURRENT_BINARY_DIR}) + + add_executable(client_api tests/client_api.cpp) + target_link_libraries(client_api + MatrixClient::MatrixClient + GTest::GTest + GTest::Main) + target_include_directories(client_api PRIVATE + ${CMAKE_CURRENT_SOURCE_DIR}/tests) + + add_executable(media_api tests/media_api.cpp) + target_link_libraries(media_api + MatrixClient::MatrixClient + GTest::GTest + GTest::Main) + target_include_directories(media_api PRIVATE + ${CMAKE_CURRENT_SOURCE_DIR}/tests) + + add_executable(e2ee tests/e2ee.cpp) + target_link_libraries(e2ee + MatrixClient::MatrixClient + GTest::GTest + GTest::Main) + target_include_directories(e2ee PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/tests) + + add_executable(utils tests/utils.cpp) + target_link_libraries(utils + MatrixClient::MatrixClient + GTest::GTest + GTest::Main) + target_include_directories(utils PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/tests) + + add_executable(connection tests/connection.cpp) + target_link_libraries(connection + MatrixClient::MatrixClient + GTest::GTest + GTest::Main) + target_include_directories(connection PRIVATE + ${CMAKE_CURRENT_SOURCE_DIR}/tests) + + add_executable(identifiers tests/identifiers.cpp) + target_link_libraries(identifiers + MatrixClient::MatrixClient + GTest::GTest + GTest::Main) + + add_executable(events tests/events.cpp) + target_link_libraries(events + MatrixClient::MatrixClient + GTest::GTest + GTest::Main) + + add_executable(messages tests/messages.cpp) + target_link_libraries(messages + MatrixClient::MatrixClient + GTest::GTest + GTest::Main) + + add_executable(responses tests/responses.cpp) + target_link_libraries(responses + MatrixClient::MatrixClient + GTest::GTest + GTest::Main) + + add_executable(requests tests/requests.cpp) + target_link_libraries(requests + MatrixClient::MatrixClient + GTest::GTest + GTest::Main) + + add_executable(errors tests/errors.cpp) + target_link_libraries(errors + MatrixClient::MatrixClient + GTest::GTest + GTest::Main) + + add_executable(crypto tests/crypto.cpp) + target_link_libraries(crypto + MatrixClient::MatrixClient + GTest::GTest + GTest::Main) + + add_test(BasicConnectivity connection) + add_test(ClientAPI client_api) + add_test(MediaAPI media_api) + add_test(Encryption e2ee) + add_test(Utilities utils) + add_test(Identifiers identifiers) + add_test(Errors errors) + add_test(CryptoStructs crypto) + add_test(StateEvents events) + add_test(RoomEvents messages) + add_test(Responses responses) + add_test(Requests requests) endif() diff --git a/include/mtx/events/member.hpp b/include/mtx/events/member.hpp index 3815f1d5979c64138c4f9eb1283bcbbd36adb39b..78e95816cf22a80e7153031c1db0db7823c27d36 100644 --- a/include/mtx/events/member.hpp +++ b/include/mtx/events/member.hpp @@ -42,6 +42,9 @@ struct Member //! with the intention of being a direct chat. bool is_direct = false; + //! reason for the membership change, empty in most cases + std::string reason; + /* ThirdPartyInvite third_party_invite; */ }; diff --git a/include/mtx/requests.hpp b/include/mtx/requests.hpp index 86d8d94560a3b361657c4319c12b0050f8e8eabc..8836497a1e014b25f762e60001d0d764d3cddef6 100644 --- a/include/mtx/requests.hpp +++ b/include/mtx/requests.hpp @@ -102,14 +102,18 @@ struct DisplayName void to_json(json &obj, const DisplayName &request); -//! Request payload for the `POST /_matrix/client/r0/rooms/{roomId}/invite` endpoint. -struct RoomInvite +//! Request payload for the `POST /_matrix/client/r0/rooms/{roomId}/invite` endpoint as well as ban, +//! unban and kick. +struct RoomMembershipChange { std::string user_id; + + //! optional kick, invite or ban reason + std::string reason; }; void -to_json(json &obj, const RoomInvite &request); +to_json(json &obj, const RoomMembershipChange &request); //! Request payload for the `PUT /_matrix/client/r0/rooms/{roomId}/typing/{userId}` endpoint. struct TypingNotification diff --git a/include/mtxclient/crypto/client.hpp b/include/mtxclient/crypto/client.hpp index cb626241a49615485a9c069e97e5df29525a0543..b79d92e6e7a1baedf3115c69269dfadff87954b2 100644 --- a/include/mtxclient/crypto/client.hpp +++ b/include/mtxclient/crypto/client.hpp @@ -5,7 +5,6 @@ #include <new> #include <nlohmann/json.hpp> -#include <sodium.h> #include <mtx/identifiers.hpp> #include <mtx/requests.hpp> diff --git a/include/mtxclient/http/client.hpp b/include/mtxclient/http/client.hpp index 16a9c59e266a861939da648f6cbf232d0dc65b6a..c095654c2860cffae130bf4b93aec6ac04f26b7e 100644 --- a/include/mtxclient/http/client.hpp +++ b/include/mtxclient/http/client.hpp @@ -192,7 +192,23 @@ public: //! Invite a user to a room. void invite_user(const std::string &room_id, const std::string &user_id, - Callback<mtx::responses::RoomInvite> cb); + Callback<mtx::responses::RoomInvite> cb, + const std::string &reason = ""); + //! Kick a user from a room. + void kick_user(const std::string &room_id, + const std::string &user_id, + Callback<mtx::responses::Empty> cb, + const std::string &reason = ""); + //! Ban a user from a room. + void ban_user(const std::string &room_id, + const std::string &user_id, + Callback<mtx::responses::Empty> cb, + const std::string &reason = ""); + //! Unban a user from a room. + void unban_user(const std::string &room_id, + const std::string &user_id, + Callback<mtx::responses::Empty> cb, + const std::string &reason = ""); //! Perform sync. void sync(const SyncOpts &opts, Callback<mtx::responses::Sync> cb); diff --git a/lib/http/client.cpp b/lib/http/client.cpp index eb0ccb2c40c632132b93d0d8708d0aa67a4f4cf8..c8d4322f0188a78bc218ab8ffa1d5df314606af0 100644 --- a/lib/http/client.cpp +++ b/lib/http/client.cpp @@ -374,14 +374,62 @@ Client::leave_room(const std::string &room_id, Callback<nlohmann::json> callback void Client::invite_user(const std::string &room_id, const std::string &user_id, - Callback<mtx::responses::RoomInvite> callback) + Callback<mtx::responses::RoomInvite> callback, + const std::string &reason) { - mtx::requests::RoomInvite req; + mtx::requests::RoomMembershipChange req; req.user_id = user_id; + req.reason = reason; auto api_path = "/client/r0/rooms/" + room_id + "/invite"; - post<mtx::requests::RoomInvite, mtx::responses::RoomInvite>(api_path, req, callback); + post<mtx::requests::RoomMembershipChange, mtx::responses::RoomInvite>( + api_path, req, callback); +} + +void +Client::kick_user(const std::string &room_id, + const std::string &user_id, + Callback<mtx::responses::Empty> callback, + const std::string &reason) +{ + mtx::requests::RoomMembershipChange req; + req.user_id = user_id; + req.reason = reason; + + auto api_path = "/client/r0/rooms/" + room_id + "/kick"; + + post<mtx::requests::RoomMembershipChange, mtx::responses::Empty>(api_path, req, callback); +} + +void +Client::ban_user(const std::string &room_id, + const std::string &user_id, + Callback<mtx::responses::Empty> callback, + const std::string &reason) +{ + mtx::requests::RoomMembershipChange req; + req.user_id = user_id; + req.reason = reason; + + auto api_path = "/client/r0/rooms/" + room_id + "/ban"; + + post<mtx::requests::RoomMembershipChange, mtx::responses::Empty>(api_path, req, callback); +} + +void +Client::unban_user(const std::string &room_id, + const std::string &user_id, + Callback<mtx::responses::Empty> callback, + const std::string &reason) +{ + mtx::requests::RoomMembershipChange req; + req.user_id = user_id; + req.reason = reason; + + auto api_path = "/client/r0/rooms/" + room_id + "/unban"; + + post<mtx::requests::RoomMembershipChange, mtx::responses::Empty>(api_path, req, callback); } void diff --git a/lib/structs/events/member.cpp b/lib/structs/events/member.cpp index 4115b6d087e08a1e8a6300e4cc9c14ce4cfa8603..788c407f3f5f1551a9ff5c9e85eb6a5bfb1b5c76 100644 --- a/lib/structs/events/member.cpp +++ b/lib/structs/events/member.cpp @@ -56,6 +56,9 @@ from_json(const json &obj, Member &member) if (obj.find("is_direct") != obj.end()) member.is_direct = obj.at("is_direct").get<bool>(); + + if (obj.find("reason") != obj.end()) + member.reason = obj.at("reason").get<std::string>(); } void @@ -65,6 +68,7 @@ to_json(json &obj, const Member &member) obj["avatar_url"] = member.avatar_url; obj["displayname"] = member.display_name; obj["is_direct"] = member.is_direct; + obj["reason"] = member.reason; } } // namespace state diff --git a/lib/structs/requests.cpp b/lib/structs/requests.cpp index d3ea07af101e6f6bd43d3d3f0f8310daa264c15d..0ce5c75c0e0570f0662c850b48b3a6372a01a118 100644 --- a/lib/structs/requests.cpp +++ b/lib/structs/requests.cpp @@ -91,9 +91,12 @@ to_json(json &obj, const DisplayName &request) } void -to_json(json &obj, const RoomInvite &request) +to_json(json &obj, const RoomMembershipChange &request) { obj["user_id"] = request.user_id; + + if (!request.reason.empty()) + obj["reason"] = request.reason; } void diff --git a/tests/client_api.cpp b/tests/client_api.cpp index fddcb1d9b113922cf1b9b5b4273a4890f39daf4f..705efbbb40ff240368948a604bfb0507a57200d4 100644 --- a/tests/client_api.cpp +++ b/tests/client_api.cpp @@ -518,6 +518,110 @@ TEST(ClientAPI, InviteRoom) bob->close(); } +TEST(ClientAPI, KickRoom) +{ + auto alice = std::make_shared<Client>("localhost"); + auto bob = std::make_shared<Client>("localhost"); + + alice->login("alice", "secret", [alice](const mtx::responses::Login &, RequestErr err) { + check_error(err); + }); + + bob->login("bob", "secret", [bob](const mtx::responses::Login &, RequestErr err) { + check_error(err); + }); + + while (alice->access_token().empty() || bob->access_token().empty()) + sleep(); + + mtx::requests::CreateRoom req; + req.name = "Name"; + req.topic = "Topic"; + req.invite = {}; + alice->create_room( + req, [alice, bob](const mtx::responses::CreateRoom &res, RequestErr err) { + check_error(err); + auto room_id = res.room_id.to_string(); + + alice->invite_user( + room_id, + "@bob:localhost", + [room_id, alice, bob](const mtx::responses::Empty &, RequestErr err) { + check_error(err); + + bob->join_room( + room_id, [alice, room_id](const nlohmann::json &, RequestErr err) { + check_error(err); + + alice->kick_user(room_id, + "@bob:localhost", + [](const mtx::responses::Empty &, + RequestErr err) { check_error(err); }); + }); + }); + }); + + alice->close(); + bob->close(); +} + +TEST(ClientAPI, BanRoom) +{ + auto alice = std::make_shared<Client>("localhost"); + auto bob = std::make_shared<Client>("localhost"); + + alice->login("alice", "secret", [alice](const mtx::responses::Login &, RequestErr err) { + check_error(err); + }); + + bob->login("bob", "secret", [bob](const mtx::responses::Login &, RequestErr err) { + check_error(err); + }); + + while (alice->access_token().empty() || bob->access_token().empty()) + sleep(); + + mtx::requests::CreateRoom req; + req.name = "Name"; + req.topic = "Topic"; + req.invite = {}; + alice->create_room( + req, [alice, bob](const mtx::responses::CreateRoom &res, RequestErr err) { + check_error(err); + auto room_id = res.room_id.to_string(); + + alice->invite_user( + room_id, + "@bob:localhost", + [room_id, alice, bob](const mtx::responses::Empty &, RequestErr err) { + check_error(err); + + bob->join_room( + room_id, [alice, room_id](const nlohmann::json &, RequestErr err) { + check_error(err); + + alice->ban_user( + room_id, + "@bob:localhost", + [alice, room_id](const mtx::responses::Empty &, + RequestErr err) { + check_error(err); + alice->unban_user( + room_id, + "@bob:localhost", + [](const mtx::responses::Empty &, + RequestErr err) { check_error(err); }, + "You not bad anymore!"); + }, + "You bad!"); + }); + }); + }); + + alice->close(); + bob->close(); +} + TEST(ClientAPI, InvalidInvite) { auto alice = std::make_shared<Client>("localhost");