diff --git a/src/matrix-api.vala b/src/matrix-api.vala index 73d6f78..6190c2a 100644 --- a/src/matrix-api.vala +++ b/src/matrix-api.vala @@ -940,7 +940,21 @@ public interface Matrix.API : GLib.Object { /* Search */ - /* TODO: implement search! */ + /** + * Perform a server side search. + * + * @param next_batch the point to return events from. If given, + * this should be a next_batch result from a + * previous call to this method + * @param search_categories describes which categories to search, + * and their criteria + */ + public abstract void + search([CCode (delegate_target_pos = 1.5, scope = "async")] + owned Matrix.API.Callback? @callback, + string? next_batch, + SearchCategories search_categories) + throws Matrix.Error; /* Server administration */ diff --git a/src/matrix-compacts.vala b/src/matrix-compacts.vala index 46d0a22..83d0e43 100644 --- a/src/matrix-compacts.vala +++ b/src/matrix-compacts.vala @@ -688,6 +688,247 @@ namespace Matrix { } } + public class EventContext : JsonCompact { + public int? before_limit { get; set; default = null; } + public int? after_limit { get; set; default = null; } + public bool? include_profile { get; set; default = null; } + + public override Json.Node? + get_json_node() + throws Matrix.Error + { + if ((before_limit == null) + && (after_limit == null) + && (include_profile == null)) + { + return null; + } + + var builder = new Json.Builder(); + + builder.begin_object(); + + if (before_limit != null) { + builder.set_member_name("before_limit"); + builder.add_int_value(before_limit); + } + + if (after_limit != null) { + builder.set_member_name("after_limit"); + builder.add_int_value(after_limit); + } + + if (include_profile != null) { + builder.set_member_name("include_profile"); + builder.add_boolean_value(include_profile); + } + + builder.end_object(); + + return builder.get_root(); + } + } + + public class SearchGrouping : JsonCompact { + public SearchGroupBy? key { get; set; default = null; } + + public override Json.Node? + get_json_node() + throws Matrix.Error + { + if (key == null) { + return null; + } + + var builder = new Json.Builder(); + + builder.begin_object(); + + builder.set_member_name("key"); + builder.add_string_value( + _g_enum_value_to_nick(typeof(SearchGroupBy), key, true)); + + builder.end_object(); + + return builder.get_root(); + } + } + + public class SearchGroupings : JsonCompact { + private List? _group_by = null; + public List? group_by { + get { + return _group_by; + } + + set { + _group_by = value.copy(); + } + + default = null; + } + + public override Json.Node? + get_json_node() + throws Matrix.Error + { + if (group_by == null) { + return null; + } + + var builder = new Json.Builder(); + + builder.begin_object(); + + builder.set_member_name("group_by"); + builder.begin_array(); + + foreach (var entry in group_by) { + var node = entry.get_json_node(); + + if (node != null) { + builder.add_value(node); + } + } + + builder.end_array(); + + builder.end_object(); + + return builder.get_root(); + } + } + + public class SearchRoomEvents : JsonCompact { + private List? _keys = null; + + public SearchOrder? order_by { get; set; default = SearchOrder.RECENT; } + public List? keys { + get { + return _keys; + } + + set { + _keys = value.copy(); + } + + default = null; } + public EventContext? event_context { get; set; default = null; } + public bool? include_state { get; set; default = false; } + public string? filter_id { get; set; default = null; } + public Filter? filter { get; set; default = null; } + public string search_term { get; set; } + public SearchGroupings? groupings { get; set; default = null; } + + public override Json.Node? + get_json_node() + throws Matrix.Error + { + Json.Node? node = null; + + var builder = new Json.Builder(); + + if ((filter_id != null) && (filter != null)) { + throw new Matrix.Error.INCOMPLETE( + "filter and filter_id is exclusive to each other"); + } + + builder.begin_object(); + + if (order_by != null) { + builder.set_member_name("order_by"); + builder.add_string_value( + _g_enum_value_to_nick(typeof(SearchOrder), order_by)); + } + + if (keys != null) { + EnumClass key_class = (EnumClass)(typeof(SearchKey).class_ref()); + var key_array = new Json.Array(); + + foreach (var entry in keys) { + if (entry != null) { + unowned EnumValue? key_value = key_class.get_value(entry); + + if (key_value != null) { + key_array.add_string_element( + key_value.value_nick.replace("-", ".")); + } + } + } + + if (key_array.get_length() > 0) { + node = new Json.Node(Json.NodeType.ARRAY); + node.set_array(key_array); + + builder.set_member_name("keys"); + builder.add_value(node); + } + } + + if ((event_context != null) + && ((node = event_context.get_json_node()) != null)) { + builder.set_member_name("event_context"); + builder.add_value(node); + } + + if (include_state != null) { + builder.set_member_name("include_state"); + builder.add_boolean_value(include_state); + } + + if ((filter != null) + && ((node = filter.get_json_node()) != null)) { + builder.set_member_name("filter"); + builder.add_value(node); + } + + if (filter_id != null) { + builder.set_member_name("filter"); + builder.add_string_value(filter_id); + } + + builder.set_member_name("search_term"); + builder.add_string_value(search_term); + + if ((groupings != null) + && ((node = groupings.get_json_node()) != null)) { + builder.set_member_name("groupings"); + builder.add_value(node); + } + + builder.end_object(); + + return builder.get_root(); + } + } + + public class SearchCategories : JsonCompact { + public SearchRoomEvents? room_events { get; set; default = null; } + + public override Json.Node? + get_json_node() + throws Matrix.Error + { + Json.Node? node = null; + + if ((room_events == null) + && ((node = room_events.get_json_node()) != null)) { + return null; + } + + var builder = new Json.Builder(); + + builder.begin_object(); + + builder.set_member_name("room_events"); + builder.add_value(node); + + builder.end_object(); + + return builder.get_root(); + } + } + private Json.Node? _json_object_node_ensure_field(Json.Node node, string field_name, diff --git a/src/matrix-enums.vala b/src/matrix-enums.vala index 2b15a2e..121e0b1 100644 --- a/src/matrix-enums.vala +++ b/src/matrix-enums.vala @@ -175,6 +175,22 @@ namespace Matrix { PRIVATE; /// hide the room from the public room list } + public enum SearchOrder { + RECENT, + RANK + } + + public enum SearchKey { + CONTENT_BODY, + CONTENT_NAME, + CONTENT_TOPIC + } + + public enum SearchGroupBy { + ROOM_ID, + SENDER + } + private int? _g_enum_nick_to_value(Type enum_type, string nick) { diff --git a/src/matrix-http-api.vala b/src/matrix-http-api.vala index ff08408..ad80a22 100644 --- a/src/matrix-http-api.vala +++ b/src/matrix-http-api.vala @@ -1410,6 +1410,25 @@ public class Matrix.HTTPAPI : GLib.Object, Matrix.API { /* Search */ + public void + search(Matrix.API.Callback? cb, + string? next_batch, + SearchCategories search_categories) + throws Matrix.Error + { + HashTable? parms = null; + + if (next_batch == null) { + parms = _create_query_params(); + + parms.replace("next_batch", next_batch); + } + + _send(cb, + CallType.API, "POST", "search", + parms, null, search_categories.get_json_node(), null, false); + } + /* Server administration */ public void