diff options
-rw-r--r-- | libmatrix.c | 44 | ||||
-rw-r--r-- | libmatrix.h | 3 | ||||
-rw-r--r-- | matrix-json.c | 19 | ||||
-rw-r--r-- | matrix-json.h | 3 | ||||
-rw-r--r-- | matrix-login.c | 91 | ||||
-rw-r--r-- | matrix-room.c | 2 |
6 files changed, 109 insertions, 53 deletions
diff --git a/libmatrix.c b/libmatrix.c index f386f8d..51b057b 100644 --- a/libmatrix.c +++ b/libmatrix.c @@ -59,19 +59,6 @@ typedef struct { } GcFuncData; /* - * stores offline messages that haven't been delivered yet. maps username - * (char *) to GList * of GOfflineMessages. initialized in matrixprpl_init. - */ -GHashTable* goffline_messages = NULL; - -typedef struct { - char *from; - char *message; - time_t mtime; - PurpleMessageFlags flags; -} GOfflineMessage; - -/* * helpers */ static PurpleConnection *get_matrixprpl_gc(const char *username) { @@ -315,10 +302,7 @@ static int matrixprpl_send_im(PurpleConnection *gc, const char *who, const char *message, PurpleMessageFlags flags) { const char *from_username = gc->account->username; - PurpleMessageFlags receive_flags = ((flags & ~PURPLE_MESSAGE_SEND) - | PURPLE_MESSAGE_RECV); PurpleAccount *to_acct = purple_accounts_find(who, PRPL_ID); - PurpleConnection *to; purple_debug_info("matrixprpl", "sending message from %s to %s: %s\n", from_username, who, message); @@ -335,28 +319,6 @@ static int matrixprpl_send_im(PurpleConnection *gc, const char *who, return 0; } - /* is the recipient online? */ - to = get_matrixprpl_gc(who); - if (to) { /* yes, send */ - serv_got_im(to, from_username, message, receive_flags, time(NULL)); - - } else { /* nope, store as an offline message */ - GOfflineMessage *offline_message; - GList *messages; - - purple_debug_info("matrixprpl", - "%s is offline, sending as offline message\n", who); - offline_message = g_new0(GOfflineMessage, 1); - offline_message->from = g_strdup(from_username); - offline_message->message = g_strdup(message); - offline_message->mtime = time(NULL); - offline_message->flags = receive_flags; - - messages = g_hash_table_lookup(goffline_messages, who); - messages = g_list_append(messages, offline_message); - g_hash_table_insert(goffline_messages, g_strdup(who), messages); - } - return 1; } @@ -1056,12 +1018,6 @@ static void matrixprpl_init(PurplePlugin *plugin) "msg <username> <message>: send a private message, aka a whisper", NULL); /* userdata */ - /* get ready to store offline messages */ - goffline_messages = g_hash_table_new_full(g_str_hash, /* hash fn */ - g_str_equal, /* key comparison fn */ - g_free, /* key free fn */ - NULL); /* value free fn */ - _matrix_protocol = plugin; } diff --git a/libmatrix.h b/libmatrix.h index 16eb403..0024348 100644 --- a/libmatrix.h +++ b/libmatrix.h @@ -14,7 +14,7 @@ * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA - */ + */ #ifndef LIBMATRIX_H #define LIBMATRIX_H @@ -37,7 +37,6 @@ typedef struct _MatrixAccount { struct _PurpleConnection *pc; gchar *homeserver; /* hostname (:port) of the homeserver */ gchar *access_token; /* access token corresponding to our user */ - GList rooms; /* a list of MatrixRooms */ } MatrixAccount; #endif diff --git a/matrix-json.c b/matrix-json.c index 3cf6d0c..967441e 100644 --- a/matrix-json.c +++ b/matrix-json.c @@ -31,6 +31,16 @@ const gchar *matrix_json_node_get_string(JsonNode *node) return json_node_get_string(node); } +gint64 matrix_json_node_get_int(JsonNode *node) +{ + if(node == NULL) + return 0; + if(JSON_NODE_TYPE(node) != JSON_NODE_VALUE) + return 0; + return json_node_get_int(node); +} + + JsonObject *matrix_json_node_get_object (JsonNode *node) { if(node == NULL) @@ -72,6 +82,15 @@ const gchar *matrix_json_object_get_string_member(JsonObject *object, return matrix_json_node_get_string(member); } +gint64 matrix_json_object_get_int_member(JsonObject *object, + const gchar *member_name) +{ + JsonNode *member; + member = matrix_json_object_get_member(object, member_name); + return matrix_json_node_get_int(member); +} + + JsonObject *matrix_json_object_get_object_member(JsonObject *object, const gchar *member_name) { diff --git a/matrix-json.h b/matrix-json.h index 0d2d97a..c789a1c 100644 --- a/matrix-json.h +++ b/matrix-json.h @@ -31,6 +31,7 @@ /* node - returns NULL if node == NULL or *node is of the wrong type */ const gchar *matrix_json_node_get_string(JsonNode *node); +gint64 matrix_json_node_get_int(JsonNode *node); JsonObject *matrix_json_node_get_object(JsonNode *node); JsonArray *matrix_json_node_get_array(JsonNode *node); @@ -42,6 +43,8 @@ JsonNode *matrix_json_object_get_member(JsonObject *object, const gchar *member_name); const gchar *matrix_json_object_get_string_member(JsonObject *object, const gchar *member_name); +gint64 matrix_json_object_get_int_member(JsonObject *object, + const gchar *member_name); JsonObject *matrix_json_object_get_object_member(JsonObject *object, const gchar *member_name); JsonArray *matrix_json_object_get_array_member(JsonObject *object, diff --git a/matrix-login.c b/matrix-login.c index de1654b..1a48e38 100644 --- a/matrix-login.c +++ b/matrix-login.c @@ -36,14 +36,89 @@ /* TODO: make this configurable */ #define MATRIX_HOMESERVER "www.sw1v.org" +/* TODO: move this out */ +typedef struct _RoomEventParserData { + MatrixAccount *acct; + const gchar *room_id; + JsonObject *event_map; +} RoomEventParserData; + +static void parse_timeline_event(JsonArray *timeline, + guint state_idx, JsonNode *timeline_entry, gpointer user_data) +{ + RoomEventParserData *data = user_data; + MatrixAccount *ma = data->acct; + JsonObject *event_map = data->event_map; + const gchar *room_id = data->room_id; + const gchar *event_id, *event_type, *msg_body, *sender; + JsonObject *json_event_obj, *json_content_obj; + PurpleMessageFlags flags; + gint64 timestamp; + + event_id = matrix_json_node_get_string(timeline_entry); + if(event_id == NULL) { + purple_debug_warning("prplmatrix", "non-string event_id"); + return; + } + + json_event_obj = matrix_json_object_get_object_member( + event_map, event_id); + if(json_event_obj == NULL) { + purple_debug_warning("prplmatrix", "unknown event_id %s", event_id); + return; + } + + event_type = matrix_json_object_get_string_member( + json_event_obj, "type"); + json_content_obj = matrix_json_object_get_object_member( + json_event_obj, "content"); + if(event_type == NULL || json_content_obj == NULL) + return; + + if(strcmp(event_type, "m.room.message") != 0) { + purple_debug_info("prplmatrix", "ignoring unknown room event %s", + event_type); + return; + } + + msg_body = matrix_json_object_get_string_member(json_content_obj, "body"); + if(msg_body == NULL) { + purple_debug_warning("prplmatrix", "no body in message event %s", + event_id); + return; + } + + sender = matrix_json_object_get_string_member(json_event_obj, "sender"); + if(sender == NULL) { + sender = "<unknown>"; + } + + timestamp = matrix_json_object_get_int_member(json_event_obj, + "origin_server_ts"); + + flags = PURPLE_MESSAGE_RECV; + + purple_debug_info("prplmatrix", "got message %s in %s\n", msg_body, room_id); + serv_got_chat_in(ma->pc, g_str_hash(room_id), sender, flags, + msg_body, timestamp / 1000); +} + +static void parse_timeline_events(MatrixAccount *acct, + const gchar *room_id, + JsonArray *events, JsonObject* event_map) +{ + RoomEventParserData data = {acct, room_id, event_map}; + json_array_foreach_element(events, parse_timeline_event, &data); +} + /** * handle a room within the initial sync response */ static void matrixprpl_handle_initial_sync_room( const gchar *room_id, JsonObject *room_data, MatrixAccount *ma) { - JsonObject *state_object, *event_map; - JsonArray *state_array; + JsonObject *state_object, *timeline_object, *event_map; + JsonArray *state_array, *timeline_array; const gchar *room_name; PurpleConversation *conv; PurpleChat *chat; @@ -51,11 +126,11 @@ static void matrixprpl_handle_initial_sync_room( MatrixRoomStateEventTable *state_table; event_map = matrix_json_object_get_object_member(room_data, "event_map"); - state_object = matrix_json_object_get_object_member(room_data, "state"); - state_array = matrix_json_object_get_array_member(state_object, "events"); /* parse the room state */ state_table = g_hash_table_new(g_str_hash, g_str_equal); /* TODO: free */ + state_object = matrix_json_object_get_object_member(room_data, "state"); + state_array = matrix_json_object_get_array_member(state_object, "events"); if(state_array != NULL) matrix_room_parse_state_events(state_table, state_array, event_map); @@ -87,6 +162,12 @@ static void matrixprpl_handle_initial_sync_room( conv = serv_got_joined_chat(ma->pc, g_str_hash(room_id), room_id); purple_conversation_set_data(conv, "room_id", g_strdup(room_id)); /* TODO: free */ purple_conversation_set_data(conv, "state", state_table); + + timeline_object = matrix_json_object_get_object_member( + room_data, "timeline"); + timeline_array = matrix_json_object_get_array_member( + timeline_object, "events"); + parse_timeline_events(ma, room_id, timeline_array, event_map); } @@ -174,7 +255,7 @@ static void matrixprpl_sync_complete(MatrixAccount *ma, } purple_connection_update_progress(ma->pc, _("Connected"), 2, 3); - purple_connection_set_state(ma->pc, PURPLE_CONNECTED); + purple_connection_set_state(ma->pa->gc, PURPLE_CONNECTED); matrixprpl_handle_initial_sync(ma, body); } diff --git a/matrix-room.c b/matrix-room.c index a4fe75d..bb519a0 100644 --- a/matrix-room.c +++ b/matrix-room.c @@ -155,8 +155,6 @@ GList *matrixprpl_chat_info(PurpleConnection *gc) { struct proto_chat_entry *pce; /* defined in prpl.h */ - purple_debug_info("matrixprpl", "returning chat setting 'room_id'\n"); - pce = g_new0(struct proto_chat_entry, 1); pce->label = _("Chat _room"); pce->identifier = "room_id"; |