Move MatrixAPI to an interface

This commit is contained in:
Gergely Polonkai 2015-12-11 14:15:42 +01:00
parent bace727576
commit b6c4c8f26d
8 changed files with 1041 additions and 171 deletions

View File

@ -55,6 +55,7 @@ AC_PATH_PROG([GLIB_MKENUMS], [glib-mkenums])
PKG_CHECK_MODULES([GLIB], [glib-2.0 >= 2.38]) PKG_CHECK_MODULES([GLIB], [glib-2.0 >= 2.38])
PKG_CHECK_MODULES([GOBJECT], [gobject-2.0 >= 2.38]) PKG_CHECK_MODULES([GOBJECT], [gobject-2.0 >= 2.38])
PKG_CHECK_MODULES([SOUP], [libsoup-2.4]) PKG_CHECK_MODULES([SOUP], [libsoup-2.4])
PKG_CHECK_MODULES([JSON], [json-glib-1.0])
LIBMATRIX_GLIB_LIBS='$(top_builddir)/src/libmatrix-glib-$(MATRIX_GLIB_API_VERSION).la' LIBMATRIX_GLIB_LIBS='$(top_builddir)/src/libmatrix-glib-$(MATRIX_GLIB_API_VERSION).la'
AC_SUBST(LIBMATRIX_GLIB_LIBS) AC_SUBST(LIBMATRIX_GLIB_LIBS)

View File

@ -19,9 +19,9 @@
<chapter> <chapter>
<title>Matrix Client</title> <title>Matrix Client</title>
<xi:include href="xml/matrix-client.xml"/> <xi:include href="xml/matrix-client.xml"/>
<xi:include href="xml/matrix-api.xml"/> <xi:include href="xml/matrix-http-api.xml"/>
<xi:include href="xml/matrix-version.xml"/> <xi:include href="xml/matrix-version.xml"/>
<xi:include href="xml/matrix-api.xml"/>
</chapter> </chapter>
<chapter id="object-tree"> <chapter id="object-tree">
<title>Object Hierarchy</title> <title>Object Hierarchy</title>

View File

@ -18,19 +18,55 @@ matrix_client_get_type
<SECTION> <SECTION>
<FILE>matrix-api</FILE> <FILE>matrix-api</FILE>
<TITLE>MatrixAPI</TITLE> <TITLE>MatrixAPI</TITLE>
MatrixAPICallback
matrix_api_ban_user
matrix_api_create_room
matrix_api_event_stream
matrix_api_get_emote_body
matrix_api_get_html_body
matrix_api_get_text_body
matrix_api_get_room_name
matrix_api_get_room_state
matrix_api_get_room_topic
matrix_api_initial_sync
matrix_api_invite_user
matrix_api_join_room
matrix_api_kick_user
matrix_api_leave_room
matrix_api_login
matrix_api_register_account
matrix_api_send_emote
matrix_api_send_message
matrix_api_send_message_event
matrix_api_send_state_event
matrix_api_set_membership
<SUBSECTION Standard> <SUBSECTION Standard>
MatrixAPI MatrixAPI
MatrixAPIClass MatrixAPIInterface
MATRIX_IS_API
MATRIX_IS_API_CLASS
MATRIX_API
MATRIX_API_CLASS
MATRIX_API_GET_CLASS
MATRIX_TYPE_API MATRIX_TYPE_API
MATRIX_API
MATRIX_IS_API
MATRIX_API_GET_IFACE
MatrixApiPrivate MatrixApiPrivate
matrix_api_get_type matrix_api_get_type
</SECTION> </SECTION>
<SECTION>
<FILE>matrix-http-api</FILE>
matrix_http_api_get_validate_certificate
matrix_http_api_set_validate_certificate
<SUBSECTION Standard>
MatrixHTTPAPI
MatrixHTTPAPIClass
MATRIX_TYPE_HTTP_API
MATRIX_HTTP_API
MATRIX_HTTP_API_CLASS
MATRIX_IS_HTTP_API
MATRIX_IS_HTTP_API_CLASS
MATRIX_HTTP_API_GET_CLASS
matrix_http_api_get_type
</SECTION>
<SECTION> <SECTION>
<FILE>matrix-version</FILE> <FILE>matrix-version</FILE>
MATRIX_GLIB_MAJOR_VERSION MATRIX_GLIB_MAJOR_VERSION

View File

