Просмотр исходного кода

Merge pull request #3899 from weseek/feat/6285-6286-response-growi-url

Feat/6285 6286 response growi url
Yuki Takei 4 лет назад
Родитель
Сommit
53608eecd2

+ 36 - 2
packages/slackbot-proxy/src/controllers/growi-to-slack.ts

@@ -18,6 +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 { injectGrowiUriToView } from '~/utils/injectGrowiUriToView';
 
 
 
 
 const logger = loggerFactory('slackbot-proxy:controllers:growi-to-slack');
 const logger = loggerFactory('slackbot-proxy:controllers:growi-to-slack');
@@ -163,6 +165,38 @@ export class GrowiToSlackCtrl {
     return res.send({ relation: createdRelation, slackBotToken: token });
     return res.send({ relation: createdRelation, slackBotToken: token });
   }
   }
 
 
+  injectGrowiUri(req:GrowiReq, growiUri:string):WebAPICallOptions {
+
+    if (req.body.view != null) {
+      injectGrowiUriToView(req.body, growiUri);
+    }
+
+    if (req.body.blocks != null) {
+      const parsedBlocks = JSON.parse(req.body.blocks as string);
+
+      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;
+    opt.headers = req.headers;
+
+    return opt;
+  }
+
   @Post('/:method')
   @Post('/:method')
   @UseBefore(AddWebclientResponseToRes, verifyGrowiToSlackRequest)
   @UseBefore(AddWebclientResponseToRes, verifyGrowiToSlackRequest)
   async postResult(
   async postResult(
@@ -194,8 +228,8 @@ export class GrowiToSlackCtrl {
     const client = generateWebClient(token);
     const client = generateWebClient(token);
 
 
     try {
     try {
-      const opt = req.body as WebAPICallOptions;
-      opt.headers = req.headers;
+      const opt = this.injectGrowiUri(req, relation.growiUri);
+
       await client.apiCall(method, opt);
       await client.apiCall(method, opt);
     }
     }
     catch (err) {
     catch (err) {

+ 13 - 17
packages/slackbot-proxy/src/controllers/slack.ts

@@ -17,6 +17,7 @@ import { RelationRepository } from '~/repositories/relation';
 import { OrderRepository } from '~/repositories/order';
 import { OrderRepository } from '~/repositories/order';
 import { AddSigningSecretToReq } from '~/middlewares/slack-to-growi/add-signing-secret-to-req';
 import { AddSigningSecretToReq } from '~/middlewares/slack-to-growi/add-signing-secret-to-req';
 import { AuthorizeCommandMiddleware, AuthorizeInteractionMiddleware } from '~/middlewares/slack-to-growi/authorizer';
 import { AuthorizeCommandMiddleware, AuthorizeInteractionMiddleware } from '~/middlewares/slack-to-growi/authorizer';
+import { ExtractGrowiUriFromReq } from '~/middlewares/slack-to-growi/extract-growi-uri-from-req';
 import { InstallerService } from '~/services/InstallerService';
 import { InstallerService } from '~/services/InstallerService';
 import { RegisterService } from '~/services/RegisterService';
 import { RegisterService } from '~/services/RegisterService';
 import { UnregisterService } from '~/services/UnregisterService';
 import { UnregisterService } from '~/services/UnregisterService';
@@ -164,7 +165,7 @@ export class SlackCtrl {
   }
   }
 
 
   @Post('/interactions')
   @Post('/interactions')
-  @UseBefore(AuthorizeInteractionMiddleware)
+  @UseBefore(AuthorizeInteractionMiddleware, ExtractGrowiUriFromReq)
   async handleInteraction(@Req() req: SlackOauthReq, @Res() res: Res): Promise<void|string|Res|WebAPICallResult> {
   async handleInteraction(@Req() req: SlackOauthReq, @Res() res: Res): Promise<void|string|Res|WebAPICallResult> {
     logger.info('receive interaction', req.body);
     logger.info('receive interaction', req.body);
     logger.info('receive interaction', req.authorizeResult);
     logger.info('receive interaction', req.authorizeResult);
@@ -211,30 +212,25 @@ export class SlackCtrl {
     }
     }
 
 
     /*
     /*
-     * forward to GROWI server
-     */
-    const relations = await this.relationRepository.find({ installation });
+    * forward to GROWI server
+    */
+    const relation = await this.relationRepository.findOne({ installation, growiUri: req.growiUri });
 
 
-    const promises = relations.map((relation: Relation) => {
+    if (relation == null) {
+      logger.error('*No relation found.*');
+      return;
+    }
+
+    try {
       // generate API URL
       // generate API URL
-      const url = new URL('/_api/v3/slack-integration/proxied/interactions', relation.growiUri);
-      return axios.post(url.toString(), {
+      const url = new URL('/_api/v3/slack-integration/proxied/interactions', req.growiUri);
+      await axios.post(url.toString(), {
         ...body,
         ...body,
       }, {
       }, {
         headers: {
         headers: {
           'x-growi-ptog-tokens': relation.tokenPtoG,
           'x-growi-ptog-tokens': relation.tokenPtoG,
         },
         },
       });
       });
-    });
-
-    // pickup PromiseRejectedResult only
-    const results = await Promise.allSettled(promises);
-    const rejectedResults: PromiseRejectedResult[] = results.filter((result): result is PromiseRejectedResult => result.status === 'rejected');
-    const botToken = installation?.data.bot?.token;
-
-    try {
-      // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
-      return postEphemeralErrors(rejectedResults, body.channel_id, body.user_id, botToken!);
     }
     }
     catch (err) {
     catch (err) {
       logger.error(err);
       logger.error(err);

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

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

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

@@ -0,0 +1,40 @@
+import {
+  IMiddleware, Middleware, Next, Req, Res,
+} from '@tsed/common';
+import { SlackOauthReq } from '~/interfaces/slack-to-growi/slack-oauth-req';
+import { growiUriInjectorFactory } from '~/services/growi-uri-injector/GrowiUriInjectorFactory';
+import { extractGrowiUriFromView } from '~/utils/extractGrowiUriFromView';
+
+@Middleware()
+export class ExtractGrowiUriFromReq implements IMiddleware {
+
+  use(@Req() req: Req & SlackOauthReq, @Res() res: Res, @Next() next: Next): void {
+
+    const payload = JSON.parse(req.body.payload);
+
+    // extract for modal
+    if (payload.view != null) {
+      const extractedValues = extractGrowiUriFromView(payload.view);
+      req.growiUri = extractedValues.growiUri;
+      payload.view.private_metadata = extractedValues.originalData;
+    }
+    else {
+      // break when uri is found
+      for (const type of Object.keys(growiUriInjectorFactory)) {
+        const growiUriInjector = growiUriInjectorFactory[type]();
+        const extractedValues = growiUriInjector.extract(payload.actions[0]);
+
+        if (extractedValues.growiUri != null) {
+          req.growiUri = extractedValues.growiUri;
+          payload.actions[0].value = JSON.stringify(extractedValues.originalData);
+          break;
+        }
+      }
+    }
+
+    req.body.payload = JSON.stringify(payload);
+
+    return next();
+  }
+
+}

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

@@ -0,0 +1,23 @@
+import { GrowiUriInjector } from './GrowiUriInjector';
+
+export class GrowiUriInjectionButtonDelegator implements GrowiUriInjector {
+
+  handleInject(type:string):boolean {
+    return type === 'button';
+  }
+
+  inject(element: {value:string}, growiUri:string): void {
+    const parsedValue = JSON.parse(element.value);
+    const originalData = JSON.stringify(parsedValue);
+    element.value = JSON.stringify({ growiUri, originalData });
+  }
+
+  extract(action: {value:string}): {growiUri?:string, originalData:any} {
+    const parsedValues = JSON.parse(action.value);
+    if (parsedValues.originalData != null) {
+      parsedValues.originalData = JSON.parse(parsedValues.originalData);
+    }
+    return parsedValues;
+  }
+
+}

+ 9 - 0
packages/slackbot-proxy/src/services/growi-uri-injector/GrowiUriInjector.ts

@@ -0,0 +1,9 @@
+
+export interface GrowiUriInjector {
+
+  handleInject(type:string):boolean
+
+  inject(body: any, growiUri:string): void;
+
+  extract(body: any):any;
+}

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

@@ -0,0 +1,18 @@
+import { GrowiUriInjector } from './GrowiUriInjector';
+import { GrowiUriInjectionButtonDelegator } from './GrowiUriInjectionButtonDelegator';
+
+/**
+ * Instanciate GrowiUriInjector
+ */
+export const growiUriInjectorFactory = {
+  button: (): GrowiUriInjector => {
+    return new GrowiUriInjectionButtonDelegator();
+  },
+};
+
+export const findInjectorByType = (type:string): null|GrowiUriInjector => {
+  if (!Object.keys(growiUriInjectorFactory).includes(type)) {
+    return null;
+  }
+  return growiUriInjectorFactory[type]();
+};

+ 10 - 0
packages/slackbot-proxy/src/utils/extractGrowiUriFromView.ts

@@ -0,0 +1,10 @@
+export const extractGrowiUriFromView = (view:{'private_metadata': string}): {growiUri?:string, originalData:{[key:string]:any}} => {
+  const parsedValues = JSON.parse(view.private_metadata);
+  if (parsedValues.originalData != null) {
+    parsedValues.originalData = JSON.parse(parsedValues.originalData);
+  }
+  else {
+    parsedValues.originalData = view.private_metadata;
+  }
+  return parsedValues;
+};

+ 7 - 0
packages/slackbot-proxy/src/utils/injectGrowiUriToView.ts

@@ -0,0 +1,7 @@
+export const injectGrowiUriToView = (body: {view:string}, growiUri:string): void => {
+  const parsedView = JSON.parse(body.view);
+  const originalData = JSON.stringify(parsedView.private_metadata);
+
+  parsedView.private_metadata = JSON.stringify({ growiUri, originalData });
+  body.view = JSON.stringify(parsedView);
+};

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

@@ -156,7 +156,7 @@ class SlackBotService extends S2sMessageHandlable {
   async shareSearchResults(client, payload) {
   async shareSearchResults(client, payload) {
     client.chat.postMessage({
     client.chat.postMessage({
       channel: payload.channel.id,
       channel: payload.channel.id,
-      text: payload.actions[0].value,
+      text: JSON.parse(payload.actions[0].value).pageList,
     });
     });
   }
   }
 
 
@@ -210,7 +210,9 @@ class SlackBotService extends S2sMessageHandlable {
             },
             },
             style: 'primary',
             style: 'primary',
             action_id: 'shareSearchResults',
             action_id: 'shareSearchResults',
-            value: `${keywordsAndDesc} \n\n ${urls.join('\n')}`,
+            value: JSON.stringify({
+              offset, body, args, pageList: `${keywordsAndDesc} \n\n ${urls.join('\n')}`,
+            }),
           },
           },
         ],
         ],
       };
       };