From e493614b775c3d9c1684a010bac28f0523a103d6 Mon Sep 17 00:00:00 2001 From: dec05eba Date: Tue, 3 Nov 2020 02:49:40 +0100 Subject: Matrix: fetch user if the user is not available for some reason (synapse bug?) --- plugins/Matrix.hpp | 2 ++ src/plugins/Matrix.cpp | 74 ++++++++++++++++++++++++++++++++++---------------- 2 files changed, 52 insertions(+), 24 deletions(-) diff --git a/plugins/Matrix.hpp b/plugins/Matrix.hpp index d9e6a97..20ad7da 100644 --- a/plugins/Matrix.hpp +++ b/plugins/Matrix.hpp @@ -451,6 +451,7 @@ namespace QuickMedia { PluginResult parse_sync_room_data(const rapidjson::Value &rooms_json); PluginResult get_previous_room_messages(RoomData *room_data); void events_add_user_info(const rapidjson::Value &events_json, RoomData *room_data); + std::shared_ptr parse_user_info(const rapidjson::Value &json, const std::string &user_id, RoomData *room_data); void events_add_user_read_markers(const rapidjson::Value &events_json, RoomData *room_data); void events_set_user_read_marker(const rapidjson::Value &events_json, RoomData *room_data, std::shared_ptr &me); void events_add_messages(const rapidjson::Value &events_json, RoomData *room_data, MessageDirection message_dir, bool has_unread_notifications); @@ -469,6 +470,7 @@ namespace QuickMedia { void set_next_batch(std::string new_next_batch); std::string get_next_batch(); void clear_sync_cache_for_new_sync(); + std::shared_ptr get_user_by_id(RoomData *room, const std::string &user_id); DownloadResult download_json(rapidjson::Document &result, const std::string &url, std::vector additional_args, bool use_browser_useragent = false, std::string *err_msg = nullptr) const; private: std::vector> rooms; diff --git a/src/plugins/Matrix.cpp b/src/plugins/Matrix.cpp index 2e96cd0..5a85e8e 100644 --- a/src/plugins/Matrix.cpp +++ b/src/plugins/Matrix.cpp @@ -1307,28 +1307,33 @@ namespace QuickMedia { if(!membership_json.IsString() || strcmp(membership_json.GetString(), "join") != 0) continue; - std::string avatar_url_str; - const rapidjson::Value &avatar_url_json = GetMember(content_json, "avatar_url"); - if(avatar_url_json.IsString()) - avatar_url_str = avatar_url_json.GetString(); + std::string sender_json_str = sender_json.GetString(); + parse_user_info(content_json, sender_json_str, room_data); + } + } - const rapidjson::Value &display_name_json = GetMember(content_json, "displayname"); + std::shared_ptr Matrix::parse_user_info(const rapidjson::Value &json, const std::string &user_id, RoomData *room_data) { + assert(json.IsObject()); + 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(); - std::string sender_json_str = sender_json.GetString(); + const rapidjson::Value &display_name_json = GetMember(json, "displayname"); - auto user_info = std::make_shared(); - user_info->user_id = sender_json_str; - user_info->avatar_url = std::move(avatar_url_str); - if(strncmp(user_info->avatar_url.c_str(), "mxc://", 6) == 0) - user_info->avatar_url.erase(user_info->avatar_url.begin(), user_info->avatar_url.begin() + 6); - if(!user_info->avatar_url.empty()) - user_info->avatar_url = homeserver + "/_matrix/media/r0/thumbnail/" + user_info->avatar_url + "?width=32&height=32&method=crop"; // TODO: Remove the constant strings around to reduce memory usage (6.3mb) - user_info->display_name = display_name_json.IsString() ? display_name_json.GetString() : sender_json_str; - user_info->display_name_color = user_id_to_color(sender_json_str); - - // Overwrites user data - room_data->add_user(std::move(user_info)); - } + auto user_info = std::make_shared(); + user_info->user_id = user_id; + user_info->avatar_url = std::move(avatar_url_str); + if(strncmp(user_info->avatar_url.c_str(), "mxc://", 6) == 0) + user_info->avatar_url.erase(user_info->avatar_url.begin(), user_info->avatar_url.begin() + 6); + if(!user_info->avatar_url.empty()) + user_info->avatar_url = homeserver + "/_matrix/media/r0/thumbnail/" + user_info->avatar_url + "?width=32&height=32&method=crop"; // TODO: Remove the constant strings around to reduce memory usage (6.3mb) + user_info->display_name = display_name_json.IsString() ? display_name_json.GetString() : user_id; + user_info->display_name_color = user_id_to_color(user_id); + + // Overwrites user data + room_data->add_user(user_info); + return user_info; } void Matrix::events_add_user_read_markers(const rapidjson::Value &events_json, RoomData *room_data) { @@ -1369,7 +1374,7 @@ namespace QuickMedia { if(!user_id_json.IsString()) continue; - auto user = room_data->get_user_by_id(user_id_json.GetString()); + auto user = get_user_by_id(room_data, user_id_json.GetString()); if(!user) { fprintf(stderr, "Read receipt for unknown user: %s, ignoring...\n", user_id_json.GetString()); continue; @@ -1575,7 +1580,7 @@ namespace QuickMedia { if(!content_json->IsObject()) return nullptr; - auto user = room_data->get_user_by_id(sender_json_str); + auto user = get_user_by_id(room_data, sender_json_str); if(!user) { // Note: this is important because otherwise replying and such is broken fprintf(stderr, "Warning: skipping unknown user: %s\n", sender_json_str.c_str()); @@ -1809,7 +1814,7 @@ namespace QuickMedia { if(!has_room_avatar_url) { if(users_excluding_me.empty()) { - auto user = room_data->get_user_by_id(creator_json.GetString()); + auto user = get_user_by_id(room_data, creator_json.GetString()); if(user) room_data->set_avatar_url(user->avatar_url); } else { @@ -1971,7 +1976,7 @@ namespace QuickMedia { events_add_user_info(events_json, &invite_room); events_set_room_name(events_json, &invite_room); - auto invited_by = invite_room.get_user_by_id(sender_json.GetString()); + auto invited_by = get_user_by_id(&invite_room, sender_json.GetString()); if(!invited_by) { fprintf(stderr, "Invited by unknown user. Bug in homeserver?\n"); break; @@ -3015,7 +3020,7 @@ namespace QuickMedia { } std::shared_ptr Matrix::get_me(RoomData *room) { - return room->get_user_by_id(user_id); + return get_user_by_id(room, user_id); } RoomData* Matrix::get_room_by_id(const std::string &id) { @@ -3082,6 +3087,27 @@ namespace QuickMedia { delegate->clear_data(); } + std::shared_ptr Matrix::get_user_by_id(RoomData *room, const std::string &user_id) { + auto user = room->get_user_by_id(user_id); + if(user) + return user; + + // 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). + char url[512]; + snprintf(url, sizeof(url), "%s/_matrix/client/r0/profile/%s", homeserver.c_str(), user_id.c_str()); + + rapidjson::Document json_root; + 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; + } + + fprintf(stderr, "User was not available locally, fetched from server...\n"); + return parse_user_info(json_root, user_id, room); + } + DownloadResult Matrix::download_json(rapidjson::Document &result, const std::string &url, std::vector additional_args, bool use_browser_useragent, std::string *err_msg) const { if(download_to_json(url, result, std::move(additional_args), use_tor, use_browser_useragent, err_msg == nullptr) != DownloadResult::OK) { // Cant get error since we parse directly to json. TODO: Make this work somehow? -- cgit v1.2.3