Ghost/core/server/services/slack.js

151 lines
5.3 KiB
JavaScript
Raw Normal View History

var common = require('../lib/common'),
request = require('../lib/request'),
imageLib = require('../lib/image'),
urlUtils = require('../lib/url-utils'),
urlService = require('../../frontend/services/url'),
settingsCache = require('./settings/cache'),
schema = require('../data/schema').checks,
moment = require('moment'),
defaultPostSlugs = [
'welcome',
'the-editor',
'using-tags',
'managing-users',
'private-sites',
'advanced-markdown',
'themes'
];
function getSlackSettings() {
var setting = settingsCache.get('slack');
// This might one day have multiple entries, for now its always a array
// and we return the first item or an empty object
return setting ? setting[0] : {};
}
function ping(post) {
let message,
title,
author,
slackData = {},
slackSettings = getSlackSettings(),
blogTitle = settingsCache.get('title');
// If this is a post, we want to send the link of the post
if (schema.isPost(post)) {
✨Dynamic Routing Beta (#9596) refs #9601 ### Dynamic Routing This is the beta version of dynamic routing. - we had a initial implementation of "channels" available in the codebase - we have removed and moved this implementation - there is now a centralised place for dynamic routing - server/services/routing - each routing component is represented by a router type e.g. collections, routes, static pages, taxonomies, rss, preview of posts - keep as much as possible logic of routing helpers, middlewares and controllers - ensure test coverage - connect all the things together - yaml file + validation - routing + routers - url service - sitemaps - url access - deeper implementation of yaml validations - e.g. hard require slashes - ensure routing hierarchy/order - e.g. you enable the subscriber app - you have a custom static page, which lives under the same slug /subscribe - static pages are stronger than apps - e.g. the first collection owns the post it has filtered - a post cannot live in two collections - ensure apps are still working and hook into the routers layer (or better said: and register in the routing service) - put as much as possible comments to the code base for better understanding - ensure a clean debug log - ensure we can unmount routes - e.g. you have a collection permalink of /:slug/ represented by {globals.permalink} - and you change the permalink in the admin to dated permalink - the express route get's refreshed from /:slug/ to /:year/:month/:day/:slug/ - unmount without server restart, yey - ensure we are backwards compatible - e.g. render home.hbs for collection index if collection route is / - ensure you can access your configured permalink from the settings table with {globals.permalink} ### Render 503 if url service did not finish - return 503 if the url service has not finished generating the resource urls ### Rewrite sitemaps - we have rewritten the sitemaps "service", because the url generator does no longer happen on runtime - we generate all urls on bootstrap - the sitemaps service will consume created resource and router urls - these urls will be shown on the xml pages - we listen on url events - we listen on router events - we no longer have to fetch the resources, which is nice - the urlservice pre-fetches resources and emits their urls - the urlservice is the only component who knows which urls are valid - i made some ES6 adaptions - we keep the caching logic -> only regenerate xml if there is a change - updated tests - checked test coverage (100%) ### Re-work usage of Url utility - replace all usages of `urlService.utils.urlFor` by `urlService.getByResourceId` - only for resources e.g. post, author, tag - this is important, because with dynamic routing we no longer create static urls based on the settings permalink on runtime - adapt url utility - adapt tests
2018-06-05 20:02:20 +03:00
message = urlService.getUrlByResourceId(post.id, {absolute: true});
title = post.title ? post.title : null;
author = post.authors ? post.authors[0] : null;
} else {
message = post.message;
}
// Quit here if slack integration is not activated
if (slackSettings && slackSettings.url && slackSettings.url !== '') {
slackSettings.username = slackSettings.username ? slackSettings.username : 'Ghost';
// Only ping when not a page
Revert post.page->post.type handling no issue - the column addition/removal can be too slow for large sites - will be added back in 3.0 --- Revert "Fixed canary api for page/type column" This reverts commit a5a7e7e919d83af3ea9cd7402a75dff60f2d7e9c. Revert "Updated frontend canary url config for page/type" This reverts commit 19100ec5e6edbe67464c4938521fe25d7ec15041. Revert "Updated canary api to handle type column correctly (#11006)" This reverts commit c3e8ba0523f5460662dcd3cddf0affd337b26eba. Revert "Ensured `page` filter works in routes.yaml" This reverts commit 9037c19e50c4da026f4b797413a682e1411b032f. Revert "Replaced usage of mongo util with nql-map-key-values" This reverts commit 8c5f1d0ef0ad9a03fb3e362c31063e47a0173411. Revert "Added shared nql-map-key-values module" This reverts commit ef4fd4b8ef3824290a00a371dad5a505431ab689. Revert "Ensured page prop is present on content api response" This reverts commit cfa0a0862bf7b247cfeb9b689cfdf6b8e3fb0c10. Revert "Fixed failing regression tests" This reverts commit 9c2bb3811fba8ea127b22f13d21112dcf1f5a46d. Revert "Updated xmlrpc and slack service to use type column" This reverts commit 44a02c7d3635967dd3fe8f96b793b50fd398bd40. Revert "Updated v0.1 posts api to work with type column" This reverts commit 2c81d7c914ac0a2c3b7f1d6d0385479e61d15f18. Revert "Removed updates to v0.1 specific code" This reverts commit 08d83c1f5332b7db6b96814651b496e707c2e124. Revert "Added missing context from ValidationError" This reverts commit cd45ab4f54abefeee8605df84cfc864fff1ad385. Revert "Renamed page->type in the page&posts serializers" This reverts commit df99e724e3d7dc1665916844983849494deea80d. Revert "Added mongo helper to input serializers" This reverts commit fb8eadb4a8109ba987d79decfe331c669a446609. Revert "Passed mongoTransformer through to NQL" This reverts commit 0ae3f0fdfc864dcf5c90c6b56cf975997974742c. Revert "Permitted mongoTransformer option for read methods" This reverts commit a89376bf2618520626d2cf1b8d86f3c8c453db23. Revert "Updated the count plugin to reference the type column" This reverts commit a52f15d3d3503bc9ce4e20961c1f4a0fd49316c7. Revert "Updated hashes for db integrity check" This reverts commit bb6b337be3d30e919e4edfdc2e59182cb81e9e5d. Revert "Remove page column and remaining references" This reverts commit 9d7190d69255ac011848c6bf654886be81abeedc. Revert "Added type column to data generator" This reverts commit e59806cb45c47e0bd547801de54ac5332913fbf5. Revert "Removed references to page column in rss tests" This reverts commit 04d0f855dede1a1bd910c1bc7ca4913ae27472ae. Revert "Removed page column references in validation tests" This reverts commit f0afbc5cc06449ccae034b930709e29133ca8374. Revert "Updated the post model to use the `type` column" This reverts commit 1189bc823ac6adde4f25d63d9fc83ca94e38d672. Revert "Updated url service to use type column" This reverts commit 61612ba8fd38a72d8ef6af5b2c199a9dcd80b80b. Revert "Updated the v2 api to deal with type column" This reverts commit 57afb2de2baf702575a2ea3e4d8e1b914f769e00. Revert "Added type property to post model defaults" This reverts commit dc3345b1c59d03261ecd678a9cbad0ec91ef5a38. Revert "Added type property to the default post fixtures" This reverts commit 82d8c380336b6455ad09622edf7ecd803d0cbe23. Revert "Added type column to posts table" This reverts commit 9b85fc6a69363c27d11963a5078136cedc696156.
2019-08-16 19:46:00 +03:00
if (post.page) {
return;
}
// Don't ping for the default posts.
// This also handles the case where during ghost's first run
// models.init() inserts this post but permissions.init() hasn't
// (can't) run yet.
if (defaultPostSlugs.indexOf(post.slug) > -1) {
return;
}
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: slackSettings.username,
// 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 ? urlUtils.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 ? urlUtils.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: slackSettings.username
};
}
return request(slackSettings.url, {
body: JSON.stringify(slackData),
headers: {
'Content-type': 'application/json'
}
}).catch(function (err) {
common.logging.error(new common.errors.GhostError({
err: err,
context: common.i18n.t('errors.services.ping.requestFailed.error', {service: 'slack'}),
help: common.i18n.t('errors.services.ping.requestFailed.help', {url: 'https://ghost.org/docs/'})
}));
});
}
}
function listener(model, options) {
// CASE: do not ping slack if we import a database
// TODO: refactor post.published events to never fire on importing
if (options && options.importing) {
return;
}
ping(model.toJSON());
}
function testPing() {
ping({
message: 'Heya! This is a test notification from your Ghost blog :smile:. Seems to work fine!'
});
}
function listen() {
common.events.on('post.published', listener);
common.events.on('slack.test', testPing);
}
// Public API
module.exports = {
listen: listen
};