hakumizuki 4 лет назад
Родитель
Сommit
f60f777bd4

+ 85 - 86
packages/slack/src/utils/block-kit-builder.ts

@@ -3,100 +3,99 @@ import {
   Button, Overflow, Datepicker, Select, RadioButtons, Checkboxes, Action, MultiSelect, PlainTextInput, Option,
 } from '@slack/types';
 
-export class BlockKitBuilder {
 
-  static divider(): DividerBlock {
-    return {
-      type: 'divider',
-    };
-  }
+export function divider(): DividerBlock {
+  return {
+    type: 'divider',
+  };
+}
 
-  static markdownSectionBlock(text: string): SectionBlock {
-    return {
-      type: 'section',
-      text: {
-        type: 'mrkdwn',
-        text,
-      },
-    };
-  }
+export function markdownSectionBlock(text: string): SectionBlock {
+  return {
+    type: 'section',
+    text: {
+      type: 'mrkdwn',
+      text,
+    },
+  };
+}
 
-  static inputSectionBlock(blockId: string, labelText: string, actionId: string, isMultiline: boolean, placeholder: string): InputBlock {
-    return {
-      type: 'input',
-      block_id: blockId,
-      label: {
+export function inputSectionBlock(blockId: string, labelText: string, actionId: string, isMultiline: boolean, placeholder: string): InputBlock {
+  return {
+    type: 'input',
+    block_id: blockId,
+    label: {
+      type: 'plain_text',
+      text: labelText,
+    },
+    element: {
+      type: 'plain_text_input',
+      action_id: actionId,
+      multiline: isMultiline,
+      placeholder: {
         type: 'plain_text',
-        text: labelText,
+        text: placeholder,
       },
-      element: {
-        type: 'plain_text_input',
-        action_id: actionId,
-        multiline: isMultiline,
-        placeholder: {
-          type: 'plain_text',
-          text: placeholder,
-        },
-      },
-    };
-  }
-
-  static actionsBlock(...elements: (Button | Overflow | Datepicker | Select | RadioButtons | Checkboxes | Action)[]): ActionsBlock {
-    return {
-      type: 'actions',
-      elements: [
-        ...elements,
-      ],
-    };
-  }
+    },
+  };
+}
 
-  static inputBlock(element: Select | MultiSelect | Datepicker | PlainTextInput | RadioButtons | Checkboxes, blockId: string, labelText: string): InputBlock {
-    return {
-      type: 'input',
-      block_id: blockId,
-      element,
-      label: {
-        type: 'plain_text',
-        text: labelText,
-      },
-    };
-  }
+export function actionsBlock(...elements: (Button | Overflow | Datepicker | Select | RadioButtons | Checkboxes | Action)[]): ActionsBlock {
+  return {
+    type: 'actions',
+    elements: [
+      ...elements,
+    ],
+  };
+}
 
-  /**
-   * Button element
-   * https://api.slack.com/reference/block-kit/block-elements#button
-   */
-  static buttonElement(text: string, actionId: string, style?: string): Button {
-    const button: Button = {
-      type: 'button',
-      text: {
-        type: 'plain_text',
-        text,
-      },
-      action_id: actionId,
-    };
-    if (style === 'primary' || style === 'danger') {
-      button.style = style;
-    }
-    return button;
-  }
+export function inputBlock(
+    element: Select | MultiSelect | Datepicker | PlainTextInput | RadioButtons | Checkboxes, blockId: string, labelText: string,
+): InputBlock {
+  return {
+    type: 'input',
+    block_id: blockId,
+    element,
+    label: {
+      type: 'plain_text',
+      text: labelText,
+    },
+  };
+}
 
-  /**
-   * Option object
-   * https://api.slack.com/reference/block-kit/composition-objects#option
-   */
-  static checkboxesElementOption(text: string, description: string, value: string): Option {
-    return {
-      text: {
-        type: 'mrkdwn',
-        text,
-      },
-      description: {
-        type: 'plain_text',
-        text: description,
-      },
-      value,
-    };
+/**
+ * Button element
+ * https://api.slack.com/reference/block-kit/block-elements#button
+ */
+export function buttonElement(text: string, actionId: string, style?: string): Button {
+  const button: Button = {
+    type: 'button',
+    text: {
+      type: 'plain_text',
+      text,
+    },
+    action_id: actionId,
+  };
+  if (style === 'primary' || style === 'danger') {
+    button.style = style;
   }
+  return button;
+}
 
+/**
+ * Option object
+ * https://api.slack.com/reference/block-kit/composition-objects#option
+ */
+export function checkboxesElementOption(text: string, description: string, value: string): Option {
+  return {
+    text: {
+      type: 'mrkdwn',
+      text,
+    },
+    description: {
+      type: 'plain_text',
+      text: description,
+    },
+    value,
+  };
 }

+ 3 - 3
packages/slack/src/utils/post-ephemeral-errors.ts

@@ -1,6 +1,6 @@
 import { WebAPICallResult } from '@slack/web-api';
 
-import { BlockKitBuilder as B } from './block-kit-builder';
+import { markdownSectionBlock } from './block-kit-builder';
 import { generateWebClient } from './webclient-factory';
 
 export const postEphemeralErrors = async(
@@ -19,7 +19,7 @@ export const postEphemeralErrors = async(
       channel: channelId,
       user: userId,
       blocks: [
-        B.markdownSectionBlock('*Error occured:*'),
+        markdownSectionBlock('*Error occured:*'),
         ...rejectedResults.map((rejectedResult) => {
           const reason = rejectedResult.reason.toString();
           const resData = rejectedResult.reason.response?.data;
@@ -30,7 +30,7 @@ export const postEphemeralErrors = async(
             errorMessage += `\n  Cause: ${resDataMessage}`;
           }
 
-          return B.markdownSectionBlock(errorMessage);
+          return markdownSectionBlock(errorMessage);
         }),
       ],
     });

+ 5 - 5
packages/slackbot-proxy/src/controllers/slack.ts

@@ -7,7 +7,7 @@ import axios from 'axios';
 import { WebAPICallResult } from '@slack/web-api';
 
 import {
-  BlockKitBuilder as B, GrowiCommand, parseSlashCommand, postEphemeralErrors, verifySlackRequest,
+  markdownSectionBlock, GrowiCommand, parseSlashCommand, postEphemeralErrors, verifySlackRequest,
 } from '@growi/slack';
 
 import { Relation } from '~/entities/relation';
@@ -139,8 +139,8 @@ export class SlackCtrl {
     if (relations.length === 0) {
       return res.json({
         blocks: [
-          B.markdownSectionBlock('*No relation found.*'),
-          B.markdownSectionBlock('Run `/growi register` first.'),
+          markdownSectionBlock('*No relation found.*'),
+          markdownSectionBlock('Run `/growi register` first.'),
         ],
       });
     }
@@ -149,8 +149,8 @@ export class SlackCtrl {
     if (growiCommand.growiCommandType === 'status') {
       return res.json({
         blocks: [
-          B.markdownSectionBlock('*Found Relations to GROWI.*'),
-          ...relations.map(relation => B.markdownSectionBlock(`GROWI url: ${relation.growiUri}`)),
+          markdownSectionBlock('*Found Relations to GROWI.*'),
+          ...relations.map(relation => markdownSectionBlock(`GROWI url: ${relation.growiUri}`)),
         ],
       });
     }

+ 8 - 8
packages/slackbot-proxy/src/services/RegisterService.ts

@@ -1,6 +1,6 @@
 import { Inject, Service } from '@tsed/di';
 import { WebClient, LogLevel, Block } from '@slack/web-api';
-import { BlockKitBuilder as B, GrowiCommand } from '@growi/slack';
+import { markdownSectionBlock, inputSectionBlock, GrowiCommand } from '@growi/slack';
 import { AuthorizeResult } from '@slack/oauth';
 import { GrowiCommandProcessor } from '~/interfaces/slack-to-growi/growi-command-processor';
 import { OrderRepository } from '~/repositories/order';
@@ -40,9 +40,9 @@ export class RegisterService implements GrowiCommandProcessor {
         private_metadata: JSON.stringify({ channel: body.channel_name }),
 
         blocks: [
-          B.inputSectionBlock('growiUrl', 'GROWI domain', 'contents_input', false, 'https://example.com'),
-          B.inputSectionBlock('tokenPtoG', 'Access Token Proxy to GROWI', 'contents_input', false, 'jBMZvpk.....'),
-          B.inputSectionBlock('tokenGtoP', 'Access Token GROWI to Proxy', 'contents_input', false, 'sdg15av.....'),
+          inputSectionBlock('growiUrl', 'GROWI domain', 'contents_input', false, 'https://example.com'),
+          inputSectionBlock('tokenPtoG', 'Access Token Proxy to GROWI', 'contents_input', false, 'jBMZvpk.....'),
+          inputSectionBlock('tokenGtoP', 'Access Token GROWI to Proxy', 'contents_input', false, 'sdg15av.....'),
         ],
       },
     });
@@ -81,7 +81,7 @@ export class RegisterService implements GrowiCommandProcessor {
     catch (error) {
       const invalidErrorMsg = 'Please enter a valid URL';
       const blocks = [
-        B.markdownSectionBlock(invalidErrorMsg),
+        markdownSectionBlock(invalidErrorMsg),
       ];
       await this.replyToSlack(client, channel, payload.user.id, 'Invalid URL', blocks);
       throw new InvalidUrlError(growiUrl);
@@ -105,7 +105,7 @@ export class RegisterService implements GrowiCommandProcessor {
 
     if (isOfficialMode) {
       const blocks = [
-        B.markdownSectionBlock('Successfully registered with the proxy! Please check test connection in your GROWI'),
+        markdownSectionBlock('Successfully registered with the proxy! Please check test connection in your GROWI'),
       ];
       await this.replyToSlack(client, channel, payload.user.id, 'Proxy URL', blocks);
       return;
@@ -113,8 +113,8 @@ export class RegisterService implements GrowiCommandProcessor {
     }
 
     const blocks = [
-      B.markdownSectionBlock('Please enter and update the following Proxy URL to slack bot setting form in your GROWI'),
-      B.markdownSectionBlock(`Proxy URL: ${serverUri}`),
+      markdownSectionBlock('Please enter and update the following Proxy URL to slack bot setting form in your GROWI'),
+      markdownSectionBlock(`Proxy URL: ${serverUri}`),
     ];
     await this.replyToSlack(client, channel, payload.user.id, 'Proxy URL', blocks);
     return;

+ 3 - 3
packages/slackbot-proxy/src/services/UnregisterService.ts

@@ -1,6 +1,6 @@
 import { Inject, Service } from '@tsed/di';
 import { WebClient, LogLevel } from '@slack/web-api';
-import { GrowiCommand, BlockKitBuilder as B } from '@growi/slack';
+import { GrowiCommand, markdownSectionBlock } from '@growi/slack';
 import { AuthorizeResult } from '@slack/oauth';
 import { GrowiCommandProcessor } from '~/interfaces/slack-to-growi/growi-command-processor';
 import { RelationRepository } from '~/repositories/relation';
@@ -38,7 +38,7 @@ export class UnregisterService implements GrowiCommandProcessor {
         private_metadata: JSON.stringify({ channel: body.channel_name, growiUrls }),
 
         blocks: [
-          ...growiUrls.map(growiCommandArg => B.markdownSectionBlock(`GROWI url: ${growiCommandArg}.`)),
+          ...growiUrls.map(growiCommandArg => markdownSectionBlock(`GROWI url: ${growiCommandArg}.`)),
         ],
       },
     });
@@ -63,7 +63,7 @@ export class UnregisterService implements GrowiCommandProcessor {
       // refer to https://api.slack.com/methods/chat.postEphemeral#text_usage
       text: 'Delete Relations',
       blocks: [
-        B.markdownSectionBlock(`Deleted ${deleteResult.affected} Relations.`),
+        markdownSectionBlock(`Deleted ${deleteResult.affected} Relations.`),
       ],
     });
 

+ 5 - 5
src/server/service/slack-command-handler/create.js

@@ -1,4 +1,4 @@
-const { BlockKitBuilder: B } = require('@growi/slack');
+const { markdownSectionBlock, inputSectionBlock } = require('@growi/slack');
 const logger = require('@alias/logger')('growi:service:SlackCommandHandler:create');
 
 module.exports = () => {
@@ -26,9 +26,9 @@ module.exports = () => {
             text: 'Cancel',
           },
           blocks: [
-            B.markdownSectionBlock('Create new page.'),
-            B.inputSectionBlock('path', 'Path', 'path_input', false, '/path'),
-            B.inputSectionBlock('contents', 'Contents', 'contents_input', true, 'Input with Markdown...'),
+            markdownSectionBlock('Create new page.'),
+            inputSectionBlock('path', 'Path', 'path_input', false, '/path'),
+            inputSectionBlock('contents', 'Contents', 'contents_input', true, 'Input with Markdown...'),
           ],
           private_metadata: JSON.stringify({ channelId: body.channel_id }),
         },
@@ -41,7 +41,7 @@ module.exports = () => {
         user: body.user_id,
         text: 'Failed To Create',
         blocks: [
-          B.markdownSectionBlock(`*Failed to create new page.*\n ${err}`),
+          markdownSectionBlock(`*Failed to create new page.*\n ${err}`),
         ],
       });
       throw err;

+ 2 - 2
src/server/service/slack-command-handler/help.js

@@ -1,4 +1,4 @@
-const { BlockKitBuilder: B } = require('@growi/slack');
+const { markdownSectionBlock } = require('@growi/slack');
 
 module.exports = () => {
   const BaseSlackCommandHandler = require('./slack-command-handler');
@@ -11,7 +11,7 @@ module.exports = () => {
       user: body.user_id,
       text: 'Help',
       blocks: [
-        B.markdownSectionBlock(message),
+        markdownSectionBlock(message),
       ],
     });
   };

+ 21 - 21
src/server/service/slack-command-handler/search.js

@@ -1,6 +1,6 @@
 const logger = require('@alias/logger')('growi:service:SlackCommandHandler:search');
 
-const { BlockKitBuilder: B } = require('@growi/slack');
+const { markdownSectionBlock, divider } = require('@growi/slack');
 const { formatDistanceStrict } = require('date-fns');
 
 const PAGINGLIMIT = 10;
@@ -21,7 +21,7 @@ module.exports = (crowi) => {
         user: body.user_id,
         text: 'Failed To Search',
         blocks: [
-          B.markdownSectionBlock('*Failed to search.*\n Hint\n `/growi search [keyword]`'),
+          markdownSectionBlock('*Failed to search.*\n Hint\n `/growi search [keyword]`'),
         ],
       });
       throw new Error('/growi command:search: Failed to search');
@@ -62,7 +62,7 @@ module.exports = (crowi) => {
 
     const now = new Date();
     const blocks = [
-      B.markdownSectionBlock(`:mag: <${decodeURI(appUrl)}|*${appTitle}*>\n${searchResultsDesc}`),
+      markdownSectionBlock(`:mag: <${decodeURI(appUrl)}|*${appTitle}*>\n${searchResultsDesc}`),
       contextBlock,
       { type: 'divider' },
       // create an array by map and extract
@@ -154,7 +154,7 @@ module.exports = (crowi) => {
         user: body.user_id,
         text: 'Failed to post ephemeral message.',
         blocks: [
-          B.markdownSectionBlock(err.toString()),
+          markdownSectionBlock(err.toString()),
         ],
       });
       throw new Error(err);
@@ -169,7 +169,7 @@ module.exports = (crowi) => {
         user: body.user_id,
         text: 'Input keywords',
         blocks: [
-          B.markdownSectionBlock('*Input keywords.*\n Hint\n `/growi search [keyword]`'),
+          markdownSectionBlock('*Input keywords.*\n Hint\n `/growi search [keyword]`'),
         ],
       });
       return;
@@ -190,22 +190,22 @@ module.exports = (crowi) => {
         user: body.user_id,
         text: `No page found with "${keywords}"`,
         blocks: [
-          B.markdownSectionBlock(`*No page that matches your keyword(s) "${keywords}".*`),
-          B.markdownSectionBlock(':mag: *Help: Searching*'),
-          B.divider(),
-          B.markdownSectionBlock('`word1` `word2` (divide with space) \n Search pages that include both word1, word2 in the title or body'),
-          B.divider(),
-          B.markdownSectionBlock('`"This is GROWI"` (surround with double quotes) \n Search pages that include the phrase "This is GROWI"'),
-          B.divider(),
-          B.markdownSectionBlock('`-keyword` \n Exclude pages that include keyword in the title or body'),
-          B.divider(),
-          B.markdownSectionBlock('`prefix:/user/` \n Search only the pages that the title start with /user/'),
-          B.divider(),
-          B.markdownSectionBlock('`-prefix:/user/` \n Exclude the pages that the title start with /user/'),
-          B.divider(),
-          B.markdownSectionBlock('`tag:wiki` \n Search for pages with wiki tag'),
-          B.divider(),
-          B.markdownSectionBlock('`-tag:wiki` \n Exclude pages with wiki tag'),
+          markdownSectionBlock(`*No page that matches your keyword(s) "${keywords}".*`),
+          markdownSectionBlock(':mag: *Help: Searching*'),
+          divider(),
+          markdownSectionBlock('`word1` `word2` (divide with space) \n Search pages that include both word1, word2 in the title or body'),
+          divider(),
+          markdownSectionBlock('`"This is GROWI"` (surround with double quotes) \n Search pages that include the phrase "This is GROWI"'),
+          divider(),
+          markdownSectionBlock('`-keyword` \n Exclude pages that include keyword in the title or body'),
+          divider(),
+          markdownSectionBlock('`prefix:/user/` \n Search only the pages that the title start with /user/'),
+          divider(),
+          markdownSectionBlock('`-prefix:/user/` \n Exclude the pages that the title start with /user/'),
+          divider(),
+          markdownSectionBlock('`tag:wiki` \n Search for pages with wiki tag'),
+          divider(),
+          markdownSectionBlock('`-tag:wiki` \n Exclude pages with wiki tag'),
         ],
       });
       return { pages: [] };

