Fix Matrix.Event.RoomMember
It now complies with the Matrix spec.
This commit is contained in:
parent
26d144c593
commit
f48eaf4c88
@ -24,13 +24,25 @@ public abstract class Matrix.Event.Base : GLib.Object, GLib.Initable {
|
|||||||
private bool _inited = false;
|
private bool _inited = false;
|
||||||
private Json.Node? _json;
|
private Json.Node? _json;
|
||||||
|
|
||||||
|
protected string? _event_type = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The type of the event. It should be namespaced similar to the
|
* The type of the event. It should be namespaced similar to the
|
||||||
* Java package naming conventions,
|
* Java package naming conventions,
|
||||||
* e.g. `com.example.subdomain.event.type`. It cannot be changed
|
* e.g. `com.example.subdomain.event.type`. It cannot be changed
|
||||||
* after object initialization.
|
* after object initialization.
|
||||||
*/
|
*/
|
||||||
public string? event_type { get; construct; default = null; }
|
public string? event_type {
|
||||||
|
get {
|
||||||
|
return _event_type;
|
||||||
|
}
|
||||||
|
|
||||||
|
construct {
|
||||||
|
_event_type = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
default = null;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The event as a JSON node.
|
* The event as a JSON node.
|
||||||
|
@ -19,15 +19,111 @@
|
|||||||
/**
|
/**
|
||||||
* Class for representing a room membership events
|
* Class for representing a room membership events
|
||||||
*
|
*
|
||||||
* The room membership event class.
|
* Adjusts the membership state for a user in a room. It is preferable
|
||||||
|
* to use the membership APIs (`/rooms/<room id>/invite` etc) when
|
||||||
|
* performing membership actions rather than adjusting the state
|
||||||
|
* directly as there are a restricted set of valid
|
||||||
|
* transformations. For example, user A cannot force user B to join a
|
||||||
|
* room, and trying to force this state change directly will
|
||||||
|
* fail.
|
||||||
|
*
|
||||||
|
* The following membership states are specified:
|
||||||
|
*
|
||||||
|
* - invite - The user has been invited to join a room, but has not
|
||||||
|
* yet joined it. They may not participate in the room until they
|
||||||
|
* join.
|
||||||
|
*
|
||||||
|
* - join - The user has joined the room (possibly after accepting an
|
||||||
|
* invite), and may participate in it.
|
||||||
|
*
|
||||||
|
* - leave - The user was once joined to the room, but has since left
|
||||||
|
* (possibly by choice, or possibly by being kicked).
|
||||||
|
*
|
||||||
|
* - ban - The user has been banned from the room, and is no longer
|
||||||
|
* allowed to join it until they are un-banned from the room (by
|
||||||
|
* having their membership state set to a value other than ban).
|
||||||
|
*
|
||||||
|
* - knock - This is a reserved word, which currently has no meaning.
|
||||||
|
*
|
||||||
|
* The third_party_invite property will be set if this invite is an
|
||||||
|
* invite event and is the successor of an m.room.third_party_invite
|
||||||
|
* event, and absent otherwise.
|
||||||
|
*
|
||||||
|
* This event may also include an invite_room_state key outside the
|
||||||
|
* content key. If present, this contains an array of stripped state
|
||||||
|
* events. These events provide information on a few select state
|
||||||
|
* events such as the room name.
|
||||||
*/
|
*/
|
||||||
public class Matrix.Event.RoomMember : Matrix.Event.State {
|
public class Matrix.Event.RoomMember : Matrix.Event.State {
|
||||||
|
private List<Matrix.Event.State>? _invite_room_state = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The membership state of the user.
|
||||||
|
*/
|
||||||
public RoomMembership membership {
|
public RoomMembership membership {
|
||||||
get; set;
|
get;
|
||||||
|
|
||||||
|
set;
|
||||||
|
|
||||||
default = RoomMembership.UNKNOWN;
|
default = RoomMembership.UNKNOWN;
|
||||||
}
|
}
|
||||||
public string? avatar_url { get; set; }
|
|
||||||
public string? display_name { get; set; }
|
/**
|
||||||
|
* The avatar URL for this user, if any. This is added by the
|
||||||
|
* homeserver.
|
||||||
|
*/
|
||||||
|
public string? avatar_url { get; set; default = null; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The display name for this user, if any. This is added by the
|
||||||
|
* homeserver.
|
||||||
|
*/
|
||||||
|
public string? display_name { get; set; default = null; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A name which can be displayed to represent the user instead of
|
||||||
|
* their third party identifier
|
||||||
|
*/
|
||||||
|
public string? tpi_display_name { get; set; default = null; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The invited matrix user ID. Must be equal to the user_id
|
||||||
|
* property of the event.
|
||||||
|
*/
|
||||||
|
public string? tpi_signed_mxid { get; set; default = null; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The token property of the containing third_party_invite object.
|
||||||
|
*/
|
||||||
|
public string? tpi_signed_token { get; set; default = null; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A single signature from the verifying server, in the format
|
||||||
|
* specified by the Signing Events section of the server-server
|
||||||
|
* API.
|
||||||
|
*/
|
||||||
|
public Json.Node? tpi_signature { get; set; default = null; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A subset of the state of the room at the time of the invite, if
|
||||||
|
* membership is invite.
|
||||||
|
*/
|
||||||
|
public List<Matrix.Event.State>? invite_room_state {
|
||||||
|
get {
|
||||||
|
return _invite_room_state;
|
||||||
|
}
|
||||||
|
|
||||||
|
set {
|
||||||
|
_invite_room_state = value.copy();
|
||||||
|
}
|
||||||
|
|
||||||
|
default = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The user ID whom this event relates to.
|
||||||
|
*/
|
||||||
|
public string? user_id { get; set; default = null; }
|
||||||
|
|
||||||
protected override void
|
protected override void
|
||||||
from_json(Json.Node json_data)
|
from_json(Json.Node json_data)
|
||||||
@ -37,6 +133,14 @@ public class Matrix.Event.RoomMember : Matrix.Event.State {
|
|||||||
Json.Object content_root = root.get_member("content").get_object();
|
Json.Object content_root = root.get_member("content").get_object();
|
||||||
Json.Node? node;
|
Json.Node? node;
|
||||||
|
|
||||||
|
// Even though the state_key is handled by the parent class,
|
||||||
|
// in this event type this actually means the sender
|
||||||
|
if ((node = root.get_member("state_key")) != null) {
|
||||||
|
_user_id = node.get_string();
|
||||||
|
} else {
|
||||||
|
warning("state_key (thus, a user ID) is missing from a m.room.member event");
|
||||||
|
}
|
||||||
|
|
||||||
if ((node = content_root.get_member("membership")) != null) {
|
if ((node = content_root.get_member("membership")) != null) {
|
||||||
Matrix.RoomMembership? mship = (Matrix.RoomMembership?)_g_enum_nick_to_value(
|
Matrix.RoomMembership? mship = (Matrix.RoomMembership?)_g_enum_nick_to_value(
|
||||||
typeof(Matrix.RoomMembership),
|
typeof(Matrix.RoomMembership),
|
||||||
@ -57,6 +161,57 @@ public class Matrix.Event.RoomMember : Matrix.Event.State {
|
|||||||
_display_name = node.get_string();
|
_display_name = node.get_string();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((node = content_root.get_member("third_party_invite")) != null) {
|
||||||
|
var tpi_root = node.get_object();
|
||||||
|
|
||||||
|
if ((node = tpi_root.get_member("display_name")) != null) {
|
||||||
|
_tpi_display_name = node.get_string();
|
||||||
|
} else {
|
||||||
|
warning("content.third_party_invite.display_name is missing from a m.room.member event");
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((node = tpi_root.get_member("signed")) != null) {
|
||||||
|
var signed_root = node.get_object();
|
||||||
|
|
||||||
|
if ((node = signed_root.get_member("mxid")) != null) {
|
||||||
|
tpi_signed_mxid = node.get_string();
|
||||||
|
} else {
|
||||||
|
warning("content.third_party_invit.signed.mxid is missing from a m.room.member event");
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((node = signed_root.get_member("token")) != null) {
|
||||||
|
tpi_signed_token = node.get_string();
|
||||||
|
} else {
|
||||||
|
warning("content.third_party_invite.signed.token is missing from a m.room.member event");
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((node = signed_root.get_member("signatures")) != null) {
|
||||||
|
tpi_signature = node;
|
||||||
|
} else {
|
||||||
|
warning("content.third_party_invite.signed.signatures is missing from a m.room.member event");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
warning("content.third_party_invite.signed is missing from a m.room.member event");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((node = root.get_member("invite_room_state")) != null) {
|
||||||
|
var events = node.get_array();
|
||||||
|
|
||||||
|
if (events.get_length() > 0) {
|
||||||
|
_invite_room_state = null;
|
||||||
|
|
||||||
|
events.foreach_element((ary, idx, member_node) => {
|
||||||
|
try {
|
||||||
|
var evt = Matrix.Event.Base.new_from_json(
|
||||||
|
null, member_node);
|
||||||
|
|
||||||
|
_invite_room_state.prepend((Matrix.Event.State)evt);
|
||||||
|
} catch (GLib.Error e) {}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Chain up
|
// Chain up
|
||||||
base.from_json(json_data);
|
base.from_json(json_data);
|
||||||
}
|
}
|
||||||
@ -68,24 +223,26 @@ public class Matrix.Event.RoomMember : Matrix.Event.State {
|
|||||||
Json.Object root, content_root;
|
Json.Object root, content_root;
|
||||||
string? mship;
|
string? mship;
|
||||||
|
|
||||||
if (membership == RoomMembership.UNKNOWN) {
|
|
||||||
throw new Matrix.Error.UNKNOWN_VALUE(
|
|
||||||
"Unknown membership value cannot be added to a room member event");
|
|
||||||
}
|
|
||||||
|
|
||||||
root = json_data.get_object();
|
root = json_data.get_object();
|
||||||
|
|
||||||
content_root = _json_object_node_ensure_field(json_data,
|
content_root = _json_object_node_ensure_field(json_data,
|
||||||
"content",
|
"content",
|
||||||
Json.NodeType.OBJECT)
|
Json.NodeType.OBJECT)
|
||||||
.get_object();
|
.get_object();
|
||||||
|
|
||||||
root.set_string_member("state_key", state_key);
|
// I’m not sure if it is a good idea to set it here.
|
||||||
|
if (user_id != null) {
|
||||||
|
root.set_string_member("state_key", user_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (membership == RoomMembership.UNKNOWN) {
|
||||||
|
throw new Matrix.Error.UNKNOWN_VALUE(
|
||||||
|
"Unknown membership value cannot be added to a room member event");
|
||||||
|
}
|
||||||
|
|
||||||
mship = _g_enum_value_to_nick(typeof(Matrix.RoomMembership),
|
mship = _g_enum_value_to_nick(typeof(Matrix.RoomMembership),
|
||||||
membership);
|
membership);
|
||||||
|
|
||||||
if (mship != null) {
|
if (mship != null) {
|
||||||
content_root.set_string_member("membership", mship);
|
content_root.set_string_member("membership", mship);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -97,6 +254,65 @@ public class Matrix.Event.RoomMember : Matrix.Event.State {
|
|||||||
content_root.set_string_member("displayname", display_name);
|
content_root.set_string_member("displayname", display_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var tpi_root = new Json.Object();
|
||||||
|
|
||||||
|
if (_tpi_display_name != null) {
|
||||||
|
tpi_root.set_string_member("display_name", tpi_display_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
var tpi_signed_root = new Json.Object();
|
||||||
|
|
||||||
|
if (_tpi_signed_mxid != null) {
|
||||||
|
tpi_signed_root.set_string_member("mxid", tpi_signed_mxid);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_tpi_signed_token != null) {
|
||||||
|
tpi_signed_root.set_string_member("token", tpi_signed_token);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_tpi_signature != null) {
|
||||||
|
tpi_signed_root.set_member("signature", tpi_signature);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((tpi_signed_root.get_size() != 3)
|
||||||
|
&& (tpi_signed_root.get_size() != 0)) {
|
||||||
|
warning("3rd party invite data is not filled; ignoring");
|
||||||
|
|
||||||
|
tpi_signed_root = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((_tpi_display_name != null) && (tpi_signed_root.get_size() == 3)) {
|
||||||
|
var tpi_signed_node = new Json.Node(Json.NodeType.OBJECT);
|
||||||
|
tpi_signed_node.set_object(tpi_signed_root);
|
||||||
|
tpi_root.set_member("signed", tpi_signed_node);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tpi_root.get_size() == 2) {
|
||||||
|
var tpi_node = new Json.Node(Json.NodeType.OBJECT);
|
||||||
|
tpi_node.set_object(tpi_root);
|
||||||
|
content_root.set_member("third_party_invite", tpi_node);
|
||||||
|
} else if (tpi_root.get_size() != 0) {
|
||||||
|
warning("3rd party invite data is incomplete; ignoring");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_invite_room_state != null) {
|
||||||
|
var state_ary = new Json.Array();
|
||||||
|
|
||||||
|
foreach (var entry in _invite_room_state) {
|
||||||
|
var state_node = entry.get_stripped_node();
|
||||||
|
|
||||||
|
if (state_node != null) {
|
||||||
|
state_ary.add_element(state_node);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (state_ary.get_length() > 0) {
|
||||||
|
var state_node = new Json.Node(Json.NodeType.ARRAY);
|
||||||
|
state_node.set_array(state_ary);
|
||||||
|
root.set_member("invite_room_state", state_node);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
base.to_json(json_data);
|
base.to_json(json_data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -63,9 +63,8 @@ cb_room_member_event(MatrixClient *client,
|
|||||||
MatrixEventBase *event,
|
MatrixEventBase *event,
|
||||||
gpointer user_data)
|
gpointer user_data)
|
||||||
{
|
{
|
||||||
g_printerr("Incoming room member event from %s in room %s (%s)\n",
|
g_printerr("Incoming room member event from %s via room %s\n",
|
||||||
matrix_event_room_get_sender(MATRIX_EVENT_ROOM(event)),
|
matrix_event_room_member_get_user_id(MATRIX_EVENT_ROOM_MEMBER(event)),
|
||||||
matrix_event_room_get_room_id(MATRIX_EVENT_ROOM(event)),
|
|
||||||
room_id);
|
room_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user