pidgin/pidgin

69e078981440
Parents b37a9a8ad04a
Children e28d0c86b62c
Implement conversation create for the demo protocol plugin

This should support both dms and group dms, but we don't have a way to test
it yet.

Testing Done:
Compiled only for now as we don't yet have a way to trigger this in the UI.

Bugs closed: PIDGIN-17855

Reviewed at https://reviews.imfreedom.org/r/3055/
--- a/protocols/demo/purpledemoprotocolconversation.c Wed Apr 10 00:52:41 2024 -0500
+++ b/protocols/demo/purpledemoprotocolconversation.c Wed Apr 10 01:07:25 2024 -0500
@@ -18,17 +18,19 @@
#include <glib/gi18n-lib.h>
-#include "purpledemoprotocol.h"
#include "purpledemoprotocolconversation.h"
-/******************************************************************************
- * PurpleProtocolConversation Implementation
- *****************************************************************************/
+#include "purpledemoplugin.h"
+#include "purpledemoprotocol.h"
+
typedef struct {
PurpleConversation *conversation;
PurpleMessage *message;
} PurpleDemoProtocolIMInfo;
+/******************************************************************************
+ * Helpers
+ *****************************************************************************/
static void
purple_demo_protocol_im_info_free(PurpleDemoProtocolIMInfo *info) {
g_clear_object(&info->conversation);
@@ -36,6 +38,62 @@
g_free(info);
}
+static gint
+purple_demo_protocol_contact_sort(gconstpointer a, gconstpointer b,
+ G_GNUC_UNUSED gpointer data)
+{
+ return purple_contact_info_compare(PURPLE_CONTACT_INFO((gpointer)a),
+ PURPLE_CONTACT_INFO((gpointer)b));
+}
+
+static char *
+purple_demo_protocol_generate_conversation_id(PurpleAccount *account,
+ PurpleCreateConversationDetails *details)
+{
+ GChecksum *checksum = NULL;
+ GListModel *participants = NULL;
+ GListStore *sorted = NULL;
+ char *ret = NULL;
+ const char *id = NULL;
+
+ /* Sort the participants. */
+ sorted = g_list_store_new(PURPLE_TYPE_CONTACT);
+ participants = purple_create_conversation_details_get_participants(details);
+ for(guint i = 0; i < g_list_model_get_n_items(participants); i++) {
+ PurpleContactInfo *info = NULL;
+
+ info = g_list_model_get_item(participants, i);
+ g_list_store_insert_sorted(sorted, info,
+ purple_demo_protocol_contact_sort,
+ NULL);
+ g_clear_object(&info);
+ }
+
+ /* Build a checksum of the account and the sorted participants. */
+ checksum = g_checksum_new(G_CHECKSUM_SHA256);
+
+ id = purple_contact_info_get_id(PURPLE_CONTACT_INFO(account));
+ g_checksum_update(checksum, (guchar *)id, -1);
+
+ for(guint i = 0; i < g_list_model_get_n_items(G_LIST_MODEL(sorted)); i++) {
+ PurpleContactInfo *info = NULL;
+
+ info = g_list_model_get_item(G_LIST_MODEL(sorted), i);
+ id = purple_contact_info_get_id(info);
+ g_checksum_update(checksum, (guchar *)id, -1);
+ g_clear_object(&info);
+ }
+
+ ret = g_strdup(g_checksum_get_string(checksum));
+
+ g_clear_pointer(&checksum, g_checksum_free);
+
+ return ret;
+}
+
+/******************************************************************************
+ * Callbacks
+ *****************************************************************************/
static gboolean
purple_demo_protocol_echo_im_cb(gpointer data) {
PurpleDemoProtocolIMInfo *info = data;
@@ -60,6 +118,88 @@
return G_SOURCE_REMOVE;
}
+/******************************************************************************
+ * PurpleProtocolConversation Implementation
+ *****************************************************************************/
+static PurpleCreateConversationDetails *
+purple_demo_protocol_get_create_conversation_details(G_GNUC_UNUSED PurpleProtocolConversation *protocol,
+ G_GNUC_UNUSED PurpleAccount *account)
+{
+ return purple_create_conversation_details_new(9);
+}
+
+static void
+purple_demo_protocol_create_conversation_async(PurpleProtocolConversation *protocol,
+ PurpleAccount *account,
+ PurpleCreateConversationDetails *details,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer data)
+{
+ PurpleConversation *conversation = NULL;
+ PurpleConversationManager *manager = NULL;
+ PurpleConversationType type = PURPLE_CONVERSATION_TYPE_UNSET;
+ GListModel *participants = NULL;
+ GTask *task = NULL;
+ char *id = NULL;
+
+ task = g_task_new(protocol, cancellable, callback, data);
+ g_task_set_source_tag(task,
+ purple_demo_protocol_create_conversation_async);
+
+ participants = purple_create_conversation_details_get_participants(details);
+ if(g_list_model_get_n_items(participants) == 1) {
+ type = PURPLE_CONVERSATION_TYPE_DM;
+ } else {
+ type = PURPLE_CONVERSATION_TYPE_GROUP_DM;
+ }
+ id = purple_demo_protocol_generate_conversation_id(account, details);
+
+ conversation = g_object_new(
+ PURPLE_TYPE_CONVERSATION,
+ "account", account,
+ "id", id,
+ "name", "this is required for some reason",
+ "type", type,
+ NULL);
+ g_clear_pointer(&id, g_free);
+
+ for(guint i = 0; i < g_list_model_get_n_items(participants); i++) {
+ PurpleContactInfo *info = NULL;
+
+ info = g_list_model_get_item(participants, i);
+ purple_conversation_add_member(conversation, info, FALSE, NULL);
+ g_clear_object(&info);
+ }
+
+ manager = purple_conversation_manager_get_default();
+ if(!purple_conversation_manager_register(manager, conversation)) {
+ g_task_return_new_error(task, PURPLE_DEMO_DOMAIN, 0,
+ _("This conversation already exists."));
+ g_clear_object(&task);
+
+ return;
+ }
+
+ g_task_return_pointer(task, conversation, g_object_unref);
+
+ g_clear_object(&task);
+}
+
+static PurpleConversation *
+purple_demo_protocol_create_conversation_finish(G_GNUC_UNUSED PurpleProtocolConversation *protocol,
+ GAsyncResult *result,
+ GError **error)
+{
+ GTask *task = G_TASK(result);
+
+ g_return_val_if_fail(g_task_get_source_tag(task) ==
+ purple_demo_protocol_create_conversation_async,
+ NULL);
+
+ return g_task_propagate_pointer(task, error);
+}
+
static void
purple_demo_protocol_send_message_async(G_GNUC_UNUSED PurpleProtocolConversation *protocol,
PurpleConversation *conversation,
@@ -126,6 +266,13 @@
void
purple_demo_protocol_conversation_init(PurpleProtocolConversationInterface *iface) {
+ iface->get_create_conversation_details =
+ purple_demo_protocol_get_create_conversation_details;
+ iface->create_conversation_async =
+ purple_demo_protocol_create_conversation_async;
+ iface->create_conversation_finish =
+ purple_demo_protocol_create_conversation_finish;
+
iface->send_message_async = purple_demo_protocol_send_message_async;
iface->send_message_finish = purple_demo_protocol_send_message_finish;
}