+ 11 - 9
src/server/service/slack-command-handler/togetter.js

@@ -1,4 +1,6 @@
-const { BlockKitBuilder: B } = require('@growi/slack');
+const {
+  inputBlock, actionsBlock, buttonElement, checkboxesElementOption,
+} = require('@growi/slack');
 
 module.exports = () => {
   const BaseSlackCommandHandler = require('./slack-command-handler');
@@ -11,7 +13,7 @@ module.exports = () => {
       limit,
     });
     console.log(reusult);
-    // Checkbox Message を返す
+    // Return Checkbox Message
     client.chat.postEphemeral({
       channel: body.channel_id,
       user: body.user_id,
@@ -23,10 +25,10 @@ module.exports = () => {
 
   handler.togetterMessageBlocks = function() {
     return [
-      B.inputBlock(this.togetterCheckboxesElement(), 'selected_messages', 'Select massages to use.'),
-      B.actionsBlock(B.buttonElement('Show more', 'togetterShowMore')),
-      B.inputBlock(this.togetterInputBlockElement('page_path', '/'), 'page_path', 'Page path'),
-      B.actionsBlock(B.buttonElement('Cancel', 'togetterCancelPageCreation'), B.buttonElement('Create page', 'togetterCreatePage', 'primary')),
+      inputBlock(this.togetterCheckboxesElement(), 'selected_messages', 'Select massages to use.'),
+      actionsBlock(buttonElement('Show more', 'togetterShowMore')),
+      inputBlock(this.togetterInputBlockElement('page_path', '/'), 'page_path', 'Page path'),
+      actionsBlock(buttonElement('Cancel', 'togetterCancelPageCreation'), buttonElement('Create page', 'togetterCreatePage', 'primary')),
     ];
   };
 
@@ -39,11 +41,11 @@ module.exports = () => {
   };
 
   handler.togetterCheckboxesElementOptions = function() {
-    // options を conversations.history の結果でインクリメント
+    // increment options with results from conversations.history
     const options = [];
-    // 仮置き
+    // temporary code
     for (let i = 0; i < 10; i++) {
-      const option = B.checkboxesElementOption('*username*  12:00PM', 'sample slack messages ... :star:', `selected-${i}`);
+      const option = checkboxesElementOption('*username*  12:00PM', 'sample slack messages ... :star:', `selected-${i}`);
       options.push(option);
     }
     return options;

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

@@ -3,7 +3,7 @@ const logger = require('@alias/logger')('growi:service:SlackBotService');
 const mongoose = require('mongoose');
 const axios = require('axios');
 
-const { BlockKitBuilder: B } = require('@growi/slack');
+const { markdownSectionBlock } = require('@growi/slack');
 const { reshapeContentsBody } = require('@growi/slack');
 const { formatDistanceStrict } = require('date-fns');
 
@@ -87,7 +87,7 @@ class SlackBotService extends S2sMessageHandlable {
       user: body.user_id,
       text: 'No command',
       blocks: [
-        B.markdownSectionBlock('*No command.*\n Hint\n `/growi [command] [keyword]`'),
+        markdownSectionBlock('*No command.*\n Hint\n `/growi [command] [keyword]`'),
       ],
     });
     return;
@@ -132,7 +132,7 @@ class SlackBotService extends S2sMessageHandlable {
       channel: channelId,
       blocks: [
         { type: 'divider' },
-        B.markdownSectionBlock(`${this.appendSpeechBaloon(`*${this.generatePageLinkMrkdwn(pathname, href)}*`, commentCount)}`),
+        markdownSectionBlock(`${this.appendSpeechBaloon(`*${this.generatePageLinkMrkdwn(pathname, href)}*`, commentCount)}`),
         {
           type: 'context',
           elements: [
@@ -183,7 +183,7 @@ class SlackBotService extends S2sMessageHandlable {
       client.chat.postMessage({
         channel: payload.user.id,
         blocks: [
-          B.markdownSectionBlock(`Cannot create new page to existed path\n *Contents* :memo:\n ${contentsBody}`)],
+          markdownSectionBlock(`Cannot create new page to existed path\n *Contents* :memo:\n ${contentsBody}`)],
       });
       logger.error('Failed to create page in GROWI.');
       throw err;