seyfert 4.4.0 → 5.0.1-dev-27866487194.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (203) hide show
  1. package/lib/api/Routes/cdn.d.ts +2 -2
  2. package/lib/api/Routes/guilds.d.ts +2 -2
  3. package/lib/api/api.d.ts +19 -7
  4. package/lib/api/api.js +197 -43
  5. package/lib/api/shared.d.ts +30 -1
  6. package/lib/api/utils/constants.d.ts +1 -1
  7. package/lib/api/utils/constants.js +1 -1
  8. package/lib/api/utils/utils.d.ts +2 -1
  9. package/lib/api/utils/utils.js +1 -1
  10. package/lib/builders/Attachment.d.ts +1 -1
  11. package/lib/builders/Attachment.js +30 -8
  12. package/lib/builders/MediaGallery.d.ts +1 -1
  13. package/lib/builders/MediaGallery.js +10 -0
  14. package/lib/builders/Modal.d.ts +18 -8
  15. package/lib/builders/Modal.js +36 -7
  16. package/lib/builders/Poll.js +18 -0
  17. package/lib/builders/RadioGroup.d.ts +4 -3
  18. package/lib/builders/RadioGroup.js +24 -3
  19. package/lib/builders/SelectMenu.d.ts +8 -6
  20. package/lib/builders/SelectMenu.js +24 -3
  21. package/lib/builders/types.d.ts +3 -2
  22. package/lib/cache/adapters/default.d.ts +1 -1
  23. package/lib/cache/adapters/default.js +23 -26
  24. package/lib/cache/adapters/limited.d.ts +1 -0
  25. package/lib/cache/adapters/limited.js +47 -33
  26. package/lib/cache/index.d.ts +19 -25
  27. package/lib/cache/index.js +58 -6
  28. package/lib/cache/resources/bans.d.ts +1 -1
  29. package/lib/cache/resources/bans.js +4 -4
  30. package/lib/cache/resources/channels.d.ts +1 -1
  31. package/lib/cache/resources/channels.js +4 -4
  32. package/lib/cache/resources/default/base.js +8 -8
  33. package/lib/cache/resources/default/guild-based.d.ts +4 -4
  34. package/lib/cache/resources/default/guild-based.js +29 -16
  35. package/lib/cache/resources/default/guild-related.d.ts +4 -4
  36. package/lib/cache/resources/default/guild-related.js +14 -14
  37. package/lib/cache/resources/emojis.d.ts +1 -1
  38. package/lib/cache/resources/emojis.js +4 -4
  39. package/lib/cache/resources/guilds.js +28 -15
  40. package/lib/cache/resources/members.d.ts +1 -1
  41. package/lib/cache/resources/members.js +6 -6
  42. package/lib/cache/resources/messages.d.ts +7 -2
  43. package/lib/cache/resources/messages.js +43 -20
  44. package/lib/cache/resources/overwrites.d.ts +1 -1
  45. package/lib/cache/resources/overwrites.js +5 -8
  46. package/lib/cache/resources/roles.d.ts +1 -1
  47. package/lib/cache/resources/roles.js +4 -4
  48. package/lib/cache/resources/stickers.d.ts +1 -1
  49. package/lib/cache/resources/stickers.js +4 -4
  50. package/lib/cache/resources/users.js +4 -4
  51. package/lib/cache/resources/voice-states.d.ts +1 -1
  52. package/lib/cache/resources/voice-states.js +4 -4
  53. package/lib/client/base.d.ts +82 -21
  54. package/lib/client/base.js +594 -39
  55. package/lib/client/client.d.ts +26 -3
  56. package/lib/client/client.js +33 -9
  57. package/lib/client/collectors.d.ts +9 -8
  58. package/lib/client/collectors.js +19 -52
  59. package/lib/client/httpclient.d.ts +3 -0
  60. package/lib/client/index.d.ts +3 -1
  61. package/lib/client/index.js +4 -0
  62. package/lib/client/intents.d.ts +3 -0
  63. package/lib/client/intents.js +9 -0
  64. package/lib/client/plugins/api.d.ts +4 -0
  65. package/lib/client/plugins/api.js +550 -0
  66. package/lib/client/plugins/errors.d.ts +25 -0
  67. package/lib/client/plugins/errors.js +79 -0
  68. package/lib/client/plugins/order.d.ts +10 -0
  69. package/lib/client/plugins/order.js +32 -0
  70. package/lib/client/plugins/registry.d.ts +273 -0
  71. package/lib/client/plugins/registry.js +868 -0
  72. package/lib/client/plugins/shared.d.ts +23 -0
  73. package/lib/client/plugins/shared.js +193 -0
  74. package/lib/client/plugins/types.d.ts +402 -0
  75. package/lib/client/plugins/types.js +8 -0
  76. package/lib/client/plugins.d.ts +78 -0
  77. package/lib/client/plugins.js +558 -0
  78. package/lib/client/workerclient.d.ts +10 -1
  79. package/lib/client/workerclient.js +23 -13
  80. package/lib/collection.d.ts +10 -8
  81. package/lib/collection.js +19 -25
  82. package/lib/commands/applications/chat.d.ts +18 -16
  83. package/lib/commands/applications/chat.js +56 -6
  84. package/lib/commands/applications/chatcontext.d.ts +23 -13
  85. package/lib/commands/applications/chatcontext.js +23 -2
  86. package/lib/commands/applications/entryPoint.d.ts +4 -3
  87. package/lib/commands/applications/entryPoint.js +1 -1
  88. package/lib/commands/applications/entrycontext.d.ts +7 -7
  89. package/lib/commands/applications/entrycontext.js +3 -1
  90. package/lib/commands/applications/menu.d.ts +4 -3
  91. package/lib/commands/applications/menucontext.d.ts +7 -7
  92. package/lib/commands/applications/menucontext.js +3 -1
  93. package/lib/commands/applications/options.d.ts +12 -12
  94. package/lib/commands/applications/shared.d.ts +31 -12
  95. package/lib/commands/decorators.d.ts +48 -36
  96. package/lib/commands/decorators.js +13 -3
  97. package/lib/commands/handle.d.ts +15 -4
  98. package/lib/commands/handle.js +224 -143
  99. package/lib/commands/handler.d.ts +23 -8
  100. package/lib/commands/handler.js +153 -66
  101. package/lib/commands/index.d.ts +1 -0
  102. package/lib/commands/optionresolver.d.ts +2 -2
  103. package/lib/common/it/colors.js +12 -2
  104. package/lib/common/it/error.d.ts +9 -0
  105. package/lib/common/it/error.js +8 -0
  106. package/lib/common/it/fake-promise.d.ts +4 -0
  107. package/lib/common/it/fake-promise.js +10 -0
  108. package/lib/common/it/formatter.d.ts +14 -11
  109. package/lib/common/it/formatter.js +4 -3
  110. package/lib/common/it/logger.d.ts +7 -1
  111. package/lib/common/it/logger.js +24 -6
  112. package/lib/common/it/utils.d.ts +6 -8
  113. package/lib/common/it/utils.js +44 -42
  114. package/lib/common/shorters/application.d.ts +3 -3
  115. package/lib/common/shorters/application.js +3 -2
  116. package/lib/common/shorters/bans.d.ts +7 -3
  117. package/lib/common/shorters/bans.js +13 -5
  118. package/lib/common/shorters/channels.d.ts +1 -1
  119. package/lib/common/shorters/channels.js +4 -4
  120. package/lib/common/shorters/emojis.js +1 -0
  121. package/lib/common/shorters/guilds.d.ts +5 -5
  122. package/lib/common/shorters/guilds.js +14 -31
  123. package/lib/common/shorters/interaction.d.ts +1 -1
  124. package/lib/common/shorters/members.d.ts +6 -6
  125. package/lib/common/shorters/members.js +13 -14
  126. package/lib/common/shorters/messages.d.ts +1 -1
  127. package/lib/common/shorters/users.d.ts +1 -1
  128. package/lib/common/shorters/webhook.d.ts +3 -2
  129. package/lib/common/shorters/webhook.js +0 -7
  130. package/lib/common/types/options.d.ts +4 -0
  131. package/lib/common/types/util.d.ts +8 -0
  132. package/lib/common/types/write.d.ts +2 -1
  133. package/lib/components/BaseSelectMenuComponent.d.ts +1 -1
  134. package/lib/components/BaseSelectMenuComponent.js +1 -1
  135. package/lib/components/ButtonComponent.d.ts +1 -1
  136. package/lib/components/StringSelectMenuComponent.d.ts +1 -1
  137. package/lib/components/componentcommand.d.ts +8 -7
  138. package/lib/components/componentcontext.d.ts +24 -34
  139. package/lib/components/componentcontext.js +7 -17
  140. package/lib/components/handler.d.ts +19 -7
  141. package/lib/components/handler.js +108 -49
  142. package/lib/components/index.d.ts +1 -0
  143. package/lib/components/index.js +1 -0
  144. package/lib/components/interactioncontext.d.ts +47 -0
  145. package/lib/components/interactioncontext.js +93 -0
  146. package/lib/components/modalcommand.d.ts +5 -4
  147. package/lib/components/modalcontext.d.ts +39 -18
  148. package/lib/components/modalcontext.js +59 -6
  149. package/lib/events/event.d.ts +9 -3
  150. package/lib/events/handler.d.ts +51 -6
  151. package/lib/events/handler.js +164 -35
  152. package/lib/events/hooks/interactions.d.ts +1 -1
  153. package/lib/events/hooks/voice.d.ts +1 -2
  154. package/lib/events/hooks/voice.js +2 -1
  155. package/lib/events/utils.d.ts +4 -0
  156. package/lib/events/utils.js +59 -0
  157. package/lib/index.d.ts +9 -4
  158. package/lib/index.js +13 -8
  159. package/lib/langs/handler.d.ts +14 -9
  160. package/lib/langs/handler.js +46 -9
  161. package/lib/structures/Application.d.ts +1 -1
  162. package/lib/structures/Emoji.d.ts +3 -3
  163. package/lib/structures/Emoji.js +2 -2
  164. package/lib/structures/Guild.d.ts +3 -3
  165. package/lib/structures/GuildBan.d.ts +3 -3
  166. package/lib/structures/GuildBan.js +3 -3
  167. package/lib/structures/GuildMember.d.ts +8 -8
  168. package/lib/structures/GuildMember.js +28 -7
  169. package/lib/structures/GuildRole.d.ts +1 -1
  170. package/lib/structures/GuildRole.js +2 -2
  171. package/lib/structures/Interaction.d.ts +11 -9
  172. package/lib/structures/Interaction.js +32 -11
  173. package/lib/structures/Message.d.ts +10 -3
  174. package/lib/structures/Message.js +29 -14
  175. package/lib/structures/VoiceState.d.ts +4 -0
  176. package/lib/structures/VoiceState.js +13 -1
  177. package/lib/structures/Webhook.d.ts +9 -1
  178. package/lib/structures/Webhook.js +4 -1
  179. package/lib/structures/channels.d.ts +16 -10
  180. package/lib/structures/channels.js +21 -26
  181. package/lib/structures/extra/BitField.d.ts +4 -4
  182. package/lib/structures/extra/BitField.js +20 -4
  183. package/lib/structures/extra/DiscordBase.js +1 -1
  184. package/lib/structures/extra/Permissions.d.ts +2 -4
  185. package/lib/structures/extra/Permissions.js +1 -17
  186. package/lib/types/payloads/_interactions/responses.d.ts +2 -2
  187. package/lib/types/payloads/components.d.ts +4 -4
  188. package/lib/websocket/SharedTypes.d.ts +4 -4
  189. package/lib/websocket/constants/index.js +2 -1
  190. package/lib/websocket/discord/events/memberUpdate.js +2 -2
  191. package/lib/websocket/discord/heartbeater.d.ts +1 -0
  192. package/lib/websocket/discord/heartbeater.js +7 -0
  193. package/lib/websocket/discord/shard.d.ts +2 -2
  194. package/lib/websocket/discord/shard.js +10 -8
  195. package/lib/websocket/discord/sharder.d.ts +8 -7
  196. package/lib/websocket/discord/sharder.js +25 -5
  197. package/lib/websocket/discord/shared.d.ts +19 -6
  198. package/lib/websocket/discord/socket/custom.js +5 -0
  199. package/lib/websocket/discord/worker.d.ts +1 -0
  200. package/lib/websocket/discord/worker.js +2 -0
  201. package/lib/websocket/discord/workermanager.d.ts +22 -8
  202. package/lib/websocket/discord/workermanager.js +41 -10
  203. package/package.json +5 -3