@ -5,6 +5,7 @@ lib_LTLIBRARIES = libmatrix-glib-0.0.la
INST_H_SRC_FILES = \ INST_H_SRC_FILES = \
matrix-client.h \ matrix-client.h \
matrix-api.h \ matrix-api.h \
matrix-http-api.h \
$(NULL) $(NULL)
INST_H_BUILT_FILES = matrix-version.h INST_H_BUILT_FILES = matrix-version.h
@ -13,12 +14,13 @@ libmatrix_glib_0_0_la_SOURCES = \
matrix-client.c \ matrix-client.c \
matrix-version.c \ matrix-version.c \
matrix-api.c \ matrix-api.c \
matrix-http-api.c \
$(INST_H_SRC_FILES) \ $(INST_H_SRC_FILES) \
$(INST_H_BUILT_FILES) \ $(INST_H_BUILT_FILES) \
$(NULL) $(NULL)
libmatrix_glib_0_0_la_CFLAGS = $(GLIB_CFLAGS) $(GOBJECT_CFLAGS) $(SOUP_CFLAGS) libmatrix_glib_0_0_la_CFLAGS = $(GLIB_CFLAGS) $(GOBJECT_CFLAGS) $(SOUP_CFLAGS) $(JSON_CFLAGS)
libmatrix_glib_0_0_la_LIBADD = $(GLIB_LIBS) $(GOBJECT_LIBS) $(SOUP_LIBS) libmatrix_glib_0_0_la_LIBADD = $(GLIB_LIBS) $(GOBJECT_LIBS) $(SOUP_LIBS) $(JSON_LIBS)
libmatrix_glib_0_0_la_DEPENDENCIES = libmatrix_glib_0_0_la_DEPENDENCIES =
CLEANFILES = CLEANFILES =
@ -29,7 +31,7 @@ MatrixGlib-$(MATRIX_GLIB_API_VERSION).gir: libmatrix-glib-0.0.la
Matrix_@MATRIX_GLIB_API_VERSION_U@_gir_FILES = $(INST_H_SRC_FILES) $(INST_H_BUILT_FILES) $(filter %.c,$(libmatrix_glib_0_0_la_SOURCES)) Matrix_@MATRIX_GLIB_API_VERSION_U@_gir_FILES = $(INST_H_SRC_FILES) $(INST_H_BUILT_FILES) $(filter %.c,$(libmatrix_glib_0_0_la_SOURCES))
Matrix_@MATRIX_GLIB_API_VERSION_U@_gir_LIBS = libmatrix-glib-0.0.la Matrix_@MATRIX_GLIB_API_VERSION_U@_gir_LIBS = libmatrix-glib-0.0.la
Matrix_@MATRIX_GLIB_API_VERSION_U@_gir_SCANNERFLAGS = --identifier-prefix=Matrix --symbol-prefix=matrix --warn-all Matrix_@MATRIX_GLIB_API_VERSION_U@_gir_SCANNERFLAGS = --identifier-prefix=Matrix --symbol-prefix=matrix --warn-all
Matrix_@MATRIX_GLIB_API_VERSION_U@_gir_INCLUDES = GLib-2.0 GObject-2.0 Soup-2.4 Matrix_@MATRIX_GLIB_API_VERSION_U@_gir_INCLUDES = GLib-2.0 GObject-2.0 Soup-2.4 Json-1.0
Matrix_@MATRIX_GLIB_API_VERSION_U@_gir_CFLAGS = -D__MATRIX_GLIB_BUILDING__ -I$(top_srcdir) -I$(srcdir) -I$(builddir) Matrix_@MATRIX_GLIB_API_VERSION_U@_gir_CFLAGS = -D__MATRIX_GLIB_BUILDING__ -I$(top_srcdir) -I$(srcdir) -I$(builddir)
Matrix_@MATRIX_GLIB_API_VERSION_U@_gir_EXPORT_PACKAGES = matrix-glib Matrix_@MATRIX_GLIB_API_VERSION_U@_gir_EXPORT_PACKAGES = matrix-glib
INTROSPECTION_GIRS = Matrix-$(MATRIX_GLIB_API_VERSION).gir INTROSPECTION_GIRS = Matrix-$(MATRIX_GLIB_API_VERSION).gir

View File

