Yuki Takei 4 лет назад
Родитель
Сommit
5df8c03ef2

+ 18 - 45
packages/slackbot-proxy/src/controllers/growi-to-slack.ts

@@ -19,7 +19,7 @@ import { OrderRepository } from '~/repositories/order';
 import { InstallerService } from '~/services/InstallerService';
 import loggerFactory from '~/utils/logger';
 import { ViewInteractionPayloadDelegator } from '~/services/growi-uri-injector/ViewInteractionPayloadDelegator';
-import { BlockActionsPayloadDelegator } from '~/services/growi-uri-injector/BlockActionsPayloadDelegator';
+import { ActionsBlockPayloadDelegator } from '~/services/growi-uri-injector/ActionsBlockPayloadDelegator';
 import { BlockElement, ViewElement } from '~/interfaces/growi-uri-injector';
 
 
@@ -43,6 +43,12 @@ export class GrowiToSlackCtrl {
   @Inject()
   orderRepository: OrderRepository;
 
+  @Inject()
+  viewInteractionPayloadDelegator: ViewInteractionPayloadDelegator;
+
+  @Inject()
+  actionsBlockPayloadDelegator: ActionsBlockPayloadDelegator;
+
   async requestToGrowi(growiUrl:string, tokenPtoG:string):Promise<void> {
     const url = new URL('/_api/v3/slack-integration/proxied/commands', growiUrl);
     await axios.post(url.toString(), {
@@ -174,53 +180,20 @@ export class GrowiToSlackCtrl {
 
   injectGrowiUri(req: GrowiReq, growiUri: string):WebAPICallOptions {
 
-    // TODO: get list from decorator
-    const vipDelegators: ViewInteractionPayloadDelegator[] = [new ViewInteractionPayloadDelegator()];
-    const bapDelegators: BlockActionsPayloadDelegator[] = [];
-
     const parsedView = JSON.parse(req.body.view) as ViewElement;
     const parsedBlocks = JSON.parse(req.body.blocks) as BlockElement[];
 
-    vipDelegators.forEach((delegator) => {
-      if (delegator.shouldHandleToInject(parsedView)) {
-        delegator.inject(parsedView, growiUri);
-      }
-    });
-    req.body.view = JSON.stringify(parsedView);
-
-    // bapDelegators.forEach((delegator) => {
-    //   if (delegator.shouldHandleToInject(parsedBlocks)) {
-    //     delegator.inject(parsedBlocks, growiUri);
-    //   }
-    // });
-    // req.body.blocks = JSON.stringify(parsedBlocks);
-
-    // const vipd = new ViewInteractionPayloadDelegator();
-    // if (vipd.shouldHandleToInject(req)) {
-    //   vipd.inject(req.body, growiUri);
-    // }
-    // else if (req.body.blocks != null) {
-    //   const parsedBlocks = JSON.parse(req.body.blocks) as any[];
-    //   req.parsedBlocks = parsedBlocks;
-
-    //   // TODO: iterate with decorator
-
-    //   parsedBlocks.forEach((parsedBlock) => {
-    //     if (parsedBlock.type !== 'actions') {
-    //       return;
-    //     }
-    //     parsedBlock.elements.forEach((element) => {
-    //       const growiUriInjector = findInjectorByType(element.type);
-    //       if (growiUriInjector != null) {
-    //         growiUriInjector.inject(element, growiUri);
-    //       }
-    //     });
-
-    //     return;
-    //   });
-
-    //   req.body.blocks = JSON.stringify(parsedBlocks);
-    // }
+    // delegate to ViewInteractionPayloadDelegator
+    if (this.viewInteractionPayloadDelegator.shouldHandleToInject(parsedView)) {
+      this.viewInteractionPayloadDelegator.inject(parsedView, growiUri);
+      req.body.view = JSON.stringify(parsedView);
+    }
+
+    // delegate to ActionsBlockPayloadDelegator
+    if (this.actionsBlockPayloadDelegator.shouldHandleToInject(parsedBlocks)) {
+      this.actionsBlockPayloadDelegator.inject(parsedBlocks, growiUri);
+      req.body.blocks = JSON.stringify(parsedBlocks);
+    }
 
     const opt = req.body;
     opt.headers = req.headers;

+ 2 - 2
packages/slackbot-proxy/src/interfaces/growi-uri-injector.ts

@@ -15,13 +15,13 @@ export type ViewInteractionPayload = {
 // see: https://api.slack.com/reference/block-kit/blocks
 export type BlockElement = {
   type: string,
-  elements: { type: string }[],
+  element?: { type: string } & any,
+  elements?: ({ type: string } & any)[],
 }
 
 // see: https://api.slack.com/reference/interaction-payloads/block-actions
 export type BlockActionsPayload = {
   type: string,
-  actions: { type: string }[],
 }
 
 export type GrowiUriWithOriginalData = {

+ 14 - 33
packages/slackbot-proxy/src/middlewares/slack-to-growi/extract-growi-uri-from-req.ts

@@ -1,13 +1,21 @@
 import {
-  IMiddleware, Middleware, Next, Req, Res,
+  IMiddleware, Inject, Middleware, Next, Req, Res,
 } from '@tsed/common';
+
 import { SlackOauthReq } from '~/interfaces/slack-to-growi/slack-oauth-req';
-import { BlockActionsPayloadDelegator } from '~/services/growi-uri-injector/BlockActionsPayloadDelegator';
 import { ViewInteractionPayloadDelegator } from '~/services/growi-uri-injector/ViewInteractionPayloadDelegator';
+import { ActionsBlockPayloadDelegator } from '~/services/growi-uri-injector/ActionsBlockPayloadDelegator';
+
 
 @Middleware()
 export class ExtractGrowiUriFromReq implements IMiddleware {
 
+  @Inject()
+  viewInteractionPayloadDelegator: ViewInteractionPayloadDelegator;
+
+  @Inject()
+  actionsBlockPayloadDelegator: ActionsBlockPayloadDelegator;
+
   use(@Req() req: SlackOauthReq, @Res() res: Res, @Next() next: Next): void {
 
     // There is no payload in the request from slack
@@ -15,14 +23,10 @@ export class ExtractGrowiUriFromReq implements IMiddleware {
       return next();
     }
 
-    // TODO: get list from decorator
-    const vipDelegators: ViewInteractionPayloadDelegator[] = [new ViewInteractionPayloadDelegator()];
-    const bapDelegators: BlockActionsPayloadDelegator[] = [];
-
     const parsedPayload = JSON.parse(req.body.payload);
 
-    // iterate combined delegators
-    for (const delegator of [...vipDelegators, ...bapDelegators]) {
+    // iterate
+    for (const delegator of [this.viewInteractionPayloadDelegator, this.actionsBlockPayloadDelegator]) {
       if (delegator.shouldHandleToExtract(parsedPayload)) {
         const data = delegator.extract(parsedPayload);
         req.growiUri = data.growiUri;
@@ -31,31 +35,8 @@ export class ExtractGrowiUriFromReq implements IMiddleware {
         break;
       }
     }
-    req.body.blocks = JSON.stringify(parsedPayload);
-
-    // req.parsedPayload = parsedPayload;
-
-    // // TODO: iterate with decorator
-    // const vipd = new ViewInteractionPayloadDelegator();
-    // if (vipd.shouldHandleToExtract(req)) {
-    //   const data = vipd.extract(req.parsedPayload);
-    //   req.growiUri = data.growiUri;
-    // }
-    // else {
-    //   // break when uri is found
-    //   for (const type of Object.keys(growiUriInjectorFactory)) {
-    //     const growiUriInjector = growiUriInjectorFactory[type]();
-    //     const extractedValues = growiUriInjector.extract(parsedPayload.actions[0]);
-
-    //     if (extractedValues.growiUri != null) {
-    //       req.growiUri = extractedValues.growiUri;
-    //       parsedPayload.actions[0].value = JSON.stringify(extractedValues.originalData);
-    //       break;
-    //     }
-    //   }
-    // }
-
-    // req.body.payload = JSON.stringify(parsedPayload);
+
+    req.body.payload = JSON.stringify(parsedPayload);
 
     return next();
   }

+ 74 - 0
packages/slackbot-proxy/src/services/growi-uri-injector/ActionsBlockPayloadDelegator.ts

@@ -0,0 +1,74 @@
+import { Inject, Service } from '@tsed/di';
+import {
+  BlockActionsPayload, BlockElement, GrowiUriInjector, GrowiUriWithOriginalData,
+} from '~/interfaces/growi-uri-injector';
+import { ButtonActionPayloadDelegator } from './block-elements/ButtonActionPayloadDelegator';
+
+
+@Service()
+export class ActionsBlockPayloadDelegator implements GrowiUriInjector<BlockElement[], BlockActionsPayload & {actions: any}> {
+
+  @Inject()
+  buttonActionPayloadDelegator: ButtonActionPayloadDelegator;
+
+  private childDelegators: GrowiUriInjector<any, any>[] = [];
+
+  constructor() {
+    this.childDelegators.push(this.buttonActionPayloadDelegator);
+  }
+
+  shouldHandleToInject(data: BlockElement[]): boolean {
+    const actionsBlocks = data.filter(blockElement => blockElement.type === 'actions');
+    if (actionsBlocks.length === 0) {
+      return false;
+    }
+
+    // collect elements
+    // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+    const elements = actionsBlocks.flatMap(actionBlock => actionBlock.elements!);
+
+    return this.childDelegators
+      .map(delegator => delegator.shouldHandleToInject(elements))
+      .includes(true);
+  }
+
+  inject(data: BlockElement[], growiUri: string): void {
+    const actionsBlocks = data.filter(blockElement => blockElement.type === 'actions');
+
+    // collect elements
+    // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+    const elements = actionsBlocks.flatMap(actionBlock => actionBlock.elements!);
+
+    this.childDelegators.forEach((delegator) => {
+      if (delegator.shouldHandleToInject(elements)) {
+        delegator.inject(elements, growiUri);
+      }
+    });
+  }
+
+  // eslint-disable-next-line @typescript-eslint/no-unused-vars
+  shouldHandleToExtract(data: BlockActionsPayload & {actions?: any}): boolean {
+    if (data.actions == null || data.actions.length === 0) {
+      return false;
+    }
+
+    return this.childDelegators
+      .map(delegator => delegator.shouldHandleToExtract(data.actions))
+      .includes(true);
+  }
+
+  extract(data: BlockActionsPayload & {actions: any}): GrowiUriWithOriginalData {
+    let growiUriWithOriginalData: GrowiUriWithOriginalData;
+
+    for (const delegator of this.childDelegators) {
+      if (delegator.shouldHandleToExtract(data.actions)) {
+        growiUriWithOriginalData = delegator.extract(data.actions);
+        break;
+      }
+    }
+
+    // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+    return growiUriWithOriginalData!;
+  }
+
+}

+ 0 - 21
packages/slackbot-proxy/src/services/growi-uri-injector/BlockActionsPayloadDelegator.ts

@@ -1,21 +0,0 @@
-import {
-  BlockActionsPayload, BlockElement, GrowiUriInjector, GrowiUriWithOriginalData,
-} from '~/interfaces/growi-uri-injector';
-
-export abstract class BlockActionsPayloadDelegator implements GrowiUriInjector<BlockElement[], BlockActionsPayload> {
-
-  correctBlockElementTypes(data: BlockElement[]): string[] {
-    return data.flatMap((blockElement) => {
-      return blockElement.elements.map(element => element.type);
-    });
-  }
-
-  abstract shouldHandleToInject(data: BlockElement[]): boolean;
-
-  abstract inject(data: BlockElement[], growiUri: string): void;
-
-  abstract shouldHandleToExtract(data: BlockActionsPayload): boolean;
-
-  abstract extract(data: BlockActionsPayload): GrowiUriWithOriginalData;
-
-}

+ 2 - 0
packages/slackbot-proxy/src/services/growi-uri-injector/ViewInteractionPayloadDelegator.ts

@@ -1,7 +1,9 @@
+import { Service } from '@tsed/di';
 import {
   GrowiUriInjector, GrowiUriWithOriginalData, isGrowiUriWithOriginalData, ViewElement, ViewInteractionPayload,
 } from '~/interfaces/growi-uri-injector';
 
+@Service()
 export class ViewInteractionPayloadDelegator implements GrowiUriInjector<ViewElement, ViewInteractionPayload> {
 
   shouldHandleToInject(data: ViewElement): boolean {

+ 33 - 0
packages/slackbot-proxy/src/services/growi-uri-injector/block-elements/ButtonActionPayloadDelegator.ts

@@ -0,0 +1,33 @@
+import { GrowiUriWithOriginalData, GrowiUriInjector } from '~/interfaces/growi-uri-injector';
+
+export class ButtonActionPayloadDelegator implements GrowiUriInjector<{type: string, value: string}[], {type: string, value: string}> {
+
+  shouldHandleToInject(elements: {type: string}[]): boolean {
+    const buttonElements = elements.filter(element => element.type === 'button');
+    return buttonElements.length > 0;
+  }
+
+  inject(elements: {type: string, value: string}[], growiUri: string): void {
+    const buttonElements = elements.filter(blockElement => blockElement.type === 'button');
+
+    buttonElements
+      .forEach((element) => {
+        const urlWithOrgData: GrowiUriWithOriginalData = { growiUri, originalData: element.value };
+        element.value = JSON.stringify(urlWithOrgData);
+      });
+  }
+
+  shouldHandleToExtract(action: {type: string, value: string}): boolean {
+    return action.type === 'button';
+  }
+
+  extract(action: {type: string, value: string}): GrowiUriWithOriginalData {
+    // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+    const restoredData: GrowiUriWithOriginalData = JSON.parse(action.value);
+    action.value = JSON.parse(restoredData.originalData);
+
+    return restoredData;
+  }
+
+
+}