diff --git a/Sources/IMsgCore/MessageStore+Messages.swift b/Sources/IMsgCore/MessageStore+Messages.swift index 0ccee4a..2694331 100644 --- a/Sources/IMsgCore/MessageStore+Messages.swift +++ b/Sources/IMsgCore/MessageStore+Messages.swift @@ -13,6 +13,7 @@ extension MessageStore { let associatedTypeColumn = hasReactionColumns ? "m.associated_message_type" : "NULL" let destinationCallerColumn = hasDestinationCallerID ? "m.destination_caller_id" : "NULL" let audioMessageColumn = hasAudioMessageColumn ? "m.is_audio_message" : "0" + let threadOriginatorColumn = hasReactionColumns ? "m.thread_originator_guid" : "NULL" let reactionFilter = hasReactionColumns ? " AND (m.associated_message_type IS NULL OR m.associated_message_type < 2000 OR m.associated_message_type > 3006)" @@ -22,7 +23,8 @@ extension MessageStore { \(audioMessageColumn) AS is_audio_message, \(destinationCallerColumn) AS destination_caller_id, \(guidColumn) AS guid, \(associatedGuidColumn) AS associated_guid, \(associatedTypeColumn) AS associated_type, (SELECT COUNT(*) FROM message_attachment_join maj WHERE maj.message_id = m.ROWID) AS attachments, - \(bodyColumn) AS body + \(bodyColumn) AS body, + \(threadOriginatorColumn) AS thread_originator_guid FROM message m JOIN chat_message_join cmj ON m.ROWID = cmj.message_id LEFT JOIN handle h ON m.handle_id = h.ROWID @@ -74,6 +76,7 @@ extension MessageStore { let associatedType = intValue(row[11]) let attachments = intValue(row[12]) ?? 0 let body = dataValue(row[13]) + let threadOriginatorGUID = stringValue(row[14]) var resolvedText = text.isEmpty ? TypedStreamParser.parseAttributedBody(body) : text if isAudioMessage, let transcription = try audioTranscription(for: rowID) { resolvedText = transcription @@ -94,7 +97,8 @@ extension MessageStore { handleID: handleID, attachmentsCount: attachments, guid: guid, - replyToGUID: replyToGUID + replyToGUID: replyToGUID, + threadOriginatorGUID: threadOriginatorGUID.isEmpty ? nil : threadOriginatorGUID )) } return messages @@ -108,6 +112,7 @@ extension MessageStore { let associatedTypeColumn = hasReactionColumns ? "m.associated_message_type" : "NULL" let destinationCallerColumn = hasDestinationCallerID ? "m.destination_caller_id" : "NULL" let audioMessageColumn = hasAudioMessageColumn ? "m.is_audio_message" : "0" + let threadOriginatorColumn = hasReactionColumns ? "m.thread_originator_guid" : "NULL" let reactionFilter = hasReactionColumns ? " AND (m.associated_message_type IS NULL OR m.associated_message_type < 2000 OR m.associated_message_type > 3006)" @@ -117,7 +122,8 @@ extension MessageStore { \(audioMessageColumn) AS is_audio_message, \(destinationCallerColumn) AS destination_caller_id, \(guidColumn) AS guid, \(associatedGuidColumn) AS associated_guid, \(associatedTypeColumn) AS associated_type, (SELECT COUNT(*) FROM message_attachment_join maj WHERE maj.message_id = m.ROWID) AS attachments, - \(bodyColumn) AS body + \(bodyColumn) AS body, + \(threadOriginatorColumn) AS thread_originator_guid FROM message m LEFT JOIN chat_message_join cmj ON m.ROWID = cmj.message_id LEFT JOIN handle h ON m.handle_id = h.ROWID @@ -152,6 +158,7 @@ extension MessageStore { let associatedType = intValue(row[12]) let attachments = intValue(row[13]) ?? 0 let body = dataValue(row[14]) + let threadOriginatorGUID = stringValue(row[15]) var resolvedText = text.isEmpty ? TypedStreamParser.parseAttributedBody(body) : text if isAudioMessage, let transcription = try audioTranscription(for: rowID) { resolvedText = transcription @@ -172,7 +179,8 @@ extension MessageStore { handleID: handleID, attachmentsCount: attachments, guid: guid, - replyToGUID: replyToGUID + replyToGUID: replyToGUID, + threadOriginatorGUID: threadOriginatorGUID.isEmpty ? nil : threadOriginatorGUID )) } return messages diff --git a/Sources/IMsgCore/Models.swift b/Sources/IMsgCore/Models.swift index ca15e9d..de2e893 100644 --- a/Sources/IMsgCore/Models.swift +++ b/Sources/IMsgCore/Models.swift @@ -221,6 +221,7 @@ public struct Message: Sendable, Equatable { public let chatID: Int64 public let guid: String public let replyToGUID: String? + public let threadOriginatorGUID: String? public let sender: String public let text: String public let date: Date @@ -240,12 +241,14 @@ public struct Message: Sendable, Equatable { handleID: Int64?, attachmentsCount: Int, guid: String = "", - replyToGUID: String? = nil + replyToGUID: String? = nil, + threadOriginatorGUID: String? = nil ) { self.rowID = rowID self.chatID = chatID self.guid = guid self.replyToGUID = replyToGUID + self.threadOriginatorGUID = threadOriginatorGUID self.sender = sender self.text = text self.date = date diff --git a/Sources/imsg/OutputModels.swift b/Sources/imsg/OutputModels.swift index ef8e477..25dd1b7 100644 --- a/Sources/imsg/OutputModels.swift +++ b/Sources/imsg/OutputModels.swift @@ -30,6 +30,7 @@ struct MessagePayload: Codable { let chatID: Int64 let guid: String let replyToGUID: String? + let threadOriginatorGUID: String? let sender: String let isFromMe: Bool let text: String @@ -42,6 +43,7 @@ struct MessagePayload: Codable { self.chatID = message.chatID self.guid = message.guid self.replyToGUID = message.replyToGUID + self.threadOriginatorGUID = message.threadOriginatorGUID self.sender = message.sender self.isFromMe = message.isFromMe self.text = message.text @@ -55,6 +57,7 @@ struct MessagePayload: Codable { case chatID = "chat_id" case guid case replyToGUID = "reply_to_guid" + case threadOriginatorGUID = "thread_originator_guid" case sender case isFromMe = "is_from_me" case text diff --git a/Sources/imsg/RPCPayloads.swift b/Sources/imsg/RPCPayloads.swift index ae71090..5e3c8ad 100644 --- a/Sources/imsg/RPCPayloads.swift +++ b/Sources/imsg/RPCPayloads.swift @@ -51,6 +51,9 @@ func messagePayload( if let replyToGUID = message.replyToGUID, !replyToGUID.isEmpty { payload["reply_to_guid"] = replyToGUID } + if let threadOriginatorGUID = message.threadOriginatorGUID, !threadOriginatorGUID.isEmpty { + payload["thread_originator_guid"] = threadOriginatorGUID + } return payload }