@ -18,168 +18,529 @@
#include "matrix-api.h" #include "matrix-api.h"
#include <string.h>
#include <libsoup/soup.h>
/** /**
* SECTION:matrix-api * SECTION:matrix-api
* @short_description: Low level API calls to communicate with a
* Matrix.org server
* @title: MatrixAPI * @title: MatrixAPI
* @stability: Unstable * @short_description: An interface for actual API implementations,
* @include: matrix-glib/matrix.h * like #MatrixHTTPAPI
* *
* This is a class for low level communication with a Matrix.org * This interface provides a skeleton for all API functionality for
* server. * client communication with a Matrix.org homeserver.
*/ **/
/** /**
* MatrixAPI: * MatrixAPI:
* *
* The MatrixAPI objects instance definition. * An opaque pointer type.
**/
/**
* MatrixAPIInterface:
* @login: virtual function for matrix_api_login()
* @register_account: virtual_function for
* matrix_api_register_account()
* @initial_sync: virtual function for matrix_api_initial_sync()
* @event_stream: virtual function for matrix_api_event_stream()
* @create_room: virtual function for matrix_api_create_room()
* @join_room: virtual function for matrix_api_join_room()
* @send_state_event: virtual function for
* matrix_api_send_state_event()
* @send_message_event: virtual function for
* matrix_api_send_message_event()
* @send_message: virtual function for matrix_api_send_message()
* @send_emote: virtual function for matrix_api_send_emote()
* @get_room_name: virtual function for matrix_api_get_room_name()
* @get_room_topic: virtual function for matrix_api_get_room_topic()
* @leave_room: virtual function for matrix_api_leave_room()
* @invite_user: virtual function for matrix_api_invite_user()
* @kick_user: virtual function for matrix_api_kick_user()
* @set_membership: virtual function for matrix_api_set_membership()
* @ban_user: virtual function for matrix_api_ban_user()
* @get_room_state: virtual function for matrix_api_get_room_state()
* @get_text_body: virtual function for matrix_api_get_text_body()
* @get_html_body: virtual function for matrix_api_get_html_body()
* @get_emote_body: virtual function for matrix_api_get_emote_body()
* @_send: virtual function for matrix_api_send()
*
* The interface vtable for #MatrixAPI
*/ */
/** /**
* MatrixAPIClass: * MatrixAPICallback:
* @parent_class: the parent class structure (#GObjectClass) * @api: A #MatrixAPI implementation
* @content: the JSON content of the response, as a #JsonNode
* @data: User data specified when calling original request function
* *
* The MatrixAPI objects class definition. * A callback function to use with API calls.
*/ */
#define API_ENDPOINT "/_matrix/client/api/v1" G_DEFINE_INTERFACE(MatrixAPI, matrix_api, G_TYPE_OBJECT);
typedef struct _MatrixAPIPrivate {
SoupSession *soup_session;
guint txn_id;
gchar *url;
gchar *token;
gboolean validate_cert;
} MatrixAPIPrivate;
enum {
PROP_URL = 1,
N_PROPERTIES
};
GParamSpec *obj_properties[N_PROPERTIES] = {NULL,};
G_DEFINE_TYPE_WITH_PRIVATE(MatrixAPI, matrix_api, G_TYPE_OBJECT);
static void static void
matrix_api_finalize(GObject *gobject) matrix_api_default_init(MatrixAPIInterface *iface)
{ {
g_signal_handlers_destroy(gobject);
G_OBJECT_CLASS(matrix_api_parent_class)->finalize(gobject);
} }
static void /**
matrix_api_set_property(GObject *gobject, * matrix_api_ban_user:
guint prop_id, * @api: a #MatrixAPI implementation
const GValue *value, * @callback: (scope async): the function to call when the request is
GParamSpec *pspec) * finished
* @user_data: user data to pass to the callback function
* @room_id: the room ID where the user should be banned
* @user_id: the user ID to ban
* @reason: (allow-none): the reason of the ban
*
* Ban the specified user from the specified room. An optional reason
* can be specified.
*/
void
matrix_api_ban_user(MatrixAPI *api,
MatrixAPICallback callback,
gpointer user_data,
gchar *room_id,
gchar *user_id,
gchar *reason)
{ {
MatrixAPI *api = MATRIX_API(gobject); g_return_if_fail(MATRIX_IS_API(api));
MatrixAPIPrivate *priv = matrix_api_get_instance_private(api);
switch (prop_id) { MATRIX_API_GET_IFACE(api)
case PROP_URL: ->ban_user(api, callback, user_data, room_id, user_id, reason);
{
const gchar *base_url;
gchar *last_occurence;
base_url = g_value_get_string(value);
if (!g_str_is_ascii(base_url)) {
g_warning("URL specified (%s) is not ASCII", base_url);
return;
}
last_occurence = g_strrstr(base_url, API_ENDPOINT);
if ((g_strcmp0(last_occurence, API_ENDPOINT) == 0) ||
(g_strcmp0(last_occurence, API_ENDPOINT"/") == 0)) {
priv->url = g_strdup(base_url);
} else {
priv->url = g_strdup_printf(
"%s%s%s",
base_url,
(base_url[strlen(base_url) - 1] == '/') ? "" : "/",
API_ENDPOINT);
}
break;
}
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID(gobject, prop_id, pspec);
}
} }
static void /**
matrix_api_get_property(GObject *gobject, * matrix_api_create_room:
guint prop_id, * @api: a #MatrixAPI implementation
GValue *value, * @callback: (scope async): the function to call when the request is
GParamSpec *pspec) * finished
* @user_data: user data to pass to the callback function
* @alias: the alias (name) of the room
* @is_public: if %TRUE, the room will be accessible for anyone
* @invitees: (allow-none): list of user IDs to invite to the new room
*
* Create a new room with the given name and invite the users in
* @invitees.
*/
void
matrix_api_create_room(MatrixAPI *api,
MatrixAPICallback callback,
gpointer user_data,
gchar *alias,
gboolean is_public,
GStrv invitees)
{ {
MatrixAPI *api = MATRIX_API(gobject); g_return_if_fail(MATRIX_IS_API(api));
MatrixAPIPrivate *priv = matrix_api_get_instance_private(api);
switch (prop_id) { MATRIX_API_GET_IFACE(api)
case PROP_URL: ->create_room(api, callback, user_data, alias, is_public, invitees);
g_value_set_string(value, priv->url);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID(gobject, prop_id, pspec);
}
} }
static void /**
matrix_api_class_init(MatrixAPIClass *klass) * matrix_api_event_stream:
* @api: a #MatrixAPI implementation
* @callback: (scope async): the function to call when the request is
* finished
* @user_data: user data to pass to the callback function
* @from_token: (allow-none): events will be listed from this token
* @timeout: timeout of the request
*
* Get the event stream, optionally beginning from @from_token.
*/
void
matrix_api_event_stream(MatrixAPI *api,
MatrixAPICallback callback,
gpointer user_data,
gchar *from_token,
gulong timeout)
{ {
GObjectClass *gobject_class = G_OBJECT_CLASS(klass); g_return_if_fail(MATRIX_IS_API(api));
gobject_class->set_property = matrix_api_set_property; MATRIX_API_GET_IFACE(api)
gobject_class->get_property = matrix_api_get_property; ->event_stream(api, callback, user_data, from_token, timeout);
gobject_class->finalize = matrix_api_finalize;
/**
* MatrixAPI:url:
*
* The base URL to use for communication with the Matrix.org
* server.
*/
obj_properties[PROP_URL] = g_param_spec_string(
"url", "Server URL",
"Matrix.org home server to connect to.",
NULL,
G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
g_object_class_install_properties(gobject_class,
N_PROPERTIES,
obj_properties);
} }
static void /**
matrix_api_init(MatrixAPI *api) * matrix_api_get_room_name:
* @api: a #MatrixAPI implementation
* @callback: (scope async): the function to call when the request is
* finished
* @user_data: user data to pass to the callback function
* @room_id: the room ID to get a name for
*
* Get the name (alias) of a room.
*/
void
matrix_api_get_room_name(MatrixAPI *api,
MatrixAPICallback callback,
gpointer user_data,
gchar *room_id)
{ {
MatrixAPIPrivate *priv = matrix_api_get_instance_private(api); g_return_if_fail(MATRIX_IS_API(api));
priv->txn_id = 0; MATRIX_API_GET_IFACE(api)
priv->url = NULL; ->get_room_name(api, callback, user_data, room_id);
priv->token = NULL;
priv->validate_cert = TRUE;
priv->soup_session = soup_session_new_with_options(
SOUP_SESSION_ADD_FEATURE_BY_TYPE, SOUP_TYPE_CONTENT_SNIFFER,
NULL);
} }
MatrixAPI * /**
matrix_api_new(const gchar *base_url, const gchar *token) * matrix_api_get_room_state:
* @api: a #MatrixAPI implementation
* @callback: (scope async): the function to call when the request is
* finished
* @user_data: user data to pass to the callback function
* @room_id: the room ID to get a state for
*
* Get the state of a room.
*/
void
matrix_api_get_room_state(MatrixAPI *api,
MatrixAPICallback callback,
gpointer user_data,
gchar *room_id)
{ {
return g_object_new(MATRIX_TYPE_API, g_return_if_fail(MATRIX_IS_API(api));
"base-url", base_url,
"token", token, MATRIX_API_GET_IFACE(api)
NULL); ->get_room_state(api, callback, user_data, room_id);
}
/**
* matrix_api_get_room_topic:
* @api: a #MatrixAPI implementation
* @callback: (scope async): the function to call when the request is
* finished
* @user_data: user data to pass to the callback function
* @room_id: the room ID to get a topic for
*
* Get the topic of a room.
*/
void
matrix_api_get_room_topic(MatrixAPI *api,
MatrixAPICallback callback,
gpointer user_data,
gchar *room_id)
{
g_return_if_fail(MATRIX_IS_API(api));
MATRIX_API_GET_IFACE(api)
->get_room_topic(api, callback, user_data, room_id);
}
/**
* matrix_api_initial_sync:
* @api: a #MatrixAPI implementation
* @callback: (scope async): the function to call when the request is
* finished
* @user_data: user data to pass to the callback function
* @limit: the maximum number of events to get
*
* perform an initial sync of events
*/
void
matrix_api_initial_sync(MatrixAPI *api,
MatrixAPICallback callback,
gpointer user_data,
guint limit)
{
g_return_if_fail(MATRIX_IS_API(api));
MATRIX_API_GET_IFACE(api)
->initial_sync(api, callback, user_data, limit);
}
/**
* matrix_api_invite_user:
* @api: a #MatrixAPI implementation
* @callback: (scope async): the function to call when the request is
* finished
* @user_data: user data to pass to the callback function
* @room_id: the room ID to invite the user to
* @user_id: the user ID to invite
*
* Invite a user to a room.
*/
void
matrix_api_invite_user(MatrixAPI *api,
MatrixAPICallback callback,
gpointer user_data,
gchar *room_id,
gchar *user_id)
{
g_return_if_fail(MATRIX_IS_API(api));
MATRIX_API_GET_IFACE(api)
->invite_user(api, callback, user_data, room_id, user_id);
}
/**
* matrix_api_join_room:
* @api: a #MatrixAPI implementation
* @callback: (scope async): the function to call when the request is
* finished
* @user_data: user data to pass to the callback function
* @room_id_or_alias: the room ID or room alias to join to
*
* Join a room.
*/
void
matrix_api_join_room(MatrixAPI *api,
MatrixAPICallback callback,
gpointer user_data,
gchar *room_id_or_alias)
{
g_return_if_fail(MATRIX_IS_API(api));
MATRIX_API_GET_IFACE(api)
->join_room(api, callback, user_data, room_id_or_alias);
}
/**
* matrix_api_kick_user:
* @api: a #MatrixAPI implementation
* @callback: (scope async): the function to call when the request is
* finished
* @user_data: user data to pass to the callback function
* @room_id: the room ID to kick the user from
* @user_id: the user to kick
* @reason: (allow-none): the reason of kicking
*
* Kick a user from a room, with an optional reason.
*/
void
matrix_api_kick_user(MatrixAPI *api,
MatrixAPICallback callback,
gpointer user_data,
gchar *room_id,
gchar *user_id,
gchar *reason)
{
g_return_if_fail(MATRIX_IS_API(api));
MATRIX_API_GET_IFACE(api)
->kick_user(api, callback, user_data, room_id, user_id, reason);
}
/**
* matrix_api_leave_room:
* @api: a #MatrixAPI implementation
* @callback: (scope async): the function to call when the request is
* finished
* @user_data: user data to pass to the callback function
* @room_id: the room ID to kick the user from
*
* Leave a room
*/
void
matrix_api_leave_room(MatrixAPI *api,
MatrixAPICallback callback,
gpointer user_data,
gchar *room_id)
{
g_return_if_fail(MATRIX_IS_API(api));
MATRIX_API_GET_IFACE(api)
->leave_room(api, callback, user_data, room_id);
}
/**
* matrix_api_login:
* @api: a #MatrixAPI implementation
* @callback: (scope async): the function to call when the request is
* finished
* @user_data: user data to pass to the callback function
* @login_type: the login type to use
* @parameters: (allow-none): parameters to pass for the login request
*
* Attempt to login with type @login_type. Implementations of this
* method must set the token property on a successful login.
*/
void
matrix_api_login(MatrixAPI *api,
MatrixAPICallback callback,
gpointer user_data,
gchar *login_type,
GHashTable *parameters)
{
g_return_if_fail(MATRIX_IS_API(api));
MATRIX_API_GET_IFACE(api)
->login(api, callback, user_data, login_type, parameters);
}
/**
* matrix_api_register_account:
* @api: a #MatrixAPI implementation
* @callback: (scope async): the function to call when the request is
* finished
* @user_data: user data to pass to the callback function
* @login_type: the login type to use
* @parameters: (allow-none): parameters to pass for the registration
* request
*
* Attempt to register with type @login_type. Implementations of this
* method must set the token property on a successful login.
*/
void
matrix_api_register_account(MatrixAPI *api,
MatrixAPICallback callback,
gpointer user_data,
gchar *login_type,
GHashTable *parameters)
{
g_return_if_fail(MATRIX_IS_API(api));
MATRIX_API_GET_IFACE(api)
->register_account(api, callback, user_data, login_type, parameters);
}
/**
* matrix_api_send_emote:
* @api: a #MatrixAPI implementation
* @callback: (scope async): the function to call when the request is
* finished
* @user_data: user data to pass to the callback function
* @room_id: the room to send the emote to
* @text_content: the emote text to send
*
* Send an emote to the room.
*/
void
matrix_api_send_emote(MatrixAPI *api,
MatrixAPICallback callback,
gpointer user_data,
gchar *room_id,
gchar *text_content)
{
g_return_if_fail(MATRIX_IS_API(api));
MATRIX_API_GET_IFACE(api)
->send_emote(api, callback, user_data, room_id, text_content);
}
/**
* matrix_api_send_message:
* @api: a #MatrixAPI implementation
* @callback: (scope async): the function to call when the request is
* finished
* @user_data: user data to pass to the callback function
* @room_id: the room to send the emote to
* @text_content: the emote text to send
* @msg_type: the type of the message to be sent
*
* Send a custom message to the room.
*/
void
matrix_api_send_message(MatrixAPI *api,
MatrixAPICallback callback,
gpointer user_data,
gchar *room_id,
gchar *text_content,
gchar *msg_type)
{
g_return_if_fail(MATRIX_IS_API(api));
MATRIX_API_GET_IFACE(api)
->send_message(api,
callback, user_data,
room_id,
text_content,
msg_type);
}
/**
* matrix_api_send_message_event:
* @api: a #MatrixAPI implementation
* @callback: (scope async): the function to call when the request is
* finished
* @user_data: user data to pass to the callback function
* @room_id: the room to send the emote to
* @event_type: the type of the event to send
* @content: the content of the event as a #JsonNode
* @txn_id: the transaction ID to use
*
* Send a message event to the room.
*/
void
matrix_api_send_message_event(MatrixAPI *api,
MatrixAPICallback callback,
gpointer user_data,
gchar *room_id,
gchar *event_type,
JsonNode *content,
guint txn_id)
{
g_return_if_fail(MATRIX_IS_API(api));
MATRIX_API_GET_IFACE(api)
->send_message_event(api,
callback, user_data,
room_id,
event_type,
content,
txn_id);
}
/**
* matrix_api_send_state_event:
* @api: a #MatrixAPI implementation
* @callback: (scope async): the function to call when the request is
* finished
* @user_data: user data to pass to the callback function
* @room_id: the room to send the emote to
* @event_type: the type of the event to send
* @content: the content of the event as a #JsonNode
* @state_key: the state key to send
*
* Send a state event to the room
*/
void
matrix_api_send_state_event(MatrixAPI *api,
MatrixAPICallback callback,
gpointer user_data,
gchar *room_id,
gchar *event_type,
JsonNode *content,
gchar *state_key)
{
g_return_if_fail(MATRIX_IS_API(api));
MATRIX_API_GET_IFACE(api)
->send_state_event(api,
callback, user_data,
room_id,
event_type,
content,
state_key);
}
/**
* matrix_api_set_membership:
* @api: a #MatrixAPI implementation
* @callback: (scope async): the function to call when the request is
* finished
* @user_data: user data to pass to the callback function
* @room_id: the room to send the emote to
* @user_id: the user of whom membership will be set
* @membership: the new membership of the user
* @reason: (allow-none): the reason of the change
*
* Set the membership of the user for the given room.
*/
void
matrix_api_set_membership(MatrixAPI *api,
MatrixAPICallback callback,
gpointer user_data,
gchar *room_id,
gchar *user_id,
gchar *membership,
gchar *reason)
{
g_return_if_fail(MATRIX_IS_API(api));
MATRIX_API_GET_IFACE(api)
->set_membership(api,
callback, user_data,
room_id,
user_id,
membership,
reason);
} }

View File

@ -16,80 +16,245 @@
* <http://www.gnu.org/licenses/>. * <http://www.gnu.org/licenses/>.
*/ */
#ifndef __MATRIX_API_H__ #ifndef __MATRIX_API_IFACE_H__
#define __MATRIX_API_H__ #define __MATRIX_API_IFACE_H__
#include <glib-object.h> #include <glib-object.h>
#include <json-glib/json-glib.h>
G_BEGIN_DECLS G_BEGIN_DECLS
#define MATRIX_TYPE_API (matrix_api_get_type()) #define MATRIX_TYPE_API (matrix_api_get_type())
#define MATRIX_API(o) (G_TYPE_CHECK_INSTANCE_CAST((o), MATRIX_TYPE_API, MatrixAPI)) #define MATRIX_API(o) (G_TYPE_CHECK_INSTANCE_CAST((o), MATRIX_TYPE_API, MatrixAPI))
#define MATRIX_API_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), MATRIX_TYPE_API, MatrixAPIClass))
#define MATRIX_IS_API(o) (G_TYPE_CHECK_INSTANCE_TYPE((o), MATRIX_TYPE_API)) #define MATRIX_IS_API(o) (G_TYPE_CHECK_INSTANCE_TYPE((o), MATRIX_TYPE_API))
#define MATRIX_IS_API_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE((k), MATRIX_TYPE_API)) #define MATRIX_API_GET_IFACE(o) (G_TYPE_INSTANCE_GET_INTERFACE((o), MATRIX_TYPE_API, MatrixAPIInterface))
#define MATRIX_API_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS((o), MATRIX_TYPE_API, MatrixAPIClass))
typedef struct _MatrixAPI MatrixAPI; typedef struct _MatrixAPIInterface MatrixAPIInterface;
typedef struct _MatrixAPIClass MatrixAPIClass; typedef struct _MatrixAPI MatrixAPI;
struct _MatrixAPI { typedef void (*MatrixAPICallback)(MatrixAPI *api, JsonNode *content, gpointer data);
/* Parent instance structure */
GObject parent_instance;
/* Instance members */ struct _MatrixAPIInterface {
/*< private >*/
GTypeInterface g_iface;
/*< public >*/
void (*register_account)(MatrixAPI *api,
MatrixAPICallback callback,
gpointer user_data,
gchar *login_type,
GHashTable *parameters);
void (*login)(MatrixAPI *api,
MatrixAPICallback callback,
gpointer user_data,
gchar *login_type,
GHashTable *parameters);
void (*initial_sync)(MatrixAPI *api,
MatrixAPICallback callback,
gpointer user_data,
guint limit);
void (*event_stream)(MatrixAPI *api,
MatrixAPICallback callback,
gpointer user_data,
gchar *from_token,
gulong timeout);
void (*create_room)(MatrixAPI *api,
MatrixAPICallback callback,
gpointer user_data,
gchar *room_alias,
gboolean is_public,
GStrv invitees);
void (*join_room)(MatrixAPI *api,
MatrixAPICallback callback,
gpointer user_data,
gchar *room_id_or_alias);
void (*send_state_event)(MatrixAPI *api,
MatrixAPICallback callback,
gpointer user_data,
gchar *room_id,
gchar *event_type,
JsonNode *content,
gchar *state_key);
void (*send_message_event)(MatrixAPI *api,
MatrixAPICallback callback,
gpointer user_data,
gchar *room_id,
gchar *event_type,
JsonNode *content,
guint txn_id);
void (*send_message)(MatrixAPI *api,
MatrixAPICallback callback,
gpointer user_data,
gchar *room_id,
gchar *text_content,
gchar *msg_type);
void (*send_emote)(MatrixAPI *api,
MatrixAPICallback callback,
gpointer user_data,
gchar *room_id,
gchar *text_content);
void (*get_room_name)(MatrixAPI *api,
MatrixAPICallback callback,
gpointer user_data,
gchar *room_id);
void (*get_room_topic)(MatrixAPI *api,
MatrixAPICallback callback,
gpointer user_data,
gchar *room_id);
void (*leave_room)(MatrixAPI *api,
MatrixAPICallback callback,
gpointer user_data,
gchar *room_id);
void (*invite_user)(MatrixAPI *api,
MatrixAPICallback callback,
gpointer user_data,
gchar *room_id,
gchar *user_id);
void (*kick_user)(MatrixAPI *api,
MatrixAPICallback callback,
gpointer user_data,
gchar *room_id,
gchar *user_id,
gchar *reason);
void (*set_membership)(MatrixAPI *api,
MatrixAPICallback callback,
gpointer user_data,
gchar *room_id,
gchar *user_id,
gchar *membership,
gchar *reason);
void (*ban_user)(MatrixAPI *api,
MatrixAPICallback callback,
gpointer user_data,
gchar *room_id,
gchar *user_id,
gchar *reason);
void (*get_room_state)(MatrixAPI *api,
MatrixAPICallback callback,
gpointer user_data,
gchar *room_id);
void (*get_text_body)(MatrixAPI *api,
MatrixAPICallback callback,
gpointer user_data,
gchar *text,
gchar *msgtype);
void (*get_html_body)(MatrixAPI *api,
MatrixAPICallback callback,
gpointer user_data,
gchar *html,
gchar *msgtype);
void (*get_emote_body)(MatrixAPI *api,
MatrixAPICallback callback,
gpointer user_data,
gchar *text);
void (*_send)(MatrixAPI *api,
MatrixAPICallback callback,
gpointer user_data,
gchar *method,
gchar *path,
gchar *content,
gchar *query_params,
gchar *headers);
/*< private >*/
void *padding[20];
}; };
struct _MatrixAPIClass { void matrix_api_initial_sync(MatrixAPI *api,
GObjectClass parent_class; MatrixAPICallback callback,
}; gpointer user_data,
guint limit);
GType matrix_api_get_type(void) G_GNUC_CONST; void matrix_api_register_account(MatrixAPI *api,
MatrixAPICallback callback,
void matrix_api_initial_sync(MatrixAPI *api, guint limit); gpointer user_data,
void matrix_api_set_validate_certificate(MatrixAPI *api, gboolean valid); gchar *login_type,
gboolean matrix_api_get_validate_certificate(MatrixAPI *api); GHashTable *parameters);
void matrix_api_register(MatrixAPI *api, gchar *login_type, ...); void matrix_api_login(MatrixAPI *api,
void matrix_api_login(MatrixAPI *api, gchar *login_type, ...); MatrixAPICallback callback,
gpointer user_data,
gchar *login_type,
GHashTable *parameters);
void matrix_api_create_room(MatrixAPI *api, void matrix_api_create_room(MatrixAPI *api,
MatrixAPICallback callback,
gpointer user_data,
gchar *alias, gchar *alias,
gboolean is_public, gboolean is_public,
GList *invitees); GStrv invitees);
void matrix_api_join_room(MatrixAPI *api, gchar *room_id_or_alias); void matrix_api_join_room(MatrixAPI *api,
void matrix_api_event_stream(MatrixAPI *api, gchar *from_token, gulong timeout); MatrixAPICallback callback,
gpointer user_data,
gchar *room_id_or_alias);
void matrix_api_event_stream(MatrixAPI *api,
MatrixAPICallback callback,
gpointer user_data,
gchar *from_token,
gulong timeout);
void matrix_api_send_state_event(MatrixAPI *api, void matrix_api_send_state_event(MatrixAPI *api,
MatrixAPICallback callback,
gpointer user_data,
gchar *room_id, gchar *room_id,
gchar *event_type, gchar *event_type,
JsonNode *content, JsonNode *content,
gchar *state_key); gchar *state_key);
void matrix_api_send_message_event(MatrixAPI *api, void matrix_api_send_message_event(MatrixAPI *api,
MatrixAPICallback callback,
gpointer user_data,
gchar *room_id, gchar *room_id,
gchar *event_type, gchar *event_type,
JsonNode *content, JsonNode *content,
guint txn_id); guint txn_id);
void matrix_api_send_message(MatrixAPI *api, void matrix_api_send_message(MatrixAPI *api,
MatrixAPICallback callback,
gpointer user_data,
gchar *room_id, gchar *room_id,
gchar *text_content, gchar *text_content,
gchar *msg_type); gchar *msg_type);
void matrix_api_send_emote(MatrixAPI *api, gchar *room_id, gchar *text_content); void matrix_api_send_emote(MatrixAPI *api,
void matrix_api_get_room_name(MatrixAPI *api, gchar *room_id); MatrixAPICallback callback,
void matrix_api_get_room_topic(MatrixAPI *api, gchar *room_id); gpointer user_data,
void matrix_api_leave_room(MatrixAPI *api, gchar *room_id); gchar *room_id,
void matrix_api_invite_user(MatrixAPI *api, gchar *room_id, gchar *user_id); gchar *text_content);
void matrix_api_get_room_name(MatrixAPI *api,
MatrixAPICallback callback,
gpointer user_data,
gchar *room_id);
void matrix_api_get_room_topic(MatrixAPI *api,
MatrixAPICallback callback,
gpointer user_data,
gchar *room_id);
void matrix_api_leave_room(MatrixAPI *api,
MatrixAPICallback callback,
gpointer user_data,
gchar *room_id);
void matrix_api_invite_user(MatrixAPI *api,
MatrixAPICallback callback,
gpointer user_data,
gchar *room_id,
gchar *user_id);
void matrix_api_kick_user(MatrixAPI *api, void matrix_api_kick_user(MatrixAPI *api,
MatrixAPICallback callback,
gpointer user_data,
gchar *room_id, gchar *room_id,
gchar *user_id, gchar *user_id,
gchar *reason); gchar *reason);
void matrix_api_set_membership(MatrixAPI *api, void matrix_api_set_membership(MatrixAPI *api,
MatrixAPICallback callback,
gpointer user_data,
gchar *room_id, gchar *room_id,
gchar *user_id, gchar *user_id,
gchar *membership, gchar *membership,
gchar *reason); gchar *reason);
void matrix_api_ban_user(MatrixAPI *api, void matrix_api_ban_user(MatrixAPI *api,
MatrixAPICallback callback,
gpointer user_data,
gchar *room_id, gchar *room_id,
gchar *user_id, gchar *user_id,
gchar *reason); gchar *reason);
void matrix_api_get_room_state(MatrixAPI *api, gchar *room_id); void matrix_api_get_room_state(MatrixAPI *api,
MatrixAPICallback callback,
gpointer user_data,
gchar *room_id);
void matrix_api_get_text_body(MatrixAPI *api, gchar *text, gchar *msgtype); void matrix_api_get_text_body(MatrixAPI *api, gchar *text, gchar *msgtype);
void matrix_api_get_html_body(MatrixAPI *api, gchar *html, gchar *msgtype); void matrix_api_get_html_body(MatrixAPI *api, gchar *html, gchar *msgtype);
void matrix_api_get_emote_body(MatrixAPI *api, gchar *text); void matrix_api_get_emote_body(MatrixAPI *api, gchar *text);
@ -102,4 +267,4 @@ void _send(MatrixAPI *api,
G_END_DECLS G_END_DECLS
#endif /* __MATRIX_API_H__ */ #endif /* __MATRIX_API_IFACE_H__ */

251
src/matrix-http-api.c Normal file
View File

@ -0,0 +1,251 @@
/*
* 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
* <http://www.gnu.org/licenses/>.
*/
#include "matrix-http-api.h"
#include "matrix-api.h"
#include <string.h>
#include <libsoup/soup.h>
/**
* SECTION:matrix-http-api
* @short_description: Low level API calls to communicate with a
* Matrix.org server via HTTP
* @title: MatrixHTTPAPI
* @stability: Unstable
* @include: matrix-glib/matrix.h
*
* This is a class for low level communication with a Matrix.org
* server via HTTP.
*/
/**
* MatrixHTTPAPI:
*
* The MatrixHTTPAPI objects instance definition.
*/
/**
* MatrixHTTPAPIClass:
* @parent_class: the parent class structure (#GObjectClass)
*
* The MatrixHTTPAPI objects class definition.
*/
#define API_ENDPOINT "/_matrix/client/api/v1"
typedef struct _MatrixHTTPAPIPrivate {
SoupSession *soup_session;
guint txn_id;
gchar *url;
gchar *token;
gboolean validate_certificate;
} MatrixHTTPAPIPrivate;
enum {
PROP_VALIDATE_CERTIFICATE = 1,
PROP_URL,
N_PROPERTIES
};
GParamSpec *obj_properties[N_PROPERTIES] = {NULL,};
static void matrix_http_api_matrix_api_init(MatrixAPIInterface *iface);
G_DEFINE_TYPE_WITH_CODE(MatrixHTTPAPI, matrix_http_api, G_TYPE_OBJECT,
G_ADD_PRIVATE(MatrixHTTPAPI)
G_IMPLEMENT_INTERFACE(MATRIX_TYPE_API, matrix_http_api_matrix_api_init));
static void
matrix_http_api_matrix_api_init(MatrixAPIInterface *iface)
{}
static void
matrix_http_api_finalize(GObject *gobject)
{
g_signal_handlers_destroy(gobject);
G_OBJECT_CLASS(matrix_http_api_parent_class)->finalize(gobject);
}
static void
matrix_http_api_set_property(GObject *gobject,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
MatrixHTTPAPI *api = MATRIX_HTTP_API(gobject);
MatrixHTTPAPIPrivate *priv = matrix_http_api_get_instance_private(api);
switch (prop_id) {
case PROP_VALIDATE_CERTIFICATE:
priv->validate_certificate = g_value_get_boolean(value);
break;
case PROP_URL:
{
const gchar *base_url;
gchar *last_occurence;
base_url = g_value_get_string(value);
if (!g_str_is_ascii(base_url)) {
g_warning("URL specified (%s) is not ASCII", base_url);
return;
}
last_occurence = g_strrstr(base_url, API_ENDPOINT);
if ((g_strcmp0(last_occurence, API_ENDPOINT) == 0) ||
(g_strcmp0(last_occurence, API_ENDPOINT"/") == 0)) {
priv->url = g_strdup(base_url);
} else {
priv->url = g_strdup_printf(
"%s%s%s",
base_url,
(base_url[strlen(base_url) - 1] == '/') ? "" : "/",
API_ENDPOINT);
}
break;
}
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID(gobject, prop_id, pspec);
}
}
static void
matrix_http_api_get_property(GObject *gobject,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
MatrixHTTPAPI *api = MATRIX_HTTP_API(gobject);
MatrixHTTPAPIPrivate *priv = matrix_http_api_get_instance_private(api);
switch (prop_id) {
case PROP_VALIDATE_CERTIFICATE:
g_value_set_boolean(value, priv->validate_certificate);
break;
case PROP_URL:
g_value_set_string(value, priv->url);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID(gobject, prop_id, pspec);
}
}
static void
matrix_http_api_class_init(MatrixHTTPAPIClass *klass)
{
GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
gobject_class->set_property = matrix_http_api_set_property;
gobject_class->get_property = matrix_http_api_get_property;
gobject_class->finalize = matrix_http_api_finalize;
/**
* MatrixHTTPAPI:validate-certificate:
*
* Set to %FALSE if you dont want the SSL/TLS certificates to be
* validated.
*/
obj_properties[PROP_VALIDATE_CERTIFICATE] = g_param_spec_boolean(
"validate-certificate",
"Validate certificate",
"TRUE if server certificates should be validated",
TRUE,
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
/**
* MatrixHTTPAPI:url:
*
* The base URL to use for communication with the Matrix.org
* server.
*/
obj_properties[PROP_URL] = g_param_spec_string(
"url", "Server URL",
"Matrix.org home server to connect to.",
NULL,
G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
g_object_class_install_properties(gobject_class,
N_PROPERTIES,
obj_properties);
}
static void
matrix_http_api_init(MatrixHTTPAPI *api)
{
MatrixHTTPAPIPrivate *priv = matrix_http_api_get_instance_private(api);
priv->txn_id = 0;
priv->url = NULL;
priv->token = NULL;
priv->validate_certificate = TRUE;
priv->soup_session = soup_session_new_with_options(
SOUP_SESSION_ADD_FEATURE_BY_TYPE, SOUP_TYPE_CONTENT_SNIFFER,
NULL);
}
MatrixHTTPAPI *
matrix_http_api_new(const gchar *base_url, const gchar *token)
{
return g_object_new(MATRIX_TYPE_HTTP_API,
"base-url", base_url,
"token", token,
NULL);
}
/**
* matrix_http_api_set_validate_certificate:
* @api: a #MatrixHTTPAPI implementation
* @validate_certificate: %TRUE if server certificates should be
* validated
*
* Sets if server certificates should be validated.
*/
void
matrix_http_api_set_validate_certificate(MatrixHTTPAPI *api,
gboolean validate_certificate)
{
MatrixHTTPAPIPrivate *priv = matrix_http_api_get_instance_private(api);
priv->validate_certificate = validate_certificate;
}
/**
* matrix_http_api_get_validate_certificate:
* @api: a #MatrixHTTPAPI implementation
*
* Gets the value set by matrix_http_api_set_validate_certificate()
*
* Returns: %TRUE if the server certificates should be validated
*/
gboolean
matrix_http_api_get_validate_certificate(MatrixHTTPAPI *api)
{
MatrixHTTPAPIPrivate *priv = matrix_http_api_get_instance_private(api);
return priv->validate_certificate;
}

54
src/matrix-http-api.h Normal file
View File

@ -0,0 +1,54 @@
/*
* 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
* <http://www.gnu.org/licenses/>.
*/
#ifndef __MATRIX_HTTP_API_H__
#define __MATRIX_HTTP_API_H__
#include <glib-object.h>
G_BEGIN_DECLS
#define MATRIX_TYPE_HTTP_API (matrix_http_api_get_type())
#define MATRIX_HTTP_API(o) (G_TYPE_CHECK_INSTANCE_CAST((o), MATRIX_TYPE_HTTP_API, MatrixHTTPAPI))
#define MATRIX_HTTP_API_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), MATRIX_TYPE_HTTP_API, MatrixHTTPAPIClass))
#define MATRIX_IS_HTTP_API(o) (G_TYPE_CHECK_INSTANCE_TYPE((o), MATRIX_TYPE_HTTP_API))
#define MATRIX_IS_HTTP_API_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE((k), MATRIX_TYPE_HTTP_API))
#define MATRIX_HTTP_API_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS((o), MATRIX_TYPE_HTTP_API, MatrixHTTPAPIClass))
typedef struct _MatrixHTTPAPI MatrixHTTPAPI;
typedef struct _MatrixHTTPAPIClass MatrixHTTPAPIClass;
struct _MatrixHTTPAPI {
/* Parent instance structure */
GObject parent_instance;
/* Instance members */
};
struct _MatrixHTTPAPIClass {
GObjectClass parent_class;
};
GType matrix_http_api_get_type(void) G_GNUC_CONST;
void matrix_http_api_set_validate_certificate(MatrixHTTPAPI *api,
gboolean validate_certificate);
gboolean matrix_http_api_get_validate_certificate(MatrixHTTPAPI *api);
G_END_DECLS
#endif /* __MATRIX_HTTP_API_H__ */