From 70dfaff0802503968e667e4e1b2f7cc2815f283f Mon Sep 17 00:00:00 2001 From: Gergely Polonkai Date: Mon, 7 Mar 2016 09:44:06 +0100 Subject: [PATCH] Move Event types to the Matrix.Event namespace --- .gitignore | 13 +- src/Makefile.am | 13 +- src/matrix-api.vala | 2 +- src/matrix-client.vala | 16 +- src/matrix-compacts.vala | 1 + src/matrix-event-base.vala | 261 ++++++++++++++ ...-event.vala => matrix-event-presence.vala} | 15 +- src/matrix-event-room-base.vala | 116 ++++++ ...ent.vala => matrix-event-room-member.vala} | 19 +- ...nt.vala => matrix-event-room-message.vala} | 2 +- src/matrix-event-state-base.vala | 57 +++ src/matrix-event-types.c | 11 +- src/matrix-event.vala | 341 ------------------ src/matrix-http-api.vala | 2 +- src/matrix-http-client.vala | 16 +- src/matrix-state-event.vala | 58 --- ...ix-room-event.vala => namespace-info.vala} | 9 +- src/test-client.c | 24 +- 18 files changed, 497 insertions(+), 479 deletions(-) create mode 100644 src/matrix-event-base.vala rename src/{matrix-presence-event.vala => matrix-event-presence.vala} (90%) create mode 100644 src/matrix-event-room-base.vala rename src/{matrix-room-member-event.vala => matrix-event-room-member.vala} (83%) rename src/{matrix-room-message-event.vala => matrix-event-room-message.vala} (96%) create mode 100644 src/matrix-event-state-base.vala delete mode 100644 src/matrix-event.vala delete mode 100644 src/matrix-state-event.vala rename src/{matrix-room-event.vala => namespace-info.vala} (81%) diff --git a/.gitignore b/.gitignore index f956b10..1c01bbc 100644 --- a/.gitignore +++ b/.gitignore @@ -52,9 +52,10 @@ Makefile.in /src/matrix-http-api.c /src/matrix-http-client.c /src/matrix-compacts.c -/src/matrix-event.c -/src/matrix-presence-event.c -/src/matrix-room-event.c -/src/matrix-room-member-event.c -/src/matrix-state-event.c -/src/matrix-room-message-event.c +/src/matrix-event-base.c +/src/matrix-event-presence.c +/src/matrix-event-room-base.c +/src/matrix-event-room-member.c +/src/matrix-event-state-base.c +/src/matrix-event-room-message.c +/src/namespace-info.c diff --git a/src/Makefile.am b/src/Makefile.am index d00bbbd..42289be 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -16,18 +16,19 @@ lib_LTLIBRARIES = libmatrix-glib-0.0.la # Vala source files libmatrix_glib_0_0_la_VALA_SOURCES = \ + namespace-info.vala \ matrix-api.vala \ matrix-client.vala \ matrix-enums.vala \ matrix-http-api.vala \ matrix-http-client.vala \ matrix-compacts.vala \ - matrix-event.vala \ - matrix-presence-event.vala \ - matrix-state-event.vala \ - matrix-room-event.vala \ - matrix-room-member-event.vala \ - matrix-room-message-event.vala \ + matrix-event-base.vala \ + matrix-event-room-base.vala \ + matrix-event-state-base.vala \ + matrix-event-presence.vala \ + matrix-event-room-member.vala \ + matrix-event-room-message.vala \ $(NULL) AM_CPPFLAGS += \ diff --git a/src/matrix-api.vala b/src/matrix-api.vala index 6190c2a..0406769 100644 --- a/src/matrix-api.vala +++ b/src/matrix-api.vala @@ -357,7 +357,7 @@ public interface Matrix.API : GLib.Object { string? topic, Matrix.RoomVisibility visibility, Json.Node? creation_content, - GLib.List? initial_state, + GLib.List? initial_state, GLib.List? invitees, GLib.List? invite_3pids) throws Matrix.Error; diff --git a/src/matrix-client.vala b/src/matrix-client.vala index b6a9032..b7baeab 100644 --- a/src/matrix-client.vala +++ b/src/matrix-client.vala @@ -47,7 +47,7 @@ public interface Matrix.Client : GLib.Object { */ [Signal (detailed=true)] public virtual signal void - @event(string? room_id, Json.Node raw_event, Matrix.Event matrix_event) + @event(string? room_id, Json.Node raw_event, Matrix.Event.Base? matrix_event) {} /** @@ -61,7 +61,7 @@ public interface Matrix.Client : GLib.Object { EventCallback(Matrix.Client client, string? room_id, Json.Node raw_event, - Matrix.Event matrix_event); + Matrix.Event.Base? matrix_event); /** * Authenticate with the Matrix.org server with a username and @@ -144,9 +144,15 @@ public interface Matrix.Client : GLib.Object { public void incoming_event(string? room_id, Json.Node raw_event, - Matrix.Event matrix_event) + Matrix.Event.Base? matrix_event) { - Quark equark = matrix_event.get_type().qname(); + Quark equark; + + if (matrix_event == null) { + equark = typeof(Matrix.Event.Base).qname(); + } else { + equark = matrix_event.get_type().qname(); + } this.@event[equark.to_string()](room_id, raw_event, matrix_event); } @@ -161,7 +167,7 @@ public interface Matrix.Client : GLib.Object { * * @param event_gtype the {@link GLib.Type} of a * {@link Matrix.Event} derivative - * @param callback the allback function to connect + * @param event_callback the allback function to connect */ public extern void connect_event(GLib.Type event_gtype, diff --git a/src/matrix-compacts.vala b/src/matrix-compacts.vala index 633e9da..06eea1a 100644 --- a/src/matrix-compacts.vala +++ b/src/matrix-compacts.vala @@ -15,6 +15,7 @@ * License along with matrix-glib-sdk. If not, see * . */ + namespace Matrix { /** * Abstract parent class for classes that can be saved to JSON. diff --git a/src/matrix-event-base.vala b/src/matrix-event-base.vala new file mode 100644 index 0000000..f3b00b6 --- /dev/null +++ b/src/matrix-event-base.vala @@ -0,0 +1,261 @@ +/* + * This file is part of matrix-glib-sdk + * + * matrix-glib-sdk is free software: you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation, either + * version 3 of the License, or (at your option) any later version. + * + * matrix-glib-sdk is distributed in the hope that it will be + * useful, but WITHOUT ANY WARRANTY; without even the implied + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with matrix-glib-sdk. If not, see + * . + */ + +/** + * Base class for Matrix events. + */ +public abstract class Matrix.Event.Base : GLib.Object, GLib.Initable { + private Error? _construct_error = null; + private bool _inited = false; + private Json.Node? _json; + + /** + * The type of the event. It should be namespaced similar to the + * Java package naming conventions, + * e.g. `com.example.subdomain.event.type`. It cannot be changed + * after object initialization. + */ + public string? event_type { get; construct; default = null; } + + /** + * The event as a JSON node. + */ + public Json.Node? json { + get { + _json = new Json.Node(Json.NodeType.OBJECT); + _json.set_object(new Json.Object()); + + // Add the content node, as all event types must include it. + var content_root = new Json.Node(Json.NodeType.OBJECT); + var content_obj = new Json.Object(); + content_root.set_object(content_obj); + _json.get_object().set_member("content", content_root); + + try { + to_json(_json); + } + catch (Matrix.Error e) { + return null; + } + + return _json; + } + + construct { + if (value != null) { + try { + initialize_from_json(value); + } catch (Matrix.Error e) {} + } + } + } + + public bool + init(GLib.Cancellable? cancellable = null) + throws Error, Matrix.Error + { + if (cancellable != null) { + throw new Matrix.Error.UNSUPPORTED( + "Cancellable initialization not supported"); + } + + if (_construct_error != null) { + throw _construct_error; + } + + _inited = true; + + return true; + } + + private void + initialize_from_json(Json.Node json_data) + throws Matrix.Error + { + Json.Object root; + Json.Node node; + + if (json_data.get_node_type() != Json.NodeType.OBJECT) { + throw new Matrix.Error.INVALID_FORMAT( + "The event is not valid"); + } + + root = json_data.get_object(); + + if ((node = root.get_member("type")) == null) { + throw new Matrix.Error.INCOMPLETE( + "Event type is not specified"); + } + + if ((_event_type != null) + && (_event_type != node.get_string())) { + throw new Matrix.Error.INVALID_TYPE( + "Changing event type is not supported"); + } + + var evt_type = node.get_string(); + + if ((node = root.get_member("content")) == null) { + warning("content key is missing from the %s event", evt_type); + + // As event type objects depend on having this node, let’s + // add it now. + var content_node = new Json.Node(Json.NodeType.OBJECT); + content_node.set_object(new Json.Object()); + root.set_member("content", content_node); + } + + from_json(json_data); + + _event_type = evt_type; + } + + /** + * Subclasses should implement this function to initialize + * themselves from JSON data. + */ + public virtual void + from_json(Json.Node json_data) + throws Matrix.Error + {} + + /** + * Subclasses should implement this to export their data to JSON. + */ + public virtual void + to_json(Json.Node json_data) + throws Matrix.Error + { + Json.Object root = json_data.get_object(); + + if (event_type != null) { + root.set_string_member("type", event_type); + } + } + + public static Base? + new_from_json(owned string? event_type = null, + Json.Node? json_data = null) + throws Matrix.Error, GLib.Error + { + GLib.Type? event_gtype; + Base? ret = null; + + if (event_type == null) { + if (json_data == null) { + throw new Matrix.Error.INCOMPLETE( + "Either event_type or json_data must be set!"); + } + + if (json_data.get_node_type() != Json.NodeType.OBJECT) { + throw new Matrix.Error.INVALID_FORMAT( + "Event is not a JSON object!"); + } + + Json.Node? node; + + if ((node = json_data.get_object().get_member("type")) == null) { + throw new Matrix.Error.INCOMPLETE( + "event_type is null and JSON object doesn't contain type!"); + } + + event_type = node.get_string(); + } + + if ((event_gtype = get_handler(event_type)) == null) { + throw new Matrix.Error.INVALID_TYPE( + "No registered type for event type %s", + event_type); + } + + ret = (Base)Object.new(event_gtype, + event_type : event_type, + json : json_data); + + ret.init(); + + return ret; + } +} + +namespace Matrix.Event { + +private HashTable? type_handlers = null; + +/** + * Get the {@link GLib.Type} of the class that is registered to + * handle events with type @param event_type. + * + * @param event_type the event type to look up + * @return a {@link GLib.Type} or {@link Matrix.Event} if no + * handler is registered + */ +public static GLib.Type? +get_handler(string event_type) +{ + unowned GLib.TypeClass? klass = null; + + if ((type_handlers != null) + && ((klass = type_handlers.get(event_type)) != null)) { + return klass.get_type(); + } + + if (Config.DEBUG) { + warning("No registered type for %s", event_type); + } + + return null; +} + +/** + * Registers @param event_type to be handled by the + * type @param event_gtype. + * + * @param event_type the type of the event + * @param event_gtype the {@link GLib.Type} of the event’s handler + */ +public static void +register_type(string event_type, GLib.Type event_gtype) + throws Matrix.Error +{ + if (!event_gtype.is_a(typeof(Matrix.Event.Base))) { + throw new Matrix.Error.INVALID_TYPE( + "Invalid event type handler. It must be a subclass of MatrixEvent"); + } + + if (type_handlers == null) { + type_handlers = new HashTable( + str_hash, str_equal); + } + + type_handlers.replace(event_type, event_gtype.class_ref()); +} + +/** + * Unregister @param event_type. + * + * @param event_type the event type to remove + */ +public static void +unregister_type(string event_type) +{ + if (type_handlers != null) { + type_handlers.remove(event_type); + } +} +} diff --git a/src/matrix-presence-event.vala b/src/matrix-event-presence.vala similarity index 90% rename from src/matrix-presence-event.vala rename to src/matrix-event-presence.vala index e908fa5..b86deb7 100644 --- a/src/matrix-presence-event.vala +++ b/src/matrix-event-presence.vala @@ -21,10 +21,11 @@ * * The presence event class. */ -public class Matrix.PresenceEvent : Matrix.Event { +public class Matrix.Event.Presence : Matrix.Event.Base { public string? avatar_url { get; set; } public string? display_name { get; set; } public ulong? last_active_ago { get; set; } + public string? user_id { get; set; default = null; } public Matrix.Presence presence { get; set; @@ -39,7 +40,7 @@ public class Matrix.PresenceEvent : Matrix.Event { Json.Node? node; if ((node = content_root.get_member("user_id")) != null) { - _sender = node.get_string(); + _user_id = node.get_string(); } else if (Config.DEBUG) { warning("user_id is missing from the m.presence event"); } @@ -86,17 +87,17 @@ public class Matrix.PresenceEvent : Matrix.Event { "unkwnown presence cannot be added to a presence event"); } - if (sender == null) { + if (_user_id == null) { throw new Matrix.Error.INCOMPLETE ( "sender must be set for presence events!"); } - content_root = _json_object_node_ensure_field(json_data, - "content", - Json.NodeType.OBJECT) + content_root = json_data + .get_object() + .get_member("content") .get_object(); - content_root.set_string_member("user_id", sender); + content_root.set_string_member("user_id", _user_id); if (last_active_ago != null) { content_root.set_int_member("last_active_ago", last_active_ago); diff --git a/src/matrix-event-room-base.vala b/src/matrix-event-room-base.vala new file mode 100644 index 0000000..a3c103f --- /dev/null +++ b/src/matrix-event-room-base.vala @@ -0,0 +1,116 @@ +/* + * This file is part of matrix-glib-sdk + * + * matrix-glib-sdk is free software: you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation, either + * version 3 of the License, or (at your option) any later version. + * + * matrix-glib-sdk is distributed in the hope that it will be + * useful, but WITHOUT ANY WARRANTY; without even the implied + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with matrix-glib-sdk. If not, see + * . + */ + +/** + * Abstract base class for room events. + */ +public abstract class Matrix.Event.Room : Matrix.Event.Base { + /** + * A globally unique event ID. Required. + */ + public string? event_id { get; set; default = null; } + + /** + * The ID of the room associated with this event. Required. + */ + public string? room_id { get; set; default = null; } + + /** + * The fully qualified Matrix ID of the user who sent the + * event. Required. + */ + public string? sender { get; set; default = null; } + + /** + * The time, in milliseconds, that has elapsed since the event was + * sent. This is part of the unsigned event data. + */ + public ulong? age { get; set; default = null; } + + /** + * The reason this event was redacted, if it was redacted. + */ + public string? redacted_because { get; set; default = null; } + + /** + * The client-supplied transaction ID. This should only be set if + * the client being given the event is the same one which sent it. + */ + public string? transaction_id { get; set; default = null; } + + protected override void + from_json(Json.Node json_data) + throws Matrix.Error + { + Json.Node? node; + var root = json_data.get_object(); + + if ((node = root.get_member("event_id")) != null) { + _event_id = node.get_string(); + } + + if ((node = root.get_member("room_id")) != null) { + _room_id = node.get_string(); + } + + if ((node = root.get_member("sender")) != null) { + _sender = node.get_string(); + } + } + + protected override void + to_json(Json.Node json_data) + throws Matrix.Error + { + var root_obj = json_data.get_object(); + + if (event_id != null) { + root_obj.set_string_member("event_id", event_id); + } + + if (room_id != null) { + root_obj.set_string_member("room_id", room_id); + } + + if (sender != null) { + root_obj.set_string_member("sender", sender); + } + + var unsigned_obj = new Json.Object(); + + if (age != null) { + unsigned_obj.set_int_member("age", age); + } + + if (redacted_because != null) { + unsigned_obj.set_string_member("redacted_because", + redacted_because); + } + + if (transaction_id != null) { + unsigned_obj.set_string_member("transaction_id", + transaction_id); + } + + if (unsigned_obj.get_size() > 0) { + var unsigned_node = new Json.Node(Json.NodeType.OBJECT); + unsigned_node.set_object(unsigned_obj); + root_obj.set_member("unsigned", unsigned_node); + } + } +} diff --git a/src/matrix-room-member-event.vala b/src/matrix-event-room-member.vala similarity index 83% rename from src/matrix-room-member-event.vala rename to src/matrix-event-room-member.vala index d6f1e11..3627ef8 100644 --- a/src/matrix-room-member-event.vala +++ b/src/matrix-event-room-member.vala @@ -21,8 +21,7 @@ * * The room membership event class. */ -public class Matrix.RoomMemberEvent : Matrix.RoomEvent { - public string? state_key { get; set; } +public class Matrix.Event.RoomMember : Matrix.Event.State { public RoomMembership membership { get; set; default = RoomMembership.UNKNOWN; @@ -38,18 +37,6 @@ public class Matrix.RoomMemberEvent : Matrix.RoomEvent { Json.Object content_root = root.get_member("content").get_object(); Json.Node? node; - if ((node = root.get_member("state_key")) != null) { - _state_key = node.get_string(); - } else if (Config.DEBUG) { - warning("state_key is missing from the m.room.member event"); - } - - if ((node = root.get_member("room_id")) != null) { - _room_id = node.get_string(); - } else if (Config.DEBUG) { - warning("room_id is missing from the m.room.member event"); - } - if ((node = content_root.get_member("membership")) != null) { Matrix.RoomMembership? mship = (Matrix.RoomMembership?)_g_enum_nick_to_value( typeof(Matrix.RoomMembership), @@ -95,10 +82,6 @@ public class Matrix.RoomMemberEvent : Matrix.RoomEvent { root.set_string_member("state_key", state_key); - if (room_id != null) { - root.set_string_member("room_id", room_id); - } - mship = _g_enum_value_to_nick(typeof(Matrix.RoomMembership), membership); diff --git a/src/matrix-room-message-event.vala b/src/matrix-event-room-message.vala similarity index 96% rename from src/matrix-room-message-event.vala rename to src/matrix-event-room-message.vala index 1a54272..b9055b8 100644 --- a/src/matrix-room-message-event.vala +++ b/src/matrix-event-room-message.vala @@ -16,7 +16,7 @@ * . */ -public class Matrix.RoomMessageEvent : Matrix.RoomEvent { +public class Matrix.Event.RoomMessage : Matrix.Event.Room { public string msg_type { get; set; } public string body { get; set; } diff --git a/src/matrix-event-state-base.vala b/src/matrix-event-state-base.vala new file mode 100644 index 0000000..b153a60 --- /dev/null +++ b/src/matrix-event-state-base.vala @@ -0,0 +1,57 @@ +/* + * This file is part of matrix-glib-sdk + * + * matrix-glib-sdk is free software: you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation, either + * version 3 of the License, or (at your option) any later version. + * + * matrix-glib-sdk is distributed in the hope that it will be + * useful, but WITHOUT ANY WARRANTY; without even the implied + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with matrix-glib-sdk. If not, see + * . + */ + +public abstract class Matrix.Event.State : Matrix.Event.Base { + public string? state_key { get; set; default = null; } + public Json.Node? prev_content { get; set; default = null; } + + protected override void + from_json(Json.Node json_data) + throws Matrix.Error + { + var root = json_data.get_object(); + Json.Node? node; + + if ((node = root.get_member("state_key")) != null) { + state_key = node.get_string(); + } + + if ((node = root.get_member("prev_content")) != null) { + _prev_content = node; + } + + base.from_json(json_data); + } + + protected override void + to_json(Json.Node json_node) + throws Matrix.Error + { + var root = json_node.get_object(); + + if (state_key != null) { + root.set_string_member("state_key", state_key); + } + + if (prev_content != null) { + root.set_member("prev_content", prev_content); + } + + base.to_json(json_node); + } +} diff --git a/src/matrix-event-types.c b/src/matrix-event-types.c index 1d96646..4dfd4c0 100644 --- a/src/matrix-event-types.c +++ b/src/matrix-event-types.c @@ -153,13 +153,13 @@ static void matrix_event_types_ctor(void) { matrix_event_register_type("m.room.member", - MATRIX_TYPE_ROOM_MEMBER_EVENT, + MATRIX_EVENT_TYPE_ROOM_MEMBER, NULL); matrix_event_register_type("m.presence", - MATRIX_TYPE_PRESENCE_EVENT, + MATRIX_EVENT_TYPE_PRESENCE, NULL); matrix_event_register_type("m.room.message", - MATRIX_TYPE_ROOM_MESSAGE_EVENT, + MATRIX_EVENT_TYPE_ROOM_MESSAGE, NULL); } @@ -172,11 +172,11 @@ matrix_client_connect_event(MatrixClient *client, { GClosure *closure; GQuark equark; - MatrixEventClass *event_class = MATRIX_EVENT_CLASS( + MatrixEventBaseClass *event_class = MATRIX_EVENT_BASE_CLASS( g_type_class_ref(event_gtype)); guint event_signal_id = g_signal_lookup("event", MATRIX_TYPE_CLIENT); - if (!MATRIX_IS_EVENT_CLASS(event_class)) { + if (!MATRIX_EVENT_IS_BASE_CLASS(event_class)) { g_warning("Trying to connect to a type that is not derived from MatrixEvent"); g_type_class_unref(event_class); @@ -196,5 +196,4 @@ matrix_client_connect_event(MatrixClient *client, g_signal_connect_closure_by_id(client, event_signal_id, equark, closure, FALSE); - } diff --git a/src/matrix-event.vala b/src/matrix-event.vala deleted file mode 100644 index c4bf1dd..0000000 --- a/src/matrix-event.vala +++ /dev/null @@ -1,341 +0,0 @@ -/* - * This file is part of matrix-glib-sdk - * - * matrix-glib-sdk is free software: you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation, either - * version 3 of the License, or (at your option) any later version. - * - * matrix-glib-sdk is distributed in the hope that it will be - * useful, but WITHOUT ANY WARRANTY; without even the implied - * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with matrix-glib-sdk. If not, see - * . - */ - -private HashTable? event_type_handlers = null; - -/** - * Base class for Matrix events. - */ -public class Matrix.Event : GLib.Object, GLib.Initable { - private Error? _construct_error = null; - private bool _inited = false; - private Json.Node? _json; - private Gee.HashMap _custom_fields = - new Gee.HashMap(); - - protected string? _sender = null; - protected string? _room_id = null; - - /** - * The Matrix ID of the events sender. - */ - public string? sender { - get { - return _sender; - } - - set { - _sender = value; - } - - default = null; - } - - /** - * The ID of the room this event is associated with. - */ - public string? room_id { - get { - return _room_id; - } - - set { - _room_id = value; - } - - default = null; - } - - /** - * The type of the event. - */ - public string? event_type { get; construct; default = null; } - - /** - * The timestamp of the event on the originating server. - */ - public ulong? origin_server_ts { get; set; default = null; } - - /** - * The unsigned part of the event. - */ - public Matrix.UnsignedEventData unsigned_data { - get; set; - default = null; - } - - /** - * The event as a JSON node. - */ - public Json.Node? json { - get { - if (_json == null) { - _json = new Json.Node(Json.NodeType.OBJECT); - _json.set_object(new Json.Object()); - - } - - try { - to_json(_json); - } - catch (Matrix.Error e) { - return null; - } - - return _json; - } - - construct { - if (value != null) { - try { - initialize_from_json(value); - } catch (Matrix.Error e) {} - } - } - } - - public bool - init(GLib.Cancellable? cancellable = null) - throws Error, Matrix.Error - { - if (cancellable != null) { - throw new Matrix.Error.UNSUPPORTED( - "Cancellable initialization not supported"); - } - - if (_construct_error != null) { - throw _construct_error; - } - - _inited = true; - - return true; - } - - private void - initialize_from_json(Json.Node json_data) - throws Matrix.Error - { - Json.Object root; - Json.Node node; - - if (json_data.get_node_type() != Json.NodeType.OBJECT) { - throw new Matrix.Error.INVALID_FORMAT( - "The event is not valid"); - } - - root = json_data.get_object(); - - if ((node = root.get_member("type")) == null) { - throw new Matrix.Error.INCOMPLETE( - "Event type is not specified"); - } - - if ((_event_type != null) - && (_event_type != node.get_string())) { - throw new Matrix.Error.INVALID_TYPE( - "Changing event type is not supported"); - } - - from_json(json_data); - - _event_type = node.get_string(); - - if ((node = root.get_member("origin_server_ts")) != null) { - _origin_server_ts = (ulong)node.get_int(); - } - - if ((node = root.get_member("sender")) != null) { - _sender = node.get_string(); - } - - if ((node = root.get_member("unsigned")) != null) { - _unsigned_data = new Matrix.UnsignedEventData.from_json(node); - } - } - - /** - * Subclasses should implement this function to initialize - * themselves from JSON data. - */ - public virtual void - from_json(Json.Node json_data) - throws Matrix.Error - {} - - /** - * Subclasses should implement this to export their data to JSON. - */ - public virtual void - to_json(Json.Node json_data) - throws Matrix.Error - { - Json.Object root = json_data.get_object(); - - foreach (var entry in _custom_fields.entries) { - root.set_member(entry.key, _json_node_deep_copy(entry.value)); - } - - if (event_type != null) { - root.set_string_member("type", event_type); - } - - if (origin_server_ts != null) { - root.set_int_member("origin_server_ts", origin_server_ts); - } - - if (sender != null) { - root.set_string_member("sender", sender); - } - - if (unsigned_data != null) { - root.set_member("unsigned", unsigned_data.get_json_node()); - } - } - - public static Event? - new_from_json(owned string? event_type = null, - string? room_id = null, - Json.Node? json_data = null) - throws Matrix.Error, GLib.Error - { - GLib.Type event_gtype; - Event? ret = null; - - if (event_type == null) { - if (json_data == null) { - throw new Matrix.Error.INCOMPLETE( - "Either event_type or json_data must be set!"); - } - - if (json_data.get_node_type() != Json.NodeType.OBJECT) { - throw new Matrix.Error.INVALID_FORMAT( - "Event is not a JSON object!"); - } - - Json.Node? node; - - if ((node = json_data.get_object().get_member("type")) == null) { - throw new Matrix.Error.INCOMPLETE( - "event_type is null and JSON object doesn't contain type!"); - } - - event_type = node.get_string(); - } - - event_gtype = get_handler(event_type); - - ret = (Event)Object.new(event_gtype, - event_type : event_type, - room_id : room_id, - json : json_data); - - ret.init(); - - return ret; - } - - /** - * Set a value for a custom field. - */ - public void - set_custom_field(string field_name, Json.Node value) - { - _custom_fields.set(field_name, value); - } - - /** - * Get the value of a custom field. - */ - public Json.Node? - get_custom_field (string field_name) - { - return _custom_fields.get(field_name); - } - - /** - * Delete a custom field. - */ - public void - delete_custom_field (string field_name) - { - _custom_fields.unset(field_name); - } - - /** - * Get the {@link GLib.Type} of the class that is registered to - * handle events with type @param event_type. - * - * @param event_type the event type to look up - * @return a {@link GLib.Type} or {@link Matrix.Event} if no - * handler is registered - */ - public static GLib.Type - get_handler(string event_type) - { - unowned GLib.TypeClass? klass = null; - - if ((event_type_handlers != null) - && ((klass = event_type_handlers.get(event_type)) != null)) { - return klass.get_type(); - } - - if (Config.DEBUG) { - warning("Using Matrix.Event for %s", event_type); - } - - return typeof(Matrix.Event); - } - - /** - * Registers @param event_type to be handled by the - * type @param event_gtype. - * - * @param event_type the type of the event - * @param event_gtype the {@link GLib.Type} of the event’s handler - */ - public static void - register_type(string event_type, GLib.Type event_gtype) - throws Matrix.Error - { - if (!event_gtype.is_a(typeof(Matrix.Event))) { - throw new Matrix.Error.INVALID_TYPE( - "Invalid event type handler. It must be a subclass of MatrixEvent"); - } - - if (event_type_handlers == null) { - event_type_handlers = new HashTable( - str_hash, str_equal); - } - - event_type_handlers.replace(event_type, event_gtype.class_ref()); - } - - /** - * Unregister @param event_type. - * - * @param event_type the event type to remove - */ - public static void - unregister_type(string event_type) - { - if (event_type_handlers != null) { - event_type_handlers.remove(event_type); - } - } -} diff --git a/src/matrix-http-api.vala b/src/matrix-http-api.vala index e654805..4a2f8ce 100644 --- a/src/matrix-http-api.vala +++ b/src/matrix-http-api.vala @@ -809,7 +809,7 @@ public class Matrix.HTTPAPI : GLib.Object, Matrix.API { string? topic, RoomVisibility visibility, Json.Node? creation_content, - List? initial_state, + List? initial_state, List? invitees, List<3PidCredential>? invite_3pids) throws Matrix.Error diff --git a/src/matrix-http-client.vala b/src/matrix-http-client.vala index 555a200..9d7a6fb 100644 --- a/src/matrix-http-client.vala +++ b/src/matrix-http-client.vala @@ -81,7 +81,7 @@ public class Matrix.HTTPClient : Matrix.HTTPAPI, Matrix.Client { Json.Object root_obj; Json.Node node; string event_type; - Matrix.Event evt; + Matrix.Event.Base? evt = null; if (event_node.get_node_type() != Json.NodeType.OBJECT) { if (Config.DEBUG) { @@ -104,19 +104,9 @@ public class Matrix.HTTPClient : Matrix.HTTPAPI, Matrix.Client { event_type = node.get_string(); try { - evt = Matrix.Event.new_from_json(event_type, room_id, event_node); - } catch (Matrix.Error e) { - if (Config.DEBUG) { - warning("Error during event creation: %s", e.message); - } - - return; + evt = Matrix.Event.Base.new_from_json(event_type, event_node); } catch (GLib.Error e) { - if (Config.DEBUG) { - warning("Error during event creation: %s", e.message); - } - - return; + evt = null; } incoming_event(room_id, event_node, evt); diff --git a/src/matrix-state-event.vala b/src/matrix-state-event.vala deleted file mode 100644 index 70132ee..0000000 --- a/src/matrix-state-event.vala +++ /dev/null @@ -1,58 +0,0 @@ -/* - * This file is part of matrix-glib-sdk - * - * matrix-glib-sdk is free software: you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation, either - * version 3 of the License, or (at your option) any later version. - * - * matrix-glib-sdk is distributed in the hope that it will be - * useful, but WITHOUT ANY WARRANTY; without even the implied - * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with matrix-glib-sdk. If not, see - * . - */ -namespace Matrix { - public class StateEvent : Matrix.Event { - public string? state_key { get; set; default = null; } - public Json.Node? content { get; set; default = null; } - - protected override void - from_json(Json.Node json_data) - throws Matrix.Error - { - var root = json_data.get_object(); - Json.Node? node; - - if ((node = root.get_member("state_key")) != null) { - state_key = node.get_string(); - } - - if ((node = root.get_member("content")) != null) { - content = node; - } - - base.from_json(json_data); - } - - protected override void - to_json(Json.Node json_node) - throws Matrix.Error - { - var root = json_node.get_object(); - - if (state_key != null) { - root.set_string_member("state_key", state_key); - } - - if (content != null) { - root.set_member("content", content); - } - - base.to_json(json_node); - } - } -} diff --git a/src/matrix-room-event.vala b/src/namespace-info.vala similarity index 81% rename from src/matrix-room-event.vala rename to src/namespace-info.vala index 3b05dd9..059ef7f 100644 --- a/src/matrix-room-event.vala +++ b/src/namespace-info.vala @@ -16,7 +16,8 @@ * . */ -/** - * Abstract base class for room events. - */ -public abstract class Matrix.RoomEvent : Matrix.Event {} +[CCode (gir_namespace = "Matrix", gir_version = "0.10")] +namespace Matrix { + [CCode (gir_namespace = "Event", gir_version = "0.10")] + namespace Event {} +} diff --git a/src/test-client.c b/src/test-client.c index 5c5b2b0..e56cb5c 100644 --- a/src/test-client.c +++ b/src/test-client.c @@ -49,23 +49,23 @@ static void cb_presence_event(MatrixClient *client, const gchar *room_id, JsonNode *raw_event, - MatrixEvent *event, + MatrixEventBase *event, gpointer user_data) { g_printerr("Incoming presence event from %s!\n", - matrix_event_get_sender(event)); + matrix_event_room_get_sender(MATRIX_EVENT_PRESENCE(event))); } static void cb_room_member_event(MatrixClient *client, const gchar *room_id, JsonNode *raw_event, - MatrixEvent *event, + MatrixEventBase *event, gpointer user_data) { g_printerr("Incoming room member event from %s in room %s (%s)\n", - matrix_event_get_sender(event), - matrix_event_get_room_id(MATRIX_EVENT(event)), + matrix_event_room_get_sender(MATRIX_EVENT_ROOM(event)), + matrix_event_room_get_room_id(MATRIX_EVENT_ROOM(event)), room_id); } @@ -73,13 +73,13 @@ static void cb_room_message_event(MatrixClient *client, const gchar *room_id, JsonNode *raw_event, - MatrixEvent *event, + MatrixEventBase *event, gpointer user_data) { g_printf("Message from %s: %s\n", - matrix_event_get_sender(event), - matrix_room_message_event_get_body( - MATRIX_ROOM_MESSAGE_EVENT(event))); + matrix_event_room_get_sender(MATRIX_EVENT_ROOM(event)), + matrix_event_room_message_get_body( + MATRIX_EVENT_ROOM_MESSAGE(event))); } int @@ -119,11 +119,11 @@ main(int argc, char *argv[]) "login-finished", G_CALLBACK(login_finished), loop); - matrix_client_connect_event(client, MATRIX_TYPE_PRESENCE_EVENT, + matrix_client_connect_event(client, MATRIX_EVENT_TYPE_PRESENCE, cb_presence_event, NULL, NULL); - matrix_client_connect_event(client, MATRIX_TYPE_ROOM_MEMBER_EVENT, + matrix_client_connect_event(client, MATRIX_EVENT_TYPE_ROOM_MEMBER, cb_room_member_event, NULL, NULL); - matrix_client_connect_event(client, MATRIX_TYPE_ROOM_MESSAGE_EVENT, + matrix_client_connect_event(client, MATRIX_EVENT_TYPE_ROOM_MESSAGE, cb_room_message_event, NULL, NULL); matrix_client_login_with_password(client, user, password, NULL);