From 0df442e04c57dd80fc9a6b885b2ba86442b405b9 Mon Sep 17 00:00:00 2001 From: dec05eba Date: Thu, 12 Nov 2020 02:35:19 +0100 Subject: Matrix: workaround synapse bug where sync doesn't include membership states when using messages filter --- src/plugins/Matrix.cpp | 85 +++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 67 insertions(+), 18 deletions(-) (limited to 'src/plugins/Matrix.cpp') diff --git a/src/plugins/Matrix.cpp b/src/plugins/Matrix.cpp index ce003a0..a48bcdd 100644 --- a/src/plugins/Matrix.cpp +++ b/src/plugins/Matrix.cpp @@ -99,16 +99,21 @@ namespace QuickMedia { } UserInfo::UserInfo(RoomData *room, std::string user_id) : - room(room), display_name_color(user_id_to_color(user_id)), user_id(user_id) + room(room), display_name_color(user_id_to_color(user_id)), user_id(user_id), resolve_state(UserResolveState::NOT_RESOLVED) { display_name = std::move(user_id); } UserInfo::UserInfo(RoomData *room, std::string user_id, std::string display_name, std::string avatar_url) : - room(room), display_name_color(user_id_to_color(user_id)), user_id(std::move(user_id)), display_name(std::move(display_name)), avatar_url(std::move(avatar_url)) { + room(room), display_name_color(user_id_to_color(user_id)), user_id(std::move(user_id)), resolve_state(UserResolveState::RESOLVED), display_name(std::move(display_name)), avatar_url(std::move(avatar_url)) { } + // TODO: Remove this when images are embedded inside the text instead of using the same space as the author + bool is_visual_media_message_type(MessageType message_type) { + return message_type == MessageType::VIDEO || message_type == MessageType::IMAGE; + } + std::shared_ptr RoomData::get_user_by_id(const std::string &user_id) { std::lock_guard lock(room_mutex); auto user_it = user_info_by_user_id.find(user_id); @@ -147,11 +152,13 @@ namespace QuickMedia { user->display_name = std::move(display_name); if(user->display_name.empty()) user->display_name = user->user_id; + user->resolve_state = UserResolveState::RESOLVED; } void RoomData::set_user_avatar_url(std::shared_ptr &user, std::string avatar_url) { std::lock_guard lock(user_mutex); user->avatar_url = std::move(avatar_url); + user->resolve_state = UserResolveState::RESOLVED; } void RoomData::prepend_messages_reverse(const std::vector> &new_messages) { @@ -1477,7 +1484,7 @@ namespace QuickMedia { std::string avatar_url_str; const rapidjson::Value &avatar_url_json = GetMember(json, "avatar_url"); if(avatar_url_json.IsString()) - avatar_url_str = avatar_url_json.GetString(); + avatar_url_str = std::string(avatar_url_json.GetString(), avatar_url_json.GetStringLength()); const rapidjson::Value &display_name_json = GetMember(json, "displayname"); @@ -1485,9 +1492,12 @@ namespace QuickMedia { std::string avatar_url = thumbnail_url_extract_media_id(avatar_url_str); if(!avatar_url.empty()) avatar_url = homeserver + "/_matrix/media/r0/thumbnail/" + avatar_url + "?width=32&height=32&method=crop"; // TODO: Remove the constant strings around to reduce memory usage (6.3mb) - auto user_info = std::make_shared(room_data, user_id, std::move(display_name), std::move(avatar_url)); + //auto user_info = std::make_shared(room_data, user_id, std::move(display_name), std::move(avatar_url)); // Overwrites user data - room_data->add_user(user_info); + //room_data->add_user(user_info); + auto user_info = get_user_by_id(room_data, user_id); + room_data->set_user_display_name(user_info, std::move(display_name)); + room_data->set_user_avatar_url(user_info, std::move(avatar_url)); return user_info; } @@ -3289,9 +3299,14 @@ namespace QuickMedia { auto user = room->get_user_by_id(user_id); if(user) return user; - #if 0 - // TODO: Instead of guessing notification limit with 100, accumulate rooms unread_notifications count and use that as the limit - // (and take into account that notification response may have notifications after call to sync above). + + //fprintf(stderr, "Unknown user: %s, creating locally... synapse bug?\n", user_id.c_str()); + auto user_info = std::make_shared(room, user_id); + room->add_user(user_info); + return user_info; + } + + void Matrix::update_user_with_latest_state(RoomData *room, const std::string &user_id) { char url[512]; snprintf(url, sizeof(url), "%s/_matrix/client/r0/profile/%s", homeserver.c_str(), user_id.c_str()); @@ -3299,18 +3314,52 @@ namespace QuickMedia { DownloadResult download_result = download_json(json_root, url, {}, true); if(download_result != DownloadResult::OK || !json_root.IsObject()) { fprintf(stderr, "Fetching profile for user %s failed!\n", user_id.c_str()); - return nullptr; + auto user = get_user_by_id(room, user_id); + assert(user); + user->resolve_state = UserResolveState::RESOLVED; + return; } - // Is this a synapse bug? sometimes lazy_fetch_members doesn't contain all related clients - fprintf(stderr, "User was not available locally, fetched from server...\n"); - return parse_user_info(json_root, user_id, room); - #else - fprintf(stderr, "Unknown user: %s, creating locally... synapse bug?\n", user_id.c_str()); - auto user_info = std::make_shared(room, user_id); - room->add_user(user_info); - return user_info; - #endif + parse_user_info(json_root, user_id, room); + } + + void Matrix::update_room_users(RoomData *room) { + std::vector additional_args = { + { "-H", "Authorization: Bearer " + access_token } + }; + + char url[512]; + snprintf(url, sizeof(url), "%s/_matrix/client/r0/rooms/%s/joined_members", homeserver.c_str(), room->id.c_str()); + + rapidjson::Document json_root; + DownloadResult download_result = download_json(json_root, url, std::move(additional_args), true); + if(download_result != DownloadResult::OK || !json_root.IsObject()) { + fprintf(stderr, "Fetching users for room %s failed!\n", room->id.c_str()); + return; + } + + const rapidjson::Value &joined_json = GetMember(json_root, "joined"); + if(!joined_json.IsObject()) + return; + + for(auto const &joined_obj : joined_json.GetObject()) { + if(!joined_obj.name.IsString() || !joined_obj.value.IsObject()) + continue; + + const rapidjson::Value &avatar_url_json = GetMember(joined_obj.value, "avatar_url"); + const rapidjson::Value &display_name_json = GetMember(joined_obj.value, "display_name"); + auto user = get_user_by_id(room, std::string(joined_obj.name.GetString(), joined_obj.name.GetStringLength())); + assert(user); + + std::string display_name = display_name_json.IsString() ? display_name_json.GetString() : user_id; + std::string avatar_url; + if(avatar_url_json.IsString()) + avatar_url = std::string(avatar_url_json.GetString(), avatar_url_json.GetStringLength()); + if(!avatar_url.empty()) + avatar_url = homeserver + "/_matrix/media/r0/thumbnail/" + thumbnail_url_extract_media_id(avatar_url) + "?width=32&height=32&method=crop"; // TODO: Remove the constant strings around to reduce memory usage (6.3mb) + room->set_user_avatar_url(user, std::move(avatar_url)); + room->set_user_display_name(user, std::move(display_name)); + } } // TODO: GET the filter to check if its valid? -- cgit v1.2.3