diff --git a/core/server/services/slack.js b/core/server/services/slack.js index 3f10daa27a..21dea2b6dd 100644 --- a/core/server/services/slack.js +++ b/core/server/services/slack.js @@ -4,6 +4,8 @@ var common = require('../lib/common'), urlService = require('../services/url'), settingsCache = require('./settings/cache'), schema = require('../data/schema').checks, + moment = require('moment'), + defaultPostSlugs = [ 'welcome', 'the-editor', @@ -22,13 +24,18 @@ function getSlackSettings() { } function ping(post) { - var message, + let message, + title, + author, slackData = {}, - slackSettings = getSlackSettings(); + slackSettings = getSlackSettings(), + blogTitle = settingsCache.get('title'); // If this is a post, we want to send the link of the post if (schema.isPost(post)) { message = urlService.getUrlByResourceId(post.id, {absolute: true}); + title = post.title ? post.title : null; + author = post.authors ? post.authors[0] : null; } else { message = post.message; } @@ -48,12 +55,56 @@ function ping(post) { return; } - slackData = { - text: message, - unfurl_links: true, - icon_url: imageLib.blogIcon.getIconUrl(true), - username: 'Ghost' - }; + if (schema.isPost(post)) { + slackData = { + // We are handling the case of test notification here by checking + // if it is a post or a test message to check webhook working. + text: `Notification from *${blogTitle}* :ghost:`, + unfurl_links: true, + icon_url: imageLib.blogIcon.getIconUrl(true), + username: 'Ghost', + // We don't want to send attachment if it is a test notification. + attachments: [ + { + fallback: 'Sorry, content cannot be shown.', + title: title, + title_link: message, + author_name: blogTitle, + image_url: post ? urlService.utils.urlFor('image', {image: post.feature_image}, true) : null, + color: '#008952', + fields: [ + { + title: 'Description', + value: post.custom_excerpt ? post.custom_excerpt : `${post.html.replace(/<[^>]+>/g, '').split('.').slice(0, 3).join('.')}.`, + short: false + } + ] + }, + { + fallback: 'Sorry, content cannot be shown.', + color: '#008952', + thumb_url: author ? urlService.utils.urlFor('image', {image: author.profile_image}, true) : null, + fields: [ + { + title: 'Author', + value: author ? `<${urlService.getUrlByResourceId(author.id, {absolute: true})} | ${author.name}>` : null, + short: true + } + ], + footer: blogTitle, + footer_icon: imageLib.blogIcon.getIconUrl(true), + ts: moment().unix() + } + ] + }; + } else { + slackData = { + text: message, + unfurl_links: true, + icon_url: imageLib.blogIcon.getIconUrl(true), + username: 'Ghost' + }; + } return request(slackSettings.url, { body: JSON.stringify(slackData), diff --git a/core/test/unit/services/slack_spec.js b/core/test/unit/services/slack_spec.js index 5cd616fb0f..d8a1a99647 100644 --- a/core/test/unit/services/slack_spec.js +++ b/core/test/unit/services/slack_spec.js @@ -121,7 +121,7 @@ describe('Slack', function () { it('makes a request for a post if url is provided', function () { var requestUrl, requestData; - const post = testUtils.DataGenerator.forKnex.createPost({slug: 'test'}); + const post = testUtils.DataGenerator.forKnex.createPost({slug: 'webhook-test'}); urlService.getUrlByResourceId.withArgs(post.id, {absolute: true}).returns('http://myblog.com/' + post.slug + '/'); isPostStub.returns(true); @@ -132,7 +132,7 @@ describe('Slack', function () { // assertions makeRequestStub.calledOnce.should.be.true(); - isPostStub.calledOnce.should.be.true(); + isPostStub.calledTwice.should.be.true(); urlService.getUrlByResourceId.calledOnce.should.be.true(); settingsCacheStub.calledWith('slack').should.be.true(); @@ -140,7 +140,10 @@ describe('Slack', function () { requestData = JSON.parse(makeRequestStub.firstCall.args[1].body); requestUrl.should.equal(slackObjWithUrl[0].url); - requestData.text.should.eql('http://myblog.com/test/'); + requestData.attachments[0].title.should.equal(post.title); + requestData.attachments[0].title_link.should.equal('http://myblog.com/webhook-test/'); + requestData.attachments[0].fields[0].value.should.equal('## markdown.'); + requestData.attachments[0].should.not.have.property('author_name'); requestData.icon_url.should.equal('http://myblog.com/favicon.ico'); requestData.username.should.equal('Ghost'); requestData.unfurl_links.should.equal(true); @@ -159,7 +162,7 @@ describe('Slack', function () { // assertions makeRequestStub.calledOnce.should.be.true(); - isPostStub.calledOnce.should.be.true(); + isPostStub.calledTwice.should.be.true(); urlService.getUrlByResourceId.called.should.be.false(); settingsCacheStub.calledWith('slack').should.be.true(); @@ -167,7 +170,7 @@ describe('Slack', function () { requestData = JSON.parse(makeRequestStub.firstCall.args[1].body); requestUrl.should.equal(slackObjWithUrl[0].url); - requestData.text.should.eql('Hi!'); + requestData.text.should.equal('Hi!'); requestData.icon_url.should.equal('https://myblog.com/favicon.ico'); requestData.username.should.equal('Ghost'); requestData.unfurl_links.should.equal(true);