Przeglądaj źródła

Merge pull request #3943 from weseek/feat/growi-bot-reshape-slack-conversation-for-create-command

Feat/growi bot reshape slack conversation for create command
Haku Mizuki 4 lat temu
rodzic
commit
3ef8ab23d3

+ 1 - 0
packages/slack/src/index.ts

@@ -17,5 +17,6 @@ export * from './middlewares/verify-slack-request';
 export * from './utils/block-creater';
 export * from './utils/block-creater';
 export * from './utils/check-communicable';
 export * from './utils/check-communicable';
 export * from './utils/post-ephemeral-errors';
 export * from './utils/post-ephemeral-errors';
+export * from './utils/reshape-contents-body';
 export * from './utils/slash-command-parser';
 export * from './utils/slash-command-parser';
 export * from './utils/webclient-factory';
 export * from './utils/webclient-factory';

+ 93 - 0
packages/slack/src/utils/reshape-contents-body.ts

@@ -0,0 +1,93 @@
+/**
+ * RegExp for Slack message header
+ * @type {RegExp}
+ * @see https://regex101.com/r/wk24Z0/1
+ */
+const regexpMessageHeader = new RegExp(/.+\s\s[\d]{1,2}:[\d]{2}(\s[AP]{1}M)?$/);
+
+/**
+ * RegExp for Slack message Time with/without AM, PM
+ * @type {RegExp}
+ * @see https://regex101.com/r/Tz3ZPG/1
+ */
+const regexpTime = new RegExp(/\s\s[\d]{1,2}:[\d]{2}(\s[AP]{1}M)?$/);
+
+/**
+ * RegExp for Slack message Time without AM, PM
+ * @type {RegExp}
+ * @see https://regex101.com/r/e1Yi6t/1
+ */
+const regexpShortTime = new RegExp(/^[\d]{1,2}:[\d]{2}$/);
+
+/**
+ * RegExp for Slack message reaction
+ * @type {RegExp}
+ * @see https://regex101.com/r/LQX3s2/1
+ */
+const regexpReaction = new RegExp(/^:[+\w-]+:$/);
+
+// Remove everything before the first Header
+const devideLinesBeforeAfterFirstHeader = (lines: string[]) => {
+  let i = 0;
+  while (!regexpMessageHeader.test(lines[i]) && i <= lines.length) {
+    i++;
+  }
+  const linesBeforeFirstHeader = lines.slice(0, i);
+  const linesAfterFirstHeader = lines.slice(i);
+  return { linesBeforeFirstHeader, linesAfterFirstHeader };
+};
+
+// Reshape linesAfterFirstHeader
+export const reshapeContentsBody = (str: string): string => {
+  const splitted = str.split('\n');
+  const { linesBeforeFirstHeader, linesAfterFirstHeader } = devideLinesBeforeAfterFirstHeader(splitted);
+  if (linesAfterFirstHeader.length === 0) {
+    return linesBeforeFirstHeader.join('');
+  }
+
+  let didReactionRemoved = false;
+  const reshapedArray = linesAfterFirstHeader.map((line) => {
+    let copyline = line;
+    // Check 1: Did a reaction removed last time?
+    if (didReactionRemoved) {
+      // remove reaction count
+      copyline = '';
+      didReactionRemoved = false;
+    }
+    // Check 2: Is this line a header?
+    else if (regexpMessageHeader.test(copyline)) {
+      // extract time from line
+      const matched = copyline.match(regexpTime);
+      let time = '';
+      if (matched !== null && matched.length > 0) {
+        time = matched[0];
+      }
+      // </div><div class="slack-talk-bubble">##*username*  HH:mm AM
+      copyline = '</div>\n<div class="slack-talk-bubble">\n\n## **'.concat(copyline);
+      copyline = copyline.replace(regexpTime, '**'.concat(time));
+    }
+    // Check 3: Is this line a short time(HH:mm)?
+    else if (regexpShortTime.test(copyline)) {
+      // --HH:mm--
+      copyline = '--'.concat(copyline, '--');
+    }
+    // Check 4: Is this line a reaction?
+    else if (regexpReaction.test(copyline)) {
+      // remove reaction
+      copyline = '';
+      didReactionRemoved = true;
+    }
+    return copyline;
+  });
+  // remove all blanks
+  const blanksRemoved = reshapedArray.filter(line => line !== '');
+  // delete the first </div> and add </div> to the last row
+  blanksRemoved[0] = blanksRemoved[0].replace(/<\/div>/g, '');
+  blanksRemoved.push('</div>');
+  // Add 2 spaces and 1 enter to all lines
+  const completedArray = blanksRemoved.map(line => line.concat('  \n'));
+  // join all
+  const contentsBeforeFirstHeader = linesBeforeFirstHeader.join('');
+  const contentsAfterFirstHeader = completedArray.join('');
+  return contentsBeforeFirstHeader.concat(contentsAfterFirstHeader);
+};

+ 4 - 2
src/server/service/slackbot.js

@@ -1,8 +1,11 @@
+
 const logger = require('@alias/logger')('growi:service:SlackBotService');
 const logger = require('@alias/logger')('growi:service:SlackBotService');
 const mongoose = require('mongoose');
 const mongoose = require('mongoose');
 
 
 const PAGINGLIMIT = 10;
 const PAGINGLIMIT = 10;
 
 
+const { reshapeContentsBody } = require('@growi/slack');
+
 const S2sMessage = require('../models/vo/s2s-message');
 const S2sMessage = require('../models/vo/s2s-message');
 const S2sMessageHandlable = require('./s2s-messaging/handlable');
 const S2sMessageHandlable = require('./s2s-messaging/handlable');
 
 
@@ -304,8 +307,7 @@ class SlackBotService extends S2sMessageHandlable {
   async createPageInGrowi(client, payload) {
   async createPageInGrowi(client, payload) {
     const Page = this.crowi.model('Page');
     const Page = this.crowi.model('Page');
     const pathUtils = require('growi-commons').pathUtils;
     const pathUtils = require('growi-commons').pathUtils;
-
-    const contentsBody = payload.view.state.values.contents.contents_input.value;
+    const contentsBody = reshapeContentsBody(payload.view.state.values.contents.contents_input.value);
 
 
     try {
     try {
       let path = payload.view.state.values.path.path_input.value;
       let path = payload.view.state.values.path.path_input.value;