SelectGrowiService.ts 3.3 KB

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