slack.js 4.9 KB

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