From 5513668f93e4b5fc5e7fc8585633536df0cff62e Mon Sep 17 00:00:00 2001 From: Dmytro Rudzik Date: Fri, 13 Apr 2018 15:38:08 +0300 Subject: [PATCH] Send messages as markdown --- __tests__/adapter/reply.js | 28 ++------- __tests__/adapter/replyLink.js | 68 --------------------- __tests__/adapter/send.js | 18 +----- __tests__/adapter/sendFailed.js | 35 +++++------ __tests__/adapter/sendLink.js | 57 ----------------- __tests__/helpers/mocks/stride/listeners.js | 20 ++++++ lib/StrideAdapter.js | 68 ++++----------------- lib/common/net/Stride.js | 38 +++--------- package.json | 2 +- 9 files changed, 67 insertions(+), 267 deletions(-) delete mode 100644 __tests__/adapter/replyLink.js delete mode 100644 __tests__/adapter/sendLink.js diff --git a/__tests__/adapter/reply.js b/__tests__/adapter/reply.js index 4468920..3da51f6 100644 --- a/__tests__/adapter/reply.js +++ b/__tests__/adapter/reply.js @@ -4,9 +4,9 @@ const context = new Context() beforeAll(() => context.begin()) afterAll(() => context.end()) -test('Adapter.reply sends message to Stride with user mention prepended', async () => { +test('Adapter.reply sends message to Stride', async () => { const getTokenRequest = utils.waitForRequest(mocks.stride.listeners.getToken) - const sendMessageRequest = utils.waitForRequest(mocks.stride.listeners.sendMessage) + const sendMessageMarkdownRequest = utils.waitForRequest(mocks.stride.listeners.sendMessageMarkdown) context.app.adapter.reply({ room: { @@ -19,26 +19,6 @@ test('Adapter.reply sends message to Stride with user mention prepended', async }, 'test message') await getTokenRequest - const res = await sendMessageRequest - expect(res.body).toEqual({ - 'body': { - 'content': [{ - 'content': [{ - 'attrs': { - 'id': 'dummy-user-id' - }, - 'type': 'mention' - }, { - 'text': ': ', - 'type': 'text' - }, { - 'text': 'test message', - 'type': 'text' - }], - 'type': 'paragraph' - }], - 'type': 'doc', - 'version': 1 - } - }) + const res = await sendMessageMarkdownRequest + expect(res.body).toBe('test message') }) diff --git a/__tests__/adapter/replyLink.js b/__tests__/adapter/replyLink.js deleted file mode 100644 index f4655ae..0000000 --- a/__tests__/adapter/replyLink.js +++ /dev/null @@ -1,68 +0,0 @@ -const {Context, mocks, utils} = require('../helpers') -const context = new Context() - -beforeAll(() => context.begin()) -afterAll(() => context.end()) - -test('Adapter.reply sends message with parsed links to Stride and with user mention prepended', async () => { - const getTokenRequest = utils.waitForRequest(mocks.stride.listeners.getToken) - const sendMessageRequest = utils.waitForRequest(mocks.stride.listeners.sendMessage) - - context.app.adapter.reply({ - room: { - cloudId: mocks.stride.listeners.defaultCloudId, - conversationId: mocks.stride.listeners.defaultConversationId - }, - user: { - id: 'dummy-user-id' - } - }, ' test message https://media.giphy.com/media/dTJd5ygpxkzWo/giphy.gif test https://media.giphy.com/media/dTJd5ygpxkzWo/giphy.gif test ') - - await getTokenRequest - const res = await sendMessageRequest - expect(res.body).toEqual({ - 'body': { - 'content': [{ - 'content': [{ - 'attrs': { - 'id': 'dummy-user-id' - }, - 'type': 'mention' - }, { - 'text': ': ', - 'type': 'text' - }, { - 'text': ' test message ', - 'type': 'text' - }, { - 'marks': [{ - 'attrs': { - 'href': 'https://media.giphy.com/media/dTJd5ygpxkzWo/giphy.gif' - }, - 'type': 'link' - }], - 'text': 'https://media.giphy.com/media/dTJd5ygpxkzWo/giphy.gif', - 'type': 'text' - }, { - 'text': ' test ', - 'type': 'text' - }, { - 'marks': [{ - 'attrs': { - 'href': 'https://media.giphy.com/media/dTJd5ygpxkzWo/giphy.gif' - }, - 'type': 'link' - }], - 'text': 'https://media.giphy.com/media/dTJd5ygpxkzWo/giphy.gif', - 'type': 'text' - }, { - 'text': ' test ', - 'type': 'text' - }], - 'type': 'paragraph' - }], - 'type': 'doc', - 'version': 1 - } - }) -}) diff --git a/__tests__/adapter/send.js b/__tests__/adapter/send.js index 301d6e5..2d665c0 100644 --- a/__tests__/adapter/send.js +++ b/__tests__/adapter/send.js @@ -6,7 +6,7 @@ afterAll(() => context.end()) test('Adapter.send sends message to Stride', async () => { const getTokenRequest = utils.waitForRequest(mocks.stride.listeners.getToken) - const sendMessageRequest = utils.waitForRequest(mocks.stride.listeners.sendMessage) + const sendMessageMarkdownRequest = utils.waitForRequest(mocks.stride.listeners.sendMessageMarkdown) context.app.adapter.send({ room: { @@ -16,18 +16,6 @@ test('Adapter.send sends message to Stride', async () => { }, 'test message') await getTokenRequest - const res = await sendMessageRequest - expect(res.body).toEqual({ - 'body': { - 'content': [{ - 'content': [{ - 'text': 'test message', - 'type': 'text' - }], - 'type': 'paragraph' - }], - 'type': 'doc', - 'version': 1 - } - }) + const res = await sendMessageMarkdownRequest + expect(res.body).toEqual('test message') }) diff --git a/__tests__/adapter/sendFailed.js b/__tests__/adapter/sendFailed.js index b4389d5..9aea4de 100644 --- a/__tests__/adapter/sendFailed.js +++ b/__tests__/adapter/sendFailed.js @@ -6,7 +6,8 @@ afterAll(() => context.end()) test('Adapter.send emits error on failed Stride API calls', async (done) => { const getTokenRequest = utils.waitForRequest(mocks.stride.listeners.getToken) - const sendMessage400Request = utils.waitForRequest(mocks.stride.listeners.sendMessage400) + const sendMessageMarkdown400Request = + utils.waitForRequest(mocks.stride.listeners.sendMessageMarkdown400) context.app.adapter.send({ room: { @@ -17,23 +18,23 @@ test('Adapter.send emits error on failed Stride API calls', async (done) => { context.app.robot.once('error', res => { expect(res).toMatchObject({ - 'code': 400, - 'source': 'stride', - 'state': { - 'req': { - 'method': 'POST', - 'headers': { - 'Content-Type': 'application/json', - 'Authorization': 'Bearer kinda jwt' + code: 400, + source: 'stride', + state: { + req: { + method: 'POST', + headers: { + 'Content-Type': 'text/markdown', + Authorization: 'Bearer kinda jwt' }, - 'body': '{"body":{"type":"doc","content":[{"type":"paragraph","content":[{"type":"text","text":"test message"}]}],"version":1}}', - 'url': 'https://api.atlassian.com/site/a436116f-02ce-4520-8fbb-7301462a1674/conversation/b1d1f2c9-d9c7-4de6-8cfd-e31029fb4ad0/message' + body: 'test message', + url: 'https://api.atlassian.com/site/a436116f-02ce-4520-8fbb-7301462a1674/conversation/b1d1f2c9-d9c7-4de6-8cfd-e31029fb4ad0/message' }, - 'methodName': 'sendMessage', - 'res': { - 'headers': {}, - 'status': 400, - 'body': '' + methodName: 'sendMessageMarkdown', + res: { + headers: {}, + status: 400, + body: '' } } }) @@ -41,5 +42,5 @@ test('Adapter.send emits error on failed Stride API calls', async (done) => { }) await getTokenRequest - await sendMessage400Request + await sendMessageMarkdown400Request }) diff --git a/__tests__/adapter/sendLink.js b/__tests__/adapter/sendLink.js deleted file mode 100644 index c91a14f..0000000 --- a/__tests__/adapter/sendLink.js +++ /dev/null @@ -1,57 +0,0 @@ -const {Context, mocks, utils} = require('../helpers') -const context = new Context() - -beforeAll(() => context.begin()) -afterAll(() => context.end()) - -test('Adapter.send sends message with parsed links to Stride', async () => { - const getTokenRequest = utils.waitForRequest(mocks.stride.listeners.getToken) - const sendMessageRequest = utils.waitForRequest(mocks.stride.listeners.sendMessage) - - context.app.adapter.send({ - room: { - cloudId: mocks.stride.listeners.defaultCloudId, - conversationId: mocks.stride.listeners.defaultConversationId - } - }, ' test message https://media.giphy.com/media/dTJd5ygpxkzWo/giphy.gif test https://media.giphy.com/media/dTJd5ygpxkzWo/giphy.gif test ') - - await getTokenRequest - const res = await sendMessageRequest - expect(res.body).toEqual({ - 'body': { - 'content': [{ - 'content': [{ - 'text': ' test message ', - 'type': 'text' - }, { - 'marks': [{ - 'attrs': { - 'href': 'https://media.giphy.com/media/dTJd5ygpxkzWo/giphy.gif' - }, - 'type': 'link' - }], - 'text': 'https://media.giphy.com/media/dTJd5ygpxkzWo/giphy.gif', - 'type': 'text' - }, { - 'text': ' test ', - 'type': 'text' - }, { - 'marks': [{ - 'attrs': { - 'href': 'https://media.giphy.com/media/dTJd5ygpxkzWo/giphy.gif' - }, - 'type': 'link' - }], - 'text': 'https://media.giphy.com/media/dTJd5ygpxkzWo/giphy.gif', - 'type': 'text' - }, { - 'text': ' test ', - 'type': 'text' - }], - 'type': 'paragraph' - }], - 'type': 'doc', - 'version': 1 - } - }) -}) diff --git a/__tests__/helpers/mocks/stride/listeners.js b/__tests__/helpers/mocks/stride/listeners.js index 7152a81..6b7ad37 100644 --- a/__tests__/helpers/mocks/stride/listeners.js +++ b/__tests__/helpers/mocks/stride/listeners.js @@ -14,6 +14,24 @@ function sendMessage (onReply, { .reply(201, onReply()) } +function sendMessageMarkdown (onReply, { + cloudId = defaultCloudId, + conversationId = defaultConversationId +} = {}) { + return nock(apiUrl) + .post(`/site/${cloudId}/conversation/${conversationId}/message`) + .reply(201, onReply()) +} + +function sendMessageMarkdown400 (onReply, { + cloudId = defaultCloudId, + conversationId = defaultConversationId +} = {}) { + return nock(apiUrl) + .post(`/site/${cloudId}/conversation/${conversationId}/message`) + .reply(400, onReply()) +} + function sendMessage400 (onReply, { cloudId = defaultCloudId, conversationId = defaultConversationId @@ -52,6 +70,8 @@ module.exports = { getToken, sendMessage, sendMessage400, + sendMessageMarkdown, + sendMessageMarkdown400, uploadFile, defaultCloudId, defaultConversationId diff --git a/lib/StrideAdapter.js b/lib/StrideAdapter.js index 1089ec4..fe8fbe5 100644 --- a/lib/StrideAdapter.js +++ b/lib/StrideAdapter.js @@ -61,66 +61,22 @@ class StrideAdapter extends Adapter { await invokeReduce(stopOrder, 'stop', this.components) } - send (envelope, ...messages) { - const doc = new Document() - - messages.forEach(msg => { - const paragraph = doc.paragraph() - this._textToParsedParagraph(msg, paragraph) + async send (envelope, ...messages) { + await Promise.each(messages, msg => { + return sc.sendMessageMarkdown(envelope.room.cloudId, envelope.room.conversationId, msg) + .catch(error => { + this.robot.emit('error', error) + }) }) - - sc.sendMessage(envelope.room.cloudId, envelope.room.conversationId, doc) - .catch(error => { - this.robot.emit('error', error) - }) } - reply (envelope, ...messages) { - const userId = envelope.user.id - const doc = new Document() - - messages.forEach(msg => { - const paragraph = doc.paragraph() - paragraph - .mention(userId) - .text(': ') - this._textToParsedParagraph(msg, paragraph) + async reply (envelope, ...messages) { + await Promise.each(messages, msg => { + return sc.sendMessageMarkdown(envelope.room.cloudId, envelope.room.conversationId, msg) + .catch(error => { + this.robot.emit('error', error) + }) }) - - sc.sendMessage(envelope.room.cloudId, envelope.room.conversationId, doc) - .catch(error => { - this.robot.emit('error', error) - }) - } - - _textToParsedParagraph (text, paragraph) { - const urlsWithIndices = extractUrlsWithIndices(text) - - const plainIndices = urlsWithIndices.reduce((acc, urlIndex) => { - acc.push(urlIndex.indices[0]) - acc.push(urlIndex.indices[1]) - return acc - }, [0]) - plainIndices.push(text.length) - - plainIndices.forEach((item, currIndex) => { - const nextItem = plainIndices[currIndex + 1] - if (nextItem) { - if (currIndex % 2) { - const nodeText = text.slice(item, nextItem) - if (nodeText) { - paragraph.link(nodeText, nodeText) - } - } else { - const nodeText = text.slice(item, nextItem) - if (nodeText) { - paragraph.text(nodeText) - } - } - } - }) - - return paragraph } } diff --git a/lib/common/net/Stride.js b/lib/common/net/Stride.js index 22ad23d..3629901 100644 --- a/lib/common/net/Stride.js +++ b/lib/common/net/Stride.js @@ -16,36 +16,16 @@ class Stride { this.audience = audience } - // async uploadFile (cloudId, conversationId, fileName, fileStream) { - // return this._fetch('uploadFile', { - // pathname: `/site/${cloudId}/conversation/${conversationId}/media`, - // query: { - // name: fileName - // } - // }, { - // method: 'POST', - // body: fileStream, - // headers: { - // 'Content-Type': 'application/octet-stream' - // } - // }) - // } - - // async getUser (cloudId, userId) { - // return this._fetch('getUser', { - // pathname: `/scim/site/${cloudId}/Users/${userId}` - // }, { method: 'GET' }) - // } - - async sendMessage (cloudId, conversationId, doc, opts) { - const fabricMsg = { - body: doc - } - - const res = await this._fetch('sendMessage', { + async sendMessageMarkdown (cloudId, conversationId, markdown, opts) { + const res = await this._fetch('sendMessageMarkdown', { pathname: `/site/${cloudId}/conversation/${conversationId}/message` - }, { method: 'POST', body: fabricMsg }) - + }, { + method: 'POST', + body: markdown, + headers: { + 'Content-Type': 'text/markdown' + } + }) return res } diff --git a/package.json b/package.json index 8b3997b..fdf2e27 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "hubot-stride", - "version": "1.0.5", + "version": "1.0.6", "description": "Hubot adapter for Atlassian Stride", "main": "lib/web.js", "directories": {