From 45113991bb3eb6e7ab54556918a8aa523da85ce8 Mon Sep 17 00:00:00 2001 From: gbogboadePush <135420608+gbogboadePush@users.noreply.github.com> Date: Mon, 11 Mar 2024 12:00:14 +0100 Subject: [PATCH] Fix/msg obj (#24) * feat:message content added * reaction and reply added * Fixed message sending and parsing (#20) * Throw error if group DTO fetching failed with 400 error. * Encrypt messageObj when sending the message * Return decrypted message content if msjObj decryption failed * Break Conversation decryption functions into simpler functions. Added option to pass secret key for optimisation. * Added support of media embed messages (#21) * Throw error if group DTO fetching failed with 400 error. * Added MediaEmbed to the enum of MessageType. Handle MediaEmbed type when sending the message. * chore: remove print --------- Co-authored-by: teach.gamil.com Co-authored-by: Oleg Co-authored-by: Gbogboade Ayomide --- Sources/Chat/Conversation.swift | 142 ++++++++++++----- Sources/Chat/Group/GetGroup.swift | 4 +- Sources/Chat/Send.swift | 73 +++++++-- Sources/Helpers/Chat/GetInboxList.swift | 2 +- Sources/Helpers/Ipfs/Cid.swift | 2 + Tests/Chat/Group/SendGroupMsgTests.swift | 2 +- Tests/Chat/P2P/SendTests.swift | 3 +- Tests/Helper/IpfsTests.swift | 54 ++++--- Tests/e2e/GroupConversation.swift | 2 +- Tests/e2e/PrivateGroupDecrypt.swift | 194 +++++++++++++++-------- Tests/e2e/PrivateGroupUpdate.swift | 7 + docs/GroupChat.md | 50 ++++++ 12 files changed, 384 insertions(+), 151 deletions(-) create mode 100644 Tests/e2e/PrivateGroupUpdate.swift diff --git a/Sources/Chat/Conversation.swift b/Sources/Chat/Conversation.swift index 20fed81..49c8622 100644 --- a/Sources/Chat/Conversation.swift +++ b/Sources/Chat/Conversation.swift @@ -45,8 +45,12 @@ extension PushChat { if toDecrypt { for i in 0.. String { + ) async throws -> (String, String?) { do { if message.encType == "pgpv1:group" { @@ -88,64 +92,118 @@ extension PushChat { message, privateKeyArmored: privateKeyArmored, env: env) } if message.encType != "pgp" { - return message.messageContent + return (message.messageContent, nil) } - return try decryptMessage( + let decrypytedMessage = try decryptMessage( message.messageContent, encryptedSecret: message.encryptedSecret!, privateKeyArmored: privateKeyArmored) + + return (decrypytedMessage, nil) } catch { if isGroupChatId(message.toCAIP10) { - return "message encrypted before you join" + return ("message encrypted before you join", nil) } - return "Unable to decrypt message" + return ("Unable to decrypt message", nil) } } public static func decryptPrivateGroupMessage( _ message: Message, privateKeyArmored: String, + groupSecretKey: String? = nil, env: ENV - ) async throws -> String { + ) async throws -> (String, String?) { do { - - let encryptedSecret = try await PushChat.getGroupSessionKey( - sessionKey: message.sessionKey!, env: env) - - print("got enc sec \(encryptedSecret)") - - return try decryptMessage( - message.messageContent, - encryptedSecret: encryptedSecret, - privateKeyArmored: privateKeyArmored - ) + let secretKey: String + if let groupSecretKey { + secretKey = groupSecretKey + } else { + secretKey = try await getPrivateGroupPGPSecretKey( + sessionKey: message.sessionKey!, + privateKeyArmored: privateKeyArmored, + env: env) + } + + return try decryptPrivateGroupMessage(message, using: secretKey, privateKeyArmored: privateKeyArmored, env: env) } catch { throw PushChat.ChatError.dectyptionFalied } } - public static func decryptMessage( - _ message: String, - encryptedSecret: String, - privateKeyArmored: String - ) throws -> String { - do { - - let secretKey = try Pgp.pgpDecrypt( - cipherText: encryptedSecret, toPrivateKeyArmored: privateKeyArmored) - - guard let userMsg = try AESCBCHelper.decrypt(cipherText: message, secretKey: secretKey) else { - throw PushChat.ChatError.dectyptionFalied - } - - let userMsgStr = String(data: userMsg, encoding: .utf8) - - if userMsgStr == nil { - throw PushChat.ChatError.dectyptionFalied - } - - return userMsgStr! - } catch { - throw PushChat.ChatError.dectyptionFalied + public static func getPrivateGroupPGPSecretKey( + sessionKey: String, + privateKeyArmored: String, + env: ENV + ) async throws -> String { + let encryptedSecret = try await PushChat.getGroupSessionKey( + sessionKey: sessionKey, env: env) + return try decryptPGPSecretKey( + encryptedSecret: encryptedSecret, toPrivateKeyArmored: privateKeyArmored) } - } + + public static func decryptPrivateGroupMessage( + _ message: Message, + using secretKey: String, + privateKeyArmored: String, + env: ENV + ) throws -> (String, String?) { + do { + var messageObj: String? = nil + if let msgObj = message.messageObj { + messageObj = try? decryptMessage( + msgObj, secretKey: secretKey) + } + + let decMsg = try decryptMessage( + message.messageContent, + secretKey: secretKey) + + return (decMsg, messageObj) + } catch { + throw PushChat.ChatError.dectyptionFalied + } + } + + public static func decryptMessage( + _ message: String, + encryptedSecret: String, + privateKeyArmored: String + ) throws -> String { + do { + + let secretKey = try decryptPGPSecretKey( + encryptedSecret: encryptedSecret, toPrivateKeyArmored: privateKeyArmored) + + return try decryptMessage(message, secretKey: secretKey) + } catch { + throw PushChat.ChatError.dectyptionFalied + } + } + + public static func decryptPGPSecretKey( + encryptedSecret: String, + toPrivateKeyArmored privateKeyArmored: String + ) throws -> String { + try Pgp.pgpDecrypt( + cipherText: encryptedSecret, toPrivateKeyArmored: privateKeyArmored) + } + + public static func decryptMessage( + _ message: String, + secretKey: String + ) throws -> String { + do { + guard let userMsg = try AESCBCHelper.decrypt(cipherText: message, secretKey: secretKey) else { + throw PushChat.ChatError.dectyptionFalied + } + + if let userMsgStr = String(data: userMsg, encoding: .utf8) { + return userMsgStr + } + throw PushChat.ChatError.dectyptionFalied + } catch { + throw PushChat.ChatError.dectyptionFalied + } + } + } diff --git a/Sources/Chat/Group/GetGroup.swift b/Sources/Chat/Group/GetGroup.swift index f979e8b..7f171ec 100644 --- a/Sources/Chat/Group/GetGroup.swift +++ b/Sources/Chat/Group/GetGroup.swift @@ -25,7 +25,7 @@ extension PushChat { } public static func getGroupInfoDTO(chatId: String, env: ENV) async throws -> PushChat - .PushGroupInfoDTO? + .PushGroupInfoDTO { let url = try PushEndpoint.getGroup(chatId: chatId, apiVersion: "v2", env: env).url var request = URLRequest(url: url) @@ -38,7 +38,7 @@ extension PushChat { } if httpResponse.statusCode == 400 { - return nil + throw URLError(.badServerResponse) } guard (200...299).contains(httpResponse.statusCode) else { diff --git a/Sources/Chat/Send.swift b/Sources/Chat/Send.swift index 21466e7..874d59f 100644 --- a/Sources/Chat/Send.swift +++ b/Sources/Chat/Send.swift @@ -47,27 +47,68 @@ extension PushChat { } } + public enum MessageType: String { + case Text = "Text" + case Image = "Image" + case Reaction = "Reaction" + case Reply = "Reply" + case MediaEmbed = "MediaEmbed" + } + public struct SendOptions { public var messageContent = "" - public var messageType = "Text" + public var messageType: MessageType public var receiverAddress: String public var account: String public var pgpPrivateKey: String public var senderPgpPubicKey: String? public var receiverPgpPubicKey: String? + public var processMessage: String? + public var reference: String? public var env: ENV = .STAGING + public enum Reactions: String { + case THUMBSUP = "\u{1F44D}" + case THUMBSDOWN = "\u{1F44E}" + case HEART = "\u{2764}\u{FE0F}" + case CLAP = "\u{1F44F}" + case LAUGH = "\u{1F602}" + case SAD = "\u{1F622}" + case ANGRY = "\u{1F621}" + case SURPRISE = "\u{1F632}" + case FIRE = "\u{1F525}" + } + public init( messageContent: String, messageType: String, receiverAddress: String, account: String, - pgpPrivateKey: String, env: ENV = .STAGING + pgpPrivateKey: String, refrence: String? = nil, env: ENV = .STAGING ) { self.messageContent = messageContent - self.messageType = messageType + self.messageType = MessageType(rawValue: messageType)! self.receiverAddress = walletToPCAIP10(account: receiverAddress) self.account = walletToPCAIP10(account: account) self.pgpPrivateKey = pgpPrivateKey + self.reference = refrence self.env = env } + + public func getMessageObjJSON() throws -> String { + switch messageType { + case .Text, .Image, .MediaEmbed: + return try getJsonStringFromKV([ + ("content", self.messageContent) + ]) + case .Reaction: + return try getJsonStringFromKV([ + ("content", self.messageContent), + ("refrence", self.reference!), + ]) + case .Reply: + return """ + {"content":{"messageType":"Text","messageObj":{"content":"\(self.messageContent)"}},"reference":"\(self.reference!)"} + """.trimmingCharacters(in: .whitespaces) + } + } } static func sendIntentService(payload: SendMessagePayload, env: ENV) async throws -> Message { @@ -154,19 +195,21 @@ extension PushChat { { var encType = "PlainText" - var (signature, messageConent) = ("", options.messageContent) + var (dep_signature, messageConent) = ("", options.messageContent) + var messageObj = try options.getMessageObjJSON() let secretKey = try Pgp.pgpDecrypt( cipherText: groupInfo.encryptedSecret!, toPrivateKeyArmored: options.pgpPrivateKey) if groupInfo.encryptedSecret != nil { + // Enc message encType = "pgpv1:group" - messageConent = try AESCBCHelper.encrypt(messageText: messageConent, secretKey: secretKey) - signature = try Pgp.sign(message: messageConent, privateKey: options.pgpPrivateKey) + dep_signature = try Pgp.sign(message: messageConent, privateKey: options.pgpPrivateKey) + messageObj = try AESCBCHelper.encrypt(messageText: messageObj, secretKey: secretKey) } else { - signature = try signMessage( + dep_signature = try signMessage( messageContent: messageConent, senderPgpPrivateKey: options.pgpPrivateKey) } @@ -175,8 +218,8 @@ extension PushChat { ("toDID", options.account), ("fromCAIP10", options.account), ("toCAIP10", options.receiverAddress), - ("messageObj", messageConent), - ("messageType", "Text"), + ("messageObj", messageObj), + ("messageType", options.messageType.rawValue), ("encType", encType), ("sessionKey", groupInfo.sessionKey!), ("encryptedSecret", "null"), @@ -189,9 +232,9 @@ extension PushChat { fromDID: options.account, toDID: options.receiverAddress, fromCAIP10: options.account, toCAIP10: options.receiverAddress, messageContent: messageConent, - messageObj: messageConent, - messageType: options.messageType, - signature: signature, encType: encType, encryptedSecret: nil, sigType: "pgpv3", + messageObj: messageObj, + messageType: options.messageType.rawValue, + signature: dep_signature, encType: encType, encryptedSecret: nil, sigType: "pgpv3", verificationProof: "pgpv3:\(verificationProof)", sessionKey: groupInfo.sessionKey) @@ -224,7 +267,7 @@ extension PushChat { return SendMessagePayload( fromDID: options.account, toDID: options.receiverAddress, fromCAIP10: options.account, toCAIP10: options.receiverAddress, - messageContent: messageConent, messageType: options.messageType, + messageContent: messageConent, messageType: options.messageType.rawValue, signature: signature, encType: encType, encryptedSecret: encryptedSecret, sigType: "pgp") } @@ -305,7 +348,7 @@ extension PushChat { if shouldEncrypt { if isGroupChatId(receiverAddress) { let groupInfo = try await PushChat.getGroupInfoDTO( - chatId: receiverAddress, env: sendOptions.env)! + chatId: receiverAddress, env: sendOptions.env) if groupInfo.isPublic { publicKeys = try await getGroupChatPublicKeys(sendOptions) } else { @@ -353,7 +396,7 @@ extension PushChat { if approveOptions.isGroupChat { // TODO: remove unwrap let groupInfo = try await PushChat.getGroupInfoDTO( - chatId: approveOptions.toDID, env: approveOptions.env)! + chatId: approveOptions.toDID, env: approveOptions.env) if !groupInfo.isPublic { return try await getApprovePayloadPrivateGroup(approveOptions, groupInfo) } diff --git a/Sources/Helpers/Chat/GetInboxList.swift b/Sources/Helpers/Chat/GetInboxList.swift index 188cb74..6ff56ed 100644 --- a/Sources/Helpers/Chat/GetInboxList.swift +++ b/Sources/Helpers/Chat/GetInboxList.swift @@ -57,7 +57,7 @@ private func decryptFeeds( throw PushChat.ChatError.decryptedPrivateKeyNecessary } - let decryptedMsg = try await PushChat.decryptMessage( + let (decryptedMsg, _) = try await PushChat.decryptMessage( message: currentFeed.msg!, privateKeyArmored: pgpPrivateKey!, env: env) currentFeed.msg?.messageContent = decryptedMsg } diff --git a/Sources/Helpers/Ipfs/Cid.swift b/Sources/Helpers/Ipfs/Cid.swift index aa2f1b4..94f0f61 100644 --- a/Sources/Helpers/Ipfs/Cid.swift +++ b/Sources/Helpers/Ipfs/Cid.swift @@ -7,6 +7,7 @@ public struct Message: Codable { public var toDID: String public var messageType: String public var messageContent: String + public var messageObj: String? public var signature: String public var sigType: String public var timestamp: Int? @@ -19,6 +20,7 @@ public struct Message: Codable { public func getCID(env: ENV, cid: String) async throws -> Message { let url: URL = PushEndpoint.getCID(env: env, cid: cid).url + let (data, res) = try await URLSession.shared.data(from: url) guard let httpResponse = res as? HTTPURLResponse else { diff --git a/Tests/Chat/Group/SendGroupMsgTests.swift b/Tests/Chat/Group/SendGroupMsgTests.swift index 071c833..8464981 100644 --- a/Tests/Chat/Group/SendGroupMsgTests.swift +++ b/Tests/Chat/Group/SendGroupMsgTests.swift @@ -34,7 +34,7 @@ class GroupChatSendMsgTests: XCTestCase { pgpPrivateKey: UserPrivateKey )) - let decrytedMessage = try await PushChat.decryptMessage( + let (decrytedMessage, _) = try await PushChat.decryptMessage( message: msgRes, privateKeyArmored: UserPrivateKey) XCTAssertEqual(msgRes.encType, "pgp") diff --git a/Tests/Chat/P2P/SendTests.swift b/Tests/Chat/P2P/SendTests.swift index 51eece5..28f16b8 100644 --- a/Tests/Chat/P2P/SendTests.swift +++ b/Tests/Chat/P2P/SendTests.swift @@ -201,7 +201,8 @@ class SendChatsTests: XCTestCase { pgpPrivateKey: UserPrivateKey )) - let res = try await PushChat.decryptMessage(message: msg, privateKeyArmored: UserPrivateKey) + let (res, _) = try await PushChat.decryptMessage( + message: msg, privateKeyArmored: UserPrivateKey) XCTAssertEqual(res, messageToSen2) } diff --git a/Tests/Helper/IpfsTests.swift b/Tests/Helper/IpfsTests.swift index 5e12cd9..441c882 100644 --- a/Tests/Helper/IpfsTests.swift +++ b/Tests/Helper/IpfsTests.swift @@ -4,30 +4,36 @@ import XCTest class IpfsTests: XCTestCase { func testGetCID() async throws { - let cid = "bafyreiauddxpzcgcwphwhsvldctuka6tvtwsfbga6v57p4gno2zpo3vmtm" - let message = try await Push.getCID(env: ENV.STAGING, cid: cid) - - XCTAssertNotNil(message.fromCAIP10, "from CAIP10 should not be nil") - XCTAssertNotNil(message.toCAIP10, "to CAIP10 should not be nil") - XCTAssertNotNil(message.messageType, "messageType should not be nil") - XCTAssertNotNil(message.messageContent, "messageContent should not be nil") - - XCTAssertEqual(message.fromCAIP10, message.fromDID, "from CAIP10 should be equal to from DID") - XCTAssertEqual(message.toCAIP10, message.toDID, "to CAIP10 should be equal to to DID") - XCTAssert(message.encType == "pgp", "encType should be pgp") - - XCTAssertTrue( - message.signature.hasPrefix("-----BEGIN PGP SIGNATURE-----"), - "signature should begin with appropriate prefix") - XCTAssertTrue( - message.signature.hasSuffix("-----END PGP SIGNATURE-----\n"), - "signature should end with appropriate suffix") - XCTAssertTrue( - message.encryptedSecret!.hasPrefix("-----BEGIN PGP MESSAGE-----"), - "encryptedSecret should begin with appropriate prefix") - XCTAssertTrue( - message.encryptedSecret!.hasSuffix("-----END PGP MESSAGE-----\n"), - "encryptedSecret should end with appropriate suffix") + let cid = "v2:8884b4e8df8e6ea8985bac41f4cd87407c02a2ac1d411033bd0586a252b6c536" + let message = try await Push.getCID(env: ENV.DEV, cid: cid) + + print("got the message: \(message)") + + // XCTAssertNotNil(message.fromCAIP10, "from CAIP10 should not be nil") + // XCTAssertNotNil(message.toCAIP10, "to CAIP10 should not be nil") + // XCTAssertNotNil(message.messageType, "messageType should not be nil") + // XCTAssertNotNil(message.messageContent, "messageContent should not be nil") + + // XCTAssertEqual(message.fromCAIP10, message.fromDID, "from CAIP10 should be equal to from DID") + // XCTAssertEqual(message.toCAIP10, message.toDID, "to CAIP10 should be equal to to DID") + // XCTAssert(message.encType == "pgp", "encType should be pgp") + + // XCTAssertTrue( + // message.signature.hasPrefix("-----BEGIN PGP SIGNATURE-----"), + // "signature should begin with appropriate prefix") + // XCTAssertTrue( + // message.signature.hasSuffix("-----END PGP SIGNATURE-----\n"), + // "signature should end with appropriate suffix") + // XCTAssertTrue( + // message.encryptedSecret!.hasPrefix("-----BEGIN PGP MESSAGE-----"), + // "encryptedSecret should begin with appropriate prefix") + // XCTAssertTrue( + // message.encryptedSecret!.hasSuffix("-----END PGP MESSAGE-----\n"), + // "encryptedSecret should end with appropriate suffix") + + // https://backend-dev.epns.io/apis/v1/ipfs/v2:8884b4e8df8e6ea8985bac41f4cd87407c02a2ac1d411033bd0586a252b6c536? + // https://backend-dev.epns.io/apis/v1/ipfs/v2:8884b4e8df8e6ea8985bac41f4cd87407c02a2ac1d411033bd0586a252b6c536%3F? + // https://backend-dev.epns.io/apis/v1/ipfs/v2:8884b4e8df8e6ea8985bac41f4cd87407c02a2ac1d411033bd0586a252b6c536? } func testGetInvalidCID() async throws { diff --git a/Tests/e2e/GroupConversation.swift b/Tests/e2e/GroupConversation.swift index 756fa20..496f11f 100644 --- a/Tests/e2e/GroupConversation.swift +++ b/Tests/e2e/GroupConversation.swift @@ -58,7 +58,7 @@ class GroupFullConversation: XCTestCase { env: .STAGING)) let newGroup = try await PushChat.getGroupInfoDTO( - chatId: createdGroup.chatId, env: ENV.STAGING)! + chatId: createdGroup.chatId, env: ENV.STAGING) XCTAssert(newGroup.sessionKey!.count > 0) XCTAssert(res.contains(address1)) diff --git a/Tests/e2e/PrivateGroupDecrypt.swift b/Tests/e2e/PrivateGroupDecrypt.swift index 3434bdc..c6dae75 100644 --- a/Tests/e2e/PrivateGroupDecrypt.swift +++ b/Tests/e2e/PrivateGroupDecrypt.swift @@ -13,95 +13,161 @@ class PrivateGroupSendRead: XCTestCase { env: env )! - let _ = try await PushChat.Latest( + let message = try await PushChat.Latest( threadHash: converationHash, pgpPrivateKey: PG_PGP_KEY, toDecrypt: true, env: env ) + assert(message.messageContent != "") + // print("got message \(message.messageContent)") // print(message) } - func testPrivateGroupSendPrivateMessage() async throws { + func testPrivateGroupSendPrivateMessageText() async throws { + let res = try await PushChat.send( + PushChat.SendOptions( + messageContent: "This is the test message", + messageType: PushChat.MessageType.Text.rawValue, + receiverAddress: PG_GROUP_ID, + account: PG_USER, + pgpPrivateKey: PG_PGP_KEY + )) + + assert(res.cid != nil) + } + + func testPrivateGroupSendPrivateMessageImage() async throws { + let res = try await PushChat.send( + PushChat.SendOptions( + messageContent: + "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAIAAAD8GO2jAAAEa0lEQVR4nLzW+1OUVRwG8F1Ylk0YxSQuAxjIRRhDyiQJKHZlAkSlHQdwEkSTywgKCiKIqFsbYEFIGWhgCBKjJBexkSUFVAZowLxEEDeH5DJyWTccySsS9Dz9D7788DnM8L7Med5zzvd7JIPNVSKRKGf3Kqi3whTuezgMK+ySYOO2XhhVVAJjCwegW2otPHegCEpzCuCU4gWclWyEohEb4J2wFOYd4n/WE73iH3GB83EMVRF1MLjrJAwKMYJPVWvgyrsv4cWQbjgg2wQNI39kYvUDWONxE941/APWBsYxfXAxfHfOD8pS+oVIIMkpmsTwbDoAeo58CMfnzkJzBdfD3SKFcyn/G2Zd4hevdOMK7Y1xhGU9Q7DYfA/MtqqHC8Z00PTELFxrdV2IBGLT3EgMccqr8NjUQhgz4gp1hXegmToQOumpYHfrcpjyiwf8yCEG2id1wYXy23CDNh/+W38JOv7MNVNV7xIigaTVbQZDc1oFLLTjfNWKMOiXHgW981vgqMwcWml4DqQJLtA2k7tLmecDd56/BsvrTOCVDj7pnMi3IsOshEggznQ4jeGRXRZnF/8pPDPEE6CxWAy/lG6B+zRMNrF2Cta587ULdtWwN+UCrMzk6Zme3Q1VPf5wo88OeHNvhBAJJPHB3EUeS8theCRX36Wdq/JX91H4+XkvmHuQCWKmPoNJTs+howPz3dd+AjfZP2TWEp4hm7S3OOtrm+F4dpkgCRLl3AMHbpvBzmEZfOFVA5+FhkDftkdwsyd3yPrvNnDu9X/CXbZ8fnRsO8xuiIeVsXKY2voPLDTiSvQvmRQigXiy7wMM82ruopduofCLNms40MNd/PUM5/h8aBEsq2DFf3OSe8ml5XV4aM8YVH61Ghq6jEBXS24yLyXrkv/leUESnCwwwBAQzS8+Ge4Lw5s08NeJIbhM+huVsTdlRl+HUYd3wv1FXAPFOv7uWsuKm9U2Dqud0qHJa+/AG9+0CJFAIvbkTje16INjaq573Ag7VI+O31GryoDpIn1o4aOE377NZ94/fA/eql0HfQdOwMfbz8A+B55h/Sz+9UjnD4IkSJ65zPlaci5JInYxa18LOOHGKh/XxC5WOMiTuSYglZkW83lrB/asiw03YG40d1FxfzOU65pg4yr2tR0GWkESnNJwxXOcW+Hy+CVQv/cJ9KnkiZX/znuOmY0atqflwuDvuTY1Vy3hYCDzjSrkUBfUBtu2sB+UefJe5PnEUYgE4mmDKxiStzZCg845OFx6BCZ4bINdZzuhXx5rVOlj9on5kvdgRwZvc/kPeAJiU1h3w46zCjRXMU24P/vz0QYnIRJI7oc+xVCWztqtkS6D0nOsRUaLjsEIk63QfQXvHGErWXl+OsWdXvExu3HAAmN4K5nfOt57P6zTSvklug/CRON8IRKIlaGs+KtlrKah/3fgNzSlsNKEs6sb5c0n2YP91smSM1VlBEH7fFanMQXvpq7r2cXaT3OF7tzrgM5G7NiBxrZCJPgvAAD//zl2dP4g/Ks+AAAAAElFTkSuQmCC", + messageType: "Image", + + receiverAddress: PG_GROUP_ID, + account: PG_USER, + pgpPrivateKey: PG_PGP_KEY + )) + + assert(res.cid != nil) + } + + func testPrivateGroupSendPrivateMessageReaction() async throws { + + let res_0 = try await PushChat.send( + PushChat.SendOptions( + messageContent: "This is the test message", + messageType: PushChat.MessageType.Text.rawValue, + receiverAddress: PG_GROUP_ID, + account: PG_USER, + pgpPrivateKey: PG_PGP_KEY + )) + + let res = try await PushChat.send( + PushChat.SendOptions( + messageContent: PushChat.SendOptions.Reactions.THUMBSUP.rawValue, + messageType: PushChat.MessageType.Reaction.rawValue, + receiverAddress: PG_GROUP_ID, + account: PG_USER, + pgpPrivateKey: PG_PGP_KEY, + refrence: res_0.cid! + )) + + assert(res.cid != nil) - let _ = try await PushChat.send( + } + + func testPrivateGroupSendPrivateMessageReply() async throws { + let res_0 = try await PushChat.send( PushChat.SendOptions( messageContent: "This is the test message", - messageType: "Text", + messageType: PushChat.MessageType.Text.rawValue, receiverAddress: PG_GROUP_ID, account: PG_USER, pgpPrivateKey: PG_PGP_KEY )) + let res = try await PushChat.send( + PushChat.SendOptions( + messageContent: "This is the reply message", + messageType: PushChat.MessageType.Reply.rawValue, + receiverAddress: PG_GROUP_ID, + account: PG_USER, + pgpPrivateKey: PG_PGP_KEY, + refrence: res_0.cid! + )) + + assert(res.cid != nil) + } } -let PG_USER = "0xc95fE6BC0eC97aFA7adF2e98628caC6ec28Bb04c" -let PG_GROUP_ID = "ed3046965676e2118f452aa21318e527bec662dece05f63003e934c116b13e7d" +let PG_USER = "0x45A6859F165edf0a55bE1246404D87f55D1A2a75" +let PG_GROUP_ID = "65247b1fe5b83e980d0cfced52d050afa4290918b41bd3ded04edc74214b25c0" + let PG_PGP_KEY = """ -----BEGIN PGP PRIVATE KEY BLOCK----- - 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 - QdNy/dq7bCBplsE0k/pBwxs/AQ== - =svYB + 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 + aLKX7DslUvWS3JV3SyuVqgMD2g== + =oN+c -----END PGP PRIVATE KEY BLOCK----- - """ diff --git a/Tests/e2e/PrivateGroupUpdate.swift b/Tests/e2e/PrivateGroupUpdate.swift new file mode 100644 index 0000000..148f4ce --- /dev/null +++ b/Tests/e2e/PrivateGroupUpdate.swift @@ -0,0 +1,7 @@ +import Push +import XCTest + +class PrivateGroupUpdate: XCTestCase { + let env = ENV.STAGING + +} diff --git a/docs/GroupChat.md b/docs/GroupChat.md index 441ba5d..3526694 100644 --- a/docs/GroupChat.md +++ b/docs/GroupChat.md @@ -247,3 +247,53 @@ try await PushChat.leaveGroup( ) ``` --- + + +### Chat Reply +```swift + +// Send normal chat +let m1 = PushChat.SendOptions( + messageContent: "This is the test message", + messageType: PushChat.MessageType.Text.rawValue, + receiverAddress: PG_GROUP_ID, + account: PG_USER, + pgpPrivateKey: PG_PGP_KEY +)) + +// Send reply +try await PushChat.send( + PushChat.SendOptions( + messageContent: "This is the reply message", + messageType: PushChat.MessageType.Reply.rawValue, + receiverAddress: PG_GROUP_ID, + account: PG_USER, + pgpPrivateKey: PG_PGP_KEY, + refrence: m1.cid! + )) +``` +--- + +### Chat Reaction +```swift +// Send normal chat +let m1 = PushChat.SendOptions( + messageContent: "This is the test message", + messageType: PushChat.MessageType.Text.rawValue, + receiverAddress: PG_GROUP_ID, + account: PG_USER, + pgpPrivateKey: PG_PGP_KEY +)) + +// Send reaction +try await PushChat.send( + PushChat.SendOptions( + messageContent:PushChat.SendOptions.Reactions.THUMBSUP.rawValue, + messageType: PushChat.MessageType.Reply.rawValue, + receiverAddress: PG_GROUP_ID, + account: PG_USER, + pgpPrivateKey: PG_PGP_KEY, + refrence: m1.cid! + )) +``` +--- \ No newline at end of file