RegisterService.ts 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  1. import { Inject, Service } from '@tsed/di';
  2. import { WebClient, LogLevel, Block } from '@slack/web-api';
  3. import {
  4. markdownSectionBlock, markdownHeaderBlock, inputSectionBlock, GrowiCommand,
  5. } from '@growi/slack';
  6. import { AuthorizeResult } from '@slack/oauth';
  7. import { GrowiCommandProcessor } from '~/interfaces/slack-to-growi/growi-command-processor';
  8. import { OrderRepository } from '~/repositories/order';
  9. import { Installation } from '~/entities/installation';
  10. import { InvalidUrlError } from '../models/errors';
  11. const isProduction = process.env.NODE_ENV === 'production';
  12. const isOfficialMode = process.env.OFFICIAL_MODE === 'true';
  13. @Service()
  14. export class RegisterService implements GrowiCommandProcessor {
  15. @Inject()
  16. orderRepository: OrderRepository;
  17. async process(growiCommand: GrowiCommand, authorizeResult: AuthorizeResult, body: {[key:string]:string}): Promise<void> {
  18. const { botToken } = authorizeResult;
  19. const client = new WebClient(botToken, { logLevel: isProduction ? LogLevel.DEBUG : LogLevel.INFO });
  20. await client.views.open({
  21. trigger_id: body.trigger_id,
  22. view: {
  23. type: 'modal',
  24. callback_id: 'register',
  25. title: {
  26. type: 'plain_text',
  27. text: 'Register Credentials',
  28. },
  29. submit: {
  30. type: 'plain_text',
  31. text: 'Submit',
  32. },
  33. close: {
  34. type: 'plain_text',
  35. text: 'Close',
  36. },
  37. private_metadata: JSON.stringify({ channel: body.channel_name }),
  38. blocks: [
  39. inputSectionBlock('growiUrl', 'GROWI domain', 'contents_input', false, 'https://example.com'),
  40. inputSectionBlock('tokenPtoG', 'Access Token Proxy to GROWI', 'contents_input', false, 'jBMZvpk.....'),
  41. inputSectionBlock('tokenGtoP', 'Access Token GROWI to Proxy', 'contents_input', false, 'sdg15av.....'),
  42. ],
  43. },
  44. });
  45. }
  46. async replyToSlack(client: WebClient, channel: string, user: string, text: string, blocks: Array<Block>): Promise<void> {
  47. await client.chat.postEphemeral({
  48. channel,
  49. user,
  50. // Recommended including 'text' to provide a fallback when using blocks
  51. // refer to https://api.slack.com/methods/chat.postEphemeral#text_usage
  52. text,
  53. blocks,
  54. });
  55. return;
  56. }
  57. async insertOrderRecord(
  58. installation: Installation | undefined,
  59. // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
  60. botToken: string | undefined, payload: any,
  61. ): Promise<void> {
  62. const inputValues = payload.view.state.values;
  63. const growiUrl = inputValues.growiUrl.contents_input.value;
  64. const tokenPtoG = inputValues.tokenPtoG.contents_input.value;
  65. const tokenGtoP = inputValues.tokenGtoP.contents_input.value;
  66. const { channel } = JSON.parse(payload.view.private_metadata);
  67. const client = new WebClient(botToken, { logLevel: isProduction ? LogLevel.DEBUG : LogLevel.INFO });
  68. try {
  69. // eslint-disable-next-line @typescript-eslint/no-unused-vars
  70. const url = new URL(growiUrl);
  71. }
  72. catch (error) {
  73. const invalidErrorMsg = 'Please enter a valid URL';
  74. const blocks = [
  75. markdownSectionBlock(invalidErrorMsg),
  76. ];
  77. await this.replyToSlack(client, channel, payload.user.id, 'Invalid URL', blocks);
  78. throw new InvalidUrlError(growiUrl);
  79. }
  80. this.orderRepository.save({
  81. installation, growiUrl, tokenPtoG, tokenGtoP,
  82. });
  83. }
  84. async notifyServerUriToSlack(
  85. // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
  86. botToken: string | undefined, payload: any,
  87. ): Promise<void> {
  88. const { channel } = JSON.parse(payload.view.private_metadata);
  89. const serverUri = process.env.SERVER_URI;
  90. const client = new WebClient(botToken, { logLevel: isProduction ? LogLevel.DEBUG : LogLevel.INFO });
  91. const blocks: Block[] = [];
  92. if (isOfficialMode) {
  93. blocks.push(markdownHeaderBlock(':white_check_mark: 1. Install Official bot to Slack'));
  94. blocks.push(markdownHeaderBlock(':white_check_mark: 2. Register for GROWI Official Bot Proxy Service'));
  95. blocks.push(markdownSectionBlock('The request has been successfully accepted. However, registration has *NOT been completed* yet.'));
  96. blocks.push(markdownHeaderBlock(':arrow_right: 3. Test Connection'));
  97. blocks.push(markdownSectionBlock('*Test Connection* to complete the registration in your GROWI.'));
  98. blocks.push(markdownHeaderBlock(':white_large_square: 4. (Opt) Manage GROWI commands'));
  99. blocks.push(markdownSectionBlock('Modify permission settings if you need.'));
  100. await this.replyToSlack(client, channel, payload.user.id, 'Proxy URL', blocks);
  101. return;
  102. }
  103. blocks.push(markdownHeaderBlock(':white_check_mark: 1. Create Bot'));
  104. blocks.push(markdownHeaderBlock(':white_check_mark: 2. Install bot to Slack'));
  105. blocks.push(markdownHeaderBlock(':white_check_mark: 3. Register for your GROWI Custom Bot Proxy'));
  106. blocks.push(markdownSectionBlock('The request has been successfully accepted. However, registration has *NOT been completed* yet.'));
  107. blocks.push(markdownHeaderBlock(':arrow_right: 4. Set Proxy URL on GROWI'));
  108. blocks.push(markdownSectionBlock('Please enter and update the following Proxy URL to slack bot setting form in your GROWI'));
  109. blocks.push(markdownSectionBlock(`Proxy URL: ${serverUri}`));
  110. blocks.push(markdownHeaderBlock(':arrow_right: 5. Test Connection'));
  111. blocks.push(markdownSectionBlock('And *Test Connection* to complete the registration in your GROWI.'));
  112. blocks.push(markdownHeaderBlock(':white_large_square: 6. (Opt) Manage GROWI commands'));
  113. blocks.push(markdownSectionBlock('Modify permission settings if you need.'));
  114. await this.replyToSlack(client, channel, payload.user.id, 'Proxy URL', blocks);
  115. return;
  116. }
  117. }