diff --git a/README.md b/README.md index 35a5674..665b9f0 100644 --- a/README.md +++ b/README.md @@ -19,8 +19,14 @@ mobile clients to send and receive IMs over SMTP+IMAP. It may be useful for GUI desktop usage **without** an Electron dependency, or console desktop usage. Current status is probably best described as "skunkworks", although connecting -to an account and sending / receiving text messages should work reliably. You -can view specific progress on [the issue board](https://gitlab.com/lupine/purple-plugin-delta/boards). +to an account and sending / receiving text and image messages should work +reliably in pidgin. Chatty supports text messages, and can be coaxed into using +this plugin, but there's a long way to go with that yet. + +A big refactoring to use "proper" purple IM structures is necessary to make +further progress, I think. + +I also need to implement support for the buddy list. We currrently build against deltachat v1.50.0. You'll need to build and install deltachat-ffi separately and ensure that it's available via `pkg-config` for diff --git a/delta-connection.c b/delta-connection.c index ee882aa..ffd69de 100644 --- a/delta-connection.c +++ b/delta-connection.c @@ -14,7 +14,7 @@ #define IMEX_RECEIVED_MESSAGE "Setup message received. To apply it, reply with:\nIMEX: %d nnnn-nnnn-nnnn-nnnn-nnnn-nnnn-nnnn-nnnn-nnnn\nNo whitespace in the setup-code!" -void delta_recv_im(DeltaConnectionData *conn, uint32_t msg_id); +void delta_recv_im(DeltaConnectionData *conn, dc_msg_t *msg); void _transpose_config(dc_context_t *mailbox, PurpleAccount *acct) @@ -59,6 +59,7 @@ typedef struct { // Used by delta_process_incoming_message uint32_t msg_id; + gboolean msg_changed; // Used by delta_process_connection_state int connection_state; @@ -71,8 +72,9 @@ delta_process_incoming_message(void *data) g_assert(pr != NULL); g_assert(pr->conn != NULL); - delta_recv_im(pr->conn, pr->msg_id); - + dc_msg_t *msg = dc_get_msg(pr->conn->mailbox, pr->msg_id); + delta_recv_im(pr->conn, msg); + dc_msg_unref(msg); g_free(data); return FALSE; @@ -107,19 +109,24 @@ delta_process_fresh_messages(void *data) ProcessRequest *pr = (ProcessRequest *)data; g_assert(pr != NULL); g_assert(pr->conn != NULL); - g_assert(pr->conn->mailbox != NULL); + + dc_context_t *mailbox = pr->conn->mailbox; + g_assert(mailbox != NULL); // Spot any messages received while offline - dc_array_t *fresh_msgs = dc_get_fresh_msgs(pr->conn->mailbox); + dc_array_t *fresh_msgs = dc_get_fresh_msgs(mailbox); size_t fresh_count = dc_array_get_cnt(fresh_msgs); purple_debug_info(PLUGIN_ID, "fresh_count: %zu\n", fresh_count); for(size_t i = 0; i < fresh_count; i++) { - delta_recv_im(pr->conn, dc_array_get_id(fresh_msgs, i)); + uint32_t msg_id = dc_array_get_id(fresh_msgs, i); + dc_msg_t *msg = dc_get_msg(mailbox, msg_id); + + delta_recv_im(pr->conn, msg); } - g_free(fresh_msgs); + dc_array_unref(fresh_msgs); return FALSE; } @@ -194,8 +201,10 @@ delta_event_handler(void *context) pr = delta_build_process_request(conn); if (msg_id) { - // FIXME: they won't all be incoming. Some will be changed + // FIXME: for now, only display IMEX setup messages to avoid duplicates pr->msg_id = msg_id; + pr->msg_changed = TRUE; + purple_timeout_add(0, delta_process_incoming_message, pr); } else { purple_timeout_add(0, delta_process_fresh_messages, pr); @@ -419,11 +428,11 @@ next: } g_free(stripped_message); - return 1; // success; echo the message to the chat window + return 0; // success; don't echo the message to the chat window since we display it anyway } void -delta_recv_im(DeltaConnectionData *conn, uint32_t msg_id) +delta_recv_im(DeltaConnectionData *conn, dc_msg_t *msg) { dc_context_t *mailbox = conn->mailbox; g_assert(mailbox != NULL); @@ -431,11 +440,12 @@ delta_recv_im(DeltaConnectionData *conn, uint32_t msg_id) PurpleConnection *pc = conn->pc; g_assert(pc != NULL); - dc_msg_t *msg = dc_get_msg(mailbox, msg_id); + uint32_t msg_id = dc_msg_get_id(msg); int viewtype = dc_msg_get_viewtype(msg); time_t timestamp = dc_msg_get_timestamp(msg); char *text = dc_msg_get_text(msg); uint32_t chat_id = dc_msg_get_chat_id(msg); + dc_contact_t *from = dc_get_contact(mailbox, dc_msg_get_from_id(msg)); dc_chat_t *chat = dc_get_chat(mailbox, chat_id); dc_array_t *contacts = dc_get_chat_contacts(mailbox, chat_id); int num_contacts = dc_array_get_cnt(contacts); @@ -468,14 +478,21 @@ delta_recv_im(DeltaConnectionData *conn, uint32_t msg_id) who = dc_chat_get_name(chat); } - int flags = PURPLE_MESSAGE_RECV; + int flags = 0; + int state = dc_msg_get_state(msg); + + if (state == DC_STATE_IN_FRESH || state == DC_STATE_IN_NOTICED || state == DC_STATE_IN_SEEN) { + flags |= PURPLE_MESSAGE_RECV; + } else { + flags |= PURPLE_MESSAGE_SEND; + } // FIXME: as a massive hack, convert IMEX setup messages into a text message // prompting the user how to trigger the IMEX filter in outgoing messages. if (dc_msg_is_setupmessage(msg)) { purple_debug_info(PLUGIN_ID, "Receiving IMEX: ID=%d\n", msg_id); viewtype = DC_MSG_TEXT; - g_free(text); + dc_str_unref(text); text = g_strndup("", 1024); g_assert(text != NULL); @@ -519,18 +536,25 @@ delta_recv_im(DeltaConnectionData *conn, uint32_t msg_id) text = g_strdup_printf("", image_id); } - serv_got_im(pc, who, text, flags, timestamp); + char *name = dc_contact_get_name(from); + int msglen = strlen(name) + 3 + strlen(text); + + char *msgtext = malloc(msglen); + g_snprintf(msgtext, msglen, "%s: %s", name, text); + + serv_got_im(pc, who, msgtext, flags, timestamp); if (image_id > 0) { purple_imgstore_unref_by_id(image_id); } dc_markseen_msgs(mailbox, &msg_id, 1); - g_free(who); + g_free(msgtext); + dc_str_unref(who); + dc_str_unref(name); dc_contact_unref(contact); out: - g_free(text); - dc_msg_unref(msg); + dc_str_unref(text); dc_chat_unref(chat); dc_array_unref(contacts); } diff --git a/libdelta.h b/libdelta.h index fd018aa..d7423a5 100644 --- a/libdelta.h +++ b/libdelta.h @@ -8,7 +8,8 @@ #define DELTA_PROTOCOL_OPTS \ OPT_PROTO_UNIQUE_CHATNAME | \ OPT_PROTO_CHAT_TOPIC | \ - OPT_PROTO_IM_IMAGE + OPT_PROTO_IM_IMAGE | \ + OPT_PROTO_MAIL_CHECK // These two will instead be the pidgin "username" and "password" options that // I can't seem to get rid of.