diff --git a/.gitignore b/.gitignore index 2ad0308..bda09ba 100644 --- a/.gitignore +++ b/.gitignore @@ -53,7 +53,6 @@ Makefile.in /src/matrix-http-client.c /src/namespace-info.vala /src/namespace-info.c -/src/matrix-event-room-power-levels.c /src/matrix-event-room-message-feedback.c /src/matrix-event-room-guest-access.c /src/matrix-event-room-redaction.c diff --git a/src/Makefile.am b/src/Makefile.am index 86e16c1..8bd5806 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -21,7 +21,6 @@ libmatrix_glib_0_0_la_VALA_SOURCES = \ matrix-client.vala \ matrix-http-api.vala \ matrix-http-client.vala \ - matrix-event-room-power-levels.vala \ matrix-event-room-message-feedback.vala \ matrix-event-room-guest-access.vala \ matrix-event-room-redaction.vala \ @@ -110,6 +109,7 @@ INST_H_SRC_FILES = \ matrix-event-room-join-rules.h \ matrix-event-room-canonical-alias.h \ matrix-event-room-create.h \ + matrix-event-room-power-levels.h \ matrix-event-typing.h \ matrix-event-receipt.h \ utils.h \ @@ -165,6 +165,7 @@ libmatrix_glib_0_0_la_SOURCES = \ matrix-event-room-join-rules.c \ matrix-event-room-canonical-alias.c \ matrix-event-room-create.c \ + matrix-event-room-power-levels.c \ matrix-profile.c \ matrix-room.c \ utils.c \ diff --git a/src/matrix-event-room-power-levels.c b/src/matrix-event-room-power-levels.c new file mode 100644 index 0000000..d77b0eb --- /dev/null +++ b/src/matrix-event-room-power-levels.c @@ -0,0 +1,799 @@ +/* + * 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 + * . + */ + +#include "matrix-event-room-power-levels.h" +#include "matrix-types.h" +#include "config.h" + +/** + * SECTION:matrix-event-room-power-levels + * @short_description: event to control power level assignments + * + * This is the default event handler for `m.room.power_levels` events. + * + * This event specifies the minimum level a user must have in order to perform a certain + * action. It also specifies the levels of each user in the room. If a `user_id` is in the + * users list, then that `user_id` has the associated power level. Otherwise they have the + * default level set in `users_default`. If `users_default` is not supplied, it is assumed to + * be 0. The level required to send a certain event is governed by the keys `events`, + * `state_default` and `events_default`. If an event type is specified in events, then the + * user must have at least the level specified in order to send that event. If the event type + * is not supplied, it defaults to `events_default` for message events and `state_default` for + * state events. + */ +enum { + PROP_0, + PROP_USERS_DEFAULT, + PROP_EVENTS_DEFAULT, + PROP_STATE_DEFAULT, + PROP_BAN, + PROP_KICK, + PROP_REDACT, + PROP_INVITE, + PROP_EVENT_LEVELS, + PROP_USER_LEVELS, + NUM_PROPERTIES +}; + +static GParamSpec *matrix_event_room_power_levels_properties[NUM_PROPERTIES]; + +typedef struct { + gint _users_default; + gint _events_default; + gint _state_default; + gint _ban; + gint _kick; + gint _redact; + gint _invite; + GHashTable* _event_levels; + GHashTable* _user_levels; +} MatrixEventRoomPowerLevelsPrivate; + +/** + * MatrixEventRoomPowerLevels: + */ +G_DEFINE_TYPE_WITH_PRIVATE(MatrixEventRoomPowerLevels, matrix_event_room_power_levels, MATRIX_EVENT_TYPE_STATE); + +static void +matrix_event_room_power_levels_real_from_json(MatrixEventBase *matrix_event_base, JsonNode *json_data, GError **error) +{ + MatrixEventRoomPowerLevelsPrivate *priv; + JsonObject *root; + JsonObject *content_root; + JsonNode *content_node; + JsonNode *node; + + g_return_if_fail (json_data != NULL); + + priv = matrix_event_room_power_levels_get_instance_private(MATRIX_EVENT_ROOM_POWER_LEVELS(matrix_event_base)); + root = json_node_get_object(json_data); + content_node = json_object_get_member(root, "content"); + content_root = json_node_get_object(content_node); + +#if DEBUG + if ((node = json_object_get_member(root, "state_key")) != NULL) { + const gchar *state_key = json_node_get_string(node); + + if ((state_key == NULL) || (*state_key == 0)) { + g_warning("state_key of a m.room.power_levels event is non-empty"); + } + } +#endif + + if ((node = json_object_get_member(content_root, "ban")) != NULL) { + priv->_ban = json_node_get_int(node); + } else { + g_warning("content.ban is missing from a m.room.power_levels event"); + } + + if ((node = json_object_get_member(content_root, "kick")) != NULL) { + priv->_kick = json_node_get_int(node); + } else { + g_warning("content.kick is missing from a m.room.power_levels event"); + } + + if ((node = json_object_get_member(content_root, "redact")) != NULL) { + priv->_redact = json_node_get_int(node); + } else { + g_warning("content.redact is missing from a m.room.power_levels event"); + } + + if ((node = json_object_get_member(content_root, "events_default")) != NULL) { + priv->_events_default = json_node_get_int(node); + } else { + g_warning("content.events_default is missing from a m.room.power_levels event"); + } + + if ((node = json_object_get_member(content_root, "state_default")) != NULL) { + priv->_state_default = json_node_get_int(node); + } else { + g_warning("content.state_default is missing from a m.room.power_levels event"); + } + + if ((node = json_object_get_member(content_root, "users_default")) != NULL) { + priv->_users_default = json_node_get_int(node); + } + + if ((node = json_object_get_member(content_root, "invite")) != NULL) { + priv->_invite = json_node_get_int(node); + } + + if ((node = json_object_get_member(content_root, "events")) != NULL) { + JsonObject *events_root; + JsonObjectIter iter; + const gchar *event_name; + JsonNode *event_node; + + g_hash_table_remove_all(priv->_event_levels); + + events_root = json_node_get_object(node); + json_object_iter_init(&iter, events_root); + + while (json_object_iter_next(&iter, &event_name, &event_node)) { + g_hash_table_insert(priv->_event_levels, g_strdup(event_name), GINT_TO_POINTER(json_node_get_int(event_node))); + } + } + + if ((node = json_object_get_member(content_root, "users")) != NULL) { + JsonObject *users_root; + JsonObjectIter iter; + const gchar *user_id; + JsonNode *user_node; + + g_hash_table_remove_all(priv->_user_levels); + + users_root = json_node_get_object(node); + json_object_iter_init(&iter, users_root); + + while (json_object_iter_next(&iter, &user_id, &user_node)) { + g_hash_table_insert(priv->_user_levels, g_strdup(user_id), GINT_TO_POINTER(json_node_get_int(user_node))); + } + } + + MATRIX_EVENT_BASE_CLASS(matrix_event_room_power_levels_parent_class)->from_json(matrix_event_base, json_data, error); +} + +static void +matrix_event_room_power_levels_real_to_json(MatrixEventBase *matrix_event_base, JsonNode *json_data, GError **error) +{ + MatrixEventRoomPowerLevelsPrivate *priv; + JsonObject *root; + JsonObject *content_root; + JsonObject *users_root; + JsonObject *events_root; + JsonNode *content_node; + JsonNode *users_node; + JsonNode *events_node; + GHashTableIter iter; + const gchar *state_key; + gpointer key; + gpointer value; + + g_return_if_fail (json_data != NULL); + + priv = matrix_event_room_power_levels_get_instance_private(MATRIX_EVENT_ROOM_POWER_LEVELS(matrix_event_base)); + root = json_node_get_object(json_data); + content_node = json_object_get_member(root, "content"); + content_root = json_node_get_object(content_node); + + state_key = matrix_event_state_get_state_key(MATRIX_EVENT_STATE(matrix_event_base)); + + if ((state_key == NULL) || (*state_key == 0)) { + g_set_error(error, MATRIX_ERROR, MATRIX_ERROR_INCOMPLETE, + "Won't generate a m.room.power_levels event with a non-empty state_key"); + + return; + } + + if (priv->_user_levels == NULL) { + g_set_error(error, MATRIX_ERROR, MATRIX_ERROR_INCOMPLETE, + "Won't create an m.room.power_levels event without a content.users key"); + + return; + } + + if (priv->_event_levels == NULL) { + g_set_error(error, MATRIX_ERROR, MATRIX_ERROR_INCOMPLETE, + "Won't create an m.room.power_levels event without a content.events key"); + + return; + } + + json_object_set_int_member(content_root, "ban", priv->_ban); + json_object_set_int_member(content_root, "kick", priv->_kick); + json_object_set_int_member(content_root, "redact", priv->_redact); + json_object_set_int_member(content_root, "state_default", priv->_state_default); + json_object_set_int_member(content_root, "events_default", priv->_events_default); + + users_root = json_object_new(); + users_node = json_node_new(JSON_NODE_OBJECT); + json_node_set_object(users_node, users_root); + + g_hash_table_iter_init(&iter, priv->_user_levels); + + while (g_hash_table_iter_next(&iter, &key, &value)) { + json_object_set_int_member(users_root, g_strdup(key), GPOINTER_TO_INT(value)); + } + + json_object_set_member(content_root, "users", users_node); + + events_root = json_object_new(); + events_node = json_node_new(JSON_NODE_OBJECT); + json_node_set_object(events_node, events_root); + + g_hash_table_iter_init(&iter, priv->_event_levels); + + while (g_hash_table_iter_next(&iter, &key, &value)) { + json_object_set_int_member(events_root, g_strdup(key), GPOINTER_TO_INT(value)); + } + + json_object_set_member(content_root, "events", events_node); + + MATRIX_EVENT_BASE_CLASS(matrix_event_room_power_levels_parent_class)->to_json(matrix_event_base, json_data, error); +} + +/** + * matrix_event_room_power_levels_set_user_level: + * @event: a #MatrixEventRoomPowerLevels + * @user_id: (transfer none) (not nullable): a Matrix ID + * @level: the level to set for @user_id + * + * Set the level of @user_id to @level in @event. + */ +void +matrix_event_room_power_levels_set_user_level(MatrixEventRoomPowerLevels *matrix_event_room_power_levels, const gchar *user_id, gint level) +{ + MatrixEventRoomPowerLevelsPrivate *priv; + + g_return_if_fail(matrix_event_room_power_levels != NULL); + g_return_if_fail(user_id != NULL); + + priv = matrix_event_room_power_levels_get_instance_private(matrix_event_room_power_levels); + + g_hash_table_insert(priv->_user_levels, g_strdup(user_id), GINT_TO_POINTER(level)); +} + +/** + * matrix_event_room_power_levels_set_event_level: + * @event: a #MatrixEventRoomPowerLevels + * @event_type: an event type name + * @level: the required level for sending @event_type messages + * + * Set the level required to send messages with type @event_type to @level. + */ +void +matrix_event_room_power_levels_set_event_level(MatrixEventRoomPowerLevels *matrix_event_room_power_levels, const gchar *event_type, gint level) +{ + MatrixEventRoomPowerLevelsPrivate *priv; + + g_return_if_fail(matrix_event_room_power_levels != NULL); + g_return_if_fail(event_type != NULL); + + priv = matrix_event_room_power_levels_get_instance_private(matrix_event_room_power_levels); + + g_hash_table_insert(priv->_event_levels, g_strdup(event_type), GINT_TO_POINTER(level)); +} + +/** + * matrix_event_room_power_levels_new: + * + * Create a new #MatrixEventRoomPowerLevels object + * + * Returns: (transfer full): a new #MatrixEventRoomPowerLevels object + */ +MatrixEventRoomPowerLevels * +matrix_event_room_power_levels_new(void) +{ + return (MatrixEventRoomPowerLevels *)matrix_event_state_construct(MATRIX_EVENT_TYPE_ROOM_POWER_LEVELS); +} + +/** + * matrix_event_room_power_levels_get_users_default: + * @event: a #MatrixEventRoomPowerLevels + * + * Get the default user level from @event. + * + * Returns: a power level + */ +gint +matrix_event_room_power_levels_get_users_default(MatrixEventRoomPowerLevels *matrix_event_room_power_levels) +{ + MatrixEventRoomPowerLevelsPrivate *priv; + + g_return_val_if_fail(matrix_event_room_power_levels != NULL, 0); + + priv = matrix_event_room_power_levels_get_instance_private(matrix_event_room_power_levels); + + return priv->_users_default; +} + +/** + * matrix_event_room_power_levels_set_users_default: + * @event: a #MatrixEventRoomPowerLevels + * @users_default: a power level + * + * Set the default user level in @event. + */ +void +matrix_event_room_power_levels_set_users_default(MatrixEventRoomPowerLevels *matrix_event_room_power_levels, gint users_default) +{ + MatrixEventRoomPowerLevelsPrivate *priv; + + g_return_if_fail(matrix_event_room_power_levels != NULL); + + priv = matrix_event_room_power_levels_get_instance_private(matrix_event_room_power_levels); + + if (priv->_users_default != users_default) { + priv->_users_default = users_default; + + g_object_notify_by_pspec((GObject *)matrix_event_room_power_levels, matrix_event_room_power_levels_properties[PROP_USERS_DEFAULT]); + } +} + +/** + * matrix_event_room_power_levels_get_events_default: + * @event: a #MatrixEventRoomPowerLevels + * + * Get the level required to send messages in @event, if not otherwise set with + * matrix_event_room_power_levels_set_event_level() + */ +gint +matrix_event_room_power_levels_get_events_default(MatrixEventRoomPowerLevels *matrix_event_room_power_levels) +{ + MatrixEventRoomPowerLevelsPrivate *priv; + + g_return_val_if_fail(matrix_event_room_power_levels != NULL, 0); + + priv = matrix_event_room_power_levels_get_instance_private(matrix_event_room_power_levels); + + return priv->_events_default; +} + +/** + * matrix_event_room_power_levels_set_events_default: + * @event: a #MatrixEventRoomPowerLevels + * @events_default: a power level + * + * Set the event level required for sending message events. This is the default value to be + * used for events that are not set with matrix_event_room_power_levels_set_event_level(). + */ +void +matrix_event_room_power_levels_set_events_default(MatrixEventRoomPowerLevels *matrix_event_room_power_levels, gint events_default) +{ + MatrixEventRoomPowerLevelsPrivate *priv; + + g_return_if_fail(matrix_event_room_power_levels != NULL); + + priv = matrix_event_room_power_levels_get_instance_private(matrix_event_room_power_levels); + + if (priv->_events_default != events_default) { + priv->_events_default = events_default; + + g_object_notify_by_pspec((GObject *)matrix_event_room_power_levels, matrix_event_room_power_levels_properties[PROP_EVENTS_DEFAULT]); + } +} + +gint +matrix_event_room_power_levels_get_state_default(MatrixEventRoomPowerLevels *matrix_event_room_power_levels) +{ + MatrixEventRoomPowerLevelsPrivate *priv; + + g_return_val_if_fail(matrix_event_room_power_levels != NULL, 0); + + priv = matrix_event_room_power_levels_get_instance_private(matrix_event_room_power_levels); + return priv->_state_default; +} + +void +matrix_event_room_power_levels_set_state_default(MatrixEventRoomPowerLevels *matrix_event_room_power_levels, gint state_default) +{ + MatrixEventRoomPowerLevelsPrivate *priv; + + g_return_if_fail(matrix_event_room_power_levels != NULL); + + priv = matrix_event_room_power_levels_get_instance_private(matrix_event_room_power_levels); + + if (priv->_state_default != state_default) { + priv->_state_default = state_default; + + g_object_notify_by_pspec((GObject *)matrix_event_room_power_levels, matrix_event_room_power_levels_properties[PROP_STATE_DEFAULT]); + } +} + +gint +matrix_event_room_power_levels_get_ban(MatrixEventRoomPowerLevels *matrix_event_room_power_levels) +{ + MatrixEventRoomPowerLevelsPrivate *priv; + + g_return_val_if_fail(matrix_event_room_power_levels != NULL, 0); + + priv = matrix_event_room_power_levels_get_instance_private(matrix_event_room_power_levels); + + return priv->_ban; +} + +void +matrix_event_room_power_levels_set_ban(MatrixEventRoomPowerLevels *matrix_event_room_power_levels, gint ban) +{ + MatrixEventRoomPowerLevelsPrivate *priv; + + g_return_if_fail(matrix_event_room_power_levels != NULL); + + priv = matrix_event_room_power_levels_get_instance_private(matrix_event_room_power_levels); + + if (priv->_ban != ban) { + priv->_ban = ban; + + g_object_notify_by_pspec((GObject *) matrix_event_room_power_levels, matrix_event_room_power_levels_properties[PROP_BAN]); + } +} + +gint +matrix_event_room_power_levels_get_kick(MatrixEventRoomPowerLevels *matrix_event_room_power_levels) +{ + MatrixEventRoomPowerLevelsPrivate *priv; + + g_return_val_if_fail(matrix_event_room_power_levels != NULL, 0); + + priv = matrix_event_room_power_levels_get_instance_private(matrix_event_room_power_levels); + + return priv->_kick; +} + +void +matrix_event_room_power_levels_set_kick(MatrixEventRoomPowerLevels *matrix_event_room_power_levels, gint kick) +{ + MatrixEventRoomPowerLevelsPrivate *priv; + + g_return_if_fail(matrix_event_room_power_levels != NULL); + + priv = matrix_event_room_power_levels_get_instance_private(matrix_event_room_power_levels); + + if (priv->_kick != kick) { + priv->_kick = kick; + + g_object_notify_by_pspec((GObject *)matrix_event_room_power_levels, matrix_event_room_power_levels_properties[PROP_KICK]); + } +} + +gint +matrix_event_room_power_levels_get_redact(MatrixEventRoomPowerLevels *matrix_event_room_power_levels) +{ + MatrixEventRoomPowerLevelsPrivate *priv; + + g_return_val_if_fail(matrix_event_room_power_levels != NULL, 0); + + priv = matrix_event_room_power_levels_get_instance_private(matrix_event_room_power_levels); + + return priv->_redact; +} + +void +matrix_event_room_power_levels_set_redact(MatrixEventRoomPowerLevels *matrix_event_room_power_levels, gint redact) +{ + MatrixEventRoomPowerLevelsPrivate *priv; + + g_return_if_fail(matrix_event_room_power_levels != NULL); + + priv = matrix_event_room_power_levels_get_instance_private(matrix_event_room_power_levels); + + if (priv->_redact != redact) { + priv->_redact = redact; + + g_object_notify_by_pspec((GObject *)matrix_event_room_power_levels, matrix_event_room_power_levels_properties[PROP_REDACT]); + } +} + +gint +matrix_event_room_power_levels_get_invite(MatrixEventRoomPowerLevels *matrix_event_room_power_levels) +{ + MatrixEventRoomPowerLevelsPrivate *priv; + + g_return_val_if_fail(matrix_event_room_power_levels != NULL, 0); + + priv = matrix_event_room_power_levels_get_instance_private(matrix_event_room_power_levels); + + return priv->_invite; +} + +void +matrix_event_room_power_levels_set_invite(MatrixEventRoomPowerLevels *matrix_event_room_power_levels, gint invite) +{ + MatrixEventRoomPowerLevelsPrivate *priv; + + g_return_if_fail(matrix_event_room_power_levels != NULL); + + priv = matrix_event_room_power_levels_get_instance_private(matrix_event_room_power_levels); + + if (priv->_invite != invite) { + priv->_invite = invite; + + g_object_notify_by_pspec((GObject *)matrix_event_room_power_levels, matrix_event_room_power_levels_properties[PROP_INVITE]); + } +} + +/** + * matrix_event_room_power_levels_get_event_levels: + * @event: a #MatrixEventRoomPowerLevels + * + * Returns: (transfer none): the list of event type power level requirements + */ +GHashTable * +matrix_event_room_power_levels_get_event_levels(MatrixEventRoomPowerLevels *matrix_event_room_power_levels) +{ + MatrixEventRoomPowerLevelsPrivate *priv; + + g_return_val_if_fail(matrix_event_room_power_levels != NULL, NULL); + + priv = matrix_event_room_power_levels_get_instance_private(matrix_event_room_power_levels); + + return priv->_event_levels; +} + +/** + * matrix_event_room_power_levels_get_user_levels: + * @event: a #MatrixEventRoomPowerLevels + * + * Get the table of individual user levels from @event. + * + * The returned value is owned by @event and should not be freed. + * + * The returned #GHashTable has user IDs as keys. The value are integer power levels + * converted to pointers; use GPOINTER_TO_INT() to convert them to actual power levels. + * + * Returns: (transfer none) (nullable): a table of user levels + */ +GHashTable * +matrix_event_room_power_levels_get_user_levels(MatrixEventRoomPowerLevels *matrix_event_room_power_levels) +{ + MatrixEventRoomPowerLevelsPrivate *priv; + + g_return_val_if_fail(matrix_event_room_power_levels != NULL, NULL); + + priv = matrix_event_room_power_levels_get_instance_private(matrix_event_room_power_levels); + + return priv->_user_levels; +} + +static void +matrix_event_room_power_levels_finalize(GObject *gobject) +{ + MatrixEventRoomPowerLevelsPrivate *priv = matrix_event_room_power_levels_get_instance_private(MATRIX_EVENT_ROOM_POWER_LEVELS(gobject)); + + g_hash_table_unref(priv->_event_levels); + g_hash_table_unref(priv->_user_levels); + + G_OBJECT_CLASS(matrix_event_room_power_levels_parent_class)->finalize(gobject); +} + +static void +matrix_event_room_power_levels_get_property(GObject *gobject, guint property_id, GValue *value, GParamSpec *pspec) +{ + MatrixEventRoomPowerLevels *matrix_event_room_power_levels = MATRIX_EVENT_ROOM_POWER_LEVELS(gobject); + + switch (property_id) { + case PROP_USERS_DEFAULT: + g_value_set_int(value, matrix_event_room_power_levels_get_users_default(matrix_event_room_power_levels)); + + break; + case PROP_EVENTS_DEFAULT: + g_value_set_int(value, matrix_event_room_power_levels_get_events_default(matrix_event_room_power_levels)); + + break; + case PROP_STATE_DEFAULT: + g_value_set_int(value, matrix_event_room_power_levels_get_state_default(matrix_event_room_power_levels)); + + break; + case PROP_BAN: + g_value_set_int(value, matrix_event_room_power_levels_get_ban(matrix_event_room_power_levels)); + + break; + case PROP_KICK: + g_value_set_int(value, matrix_event_room_power_levels_get_kick(matrix_event_room_power_levels)); + + break; + case PROP_REDACT: + g_value_set_int(value, matrix_event_room_power_levels_get_redact(matrix_event_room_power_levels)); + + break; + case PROP_INVITE: + g_value_set_int(value, matrix_event_room_power_levels_get_invite(matrix_event_room_power_levels)); + + break; + case PROP_EVENT_LEVELS: + g_value_set_boxed(value, matrix_event_room_power_levels_get_event_levels(matrix_event_room_power_levels)); + + break; + case PROP_USER_LEVELS: + g_value_set_boxed(value, matrix_event_room_power_levels_get_user_levels(matrix_event_room_power_levels)); + + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(gobject, property_id, pspec); + + break; + } +} + +static void +matrix_event_room_power_levels_set_property(GObject *gobject, guint property_id, const GValue *value, GParamSpec *pspec) +{ + MatrixEventRoomPowerLevels *matrix_event_room_power_levels = MATRIX_EVENT_ROOM_POWER_LEVELS(gobject); + + switch (property_id) { + case PROP_USERS_DEFAULT: + matrix_event_room_power_levels_set_users_default(matrix_event_room_power_levels, g_value_get_int(value)); + + break; + case PROP_EVENTS_DEFAULT: + matrix_event_room_power_levels_set_events_default(matrix_event_room_power_levels, g_value_get_int(value)); + + break; + case PROP_STATE_DEFAULT: + matrix_event_room_power_levels_set_state_default(matrix_event_room_power_levels, g_value_get_int(value)); + + break; + case PROP_BAN: + matrix_event_room_power_levels_set_ban(matrix_event_room_power_levels, g_value_get_int(value)); + + break; + case PROP_KICK: + matrix_event_room_power_levels_set_kick(matrix_event_room_power_levels, g_value_get_int(value)); + + break; + case PROP_REDACT: + matrix_event_room_power_levels_set_redact(matrix_event_room_power_levels, g_value_get_int(value)); + + break; + case PROP_INVITE: + matrix_event_room_power_levels_set_invite(matrix_event_room_power_levels, g_value_get_int(value)); + + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(gobject, property_id, pspec); + break; + } +} + +static void +matrix_event_room_power_levels_class_init(MatrixEventRoomPowerLevelsClass *klass) +{ + ((MatrixEventBaseClass *)klass)->from_json = matrix_event_room_power_levels_real_from_json; + ((MatrixEventBaseClass *)klass)->to_json = matrix_event_room_power_levels_real_to_json; + G_OBJECT_CLASS(klass)->get_property = matrix_event_room_power_levels_get_property; + G_OBJECT_CLASS(klass)->set_property = matrix_event_room_power_levels_set_property; + G_OBJECT_CLASS(klass)->finalize = matrix_event_room_power_levels_finalize; + + /** + * MatrixEventRoomPowerLevels:users-default: + * + * The default power level for every user in the room, unless their user ID is mentioned + * in the #MatrixEventRoomPowerLevels:users property. + */ + matrix_event_room_power_levels_properties[PROP_USERS_DEFAULT] = g_param_spec_int( + "users-default", "users-default", "users-default", + G_MININT, G_MAXINT, 0, + G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE); + g_object_class_install_property(G_OBJECT_CLASS(klass), PROP_USERS_DEFAULT, matrix_event_room_power_levels_properties[PROP_USERS_DEFAULT]); + + /** + * MatrixEventRoomPowerLevels:events-default: + * + * The default level required to send message events. Can be overridden with values in + * the #MatrixEventRoomPowerLevels:events property. + */ + matrix_event_room_power_levels_properties[PROP_EVENTS_DEFAULT] = g_param_spec_int( + "events-default", "events-default", "events-default", + G_MININT, G_MAXINT, 0, + G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE); + g_object_class_install_property(G_OBJECT_CLASS(klass), PROP_EVENTS_DEFAULT, matrix_event_room_power_levels_properties[PROP_EVENTS_DEFAULT]); + + /** + * MatrixEventRoomPowerLevels:state-default: + * + * The default level required to send state events. Can be overridden with values in the + * #MatrixEventRoomPowerLevels:events property. + */ + matrix_event_room_power_levels_properties[PROP_STATE_DEFAULT] = g_param_spec_int( + "state-default", "state-default", "state-default", + G_MININT, G_MAXINT, 10, + G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE); + g_object_class_install_property(G_OBJECT_CLASS(klass), PROP_STATE_DEFAULT, matrix_event_room_power_levels_properties[PROP_STATE_DEFAULT]); + + /** + * MatrixEventRoomPowerLevels:ban: + * + * The level required to ban a user. + */ + matrix_event_room_power_levels_properties[PROP_BAN] = g_param_spec_int( + "ban", "ban", "ban", + G_MININT, G_MAXINT, 5, + G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE); + g_object_class_install_property(G_OBJECT_CLASS(klass), PROP_BAN, matrix_event_room_power_levels_properties[PROP_BAN]); + + /** + * MatrixEventRoomPowerLevels:kick: + * + * The level required to kick a user. + */ + matrix_event_room_power_levels_properties[PROP_KICK] = g_param_spec_int( + "kick", "kick", "kick", + G_MININT, G_MAXINT, 5, + G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE); + g_object_class_install_property(G_OBJECT_CLASS(klass), PROP_KICK, matrix_event_room_power_levels_properties[PROP_KICK]); + + /** + * MatrixEventRoomPowerLevels:redact: + * + * The level required to redact an event. + */ + matrix_event_room_power_levels_properties[PROP_REDACT] = g_param_spec_int( + "redact", "redact", "redact", + G_MININT, G_MAXINT, 20, + G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE); + g_object_class_install_property(G_OBJECT_CLASS(klass), PROP_REDACT, matrix_event_room_power_levels_properties[PROP_REDACT]); + + /** + * MatrixEventRoomPowerLevels:invite: + * + * The level required to invite someone. + */ + matrix_event_room_power_levels_properties[PROP_INVITE] = g_param_spec_int( + "invite", "invite", "invite", + G_MININT, G_MAXINT, 0, + G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE); + g_object_class_install_property(G_OBJECT_CLASS(klass), PROP_INVITE, matrix_event_room_power_levels_properties[PROP_INVITE]); + + /** + * MatrixEventRoomPowerLevels:event-levels: + * + * A hash map to store the required level to send specific events. + */ + matrix_event_room_power_levels_properties[PROP_EVENT_LEVELS] = g_param_spec_boxed( + "event-levels", "event-levels", "event-levels", + G_TYPE_HASH_TABLE, + G_PARAM_STATIC_STRINGS | G_PARAM_READABLE); + g_object_class_install_property(G_OBJECT_CLASS(klass), PROP_EVENT_LEVELS, matrix_event_room_power_levels_properties[PROP_EVENT_LEVELS]); + + /** + * MatrixEventRoomPowerLevels:user-levels: + * + * A hash map to store current level for individual users. + */ + matrix_event_room_power_levels_properties[PROP_USER_LEVELS] = g_param_spec_boxed( + "user-levels", "user-levels", "user-levels", + G_TYPE_HASH_TABLE, + G_PARAM_STATIC_STRINGS | G_PARAM_READABLE); + g_object_class_install_property(G_OBJECT_CLASS(klass), PROP_USER_LEVELS, matrix_event_room_power_levels_properties[PROP_USER_LEVELS]); +} + +static void +matrix_event_room_power_levels_init(MatrixEventRoomPowerLevels *matrix_event_room_power_levels) +{ + MatrixEventRoomPowerLevelsPrivate *priv = matrix_event_room_power_levels_get_instance_private(matrix_event_room_power_levels); + + priv->_users_default = 0; + priv->_events_default = 0; + priv->_state_default = 10; + priv->_ban = 5; + priv->_kick = 5; + priv->_redact = 20; + priv->_invite = 0; + priv->_event_levels = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL); + priv->_user_levels = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL); +} diff --git a/src/matrix-event-room-power-levels.h b/src/matrix-event-room-power-levels.h new file mode 100644 index 0000000..ca1b1f4 --- /dev/null +++ b/src/matrix-event-room-power-levels.h @@ -0,0 +1,56 @@ +/* + * 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 + * . + */ + +#ifndef __MATRIX_GLIB_SDK_EVENT_ROOM_POWER_LEVELS_H__ +# define __MATRIX_GLIB_SDK_EVENT_ROOM_POWER_LEVELS_H__ + +# include +# include "matrix-event-state-base.h" + +G_BEGIN_DECLS + +#define MATRIX_EVENT_TYPE_ROOM_POWER_LEVELS (matrix_event_room_power_levels_get_type ()) +G_DECLARE_DERIVABLE_TYPE(MatrixEventRoomPowerLevels, matrix_event_room_power_levels, MATRIX_EVENT, ROOM_POWER_LEVELS, MatrixEventState) + +struct _MatrixEventRoomPowerLevelsClass { + MatrixEventStateClass parent_class; +}; + +MatrixEventRoomPowerLevels *matrix_event_room_power_levels_new(void); +void matrix_event_room_power_levels_set_user_level(MatrixEventRoomPowerLevels *event, const gchar *user_id, gint level); +void matrix_event_room_power_levels_set_event_level(MatrixEventRoomPowerLevels *event, const gchar *event_type, gint level); +gint matrix_event_room_power_levels_get_users_default(MatrixEventRoomPowerLevels *event); +void matrix_event_room_power_levels_set_users_default(MatrixEventRoomPowerLevels *event, gint users_default); +gint matrix_event_room_power_levels_get_events_default(MatrixEventRoomPowerLevels *event); +void matrix_event_room_power_levels_set_events_default(MatrixEventRoomPowerLevels *event, gint events_default); +gint matrix_event_room_power_levels_get_state_default(MatrixEventRoomPowerLevels *event); +void matrix_event_room_power_levels_set_state_default(MatrixEventRoomPowerLevels *event, gint state_default); +gint matrix_event_room_power_levels_get_ban(MatrixEventRoomPowerLevels *event); +void matrix_event_room_power_levels_set_ban(MatrixEventRoomPowerLevels *event, gint ban); +gint matrix_event_room_power_levels_get_kick(MatrixEventRoomPowerLevels *event); +void matrix_event_room_power_levels_set_kick(MatrixEventRoomPowerLevels *event, gint kick); +gint matrix_event_room_power_levels_get_redact(MatrixEventRoomPowerLevels *event); +void matrix_event_room_power_levels_set_redact(MatrixEventRoomPowerLevels *event, gint redact); +gint matrix_event_room_power_levels_get_invite(MatrixEventRoomPowerLevels *event); +void matrix_event_room_power_levels_set_invite(MatrixEventRoomPowerLevels *event, gint invite); +GHashTable *matrix_event_room_power_levels_get_event_levels(MatrixEventRoomPowerLevels *event); +GHashTable *matrix_event_room_power_levels_get_user_levels(MatrixEventRoomPowerLevels *event); + +G_END_DECLS + +#endif /* __MATRIX_GLIB_SDK_EVENT_ROOM_POWER_LEVELS_H__ */ diff --git a/src/matrix-event-room-power-levels.vala b/src/matrix-event-room-power-levels.vala deleted file mode 100644 index 49b26f6..0000000 --- a/src/matrix-event-room-power-levels.vala +++ /dev/null @@ -1,232 +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 - * . - */ - -/** - * Class to handle m.room.power_levels event - * - * This event specifies the minimum level a user must have in order to - * perform a certain action. It also specifies the levels of each user - * in the room. If a user_id is in the users list, then that user_id - * has the associated power level. Otherwise they have the default - * level users_default. If users_default is not supplied, it is - * assumed to be 0. The level required to send a certain event is - * governed by events, state_default and events_default. If an event - * type is specified in events, then the user must have at least the - * level specified in order to send that event. If the event type is - * not supplied, it defaults to events_default for Message Events and - * state_default for State Events. - */ -public class Matrix.Event.RoomPowerLevels : Matrix.Event.State { - /** - * The default power level for every user in the room, unless - * their user_id is mentioned in the users key. - */ - public int users_default { get; set; default = 0; } - - /** - * The default level required to send message events. Can be - * overridden by the events key. - */ - public int events_default { get; set; default = 0; } - - /** - * The default level required to send state events. Can be - * overridden by the events key. - */ - public int state_default { get; set; default = 10; } - - /** - * The level required to ban a user. - */ - public int ban { get; set; default = 5; } - - /** - * The level required to kick a user. - */ - public int kick { get; set; default = 5; } - - /** - * The level required to redact an event. - */ - public int redact { get; set; default = 20; } - - /** - * The level required to invite someone. - */ - public int invite { get; set; default = 0; } - - /** - * A hash map to store the required level to send specific events. - */ - public HashTable event_levels { - get { - return _event_levels; - } - } - - /** - * A hash map to store current level for individual users. - */ - public HashTable user_levels { - get { - return _user_levels; - } - } - - private HashTable _event_levels = - new HashTable(str_hash, str_equal); - - private HashTable _user_levels = - new HashTable(str_hash, str_equal); - - protected override void - from_json(Json.Node json_data) - throws Matrix.Error - { - var root = json_data.get_object(); - var content_root = root.get_member("content").get_object(); - Json.Node? node = null; - - if (Config.DEBUG && ((node = root.get_member("content")) != null)) { - if (node.get_string() != "") { - warning("state_key of a m.room.power_levels event is non-empty"); - } - } - - if ((node = content_root.get_member("ban")) != null) { - _ban = (int)node.get_int(); - } else { - warning("content.ban is missing from a m.room.power_levels event"); - } - - if ((node = content_root.get_member("kick")) != null) { - _kick = (int)node.get_int(); - } else { - warning("content.kick is missing from a m.room.power_levels event"); - } - - if ((node = content_root.get_member("redact")) != null) { - _redact = (int)node.get_int(); - } else { - warning("content.redact is missing from a m.room.power_levels event"); - } - - if ((node = content_root.get_member("events_default")) != null) { - _events_default = (int)node.get_int(); - } else { - warning("content.events_default is missing from a m.room.power_levels event"); - } - - if ((node = content_root.get_member("state_default")) != null) { - _state_default = (int)node.get_int(); - } else { - warning("content.state_default is missing from a m.room.power_levels event"); - } - - if ((node = content_root.get_member("users_default")) != null) { - _users_default = (int)node.get_int(); - } - - if ((node = content_root.get_member("invite")) != null) { - _invite = (int)node.get_int(); - } - - if ((node = content_root.get_member("events")) != null) { - _event_levels.remove_all(); - - node.get_object().foreach_member((obj, event_name, event_node) => { - _event_levels[event_name] = (int)event_node.get_int(); - }); - } - - if ((node = content_root.get_member("users")) != null) { - _user_levels.remove_all(); - - node.get_object().foreach_member((obj, user_id, user_node) => { - _user_levels[user_id] = (int)user_node.get_int(); - }); - } - - base.from_json(json_data); - } - - protected override void - to_json(Json.Node json_data) - throws Matrix.Error - { - var content_root = json_data.get_object() - .get_member("content").get_object(); - - if (_state_key != "") { - throw new Matrix.Error.INCOMPLETE( - "Won't generate a m.room.power_levels event with a non-empty state_key"); - } - - if (_user_levels == null) { - throw new Matrix.Error.INCOMPLETE( - "Won't create an m.room.power_levels event without a content.users key"); - } - - if (_event_levels == null) { - throw new Matrix.Error.INCOMPLETE( - "Won't create an m.room.power_levels event without a content.events key"); - } - - content_root.set_int_member("ban", _ban); - content_root.set_int_member("kick", _kick); - content_root.set_int_member("redact", _redact); - content_root.set_int_member("state_default", _state_default); - content_root.set_int_member("events_default", _events_default); - - var user_obj = new Json.Object(); - var user_node = new Json.Node(Json.NodeType.OBJECT); - user_node.set_object(user_obj); - - _user_levels.foreach( - (key, value) => { - user_obj.set_int_member(key, value); - }); - - content_root.set_member("users", user_node); - - var events_obj = new Json.Object(); - var events_node = new Json.Node(Json.NodeType.OBJECT); - events_node.set_object(events_obj); - - _event_levels.foreach( - (key, value) => { - events_obj.set_int_member(key, value); - }); - - content_root.set_member("users", events_node); - - base.to_json(json_data); - } - - public void - set_user_level(string user_id, int level) - { - _user_levels[user_id] = level; - } - - public void - set_event_level(string event_type, int level) - { - _event_levels[event_type] = level; - } -} diff --git a/src/matrix-event-types.c b/src/matrix-event-types.c index f45947c..acf16af 100644 --- a/src/matrix-event-types.c +++ b/src/matrix-event-types.c @@ -32,6 +32,7 @@ #include "matrix-event-room-join-rules.h" #include "matrix-event-room-canonical-alias.h" #include "matrix-event-room-create.h" +#include "matrix-event-room-power-levels.h" #include "matrix-event-call-answer.h" #include "matrix-event-call-hangup.h" #include "matrix-event-call-invite.h" diff --git a/vapi/c-api.vapi b/vapi/c-api.vapi index 1975499..51387c3 100644 --- a/vapi/c-api.vapi +++ b/vapi/c-api.vapi @@ -798,6 +798,29 @@ namespace Matrix { to_json(Json.Node json_data) throws Matrix.Error; } + + [CCode (cheader_filename = "matrix-event-room-power-levels.h")] + public class RoomPowerLevels : State { + public int users_default { get; set; default = 0; } + public int events_default { get; set; default = 0; } + public int state_default { get; set; default = 10; } + public int ban { get; set; default = 5; } + public int kick { get; set; default = 5; } + public int redact { get; set; default = 20; } + public int invite { get; set; default = 0; } + public GLib.HashTable event_levels { get; } + public GLib.HashTable user_levels { get; } + + protected override void from_json(Json.Node json_data) + throws Matrix.Error; + + protected override void to_json(Json.Node json_data) + throws Matrix.Error; + + public void set_user_level(string user_id, int level); + + public void set_event_level(string event_type, int level); + } } [CCode (gir_namespace = "MatrixMessage", gir_version = "0.0")]