/** * slack */ module.exports = function(crowi) { 'use strict'; var debug = require('debug')('crowi:util:slack'), Config = crowi.model('Config'), Botkit = require('botkit'), isDebugSlackbot = false, appBot = null, // for Slack App iwhBot = null, // for Slack Incoming Webhooks slack = {}; slack.appController = undefined; // for Slack App slack.iwhController = undefined; // for Slack Incoming Webhooks // isDebugSlackbot = true; // for debug slack.getBot = function() { var config = crowi.getConfig(); // when incoming Webhooks is prioritized if (Config.isIncomingWebhookPrioritized(config)) { if (Config.hasSlackIwhUrl(config)) { return iwhBot || slack.initIwhBot(); } else if (Config.hasSlackToken(config)) { return appBot || slack.initAppBot(); } } // else else { if (Config.hasSlackToken(config)) { return appBot || slack.initAppBot(); } else if (Config.hasSlackIwhUrl(config)) { return iwhBot || slack.initIwhBot(); } } return false; }; slack.initAppBot = function(isClearToken) { var config = crowi.getConfig(); if (!slack.appController) { slack.configureSlackApp(); } if (!slack.appController) { return false; } if (!isClearToken && Config.hasSlackToken(config)) { appBot = slack.appController.spawn({token: config.notification['slack:token']}); } else { appBot = slack.appController.spawn(); } return appBot; }; slack.initIwhBot = function() { var config = crowi.getConfig(); if (!slack.iwhController) { slack.configureSlackIwh(); } if (!slack.iwhController) { return false; } iwhBot = slack.iwhController.spawn({ incoming_webhook: { url: config.notification['slack:incomingWebhookUrl'] } }); return iwhBot; } slack.configureSlackApp = function () { var config = crowi.getConfig(); if (Config.hasSlackAppConfig(config)) { slack.appController = Botkit.slackbot({debug: isDebugSlackbot}); slack.appController.configureSlackApp({ clientId: config.notification['slack:clientId'], clientSecret: config.notification['slack:clientSecret'], redirectUri: slack.getSlackAuthCallbackUrl(), scopes: ['chat:write:bot'] }); return true; } return false; } slack.configureSlackIwh = function () { var config = crowi.getConfig(); if (Config.hasSlackIwhUrl(config)) { slack.iwhController = Botkit.slackbot({debug: isDebugSlackbot}); return true; } return false; } // hmmm slack.getSlackAuthCallbackUrl = function() { var config = crowi.getConfig(); // Web アクセスがきてないと app:url がセットされないので crowi.setupSlack 時にはできない // cli, bot 系作るときに問題なりそう return (config.crowi['app:url'] || '') + '/admin/notification/slackAuth'; } slack.getAuthorizeURL = function () { if (!slack.appController) { slack.configureSlackApp(); } if (!slack.appController) { return ''; } return slack.appController.getAuthorizeURL(); } slack.post = function (message) { var bot = slack.getBot(); let sendMethod = undefined; // use Slack App if (bot === appBot) { debug(`sendMethod: bot.api.chat.postMessage`); sendMethod = bot.api.chat.postMessage; } // use Slack Incoming Webhooks else if (bot === iwhBot) { debug(`sendMethod: bot.sendWebhook`); sendMethod = bot.sendWebhook; } if (sendMethod === undefined) { debug(`sendMethod is undefined`); return Promise.resolve(); } return new Promise(function(resolve, reject) { sendMethod(message, function(err, res) { if (err) { debug('Post error', err, res); debug('Sent data to slack is:', message); return reject(err); } resolve(res); }); }); }; slack.convertMarkdownToMrkdwn = function(body) { var config = crowi.getConfig(); var url = ''; if (config.crowi && config.crowi['app:url']) { url = config.crowi['app:url']; } body = body .replace(/\n\*\s(.+)/g, '\n• $1') .replace(/#{1,}\s?(.+)/g, '\n*$1*') .replace(/(\[(.+)\]\((https?:\/\/.+)\))/g, '<$3|$2>') .replace(/(\[(.+)\]\((\/.+)\))/g, '<' + url + '$3|$2>') ; return body; }; slack.prepareAttachmentTextForCreate = function(page, user) { var body = page.revision.body; if (body.length > 2000) { body = body.substr(0, 2000) + '...'; } return this.convertMarkdownToMrkdwn(body); }; slack.prepareAttachmentTextForUpdate = function(page, user, previousRevision) { var diff = require('diff'); var diffText = '' diff.diffLines(previousRevision.body, page.revision.body).forEach(function(line) { debug('diff line', line) var value = line.value.replace(/\r\n|\r/g, '\n'); if (line.added) { diffText += `:pencil2: ...\n${line.value}`; } else if (line.removed) { // diffText += '-' + line.value.replace(/(.+)?\n/g, '- $1\n'); // 1以下は無視 if (line.count > 1) { diffText += `:wastebasket: ... ${line.count} lines\n`; } } else { //diffText += '...\n'; } }); debug('diff is', diffText) return diffText; }; slack.prepareSlackMessage = function(page, user, channel, updateType, previousRevision) { var config = crowi.getConfig(); var url = config.crowi['app:url'] || ''; var body = page.revision.body; if (updateType == 'create') { body = this.prepareAttachmentTextForCreate(page, user); } else { body = this.prepareAttachmentTextForUpdate(page, user, previousRevision); } var attachment = { color: '#263a3c', author_name: '@' + user.username, author_link: url + '/user/' + user.username, author_icon: user.image, title: page.path, title_link: url + '/' + page._id, text: body, mrkdwn_in: ["text"], }; if (user.image) { attachment.author_icon = user.image; } var message = { channel: '#' + channel, username: 'Crowi', text: this.getSlackMessageText(page.path, user, updateType), attachments: [attachment], }; return message; }; slack.getSlackMessageText = function(path, user, updateType) { var text; if (updateType == 'create') { text = `:white_check_mark: ${user.username} created a new page! ${path}`; } else { text = `:up: ${user.username} updated ${path}`; } return text; }; return slack; };