satoriapi.c

changeset 3
33a7b189a2c6
parent 1
98bcf06036b8
--- a/satoriapi.c	Sun Aug 10 23:03:27 2025 +0800
+++ b/satoriapi.c	Sun Aug 10 23:53:22 2025 +0800
@@ -25,6 +25,7 @@
 
 #include "purplesatoriconnection.h"
 #include "purplesatoriplugin.h"
+#include "purplesatoriprotocolconversation.h"
 #include "satorimessage.h"
 #include "satoritypes.h"
 #include "satoriapi.h"
@@ -153,9 +154,12 @@
 		found = FALSE;
 	}
 
-	purple_contact_info_set_display_name(
-		PURPLE_CONTACT_INFO(contact),
-		user->nick ? user->nick : user->name);
+	if (user->nick)
+		purple_contact_info_set_display_name(
+			PURPLE_CONTACT_INFO(contact), user->nick);
+	else if (user->name)
+		purple_contact_info_set_display_name(
+			PURPLE_CONTACT_INFO(contact), user->name);
 
 	PurplePresence *presence = purple_contact_info_get_presence(
 		PURPLE_CONTACT_INFO(contact));
@@ -252,8 +256,7 @@
 		JB_END_OBJ(data, b);
 	}
 
-	SoupMessage *msg = satori_message_new(
-		"POST", SATORI_ENDPOINT("/v1/friend.list"));
+	SoupMessage *msg = SATORI_ENDPOINT(con, "/friend.list");
 	soup_message_set_request_body_from_bytes(msg, "application/json", data);
 
 	purple_satori_connection_send_and_read_async(
@@ -337,8 +340,7 @@
 		JB_END_OBJ(data, b);
 	}
 
-	SoupMessage *msg = satori_message_new(
-		"POST", SATORI_ENDPOINT("/v1/channel.list"));
+	SoupMessage *msg = SATORI_ENDPOINT(con, "/channel.list");
 	soup_message_set_request_body_from_bytes(msg, "application/json", data);
 
 	purple_satori_connection_send_and_read_async(
@@ -412,8 +414,7 @@
 		JB_END_OBJ(data, b);
 	}
 
-	SoupMessage *msg = satori_message_new(
-		"POST", SATORI_ENDPOINT("/v1/guild.list"));
+	SoupMessage *msg = SATORI_ENDPOINT(con, "/guild.list");
 	soup_message_set_request_body_from_bytes(msg, "application/json", data);
 
 	purple_satori_connection_send_and_read_async(
@@ -425,6 +426,10 @@
 	g_bytes_unref(data);
 }
 
+/******************************************************************************
+ * DM Creation
+ *****************************************************************************/
+
 typedef struct {
 	PurpleSatoriConnection *con;
 	SatoriUser user;
@@ -497,8 +502,7 @@
 		JB_END_OBJ(data, b);
 	}
 
-	SoupMessage *msg = satori_message_new(
-		"POST", SATORI_ENDPOINT("/v1/user.channel.create"));
+	SoupMessage *msg = SATORI_ENDPOINT(con, "/user.channel.create");
 	soup_message_set_request_body_from_bytes(msg, "application/json", data);
 
 	SatoriOnDmChannelData *dptr = g_new0(SatoriOnDmChannelData, 1);
@@ -515,3 +519,110 @@
 	g_object_unref(msg);
 	g_bytes_unref(data);
 }
+
+/******************************************************************************
+ * Message Routines
+ *****************************************************************************/
+
+typedef struct {
+	PurpleConversation *conversation;
+	PurpleMessage *message;
+	GTask *task;
+} SatoriSendMessageData;
+
+static void
+satori_on_message_sent(SoupSession *session,
+		       GAsyncResult *res,
+		       SatoriSendMessageData *dptr)
+{
+	GError *error = NULL;
+	GBytes *resp = soup_session_send_and_read_finish(session, res, &error);
+
+	if (error) {
+		purple_debug_error("satori",
+				   "create_dm_channel failed: %s",
+				   error->message);
+		if (resp)
+			g_bytes_unref(resp);
+
+		g_task_return_error(dptr->task, error);
+		goto cleanup;
+	}
+
+	gsize sz;
+	const gchar *ptr = g_bytes_get_data(resp, &sz);
+
+	JsonParser *parser = json_parser_new();
+	if (!json_parser_load_from_data(parser, ptr, sz, NULL)) {
+		purple_debug_warning("satori", "bad json received from api");
+		g_task_return_new_error_literal(dptr->task, PURPLE_SATORI_DOMAIN, 0,
+						"bad json received from api");
+		goto cleanup;
+	}
+
+	/* Initialize ID */
+
+	JsonArray *root = json_node_get_array(json_parser_get_root(parser));
+	JsonObject *msg_obj = json_array_get_object_element(root, 0);
+	const gchar *id = json_object_get_string_member_with_default(
+		msg_obj, "id", NULL);
+
+	if (!id) {
+		g_task_return_new_error_literal(dptr->task, PURPLE_SATORI_DOMAIN, 0,
+						"message not found");
+		goto cleanup;
+	}
+
+	purple_message_set_id(dptr->message, id);
+	purple_message_set_delivered(dptr->message, TRUE);
+
+	/* Initialize created_time */
+
+	time_t created_at = json_object_get_int_member_with_default(
+		msg_obj, "created_at", 0) / 1000; /* timestamp in mS */
+
+	if (created_at) {
+		GDateTime *ts = g_date_time_new_from_unix_local(created_at);
+		purple_message_set_delivered_at(dptr->message, ts);
+		g_date_time_unref(ts);
+	}
+
+	g_task_return_boolean(dptr->task, TRUE);
+	g_object_unref(parser);
+cleanup:
+	g_clear_object(&dptr->task);
+	g_free(dptr);
+}
+
+void
+satori_send_message(PurpleSatoriConnection *con,
+		    PurpleConversation *conversation,
+		    PurpleMessage *message,
+		    const gchar *content,
+		    GTask *task)
+{
+	GBytes *data = NULL;
+
+	{
+		JB_BEGIN_OBJ(b);
+		JBA(b, "channel_id", purple_conversation_get_id(conversation));
+		JBA(b, "content", content);
+		JB_END_OBJ(data, b);
+	}
+
+	SoupMessage *msg = SATORI_ENDPOINT(con, "/message.create");
+	soup_message_set_request_body_from_bytes(msg, "application/json", data);
+
+	SatoriSendMessageData *dptr = g_new0(SatoriSendMessageData, 1);
+	dptr->conversation = conversation;
+	dptr->message = message;
+	dptr->task = task;
+
+	purple_satori_connection_send_and_read_async(
+		con, msg, 0, NULL,
+		(GAsyncReadyCallback) satori_on_message_sent,
+		dptr);
+
+	g_object_unref(msg);
+	g_bytes_unref(data);
+}

mercurial