From 903d996e10401ec93a03b813cbc6ac4ace6a5dfa Mon Sep 17 00:00:00 2001 From: dec05eba Date: Wed, 4 Nov 2020 15:03:33 +0100 Subject: Test caching filter in matrix --- include/Storage.hpp | 1 + plugins/Matrix.hpp | 2 ++ src/Storage.cpp | 9 +++++++++ src/plugins/Matrix.cpp | 46 +++++++++++++++++++++++++++++++++++++++++++++- 4 files changed, 57 insertions(+), 1 deletion(-) diff --git a/include/Storage.hpp b/include/Storage.hpp index ae7db04..2e9d883 100644 --- a/include/Storage.hpp +++ b/include/Storage.hpp @@ -25,6 +25,7 @@ namespace QuickMedia { int file_get_content(const Path &path, std::string &result); int file_get_size(const Path &path, size_t *size); int file_overwrite(const Path &path, const std::string &data); + int file_overwrite_atomic(const Path &path, const std::string &data); void for_files_in_dir(const Path &path, FileIteratorCallback callback); void for_files_in_dir_sort_last_modified(const Path &path, FileIteratorCallback callback); diff --git a/plugins/Matrix.hpp b/plugins/Matrix.hpp index bf9f715..f4a3200 100644 --- a/plugins/Matrix.hpp +++ b/plugins/Matrix.hpp @@ -472,6 +472,7 @@ namespace QuickMedia { 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); + std::string get_filter_cached(); 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; @@ -494,5 +495,6 @@ namespace QuickMedia { bool sync_is_cache = false; std::string sync_fail_reason; MatrixDelegate *delegate = nullptr; + std::optional filter_cached; }; } \ No newline at end of file diff --git a/src/Storage.cpp b/src/Storage.cpp index 086f6d8..dadff5b 100644 --- a/src/Storage.cpp +++ b/src/Storage.cpp @@ -157,6 +157,15 @@ namespace QuickMedia { return file_overwrite(path, data.c_str(), data.size()); } + int file_overwrite_atomic(const Path &path, const std::string &data) { + Path tmp_path = path; + tmp_path.append(".tmp"); + int res = file_overwrite(tmp_path, data.c_str(), data.size()); + if(res != 0) + return res; + return rename(tmp_path.data.c_str(), path.data.c_str()); + } + void for_files_in_dir(const Path &path, FileIteratorCallback callback) { try { for(auto &p : std::filesystem::directory_iterator(path.data)) { diff --git a/src/plugins/Matrix.cpp b/src/plugins/Matrix.cpp index 11d0746..2736421 100644 --- a/src/plugins/Matrix.cpp +++ b/src/plugins/Matrix.cpp @@ -20,6 +20,7 @@ static const char* SERVICE_NAME = "matrix"; static const char* OTHERS_ROOM_TAG = "tld.name.others"; +static const char* FILTER = "{\"presence\":{\"limit\":0,\"types\":[\"\"]},\"account_data\":{\"limit\":0,\"types\":[\"\"]},\"room\":{\"state\":{\"not_types\":[\"m.room.related_groups\",\"m.room.power_levels\",\"m.room.join_rules\",\"m.room.history_visibility\"],\"lazy_load_members\":true},\"timeline\":{\"limit\":3,\"lazy_load_members\":true},\"ephemeral\":{\"limit\":0,\"types\":[\"\"],\"lazy_load_members\":true},\"account_data\":{\"limit\":1,\"types\":[\"m.fully_read\",\"m.tag\"],\"lazy_load_members\":true}}}"; static rapidjson::Value nullValue(rapidjson::kNullType); static const rapidjson::Value& GetMember(const rapidjson::Value &obj, const char *key) { @@ -850,7 +851,7 @@ namespace QuickMedia { // Filter with account data // {"presence":{"limit":0,"types":[""]},"account_data":{"not_types":["im.vector.setting.breadcrumbs","m.push_rules","im.vector.setting.allowed_widgets","io.element.recent_emoji"]},"room":{"state":{"limit":1,"not_types":["m.room.related_groups","m.room.power_levels","m.room.join_rules","m.room.history_visibility"],"lazy_load_members":true},"timeline":{"limit":3,"lazy_load_members":true},"ephemeral":{"limit":0,"types":[""],"lazy_load_members":true},"account_data":{"limit":1,"types":["m.fully_read"],"lazy_load_members":true}}} // Filter without account data - const char *filter = "{\"presence\":{\"limit\":0,\"types\":[\"\"]},\"account_data\":{\"limit\":0,\"types\":[\"\"]},\"room\":{\"state\":{\"not_types\":[\"m.room.related_groups\",\"m.room.power_levels\",\"m.room.join_rules\",\"m.room.history_visibility\"],\"lazy_load_members\":true},\"timeline\":{\"limit\":3,\"lazy_load_members\":true},\"ephemeral\":{\"limit\":0,\"types\":[\"\"],\"lazy_load_members\":true},\"account_data\":{\"limit\":1,\"types\":[\"m.fully_read\",\"m.tag\"],\"lazy_load_members\":true}}}"; + std::string filter = get_filter_cached(); const std::string filter_encoded = url_param_encode(filter); std::vector additional_args = { @@ -2753,6 +2754,8 @@ namespace QuickMedia { Path matrix_sync_data_path = get_cache_dir().join("matrix").join("sync_data.json"); remove(matrix_sync_data_path.data.c_str()); + Path filter_cache_path = get_storage_dir().join("matrix").join("filter"); + remove(filter_cache_path.data.c_str()); if(!json_root.IsObject()) { err_msg = "Failed to parse matrix login response"; @@ -2822,6 +2825,7 @@ namespace QuickMedia { upload_limit.reset(); set_next_batch(""); invites.clear(); + filter_cached.reset(); return PluginResult::OK; } @@ -3189,6 +3193,46 @@ namespace QuickMedia { #endif } + // TODO: GET the filter to check if its valid? + std::string Matrix::get_filter_cached() { + if(filter_cached) + return filter_cached.value(); + + Path filter_path = get_storage_dir().join("matrix").join("filter"); + std::string file_content; + if(file_get_content(filter_path, file_content) == 0) { + fprintf(stderr, "Loaded filter from cache\n"); + filter_cached = file_content; + return filter_cached.value(); + } + + fprintf(stderr, "Filter not available in cache, adding to server\n"); + + std::vector additional_args = { + { "-X", "POST" }, + { "-H", "Authorization: Bearer " + access_token }, + { "--data-binary", FILTER } + }; + + char url[512]; + snprintf(url, sizeof(url), "%s/_matrix/client/r0/user/%s/filter", homeserver.c_str(), user_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()) return FILTER; + + const rapidjson::Value &filter_id_json = GetMember(json_root, "filter_id"); + if(!filter_id_json.IsString()) + return FILTER; + + filter_cached = filter_id_json.GetString(); + Path filter_dir = get_storage_dir().join("matrix"); + if(create_directory_recursive(filter_dir) == 0) { + file_overwrite_atomic(filter_path, filter_cached.value()); + } + return filter_cached.value(); + } + 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