diff --git a/packages/status-communities/src/community.spec.ts b/packages/status-communities/src/community.spec.ts index bd3490d5..21c3c5bb 100644 --- a/packages/status-communities/src/community.spec.ts +++ b/packages/status-communities/src/community.spec.ts @@ -4,7 +4,7 @@ import { Waku } from "js-waku"; import { Community } from "./community"; import { CommunityDescription } from "./wire/community_description"; -describe("Community live data", () => { +describe("Community [live data]", () => { before(function () { if (process.env.CI) { // Skip live data test in CI diff --git a/packages/status-communities/src/encryption.spec.ts b/packages/status-communities/src/encryption.spec.ts index 2c16ed94..c4b51897 100644 --- a/packages/status-communities/src/encryption.spec.ts +++ b/packages/status-communities/src/encryption.spec.ts @@ -11,4 +11,14 @@ describe("Encryption", () => { "c49ad65ebf2a7b7253bf400e3d27719362a91b2c9b9f54d50a69117021666c33" ); }); + + it("Generate symmetric key from password for chat", async function () { + const str = + "0x02dcec6041fb999d65f1d33363e08c93d3c1f6f0fbbb26add383e2cf46c2b921f41dc14fd8-9a8b-4df5-a358-2c3067be5439"; + const symKey = await createSymKeyFromPassword(str); + + expect(Buffer.from(symKey).toString("hex")).to.eq( + "76ff5bf0a74a8e724367c7fc003f066d477641f468768a8da2817addf5c2ce76" + ); + }); }); diff --git a/packages/status-communities/src/messenger.spec.ts b/packages/status-communities/src/messenger.spec.ts index fcaae7bb..fe398880 100644 --- a/packages/status-communities/src/messenger.spec.ts +++ b/packages/status-communities/src/messenger.spec.ts @@ -1,6 +1,7 @@ import { expect } from "chai"; import debug from "debug"; +import { Community } from "./community"; import { Identity } from "./identity"; import { Messenger } from "./messenger"; import { bufToHex } from "./utils"; @@ -118,3 +119,68 @@ describe("Messenger", () => { await messengerBob.stop(); }); }); + +describe("Messenger [live data]", () => { + before(function () { + if (process.env.CI) { + // Skip live data test in CI + this.skip(); + } + }); + + let messenger: Messenger; + let identity: Identity; + + beforeEach(async function () { + this.timeout(20_000); + + dbg("Generate keys"); + identity = Identity.generate(); + + dbg("Create messengers"); + + messenger = await Messenger.create(identity, { bootstrap: true }); + + dbg("Wait to be connected to a peer"); + await messenger.waku.waitForConnectedPeer(); + dbg("Messengers ready"); + }); + + it("Receive public chat messages", async function () { + this.timeout(20_000); + + const community = await Community.instantiateCommunity( + "0x0262c65c881f5a9f79343a26faaa02aad3af7c533d9445fb1939ed11b8bf4d2abd", + messenger.waku + ); + + await messenger.joinChats(community.chats.values()); + + const startTime = new Date(Date.now() - 7 * 24 * 60 * 60 * 1000); + const endTime = new Date(); + + const chat = Array.from(community.chats.values()).find( + (chat) => chat.communityChat?.identity?.displayName === "foobar" + ); + + if (!chat) throw "Could not find foobar chat"; + + console.log(chat); + + await messenger.retrievePreviousMessages( + chat.id, + startTime, + endTime, + (metadata) => { + metadata.forEach((m) => { + console.log("Message", m.chatMessage?.text); + }); + } + ); + }); + + afterEach(async function () { + this.timeout(5000); + await messenger.stop(); + }); +}); diff --git a/packages/status-communities/src/messenger.ts b/packages/status-communities/src/messenger.ts index 69d175dc..618d8256 100644 --- a/packages/status-communities/src/messenger.ts +++ b/packages/status-communities/src/messenger.ts @@ -15,7 +15,11 @@ export class Messenger { chatsById: Map; observers: { [chatId: string]: Set< - (message: ApplicationMetadataMessage, timestamp: Date) => void + ( + message: ApplicationMetadataMessage, + timestamp: Date, + chatId: string + ) => void >; }; identity: Identity; @@ -49,6 +53,19 @@ export class Messenger { await this.joinChat(chat); } + /** + * Joins several of public chats. + * + * Use `addListener` to get messages received on these chats. + */ + public async joinChats(chats: Iterable): Promise { + await Promise.all( + Array.from(chats).map((chat) => { + return this.joinChat(chat); + }) + ); + } + /** * Joins a public chat. * @@ -110,18 +127,30 @@ export class Messenger { * @throws string If the chat has not been joined first using [joinChat]. */ public addObserver( - observer: (message: ApplicationMetadataMessage, timestamp: Date) => void, - chatId: string + observer: ( + message: ApplicationMetadataMessage, + timestamp: Date, + chatId: string + ) => void, + chatId: string | string[] ): void { - // Not sure this is the best design here. Maybe `addObserver` and `joinChat` should be merged. + let chats = []; - if (!this.chatsById.has(chatId)) - throw "Cannot add observer on a chat that is not joined."; - if (!this.observers[chatId]) { - this.observers[chatId] = new Set(); + if (typeof chatId === "string") { + chats.push(chatId); + } else { + chats = [...chatId]; } - this.observers[chatId].add(observer); + chats.forEach((id) => { + if (!this.chatsById.has(id)) + throw "Cannot add observer on a chat that is not joined."; + if (!this.observers[id]) { + this.observers[id] = new Set(); + } + + this.observers[id].add(observer); + }); } /** @@ -211,7 +240,7 @@ export class Messenger { if (this.observers[chat.id]) { this.observers[chat.id].forEach((observer) => { - observer(message, timestamp); + observer(message, timestamp, chat.id); }); } }