slack.js 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194
  1. /**
  2. * slack
  3. */
  4. module.exports = function(crowi) {
  5. 'use strict';
  6. var debug = require('debug')('crowi:util:slack'),
  7. Config = crowi.model('Config'),
  8. Botkit = require('botkit'),
  9. sprintf = require('sprintf'),
  10. bot = null,
  11. slack = {};
  12. slack.controller = undefined;
  13. slack.createBot = function() {
  14. // alreay created
  15. if (bot) {
  16. return bot;
  17. }
  18. var config = crowi.getConfig();
  19. if (!slack.controller) {
  20. slack.configureSlackApp();
  21. }
  22. if (!slack.controller) {
  23. return false;
  24. }
  25. if (Config.hasSlackToken(config)) {
  26. bot = slack.controller.spawn({token: config.notification['slack:token']});
  27. } else {
  28. bot = slack.controller.spawn();
  29. }
  30. return bot;
  31. };
  32. slack.configureSlackApp = function ()
  33. {
  34. var config = crowi.getConfig();
  35. if (Config.hasSlackConfig(config)) {
  36. slack.controller = Botkit.slackbot();
  37. slack.controller.configureSlackApp({
  38. clientId: config.notification['slack:clientId'],
  39. clientSecret: config.notification['slack:clientSecret'],
  40. redirectUri: slack.getSlackAuthCallbackUrl(),
  41. scopes: ['chat:write:bot']
  42. });
  43. return true;
  44. }
  45. return false;
  46. }
  47. // hmmm
  48. slack.getSlackAuthCallbackUrl = function()
  49. {
  50. var config = crowi.getConfig();
  51. // Web アクセスがきてないと app:url がセットされないので crowi.setupSlack 時にはできない
  52. // cli, bot 系作るときに問題なりそう
  53. return (config.crowi['app:url'] || '') + '/admin/notification/slackAuth';
  54. }
  55. slack.getAuthorizeURL = function () {
  56. if (!slack.controller) {
  57. slack.configureSlackApp();
  58. }
  59. if (!slack.controller) {
  60. return '';
  61. }
  62. return slack.controller.getAuthorizeURL();
  63. }
  64. slack.post = function (message) {
  65. var bot = slack.createBot();
  66. return new Promise(function(resolve, reject) {
  67. bot.api.chat.postMessage(message, function(err, res) {
  68. if (err) {
  69. debug('Post error', err, res);
  70. debug('Sent data to slack is:', message);
  71. return reject(err);
  72. }
  73. resolve(res);
  74. });
  75. });
  76. };
  77. slack.convertMarkdownToMrkdwn = function(body) {
  78. var config = crowi.getConfig();
  79. var url = '';
  80. if (config.crowi && config.crowi['app:url']) {
  81. url = config.crowi['app:url'];
  82. }
  83. body = body
  84. .replace(/\n\*\s(.+)/g, '\n• $1')
  85. .replace(/#{1,}\s?(.+)/g, '\n*$1*')
  86. .replace(/(\[(.+)\]\((https?:\/\/.+)\))/g, '<$3|$2>')
  87. .replace(/(\[(.+)\]\((\/.+)\))/g, '<' + url + '$3|$2>')
  88. ;
  89. return body;
  90. };
  91. slack.prepareAttachmentTextForCreate = function(page, user) {
  92. var body = page.revision.body;
  93. if (body.length > 2000) {
  94. body = body.substr(0, 2000) + '...';
  95. }
  96. return this.convertMarkdownToMrkdwn(body);
  97. };
  98. slack.prepareAttachmentTextForUpdate = function(page, user, previousRevision) {
  99. var diff = require('diff');
  100. var diffText = ''
  101. diff.diffLines(previousRevision.body, page.revision.body).forEach(function(line) {
  102. debug('diff line', line)
  103. var value = line.value.replace(/\r\n|\r/g, '\n');
  104. if (line.added) {
  105. diffText += sprintf(':pencil2: ...\n%s', line.value);
  106. } else if (line.removed) {
  107. // diffText += '-' + line.value.replace(/(.+)?\n/g, '- $1\n');
  108. // 1以下は無視
  109. if (line.count > 1) {
  110. diffText += sprintf(':wastebasket: ... %s lines\n', line.count);
  111. }
  112. } else {
  113. //diffText += '...\n';
  114. }
  115. });
  116. debug('diff is', diffText)
  117. return diffText;
  118. };
  119. slack.prepareSlackMessage = function(page, user, channel, updateType, previousRevision) {
  120. var config = crowi.getConfig();
  121. var url = config.crowi['app:url'] || '';
  122. var body = page.revision.body;
  123. if (updateType == 'create') {
  124. body = this.prepareAttachmentTextForCreate(page, user);
  125. } else {
  126. body = this.prepareAttachmentTextForUpdate(page, user, previousRevision);
  127. }
  128. var attachment = {
  129. color: '#263a3c',
  130. author_name: '@' + user.username,
  131. author_link: url + '/user/' + user.username,
  132. author_icon: user.image,
  133. title: page.path,
  134. title_link: url + page.path,
  135. text: body,
  136. mrkdwn_in: ["text"],
  137. };
  138. if (user.image) {
  139. attachment.author_icon = user.image;
  140. }
  141. var message = {
  142. channel: '#' + channel,
  143. username: 'Crowi',
  144. text: this.getSlackMessageText(page.path, user, updateType),
  145. attachments: [attachment],
  146. };
  147. return message;
  148. };
  149. slack.getSlackMessageText = function(path, user, updateType) {
  150. var text;
  151. if (updateType == 'create') {
  152. text = sprintf(':white_check_mark: %s created a new page! %s', user.username, path);
  153. } else {
  154. text = sprintf(':up: %s updated %s', user.username, path);
  155. }
  156. return text;
  157. };
  158. return slack;
  159. };