From 27eef20fab781a6f9ef5529a5e8bdeb08afb7385 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hermann=20H=C3=B6hne?= Date: Mon, 13 Mar 2023 00:04:17 +0100 Subject: [PATCH] Rework display of messages. Should help with #130 and #151. --- src/c/bridge.h | 3 +-- src/c/display_message.c | 52 +++++++++++++++++----------------------- src/c/process_message.c | 4 ++-- src/c/purple_compat.h | 1 + src/go/bridge.go | 40 +++++++++++++++---------------- src/go/handle_message.go | 4 ++-- src/go/send_message.go | 5 ++-- 7 files changed, 51 insertions(+), 58 deletions(-) diff --git a/src/c/bridge.h b/src/c/bridge.h index f37ffd2..e63b5ee 100644 --- a/src/c/bridge.h +++ b/src/c/bridge.h @@ -79,8 +79,7 @@ struct gowhatsapp_message { char msgtype; /// message type – see above char subtype; /// loglevel, error severity, attachment type or online-state char isGroup; /// this is a group chat message - char fromMe; /// this is (a copy of) an outgoing message - char system; /// this is a system-message, not user-generated + char isOutgoing; /// this is an outgoing message (echo sent from this instance) }; typedef struct gowhatsapp_message gowhatsapp_message_t; diff --git a/src/c/display_message.c b/src/c/display_message.c index 0859345..ed2cdb7 100644 --- a/src/c/display_message.c +++ b/src/c/display_message.c @@ -1,17 +1,6 @@ #include "gowhatsapp.h" #include "constants.h" -static -PurpleConversation *gowhatsapp_have_conversation(char *username, PurpleAccount *account) { - gowhatsapp_ensure_buddy_in_blist(account, username, NULL); - - PurpleConversation *conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, username, account); - if (conv == NULL) { - conv = purple_conversation_new(PURPLE_CONV_TYPE_IM, account, username); // MEMCHECK: caller takes ownership - } - return conv; -} - void gowhatsapp_display_text_message(PurpleConnection *pc, gowhatsapp_message_t *gwamsg, PurpleMessageFlags flags) { @@ -31,35 +20,38 @@ gowhatsapp_display_text_message(PurpleConnection *pc, gowhatsapp_message_t *gwam } } - if (gwamsg->fromMe) { - // special handling of messages sent by self incoming from remote, addressing issue #32 - // copied from EionRobb/purple-discord/blob/master/libdiscord.c - flags |= PURPLE_MESSAGE_SEND | PURPLE_MESSAGE_REMOTE_SEND | PURPLE_MESSAGE_DELAYED; + if (purple_strequal(purple_account_get_username(gwamsg->account), gwamsg->senderJid)) { + flags |= PURPLE_MESSAGE_SEND; + // Note: For outgoing messages (no matter if local echo or sent by other device), + // PURPLE_MESSAGE_SEND must be set due to how purple_conversation_write is implemented + if (!gwamsg->isOutgoing) { + // special handling of messages sent by self incoming from remote, addressing issue #32 + // adjusted for Spectrum, see issue #130 + flags |= PURPLE_MESSAGE_REMOTE_SEND; + } } else { flags |= PURPLE_MESSAGE_RECV; } + if (gwamsg->isGroup) { PurpleConversation *conv = gowhatsapp_enter_group_chat(pc, gwamsg->remoteJid, NULL); if (conv != NULL) { - // participants in group chats have their senderJid supplied - const char *who = gwamsg->senderJid; - if (gwamsg->fromMe) { - who = purple_account_get_username(gwamsg->account); - } - PurpleConvChat *conv_chat = purple_conversation_get_chat_data(conv); - purple_conv_chat_write(conv_chat, who, gwamsg->text, flags, gwamsg->timestamp); + purple_serv_got_chat_in(pc, g_str_hash(gwamsg->remoteJid), gwamsg->senderJid, flags, gwamsg->text, gwamsg->timestamp); } } else { - if (gwamsg->fromMe) { - PurpleConversation *conv = gowhatsapp_have_conversation(gwamsg->remoteJid, gwamsg->account); - // display message sent from own account (but other device) here - purple_conversation_write(conv, gwamsg->remoteJid, gwamsg->text, flags, gwamsg->timestamp); + if (flags & PURPLE_MESSAGE_SEND) { + // display message sent from own account (other device as well as local echo) + // cannot use purple_serv_got_im since it sets the flag PURPLE_MESSAGE_RECV + PurpleConversation *conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, gwamsg->remoteJid, gwamsg->account); + if (conv == NULL) { + conv = purple_conversation_new(PURPLE_CONV_TYPE_IM, gwamsg->account, gwamsg->remoteJid); // MEMCHECK: caller takes ownership + } + purple_conv_im_write(purple_conversation_get_im_data(conv), gwamsg->remoteJid, gwamsg->text, flags, gwamsg->timestamp); } else { - // messages sometimes arrive before buddy has been - // created... this method will be missing a display - // name, but i don't think i ever saw one of them anyway + // messages sometimes arrive before buddy has been created + // a buddy created here may be missing a display name, + // but i don't think i ever saw one of them anyway gowhatsapp_ensure_buddy_in_blist(gwamsg->account, gwamsg->remoteJid, gwamsg->name); - // normal mode: direct incoming message purple_serv_got_im(pc, gwamsg->remoteJid, gwamsg->text, flags, gwamsg->timestamp); } } diff --git a/src/c/process_message.c b/src/c/process_message.c index 0ef2ed7..3be98a0 100644 --- a/src/c/process_message.c +++ b/src/c/process_message.c @@ -17,7 +17,7 @@ gowhatsapp_process_message(gowhatsapp_message_t *gwamsg) return; } purple_debug_info( - GOWHATSAPP_NAME, "recieved %s (subtype %d) for account %p remote %s (isGroup %d) sender %s (alias %s, fromMe %d) sent %ld: %s\n", + GOWHATSAPP_NAME, "recieved %s (subtype %d) for account %p remote %s (isGroup %d) sender %s (alias %s, isOutgoing %d) sent %ld: %s\n", gowhatsapp_message_type_string[gwamsg->msgtype], gwamsg->subtype, gwamsg->account, @@ -25,7 +25,7 @@ gowhatsapp_process_message(gowhatsapp_message_t *gwamsg) gwamsg->isGroup, gwamsg->senderJid, gwamsg->name, - gwamsg->fromMe, + gwamsg->isOutgoing, gwamsg->timestamp, gwamsg->text ); diff --git a/src/c/purple_compat.h b/src/c/purple_compat.h index 101cf71..b6a94e5 100644 --- a/src/c/purple_compat.h +++ b/src/c/purple_compat.h @@ -13,6 +13,7 @@ #define purple_im_conversation_new(account, from) PURPLE_CONV_IM(purple_conversation_new(PURPLE_CONV_TYPE_IM, account, from)) #define PURPLE_CONVERSATION(chatorim) ((chatorim) == NULL ? NULL : (chatorim)->conv) #define purple_serv_got_im serv_got_im +#define purple_serv_got_chat_in serv_got_chat_in #define purple_connection_set_flags(pc, f) ((pc)->flags = (f)) #define purple_connection_get_flags(pc) ((pc)->flags) #define purple_connection_get_protocol purple_connection_get_prpl diff --git a/src/go/bridge.go b/src/go/bridge.go index de87e14..e8ccd42 100644 --- a/src/go/bridge.go +++ b/src/go/bridge.go @@ -293,16 +293,16 @@ func purple_disconnected(account *PurpleAccount) { * This will display a text message. * Single participants and group chats. */ -func purple_display_text_message(account *PurpleAccount, remoteJid string, isGroup bool, isFromMe bool, senderJid string, pushName *string, timestamp time.Time, text string) { +func purple_display_text_message(account *PurpleAccount, remoteJid string, isGroup bool, isOutgoing bool, senderJid string, pushName *string, timestamp time.Time, text string) { cmessage := C.struct_gowhatsapp_message{ - account: account, - msgtype: C.char(C.gowhatsapp_message_type_text), - remoteJid: C.CString(remoteJid), - senderJid: C.CString(senderJid), - timestamp: C.time_t(timestamp.Unix()), - text: C.CString(text), - isGroup: bool_to_Cchar(isGroup), - fromMe: bool_to_Cchar(isFromMe), + account: account, + msgtype: C.char(C.gowhatsapp_message_type_text), + remoteJid: C.CString(remoteJid), + senderJid: C.CString(senderJid), + timestamp: C.time_t(timestamp.Unix()), + text: C.CString(text), + isGroup: bool_to_Cchar(isGroup), + isOutgoing: bool_to_Cchar(isOutgoing), } if pushName != nil { cmessage.name = C.CString(*pushName) @@ -349,18 +349,18 @@ func purple_update_name(account *PurpleAccount, remoteJid string, pushName strin * while in fact the file has already been received and they may only chose * where to store it. */ -func purple_handle_attachment(account *PurpleAccount, remoteJid string, isGroup bool, senderJid string, isFromMe bool, data_type C.int, mimetype *string, filename string, data []byte) { +func purple_handle_attachment(account *PurpleAccount, remoteJid string, isGroup bool, senderJid string, isOutgoing bool, data_type C.int, mimetype *string, filename string, data []byte) { cmessage := C.struct_gowhatsapp_message{ - account: account, - msgtype: C.char(C.gowhatsapp_message_type_attachment), - subtype: C.char(data_type), - remoteJid: C.CString(remoteJid), - isGroup: bool_to_Cchar(isGroup), - senderJid: C.CString(senderJid), - fromMe: bool_to_Cchar(isFromMe), - name: C.CString(filename), - blob: C.CBytes(data), - blobsize: C.size_t(len(data)), // contrary to https://golang.org/pkg/builtin/#len and https://golang.org/ref/spec#Numeric_types, len returns an int of 64 bits on 32 bit Windows machines (see https://github.com/hoehermann/purple-gowhatsapp/issues/1) + account: account, + msgtype: C.char(C.gowhatsapp_message_type_attachment), + subtype: C.char(data_type), + remoteJid: C.CString(remoteJid), + isGroup: bool_to_Cchar(isGroup), + senderJid: C.CString(senderJid), + isOutgoing: bool_to_Cchar(isOutgoing), + name: C.CString(filename), + blob: C.CBytes(data), + blobsize: C.size_t(len(data)), // contrary to https://golang.org/pkg/builtin/#len and https://golang.org/ref/spec#Numeric_types, len returns an int of 64 bits on 32 bit Windows machines (see https://github.com/hoehermann/purple-gowhatsapp/issues/1) } if mimetype != nil { cmessage.text = C.CString(*mimetype) diff --git a/src/go/handle_message.go b/src/go/handle_message.go index 12cdba5..fd5beb4 100644 --- a/src/go/handle_message.go +++ b/src/go/handle_message.go @@ -81,7 +81,7 @@ func (handler *Handler) handle_message(message *waProto.Message, id string, sour handler.log.Warnf("Received a message without any text.") } else { // note: info.PushName always denotes the sender (not the chat) - purple_display_text_message(handler.account, source.Chat.ToNonAD().String(), source.IsGroup, source.IsFromMe, source.Sender.ToNonAD().String(), name, timestamp, text) + purple_display_text_message(handler.account, source.Chat.ToNonAD().String(), source.IsGroup, false, source.Sender.ToNonAD().String(), name, timestamp, text) handler.addToCache(CachedMessage{id: id, text: text, timestamp: timestamp}) if !source.IsFromMe && !is_historical { // do not send receipt for own messages or historical messages handler.mark_read_defer(id, source.Chat, source.Sender) @@ -167,6 +167,6 @@ func (handler *Handler) handle_attachment(message *waProto.Message, source types // so source is known even when receiving from group chats filename = fmt.Sprintf("%s_%s", sender.User, filename) } - purple_handle_attachment(handler.account, chat, source.IsGroup, sender.String(), source.IsFromMe, data_type, mimetype, filename, data) + purple_handle_attachment(handler.account, chat, source.IsGroup, sender.String(), false, data_type, mimetype, filename, data) } } diff --git a/src/go/send_message.go b/src/go/send_message.go index 645d818..ef719e6 100644 --- a/src/go/send_message.go +++ b/src/go/send_message.go @@ -52,8 +52,9 @@ func (handler *Handler) send_text_message(recipient types.JID, isGroup bool, mes // inject message back to self to indicate success setting := purple_get_string(handler.account, C.GOWHATSAPP_ECHO_OPTION, C.GOWHATSAPP_ECHO_CHOICE_ON_SUCCESS) if setting == C.GoString(C.GOWHATSAPP_ECHO_CHOICE_ON_SUCCESS) { - ownJid := "" // TODO: find out if this messes up group chats - purple_display_text_message(handler.account, recipient.ToNonAD().String(), isGroup, true, ownJid, nil, resp.Timestamp, message) + ownJid := handler.client.Store.ID.ToNonAD().String() + recipientJid := recipient.ToNonAD().String() + purple_display_text_message(handler.account, recipientJid, isGroup, true, ownJid, nil, resp.Timestamp, message) } handler.addToCache(CachedMessage{id: resp.ID, text: message, timestamp: resp.Timestamp}) }