slack.js 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  1. import urljoin from 'url-join';
  2. import loggerFactory from '~/utils/logger';
  3. const logger = loggerFactory('growi:util:slack');
  4. /**
  5. * slack
  6. */
  7. /* eslint-disable no-use-before-define */
  8. const convertMarkdownToMarkdown = function(body, siteUrl) {
  9. return body
  10. .replace(/\n\*\s(.+)/g, '\n• $1')
  11. .replace(/#{1,}\s?(.+)/g, '\n*$1*')
  12. .replace(/(\[(.+)\]\((https?:\/\/.+)\))/g, '<$3|$2>')
  13. .replace(/(\[(.+)\]\((\/.+)\))/g, `<${siteUrl}$3|$2>`);
  14. };
  15. const prepareAttachmentTextForCreate = function(page, siteUrl) {
  16. let body = page.revision.body;
  17. if (body.length > 2000) {
  18. body = `${body.substr(0, 2000)}...`;
  19. }
  20. return convertMarkdownToMarkdown(body, siteUrl);
  21. };
  22. /**
  23. * Return diff with latest revisionBody
  24. * @param {IPageHasId} page
  25. * @param {string} siteUrl
  26. * @param {IRevisionHasId} previousRevision
  27. */
  28. const prepareAttachmentTextForUpdate = function(page, siteUrl, previousRevision) {
  29. if (previousRevision == null) {
  30. return;
  31. }
  32. const diff = require('diff');
  33. let diffText = '';
  34. diff.diffLines(previousRevision.body, page.revision.body).forEach((line) => {
  35. logger.debug('diff line', line);
  36. const value = line.value.replace(/\r\n|\r/g, '\n'); // eslint-disable-line no-unused-vars
  37. if (line.added) {
  38. diffText += `${line.value} ... :lower_left_fountain_pen:`;
  39. }
  40. else if (line.removed) {
  41. // diffText += '-' + line.value.replace(/(.+)?\n/g, '- $1\n');
  42. // 1以下は無視
  43. if (line.count > 1) {
  44. diffText += `:wastebasket: ... ${line.count} lines\n`;
  45. }
  46. }
  47. else {
  48. // diffText += '...\n';
  49. }
  50. });
  51. logger.debug('diff is', diffText);
  52. return diffText;
  53. };
  54. const prepareAttachmentTextForComment = function(comment) {
  55. let body = comment.comment;
  56. if (body.length > 2000) {
  57. body = `${body.substr(0, 2000)}...`;
  58. }
  59. if (comment.isMarkdown) {
  60. return convertMarkdownToMarkdown(body);
  61. }
  62. return body;
  63. };
  64. const generateSlackMessageTextForPage = function(path, pageId, user, siteUrl, updateType) {
  65. let text;
  66. const pageUrl = `<${urljoin(siteUrl, pageId)}|${path}>`;
  67. if (updateType === 'create') {
  68. text = `:rocket: ${user.username} created a new page! ${pageUrl}`;
  69. }
  70. else {
  71. text = `:heavy_check_mark: ${user.username} updated ${pageUrl}`;
  72. }
  73. return text;
  74. };
  75. export const prepareSlackMessageForPage = (page, user, appTitle, siteUrl, channel, updateType, previousRevision) => {
  76. let body = page.revision.body;
  77. if (updateType === 'create') {
  78. body = prepareAttachmentTextForCreate(page, siteUrl);
  79. }
  80. else {
  81. body = prepareAttachmentTextForUpdate(page, siteUrl, previousRevision);
  82. }
  83. const attachment = {
  84. color: '#263a3c',
  85. author_name: `@${user.username}`,
  86. author_link: urljoin(siteUrl, 'user', user.username),
  87. author_icon: user.image,
  88. title: page.path,
  89. title_link: urljoin(siteUrl, page.id),
  90. text: body,
  91. mrkdwn_in: ['text'],
  92. };
  93. if (user.image) {
  94. attachment.author_icon = user.image;
  95. }
  96. const message = {
  97. channel: (channel != null) ? `#${channel}` : undefined,
  98. username: appTitle,
  99. text: generateSlackMessageTextForPage(page.path, page.id, user, siteUrl, updateType),
  100. attachments: [attachment],
  101. };
  102. return message;
  103. };
  104. export const prepareSlackMessageForComment = (comment, user, appTitle, siteUrl, channel, path) => {
  105. const body = prepareAttachmentTextForComment(comment);
  106. const attachment = {
  107. color: '#263a3c',
  108. author_name: `@${user.username}`,
  109. author_link: urljoin(siteUrl, 'user', user.username),
  110. author_icon: user.image,
  111. text: body,
  112. mrkdwn_in: ['text'],
  113. };
  114. if (user.image) {
  115. attachment.author_icon = user.image;
  116. }
  117. const pageUrl = `<${urljoin(siteUrl, String(comment.page))}|${path}>`;
  118. const text = `:speech_balloon: ${user.username} commented on ${pageUrl}`;
  119. const message = {
  120. channel: (channel != null) ? `#${channel}` : undefined,
  121. username: appTitle,
  122. text,
  123. attachments: [attachment],
  124. };
  125. return message;
  126. };
  127. /**
  128. * For GlobalNotification
  129. *
  130. * @param {string} messageBody
  131. * @param {string} attachmentBody
  132. * @param {string} slackChannel
  133. */
  134. export const prepareSlackMessageForGlobalNotification = (messageBody, attachmentBody, appTitle, slackChannel) => {
  135. const attachment = {
  136. color: '#263a3c',
  137. text: attachmentBody,
  138. mrkdwn_in: ['text'],
  139. };
  140. const message = {
  141. channel: (slackChannel != null) ? `#${slackChannel}` : undefined,
  142. username: appTitle,
  143. text: messageBody,
  144. attachments: JSON.stringify([attachment]),
  145. };
  146. return message;
  147. };