IRCv3: add support for away-notify

Tue, 15 Apr 2025 19:32:11 -0500

author
Gary Kramlich <grim@reaperworld.com>
date
Tue, 15 Apr 2025 19:32:11 -0500
changeset 43228
6f895d255386
parent 43227
332f1bad44cc
child 43229
c3d06b7a6126

IRCv3: add support for away-notify

This adds support for the away-notify specification and handles AWAY messages
for users and updates their presence accordingly. This also defaults all IRC
contacts to being online.

Testing Done:
Used a temporary `g_warning` to verify the presence changes from another client. Also called in the turtles.

Bugs closed: PIDGIN-18088

Reviewed at https://reviews.imfreedom.org/r/3968/

protocols/ircv3/purpleircv3connection.c file | annotate | diff | comparison | revisions
protocols/ircv3/purpleircv3messagehandlers.c file | annotate | diff | comparison | revisions
protocols/ircv3/purpleircv3messagehandlers.h file | annotate | diff | comparison | revisions
--- a/protocols/ircv3/purpleircv3connection.c	Tue Apr 15 12:51:42 2025 -0500
+++ b/protocols/ircv3/purpleircv3connection.c	Tue Apr 15 19:32:11 2025 -0500
@@ -449,6 +449,9 @@
 	                        G_CALLBACK(purple_ircv3_message_handler_tagmsg),
 	                        connection, G_CONNECT_DEFAULT);
 
+	g_signal_connect_object(client, "message::" IBIS_MSG_AWAY,
+	                        G_CALLBACK(purple_ircv3_message_handler_away),
+	                        connection, G_CONNECT_DEFAULT);
 	g_signal_connect_object(client, "message::" IBIS_MSG_JOIN,
 	                        G_CALLBACK(purple_ircv3_message_handler_join),
 	                        connection, G_CONNECT_DEFAULT);
@@ -583,6 +586,10 @@
 	 */
 	ibis_capabilities_lookup_and_request(capabilities,
 	                                     IBIS_CAPABILITY_ACCOUNT_TAG);
+
+	/* away-notify tells us when users in a channel go away or come back. */
+	ibis_capabilities_lookup_and_request(capabilities,
+	                                     IBIS_CAPABILITY_AWAY_NOTIFY);
 }
 
 static void
@@ -961,6 +968,7 @@
 	PurpleAccount *account = NULL;
 	PurpleContact *contact = NULL;
 	PurpleContactManager *manager = NULL;
+	PurplePresence *presence = NULL;
 	IbisTags *tags = NULL;
 	const char *source = NULL;
 	char *nick = NULL;
@@ -1001,6 +1009,11 @@
 	purple_contact_info_set_sid(PURPLE_CONTACT_INFO(contact), source);
 	purple_contact_info_set_display_name(PURPLE_CONTACT_INFO(contact), nick);
 
+	/* Grab the presence and set it as online right away. */
+	presence = purple_contact_info_get_presence(PURPLE_CONTACT_INFO(contact));
+	purple_presence_set_primitive(presence,
+	                              PURPLE_PRESENCE_PRIMITIVE_AVAILABLE);
+
 	g_free(nick);
 
 	return contact;
--- a/protocols/ircv3/purpleircv3messagehandlers.c	Tue Apr 15 12:51:42 2025 -0500
+++ b/protocols/ircv3/purpleircv3messagehandlers.c	Tue Apr 15 19:32:11 2025 -0500
@@ -192,6 +192,49 @@
  * General Commands
  *****************************************************************************/
 gboolean
+purple_ircv3_message_handler_away(G_GNUC_UNUSED IbisClient *client,
+                                  G_GNUC_UNUSED const char *command,
+                                  IbisMessage *message,
+                                  gpointer data)
+{
+	PurpleIRCv3Connection *connection = data;
+	PurpleContact *contact = NULL;
+	PurplePresence *presence = NULL;
+	GStrv params = NULL;
+	char *away_message = NULL;
+
+	contact = purple_ircv3_connection_find_or_create_contact(connection,
+	                                                         message);
+
+	presence = purple_contact_info_get_presence(PURPLE_CONTACT_INFO(contact));
+
+	/* Figure out if we have a message. */
+	params = ibis_message_get_params(message);
+	if(params != NULL) {
+		away_message = g_strjoinv(" ", params);
+	}
+
+	/* We have a message so we need to set it and possibly set the presence to
+	 * away.
+	 */
+	if(!purple_strempty(away_message)) {
+		purple_presence_set_message(presence, away_message);
+
+		purple_presence_set_primitive(presence,
+		                              PURPLE_PRESENCE_PRIMITIVE_AWAY);
+	} else {
+		purple_presence_set_message(presence, NULL);
+
+		purple_presence_set_primitive(presence,
+		                              PURPLE_PRESENCE_PRIMITIVE_AVAILABLE);
+	}
+
+	g_clear_pointer(&away_message, g_free);
+
+	return TRUE;
+}
+
+gboolean
 purple_ircv3_message_handler_join(G_GNUC_UNUSED IbisClient *client,
                                   G_GNUC_UNUSED const char *command,
                                   IbisMessage *message,
--- a/protocols/ircv3/purpleircv3messagehandlers.h	Tue Apr 15 12:51:42 2025 -0500
+++ b/protocols/ircv3/purpleircv3messagehandlers.h	Tue Apr 15 19:32:11 2025 -0500
@@ -38,6 +38,7 @@
 
 G_BEGIN_DECLS
 
+G_GNUC_INTERNAL gboolean purple_ircv3_message_handler_away(IbisClient *client, const char *command, IbisMessage *message, gpointer data);
 G_GNUC_INTERNAL gboolean purple_ircv3_message_handler_join(IbisClient *client, const char *command, IbisMessage *message, gpointer data);
 G_GNUC_INTERNAL gboolean purple_ircv3_message_handler_part(IbisClient *client, const char *command, IbisMessage *message, gpointer data);
 G_GNUC_INTERNAL gboolean purple_ircv3_message_handler_namreply(IbisClient *client, const char *command, IbisMessage *message, gpointer data);

mercurial