/*
* 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 {
/**
* Abstract parent class for classes that can be saved to JSON.
*/
public abstract class JsonCompact {
public abstract Json.Node?
get_json_node()
throws Matrix.Error;
public string
get_json_data(out size_t datalen)
throws Matrix.Error
{
var generator = new Json.Generator();
generator.set_root(get_json_node());
return generator.to_data(out datalen);
}
}
/**
* Class to hold a filter.
*/
public class Filter : JsonCompact {
private List? _event_fields;
/**
* The event fields to include in the filtered events.
*/
public List? event_fields {
get {
return _event_fields;
}
set {
_event_fields = value.copy();
}
default = null;
}
/**
* The desired event format for the filtered events (e.g. for
* matrix_api_sync())
*/
public EventFormat event_format {
get; set;
default = Matrix.EventFormat.CLIENT;
}
/**
* A filtering ruleset for presence events.
*/
public FilterRules? presence_filter { get; set; default = null; }
/**
* A filtering ruleset for room events.
*/
public RoomFilter? room_filter { get; set; default = null; }
/**
* Get the filter as a JSON node.
*/
public override Json.Node?
get_json_node()
throws Matrix.Error
{
var builder = new Json.Builder();
builder.begin_object();
builder.set_member_name("event_fields");
builder.begin_array();
foreach (var entry in event_fields) {
builder.add_string_value(entry);
}
builder.end_array();
builder.set_member_name("event_format");
builder.add_string_value(
_g_enum_value_to_nick(typeof(EventFormat), event_format));
builder.set_member_name("presence");
builder.add_value(presence_filter.get_json_node());
builder.set_member_name("room");
builder.add_value(room_filter.get_json_node());
builder.end_object();
return builder.get_root();
}
}
/**
* Class to hold room filters.
*/
public class RoomFilter : JsonCompact {
/**
* If {{{true}}}, events for rooms that the user has left will
* be included in the filtered event list.
*/
public bool include_leave { get; set; default=true; }
/**
* Filtering rules for ephemeral events, i.e. events that are
* not recorded in the room history (typing notifications,
* receipts, etc.)
*/
public FilterRules? ephemeral { get; set; default = null; }
/**
* Filtering rules for state events.
*/
public FilterRules? state { get; set; default = null; }
/**
* Filtering rules for timeline events.
*/
public FilterRules? timeline { get; set; default = null; }
/**
* Get the room filters as a JSON node.
*/
public override Json.Node?
get_json_node()
throws Matrix.Error
{
var builder = new Json.Builder();
builder.begin_object();
builder.set_member_name("include_leave");
builder.add_boolean_value(include_leave);
if (ephemeral != null) {
builder.set_member_name("ephemeral");
builder.add_value(ephemeral.get_json_node());
}
if (state != null) {
builder.set_member_name("state");
builder.add_value(state.get_json_node());
}
if (timeline != null) {
builder.set_member_name("timeline");
builder.add_value(timeline.get_json_node());
}
builder.end_object();
return builder.get_root();
}
}
/**
* Class to hold filtering rules.
*/
public class FilterRules : JsonCompact {
private List? _types;
private List? _excluded_types;
private List? _senders;
private List? _excluded_senders;
private List? _rooms;
private List? _excluded_rooms;
/**
* The limit of the count of returned events.
*/
public uint limit { get; set; }
/**
* List of message types to include in the filtered result.
*/
public List? types {
get {
return _types;
}
set {
_types = value.copy();
}
default = null;
}
/**
* List of message types to exclude from the filtered
* result. A matching type will be excluded from the result
* even if it is listed in the types to include.
*/
public List? excluded_types {
get {
return _excluded_types;
}
set {
_excluded_types = value.copy();
}
default = null;
}
/**
* List of senders to include in the filtered results.
*/
public List? senders {
get {
return _senders;
}
set {
_senders = value.copy();
}
default = null;
}
/**
* List of senders to exclude from the filtered result. A
* matching sender will be excluded from the result even if it
* is listed in the senders to include.
*/
public List? excluded_senders {
get {
return _excluded_senders;
}
set {
_excluded_senders = value.copy();
}
default = null;
}
/**
* List of rooms to include in the filtered results.
*/
public List? rooms {
get {
return _rooms;
}
set {
_rooms = value.copy();
}
default = null;
}
/**
* List of rooms to exclude from the filtered result. A
* matching room will be excluded from the result even if it
* is listed in the rooms to include.
*/
public List? excluded_rooms {
get {
return _excluded_rooms;
}
set {
_excluded_rooms = value.copy();
}
default = null;
}
/**
* Get the filtering rules as a JSON node.
*/
public override Json.Node?
get_json_node()
throws Matrix.Error
{
var builder = new Json.Builder();
builder.begin_object();
builder.set_member_name("limit");
builder.add_int_value(limit);
if (rooms != null) {
builder.set_member_name("rooms");
builder.begin_array();
foreach (var entry in rooms) {
builder.add_string_value(entry);
}
builder.end_array();
}
if (excluded_rooms != null) {
builder.set_member_name("not_rooms");
builder.begin_array();
foreach (var entry in excluded_rooms) {
builder.add_string_value(entry);
}
builder.end_array();
}
if (senders != null) {
builder.set_member_name("senders");
builder.begin_array();
foreach (var entry in senders) {
builder.add_string_value(entry);
}
builder.end_array();
}
if (excluded_senders != null) {
builder.set_member_name("not_senders");
builder.begin_array();
foreach (var entry in excluded_senders) {
builder.add_string_value(entry);
}
builder.end_array();
}
if (types != null) {
builder.set_member_name("types");
builder.begin_array();
foreach (var entry in types) {
builder.add_string_value(entry);
}
builder.end_array();
}
if (excluded_types != null) {
builder.set_member_name("not_types");
builder.begin_array();
foreach(var entry in types) {
builder.add_string_value(entry);
}
builder.end_array();
}
builder.end_object();
return builder.get_root();
}
}
/**
* Class to hold 3rd party credential related data.
*/
public class @3PidCredential : JsonCompact {
/**
* The Identity Server used for this credential.
*/
public string? id_server { get; set; default = null; }
/**
* The session identifier got from the Identity Server.
*/
public string? session_id { get; set; default = null; }
/**
* The client secret that was used in the session with the
* Identity Server.
*/
public string? client_secret { get; set; default = null; }
/**
* Get 3rd party credential related data as a JSON node.
*/
public override Json.Node?
get_json_node()
throws Matrix.Error
{
if ((id_server == null)
|| (session_id == null)
|| (client_secret == null))
{
throw new Matrix.Error.INCOMPLETE(
"All fields of a 3PID credential must be filled!");
}
var builder = new Json.Builder();
builder.begin_object();
builder.set_member_name("id_server");
builder.add_string_value(id_server);
builder.set_member_name("session_id");
builder.add_string_value(session_id);
builder.set_member_name("client_secret");
builder.add_string_value(client_secret);
builder.end_object();
return builder.get_root();
}
}
/**
* Class to hold pusher related data.
*/
public class Pusher : JsonCompact {
/**
* A device display name.
*/
public string? device_display_name { get; set; default = null; }
/**
* An application display name.
*/
public string? app_display_name { get; set; default = null; }
/**
* An application ID.
*/
public string? app_id { get; set; default = null; }
/**
* If {{{true}}}, the homeserver should add another pusher
* with the given push key and app ID in addition to any
* others with different user IDs. Otherwise, the homeserver
* must remove any other pushers with the same App ID and
* pushkey for different users.
*/
public bool append { get; set; default = true; }
/**
* The kind of the pusher. {{{http}}} makes a pusher that
* sends HTTP pokes. {{{null}}} deletes the pusher.
*/
public string? kind { get; set; default = null; }
/**
* The preferred language for receiving notifications,
* e.g. {{{en}}} or {{{en-US}}}.
*/
public string? lang { get; set; default = null; }
/**
* A string that determines what set of device rules will be
* matched when evaluating push rules for this pusher. It is
* an arbitrary string. Multiple devices may use the same
* profile tag. It is advised that when an app's data is
* copied or restored to a different device, this value remain
* the same. Client apps should offer ways to change the
* profile tag, optionally copying rules from the old profile
* tag. Maximum length is 32 bytes. If the profile tag is
* longer than this, it will be truncated
*/
public string? profile_tag { get; set; default = null; }
/**
* A unique identifier for this pusher. The value you should
* use for this is the routing or destination address
* information for the notification, for example, the APNS
* token for APNS or the Registration ID for GCM. If your
* notification client has no such concept, use any unique
* identifier. Maximum length is 512 bytes. If pushkey is
* longer than this, it will be truncated
*/
public string? pushkey { get; set; default = null; }
/**
* a dictionary of information for the pusher implementation
* itself. For example, if kind is {{{http}}}, this should
* contain an {{{url}}} member, which is the URL to use to
* send notifications to. This function creates a deep copy of
* the data, so it can be freed after this call.
*/
public Json.Node? data { get; set; default = null; }
/**
* Get the pusher data as a JSON node.
*/
public override Json.Node?
get_json_node()
throws Matrix.Error
{
if ((device_display_name == null)
|| (app_display_name == null)
|| (app_id == null)
|| (data == null)
|| (kind == null)
|| (lang == null)
|| (profile_tag == null)
|| (pushkey == null)) {
throw new Matrix.Error.INCOMPLETE("Pusher data incomplete");
}
var builder = new Json.Builder();
builder.begin_object();
builder.set_member_name("device_display_name");
builder.add_string_value(device_display_name);
builder.set_member_name("app_display_name");
builder.add_string_value(app_display_name);
builder.set_member_name("app_id");
builder.add_string_value(app_id);
builder.set_member_name("append");
builder.add_boolean_value(append);
builder.set_member_name("kind");
builder.add_string_value(kind);
builder.set_member_name("lang");
builder.add_string_value(lang);
builder.set_member_name("profile_tag");
builder.add_string_value(profile_tag);
builder.set_member_name("pushkey");
builder.add_string_value(pushkey);
builder.set_member_name("data");
builder.add_value(data);
builder.end_object();
return builder.get_root();
}
}
/**
* Class to hold unsigned event data, like event age, redact
* reason or a transaction ID.
*/
public class UnsignedEventData : JsonCompact {
/**
* The age of the event, in seconds.
*/
public uint age { get; set; default = 0; }
/**
* The reason of redaction, if any.
*/
public string? redact_reason { get; set; default = null; }
/**
* The transaction ID of the message.
*/
public string? transaction_id { get; set; default = null; }
/**
* Create an UnsignedEventData object based
* on @param json_data.
*/
public
UnsignedEventData.from_json(Json.Node json_data)
requires(json_data.get_node_type() == Json.NodeType.OBJECT)
{
var root = json_data.get_object();
Json.Node node;
if ((node = root.get_member("age")) != null) {
age = (uint)node.get_int();
}
if ((node = root.get_member("redacted_because")) != null) {
redact_reason = node.get_string();
}
if ((node = root.get_member("transaction_id")) != null) {
transaction_id = node.get_string();
}
}
/**
* Get the unsigned event data as a JSON node.
*/
public override Json.Node?
get_json_node()
throws Matrix.Error
{
var builder = new Json.Builder();
builder.begin_object();
builder.set_member_name("age");
builder.add_int_value(age);
if (redact_reason != null) {
builder.set_member_name("redacted_because");
builder.add_string_value(redact_reason);
}
if (transaction_id != null) {
builder.set_member_name("transaction_id");
builder.add_string_value(transaction_id);
}
builder.end_object();
return builder.get_root();
}
}
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,
Json.NodeType field_type)
requires(node.get_node_type() == Json.NodeType.OBJECT)
{
var root = node.get_object();
Json.Node? new_node;
if ((new_node = root.get_member(field_name)) == null) {
new_node = new Json.Node(field_type);
switch (field_type) {
case Json.NodeType.OBJECT:
new_node.set_object(new Json.Object());
break;
case Json.NodeType.ARRAY:
new_node.set_array(new Json.Array());
break;
// Other node types don’t need special treatment
default:
break;
}
root.set_member(field_name, new_node);
}
return new_node;
}
public Json.Node?
_json_node_deep_copy(Json.Node? node)
{
Json.Node ret;
if (node == null) {
return null;
}
ret = new Json.Node(node.get_node_type());
switch (node.get_node_type()) {
case Json.NodeType.OBJECT:
var new_obj = new Json.Object();
node.get_object().foreach_member(
(old_obj, member_name, member_node) => {
new_obj.set_member(
member_name,
_json_node_deep_copy(member_node));
});
ret.set_object(new_obj);
break;
case Json.NodeType.ARRAY:
var new_ary = new Json.Array();
node.get_array().foreach_element(
(old_ary, idx, element_node) => {
new_ary.add_element(
_json_node_deep_copy(element_node));
});
break;
case Json.NodeType.VALUE:
ret.set_value(node.get_value());
break;
case Json.NodeType.NULL:
break;
}
return ret;
}
}