error-handler.ts 2.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
  1. import type { RespondBodyForResponseUrl } from '@growi/slack';
  2. import { markdownSectionBlock } from '@growi/slack/dist/utils/block-kit-builder';
  3. import { respond } from '@growi/slack/dist/utils/response-url';
  4. import { type ChatPostEphemeralResponse, WebClient } from '@slack/web-api';
  5. import assert from 'assert';
  6. import { SlackCommandHandlerError } from '../../models/vo/slack-command-handler-error';
  7. function generateRespondBodyForInternalServerError(
  8. message,
  9. ): RespondBodyForResponseUrl {
  10. return {
  11. text: message,
  12. blocks: [
  13. markdownSectionBlock(
  14. `*GROWI Internal Server Error occured.*\n \`${message}\``,
  15. ),
  16. ],
  17. };
  18. }
  19. async function handleErrorWithWebClient(
  20. error: Error,
  21. client: WebClient,
  22. body: any,
  23. ): Promise<ChatPostEphemeralResponse> {
  24. const isInteraction = !body.channel_id;
  25. // this method is expected to use when system couldn't response_url
  26. assert(
  27. !(error instanceof SlackCommandHandlerError) || error.responseUrl == null,
  28. );
  29. const payload = JSON.parse(body.payload);
  30. const channel = isInteraction ? payload.channel.id : body.channel_id;
  31. const user = isInteraction ? payload.user.id : body.user_id;
  32. return client.chat.postEphemeral({
  33. channel,
  34. user,
  35. ...generateRespondBodyForInternalServerError(error.message),
  36. });
  37. }
  38. export async function handleError(
  39. error: SlackCommandHandlerError | Error,
  40. responseUrl?: string,
  41. ): Promise<void>;
  42. export async function handleError(
  43. error: Error,
  44. client: WebClient,
  45. body: any,
  46. ): Promise<ChatPostEphemeralResponse>;
  47. export async function handleError(
  48. error: SlackCommandHandlerError | Error,
  49. ...args: any[]
  50. ): Promise<void | ChatPostEphemeralResponse> {
  51. // handle a SlackCommandHandlerError
  52. if (error instanceof SlackCommandHandlerError) {
  53. const responseUrl = args[0] || error.responseUrl;
  54. assert(responseUrl != null, 'Specify responseUrl.');
  55. return respond(responseUrl, error.respondBody);
  56. }
  57. const secondArg = args[0];
  58. assert(
  59. secondArg != null,
  60. "Couldn't handle Error without the second argument.",
  61. );
  62. // handle a normal Error with response_url
  63. if (typeof secondArg === 'string') {
  64. const respondBody = generateRespondBodyForInternalServerError(
  65. error.message,
  66. );
  67. return respond(secondArg, respondBody);
  68. }
  69. assert(args[0] instanceof WebClient);
  70. // handle with WebClient
  71. return handleErrorWithWebClient(error, args[0], args[1]);
  72. }