slack.js 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172
  1. /**
  2. * slack
  3. */
  4. module.exports = function(crowi) {
  5. 'use strict';
  6. const SLACK_URL = 'https://slack.com';
  7. const debug = require('debug')('crowi:util:slack'),
  8. config = crowi.getConfig(),
  9. Config = crowi.model('Config'),
  10. Slack = require('slack-node'),
  11. slack = {};
  12. const postWithIwh = function(messageObj, callback) {
  13. const client = new Slack();
  14. client.setWebhook(config.notification['slack:incomingWebhookUrl']);
  15. client.webhook(messageObj, callback);
  16. }
  17. const postWithWebApi = function(messageObj, callback) {
  18. const client = new Slack(config.notification['slack:token']);
  19. // stringify attachments
  20. if (messageObj.attachments != null) {
  21. messageObj.attachments = JSON.stringify(messageObj.attachments);
  22. }
  23. client.api('chat.postMessage', messageObj, callback);
  24. }
  25. const convertMarkdownToMrkdwn = function(body) {
  26. var url = '';
  27. if (config.crowi && config.crowi['app:url']) {
  28. url = config.crowi['app:url'];
  29. }
  30. body = body
  31. .replace(/\n\*\s(.+)/g, '\n• $1')
  32. .replace(/#{1,}\s?(.+)/g, '\n*$1*')
  33. .replace(/(\[(.+)\]\((https?:\/\/.+)\))/g, '<$3|$2>')
  34. .replace(/(\[(.+)\]\((\/.+)\))/g, '<' + url + '$3|$2>')
  35. ;
  36. return body;
  37. };
  38. const prepareAttachmentTextForCreate = function(page, user) {
  39. var body = page.revision.body;
  40. if (body.length > 2000) {
  41. body = body.substr(0, 2000) + '...';
  42. }
  43. return convertMarkdownToMrkdwn(body);
  44. };
  45. const prepareAttachmentTextForUpdate = function(page, user, previousRevision) {
  46. var diff = require('diff');
  47. var diffText = ''
  48. diff.diffLines(previousRevision.body, page.revision.body).forEach(function(line) {
  49. debug('diff line', line)
  50. var value = line.value.replace(/\r\n|\r/g, '\n');
  51. if (line.added) {
  52. diffText += `:pencil2: ...\n${line.value}`;
  53. } else if (line.removed) {
  54. // diffText += '-' + line.value.replace(/(.+)?\n/g, '- $1\n');
  55. // 1以下は無視
  56. if (line.count > 1) {
  57. diffText += `:wastebasket: ... ${line.count} lines\n`;
  58. }
  59. } else {
  60. //diffText += '...\n';
  61. }
  62. });
  63. debug('diff is', diffText)
  64. return diffText;
  65. };
  66. const prepareSlackMessage = function(page, user, channel, updateType, previousRevision) {
  67. var url = config.crowi['app:url'] || '';
  68. var body = page.revision.body;
  69. if (updateType == 'create') {
  70. body = prepareAttachmentTextForCreate(page, user);
  71. } else {
  72. body = prepareAttachmentTextForUpdate(page, user, previousRevision);
  73. }
  74. var attachment = {
  75. color: '#263a3c',
  76. author_name: '@' + user.username,
  77. author_link: url + '/user/' + user.username,
  78. author_icon: user.image,
  79. title: page.path,
  80. title_link: url + '/' + page._id,
  81. text: body,
  82. mrkdwn_in: ["text"],
  83. };
  84. if (user.image) {
  85. attachment.author_icon = user.image;
  86. }
  87. var message = {
  88. channel: '#' + channel,
  89. username: Config.appTitle(config),
  90. text: getSlackMessageText(page.path, user, updateType),
  91. attachments: [attachment],
  92. };
  93. return message;
  94. };
  95. const getSlackMessageText = function(path, user, updateType) {
  96. let text;
  97. const url = config.crowi['app:url'] || '';
  98. const pageUrl = `<${url}${path}|${path}>`;
  99. if (updateType == 'create') {
  100. text = `:white_check_mark: ${user.username} created a new page! ${pageUrl}`;
  101. } else {
  102. text = `:up: ${user.username} updated ${pageUrl}`;
  103. }
  104. return text;
  105. };
  106. // slack.post = function (channel, message, opts) {
  107. slack.post = (page, user, channel, updateType, previousRevision) => {
  108. const messageObj = prepareSlackMessage(page, user, channel, updateType, previousRevision);
  109. return new Promise((resolve, reject) => {
  110. // define callback function for Promise
  111. const callback = function(err, res) {
  112. if (err) {
  113. debug('Post error', err, res);
  114. debug('Sent data to slack is:', messageObj);
  115. return reject(err);
  116. }
  117. resolve(res);
  118. };
  119. // when incoming Webhooks is prioritized
  120. if (Config.isIncomingWebhookPrioritized(config)) {
  121. if (Config.hasSlackIwhUrl(config)) {
  122. debug(`posting message with IncomingWebhook`);
  123. postWithIwh(messageObj, callback);
  124. }
  125. else if (Config.hasSlackToken(config)) {
  126. debug(`posting message with Web API`);
  127. postWithWebApi(messageObj, callback);
  128. }
  129. }
  130. // else
  131. else {
  132. if (Config.hasSlackToken(config)) {
  133. debug(`posting message with Web API`);
  134. postWithWebApi(messageObj, callback);
  135. }
  136. else if (Config.hasSlackIwhUrl(config)) {
  137. debug(`posting message with IncomingWebhook`);
  138. postWithIwh(messageObj, callback);
  139. }
  140. }
  141. resolve();
  142. });
  143. };
  144. return slack;
  145. };