From 118ea78d95a82d9f943180c8f976befc5d2dc97e Mon Sep 17 00:00:00 2001 From: dec05eba Date: Sat, 11 Mar 2023 23:12:25 +0100 Subject: Matrix: allow pressing enter on a message with a room alias to join the room --- src/plugins/Matrix.cpp | 83 +++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 82 insertions(+), 1 deletion(-) (limited to 'src/plugins') diff --git a/src/plugins/Matrix.cpp b/src/plugins/Matrix.cpp index 062d16a..d847719 100644 --- a/src/plugins/Matrix.cpp +++ b/src/plugins/Matrix.cpp @@ -3464,6 +3464,74 @@ namespace QuickMedia { return email.substr(0, index); } + // Not 100% correct on the server name part, but good enough + static std::string_view extract_matrix_identifier(const char *str, size_t size) { + if(size == 0) + return {}; + + size_t index = 0; + switch(str[index]) { + case '@': + case '!': + case '$': + case '+': + case '#': + break; + default: + return {}; + } + + ++index; + const size_t local_part_start = index; + bool found_colon = false; + // Parse local part + for(; index < size; ++index) { + char c = str[index]; + if((c >= 'a' && c <= 'z') || c == '-' || c == '.' || c == '=' || c == '_' || c == '/') { + + } else if(c == ':') { + found_colon = true; + break; + } + } + + if(!found_colon || index - local_part_start == 0) + return {}; + + ++index; + const size_t server_part_start = index; + // Parse server name + for(; index < size; ++index) { + char c = str[index]; + if((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') || c == '-' || c == '.' || c == ':' || c == '[' || c == ']') { + + } else { + break; + } + } + + if(index - server_part_start == 0) + return {}; + + return { str, index }; + } + + std::vector matrix_extract_room_ids(const std::string &str) { + std::vector result; + size_t index = 0; + while(index < str.size()) { + std::string_view room_id = extract_matrix_identifier(str.data() + index, str.size() - index); + // TODO: Support ! room id joining. It doesn't work right now. Seems like matrix itself doesn't support that + if(room_id.empty() || (room_id[0] != '#'/* && room_id[0] != '!'*/)) { + ++index; + } else { + index += room_id.size(); + result.emplace_back(room_id.data(), room_id.size()); + } + } + return result; + } + static std::string combine_user_display_names_for_room_name(std::vector> &user_info, const std::string &fallback_user_id) { std::string result; if(user_info.size() == 0) @@ -5446,8 +5514,21 @@ namespace QuickMedia { return true; } + static std::string room_id_extract_server_name(const std::string &room_id) { + size_t index = room_id.find(':'); + if(index == std::string::npos) + return ""; + else + return room_id.substr(index + 1); + } + PluginResult Matrix::join_room(const std::string &room_id_or_name) { assert(delegate); + + std::string url = homeserver + "/_matrix/client/r0/join/" + url_param_encode(room_id_or_name); + if(!room_id_or_name.empty() && room_id_or_name[0] == '!') + url += "?via=" + url_param_encode(room_id_extract_server_name(room_id_or_name)); + std::vector additional_args = { { "-X", "POST" }, { "-H", "content-type: application/json" }, @@ -5457,7 +5538,7 @@ namespace QuickMedia { rapidjson::Document json_root; std::string err_msg; - DownloadResult download_result = download_json(json_root, homeserver + "/_matrix/client/r0/join/" + url_param_encode(room_id_or_name), std::move(additional_args), true, &err_msg); + DownloadResult download_result = download_json(json_root, url, std::move(additional_args), true, &err_msg); if(download_result != DownloadResult::OK) return download_result_to_plugin_result(download_result); if(!json_root.IsObject()) -- cgit v1.2.3