@@ -21,7 +21,7 @@ export interface CDNRoute {
21
21
  splashes(guildId: string): {
22
22
  get(hash: string, options?: BaseCDNUrlOptions): string;
23
23
  };
24
- 'discovery-splashes'(guidId: string): {
24
+ 'discovery-splashes'(guildId: string): {
25
25
  get(hash: string, options?: BaseCDNUrlOptions): string;
26
26
  };
27
27
  banners(id: string): {
@@ -82,4 +82,4 @@ export interface CDNRoute {
82
82
  };
83
83
  };
84
84
  }
85
- export type UserAvatarDefault = 1 | 2 | 3 | 4 | 5 | number;
85
+ export type UserAvatarDefault = 0 | 1 | 2 | 3 | 4 | 5;
@@ -1,6 +1,6 @@
1
1
  import type { Identify, OmitInsert } from '../../common';
2
2
  import type { APIThreadChannel, RESTDeleteAPIAutoModerationRuleResult, RESTDeleteAPIGuildBanResult, RESTDeleteAPIGuildEmojiResult, RESTDeleteAPIGuildIntegrationResult, RESTDeleteAPIGuildMemberResult, RESTDeleteAPIGuildMemberRoleResult, RESTDeleteAPIGuildResult, RESTDeleteAPIGuildRoleResult, RESTDeleteAPIGuildScheduledEventResult, RESTDeleteAPIGuildStickerResult, RESTDeleteAPIGuildTemplateResult, RESTGetAPIAuditLogQuery, RESTGetAPIAuditLogResult, RESTGetAPIAutoModerationRuleResult, RESTGetAPIAutoModerationRulesResult, RESTGetAPIGuildBanResult, RESTGetAPIGuildBansQuery, RESTGetAPIGuildBansResult, RESTGetAPIGuildChannelsResult, RESTGetAPIGuildEmojiResult, RESTGetAPIGuildEmojisResult, RESTGetAPIGuildIntegrationsResult, RESTGetAPIGuildInvitesResult, RESTGetAPIGuildMemberResult, RESTGetAPIGuildMembersQuery, RESTGetAPIGuildMembersResult, RESTGetAPIGuildMembersSearchQuery, RESTGetAPIGuildMembersSearchResult, RESTGetAPIGuildMessagesSearchQuery, RESTGetAPIGuildMessagesSearchResult, RESTGetAPIGuildPreviewResult, RESTGetAPIGuildPruneCountQuery, RESTGetAPIGuildPruneCountResult, RESTGetAPIGuildQuery, RESTGetAPIGuildResult, RESTGetAPIGuildRoleMemberCountsResult, RESTGetAPIGuildRoleResult, RESTGetAPIGuildRolesResult, RESTGetAPIGuildScheduledEventQuery, RESTGetAPIGuildScheduledEventResult, RESTGetAPIGuildScheduledEventsQuery, RESTGetAPIGuildScheduledEventsResult, RESTGetAPIGuildScheduledEventUsersQuery, RESTGetAPIGuildScheduledEventUsersResult, RESTGetAPIGuildSoundboardSoundsResult, RESTGetAPIGuildStickerResult, RESTGetAPIGuildStickersResult, RESTGetAPIGuildTemplatesResult, RESTGetAPIGuildThreadsResult, RESTGetAPIGuildVanityUrlResult, RESTGetAPIGuildVoiceRegionsResult, RESTGetAPIGuildVoiceStateCurrentMemberResult, RESTGetAPIGuildVoiceStateUserResult, RESTGetAPIGuildWebhooksResult, RESTGetAPIGuildWelcomeScreenResult, RESTGetAPIGuildWidgetImageQuery, RESTGetAPIGuildWidgetImageResult, RESTGetAPIGuildWidgetJSONResult, RESTGetAPIGuildWidgetSettingsResult, RESTGetAPITemplateResult, RESTPatchAPIAutoModerationRuleJSONBody, RESTPatchAPIAutoModerationRuleResult, RESTPatchAPICurrentGuildMemberJSONBody, RESTPatchAPIGuildChannelPositionsJSONBody, RESTPatchAPIGuildChannelPositionsResult, RESTPatchAPIGuildEmojiJSONBody, RESTPatchAPIGuildEmojiResult, RESTPatchAPIGuildJSONBody, RESTPatchAPIGuildMemberJSONBody, RESTPatchAPIGuildMemberResult, RESTPatchAPIGuildResult, RESTPatchAPIGuildRoleJSONBody, RESTPatchAPIGuildRolePositionsJSONBody, RESTPatchAPIGuildRolePositionsResult, RESTPatchAPIGuildRoleResult, RESTPatchAPIGuildScheduledEventJSONBody, RESTPatchAPIGuildScheduledEventResult, RESTPatchAPIGuildSoundboardSoundJSONBody, RESTPatchAPIGuildSoundboardSoundResult, RESTPatchAPIGuildStickerJSONBody, RESTPatchAPIGuildStickerResult, RESTPatchAPIGuildTemplateJSONBody, RESTPatchAPIGuildTemplateResult, RESTPatchAPIGuildVoiceStateCurrentMemberJSONBody, RESTPatchAPIGuildVoiceStateCurrentMemberResult, RESTPatchAPIGuildVoiceStateUserJSONBody, RESTPatchAPIGuildVoiceStateUserResult, RESTPatchAPIGuildWelcomeScreenJSONBody, RESTPatchAPIGuildWelcomeScreenResult, RESTPatchAPIGuildWidgetSettingsJSONBody, RESTPatchAPIGuildWidgetSettingsResult, RESTPostAPIAutoModerationRuleJSONBody, RESTPostAPIAutoModerationRuleResult, RESTPostAPIGuildBulkBanJSONBody, RESTPostAPIGuildBulkBanResult, RESTPostAPIGuildChannelJSONBody, RESTPostAPIGuildChannelResult, RESTPostAPIGuildEmojiJSONBody, RESTPostAPIGuildEmojiResult, RESTPostAPIGuildPruneJSONBody, RESTPostAPIGuildPruneResult, RESTPostAPIGuildRoleJSONBody, RESTPostAPIGuildRoleResult, RESTPostAPIGuildScheduledEventJSONBody, RESTPostAPIGuildScheduledEventResult, RESTPostAPIGuildSoundboardSoundJSONBody, RESTPostAPIGuildSoundboardSoundResult, RESTPostAPIGuildStickerFormDataBody, RESTPostAPIGuildStickerResult, RESTPostAPIGuildsMFAJSONBody, RESTPostAPIGuildsMFAResult, RESTPostAPIGuildTemplatesJSONBody, RESTPostAPIGuildTemplatesResult, RESTPostAPITemplateCreateGuildJSONBody, RESTPostAPITemplateCreateGuildResult, RESTPutAPIGuildBanJSONBody, RESTPutAPIGuildBanResult, RESTPutAPIGuildMemberJSONBody, RESTPutAPIGuildMemberResult, RESTPutAPIGuildMemberRoleResult, RESTPutAPIGuildTemplateSyncResult } from '../../types';
3
- import type { RestArguments, RestArgumentsNoBody } from '../api';
3
+ import type { RestArguments, RestArgumentsNoBody, RestArgumentsRequiredQuery } from '../api';
4
4
  import type { RawFile } from '../shared';
5
5
  export interface GuildRoutes {
6
6
  guilds: {
@@ -40,7 +40,7 @@ export interface GuildRoutes {
40
40
  members: {
41
41
  get(args?: RestArgumentsNoBody<RESTGetAPIGuildMembersQuery>): Promise<RESTGetAPIGuildMembersResult>;
42
42
  search: {
43
- get(args: RestArgumentsNoBody<RESTGetAPIGuildMembersSearchQuery>): Promise<RESTGetAPIGuildMembersSearchResult>;
43
+ get(args: RestArgumentsRequiredQuery<RESTGetAPIGuildMembersSearchQuery>): Promise<RESTGetAPIGuildMembersSearchResult>;
44
44
  };
45
45
  '@me': {
46
46
  patch(args: RestArguments<RESTPatchAPICurrentGuildMemberJSONBody>): Promise<RESTGetAPIGuildMemberResult>;
package/lib/api/api.d.ts CHANGED
@@ -1,16 +1,17 @@
1
1
  import { type UUID } from 'node:crypto';
2
2
  import { type Awaitable, Logger, SeyfertError } from '../common';
3
- import type { WorkerSendApiRequest } from '../websocket/discord/worker';
3
+ import { type WorkerSendApiRequest } from '../websocket/discord/worker';
4
4
  import { Bucket } from './bucket';
5
5
  import type { APIRoutes } from './Routes';
6
- import { type ApiHandlerInternalOptions, type ApiHandlerOptions, type ApiRequestOptions, type HttpMethods, type RawFile, type RequestHeaders } from './shared';
7
- export interface ApiHandler {
6
+ import { type ApiHandlerInternalOptions, type ApiHandlerOptions, type ApiRequestOptions, type HttpMethods, type RawFile, type RequestHeaders, type RestObserveOptions, type RestObserver, type RestObserverDisposer, type RestObserverEntry } from './shared';
7
+ export type { RestObserveOptions, RestObserver, RestObserverDisposer, RestObserverEntry, RestObserverFailPayload, RestObserverRatelimitPayload, RestObserverRequestPayload, RestObserverSuccessPayload, } from './shared';
8
+ export interface ApiHandler<TClient = unknown> {
8
9
  debugger?: Logger;
9
10
  }
10
11
  export type OnRatelimitCallback = (response: Response, request: ApiRequestOptions) => Awaitable<any>;
11
12
  export type OnSuccessRequestCallback = (method: HttpMethods, url: `/${string}`, response: Response) => Awaitable<any>;
12
13
  export type OnFailRequestCallback = (method: HttpMethods, url: `/${string}`, error: unknown, statusCode?: number) => Awaitable<any>;
13
- export declare class ApiHandler {
14
+ export declare class ApiHandler<TClient = unknown> {
14
15
  options: ApiHandlerInternalOptions;
15
16
  globalBlock: boolean;
16
17
  ratelimits: Map<string, Bucket>;
@@ -23,22 +24,30 @@ export declare class ApiHandler {
23
24
  onRatelimit?: OnRatelimitCallback;
24
25
  onSuccessRequest?: OnSuccessRequestCallback;
25
26
  onFailRequest?: OnFailRequestCallback;
27
+ pluginRestObserverProvider?: () => readonly RestObserverEntry[];
28
+ pluginRestObserverClient?: TClient;
29
+ private restObservers;
26
30
  constructor(options: ApiHandlerOptions);
31
+ observe(observer: RestObserver<TClient>, _opts?: RestObserveOptions): RestObserverDisposer;
27
32
  set debug(active: boolean);
28
33
  get proxy(): APIRoutes;
29
34
  globalUnblock(): void;
30
35
  randomUUID(): UUID;
31
36
  protected sendMessage(_body: WorkerSendApiRequest): void;
32
37
  protected postMessage<T = unknown>(body: WorkerSendApiRequest): Promise<T>;
38
+ private notifyRequest;
33
39
  private notifySuccessRequest;
34
40
  private notifyFailRequest;
35
- request<T = unknown>(method: HttpMethods, url: `/${string}`, { auth, ...request }?: ApiRequestOptions): Promise<T>;
41
+ private notifyRatelimit;
42
+ private notifyRestObservers;
43
+ private notifyRestObserverEntries;
44
+ request<T = unknown>(method: HttpMethods, url: `/${string}`, request?: ApiRequestOptions): Promise<T>;
36
45
  parseError(method: HttpMethods, route: `/${string}`, response: Response, result: string | Record<string, any>, originTrace?: {
37
46
  stack?: string;
38
47
  }): SeyfertError;
39
48
  parseValidationError(data: Record<string, any>, path?: string, errors?: string[]): string[];
40
- handle50X(method: HttpMethods, url: `/${string}`, request: ApiRequestOptions, next: () => void): Promise<unknown>;
41
- handle429(route: string, method: HttpMethods, url: `/${string}`, request: ApiRequestOptions, response: Response, result: string, next: () => void, reject: (err: unknown) => void, now: number): Promise<unknown>;
49
+ handle50X(method: HttpMethods, url: `/${string}`, request: ApiRequestOptions, attempts: number | (() => void), next?: () => void, resolve?: (value: unknown) => void, reject?: (err: unknown) => void): Promise<unknown>;
50
+ handle429(route: string, method: HttpMethods, url: `/${string}`, request: ApiRequestOptions, response: Response, result: string, next: () => void, reject: (err: unknown) => void, now: number, notifyUrl: `/${string}`): Promise<unknown>;
42
51
  clearResetInterval(route: string): void;
43
52
  setResetBucket(route: string, resp: Response, now: number, headerNow: number): void;
44
53
  setRatelimitsBucket(route: string, resp: Response): void;
@@ -63,3 +72,6 @@ export type RestArgumentsNoBody<Q extends never | Record<string, any> = never> =
63
72
  query?: Q;
64
73
  files?: RawFile[];
65
74
  } & RequestOptions;
75
+ export type RestArgumentsRequiredQuery<Q extends Record<string, any>> = Omit<RestArgumentsNoBody<Q>, 'query'> & {
76
+ query: Q;
77
+ };
package/lib/api/api.js CHANGED
@@ -4,6 +4,7 @@ exports.ApiHandler = void 0;
4
4
  const node_crypto_1 = require("node:crypto");
5
5
  const common_1 = require("../common");
6
6
  const utils_1 = require("../common/it/utils");
7
+ const worker_1 = require("../websocket/discord/worker");
7
8
  const bucket_1 = require("./bucket");
8
9
  const Router_1 = require("./Router");
9
10
  const shared_1 = require("./shared");
@@ -18,6 +19,9 @@ class ApiHandler {
18
19
  onRatelimit;
19
20
  onSuccessRequest;
20
21
  onFailRequest;
22
+ pluginRestObserverProvider;
23
+ pluginRestObserverClient;
24
+ restObservers = new Map();
21
25
  constructor(options) {
22
26
  this.options = {
23
27
  baseUrl: 'api/v10',
@@ -59,6 +63,17 @@ class ApiHandler {
59
63
  };
60
64
  }
61
65
  }
66
+ observe(observer, _opts) {
67
+ const id = Symbol('rest-observer');
68
+ this.restObservers.set(id, { observer });
69
+ let disposed = false;
70
+ return () => {
71
+ if (disposed)
72
+ return;
73
+ disposed = true;
74
+ this.restObservers.delete(id);
75
+ };
76
+ }
62
77
  set debug(active) {
63
78
  this.debugger = active
64
79
  ? new common_1.Logger({
@@ -83,15 +98,45 @@ class ApiHandler {
83
98
  return uuid;
84
99
  }
85
100
  sendMessage(_body) {
86
- throw new common_1.SeyfertError('FUNCTION_NOT_IMPLEMENTED', { metadata: { detail: 'Function not implemented' } });
101
+ throw new common_1.SeyfertError('FUNCTION_NOT_IMPLEMENTED', {
102
+ metadata: { detail: 'Function not implemented' },
103
+ });
87
104
  }
88
105
  postMessage(body) {
89
106
  this.sendMessage(body);
90
107
  return new Promise((res, rej) => {
91
- this.workerPromises.set(body.nonce, { reject: rej, resolve: res });
108
+ const timeout = setTimeout(() => {
109
+ this.workerPromises.delete(body.nonce);
110
+ rej(new common_1.SeyfertError('WORKER_TIMEOUT', { metadata: { detail: `nonce: ${body.nonce}` } }));
111
+ }, worker_1.WORKER_TIMEOUT_MS);
112
+ this.workerPromises.set(body.nonce, {
113
+ resolve: value => {
114
+ clearTimeout(timeout);
115
+ res(value);
116
+ },
117
+ reject: reason => {
118
+ clearTimeout(timeout);
119
+ rej(reason);
120
+ },
121
+ });
92
122
  });
93
123
  }
94
- async notifySuccessRequest(method, url, response) {
124
+ async notifyRequest(method, url, request) {
125
+ await this.notifyRestObservers('onRequest', () => freezeRestPayload({
126
+ client: this.pluginRestObserverClient,
127
+ method,
128
+ url,
129
+ request: readonlyRequestOptions(request),
130
+ }));
131
+ }
132
+ async notifySuccessRequest(method, url, response, request) {
133
+ await this.notifyRestObservers('onSuccess', () => freezeRestPayload({
134
+ client: this.pluginRestObserverClient,
135
+ method,
136
+ url,
137
+ request: readonlyRequestOptions(request),
138
+ response,
139
+ }));
95
140
  try {
96
141
  await this.onSuccessRequest?.(method, url, response);
97
142
  }
@@ -99,7 +144,15 @@ class ApiHandler {
99
144
  this.debugger?.warn('onSuccessRequest callback error', error);
100
145
  }
101
146
  }
102
- async notifyFailRequest(method, url, error, statusCode) {
147
+ async notifyFailRequest(method, url, error, statusCode, request) {
148
+ await this.notifyRestObservers('onFail', () => freezeRestPayload({
149
+ client: this.pluginRestObserverClient,
150
+ method,
151
+ url,
152
+ request: readonlyRequestOptions(request),
153
+ error,
154
+ statusCode,
155
+ }));
103
156
  try {
104
157
  await this.onFailRequest?.(method, url, error, statusCode);
105
158
  }
@@ -107,7 +160,54 @@ class ApiHandler {
107
160
  this.debugger?.warn('onFailRequest callback error', callbackError);
108
161
  }
109
162
  }
110
- async request(method, url, { auth = true, ...request } = {}) {
163
+ async notifyRatelimit(response, request, method, url) {
164
+ await this.notifyRestObservers('onRatelimit', () => freezeRestPayload({
165
+ client: this.pluginRestObserverClient,
166
+ method,
167
+ url,
168
+ request: readonlyRequestOptions(request),
169
+ response,
170
+ }));
171
+ try {
172
+ await this.onRatelimit?.(response, request);
173
+ }
174
+ catch (error) {
175
+ this.debugger?.warn('onRatelimit callback error', error);
176
+ }
177
+ }
178
+ async notifyRestObservers(name, createPayload) {
179
+ let payload;
180
+ let hasPayload = false;
181
+ const getPayload = () => {
182
+ if (!hasPayload) {
183
+ payload = createPayload();
184
+ hasPayload = true;
185
+ }
186
+ return payload;
187
+ };
188
+ await this.notifyRestObserverEntries(name, getPayload, this.pluginRestObserverProvider?.() ?? []);
189
+ await this.notifyRestObserverEntries(name, getPayload, this.restObservers.values());
190
+ }
191
+ async notifyRestObserverEntries(name, getPayload, entries) {
192
+ for (const entry of entries) {
193
+ const observer = entry.observer[name];
194
+ if (!observer)
195
+ continue;
196
+ const payload = getPayload();
197
+ try {
198
+ await observer(payload);
199
+ }
200
+ catch (error) {
201
+ const source = entry.plugin ? `[plugin:${entry.plugin}] ` : '';
202
+ this.debugger?.warn(`${source}REST observer "${name}" callback error`, error);
203
+ }
204
+ }
205
+ }
206
+ async request(method, url, request = {}) {
207
+ const requestOptions = { ...request };
208
+ const { auth = true } = requestOptions;
209
+ let attempts = requestOptions._50xRetries ?? 0;
210
+ delete requestOptions._50xRetries;
111
211
  const originTrace = {};
112
212
  Error.captureStackTrace(originTrace, this.request);
113
213
  if (this.options.workerProxy) {
@@ -118,23 +218,32 @@ class ApiHandler {
118
218
  type: 'WORKER_API_REQUEST',
119
219
  workerId: this.workerData.workerId,
120
220
  nonce,
121
- requestOptions: { auth, ...request },
221
+ requestOptions: { auth, ...requestOptions },
122
222
  });
123
223
  }
124
- const route = request.route || this.routefy(url, method);
125
- let attempts = 0;
224
+ const route = requestOptions.route || this.routefy(url, method);
126
225
  const callback = async (next, resolve, reject) => {
127
226
  const headers = {
128
227
  'User-Agent': this.options.userAgent,
129
228
  };
130
- const { data, finalUrl } = this.parseRequest({
131
- url,
132
- headers,
133
- request: { ...request, auth },
134
- });
229
+ let data;
230
+ let finalUrl;
231
+ try {
232
+ ({ data, finalUrl } = this.parseRequest({
233
+ url,
234
+ headers,
235
+ request: { ...requestOptions, auth },
236
+ }));
237
+ }
238
+ catch (err) {
239
+ next();
240
+ reject(err);
241
+ return;
242
+ }
135
243
  let response;
136
244
  try {
137
245
  const requestUrl = `${this.options.domain}/${this.options.baseUrl}${finalUrl}`;
246
+ await this.notifyRequest(method, finalUrl, { ...request, auth });
138
247
  this.debugger?.debug(`Sending, Method: ${method} | Url: [${finalUrl}](${route}) | Auth: ${auth}`);
139
248
  response = await fetch(requestUrl, {
140
249
  method,
@@ -145,7 +254,7 @@ class ApiHandler {
145
254
  }
146
255
  catch (err) {
147
256
  this.debugger?.debug('Fetch error', err);
148
- await this.notifyFailRequest(method, finalUrl, err);
257
+ await this.notifyFailRequest(method, finalUrl, err, undefined, { ...request, auth });
149
258
  next();
150
259
  reject(err);
151
260
  return;
@@ -154,18 +263,19 @@ class ApiHandler {
154
263
  const headerNow = Date.parse(response.headers.get('date') ?? '');
155
264
  this.setRatelimitsBucket(route, response);
156
265
  this.setResetBucket(route, response, now, headerNow);
266
+ const observerResponse = response.clone();
157
267
  let result = await response.text();
158
268
  if (response.status >= 300) {
159
269
  if (response.status === 429) {
160
- const result429 = await this.handle429(route, method, url, request, response, result, next, reject, now);
270
+ const result429 = await this.handle429(route, method, url, { ...request, auth }, observerResponse, result, next, reject, now, finalUrl);
161
271
  if (result429 !== false)
162
272
  return resolve(result429);
163
- await this.notifyFailRequest(method, finalUrl, result, response.status);
273
+ await this.notifyFailRequest(method, finalUrl, result, response.status, { ...request, auth });
164
274
  return this.clearResetInterval(route);
165
275
  }
166
276
  if ([502, 503].includes(response.status) && ++attempts < 4) {
167
277
  this.clearResetInterval(route);
168
- return this.handle50X(method, url, request, next);
278
+ return this.handle50X(method, url, requestOptions, attempts, next, resolve, reject);
169
279
  }
170
280
  this.clearResetInterval(route);
171
281
  next();
@@ -176,7 +286,7 @@ class ApiHandler {
176
286
  }
177
287
  catch (err) {
178
288
  this.debugger?.warn('SeyfertError parsing result error (', result, ')', err);
179
- await this.notifyFailRequest(method, finalUrl, err, response.status);
289
+ await this.notifyFailRequest(method, finalUrl, err, response.status, { ...request, auth });
180
290
  reject(err);
181
291
  return;
182
292
  }
@@ -184,7 +294,7 @@ class ApiHandler {
184
294
  }
185
295
  const parsedError = this.parseError(method, route, response, result, originTrace);
186
296
  this.debugger?.warn(parsedError.message);
187
- await this.notifyFailRequest(method, finalUrl, parsedError, response.status);
297
+ await this.notifyFailRequest(method, finalUrl, parsedError, response.status, { ...request, auth });
188
298
  reject(parsedError);
189
299
  return;
190
300
  }
@@ -195,14 +305,14 @@ class ApiHandler {
195
305
  }
196
306
  catch (err) {
197
307
  this.debugger?.warn('Failed parsing result (', result, ')', err);
198
- await this.notifyFailRequest(method, finalUrl, err, response.status);
308
+ await this.notifyFailRequest(method, finalUrl, err, response.status, { ...request, auth });
199
309
  next();
200
310
  reject(err);
201
311
  return;
202
312
  }
203
313
  }
204
314
  }
205
- await this.notifySuccessRequest(method, finalUrl, response);
315
+ await this.notifySuccessRequest(method, finalUrl, observerResponse, { ...request, auth });
206
316
  next();
207
317
  return resolve(result || undefined);
208
318
  };
@@ -279,21 +389,30 @@ class ApiHandler {
279
389
  }
280
390
  return errors;
281
391
  }
282
- async handle50X(method, url, request, next) {
392
+ async handle50X(method, url, request, attempts, next = () => { }, resolve, reject) {
393
+ const retryAttempt = typeof attempts === 'number' ? attempts : 0;
394
+ const callback = typeof attempts === 'function' ? attempts : next;
395
+ const requestOptions = {
396
+ ...request,
397
+ unshift: true,
398
+ ...(retryAttempt > 0 ? { _50xRetries: retryAttempt } : {}),
399
+ };
283
400
  const wait = Math.floor(Math.random() * 1900 + 100);
284
401
  this.debugger?.warn(`Handling a 50X status, retrying in ${wait}ms`);
285
- next();
402
+ callback();
286
403
  await (0, common_1.delay)(wait);
287
- return this.request(method, url, {
288
- body: request.body,
289
- auth: request.auth,
290
- reason: request.reason,
291
- route: request.route,
292
- unshift: true,
404
+ return this.request(method, url, requestOptions)
405
+ .then(value => {
406
+ resolve?.(value);
407
+ return value;
408
+ })
409
+ .catch(error => {
410
+ reject?.(error);
411
+ throw error;
293
412
  });
294
413
  }
295
- async handle429(route, method, url, request, response, result, next, reject, now) {
296
- await this.onRatelimit?.(response, request);
414
+ async handle429(route, method, url, request, response, result, next, reject, now, notifyUrl) {
415
+ await this.notifyRatelimit(response, request, method, notifyUrl);
297
416
  const bucket = this.ratelimits.get(route);
298
417
  let retryAfter;
299
418
  const data = JSON.parse(result);
@@ -325,19 +444,13 @@ class ApiHandler {
325
444
  await (0, common_1.delay)(retryAfter);
326
445
  next();
327
446
  return this.request(method, url, {
328
- body: request.body,
329
- auth: request.auth,
330
- reason: request.reason,
331
- route: request.route,
447
+ ...request,
332
448
  unshift: true,
333
449
  });
334
450
  }
335
451
  next();
336
452
  return this.request(method, url, {
337
- body: request.body,
338
- auth: request.auth,
339
- reason: request.reason,
340
- route: request.route,
453
+ ...request,
341
454
  unshift: true,
342
455
  });
343
456
  }
@@ -372,8 +485,8 @@ class ApiHandler {
372
485
  if (resp.headers.has('x-ratelimit-limit')) {
373
486
  this.ratelimits.get(route).limit = +resp.headers.get('x-ratelimit-limit');
374
487
  }
375
- this.ratelimits.get(route).remaining =
376
- resp.headers.get('x-ratelimit-remaining') === undefined ? 1 : +resp.headers.get('x-ratelimit-remaining');
488
+ const raw = resp.headers.get('x-ratelimit-remaining');
489
+ this.ratelimits.get(route).remaining = raw != null ? +raw : 1;
377
490
  if (this.options.smartBucket) {
378
491
  if (resp.headers.has('x-ratelimit-reset-after') &&
379
492
  !this.ratelimits.get(route).resetAfter &&
@@ -389,7 +502,11 @@ class ApiHandler {
389
502
  let finalUrl = options.url;
390
503
  let data;
391
504
  if (options.request.auth) {
392
- options.headers.Authorization = `${this.options.type} ${options.request.token || this.options.token}`;
505
+ const token = options.request.token || this.options.token;
506
+ if (token === 'INVALID' || typeof token !== 'string' || token.length === 0) {
507
+ throw new common_1.SeyfertError('INVALID_TOKEN', { metadata: { detail: 'token is not a string' } });
508
+ }
509
+ options.headers.Authorization = `${this.options.type} ${token}`;
393
510
  }
394
511
  if (options.request.query) {
395
512
  const params = new URLSearchParams();
@@ -449,7 +566,7 @@ class ApiHandler {
449
566
  .replace(/^\/webhooks\/(\d+)\/[A-Za-z0-9-_]{64,}/, '/webhooks/$1/:token');
450
567
  if (method === 'DELETE' && route.endsWith('/messages/:id')) {
451
568
  const messageID = url.slice(url.lastIndexOf('/') + 1);
452
- const createdAt = Number((0, common_1.snowflakeToTimestamp)(messageID));
569
+ const createdAt = (0, common_1.snowflakeToTimestamp)(messageID);
453
570
  if (Date.now() - createdAt >= 1000 * 60 * 60 * 24 * 14) {
454
571
  method += '_OLD';
455
572
  }
@@ -471,3 +588,40 @@ class ApiHandler {
471
588
  }
472
589
  }
473
590
  exports.ApiHandler = ApiHandler;
591
+ function freezeRestPayload(payload) {
592
+ return Object.freeze(payload);
593
+ }
594
+ function readonlyRequestOptions(request) {
595
+ const clone = deepClonePlain({
596
+ ...request,
597
+ body: request.body ? deepClonePlain(request.body) : undefined,
598
+ query: request.query ? deepClonePlain(request.query) : undefined,
599
+ files: request.files?.map(file => deepClonePlain(file)),
600
+ });
601
+ return deepFreezePlain(clone);
602
+ }
603
+ function deepClonePlain(value) {
604
+ if (Array.isArray(value))
605
+ return value.map(deepClonePlain);
606
+ if (!isPlainObject(value))
607
+ return value;
608
+ return Object.fromEntries(Object.entries(value).map(([key, entry]) => [key, deepClonePlain(entry)]));
609
+ }
610
+ function deepFreezePlain(value) {
611
+ if (Array.isArray(value)) {
612
+ for (const entry of value)
613
+ deepFreezePlain(entry);
614
+ return Object.freeze(value);
615
+ }
616
+ if (!isPlainObject(value))
617
+ return value;
618
+ for (const entry of Object.values(value))
619
+ deepFreezePlain(entry);
620
+ return Object.freeze(value);
621
+ }
622
+ function isPlainObject(value) {
623
+ if (typeof value !== 'object' || value === null)
624
+ return false;
625
+ const prototype = Object.getPrototypeOf(value);
626
+ return prototype === Object.prototype || prototype === null;
627
+ }
@@ -1,4 +1,4 @@
1
- import type { MakeRequired } from '../common';
1
+ import type { Awaitable, MakeRequired } from '../common';
2
2
  export * from './api';
3
3
  export * from './utils/constants';
4
4
  export * from './utils/types';
@@ -34,3 +34,32 @@ export interface ApiRequestOptions {
34
34
  token?: string;
35
35
  }
36
36
  export type HttpMethods = 'GET' | 'DELETE' | 'PUT' | 'POST' | 'PATCH';
37
+ export interface RestObserverRequestPayload<TClient = unknown> {
38
+ readonly client: TClient;
39
+ readonly method: HttpMethods;
40
+ readonly url: `/${string}`;
41
+ readonly request: Readonly<ApiRequestOptions>;
42
+ }
43
+ export interface RestObserverSuccessPayload<TClient = unknown> extends RestObserverRequestPayload<TClient> {
44
+ readonly response: Response;
45
+ }
46
+ export interface RestObserverFailPayload<TClient = unknown> extends RestObserverRequestPayload<TClient> {
47
+ readonly error: unknown;
48
+ readonly statusCode?: number;
49
+ }
50
+ export interface RestObserverRatelimitPayload<TClient = unknown> extends RestObserverRequestPayload<TClient> {
51
+ readonly response: Response;
52
+ }
53
+ export interface RestObserver<TClient = unknown> {
54
+ onRequest?(payload: RestObserverRequestPayload<TClient>): Awaitable<unknown>;
55
+ onSuccess?(payload: RestObserverSuccessPayload<TClient>): Awaitable<unknown>;
56
+ onFail?(payload: RestObserverFailPayload<TClient>): Awaitable<unknown>;
57
+ onRatelimit?(payload: RestObserverRatelimitPayload<TClient>): Awaitable<unknown>;
58
+ }
59
+ export interface RestObserverEntry<TClient = unknown> {
60
+ readonly plugin?: string;
61
+ readonly observer: RestObserver<TClient>;
62
+ }
63
+ export interface RestObserveOptions {
64
+ }
65
+ export type RestObserverDisposer = () => void;
@@ -1,4 +1,4 @@
1
- export declare const DefaultUserAgent: "DiscordBot (https://seyfert.dev, v4.4.0)";
1
+ export declare const DefaultUserAgent: "DiscordBot (https://seyfert.dev, v4.0.0)";
2
2
  export declare const ALLOWED_EXTENSIONS: readonly ["webp", "png", "jpg", "jpeg", "gif"];
3
3
  export declare const ALLOWED_STICKER_EXTENSIONS: readonly ["png", "json", "gif"];
4
4
  export declare const ALLOWED_SIZES: readonly [16, 32, 64, 100, 128, 256, 512, 1024, 2048, 4096];
@@ -1,7 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.ALLOWED_TAG_BADGE_EXTENSIONS = exports.ALLOWED_SOUNDS_EXTENSIONS = exports.ALLOWED_SIZES = exports.ALLOWED_STICKER_EXTENSIONS = exports.ALLOWED_EXTENSIONS = exports.DefaultUserAgent = void 0;
4
- exports.DefaultUserAgent = 'DiscordBot (https://seyfert.dev, v4.4.0)';
4
+ exports.DefaultUserAgent = 'DiscordBot (https://seyfert.dev, v4.0.0)';
5
5
  exports.ALLOWED_EXTENSIONS = ['webp', 'png', 'jpg', 'jpeg', 'gif'];
6
6
  exports.ALLOWED_STICKER_EXTENSIONS = ['png', 'json', 'gif'];
7
7
  exports.ALLOWED_SIZES = [16, 32, 64, 100, 128, 256, 512, 1_024, 2_048, 4_096];
@@ -1,10 +1,11 @@
1
1
  import type { Snowflake } from '../../types';
2
+ import type { UserAvatarDefault } from '../Routes/cdn';
2
3
  /**
3
4
  * Calculates the default avatar index for a given user id.
4
5
  *
5
6
  * @param userId - The user id to calculate the default avatar index for
6
7
  */
7
- export declare function calculateUserDefaultAvatarIndex(userId: Snowflake, discriminator: string): number;
8
+ export declare function calculateUserDefaultAvatarIndex(userId: Snowflake, discriminator: string): UserAvatarDefault;
8
9
  /**
9
10
  * Verifies that a value is a buffer-like object.
10
11
  *
@@ -8,7 +8,7 @@ exports.isBufferLike = isBufferLike;
8
8
  * @param userId - The user id to calculate the default avatar index for
9
9
  */
10
10
  function calculateUserDefaultAvatarIndex(userId, discriminator) {
11
- return discriminator === '0' ? Number(BigInt(userId) >> 22n) % 6 : Number.parseInt(discriminator) % 5;
11
+ return (discriminator === '0' ? Number(BigInt(userId) >> 22n) % 6 : Number.parseInt(discriminator) % 5);
12
12
  }
13
13
  /**
14
14
  * Verifies that a value is a buffer-like object.
@@ -101,7 +101,7 @@ export declare function resolveAttachmentData(data: AttachmentResolvable, type:
101
101
  * @param data - The base64 data.
102
102
  * @returns The resolved data URL.
103
103
  */
104
- export declare function resolveBase64(data: string | Buffer): string;
104
+ export declare function resolveBase64(data: string | Buffer, contentType?: string): string;
105
105
  /**
106
106
  * Resolves an image to a base64 data URL.
107
107
  * @param image - The image to resolve.