/cpw/tomkiewicz/gg11: 300c246402ac: Gadu-Gadu: delayed chat joining

Tomasz Wasilczyk tomkiewicz at cpw.pidgin.im
Tue Sep 11 17:55:14 EDT 2012


Changeset: 300c246402ac2eb6d366e424ca42a58f4c223b87
Author:	 Tomasz Wasilczyk <tomkiewicz at cpw.pidgin.im>
Date:	 2012-09-11 23:55 +0200
Branch:	 default
URL: http://hg.pidgin.im/cpw/tomkiewicz/gg11/rev/300c246402ac

Description:

Gadu-Gadu: delayed chat joining

diffstat:

 libpurple/protocols/gg/chat.c |  247 ++++++++++++++++++++++++++++++++++-------
 libpurple/protocols/gg/gg.c   |    1 +
 2 files changed, 203 insertions(+), 45 deletions(-)

diffs (truncated from 415 to 300 lines):

diff --git a/libpurple/protocols/gg/chat.c b/libpurple/protocols/gg/chat.c
--- a/libpurple/protocols/gg/chat.c
+++ b/libpurple/protocols/gg/chat.c
@@ -11,6 +11,9 @@ struct _ggp_chat_session_data
 {
 	ggp_chat_local_info *chats;
 	int chats_count;
+
+	gboolean got_all_chats_info;
+	GSList *pending_joins;
 };
 
 struct _ggp_chat_local_info
@@ -21,18 +24,23 @@ struct _ggp_chat_local_info
 	PurpleConversation *conv;
 	PurpleConnection *gc;
 	
+	gboolean left;
 	gboolean previously_joined;
+	
+	uin_t *participants;
+	int participants_count;
 };
 
 static ggp_chat_local_info * ggp_chat_new(PurpleConnection *gc, uint64_t id);
 static ggp_chat_local_info * ggp_chat_get(PurpleConnection *gc, uint64_t id);
+static void ggp_chat_open_conv(ggp_chat_local_info *chat);
 static ggp_chat_local_info * ggp_chat_get_local(PurpleConnection *gc,
 	int local_id);
-static void ggp_chat_joined(ggp_chat_local_info *chat, uin_t uin,
-	gboolean new_arrival);
+static void ggp_chat_joined(ggp_chat_local_info *chat, uin_t uin);
 static void ggp_chat_left(ggp_chat_local_info *chat, uin_t uin);
 static const gchar * ggp_chat_get_name_from_id(uint64_t id);
 static uint64_t ggp_chat_get_id_from_name(const gchar * name);
+static void ggp_chat_join_id(PurpleConnection *gc, uint64_t id);
 
 static inline ggp_chat_session_data *
 ggp_chat_get_sdata(PurpleConnection *gc)
@@ -50,12 +58,15 @@ void ggp_chat_setup(PurpleConnection *gc
 
 	sdata->chats = NULL;
 	sdata->chats_count = 0;
+	sdata->got_all_chats_info = FALSE;
+	sdata->pending_joins = NULL;
 }
 
 void ggp_chat_cleanup(PurpleConnection *gc)
 {
 	ggp_chat_session_data *sdata = ggp_chat_get_sdata(gc);
 
+	g_slist_free_full(sdata->pending_joins, g_free);
 	g_free(sdata->chats);
 	g_free(sdata);
 }
@@ -66,36 +77,22 @@ static ggp_chat_local_info * ggp_chat_ne
 	int local_id;
 	ggp_chat_local_info *chat;
 
-	if (NULL == (chat = ggp_chat_get(gc, id)))
-	{
-		local_id = sdata->chats_count++;
-		sdata->chats = realloc(sdata->chats,
-			sdata->chats_count * sizeof(ggp_chat_local_info));
-		chat = &sdata->chats[local_id];
+	if (NULL != (chat = ggp_chat_get(gc, id)))
+		return chat;
 
-		chat->local_id = local_id;
-		chat->id = id;
-		chat->conv = NULL;
-		chat->gc = gc;
-		chat->previously_joined = FALSE;
-	}
+	local_id = sdata->chats_count++;
+	sdata->chats = realloc(sdata->chats,
+		sdata->chats_count * sizeof(ggp_chat_local_info));
+	chat = &sdata->chats[local_id];
 
