SelectRequestService.ts 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  1. import { Service } from '@tsed/di';
  2. import axios from 'axios';
  3. import { GrowiCommand, generateWebClient } from '@growi/slack';
  4. import { AuthorizeResult } from '@slack/oauth';
  5. import { GrowiCommandProcessor } from '~/interfaces/slack-to-growi/growi-command-processor';
  6. import { RelationRepository } from '~/repositories/relation';
  7. import { Installation } from '~/entities/installation';
  8. @Service()
  9. export class SelectRequestService implements GrowiCommandProcessor {
  10. async process(growiCommand: GrowiCommand, authorizeResult: AuthorizeResult, body: {[key:string]:string } & {growiUris:string[]}): Promise<void> {
  11. const { botToken } = authorizeResult;
  12. if (botToken == null) {
  13. throw new Error('botToken is required.');
  14. }
  15. const client = generateWebClient(botToken);
  16. await client.views.open({
  17. trigger_id: body.trigger_id,
  18. view: {
  19. type: 'modal',
  20. callback_id: 'select_growi',
  21. title: {
  22. type: 'plain_text',
  23. text: 'Select Growi Url',
  24. },
  25. submit: {
  26. type: 'plain_text',
  27. text: 'Submit',
  28. },
  29. close: {
  30. type: 'plain_text',
  31. text: 'Close',
  32. },
  33. private_metadata: JSON.stringify({ body, growiCommand }),
  34. blocks: [
  35. {
  36. type: 'input',
  37. block_id: 'select_growi',
  38. label: {
  39. type: 'plain_text',
  40. text: 'GROWI App',
  41. },
  42. element: {
  43. type: 'static_select',
  44. action_id: 'growi_app',
  45. options: body.growiUris.map((growiUri) => {
  46. return ({
  47. text: {
  48. type: 'plain_text',
  49. text: growiUri,
  50. },
  51. value: growiUri,
  52. });
  53. }),
  54. },
  55. },
  56. ],
  57. },
  58. });
  59. }
  60. // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
  61. async forwardRequest(relationRepository:RelationRepository, installation:Installation | undefined, payload:any):Promise<void> {
  62. const { trigger_id: triggerId } = payload;
  63. const { state, private_metadata: privateMetadata } = payload?.view;
  64. const { value: growiUri } = state?.values?.select_growi?.growi_app?.selected_option;
  65. const parsedPrivateMetadata = JSON.parse(privateMetadata);
  66. const { growiCommand, body } = parsedPrivateMetadata;
  67. if (growiCommand == null || body == null) {
  68. throw new Error('growiCommand and body are required.');
  69. }
  70. // ovverride trigger_id
  71. body.trigger_id = triggerId;
  72. const relation = await relationRepository.findOne({ installation, growiUri });
  73. if (relation == null) {
  74. throw new Error('No relation found.');
  75. }
  76. /*
  77. * forward to GROWI server
  78. */
  79. // generate API URL
  80. const url = new URL('/_api/v3/slack-integration/proxied/commands', relation.growiUri);
  81. await axios.post(url.toString(), {
  82. ...body,
  83. growiCommand,
  84. }, {
  85. headers: {
  86. 'x-growi-ptog-tokens': relation.tokenPtoG,
  87. },
  88. });
  89. }
  90. }