From bb6c60c71bc3ba353f951279e85d188ab67c2094 Mon Sep 17 00:00:00 2001 From: trek-boldly-go Date: Wed, 17 Jan 2024 17:08:34 -0600 Subject: [PATCH 1/4] no real code changes here, just cleaning up --- imessage/bluebubbles/api.go | 62 +++++++++++++++++------- imessage/bluebubbles/interface.go | 78 ++++++++++++++++++------------- 2 files changed, 90 insertions(+), 50 deletions(-) diff --git a/imessage/bluebubbles/api.go b/imessage/bluebubbles/api.go index 87e80b7..a5c1a3a 100644 --- a/imessage/bluebubbles/api.go +++ b/imessage/bluebubbles/api.go @@ -26,7 +26,7 @@ const ( // Ref: https://github.com/BlueBubblesApp/bluebubbles-server/blob/master/packages/server/src/server/events.ts NewMessage string = "new-message" MessageSendError string = "message-send-error" - MessageUpdated string = "message-updated" + MessageUpdated string = "updated-message" ParticipantRemoved string = "participant-removed" ParticipantAdded string = "participant-added" ParticipantLeft string = "participant-left" @@ -225,8 +225,30 @@ func (bb *blueBubbles) handleMessageSendError(data json.RawMessage) (err error) return ErrNotImplemented } -func (bb *blueBubbles) handleMessageUpdated(data json.RawMessage) (err error) { - bb.log.Trace().RawJSON("data", data).Msg("handleMessageUpdated") +func (bb *blueBubbles) handleMessageUpdated(rawMessage json.RawMessage) (err error) { + bb.log.Trace().RawJSON("rawMessage", rawMessage).Msg("handleMessageUpdated") + + //TODO: This code words just fine, unless you send a caption with a picture. then it duplicates your message in the matrix client (not visible to the other imessage user though) + // Let's get the multipart message working before we worry about this function + // var data Message + // err = json.Unmarshal(rawMessage, &data) + // if err != nil { + // return err + // } + + // message, err := bb.convertBBMessageToiMessage(data) + + // if err != nil { + // return err + // } + + // select { + // case bb.messageChan <- message: + // default: + // bb.log.Warn().Msg("Incoming message buffer is full") + // } + + // return nil return ErrNotImplemented } @@ -896,20 +918,24 @@ func (bb *blueBubbles) convertBBMessageToiMessage(bbMessage Message) (*imessage. message.Text = bbMessage.Text message.ChatGUID = bbMessage.Chats[0].GUID - // TODO: there doesn't seem to be a "from" in the bluebubbles data - // message.JSONSenderGUID = bbMessage.Handle.Address - // message.Sender = imessage.Identifier{ - // LocalID: bbMessage.Handle.Address, - // Service: bbMessage.Handle.Service, - // IsGroup: false, - // } - - message.JSONTargetGUID = bbMessage.Handle.Address - message.Target = imessage.Identifier{ - LocalID: bbMessage.Handle.Address, - Service: bbMessage.Handle.Service, - IsGroup: false, + // bbMessage.Handle seems to always be the other person, + // so the sender/target depends on whether the message is from you + if bbMessage.IsFromMe { + message.JSONTargetGUID = bbMessage.Handle.Address + message.Target = imessage.Identifier{ + LocalID: bbMessage.Handle.Address, + Service: bbMessage.Handle.Service, + IsGroup: false, + } + } else { + message.JSONSenderGUID = bbMessage.Handle.Address + message.Sender = imessage.Identifier{ + LocalID: bbMessage.Handle.Address, + Service: bbMessage.Handle.Service, + IsGroup: false, + } } + message.Service = bbMessage.Handle.Service message.IsFromMe = bbMessage.IsFromMe message.IsRead = false @@ -926,9 +952,9 @@ func (bb *blueBubbles) convertBBMessageToiMessage(bbMessage Message) (*imessage. // message.ReplyToPart = bbMessage.PartCount // TODO: Tapbacks - // if bbMessage.AssociatedMessageGuid != nil { + // if bbMessage.AssociatedMessageGuid != "" { // message.Tapback = &imessage.Tapback{ - // TargetGUID: *bbMessage.AssociatedMessageGuid, + // TargetGUID: bbMessage.AssociatedMessageGuid, // } // message.Tapback.Parse() // } else { diff --git a/imessage/bluebubbles/interface.go b/imessage/bluebubbles/interface.go index b30285e..dda589b 100644 --- a/imessage/bluebubbles/interface.go +++ b/imessage/bluebubbles/interface.go @@ -90,38 +90,52 @@ type TypingNotification struct { } type Message struct { - AssociatedMessageGuid string `json:"associatedMessageGuid,omitempty"` - AssociatedMessageType string `json:"associatedMessageType,omitempty"` - Attachments []Attachment `json:"attachments,omitempty"` - AttributedBody []interface{} `json:"attributedBody,omitempty"` - BalloonBundleId interface{} `json:"balloonBundleId,omitempty"` - Chats []Chat `json:"chats,omitempty"` - DateCreated int64 `json:"dateCreated,omitempty"` - DateDelivered int64 `json:"dateDelivered,omitempty"` - DateEdited int64 `json:"dateEdited,omitempty"` - DateRead int64 `json:"dateRead,omitempty"` - DateRetracted int64 `json:"dateRetracted,omitempty"` - Error int `json:"error,omitempty"` - ExpressiveSendStyleId interface{} `json:"expressiveSendStyleId,omitempty"` - GroupActionType int `json:"groupActionType,omitempty"` - GroupTitle string `json:"groupTitle,omitempty"` - GUID string `json:"guid,omitempty"` - Handle Handle `json:"handle,omitempty"` - HandleId int `json:"handleId,omitempty"` - HasDdResults bool `json:"hasDdResults,omitempty"` - HasPayloadData bool `json:"hasPayloadData,omitempty"` - IsAudioMessage bool `json:"isAudioMessage,omitempty"` - IsArchived bool `json:"isArchived,omitempty"` - IsFromMe bool `json:"isFromMe,omitempty"` - ItemType int `json:"itemType,omitempty"` - MessageSummaryInfo interface{} `json:"messageSummaryInfo,omitempty"` - OriginalROWID int `json:"originalROWID,omitempty"` - OtherHandle int `json:"otherHandle,omitempty"` - PartCount int `json:"partCount,omitempty"` - PayloadData interface{} `json:"payloadData,omitempty"` - Subject string `json:"subject,omitempty"` - Text string `json:"text,omitempty"` - ThreadOriginatorGuid string `json:"threadOriginatorGuid,omitempty"` + AssociatedMessageGuid string `json:"associatedMessageGuid,omitempty"` + AssociatedMessageType string `json:"associatedMessageType,omitempty"` + Attachments []Attachment `json:"attachments,omitempty"` + AttributedBody []interface{} `json:"attributedBody,omitempty"` + BalloonBundleId interface{} `json:"balloonBundleId,omitempty"` + Chats []Chat `json:"chats,omitempty"` + DateCreated int64 `json:"dateCreated,omitempty"` + DateDelivered int64 `json:"dateDelivered,omitempty"` + DateEdited int64 `json:"dateEdited,omitempty"` + DateRead int64 `json:"dateRead,omitempty"` + DateRetracted int64 `json:"dateRetracted,omitempty"` + Error int `json:"error,omitempty"` + ExpressiveSendStyleId interface{} `json:"expressiveSendStyleId,omitempty"` + GroupActionType int `json:"groupActionType,omitempty"` + GroupTitle string `json:"groupTitle,omitempty"` + GUID string `json:"guid,omitempty"` + Handle Handle `json:"handle,omitempty"` + HandleId int `json:"handleId,omitempty"` + HasDdResults bool `json:"hasDdResults,omitempty"` + HasPayloadData bool `json:"hasPayloadData,omitempty"` + IsArchived bool `json:"isArchived,omitempty"` + IsAudioMessage bool `json:"isAudioMessage,omitempty"` + IsAutoReply bool `json:"isAutoReply,omitempty"` + IsCorrupt bool `json:"isCorrupt,omitempty"` + IsDelayed bool `json:"isDelayed,omitempty"` + IsExpired bool `json:"isExpired,omitempty"` + IsForward bool `json:"isForward,omitempty"` + IsFromMe bool `json:"isFromMe,omitempty"` + IsServiceMessage bool `json:"isServiceMessage,omitempty"` + IsSpam bool `json:"isSpam,omitempty"` + IsSystemMessage bool `json:"isSystemMessage,omitempty"` + ItemType int `json:"itemType,omitempty"` + MessageSummaryInfo interface{} `json:"messageSummaryInfo,omitempty"` + OriginalROWID int `json:"originalROWID,omitempty"` + OtherHandle int `json:"otherHandle,omitempty"` + PartCount int `json:"partCount,omitempty"` + PayloadData interface{} `json:"payloadData,omitempty"` + ReplyToGuid string `json:"replyToGuid,omitempty"` + ShareDirection int `json:"shareDirection,omitempty"` + ShareStatus int `json:"shareStatus,omitempty"` + Subject string `json:"subject,omitempty"` + Text string `json:"text,omitempty"` + ThreadOriginatorGuid string `json:"threadOriginatorGuid,omitempty"` + ThreadOriginatorPart interface{} `json:"threadOriginatorPart,omitempty"` + TimeExpressiveSendStyleId interface{} `json:"timeExpressiveSendStyleId,omitempty"` + WasDeliveredQuietly bool `json:"wasDeliveredQuietly,omitempty"` } type Attachment struct { From 90c49645d40e5154f9be9cf27f2ca885bc5aa0b9 Mon Sep 17 00:00:00 2001 From: trek-boldly-go Date: Wed, 17 Jan 2024 22:41:28 -0600 Subject: [PATCH 2/4] message replies seem to work now (send and receive) --- imessage/bluebubbles/api.go | 31 ++++++++++++++++++++----------- imessage/tapback.go | 19 +++++++++++++++++++ 2 files changed, 39 insertions(+), 11 deletions(-) diff --git a/imessage/bluebubbles/api.go b/imessage/bluebubbles/api.go index a5c1a3a..551c3b5 100644 --- a/imessage/bluebubbles/api.go +++ b/imessage/bluebubbles/api.go @@ -947,20 +947,29 @@ func (bb *blueBubbles) convertBBMessageToiMessage(bbMessage Message) (*imessage. message.IsEmote = false message.IsAudioMessage = bbMessage.IsAudioMessage - // TODO: ReplyTo - // message.ReplyToGUID = bbMessage.ThreadOriginatorGuid - // message.ReplyToPart = bbMessage.PartCount - - // TODO: Tapbacks - // if bbMessage.AssociatedMessageGuid != "" { - // message.Tapback = &imessage.Tapback{ - // TargetGUID: bbMessage.AssociatedMessageGuid, - // } - // message.Tapback.Parse() + message.ReplyToGUID = bbMessage.ThreadOriginatorGuid + + // TODO: ReplyToPart from bluebubbles looks like "0:0:17" in one test I did + // I don't know what the value means, or how to parse it + // num, err := strconv.Atoi(bbMessage.ThreadOriginatorPart) + // if err != nil { + // bb.log.Err(err).Str("ThreadOriginatorPart", bbMessage.ThreadOriginatorPart).Msg("Unable to convert ThreadOriginatorPart to an int") // } else { - // message.Tapback = nil + // message.ReplyToPart = num // } + // Tapbacks + if bbMessage.AssociatedMessageGuid != "" && + bbMessage.AssociatedMessageType != "" { + message.Tapback = &imessage.Tapback{ + TargetGUID: bbMessage.AssociatedMessageGuid, + Type: imessage.TapbackFromName(bbMessage.AssociatedMessageType), + } + message.Tapback.Parse() + } else { + message.Tapback = nil + } + message.Attachments = make([]*imessage.Attachment, len(bbMessage.Attachments)) for i, blueBubblesAttachment := range bbMessage.Attachments { attachment, err := bb.convertAttachment(blueBubblesAttachment) diff --git a/imessage/tapback.go b/imessage/tapback.go index 3d6b6eb..9f07b36 100644 --- a/imessage/tapback.go +++ b/imessage/tapback.go @@ -95,6 +95,25 @@ func TapbackFromEmoji(emoji string) TapbackType { } } +func TapbackFromName(name string) TapbackType { + switch name { + case "love": + return TapbackLove + case "like": + return TapbackLike + case "dislike": + return TapbackDislike + case "laugh": + return TapbackLaugh + case "emphasize": + return TapbackEmphasis + case "question": + return TapbackQuestion + default: + return 0 + } +} + func (amt TapbackType) String() string { return amt.Emoji() } From aea9dbc791ef18937015bf84e48b8a618f593f8d Mon Sep 17 00:00:00 2001 From: trek-boldly-go Date: Thu, 18 Jan 2024 13:16:36 -0600 Subject: [PATCH 3/4] changed IsFromMe to false This probably isn't everything this function needs corrected, but it seems to get the job done for now. --- imessage/bluebubbles/api.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/imessage/bluebubbles/api.go b/imessage/bluebubbles/api.go index 551c3b5..842be14 100644 --- a/imessage/bluebubbles/api.go +++ b/imessage/bluebubbles/api.go @@ -308,7 +308,7 @@ func (bb *blueBubbles) handleChatReadStatusChanged(data json.RawMessage) (err er var receipt = imessage.ReadReceipt{ SenderGUID: lastMessage.Handle.Address, // TODO: Make sure this is the right field? - IsFromMe: true, + IsFromMe: false, // changing this to false as I believe read reciepts will always be from others ChatGUID: rec.ChatGUID, ReadUpTo: chatInfo.Data.LastMessage.GUID, ReadAt: now, From ca0d7bb6119e87619417ab2aaba9320657751f04 Mon Sep 17 00:00:00 2001 From: trek-boldly-go Date: Thu, 18 Jan 2024 13:28:30 -0600 Subject: [PATCH 4/4] linter problem with whitespace --- imessage/bluebubbles/api.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/imessage/bluebubbles/api.go b/imessage/bluebubbles/api.go index e29bd35..cf8ec37 100644 --- a/imessage/bluebubbles/api.go +++ b/imessage/bluebubbles/api.go @@ -979,7 +979,7 @@ func (bb *blueBubbles) convertBBMessageToiMessage(bbMessage Message) (*imessage. // } else { // message.ReplyToPart = num // } - + // Tapbacks if bbMessage.AssociatedMessageGuid != "" && bbMessage.AssociatedMessageType != "" {