chapterjs 0.1.2 → 0.1.4

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 (320) hide show
  1. package/dist/assets/asset.d.ts +46 -0
  2. package/dist/assets/asset.js +86 -0
  3. package/dist/assets/public.d.ts +19 -0
  4. package/dist/assets/public.js +120 -0
  5. package/dist/cache/cache.d.ts +62 -0
  6. package/dist/cache/cache.js +80 -0
  7. package/dist/cache/store.d.ts +45 -0
  8. package/dist/cache/store.js +53 -0
  9. package/dist/cli/build.d.ts +41 -0
  10. package/dist/cli/build.js +206 -0
  11. package/dist/cli/cli.js +108 -25
  12. package/dist/cli/cluster.d.ts +70 -0
  13. package/dist/cli/cluster.js +213 -0
  14. package/dist/cli/dev.d.ts +18 -1
  15. package/dist/cli/dev.js +252 -198
  16. package/dist/cli/env.d.ts +31 -0
  17. package/dist/cli/env.js +93 -0
  18. package/dist/cli/log.d.ts +13 -0
  19. package/dist/cli/log.js +17 -0
  20. package/dist/cli/node-version.d.ts +8 -0
  21. package/dist/cli/node-version.js +13 -0
  22. package/dist/cli/preflight.d.ts +36 -0
  23. package/dist/cli/preflight.js +122 -0
  24. package/dist/cli/project.d.ts +122 -0
  25. package/dist/cli/project.js +452 -0
  26. package/dist/cli/start.d.ts +25 -0
  27. package/dist/cli/start.js +225 -0
  28. package/dist/commands/autocomplete.d.ts +13 -0
  29. package/dist/commands/autocomplete.js +159 -0
  30. package/dist/commands/command.d.ts +346 -0
  31. package/dist/commands/command.js +28 -0
  32. package/dist/commands/convention.d.ts +64 -0
  33. package/dist/commands/convention.js +464 -0
  34. package/dist/commands/register.d.ts +18 -0
  35. package/dist/commands/register.js +42 -0
  36. package/dist/commands/router.d.ts +20 -0
  37. package/dist/commands/router.js +228 -0
  38. package/dist/commands/tree.d.ts +43 -0
  39. package/dist/commands/tree.js +206 -0
  40. package/dist/commands/twins.d.ts +15 -0
  41. package/dist/commands/twins.js +78 -0
  42. package/dist/components/button.d.ts +79 -0
  43. package/dist/components/button.js +108 -0
  44. package/dist/components/component.d.ts +140 -0
  45. package/dist/components/component.js +39 -0
  46. package/dist/components/convention.d.ts +35 -0
  47. package/dist/components/convention.js +339 -0
  48. package/dist/components/custom-id.d.ts +72 -0
  49. package/dist/components/custom-id.js +128 -0
  50. package/dist/components/embed.d.ts +28 -0
  51. package/dist/components/embed.js +11 -0
  52. package/dist/components/file.d.ts +30 -0
  53. package/dist/components/file.js +52 -0
  54. package/dist/components/instance.d.ts +100 -0
  55. package/dist/components/instance.js +86 -0
  56. package/dist/components/layout.d.ts +103 -0
  57. package/dist/components/layout.js +279 -0
  58. package/dist/components/modal.d.ts +244 -0
  59. package/dist/components/modal.js +399 -0
  60. package/dist/components/options.d.ts +41 -0
  61. package/dist/components/options.js +101 -0
  62. package/dist/components/render.d.ts +12 -0
  63. package/dist/components/render.js +58 -0
  64. package/dist/components/router.d.ts +18 -0
  65. package/dist/components/router.js +256 -0
  66. package/dist/components/select.d.ts +144 -0
  67. package/dist/components/select.js +179 -0
  68. package/dist/core/bot.d.ts +99 -0
  69. package/dist/core/bot.js +174 -0
  70. package/dist/core/memory.d.ts +66 -0
  71. package/dist/core/memory.js +115 -0
  72. package/dist/discord/api.d.ts +112 -0
  73. package/dist/discord/api.js +115 -0
  74. package/dist/discord/cdn.d.ts +67 -0
  75. package/dist/discord/cdn.js +100 -0
  76. package/dist/discord/codes.d.ts +171 -0
  77. package/dist/discord/codes.js +421 -0
  78. package/dist/discord/endpoint.d.ts +56 -0
  79. package/dist/discord/endpoint.js +53 -0
  80. package/dist/discord/endpoints.d.ts +1529 -0
  81. package/dist/discord/endpoints.js +1139 -0
  82. package/dist/discord/formatting.d.ts +67 -0
  83. package/dist/discord/formatting.js +87 -0
  84. package/dist/discord/index.d.ts +10 -0
  85. package/dist/discord/index.js +13 -0
  86. package/dist/discord/intents.d.ts +48 -0
  87. package/dist/discord/intents.js +128 -0
  88. package/dist/discord/permissions.d.ts +94 -0
  89. package/dist/discord/permissions.js +185 -0
  90. package/dist/discord/snowflake.d.ts +21 -0
  91. package/dist/discord/snowflake.js +36 -0
  92. package/dist/discord/types/application-command.d.ts +332 -0
  93. package/dist/discord/types/application-command.js +48 -0
  94. package/dist/discord/types/application-role-connection-metadata.d.ts +42 -0
  95. package/dist/discord/types/application-role-connection-metadata.js +22 -0
  96. package/dist/discord/types/application.d.ts +208 -0
  97. package/dist/discord/types/application.js +48 -0
  98. package/dist/discord/types/audit-log.d.ts +255 -0
  99. package/dist/discord/types/audit-log.js +144 -0
  100. package/dist/discord/types/auto-moderation.d.ts +167 -0
  101. package/dist/discord/types/auto-moderation.js +52 -0
  102. package/dist/discord/types/channel.d.ts +557 -0
  103. package/dist/discord/types/channel.js +88 -0
  104. package/dist/discord/types/common.d.ts +54 -0
  105. package/dist/discord/types/common.js +38 -0
  106. package/dist/discord/types/component.d.ts +775 -0
  107. package/dist/discord/types/component.js +76 -0
  108. package/dist/discord/types/emoji.d.ts +74 -0
  109. package/dist/discord/types/emoji.js +1 -0
  110. package/dist/discord/types/entitlement.d.ts +84 -0
  111. package/dist/discord/types/entitlement.js +22 -0
  112. package/dist/discord/types/gateway-events.d.ts +1148 -0
  113. package/dist/discord/types/gateway-events.js +54 -0
  114. package/dist/discord/types/gateway.d.ts +38 -0
  115. package/dist/discord/types/gateway.js +1 -0
  116. package/dist/discord/types/guild-scheduled-event.d.ts +257 -0
  117. package/dist/discord/types/guild-scheduled-event.js +68 -0
  118. package/dist/discord/types/guild-template.d.ts +51 -0
  119. package/dist/discord/types/guild-template.js +1 -0
  120. package/dist/discord/types/guild.d.ts +910 -0
  121. package/dist/discord/types/guild.js +153 -0
  122. package/dist/discord/types/index.d.ts +31 -0
  123. package/dist/discord/types/index.js +31 -0
  124. package/dist/discord/types/interaction.d.ts +321 -0
  125. package/dist/discord/types/interaction.js +47 -0
  126. package/dist/discord/types/invite.d.ts +158 -0
  127. package/dist/discord/types/invite.js +39 -0
  128. package/dist/discord/types/message.d.ts +834 -0
  129. package/dist/discord/types/message.js +159 -0
  130. package/dist/discord/types/oauth2.d.ts +22 -0
  131. package/dist/discord/types/oauth2.js +1 -0
  132. package/dist/discord/types/permissions.d.ts +183 -0
  133. package/dist/discord/types/permissions.js +118 -0
  134. package/dist/discord/types/poll.d.ts +106 -0
  135. package/dist/discord/types/poll.js +8 -0
  136. package/dist/discord/types/sku.d.ts +47 -0
  137. package/dist/discord/types/sku.js +26 -0
  138. package/dist/discord/types/soundboard.d.ts +71 -0
  139. package/dist/discord/types/soundboard.js +1 -0
  140. package/dist/discord/types/stage-instance.d.ts +58 -0
  141. package/dist/discord/types/stage-instance.js +10 -0
  142. package/dist/discord/types/sticker.d.ts +115 -0
  143. package/dist/discord/types/sticker.js +20 -0
  144. package/dist/discord/types/subscription.d.ts +54 -0
  145. package/dist/discord/types/subscription.js +12 -0
  146. package/dist/discord/types/team.d.ts +55 -0
  147. package/dist/discord/types/team.js +21 -0
  148. package/dist/discord/types/user.d.ts +273 -0
  149. package/dist/discord/types/user.js +83 -0
  150. package/dist/discord/types/voice.d.ts +72 -0
  151. package/dist/discord/types/voice.js +1 -0
  152. package/dist/discord/types/webhook.d.ts +184 -0
  153. package/dist/discord/types/webhook.js +12 -0
  154. package/dist/events/convention.d.ts +25 -0
  155. package/dist/events/convention.js +97 -0
  156. package/dist/events/event.d.ts +8 -0
  157. package/dist/events/event.js +20 -0
  158. package/dist/events/registry.d.ts +706 -0
  159. package/dist/events/registry.js +839 -0
  160. package/dist/events/router.d.ts +45 -0
  161. package/dist/events/router.js +133 -0
  162. package/dist/events/types.d.ts +7 -0
  163. package/dist/events/types.js +48 -0
  164. package/dist/gateway/errors.d.ts +18 -0
  165. package/dist/gateway/errors.js +47 -0
  166. package/dist/gateway/gateway.d.ts +64 -0
  167. package/dist/gateway/gateway.js +117 -0
  168. package/dist/gateway/identify-queue.d.ts +25 -0
  169. package/dist/gateway/identify-queue.js +29 -0
  170. package/dist/gateway/shard.d.ts +94 -0
  171. package/dist/gateway/shard.js +414 -0
  172. package/dist/gateway/state.d.ts +11 -0
  173. package/dist/gateway/state.js +184 -0
  174. package/dist/index.d.ts +55 -18
  175. package/dist/index.js +38 -12
  176. package/dist/interactions/cooldown.d.ts +33 -0
  177. package/dist/interactions/cooldown.js +74 -0
  178. package/dist/interactions/dispatch.d.ts +91 -0
  179. package/dist/interactions/dispatch.js +110 -0
  180. package/dist/loader/generated.d.ts +37 -0
  181. package/dist/loader/generated.js +114 -0
  182. package/dist/loader/hot.d.ts +13 -0
  183. package/dist/loader/hot.js +85 -0
  184. package/dist/loader/loader.d.ts +72 -0
  185. package/dist/loader/loader.js +135 -0
  186. package/dist/loader/locate.d.ts +10 -0
  187. package/dist/loader/locate.js +36 -0
  188. package/dist/loader/watch.d.ts +17 -0
  189. package/dist/loader/watch.js +66 -0
  190. package/dist/main.d.ts +3 -0
  191. package/dist/main.js +6 -0
  192. package/dist/messages/commands.d.ts +23 -0
  193. package/dist/messages/commands.js +123 -0
  194. package/dist/messages/convention.d.ts +89 -0
  195. package/dist/messages/convention.js +347 -0
  196. package/dist/messages/messages.d.ts +219 -0
  197. package/dist/messages/messages.js +30 -0
  198. package/dist/messages/phrases.d.ts +23 -0
  199. package/dist/messages/phrases.js +44 -0
  200. package/dist/messages/translate.d.ts +100 -0
  201. package/dist/messages/translate.js +249 -0
  202. package/dist/presence/convention.d.ts +26 -0
  203. package/dist/presence/convention.js +133 -0
  204. package/dist/presence/presence.d.ts +57 -0
  205. package/dist/presence/presence.js +27 -0
  206. package/dist/rest/errors.d.ts +55 -0
  207. package/dist/rest/errors.js +92 -0
  208. package/dist/rest/rate-limiter.d.ts +46 -0
  209. package/dist/rest/rate-limiter.js +153 -0
  210. package/dist/rest/rest.d.ts +63 -0
  211. package/dist/rest/rest.js +194 -0
  212. package/dist/structures/base.d.ts +48 -0
  213. package/dist/structures/base.js +84 -0
  214. package/dist/structures/channel.d.ts +380 -0
  215. package/dist/structures/channel.js +627 -0
  216. package/dist/structures/context.d.ts +30 -0
  217. package/dist/structures/context.js +7 -0
  218. package/dist/structures/emoji.d.ts +46 -0
  219. package/dist/structures/emoji.js +65 -0
  220. package/dist/structures/entities.d.ts +62 -0
  221. package/dist/structures/entities.js +226 -0
  222. package/dist/structures/guild.d.ts +348 -0
  223. package/dist/structures/guild.js +466 -0
  224. package/dist/structures/interaction.d.ts +197 -0
  225. package/dist/structures/interaction.js +396 -0
  226. package/dist/structures/invite.d.ts +38 -0
  227. package/dist/structures/invite.js +57 -0
  228. package/dist/structures/known.d.ts +28 -0
  229. package/dist/structures/known.js +58 -0
  230. package/dist/structures/member.d.ts +140 -0
  231. package/dist/structures/member.js +260 -0
  232. package/dist/structures/message.d.ts +197 -0
  233. package/dist/structures/message.js +268 -0
  234. package/dist/structures/payload.d.ts +91 -0
  235. package/dist/structures/payload.js +184 -0
  236. package/dist/structures/role.d.ts +69 -0
  237. package/dist/structures/role.js +112 -0
  238. package/dist/structures/user.d.ts +59 -0
  239. package/dist/structures/user.js +94 -0
  240. package/dist/structures/webhook.d.ts +46 -0
  241. package/dist/structures/webhook.js +79 -0
  242. package/dist/tasks/convention.d.ts +26 -0
  243. package/dist/tasks/convention.js +78 -0
  244. package/dist/tasks/schedule.d.ts +54 -0
  245. package/dist/tasks/schedule.js +236 -0
  246. package/dist/tasks/scheduler.d.ts +33 -0
  247. package/dist/tasks/scheduler.js +107 -0
  248. package/dist/tasks/task.d.ts +76 -0
  249. package/dist/tasks/task.js +28 -0
  250. package/dist/util/case.d.ts +13 -0
  251. package/dist/util/case.js +54 -0
  252. package/dist/util/duration.d.ts +8 -0
  253. package/dist/util/duration.js +29 -0
  254. package/dist/util/websocket.d.ts +9 -0
  255. package/dist/util/websocket.js +31 -0
  256. package/dist/voice/connection.d.ts +90 -0
  257. package/dist/voice/connection.js +494 -0
  258. package/dist/voice/dave.d.ts +109 -0
  259. package/dist/voice/dave.js +245 -0
  260. package/dist/voice/opus.d.ts +19 -0
  261. package/dist/voice/opus.js +273 -0
  262. package/dist/voice/session.d.ts +55 -0
  263. package/dist/voice/session.js +405 -0
  264. package/dist/voice/source.d.ts +22 -0
  265. package/dist/voice/source.js +195 -0
  266. package/dist/voice/transport.d.ts +43 -0
  267. package/dist/voice/transport.js +140 -0
  268. package/dist/voice/usage.d.ts +4 -0
  269. package/dist/voice/usage.js +33 -0
  270. package/package.json +26 -7
  271. package/vendor/dave/LICENSE +231 -0
  272. package/vendor/dave/libdave.d.mts +99 -0
  273. package/vendor/dave/libdave.mjs +2 -0
  274. package/vendor/dave/libdave.wasm +0 -0
  275. package/dist/components.d.ts +0 -97
  276. package/dist/components.js +0 -260
  277. package/dist/context.d.ts +0 -72
  278. package/dist/context.js +0 -273
  279. package/dist/discord/client.d.ts +0 -35
  280. package/dist/discord/client.js +0 -66
  281. package/dist/discord/constants.d.ts +0 -49
  282. package/dist/discord/constants.js +0 -61
  283. package/dist/discord/events.d.ts +0 -129
  284. package/dist/discord/events.js +0 -102
  285. package/dist/discord/gateway.d.ts +0 -61
  286. package/dist/discord/gateway.js +0 -320
  287. package/dist/discord/payloads.d.ts +0 -275
  288. package/dist/discord/payloads.js +0 -3
  289. package/dist/discord/presence.d.ts +0 -42
  290. package/dist/discord/presence.js +0 -51
  291. package/dist/discord/rest.d.ts +0 -49
  292. package/dist/discord/rest.js +0 -271
  293. package/dist/discord/types.d.ts +0 -334
  294. package/dist/discord/types.js +0 -4
  295. package/dist/events.d.ts +0 -94
  296. package/dist/events.js +0 -255
  297. package/dist/presence.d.ts +0 -92
  298. package/dist/presence.js +0 -250
  299. package/dist/structures/Channel.d.ts +0 -110
  300. package/dist/structures/Channel.js +0 -171
  301. package/dist/structures/Guild.d.ts +0 -70
  302. package/dist/structures/Guild.js +0 -105
  303. package/dist/structures/Interaction.d.ts +0 -113
  304. package/dist/structures/Interaction.js +0 -274
  305. package/dist/structures/Member.d.ts +0 -70
  306. package/dist/structures/Member.js +0 -124
  307. package/dist/structures/Message.d.ts +0 -87
  308. package/dist/structures/Message.js +0 -182
  309. package/dist/structures/Reaction.d.ts +0 -38
  310. package/dist/structures/Reaction.js +0 -64
  311. package/dist/structures/Role.d.ts +0 -43
  312. package/dist/structures/Role.js +0 -77
  313. package/dist/structures/User.d.ts +0 -41
  314. package/dist/structures/User.js +0 -79
  315. package/dist/structures/utils.d.ts +0 -72
  316. package/dist/structures/utils.js +0 -59
  317. package/dist/utils/errors.d.ts +0 -5
  318. package/dist/utils/errors.js +0 -28
  319. package/dist/utils/modules.d.ts +0 -39
  320. package/dist/utils/modules.js +0 -156
