From d61ee3527367c84f088993383900490889b43ce7 Mon Sep 17 00:00:00 2001 From: Ghilia Weldesselasie Date: Fri, 25 Oct 2019 08:49:26 -0400 Subject: [PATCH] feat(ghostThreads): introduced filters (#634) * feat: introduced filters * fix: simplified passesFilter reducer * test: wrote filter test * fix: comment and test fix --- src/__tests__/ghost.test.js | 54 +++++++++++++++++++++++++++++++++++-- src/ghost.js | 9 ++++++- src/space.js | 1 + 3 files changed, 61 insertions(+), 3 deletions(-) diff --git a/src/__tests__/ghost.test.js b/src/__tests__/ghost.test.js index fbfae796..2f1a23a7 100644 --- a/src/__tests__/ghost.test.js +++ b/src/__tests__/ghost.test.js @@ -138,11 +138,61 @@ describe('Ghost Chat', () => { }) afterAll(async () => { - await utils.stopIPFS(ipfs2, 5) + await utils.stopIPFS(ipfs2, 12) + }) + }) + + describe('ghost filter tests', () => { + let chat3 + let ipfs3 + let filter = (payload, issuer, from) => { + if (issuer == DID1) { + return false + } + return true + } + + it('creates third chat correctly', async (done) => { + chat.removeAllListeners() + chat3 = new GhostThread(CHAT_NAME, { ipfs: ipfs3 }, THREEID3_MOCK, { ghostFilters: [filter] }); + expect(chat3._name).toEqual(CHAT_NAME) + expect(chat3._3id).toEqual(THREEID3_MOCK) + expect(chat3.listMembers()).toBeDefined() + expect(chat3.getPosts()).toBeDefined() + + // checks if chat3 joined properly + chat.on('user-joined', async (_event, did, peerId) => { + expect(_event).toEqual('joined') + expect(did).toEqual(DID3) + done() + }) + }) + + it('chat3 should not catch broadcasts from chat', async (done) => { + chat.removeAllListeners() + chat.onUpdate(async ({ type, author, message }) => { + // chat3 should not have the same backlog as chat + // because messages from DID1 (and by extension chat) are being ignored + if (message = 'wide') { + const posts = await chat.getPosts() + const posts3 = await chat3.getPosts() + expect(posts).not.toEqual(posts3) + done() + } + }) + await chat.post('wide') + }) + + beforeAll(async () => { + ipfs3 = await utils.initIPFS(12) + }) + + afterAll(async () => { + await utils.stopIPFS(ipfs3, 12) }) }) afterAll(async () => { - await utils.stopIPFS(ipfs, 4) + await utils.stopIPFS(ipfs, 11) }) }) diff --git a/src/ghost.js b/src/ghost.js index a6289bee..00a72191 100644 --- a/src/ghost.js +++ b/src/ghost.js @@ -17,9 +17,16 @@ class GhostThread extends EventEmitter { this._backlog = new Set() // set of past messages this._backlogLimit = opts.ghostBacklogLimit || DEFAULT_BACKLOG_LIMIT + this._filters = opts.ghostFilters || [] + this._room.on('message', async ({ from, data }) => { const { payload, issuer } = await this._verifyData(data) - if (payload) { + + // we pass the payload, issuer and peerID (from) to each filter in our filters array and reduce the value to a single boolean + // this boolean indicates whether the message passed the filters + const passesFilters = this._filters.reduce((acc, filter) => acc && filter(payload, issuer, from), true) + + if (payload && passesFilters) { switch (payload.type) { case 'join': this._userJoined(issuer, from) diff --git a/src/space.js b/src/space.js index d4f4c441..c0ff1369 100644 --- a/src/space.js +++ b/src/space.js @@ -69,6 +69,7 @@ class Space { * @param {Boolean} opts.noAutoSub Disable auto subscription to the thread when posting to it (default false) * @param {Boolean} opts.ghost Enable ephemeral messaging via Ghost Thread * @param {Number} opts.ghostBacklogLimit The number of posts to maintain in the ghost backlog + * @param {Array} opts.ghostFilters Array of functions for filtering messages * * @return {Thread} An instance of the thread class for the joined thread */