pidgin/pidgin

c1af98cbd43a
Parents 365eaa9d46f8
Children c3946f9d7d2d
IRCv3: Implement join and part message handlers

This only handle the RFC versions, we'll do extended-join later.

The TODO's are not meant to be done in this RR because they require additional code in IRCv3Connection, and once that's done we'll grab these then.

Testing Done:
Connected to my local ergo and had another client join and part a few times while I verified that the member list was updated correctly.

Reviewed at https://reviews.imfreedom.org/r/3235/
--- a/protocols/ircv3/purpleircv3connection.c Fri Jun 07 15:18:15 2024 -0500
+++ b/protocols/ircv3/purpleircv3connection.c Fri Jun 07 17:45:00 2024 -0500
@@ -86,6 +86,13 @@
G_CALLBACK(purple_ircv3_message_handler_privmsg),
connection, G_CONNECT_DEFAULT);
+ g_signal_connect_object(client, "message::" IBIS_MSG_JOIN,
+ G_CALLBACK(purple_ircv3_message_handler_join),
+ connection, G_CONNECT_DEFAULT);
+ g_signal_connect_object(client, "message::" IBIS_MSG_PART,
+ G_CALLBACK(purple_ircv3_message_handler_part),
+ connection, G_CONNECT_DEFAULT);
+
g_signal_connect_object(client, "message",
G_CALLBACK(purple_ircv3_connection_unknown_message_cb),
connection, G_CONNECT_AFTER);
--- a/protocols/ircv3/purpleircv3messagehandlers.c Fri Jun 07 15:18:15 2024 -0500
+++ b/protocols/ircv3/purpleircv3messagehandlers.c Fri Jun 07 17:45:00 2024 -0500
@@ -28,9 +28,156 @@
#include "purpleircv3core.h"
/******************************************************************************
+ * Helpers
+ *****************************************************************************/
+static void
+purple_ircv3_add_contact_to_conversation(PurpleContact *contact,
+ PurpleConversation *conversation)
+{
+ PurpleConversationMember *member = NULL;
+
+ member = purple_conversation_find_member(conversation,
+ PURPLE_CONTACT_INFO(contact));
+
+ if(!PURPLE_IS_CONVERSATION_MEMBER(member)) {
+ purple_conversation_add_member(conversation,
+ PURPLE_CONTACT_INFO(contact),
+ TRUE, NULL);
+ }
+}
+
+/******************************************************************************
* General Commands
*****************************************************************************/
gboolean
+purple_ircv3_message_handler_join(G_GNUC_UNUSED IbisClient *client,
+ G_GNUC_UNUSED const char *command,
+ IbisMessage *message,
+ gpointer data)
+{
+ PurpleIRCv3Connection *connection = data;
+ PurpleContact *contact = NULL;
+ PurpleConversation *conversation = NULL;
+ GStrv params = NULL;
+ guint n_params = 0;
+ char *nick = NULL;
+ const char *source = NULL;
+ const char *conversation_name = NULL;
+
+ source = ibis_message_get_source(message);
+ ibis_source_parse(source, &nick, NULL, NULL);
+ if(purple_strempty(nick)) {
+ /* We _shouldn't_ be able to get an empty nick, but just in case... */
+ g_clear_pointer(&nick, g_free);
+
+ /* TODO: write message about being unable to parse source to status
+ * window.
+ */
+
+ return TRUE;
+ }
+
+ contact = purple_ircv3_connection_find_or_create_contact(connection, nick);
+ purple_contact_info_set_sid(PURPLE_CONTACT_INFO(contact), source);
+
+ g_free(nick);
+
+ params = ibis_message_get_params(message);
+ n_params = g_strv_length(params);
+
+ /* A normal join command has the channel as the only parameter. */
+ if(n_params == 1) {
+ conversation_name = params[0];
+ } else {
+ /* TODO: write this to join to the status window saying we didn't know
+ * how to parse it.
+ */
+
+ return TRUE;
+ }
+
+ conversation = purple_ircv3_connection_find_or_create_conversation(connection,
+ conversation_name);
+ purple_ircv3_add_contact_to_conversation(contact, conversation);
+
+ return TRUE;
+}
+
+gboolean
+purple_ircv3_message_handler_part(G_GNUC_UNUSED IbisClient *client,
+ G_GNUC_UNUSED const char *command,
+ IbisMessage *message,
+ gpointer data)
+{
+ PurpleIRCv3Connection *connection = data;
+ PurpleAccount *account = NULL;
+ PurpleContact *contact = NULL;
+ PurpleConversation *conversation = NULL;
+ PurpleConversationManager *manager = NULL;
+ GStrv params = NULL;
+ guint n_params = 0;
+ char *reason = NULL;
+ char *nick = NULL;
+ const char *conversation_name = NULL;
+ const char *source = NULL;
+
+ params = ibis_message_get_params(message);
+ if(g_strv_length(params) == 0) {
+ /* TODO: mention unparsable message in the status window. */
+ return TRUE;
+ }
+
+ /* TODO: The spec says servers _SHOULD NOT_ send a comma separated list of
+ * channels, but we should support that at some point just in case.
+ */
+ conversation_name = params[0];
+
+ account = purple_connection_get_account(PURPLE_CONNECTION(connection));
+ manager = purple_conversation_manager_get_default();
+ conversation = purple_conversation_manager_find_with_id(manager, account,
+ conversation_name);
+
+ if(!PURPLE_IS_CONVERSATION(conversation)) {
+ /* TODO: write status message unknown channel. */
+
+ return TRUE;
+ }
+
+ source = ibis_message_get_source(message);
+ ibis_source_parse(source, &nick, NULL, NULL);
+ if(purple_strempty(nick)) {
+ /* We _shouldn't_ be able to get an empty nick, but just in case... */
+ g_clear_pointer(&nick, g_free);
+
+ /* TODO: write message about being unable to parse source to status
+ * window.
+ */
+
+ return TRUE;
+ }
+
+ /* We do want to find or create the contact, even on a part, because we
+ * could have connected to a BNC and we weren't told about the contact yet.
+ */
+ contact = purple_ircv3_connection_find_or_create_contact(connection, nick);
+ g_free(nick);
+
+ /* If a part message was given, join the remaining parameters with a space.
+ */
+ if(n_params > 1) {
+ reason = g_strjoinv(" ", params + 1);
+ }
+
+ purple_conversation_remove_member(conversation,
+ PURPLE_CONTACT_INFO(contact), TRUE,
+ reason);
+
+ g_clear_pointer(&reason, g_free);
+
+ return TRUE;
+}
+
+gboolean
purple_ircv3_message_handler_privmsg(G_GNUC_UNUSED IbisClient *client,
const char *command,
IbisMessage *ibis_message, gpointer data)
@@ -79,21 +226,9 @@
target);
/* Find or create the contact. */
contact = purple_ircv3_connection_find_or_create_contact(connection, nick);
- if(PURPLE_IS_CONTACT(contact)) {
- PurpleConversationMember *member = NULL;
-
- /* Update the contact's sid as it may have changed. */
- purple_contact_info_set_sid(PURPLE_CONTACT_INFO(contact), source);
+ purple_contact_info_set_sid(PURPLE_CONTACT_INFO(contact), source);
- /* Make sure the contact is in the conversation. */
- member = purple_conversation_find_member(conversation,
- PURPLE_CONTACT_INFO(contact));
- if(!PURPLE_IS_CONVERSATION_MEMBER(member)) {
- purple_conversation_add_member(conversation,
- PURPLE_CONTACT_INFO(contact),
- FALSE, NULL);
- }
- }
+ purple_ircv3_add_contact_to_conversation(contact, conversation);
if(purple_strequal(command, IBIS_MSG_NOTICE)) {
flags |= PURPLE_MESSAGE_NOTIFY;
--- a/protocols/ircv3/purpleircv3messagehandlers.h Fri Jun 07 15:18:15 2024 -0500
+++ b/protocols/ircv3/purpleircv3messagehandlers.h Fri Jun 07 17:45:00 2024 -0500
@@ -38,6 +38,8 @@
G_BEGIN_DECLS
+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_privmsg(IbisClient *client, const char *command, IbisMessage *message, gpointer data);
G_GNUC_INTERNAL gboolean purple_ircv3_message_handler_topic(IbisClient *client, const char *command, IbisMessage *message, gpointer data);