interaction-payload-accessor.ts 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  1. import assert from 'node:assert';
  2. import type { IChannel } from '../interfaces/channel';
  3. import type { IInteractionPayloadAccessor } from '../interfaces/request-from-slack';
  4. import loggerFactory from './logger';
  5. const logger = loggerFactory('@growi/slack:utils:interaction-payload-accessor');
  6. export class InteractionPayloadAccessor implements IInteractionPayloadAccessor {
  7. // biome-ignore lint/suspicious/noExplicitAny: ignore
  8. private payload: any;
  9. // biome-ignore lint/suspicious/noExplicitAny: ignore
  10. constructor(payload: any) {
  11. this.payload = payload;
  12. }
  13. // biome-ignore lint/suspicious/noExplicitAny: ignore
  14. firstAction(): any | null {
  15. const actions = this.payload.actions;
  16. if (actions != null && actions[0] != null) {
  17. return actions[0];
  18. }
  19. return null;
  20. }
  21. getResponseUrl(): string {
  22. const responseUrl = this.payload.response_url;
  23. if (responseUrl != null) {
  24. return responseUrl;
  25. }
  26. const responseUrls = this.payload.response_urls;
  27. assert(responseUrls != null);
  28. assert(responseUrls[0] != null);
  29. return responseUrls[0].response_url;
  30. }
  31. // biome-ignore lint/suspicious/noExplicitAny: ignore
  32. getStateValues(): any | null {
  33. const state = this.payload.state;
  34. if (state != null && state.values != null) {
  35. return state.values;
  36. }
  37. const view = this.payload.view;
  38. if (view != null && view.state != null && view.state.values != null) {
  39. return view.state.values;
  40. }
  41. return null;
  42. }
  43. // biome-ignore lint/suspicious/noExplicitAny: ignore
  44. getViewPrivateMetaData(): any | null {
  45. const view = this.payload.view;
  46. if (view?.private_metadata) {
  47. return JSON.parse(view.private_metadata);
  48. }
  49. return null;
  50. }
  51. getActionIdAndCallbackIdFromPayLoad(): { [key: string]: string } {
  52. const actionId = this.firstAction()?.action_id || '';
  53. const callbackId = this.payload.view?.callback_id || '';
  54. return { actionId, callbackId };
  55. }
  56. getChannel(): IChannel | null {
  57. // private_metadata should have the channelName parameter when view_submission
  58. const privateMetadata = this.getViewPrivateMetaData();
  59. if (privateMetadata != null && privateMetadata.channelName != null) {
  60. throw new Error(
  61. 'PrivateMetaDatas are not implemented after removal of modal from slash commands. Use payload instead.',
  62. );
  63. }
  64. const channel = this.payload.channel;
  65. if (channel != null) {
  66. return channel;
  67. }
  68. return null;
  69. }
  70. // biome-ignore lint/suspicious/noExplicitAny: ignore
  71. getOriginalData(): any | null {
  72. const value = this.firstAction()?.value;
  73. if (value == null) return null;
  74. const { originalData } = JSON.parse(value);
  75. if (originalData == null) return JSON.parse(value);
  76. // biome-ignore lint/suspicious/noImplicitAnyLet: ignore
  77. let parsedOriginalData;
  78. try {
  79. parsedOriginalData = JSON.parse(originalData);
  80. } catch (err) {
  81. logger.error('Failed to parse original data:\n', err);
  82. return null;
  83. }
  84. return parsedOriginalData;
  85. }
  86. }