pidgin.next.minor: 4a5878f9: Moved the conversation attributes API an...

evands at pidgin.im evands at pidgin.im
Mon Feb 21 18:10:59 EST 2011


----------------------------------------------------------------------
Revision: 4a5878f91c824f207ed343b57b36ae74e1baa438
Parent:   affddbabd1d28096316d8b448b0d8714d10c8630
Author:   evands at pidgin.im
Date:     02/21/11 18:08:47
Branch:   im.pidgin.pidgin.next.minor
URL: http://d.pidgin.im/viewmtn/revision/info/4a5878f91c824f207ed343b57b36ae74e1baa438

Changelog: 

Moved the conversation attributes API and the IRC periodic WHO updates to i.p.p.next.minor, where they belong.
applied changes from 3de680fff7ddd1b00149657afb7f6cd833000a90
             through 7ee5e1d431651ed2b1a54bc942d63f35580af55c

applied changes from e7c103fdfbc59bb2ca41a3c8813c4ff2847a673f
             through 22937ab220c41cd0c4a3f9e21e3db687db80da75

applied changes from 22937ab220c41cd0c4a3f9e21e3db687db80da75
             through cba010d1c097d4e6599f08276ed9d894710c1074

applied changes from a694289accbec14c593b3636ef1f626fd8279805
             through 8a43e3ddd7adacb208afe2d7ee3ea983c95901be

Changes against parent affddbabd1d28096316d8b448b0d8714d10c8630

  patched  libpurple/conversation.c
  patched  libpurple/conversation.h
  patched  libpurple/protocols/irc/irc.c
  patched  libpurple/protocols/irc/irc.h
  patched  libpurple/protocols/irc/msgs.c
  patched  libpurple/protocols/irc/parse.c

