aboutsummaryrefslogtreecommitdiffstats
path: root/matrix-roommembers.c
diff options
context:
space:
mode:
Diffstat (limited to 'matrix-roommembers.c')
-rw-r--r--matrix-roommembers.c316
1 files changed, 316 insertions, 0 deletions
diff --git a/matrix-roommembers.c b/matrix-roommembers.c
new file mode 100644
index 0000000..a437796
--- /dev/null
+++ b/matrix-roommembers.c
@@ -0,0 +1,316 @@
+/*
+ * matrix-roommember.c
+ *
+ *
+ * Copyright (c) Openmarket UK Ltd 2015
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * 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
+ */
+
+
+#include "matrix-roommembers.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "debug.h"
+
+#include "matrix-json.h"
+
+/******************************************************************************
+ *
+ * Individual members
+ */
+
+typedef struct _MatrixRoomMember {
+ gchar *userid;
+
+ /* the displayname we gave to purple */
+ gchar *current_displayname;
+
+ /* the current room membership */
+ int membership;
+
+ /* the displayname from the state table */
+ const gchar *state_displayname;
+} MatrixRoomMember;
+
+
+/**
+ * calculate the displayname for the given member
+ *
+ * @returns a string, which should be freed
+ */
+static gchar *_calculate_displayname_for_member(const MatrixRoomMember *member)
+{
+ if(member->state_displayname != NULL) {
+ return g_strdup(member->state_displayname);
+ } else {
+ return g_strdup(member->userid);
+ }
+}
+
+
+static int _parse_membership(const gchar *membership)
+{
+ if(membership == NULL)
+ return MATRIX_ROOM_MEMBERSHIP_NONE;
+
+ if(strcmp(membership, "join") == 0)
+ return MATRIX_ROOM_MEMBERSHIP_JOIN;
+ if(strcmp(membership, "leave") == 0)
+ return MATRIX_ROOM_MEMBERSHIP_LEAVE;
+ if(strcmp(membership, "invite") == 0)
+ return MATRIX_ROOM_MEMBERSHIP_INVITE;
+ return MATRIX_ROOM_MEMBERSHIP_NONE;
+}
+
+static MatrixRoomMember *_new_member(const gchar *userid)
+{
+ MatrixRoomMember *mem = g_new0(MatrixRoomMember, 1);
+ mem->userid = g_strdup(userid);
+ return mem;
+}
+
+static void _free_member(MatrixRoomMember *member)
+{
+ g_assert(member != NULL);
+ g_free(member->userid);
+ member->userid = NULL;
+ g_free(member->current_displayname);
+ member->current_displayname = NULL;
+ g_free(member);
+}
+
+
+/******************************************************************************
+ *
+ * member table
+ */
+
+struct _MatrixRoomMemberTable {
+ GHashTable *hash_table;
+ GSList *new_members;
+ GSList *left_members;
+ GSList *renamed_members;
+};
+
+MatrixRoomMemberTable *matrix_roommembers_new_table()
+{
+ MatrixRoomMemberTable *table;
+ table = g_new0(MatrixRoomMemberTable, 1);
+ table -> hash_table = g_hash_table_new_full(g_str_hash, g_str_equal, g_free,
+ (GDestroyNotify) _free_member);
+ return table;
+}
+
+
+void matrix_roommembers_free_table(MatrixRoomMemberTable *table)
+{
+ g_hash_table_destroy(table->hash_table);
+ table->hash_table = NULL;
+ g_free(table);
+}
+
+
+static MatrixRoomMember *_lookup_member(MatrixRoomMemberTable *table,
+ const gchar *userid)
+{
+ return g_hash_table_lookup(table->hash_table, userid);
+}
+
+
+#if 0
+static void _on_member_changed_displayname(PurpleConversation *conv,
+ const gchar *member_user_id, MatrixRoomMember *member)
+{
+ PurpleConvChat *chat = PURPLE_CONV_CHAT(conv);
+ gchar *old_displayname, *new_displayname;
+
+ old_displayname = member->current_displayname;
+ g_assert(old_displayname != NULL);
+ new_displayname = _calculate_displayname_for_member(member_user_id, member);
+
+ purple_conv_chat_rename_user(chat, old_displayname, new_displayname);
+ g_free(old_displayname);
+ member->current_displayname = new_displayname;
+}
+
+
+static void _on_member_left(PurpleConversation *conv,
+ const gchar *member_user_id, MatrixRoomMember *member)
+{
+ PurpleConvChat *chat = PURPLE_CONV_CHAT(conv);
+ gchar *old_displayname;
+
+ old_displayname = member->current_displayname;
+ g_assert(old_displayname != NULL);
+ purple_conv_chat_remove_user(chat, old_displayname, NULL);
+ g_free(old_displayname);
+ member->current_displayname = NULL;
+}
+#endif
+
+
+const gchar *matrix_roommembers_get_displayname_for_member(
+ MatrixRoomMemberTable *table, const gchar *user_id)
+{
+ MatrixRoomMember *member = _lookup_member(table, user_id);
+ gchar *displayname;
+
+ if(member == NULL)
+ return user_id;
+
+ displayname = member -> current_displayname;
+
+ if (displayname != NULL)
+ return displayname;
+
+ member -> current_displayname = displayname;
+ return displayname;
+}
+
+
+void matrix_roommembers_get_new_members(MatrixRoomMemberTable *table,
+ GList **display_names, GList **flags)
+{
+ while(table->new_members != NULL) {
+ MatrixRoomMember *member = table->new_members->data;
+ gchar *displayname;
+ GSList *tmp;
+
+ g_assert(member->current_displayname == NULL);
+ displayname = _calculate_displayname_for_member(member);
+ member->current_displayname = displayname;
+ *display_names = g_list_prepend(*display_names, displayname);
+ *flags = g_list_prepend(*flags, GINT_TO_POINTER(0));
+
+ tmp = table->new_members;
+ table->new_members = tmp->next;
+ g_slist_free_1(tmp);
+ }
+}
+
+void matrix_roommembers_get_renamed_members(MatrixRoomMemberTable *table,
+ GList **old_names, GList **new_names)
+{
+ while(table->renamed_members != NULL) {
+ MatrixRoomMember *member = table->renamed_members->data;
+ gchar *displayname;
+ GSList *tmp;
+
+ g_assert(member->current_displayname != NULL);
+ displayname = _calculate_displayname_for_member(member);
+ *old_names = g_list_prepend(*old_names, member->current_displayname);
+ *new_names = g_list_prepend(*new_names, displayname);
+ member->current_displayname = displayname;
+
+ tmp = table->renamed_members;
+ table->renamed_members = tmp->next;
+ g_slist_free_1(tmp);
+ }
+}
+
+void matrix_roommembers_get_left_members(MatrixRoomMemberTable *table,
+ GList **names)
+{
+ while(table->left_members != NULL) {
+ MatrixRoomMember *member = table->left_members->data;
+ GSList *tmp;
+
+ g_assert(member->current_displayname != NULL);
+ *names = g_list_prepend(*names, member->current_displayname);
+ member->current_displayname = NULL;
+
+ tmp = table->left_members;
+ table->left_members = tmp->next;
+ g_slist_free_1(tmp);
+ }
+}
+
+
+void matrix_roommembers_update_member(MatrixRoomMemberTable *table,
+ const gchar *member_user_id, JsonObject *new_state)
+{
+ const gchar *old_displayname = NULL;
+ MatrixRoomMember *member;
+ int old_membership_val = MATRIX_ROOM_MEMBERSHIP_NONE,
+ new_membership_val;
+ const gchar *new_displayname, *new_membership;
+
+ new_displayname = matrix_json_object_get_string_member(
+ new_state, "displayname");
+ new_membership = matrix_json_object_get_string_member(
+ new_state, "membership");
+
+ new_membership_val = _parse_membership(new_membership);
+
+ member = _lookup_member(table, member_user_id);
+
+ if(member != NULL) {
+ old_displayname = member -> state_displayname;
+ old_membership_val = member -> membership;
+ }
+
+ if(!member) {
+ member = _new_member(member_user_id);
+ g_hash_table_insert(table->hash_table, g_strdup(member_user_id),
+ member);
+ }
+ member->membership = new_membership_val;
+ member->state_displayname = new_displayname;
+
+ purple_debug_info("matrixprpl", "member %s change %i->%i, "
+ "%s->%s\n", member_user_id,
+ old_membership_val, new_membership_val,
+ old_displayname, new_displayname);
+
+ if(new_membership_val == MATRIX_ROOM_MEMBERSHIP_JOIN) {
+ if(old_membership_val != MATRIX_ROOM_MEMBERSHIP_JOIN) {
+ table->new_members = g_slist_append(
+ table->new_members, member);
+ } else if(g_strcmp0(old_displayname, new_displayname) != 0) {
+ table->renamed_members = g_slist_append(
+ table->renamed_members, member);
+ }
+ } else {
+ if(old_membership_val == MATRIX_ROOM_MEMBERSHIP_JOIN) {
+ table->left_members = g_slist_append(
+ table->left_members, member);
+ }
+ }
+}
+
+
+/**
+ * Returns a list of user ids. Free the list, but not the string pointers.
+ */
+GList *matrix_roommembers_get_active_members(
+ MatrixRoomMemberTable *member_table)
+{
+ GHashTableIter iter;
+ gpointer key, value;
+ GList *members = NULL;
+
+ g_hash_table_iter_init (&iter, member_table->hash_table);
+ while (g_hash_table_iter_next (&iter, &key, &value)) {
+ const gchar *user_id = key;
+ MatrixRoomMember *member = value;
+
+ if(member->membership == MATRIX_ROOM_MEMBERSHIP_JOIN)
+ members = g_list_prepend(members, (gpointer)user_id);
+ }
+ return members;
+}