@@ -0,0 +1,396 @@
1
+ import { CreateFollowupMessage, CreateInteractionResponse, DeleteOriginalInteractionResponse, EditOriginalInteractionResponse, GetOriginalInteractionResponse, } from '../discord/endpoints.js';
2
+ import { renderedOf } from '../components/instance.js';
3
+ import { InteractionCallbackType, } from '../discord/types/interaction.js';
4
+ import { MessageFlags } from '../discord/types/message.js';
5
+ import { ctxOf, dataOf, IdStructure } from './base.js';
6
+ import { findGuild, knownChannel, knownMember } from './known.js';
7
+ import { buildMessage, } from './payload.js';
8
+ import { resolve } from '../components/instance.js';
9
+ import { translatorOf } from '../messages/translate.js';
10
+ /** Only the framework reads how far an interaction was answered. */
11
+ export let isUpdating;
12
+ /** Answers with a change of the message: see `ComponentInteraction.update()`. */
13
+ let updateMessage;
14
+ let deferUpdateMessage;
15
+ let openModal;
16
+ /**
17
+ * Someone used something of the bot (a command...) and waits for an answer.
18
+ * Discord wants a first answer within 3 seconds, and accepts edits and
19
+ * other messages for 15 minutes.
20
+ * @see https://docs.discord.com/developers/interactions/receiving-and-responding
21
+ */
22
+ export class Interaction extends IdStructure {
23
+ /** Who did it. */
24
+ user;
25
+ #ephemeral;
26
+ /**
27
+ * `deferred`: "thinking…" is shown, the answer is a new message.
28
+ * `updating`: the answer is a change of the message of the component,
29
+ * nothing is shown meanwhile.
30
+ */
31
+ #state = 'waiting';
32
+ /** Answers are sent one after the other, in the order they were asked. */
33
+ #queue = Promise.resolve();
34
+ static {
35
+ isUpdating = interaction => interaction.#state === 'updating';
36
+ updateMessage = (interaction, message) => {
37
+ const { body, files } = buildMessage(message, {
38
+ edit: true,
39
+ t: interaction.#t(interaction.#ephemeral),
40
+ });
41
+ return interaction.#run(async () => {
42
+ const { rest, entities } = ctxOf(interaction);
43
+ const { id, token, application_id: applicationId, } = dataOf(interaction);
44
+ if (interaction.#state === 'answered' ||
45
+ interaction.#state === 'deferred') {
46
+ throw new Error('This interaction was already answered: the message can no longer be changed through it. Use interaction.message.edit() to change the message, or interaction.followUp() to send another one.');
47
+ }
48
+ if (interaction.#state === 'updating') {
49
+ const raw = await rest.request(EditOriginalInteractionResponse, [applicationId, token], { body, files, auth: false });
50
+ interaction.#state = 'answered';
51
+ return entities.message(raw, interaction.guildId ?? undefined);
52
+ }
53
+ const response = await rest.request(CreateInteractionResponse, [id, token], {
54
+ body: { type: InteractionCallbackType.UpdateMessage, data: body },
55
+ query: { with_response: true },
56
+ files,
57
+ auth: false,
58
+ });
59
+ interaction.#state = 'answered';
60
+ const raw = response?.resource?.message ??
61
+ (await rest.request(GetOriginalInteractionResponse, [applicationId, token], { auth: false }));
62
+ return entities.message(raw, interaction.guildId ?? undefined);
63
+ });
64
+ };
65
+ deferUpdateMessage = interaction => interaction.#run(async () => {
66
+ if (interaction.#state !== 'waiting')
67
+ return;
68
+ const { id, token } = dataOf(interaction);
69
+ await ctxOf(interaction).rest.request(CreateInteractionResponse, [id, token], {
70
+ body: { type: InteractionCallbackType.DeferredUpdateMessage },
71
+ auth: false,
72
+ });
73
+ interaction.#state = 'updating';
74
+ });
75
+ openModal = (interaction, form) => {
76
+ const rendered = renderedOf(form, 'The form given to showModal()');
77
+ if (rendered.kind !== 'modal') {
78
+ throw new TypeError(`showModal() opens a form of src/components/modals/, got a ${rendered.kind}.`);
79
+ }
80
+ return interaction.#run(async () => {
81
+ if (interaction.#state !== 'waiting') {
82
+ throw new Error('A form can only be the first answer to an interaction: call interaction.showModal() before reply() or defer(), and the framework waits for it.');
83
+ }
84
+ const { id, token } = dataOf(interaction);
85
+ await ctxOf(interaction).rest.request(CreateInteractionResponse, [id, token], {
86
+ body: {
87
+ type: InteractionCallbackType.Modal,
88
+ // A form is seen by the person alone: in their language.
89
+ data: resolve(rendered, translatorOf(ctxOf(interaction), {
90
+ person: interaction.locale,
91
+ ephemeral: true,
92
+ })).raw,
93
+ },
94
+ auth: false,
95
+ });
96
+ interaction.#state = 'answered';
97
+ });
98
+ };
99
+ }
100
+ constructor(ctx, data, user, { ephemeral = false } = {}) {
101
+ super(ctx, data);
102
+ this.user = user;
103
+ this.#ephemeral = ephemeral;
104
+ }
105
+ /** The id of the server; `null` in a private message. */
106
+ get guildId() {
107
+ return dataOf(this).guild_id ?? null;
108
+ }
109
+ /** The id of the channel it happened in. */
110
+ get channelId() {
111
+ return dataOf(this).channel_id ?? this.channel.id;
112
+ }
113
+ /** The server it happened in; `null` in a private message. */
114
+ get guild() {
115
+ return findGuild(this, this.guildId);
116
+ }
117
+ /** The channel it happened in: Discord sends it with the interaction. */
118
+ get channel() {
119
+ const id = dataOf(this).channel_id;
120
+ const channel = (id ? ctxOf(this).cache.channels.get(id) : undefined) ??
121
+ knownChannel(this);
122
+ if (!channel?.isTextBased()) {
123
+ throw new Error('This interaction came without its channel.');
124
+ }
125
+ return channel;
126
+ }
127
+ /** Who did it, as a member of the server; `null` in a private message. */
128
+ get member() {
129
+ return this.guild?.members.get(this.user.id) ?? knownMember(this) ?? null;
130
+ }
131
+ /** The language of the person: use it to answer in their language. */
132
+ get locale() {
133
+ // Discord sends it with everything a person does (all but pings).
134
+ return dataOf(this).locale;
135
+ }
136
+ /** Whether an answer was sent, or promised with `defer()`. */
137
+ get answered() {
138
+ return this.#state !== 'waiting';
139
+ }
140
+ /** Whether `defer()` was called and the answer is still to come. */
141
+ get deferred() {
142
+ return this.#state === 'deferred' || this.#state === 'updating';
143
+ }
144
+ /** The data of the interaction, without its token: a token is a secret. */
145
+ toJSON() {
146
+ const { token: _token, ...data } = super.toJSON();
147
+ return data;
148
+ }
149
+ /**
150
+ * Runs one answer after the previous ones. Written with `await` so that an
151
+ * error keeps the line of user code that asked for the answer.
152
+ */
153
+ async #run(action) {
154
+ const previous = this.#queue;
155
+ let release;
156
+ this.#queue = new Promise(resolve => (release = resolve));
157
+ await previous;
158
+ try {
159
+ return await action();
160
+ }
161
+ finally {
162
+ release();
163
+ }
164
+ }
165
+ /** `t` for an answer: the person when they alone see it, else the server. */
166
+ #t(ephemeral) {
167
+ return translatorOf(ctxOf(this), {
168
+ person: this.locale,
169
+ guild: this.guild,
170
+ ephemeral: ephemeral ?? this.#ephemeral,
171
+ });
172
+ }
173
+ #flags(ephemeral, flags = 0) {
174
+ return (ephemeral ?? this.#ephemeral)
175
+ ? flags | MessageFlags.Ephemeral
176
+ : flags;
177
+ }
178
+ /**
179
+ * Answers. If `defer()` was called (by you, or by the framework because
180
+ * the answer was taking long), this completes the pending answer.
181
+ * @see https://docs.discord.com/developers/interactions/receiving-and-responding#create-interaction-response
182
+ */
183
+ reply(message) {
184
+ const options = typeof message === 'string' ? { content: message } : message;
185
+ const { body, files } = buildMessage(options, {
186
+ t: this.#t(options.ephemeral),
187
+ });
188
+ return this.#run(async () => {
189
+ const { rest, entities } = ctxOf(this);
190
+ const { id, token, application_id: applicationId } = dataOf(this);
191
+ if (this.#state === 'answered') {
192
+ throw new Error('This interaction was already answered. Use interaction.followUp() to send another message, or interaction.edit() to change the answer.');
193
+ }
194
+ if (this.#state === 'updating') {
195
+ // The pending answer is a change of the message of the component:
196
+ // a new message is a follow-up, which looks the same to the person.
197
+ const raw = await rest.request(CreateFollowupMessage, [applicationId, token], {
198
+ body: {
199
+ ...body,
200
+ flags: this.#flags(options.ephemeral, body.flags),
201
+ },
202
+ files,
203
+ auth: false,
204
+ });
205
+ this.#state = 'answered';
206
+ return entities.message(raw, this.guildId ?? undefined);
207
+ }
208
+ if (this.#state === 'deferred') {
209
+ // Whether the answer is ephemeral was decided when deferring.
210
+ const raw = await rest.request(EditOriginalInteractionResponse, [applicationId, token], { body, files, auth: false });
211
+ this.#state = 'answered';
212
+ return entities.message(raw, this.guildId ?? undefined);
213
+ }
214
+ const response = await rest.request(CreateInteractionResponse, [id, token], {
215
+ body: {
216
+ type: InteractionCallbackType.ChannelMessageWithSource,
217
+ data: {
218
+ ...body,
219
+ flags: this.#flags(options.ephemeral, body.flags),
220
+ },
221
+ },
222
+ query: { with_response: true },
223
+ files,
224
+ auth: false,
225
+ });
226
+ this.#state = 'answered';
227
+ const raw = response?.resource?.message ??
228
+ (await rest.request(GetOriginalInteractionResponse, [applicationId, token], { auth: false }));
229
+ return entities.message(raw, this.guildId ?? undefined);
230
+ });
231
+ }
232
+ /**
233
+ * Tells Discord the answer is coming: the person sees "thinking…" and
234
+ * `reply()` can then take up to 15 minutes. The framework does it by
235
+ * itself when an answer takes long; call it yourself to choose when.
236
+ */
237
+ defer({ ephemeral } = {}) {
238
+ return this.#run(async () => {
239
+ if (this.#state !== 'waiting')
240
+ return;
241
+ const { id, token } = dataOf(this);
242
+ await ctxOf(this).rest.request(CreateInteractionResponse, [id, token], {
243
+ body: {
244
+ type: InteractionCallbackType.DeferredChannelMessageWithSource,
245
+ data: { flags: this.#flags(ephemeral) },
246
+ },
247
+ auth: false,
248
+ });
249
+ this.#state = 'deferred';
250
+ });
251
+ }
252
+ /**
253
+ * Changes the answer.
254
+ * @see https://docs.discord.com/developers/interactions/receiving-and-responding#edit-original-interaction-response
255
+ */
256
+ edit(message) {
257
+ const { body, files } = buildMessage(message, {
258
+ edit: true,
259
+ t: this.#t(undefined),
260
+ });
261
+ return this.#run(async () => {
262
+ if (this.#state === 'waiting') {
263
+ throw new Error('There is no answer to edit yet: call interaction.reply() first.');
264
+ }
265
+ const { rest, entities } = ctxOf(this);
266
+ const { token, application_id: applicationId } = dataOf(this);
267
+ const raw = await rest.request(EditOriginalInteractionResponse, [applicationId, token], { body, files, auth: false });
268
+ this.#state = 'answered';
269
+ return entities.message(raw, this.guildId ?? undefined);
270
+ });
271
+ }
272
+ /**
273
+ * Sends another message, after the answer.
274
+ * @see https://docs.discord.com/developers/interactions/receiving-and-responding#create-followup-message
275
+ */
276
+ followUp(message) {
277
+ const options = typeof message === 'string' ? { content: message } : message;
278
+ const { body, files } = buildMessage(options, {
279
+ t: this.#t(options.ephemeral),
280
+ });
281
+ return this.#run(async () => {
282
+ if (this.#state === 'waiting') {
283
+ throw new Error('A follow-up comes after an answer: call interaction.reply() first.');
284
+ }
285
+ const { rest, entities } = ctxOf(this);
286
+ const { token, application_id: applicationId } = dataOf(this);
287
+ const raw = await rest.request(CreateFollowupMessage, [applicationId, token], {
288
+ body: { ...body, flags: this.#flags(options.ephemeral, body.flags) },
289
+ files,
290
+ auth: false,
291
+ });
292
+ return entities.message(raw, this.guildId ?? undefined);
293
+ });
294
+ }
295
+ /**
296
+ * Deletes the answer.
297
+ * @see https://docs.discord.com/developers/interactions/receiving-and-responding#delete-original-interaction-response
298
+ */
299
+ delete() {
300
+ return this.#run(async () => {
301
+ const { token, application_id: applicationId } = dataOf(this);
302
+ await ctxOf(this).rest.request(DeleteOriginalInteractionResponse, [applicationId, token], { auth: false });
303
+ });
304
+ }
305
+ }
306
+ /** Someone used a slash command. */
307
+ export class CommandInteraction extends Interaction {
308
+ /** The command as the person typed it: `/mod ban`. */
309
+ commandName;
310
+ constructor(ctx, data, user, options) {
311
+ super(ctx, data, user, options);
312
+ this.commandName = options.commandName;
313
+ }
314
+ /**
315
+ * Opens a form, as the answer: `showModal(report({ userId }))`, with a
316
+ * form of `src/components/modals/`. It must be the first answer, and the
317
+ * person has as long as they want to fill it in.
318
+ * @see https://docs.discord.com/developers/interactions/receiving-and-responding#interaction-response-object-modal
319
+ */
320
+ showModal(form) {
321
+ return openModal(this, form);
322
+ }
323
+ }
324
+ /**
325
+ * Someone clicked a button or picked something in a select menu of a
326
+ * message of the bot. It can answer like a command, or change the message
327
+ * the component is on.
328
+ * @see https://docs.discord.com/developers/interactions/receiving-and-responding#interaction-object-message-component-data-structure
329
+ */
330
+ export class ComponentInteraction extends Interaction {
331
+ /** The message the component is on. */
332
+ message;
333
+ constructor(ctx, data, user, options) {
334
+ super(ctx, data, user, options);
335
+ this.message = options.message;
336
+ }
337
+ /**
338
+ * Changes the message the component is on, as the answer: its text, its
339
+ * embeds, its components, its files. Only what you pass changes;
340
+ * `components: []` removes the buttons and menus.
341
+ * @see https://docs.discord.com/developers/interactions/receiving-and-responding#interaction-response-object-interaction-callback-type
342
+ */
343
+ update(message) {
344
+ return updateMessage(this, message);
345
+ }
346
+ /**
347
+ * Tells Discord the message will change later: the person sees nothing
348
+ * meanwhile, and `update()` can then take up to 15 minutes. The
349
+ * framework does it by itself when an answer takes long.
350
+ */
351
+ deferUpdate() {
352
+ return deferUpdateMessage(this);
353
+ }
354
+ /**
355
+ * Opens a form, as the answer: `showModal(report({ userId }))`, with a
356
+ * form of `src/components/modals/`. It must be the first answer.
357
+ * @see https://docs.discord.com/developers/interactions/receiving-and-responding#interaction-response-object-modal
358
+ */
359
+ showModal(form) {
360
+ return openModal(this, form);
361
+ }
362
+ }
363
+ /**
364
+ * Someone sent a form of the bot. It can answer like a command; when a
365
+ * button or a menu opened the form, it can also change their message.
366
+ * @see https://docs.discord.com/developers/interactions/receiving-and-responding#interaction-object-modal-submit-data-structure
367
+ */
368
+ export class ModalInteraction extends Interaction {
369
+ /** The message whose button or menu opened the form; `null` when a command did. */
370
+ message;
371
+ constructor(ctx, data, user, options) {
372
+ super(ctx, data, user, options);
373
+ this.message = options.message;
374
+ }
375
+ /**
376
+ * Changes the message whose button or menu opened the form, as the
377
+ * answer. Only what you pass changes.
378
+ * @see https://docs.discord.com/developers/interactions/receiving-and-responding#interaction-response-object-interaction-callback-type
379
+ */
380
+ update(message) {
381
+ if (!this.message) {
382
+ return Promise.reject(new Error('This form was opened by a command, not by a button or a menu: there is no message to change. Use interaction.reply().'));
383
+ }
384
+ return updateMessage(this, message);
385
+ }
386
+ /**
387
+ * Tells Discord the message that opened the form will change later: the
388
+ * person sees nothing meanwhile.
389
+ */
390
+ deferUpdate() {
391
+ if (!this.message) {
392
+ return Promise.reject(new Error('This form was opened by a command, not by a button or a menu: there is no message to change. Use interaction.defer().'));
393
+ }
394
+ return deferUpdateMessage(this);
395
+ }
396
+ }
@@ -0,0 +1,38 @@
1
+ import type { Snowflake } from '../discord/types/common.js';
2
+ import type { RawInvite, RawInviteMetadata } from '../discord/types/invite.js';
3
+ import { Structure } from './base.js';
4
+ import type { Context } from './context.js';
5
+ import type { User } from './user.js';
6
+ export type InviteData = Omit<RawInvite, 'inviter'> & Partial<RawInviteMetadata>;
7
+ /**
8
+ * An invite to a server.
9
+ * @see https://docs.discord.com/developers/resources/invite#invite-object
10
+ */
11
+ export declare class Invite extends Structure<InviteData> {
12
+ /** Who created the invite, when Discord says it. */
13
+ readonly inviter: User | null;
14
+ constructor(ctx: Context, data: InviteData, inviter: User | null);
15
+ /** The unique code of the invite (`discord.gg/code`). */
16
+ get code(): string;
17
+ /** The link to share. */
18
+ get url(): string;
19
+ /** The id of the server the invite leads to. */
20
+ get guildId(): Snowflake | null;
21
+ /** The id of the channel the invite leads to. */
22
+ get channelId(): Snowflake | null;
23
+ /** When the invite stops working; `null` when it never does. */
24
+ get expiresAt(): Date | null;
25
+ /** How many times the invite was used, when Discord says it. */
26
+ get uses(): number | null;
27
+ /** How many times the invite can be used; `0` means no limit. */
28
+ get maxUses(): number | null;
29
+ /** Whether members who joined with it are kicked when they go offline. */
30
+ get temporary(): boolean;
31
+ /**
32
+ * Deletes the invite: its link stops working.
33
+ * @see https://docs.discord.com/developers/resources/invite#delete-invite
34
+ */
35
+ delete(reason?: string): Promise<void>;
36
+ /** The link to share. */
37
+ toString(): string;
38
+ }
@@ -0,0 +1,57 @@
1
+ import { DeleteInvite } from '../discord/endpoints.js';
2
+ import { ctxOf, dataOf, Structure, toDate } from './base.js';
3
+ /**
4
+ * An invite to a server.
5
+ * @see https://docs.discord.com/developers/resources/invite#invite-object
6
+ */
7
+ export class Invite extends Structure {
8
+ /** Who created the invite, when Discord says it. */
9
+ inviter;
10
+ constructor(ctx, data, inviter) {
11
+ super(ctx, data);
12
+ this.inviter = inviter;
13
+ }
14
+ /** The unique code of the invite (`discord.gg/code`). */
15
+ get code() {
16
+ return dataOf(this).code;
17
+ }
18
+ /** The link to share. */
19
+ get url() {
20
+ return `https://discord.gg/${this.code}`;
21
+ }
22
+ /** The id of the server the invite leads to. */
23
+ get guildId() {
24
+ return dataOf(this).guild?.id ?? null;
25
+ }
26
+ /** The id of the channel the invite leads to. */
27
+ get channelId() {
28
+ return dataOf(this).channel?.id ?? null;
29
+ }
30
+ /** When the invite stops working; `null` when it never does. */
31
+ get expiresAt() {
32
+ return toDate(dataOf(this).expires_at);
33
+ }
34
+ /** How many times the invite was used, when Discord says it. */
35
+ get uses() {
36
+ return dataOf(this).uses ?? null;
37
+ }
38
+ /** How many times the invite can be used; `0` means no limit. */
39
+ get maxUses() {
40
+ return dataOf(this).max_uses ?? null;
41
+ }
42
+ /** Whether members who joined with it are kicked when they go offline. */
43
+ get temporary() {
44
+ return dataOf(this).temporary ?? false;
45
+ }
46
+ /**
47
+ * Deletes the invite: its link stops working.
48
+ * @see https://docs.discord.com/developers/resources/invite#delete-invite
49
+ */
50
+ async delete(reason) {
51
+ await ctxOf(this).rest.request(DeleteInvite, [this.code], { reason });
52
+ }
53
+ /** The link to share. */
54
+ toString() {
55
+ return this.url;
56
+ }
57
+ }
@@ -0,0 +1,28 @@
1
+ import type { Snowflake } from '../discord/types/common.js';
2
+ import { Structure } from './base.js';
3
+ import type { Channel } from './channel.js';
4
+ import type { Guild } from './guild.js';
5
+ import type { GuildMember } from './member.js';
6
+ interface Known {
7
+ guild?: Guild | undefined;
8
+ member?: GuildMember | undefined;
9
+ channel?: Channel | undefined;
10
+ }
11
+ /** The server a structure came with. */
12
+ export declare function knownGuild(structure: Structure<object>): Guild | undefined;
13
+ /** The member a structure came with (the author, who used a command). */
14
+ export declare function knownMember(structure: Structure<object>): GuildMember | undefined;
15
+ /** The channel a structure came with. */
16
+ export declare function knownChannel(structure: Structure<object>): Channel | undefined;
17
+ /** Keeps what a structure comes with; what is not given is left as it was. */
18
+ export declare function remember(structure: Structure<object>, seen: Known): void;
19
+ /** The server of something that may have one. */
20
+ export declare function findGuild(structure: Structure<object>, guildId: Snowflake | null | undefined): Guild | null;
21
+ /**
22
+ * The server of something that belongs to one (a member, a role, a channel
23
+ * of a server): it is always there. Such a thing only reaches user code
24
+ * from a server the bot is in; anything else is refused loudly rather than
25
+ * answered with a `null` nobody expects.
26
+ */
27
+ export declare function guildOf(structure: Structure<object>, guildId: Snowflake): Guild;
28
+ export {};
@@ -0,0 +1,58 @@
1
+ // What a structure was created with. A property like `member.guild` or
2
+ // `message.channel` reads the cache, so it would turn to nothing the moment
3
+ // the cache forgets (the bot is removed from the server, the member leaves,
4
+ // the session starts over) while code still holds the structure. What the
5
+ // structure came with is kept, so that what was there stays there: the
6
+ // cache first, then this.
7
+ //
8
+ // It costs one reference per structure and no allocation for what belongs
9
+ // to a server (members, roles, channels: there can be millions), which keep
10
+ // their server itself. Only what comes with more (a message, an interaction:
11
+ // few, and short-lived) keeps a small object.
12
+ import { ctxOf, originOf, setOrigin, Structure } from './base.js';
13
+ /** A server kept as such is a structure; anything else is a `Known`. */
14
+ const isGuild = (origin) => origin instanceof Structure;
15
+ /** The server a structure came with. */
16
+ export function knownGuild(structure) {
17
+ const origin = originOf(structure);
18
+ if (!origin)
19
+ return undefined;
20
+ return isGuild(origin) ? origin : origin.guild;
21
+ }
22
+ /** The member a structure came with (the author, who used a command). */
23
+ export function knownMember(structure) {
24
+ const origin = originOf(structure);
25
+ return origin && !isGuild(origin) ? origin.member : undefined;
26
+ }
27
+ /** The channel a structure came with. */
28
+ export function knownChannel(structure) {
29
+ const origin = originOf(structure);
30
+ return origin && !isGuild(origin) ? origin.channel : undefined;
31
+ }
32
+ /** Keeps what a structure comes with; what is not given is left as it was. */
33
+ export function remember(structure, seen) {
34
+ const guild = seen.guild ?? knownGuild(structure);
35
+ const member = seen.member ?? knownMember(structure);
36
+ const channel = seen.channel ?? knownChannel(structure);
37
+ // Only a server: the server itself, nothing allocated.
38
+ setOrigin(structure, member || channel ? { guild, member, channel } : guild);
39
+ }
40
+ /** The server of something that may have one. */
41
+ export function findGuild(structure, guildId) {
42
+ if (!guildId)
43
+ return null;
44
+ return (ctxOf(structure).cache.guilds.get(guildId) ?? knownGuild(structure) ?? null);
45
+ }
46
+ /**
47
+ * The server of something that belongs to one (a member, a role, a channel
48
+ * of a server): it is always there. Such a thing only reaches user code
49
+ * from a server the bot is in; anything else is refused loudly rather than
50
+ * answered with a `null` nobody expects.
51
+ */
52
+ export function guildOf(structure, guildId) {
53
+ const guild = findGuild(structure, guildId);
54
+ if (!guild) {
55
+ throw new Error(`The server ${guildId} is not one the bot is in, so what belongs to it can't be read.`);
56
+ }
57
+ return guild;
58
+ }