From 9c2f497c9e28326ca3072a7274aac0cbac9db7d3 Mon Sep 17 00:00:00 2001 From: Franck Royer Date: Wed, 22 Sep 2021 15:05:36 +1000 Subject: [PATCH] Send and receive message --- ...-chai-npm-4.2.22-557883092e-dca66a263b.zip | Bin 0 -> 9785 bytes packages/status-communities/package.json | 1 + packages/status-communities/src/chat.ts | 18 ++-- .../status-communities/src/chat_message.ts | 8 ++ .../status-communities/src/messenger.spec.ts | 23 ++++- packages/status-communities/src/messenger.ts | 81 ++++++++++++++++-- packages/status-communities/tsconfig.json | 6 +- yarn.lock | 8 ++ 8 files changed, 127 insertions(+), 18 deletions(-) create mode 100644 .yarn/cache/@types-chai-npm-4.2.22-557883092e-dca66a263b.zip diff --git a/.yarn/cache/@types-chai-npm-4.2.22-557883092e-dca66a263b.zip b/.yarn/cache/@types-chai-npm-4.2.22-557883092e-dca66a263b.zip new file mode 100644 index 0000000000000000000000000000000000000000..629fd645bac35c8db1052b6a425dd48864d3b87c GIT binary patch literal 9785 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 { ]); }); - it("Sends message in public chat", function () { + it("Sends & Receive message in public chat", async function () { messenger1.joinChat(testChatId); messenger2.joinChat(testChatId); + + const text = "This is a message."; + + const receivedMessagePromise: Promise = new Promise( + (resolve) => { + messenger2.addObserver((message) => { + resolve(message); + }, testChatId); + } + ); + + messenger1.sendMessage(text, testChatId); + + const receivedMessage = await receivedMessagePromise; + + expect(receivedMessage?.text).to.eq(text); }); afterEach(async function () { diff --git a/packages/status-communities/src/messenger.ts b/packages/status-communities/src/messenger.ts index ef5cf2f2..8376f43e 100644 --- a/packages/status-communities/src/messenger.ts +++ b/packages/status-communities/src/messenger.ts @@ -1,26 +1,33 @@ -import { Waku, WakuMessage } from "js-waku"; -import {CreateOptions as WakuCreateOptions } from "js-waku/build/main/lib/waku"; +import { Waku, WakuMessage } from "js-waku"; +import { CreateOptions as WakuCreateOptions } from "js-waku/build/main/lib/waku"; import { Chat } from "./chat"; import { ChatMessage } from "./chat_message"; export class Messenger { waku: Waku; - chatsById: Map; + observers: { + [chatId: string]: Set<(chatMessage: ChatMessage) => void>; + }; private constructor(waku: Waku) { this.waku = waku; this.chatsById = new Map(); + this.observers = {}; } public static async create(wakuOptions?: WakuCreateOptions) { const _wakuOptions = Object.assign({ bootstrap: true }, wakuOptions); const waku = await Waku.create(_wakuOptions); - const messenger = new Messenger(waku); - return messenger; + return new Messenger(waku); } + /** + * Joins a public chat. + * + * Use `addListener` to get messages received on this chat. + */ public joinChat(chatId: string) { if (this.chatsById.has(chatId)) throw "Chat already joined"; @@ -33,6 +40,12 @@ export class Messenger { const chatMessage = ChatMessage.decode(wakuMessage.payload); chat.handleNewMessage(chatMessage); + + if (this.observers[chatId]) { + this.observers[chatId].forEach((observer) => { + observer(chatMessage); + }); + } }, [chat.contentTopic] ); @@ -40,6 +53,64 @@ export class Messenger { this.chatsById.set(chatId, chat); } + /** + * Sends a message on the given chat Id. + * + * @param text + * @param chatId + */ + public async sendMessage(text: string, chatId: string): Promise { + const chat = this.chatsById.get(chatId); + if (!chat) throw `Chat not joined: ${chatId}`; + + const message = chat.createMessage(text); + + const wakuMessage = await WakuMessage.fromBytes( + message.encode(), + chat.contentTopic + ); + + await this.waku.relay.send(wakuMessage); + } + + /** + * Add an observer of new messages received on the chat. + * + * @throws string If the chat has not been joined first using [joinChat]. + */ + public addObserver( + observer: (chatMessage: ChatMessage) => void, + chatId: string + ) { + // Not sure this is the best design here. Maybe `addObserver` and `joinChat` should be merged. + + 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(); + } + + this.observers[chatId].add(observer); + } + + /** + * Add an observer of new messages received on the chat. + * + * @throws string If the chat has not been joined first using [joinChat]. + */ + + deleteObserver( + observer: (chatMessage: ChatMessage) => void, + chatId: string + ): void { + if (this.observers[chatId]) { + this.observers[chatId].delete(observer); + } + } + + /** + * Stops the messenger. + */ public async stop(): Promise { await this.waku.stop(); } diff --git a/packages/status-communities/tsconfig.json b/packages/status-communities/tsconfig.json index 23446d37..482825d4 100644 --- a/packages/status-communities/tsconfig.json +++ b/packages/status-communities/tsconfig.json @@ -38,7 +38,11 @@ "skipLibCheck": true, "lib": ["es6", "dom"], - "typeRoots": ["./node_modules/@types", "./src/types", "../../node_modules/@types"] + "typeRoots": [ + "./node_modules/@types", + "./src/types", + "../../node_modules/@types" + ] }, "include": ["src"], "exclude": ["node_modules/**"], diff --git a/yarn.lock b/yarn.lock index 66b78e05..b713840e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -448,6 +448,13 @@ __metadata: languageName: node linkType: hard +"@types/chai@npm:^4.2.22": + version: 4.2.22 + resolution: "@types/chai@npm:4.2.22" + checksum: dca66a263b25c26112c0a8c6df20316412fa54b557443a108836c07cee961aa56cc5b1763273f69eb450c83ca9f28069ff78b617bffc01806cdd83afc1c20c2a + languageName: node + linkType: hard + "@types/debug@npm:^4.1.5": version: 4.1.7 resolution: "@types/debug@npm:4.1.7" @@ -5531,6 +5538,7 @@ fsevents@~2.3.2: version: 0.0.0-use.local resolution: "status-communities@workspace:packages/status-communities" dependencies: + "@types/chai": ^4.2.22 "@types/mocha": ^9.0.0 "@typescript-eslint/eslint-plugin": ^4.31.1 "@typescript-eslint/parser": ^4.31.1