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

+ 0 - 2
packages/slack/src/interfaces/request-between-growi-and-proxy.ts

@@ -12,8 +12,6 @@ export type RequestFromGrowi = Request & {
     view?: string,
     view?: string,
     blocks?: string
     blocks?: string
   },
   },
-  // for storing parsed blocks object
-  parsedBlocks?: any[],
 };
 };
 
 
 export type RequestFromProxy = Request & {
 export type RequestFromProxy = Request & {

+ 48 - 26
packages/slackbot-proxy/src/controllers/growi-to-slack.ts

@@ -18,8 +18,8 @@ import { OrderRepository } from '~/repositories/order';
 
 
 import { InstallerService } from '~/services/InstallerService';
 import { InstallerService } from '~/services/InstallerService';
 import loggerFactory from '~/utils/logger';
 import loggerFactory from '~/utils/logger';
-import { findInjectorByType } from '~/services/growi-uri-injector/GrowiUriInjectorFactory';
 import { ViewInteractionPayloadDelegator } from '~/services/growi-uri-injector/ViewInteractionPayloadDelegator';
 import { ViewInteractionPayloadDelegator } from '~/services/growi-uri-injector/ViewInteractionPayloadDelegator';
+import { BlockActionsPayloadDelegator } from '~/services/growi-uri-injector/BlockActionsPayloadDelegator';
 
 
 
 
 const logger = loggerFactory('slackbot-proxy:controllers:growi-to-slack');
 const logger = loggerFactory('slackbot-proxy:controllers:growi-to-slack');
@@ -173,31 +173,53 @@ export class GrowiToSlackCtrl {
 
 
   injectGrowiUri(req: GrowiReq, growiUri: string):WebAPICallOptions {
   injectGrowiUri(req: GrowiReq, growiUri: string):WebAPICallOptions {
 
 
-    // TODO: iterate with decorator
-    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;
-
-      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);
-    }
+    // TODO: get list from decorator
+    const vipDelegators: ViewInteractionPayloadDelegator[] = [new ViewInteractionPayloadDelegator()];
+    const bapDelegators: BlockActionsPayloadDelegator[] = [];
+
+    const parsedView = JSON.parse(req.body.view);
+    const parsedBlocks = JSON.parse(req.body.blocks);
+
+    vipDelegators.forEach((delegator) => {
+      if (delegator.shouldHandleToInject(parsedView)) {
+        delegator.inject(parsedView, growiUri);
+      }
+    });
+    req.body.view = JSON.stringify(parsedView);
+
+    bapDelegators.forEach((delegator) => {
+      if (delegator.shouldHandleToInject(req)) {
+        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);
+    // }
 
 
     const opt = req.body;
     const opt = req.body;
     opt.headers = req.headers;
     opt.headers = req.headers;

+ 4 - 4
packages/slackbot-proxy/src/interfaces/growi-to-slack/growi-uri-injector.ts → packages/slackbot-proxy/src/interfaces/growi-uri-injector.ts

@@ -1,5 +1,5 @@
-import { Req } from '@tsed/common';
-import { SlackOauthReq } from '../slack-to-growi/slack-oauth-req';
+import { GrowiReq } from './growi-to-slack/growi-req';
+import { SlackOauthReq } from './slack-to-growi/slack-oauth-req';
 
 
 export type GrowiUriWithOriginalData = {
 export type GrowiUriWithOriginalData = {
   growiUri: string,
   growiUri: string,
@@ -18,10 +18,10 @@ export const isGrowiUriWithOriginalData = (data: any): data is GrowiUriWithOrigi
 
 
 export interface GrowiUriInjector<IB, EP> {
 export interface GrowiUriInjector<IB, EP> {
 
 
-  shouldHandleToInject(req: Req): boolean;
+  shouldHandleToInject(req: GrowiReq): boolean;
   inject(body: IB, growiUri:string): void;
   inject(body: IB, growiUri:string): void;
 
 
-  shouldHandleToExtract(req: Req & SlackOauthReq): boolean;
+  shouldHandleToExtract(req: SlackOauthReq): boolean;
   extract(payload: EP): GrowiUriWithOriginalData;
   extract(payload: EP): GrowiUriWithOriginalData;
 
 
 }
 }

+ 0 - 1
packages/slackbot-proxy/src/interfaces/slack-to-growi/slack-oauth-req.ts

@@ -3,6 +3,5 @@ import { Req } from '@tsed/common';
 
 
 export type SlackOauthReq = Req & {
 export type SlackOauthReq = Req & {
   authorizeResult: AuthorizeResult,
   authorizeResult: AuthorizeResult,
-  parsedPayload?: any,
   growiUri?: string,
   growiUri?: string,
 };
 };

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

@@ -2,43 +2,60 @@ import {
   IMiddleware, Middleware, Next, Req, Res,
   IMiddleware, Middleware, Next, Req, Res,
 } from '@tsed/common';
 } from '@tsed/common';
 import { SlackOauthReq } from '~/interfaces/slack-to-growi/slack-oauth-req';
 import { SlackOauthReq } from '~/interfaces/slack-to-growi/slack-oauth-req';
-import { growiUriInjectorFactory } from '~/services/growi-uri-injector/GrowiUriInjectorFactory';
+import { BlockActionsPayloadDelegator } from '~/services/growi-uri-injector/BlockActionsPayloadDelegator';
 import { ViewInteractionPayloadDelegator } from '~/services/growi-uri-injector/ViewInteractionPayloadDelegator';
 import { ViewInteractionPayloadDelegator } from '~/services/growi-uri-injector/ViewInteractionPayloadDelegator';
 
 
 @Middleware()
 @Middleware()
 export class ExtractGrowiUriFromReq implements IMiddleware {
 export class ExtractGrowiUriFromReq implements IMiddleware {
 
 
-  use(@Req() req: Req & SlackOauthReq, @Res() res: Res, @Next() next: Next): void {
+  use(@Req() req: SlackOauthReq, @Res() res: Res, @Next() next: Next): void {
 
 
     // There is no payload in the request from slack
     // There is no payload in the request from slack
     if (req.body.payload == null) {
     if (req.body.payload == null) {
       return next();
       return next();
     }
     }
 
 
+    // TODO: get list from decorator
+    const vipDelegators: ViewInteractionPayloadDelegator[] = [new ViewInteractionPayloadDelegator()];
+    const bapDelegators: BlockActionsPayloadDelegator[] = [];
+    const delegators = vipDelegators.concat(bapDelegators);
+
     const parsedPayload = JSON.parse(req.body.payload);
     const parsedPayload = JSON.parse(req.body.payload);
-    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;
-        }
+    for (const delegator of delegators) {
+      if (delegator.shouldHandleToExtract(parsedPayload)) {
+        const data = delegator.extract(parsedPayload);
+        req.growiUri = data.growiUri;
+
+        // break if growiUri discovered
+        break;
       }
       }
     }
     }
-
-    req.body.payload = JSON.stringify(parsedPayload);
+    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);
 
 
     return next();
     return next();
   }
   }

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

@@ -0,0 +1,47 @@
+import { GrowiUriInjector, GrowiUriWithOriginalData, isGrowiUriWithOriginalData } from '~/interfaces/growi-uri-injector';
+import { GrowiReq } from '~/interfaces/growi-to-slack/growi-req';
+import { SlackOauthReq } from '~/interfaces/slack-to-growi/slack-oauth-req';
+
+export class BlockActionsPayloadDelegator implements GrowiUriInjector<{view: string}, {view: {'private_metadata': string}}> {
+
+  // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
+  shouldHandleToInject(req: GrowiReq): boolean {
+    return req.body.view != null;
+  }
+
+  inject(body: {view: string}, growiUri:string): void {
+    const parsedView = JSON.parse(body.view);
+    const originalData = JSON.stringify(parsedView.private_metadata);
+
+    const data: GrowiUriWithOriginalData = { growiUri, originalData };
+
+    parsedView.private_metadata = JSON.stringify(data);
+    body.view = JSON.stringify(parsedView);
+  }
+
+  // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
+  shouldHandleToExtract(req: Req & SlackOauthReq): boolean {
+    const { type, view } = req.parsedPayload;
+    if (type !== 'view_submission') {
+      return false;
+    }
+
+    try {
+      const data: any = JSON.parse(view.private_metadata);
+      return isGrowiUriWithOriginalData(data);
+    }
+    // when parsing failed
+    catch (err) {
+      return false;
+    }
+  }
+
+  extract(payload: {view: {'private_metadata': string}}): GrowiUriWithOriginalData {
+    // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+    const data: GrowiUriWithOriginalData = JSON.parse(payload.view.private_metadata!); // private_metadata must not be null at this moment
+    payload.view.private_metadata = JSON.parse(data.originalData);
+
+    return data;
+  }
+
+}

+ 1 - 1
packages/slackbot-proxy/src/services/growi-uri-injector/GrowiUriInjectionButtonDelegator.ts

@@ -1,4 +1,4 @@
-import { ObsoleteGrowiUriInjector } from '~/interfaces/growi-to-slack/growi-uri-injector';
+import { ObsoleteGrowiUriInjector } from '~/interfaces/growi-uri-injector';
 
 
 export class GrowiUriInjectionButtonDelegator implements ObsoleteGrowiUriInjector {
 export class GrowiUriInjectionButtonDelegator implements ObsoleteGrowiUriInjector {
 
 

+ 1 - 1
packages/slackbot-proxy/src/services/growi-uri-injector/GrowiUriInjectorFactory.ts

@@ -1,4 +1,4 @@
-import { ObsoleteGrowiUriInjector } from '~/interfaces/growi-to-slack/growi-uri-injector';
+import { ObsoleteGrowiUriInjector } from '~/interfaces/growi-uri-injector';
 import { GrowiUriInjectionButtonDelegator } from './GrowiUriInjectionButtonDelegator';
 import { GrowiUriInjectionButtonDelegator } from './GrowiUriInjectionButtonDelegator';
 
 
 /**
 /**

+ 4 - 5
packages/slackbot-proxy/src/services/growi-uri-injector/ViewInteractionPayloadDelegator.ts

@@ -1,12 +1,11 @@
-import { Req } from '@tsed/common';
-
-import { GrowiUriInjector, GrowiUriWithOriginalData, isGrowiUriWithOriginalData } from '~/interfaces/growi-to-slack/growi-uri-injector';
+import { GrowiUriInjector, GrowiUriWithOriginalData, isGrowiUriWithOriginalData } from '~/interfaces/growi-uri-injector';
+import { GrowiReq } from '~/interfaces/growi-to-slack/growi-req';
 import { SlackOauthReq } from '~/interfaces/slack-to-growi/slack-oauth-req';
 import { SlackOauthReq } from '~/interfaces/slack-to-growi/slack-oauth-req';
 
 
 export class ViewInteractionPayloadDelegator implements GrowiUriInjector<{view: string}, {view: {'private_metadata': string}}> {
 export class ViewInteractionPayloadDelegator implements GrowiUriInjector<{view: string}, {view: {'private_metadata': string}}> {
 
 
   // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
   // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
-  shouldHandleToInject(req: Req): boolean {
+  shouldHandleToInject(req: GrowiReq): boolean {
     return req.body.view != null;
     return req.body.view != null;
   }
   }
 
 
@@ -21,7 +20,7 @@ export class ViewInteractionPayloadDelegator implements GrowiUriInjector<{view:
   }
   }
 
 
   // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
   // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
-  shouldHandleToExtract(req: Req & SlackOauthReq): boolean {
+  shouldHandleToExtract(req: SlackOauthReq): boolean {
     const { type, view } = req.parsedPayload;
     const { type, view } = req.parsedPayload;
     if (type !== 'view_submission') {
     if (type !== 'view_submission') {
       return false;
       return false;