-------------- next part --------------
============================================================
--- libpurple/conversation.c	ee99c716bc1eee1b506e868d1ba00cbaf5ff511a
+++ libpurple/conversation.c	fc8223f858755be063c678670a2a68e7fabdffb1
@@ -2137,6 +2137,8 @@ purple_conv_chat_cb_new(const char *name
 	cb->name = g_strdup(name);
 	cb->flags = flags;
 	cb->alias = g_strdup(alias);
+	cb->attributes = g_hash_table_new_full(g_str_hash, g_str_equal,
+										   g_free, g_free);
 
 	PURPLE_DBUS_REGISTER_POINTER(cb, PurpleConvChatBuddy);
 	return cb;
@@ -2169,6 +2171,7 @@ purple_conv_chat_cb_destroy(PurpleConvCh
 	g_free(cb->alias);
 	g_free(cb->alias_key);
 	g_free(cb->name);
+	g_hash_table_destroy(cb->attributes);
 
 	PURPLE_DBUS_UNREGISTER_POINTER(cb);
 	g_free(cb);
@@ -2182,7 +2185,77 @@ purple_conv_chat_cb_get_name(PurpleConvC
 	return cb->name;
 }
 
+const char *
+purple_conv_chat_cb_get_attribute(PurpleConvChatBuddy *cb, const char *key)
+{
+	g_return_val_if_fail(cb != NULL, NULL);
+	g_return_val_if_fail(key != NULL, NULL);
+	
+	return g_hash_table_lookup(cb->attributes, key);
+}
+
+static void
+append_attribute_key(gpointer key, gpointer value, gpointer user_data)
+{
+	GList **list = user_data;
+	*list = g_list_prepend(*list, key);
+}
+
 GList *
+purple_conv_chat_cb_get_attribute_keys(PurpleConvChatBuddy *cb)
+{
+	GList *keys = NULL;
+	
+	g_return_val_if_fail(cb != NULL, NULL);
+	
+	g_hash_table_foreach(cb->attributes, (GHFunc)append_attribute_key, &keys);
+	
+	return keys;
+}
+
+void
+purple_conv_chat_cb_set_attribute(PurpleConvChat *chat, PurpleConvChatBuddy *cb, const char *key, const char *value)
+{
+	PurpleConversation *conv;
+	PurpleConversationUiOps *ops;
+	
+	g_return_if_fail(cb != NULL);
+	g_return_if_fail(key != NULL);
+	g_return_if_fail(value != NULL);
+	
+	g_hash_table_replace(cb->attributes, g_strdup(key), g_strdup(value));
+	
+	conv = purple_conv_chat_get_conversation(chat);
+	ops = purple_conversation_get_ui_ops(conv);
+	
+	if (ops != NULL && ops->chat_update_user != NULL)
+		ops->chat_update_user(conv, cb->name);
+}
+
+void
+purple_conv_chat_cb_set_attributes(PurpleConvChat *chat, PurpleConvChatBuddy *cb, GList *keys, GList *values)
+{
+	PurpleConversation *conv;
+	PurpleConversationUiOps *ops;
+	
+	g_return_if_fail(cb != NULL);
+	g_return_if_fail(keys != NULL);
+	g_return_if_fail(values != NULL);
+	
+	while (keys != NULL && values != NULL) {
+		g_hash_table_replace(cb->attributes, g_strdup(keys->data), g_strdup(values->data));
+		keys = g_list_next(keys);
+		values = g_list_next(values);
+	}
+	
+	conv = purple_conv_chat_get_conversation(chat);
+	ops = purple_conversation_get_ui_ops(conv);
+	
+	if (ops != NULL && ops->chat_update_user != NULL)
+		ops->chat_update_user(conv, cb->name);
+}
+
+GList *
 purple_conversation_get_extended_menu(PurpleConversation *conv)
 {
 	GList *menu = NULL;
============================================================
--- libpurple/protocols/irc/irc.c	9824f680d433623dac1d94bb4e8b6fead8d0e597
+++ libpurple/protocols/irc/irc.c	d8ff17c7e1fdddcde1c6720e7b220c49deb1c870
@@ -41,6 +41,8 @@ static void irc_ison_buddy_init(char *na
 
 static void irc_ison_buddy_init(char *name, struct irc_buddy *ib, GList **list);
 
+static void irc_who_channel(PurpleConversation *conv, struct irc_conn *irc);
+
 static const char *irc_blist_icon(PurpleAccount *a, PurpleBuddy *b);
 static GList *irc_status_types(PurpleAccount *account);
 static GList *irc_actions(PurplePlugin *plugin, gpointer context);
@@ -232,6 +234,26 @@ static void irc_ison_buddy_init(char *na
 	*list = g_list_append(*list, ib);
 }
 
+
+gboolean irc_who_channel_timeout(struct irc_conn *irc)
+{
+	// WHO all of our channels.
+	g_list_foreach(purple_get_conversations(), (GFunc)irc_who_channel, (gpointer)irc);
+	
+	return TRUE;
+}
+
+static void irc_who_channel(PurpleConversation *conv, struct irc_conn *irc)
+{
+	if (purple_conversation_get_account(conv) == irc->account && purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT) {
+		char *buf = irc_format(irc, "vc", "WHO", purple_conversation_get_name(conv));
+		
+		purple_debug(PURPLE_DEBUG_INFO, "irc", "Performing periodic who on %s", purple_conversation_get_name(conv));
+		irc_send(irc, buf);
+		g_free(buf);
+	}
+}
+
 static void irc_ison_one(struct irc_conn *irc, struct irc_buddy *ib)
 {
 	char *buf;
@@ -517,6 +539,8 @@ static void irc_close(PurpleConnection *
 	}
 	if (irc->timer)
 		purple_timeout_remove(irc->timer);
+	if (irc->who_channel_timer)
+		purple_timeout_remove(irc->who_channel_timer);
 	g_hash_table_destroy(irc->cmds);
 	g_hash_table_destroy(irc->msgs);
 	g_hash_table_destroy(irc->buddies);
============================================================
--- libpurple/conversation.h	381a495feb11bace150cc4afcf6b7b50a9c8624d
+++ libpurple/conversation.h	1b5c4abc64bc9456e7f4d60bf23713f150e1da94
@@ -139,7 +139,8 @@ typedef enum
 	PURPLE_CBFLAGS_HALFOP        = 0x0002, /**< Half-op                      */
 	PURPLE_CBFLAGS_OP            = 0x0004, /**< Channel Op or Moderator      */
 	PURPLE_CBFLAGS_FOUNDER       = 0x0008, /**< Channel Founder              */
-	PURPLE_CBFLAGS_TYPING        = 0x0010  /**< Currently typing             */
+	PURPLE_CBFLAGS_TYPING        = 0x0010, /**< Currently typing             */
+	PURPLE_CBFLAGS_AWAY          = 0x0020  /**< Currently away. @since 2.8.0 */
 
 } PurpleConvChatBuddyFlags;
 
@@ -300,6 +301,9 @@ struct _PurpleConvChatBuddy
 	PurpleConvChatBuddyFlags flags;  /**< A bitwise OR of flags for this participant,
 	                                  *   such as whether they are a channel operator.
 	                                  */
+	GHashTable *attributes;          /**< A hash table of attributes about the user, such as
+                                    *   real name, user at host, etc.
+                                    */
 };
 
 /**
@@ -513,6 +517,46 @@ const char *purple_conversation_get_name
 const char *purple_conversation_get_name(const PurpleConversation *conv);
 
 /**
+ * Get an attribute of a chat buddy
+ *
+ * @param cb	The chat buddy.
+ * @param key	The key of the attribute.
+ *
+ * @return The value of the attribute key.
+ */
+const char *purple_conv_chat_cb_get_attribute(PurpleConvChatBuddy *cb, const char *key);
+
+/**
+ * Get the keys of all atributes of a chat buddy
+ *
+ * @param cb	The chat buddy.
+ *
+ * @return A list of the attributes of a chat buddy.
+ */
+GList *purple_conv_chat_cb_get_attribute_keys(PurpleConvChatBuddy *cb);
+	
+/**
+ * Set an attribute of a chat buddy
+ *
+ * @param chat	The chat.
+ * @param cb	The chat buddy.
+ * @param key	The key of the attribute.
+ * @param value	The value of the attribute.
+ */
+void purple_conv_chat_cb_set_attribute(PurpleConvChat *chat, PurpleConvChatBuddy *cb, const char *key, const char *value);
+
+/**
+ * Set attributes of a chat buddy
+ *
+ * @param chat	The chat.
+ * @param cb	The chat buddy.
+ * @param keys	A GList of the keys.
+ * @param values A GList of the values.
+ */
+void
+purple_conv_chat_cb_set_attributes(PurpleConvChat *chat, PurpleConvChatBuddy *cb, GList *keys, GList *values);
+
+/**
  * Enables or disables logging for this conversation.
  *
  * @param conv The conversation.
============================================================
--- libpurple/protocols/irc/irc.h	df6b06ec27843e6a773c86340988fbd1dddc30a7
+++ libpurple/protocols/irc/irc.h	7e52fe9ba8caa9d1f5a4055123b287b54ef3f599
@@ -55,6 +55,7 @@ struct irc_conn {
 	char *server;
 	int fd;
 	guint timer;
+	guint who_channel_timer;
 	GHashTable *buddies;
 
 	gboolean ison_outstanding;
@@ -106,6 +107,7 @@ gboolean irc_blist_timeout(struct irc_co
 
 int irc_send(struct irc_conn *irc, const char *buf);
 gboolean irc_blist_timeout(struct irc_conn *irc);
+gboolean irc_who_channel_timeout(struct irc_conn *irc);
 void irc_buddy_query(struct irc_conn *irc);
 
 char *irc_escape_privmsg(const char *text, gssize length);
@@ -164,6 +166,7 @@ void irc_msg_whois(struct irc_conn *irc,
 void irc_msg_unknown(struct irc_conn *irc, const char *name, const char *from, char **args);
 void irc_msg_wallops(struct irc_conn *irc, const char *name, const char *from, char **args);
 void irc_msg_whois(struct irc_conn *irc, const char *name, const char *from, char **args);
+void irc_msg_who(struct irc_conn *irc, const char *name, const char *from, char **args);
 
 void irc_msg_ignore(struct irc_conn *irc, const char *name, const char *from, char **args);
 
============================================================
--- libpurple/protocols/irc/msgs.c	b5f39963e57607dc76e1fc35371acaeb0bd1f72f
+++ libpurple/protocols/irc/msgs.c	58a11bfdfa8d0e944ca399e095ec92f999244623
@@ -110,6 +110,8 @@ static void irc_connected(struct irc_con
 	irc_blist_timeout(irc);
 	if (!irc->timer)
 		irc->timer = purple_timeout_add_seconds(45, (GSourceFunc)irc_blist_timeout, (gpointer)irc);
+    if (!irc->who_channel_timer)
+        irc->who_channel_timer = purple_timeout_add_seconds(300, (GSourceFunc)irc_who_channel_timeout, (gpointer)irc);
 }
 
 void irc_msg_default(struct irc_conn *irc, const char *name, const char *from, char **args)
@@ -400,6 +402,59 @@ void irc_msg_endwhois(struct irc_conn *i
 	memset(&irc->whois, 0, sizeof(irc->whois));
 }
 
+void irc_msg_who(struct irc_conn *irc, const char *name, const char *from, char **args)
+{
+	if (!strcmp(name, "352")) {
+		PurpleConversation *conv;
+		PurpleConvChat *chat;
+		PurpleConvChatBuddy *cb;
+		
+		char *userhost, *realname;
+		
+		PurpleConvChatBuddyFlags flags;
+		GList *keys = NULL, *values = NULL;
+		
+		conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT, args[1], irc->account);
+		if (!conv) {
+			purple_debug(PURPLE_DEBUG_ERROR, "irc", "Got a WHO response for %s, which doesn't exist\n", args[1]);
+			return;
+		}
+
+		cb = purple_conv_chat_cb_find(PURPLE_CONV_CHAT(conv), args[5]);
+		if (!cb) {
+			purple_debug(PURPLE_DEBUG_ERROR, "irc", "Got a WHO response for %s who isn't a buddy.\n", args[5]);
+			return;
+		}
+
+		chat = PURPLE_CONV_CHAT(conv);
+		
+		userhost = g_strdup_printf("%s@%s", args[2], args[3]);
+		realname = g_strdup(args[8]);
+		
+		keys = g_list_prepend(keys, "userhost");
+		values = g_list_prepend(values, userhost);
+		
+		keys = g_list_prepend(keys, "realname");
+		values = g_list_prepend(values, realname);
+		
+		purple_conv_chat_cb_set_attributes(chat, cb, keys, values);
+		
+		g_list_free(keys);
+		g_list_free(values);
+		
+		g_free(userhost);
+		g_free(realname);
+		
+		flags = purple_conv_chat_user_get_flags(chat, cb->name);
+
+		if (args[6][0] == 'G' && !(flags & PURPLE_CBFLAGS_AWAY)) {
+			purple_conv_chat_user_set_flags(chat, cb->name, flags | PURPLE_CBFLAGS_AWAY);
+		} else if(args[6][0] == 'H' && (flags & PURPLE_CBFLAGS_AWAY)) {
+			purple_conv_chat_user_set_flags(chat, cb->name, flags & ~PURPLE_CBFLAGS_AWAY);
+		}
+	}
+}
+
 void irc_msg_list(struct irc_conn *irc, const char *name, const char *from, char **args)
 {
 	if (!irc->roomlist)
@@ -797,7 +852,10 @@ void irc_msg_join(struct irc_conn *irc, 
 {
 	PurpleConnection *gc = purple_account_get_connection(irc->account);
 	PurpleConversation *convo;
-	char *nick = irc_mask_nick(from), *userhost;
+	PurpleConvChat *chat;
+	PurpleConvChatBuddy *cb;
+
+	char *nick = irc_mask_nick(from), *userhost, *buf;
 	struct irc_buddy *ib;
 	static int id = 1;
 
@@ -820,6 +878,12 @@ void irc_msg_join(struct irc_conn *irc, 
 		}
 		purple_conversation_set_data(convo, IRC_NAMES_FLAG,
 					   GINT_TO_POINTER(FALSE));
+		
+		// Get the real name and user host for all participants.
+		buf = irc_format(irc, "vc", "WHO", args[0]);
+		irc_send(irc, buf);
+		g_free(buf);
+		
 		/* Until purple_conversation_present does something that
 		 * one would expect in Pidgin, this call produces buggy
 		 * behavior both for the /join and auto-join cases. */
@@ -835,8 +899,16 @@ void irc_msg_join(struct irc_conn *irc, 
 	}
 
 	userhost = irc_mask_userhost(from);
-	purple_conv_chat_add_user(PURPLE_CONV_CHAT(convo), nick, userhost, PURPLE_CBFLAGS_NONE, TRUE);
-
+	chat = PURPLE_CONV_CHAT(convo);
+	
+	purple_conv_chat_add_user(chat, nick, userhost, PURPLE_CBFLAGS_NONE, TRUE);
+	
+	cb = purple_conv_chat_cb_find(chat, nick);
+	
+	if (cb) {
+		purple_conv_chat_cb_set_attribute(chat, cb, "userhost", userhost);		
+	}
+	
 	if ((ib = g_hash_table_lookup(irc->buddies, nick)) != NULL) {
 		ib->new_online_status = TRUE;
 		irc_buddy_status(nick, ib, irc);
============================================================
--- libpurple/protocols/irc/parse.c	bef80be622ee6689a6c7cc26d8022584cfcfaa3d
+++ libpurple/protocols/irc/parse.c	0dcf2c2d3ec3063211329a0e332672c1048c7cf9
@@ -65,6 +65,7 @@ static struct _irc_msg {
 	{ "319", "nn:", irc_msg_whois },	/* Whois channels		*/
 	{ "320", "nn:", irc_msg_whois },	/* Whois (fn ident)		*/
 	{ "314", "nnnvv:", irc_msg_whois },	/* Whowas user			*/
+	{ "315", "nt:", irc_msg_who },      /* end of WHO channel   */
 	{ "369", "nt:", irc_msg_endwhois },	/* End of WHOWAS		*/
 	{ "321", "*", irc_msg_list },		/* Start of list		*/
 	{ "322", "ncv:", irc_msg_list },	/* List.			*/
@@ -73,6 +74,7 @@ static struct _irc_msg {
 	{ "331", "nc:",	irc_msg_topic },	/* No channel topic		*/
 	{ "332", "nc:", irc_msg_topic },	/* Channel topic		*/
 	{ "333", "*", irc_msg_ignore },		/* Topic setter stuff		*/
+	{ "352", "nvcvnvvv:", irc_msg_who },/* Channel WHO			*/
 	{ "353", "nvc:", irc_msg_names },	/* Names list			*/
 	{ "366", "nc:", irc_msg_names },	/* End of names			*/
 	{ "367", "ncnnv", irc_msg_ban },	/* Ban list			*/


More information about the Commits mailing list