diff --git a/SessionMessagingKit/Open Groups/OpenGroupMessage+Conversion.swift b/SessionMessagingKit/Open Groups/OpenGroupMessage+Conversion.swift index be4515ce2..060be6bc9 100644 --- a/SessionMessagingKit/Open Groups/OpenGroupMessage+Conversion.swift +++ b/SessionMessagingKit/Open Groups/OpenGroupMessage+Conversion.swift @@ -1,35 +1,74 @@ internal extension OpenGroupMessage { - static func from(_ message: VisibleMessage, for server: String) -> OpenGroupMessage? { - guard message.isValid else { preconditionFailure() } // Should be valid at this point + static func from(_ message: VisibleMessage, for server: String, using transaction: YapDatabaseReadWriteTransaction) -> OpenGroupMessage? { let storage = Configuration.shared.storage - let displayName = storage.getUserDisplayName() ?? "Anonymous" guard let userPublicKey = storage.getUserPublicKey() else { return nil } + // Validation + guard message.isValid else { return nil } // Should be valid at this point + // Quote let quote: OpenGroupMessage.Quote? = { if let quote = message.quote { guard quote.isValid else { return nil } - return OpenGroupMessage.Quote(quotedMessageTimestamp: quote.timestamp!, quoteePublicKey: quote.publicKey!, quotedMessageBody: quote.text!, quotedMessageServerID: nil) // TODO: Server ID + let quotedMessageServerID = TSIncomingMessage.find(withAuthorId: quote.publicKey!, timestamp: quote.timestamp!, transaction: transaction)?.openGroupServerMessageID + return OpenGroupMessage.Quote(quotedMessageTimestamp: quote.timestamp!, quoteePublicKey: quote.publicKey!, quotedMessageBody: quote.text, quotedMessageServerID: quotedMessageServerID) } else { return nil } }() - let body = message.text! + // Message + let displayName = storage.getUserDisplayName() ?? "Anonymous" + let body = message.text ?? String(message.sentTimestamp!) // The back-end doesn't accept messages without a body so we use this as a workaround let result = OpenGroupMessage(serverID: nil, senderPublicKey: userPublicKey, displayName: displayName, profilePicture: nil, body: body, type: OpenGroupAPI.openGroupMessageType, timestamp: message.sentTimestamp!, quote: quote, attachments: [], signature: nil, serverTimestamp: 0) - if let linkPreview: OpenGroupMessage.Attachment = { - if let linkPreview = message.linkPreview { - guard linkPreview.isValid else { return nil } - // TODO: Implement - return OpenGroupMessage.Attachment(kind: .linkPreview, server: server, serverID: 0, contentType: "", size: 0, fileName: "", - flags: 0, width: 0, height: 0, caption: "", url: "", linkPreviewURL: "", linkPreviewTitle: "") - } else { - return nil - } - }() { - result.attachments.append(linkPreview) + // Link preview + if let linkPreview = message.linkPreview { + guard linkPreview.isValid, let attachmentID = linkPreview.attachmentID, + let attachment = TSAttachmentStream.fetch(uniqueId: attachmentID, transaction: transaction) else { return nil } + let fileName = attachment.sourceFilename ?? UUID().uuidString + let width = attachment.shouldHaveImageSize() ? attachment.imageSize().width : 0 + let height = attachment.shouldHaveImageSize() ? attachment.imageSize().height : 0 + let openGroupLinkPreview = OpenGroupMessage.Attachment( + kind: .linkPreview, + server: server, + serverID: 0, + contentType: attachment.contentType, + size: UInt(attachment.byteCount), + fileName: fileName, + flags: 0, + width: UInt(width), + height: UInt(height), + caption: attachment.caption, + url: attachment.downloadURL, + linkPreviewURL: linkPreview.url, + linkPreviewTitle: linkPreview.title + ) + result.attachments.append(openGroupLinkPreview) + } + // Attachments + let attachments: [OpenGroupMessage.Attachment] = message.attachmentIDs.compactMap { attachmentID in + guard let attachment = TSAttachmentStream.fetch(uniqueId: attachmentID, transaction: transaction) else { return nil } // Should never occur + let fileName = attachment.sourceFilename ?? UUID().uuidString + let width = attachment.shouldHaveImageSize() ? attachment.imageSize().width : 0 + let height = attachment.shouldHaveImageSize() ? attachment.imageSize().height : 0 + return OpenGroupMessage.Attachment( + kind: .attachment, + server: server, + serverID: 0, + contentType: attachment.contentType, + size: UInt(attachment.byteCount), + fileName: fileName, + flags: 0, + width: UInt(width), + height: UInt(height), + caption: attachment.caption, + url: attachment.downloadURL, + linkPreviewURL: nil, + linkPreviewTitle: nil + ) } - // TODO: Attachments + result.attachments += attachments + // Return return result } } diff --git a/SessionMessagingKit/Open Groups/OpenGroupMessage.swift b/SessionMessagingKit/Open Groups/OpenGroupMessage.swift index b562f4a58..7b26d50c0 100644 --- a/SessionMessagingKit/Open Groups/OpenGroupMessage.swift +++ b/SessionMessagingKit/Open Groups/OpenGroupMessage.swift @@ -34,7 +34,7 @@ public final class OpenGroupMessage : NSObject { public struct Quote { public let quotedMessageTimestamp: UInt64 public let quoteePublicKey: String - public let quotedMessageBody: String + public let quotedMessageBody: String? public let quotedMessageServerID: UInt64? } @@ -96,7 +96,7 @@ public final class OpenGroupMessage : NSObject { quotedMessageTimestamp: UInt64, quoteePublicKey: String?, quotedMessageBody: String?, quotedMessageServerID: UInt64, signatureData: Data?, signatureVersion: UInt64, serverTimestamp: UInt64) { let quote: Quote? - if quotedMessageTimestamp != 0, let quoteeHexEncodedPublicKey = quoteePublicKey, let quotedMessageBody = quotedMessageBody { + if quotedMessageTimestamp != 0, let quoteeHexEncodedPublicKey = quoteePublicKey { let quotedMessageServerID = (quotedMessageServerID != 0) ? quotedMessageServerID : nil quote = Quote(quotedMessageTimestamp: quotedMessageTimestamp, quoteePublicKey: quoteeHexEncodedPublicKey, quotedMessageBody: quotedMessageBody, quotedMessageServerID: quotedMessageServerID) } else { @@ -137,7 +137,8 @@ public final class OpenGroupMessage : NSObject { internal func toJSON() -> JSON { var value: JSON = [ "timestamp" : timestamp ] if let quote = quote { - value["quote"] = [ "id" : quote.quotedMessageTimestamp, "author" : quote.quoteePublicKey, "text" : quote.quotedMessageBody ] + value["quote"] = [ "id" : quote.quotedMessageTimestamp, "author" : quote.quoteePublicKey ] + if let quotedMessageBody = quote.quotedMessageBody { value["text"] = quotedMessageBody } } if let signature = signature { value["sig"] = signature.data.toHexString() @@ -183,7 +184,10 @@ public final class OpenGroupMessage : NSObject { private func getValidationData(for signatureVersion: UInt64) -> Data? { var string = "\(body.trimmingCharacters(in: CharacterSet.whitespacesAndNewlines))\(timestamp)" if let quote = quote { - string += "\(quote.quotedMessageTimestamp)\(quote.quoteePublicKey)\(quote.quotedMessageBody.trimmingCharacters(in: CharacterSet.whitespacesAndNewlines))" + string += "\(quote.quotedMessageTimestamp)\(quote.quoteePublicKey)" + if let quotedMessageBody = quote.quotedMessageBody { + string += "\(quotedMessageBody.trimmingCharacters(in: CharacterSet.whitespacesAndNewlines))" + } if let quotedMessageServerID = quote.quotedMessageServerID { string += "\(quotedMessageServerID)" } diff --git a/SessionMessagingKit/Sending & Receiving/MessageSender.swift b/SessionMessagingKit/Sending & Receiving/MessageSender.swift index caad66df1..f331a87c5 100644 --- a/SessionMessagingKit/Sending & Receiving/MessageSender.swift +++ b/SessionMessagingKit/Sending & Receiving/MessageSender.swift @@ -231,7 +231,7 @@ public final class MessageSender : NSObject { } }() guard let message = message as? VisibleMessage, - let openGroupMessage = OpenGroupMessage.from(message, for: server) else { seal.reject(Error.invalidMessage); return promise } + let openGroupMessage = OpenGroupMessage.from(message, for: server, using: transaction as! YapDatabaseReadWriteTransaction) else { seal.reject(Error.invalidMessage); return promise } // Send the result OpenGroupAPI.sendMessage(openGroupMessage, to: channel, on: server).done(on: DispatchQueue.global(qos: .userInitiated)) { openGroupMessage in message.openGroupServerMessageID = openGroupMessage.serverID diff --git a/SessionMessagingKit/Sending & Receiving/Pollers/OpenGroupPoller.swift b/SessionMessagingKit/Sending & Receiving/Pollers/OpenGroupPoller.swift index bb2994013..de35a3821 100644 --- a/SessionMessagingKit/Sending & Receiving/Pollers/OpenGroupPoller.swift +++ b/SessionMessagingKit/Sending & Receiving/Pollers/OpenGroupPoller.swift @@ -119,7 +119,7 @@ public final class OpenGroupPoller : NSObject { dataMessage.setGroup(try! groupContext.build()) if let quote = message.quote { let signalQuote = SNProtoDataMessageQuote.builder(id: quote.quotedMessageTimestamp, author: quote.quoteePublicKey) - signalQuote.setText(quote.quotedMessageBody) + if let quotedMessageBody = quote.quotedMessageBody { signalQuote.setText(quotedMessageBody) } dataMessage.setQuote(try! signalQuote.build()) } let body = (message.body == message.timestamp.description) ? "" : message.body // Workaround for the fact that the back-end doesn't accept messages without a body