-	if (chat->conv != NULL)
-	{
-		purple_debug_warning("gg", "ggp_chat_new: "
-			"chat %llu already exists\n", id);
-		return chat;
-	}
-
-	chat->conv = serv_got_joined_chat(gc, chat->local_id,
-		ggp_chat_get_name_from_id(id));
-	if (chat->previously_joined)
-	{
-		purple_conversation_write(chat->conv, NULL,
-			_("You have re-joined the chat"), PURPLE_MESSAGE_SYSTEM,
-			time(NULL));
-	}
-	chat->previously_joined = TRUE;
+	chat->local_id = local_id;
+	chat->id = id;
+	chat->conv = NULL;
+	chat->gc = gc;
+	chat->left = FALSE;
+	chat->previously_joined = FALSE;
+	chat->participants = NULL;
+	chat->participants_count = 0;
 
 	return chat;
 }
@@ -112,6 +109,32 @@ static ggp_chat_local_info * ggp_chat_ge
 	return NULL;
 }
 
+static void ggp_chat_open_conv(ggp_chat_local_info *chat)
+{
+	PurpleConvChat *pcchat;
+	int i;
+
+	if (chat->conv != NULL)
+		return;
+
+	chat->conv = serv_got_joined_chat(chat->gc, chat->local_id,
+		ggp_chat_get_name_from_id(chat->id));
+	if (chat->previously_joined)
+	{
+		purple_conversation_write(chat->conv, NULL,
+			_("You have re-joined the chat"), PURPLE_MESSAGE_SYSTEM,
+			time(NULL));
+	}
+	chat->previously_joined = TRUE;
+
+	pcchat = purple_conversation_get_chat_data(chat->conv);
+	purple_conv_chat_clear_users(pcchat);
+	for (i = 0; i < chat->participants_count; i++)
+		purple_conv_chat_add_user(pcchat,
+			ggp_uin_to_str(chat->participants[i]), NULL,
+			PURPLE_CBFLAGS_NONE, FALSE);
+}
+
 static ggp_chat_local_info * ggp_chat_get_local(PurpleConnection *gc,
 	int local_id)
 {
@@ -127,6 +150,7 @@ static ggp_chat_local_info * ggp_chat_ge
 
 void ggp_chat_got_event(PurpleConnection *gc, const struct gg_event *ev)
 {
+	ggp_chat_session_data *sdata = ggp_chat_get_sdata(gc);
 	ggp_chat_local_info *chat;
 	int i;
 
@@ -135,7 +159,20 @@ void ggp_chat_got_event(PurpleConnection
 		const struct gg_event_chat_info *eci = &ev->event.chat_info;
 		chat = ggp_chat_new(gc, eci->id);
 		for (i = 0; i < eci->participants_count; i++)
-			ggp_chat_joined(chat, eci->participants[i], FALSE);
+			ggp_chat_joined(chat, eci->participants[i]);
+	}
+	else if (ev->type == GG_EVENT_CHAT_INFO_GOT_ALL)
+	{
+		GSList *it = sdata->pending_joins;
+		sdata->got_all_chats_info = TRUE;
+		while (it)
+		{
+			uint64_t *id_p = it->data;
+			ggp_chat_join_id(gc, *id_p);
+			it = g_slist_next(it);
+		}
+		g_slist_free_full(sdata->pending_joins, g_free);
+		sdata->pending_joins = NULL;
 	}
 	else if (ev->type == GG_EVENT_CHAT_INFO_UPDATE)
 	{
@@ -149,7 +186,7 @@ void ggp_chat_got_event(PurpleConnection
 			return;
 		}
 		if (eciu->type == GG_CHAT_INFO_UPDATE_ENTERED)
-			ggp_chat_joined(chat, eciu->participant, TRUE);
+			ggp_chat_joined(chat, eciu->participant);
 		else if (eciu->type == GG_CHAT_INFO_UPDATE_EXITED)
 			ggp_chat_left(chat, eciu->participant);
 		else
@@ -163,7 +200,8 @@ void ggp_chat_got_event(PurpleConnection
 		uin_t me = ggp_str_to_uin(purple_account_get_username(
 			purple_connection_get_account(gc)));
 		chat = ggp_chat_new(gc, ecc->id);
-		ggp_chat_joined(chat, me, FALSE);
+		ggp_chat_joined(chat, me);
+		ggp_chat_open_conv(chat);
 	}
 	else if (ev->type == GG_EVENT_CHAT_INVITE_ACK ||
 		ev->type == GG_EVENT_CHAT_SEND_MSG_ACK)
@@ -177,16 +215,55 @@ void ggp_chat_got_event(PurpleConnection
 	}
 }
 
-static void ggp_chat_joined(ggp_chat_local_info *chat, uin_t uin,
-	gboolean new_arrival)
+static int ggp_chat_participant_find(ggp_chat_local_info *chat, uin_t uin)
 {
+	int i;
+	for (i = 0; i < chat->participants_count; i++)
+		if (chat->participants[i] == uin)
+			return i;
+	return -1;
+}
+
+static void ggp_chat_joined(ggp_chat_local_info *chat, uin_t uin)
+{
+	int idx = ggp_chat_participant_find(chat, uin);
+	if (idx >= 0)
+	{
+		purple_debug_warning("gg", "ggp_chat_joined: "
+			"user %u is already present in chat %llu\n",
+			uin, chat->id);
+		return;
+	}
+	chat->participants_count++;
+	chat->participants = realloc(chat->participants,
+		sizeof(uin) * chat->participants_count);
+	chat->participants[chat->participants_count - 1] = uin;
+	
+	if (!chat->conv)
+		return;
 	purple_conv_chat_add_user(purple_conversation_get_chat_data(chat->conv),
-		ggp_uin_to_str(uin), NULL, PURPLE_CBFLAGS_NONE, new_arrival);
+		ggp_uin_to_str(uin), NULL, PURPLE_CBFLAGS_NONE, TRUE);
 }
 
 static void ggp_chat_left(ggp_chat_local_info *chat, uin_t uin)
 {
 	uin_t me;
+	int idx = ggp_chat_participant_find(chat, uin);
+
+	if (idx < 0)
+	{
+		purple_debug_warning("gg", "ggp_chat_joined: "
+			"user %u isn't present in chat %llu\n", uin, chat->id);
+		return;
+	}
+	chat->participants[idx] =
+		chat->participants[chat->participants_count - 1];
+	chat->participants_count--;
+	chat->participants = realloc(chat->participants,
+		sizeof(uin) * chat->participants_count);
+
+	if (chat->conv == NULL)
+		return;
 
 	me = ggp_str_to_uin(purple_account_get_username(
 		purple_connection_get_account(chat->gc)));
@@ -198,6 +275,7 @@ static void ggp_chat_left(ggp_chat_local
 			time(NULL));
 		serv_got_chat_left(chat->gc, chat->local_id);
 		chat->conv = NULL;
+		chat->left = TRUE;
 	}
 	purple_conv_chat_remove_user(purple_conversation_get_chat_data(
 		chat->conv), ggp_uin_to_str(uin), NULL);
@@ -259,29 +337,89 @@ static uint64_t ggp_chat_get_id_from_nam
 
 void ggp_chat_join(PurpleConnection *gc, GHashTable *components)
 {
+	ggp_chat_session_data *sdata = ggp_chat_get_sdata(gc);
 	GGPInfo *info = purple_connection_get_protocol_data(gc);
-	const gchar *id;
+	const gchar *id_cs;
+	gchar *id_s;
+	uint64_t id;
 
-	id = g_hash_table_lookup(components, "id");
-	if (id == NULL || id[0] != '\0')
+	id_cs = g_hash_table_lookup(components, "id");
+	id_s = g_strdup(id_cs);
+	if (id_s)
+		g_strstrip(id_s);
+	if (id_s == NULL || id_s[0] == '\0')
 	{
-		purple_debug_error("gg", "ggp_chat_join; cannot join\n");
+		g_free(id_s);
+		if (gg_chat_create(info->session) < 0)
+		{
+			purple_debug_error("gg", "ggp_chat_join; "
+				"cannot create\n");
+			purple_serv_got_join_chat_failed(gc, components);
+		}
+		return;
+	}
+	id = ggp_chat_get_id_from_name(id_s);
+	g_free(id_s);
+
+	if (!id)
+	{
+		char *buff = g_strdup_printf(
+			_("%s is not a valid room identifier"), id_cs);
+		purple_notify_error(gc, _("Invalid Room Identifier"),
+			_("Invalid Room Identifier"), buff);
+		g_free(buff);
 		purple_serv_got_join_chat_failed(gc, components);
 		return;
 	}
 
-	if (gg_chat_create(info->session) < 0)
+	if (sdata->got_all_chats_info)



More information about the Commits mailing list