chapterjs 0.1.1 → 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
@@ -1,92 +0,0 @@
1
- import type { Client } from './discord/client.js';
2
- import type { Gateway } from './discord/gateway.js';
3
- import type { Presence } from './discord/presence.js';
4
- export interface PresenceContext {
5
- client: Client;
6
- }
7
- /** Computes one presence. Can be async, e.g. to read from a database. */
8
- export type PresenceFunction = (context: PresenceContext) => Presence | Promise<Presence>;
9
- /** One step of a rotation, shown for `duration` milliseconds (minimum 5000). */
10
- export type PresenceStep = (Presence & {
11
- duration: number;
12
- }) | {
13
- duration: number;
14
- presence: PresenceFunction;
15
- };
16
- /**
17
- * Computes either a presence or a whole rotation, e.g. from a database.
18
- * A rotation is played in full, then the function is called again.
19
- */
20
- export type PresenceSourceFunction = (context: PresenceContext) => Presence | PresenceStep[] | Promise<Presence | PresenceStep[]>;
21
- /** Stops listening for changes. */
22
- export type PresenceWatchCleanup = () => void;
23
- export interface PresenceDefinition {
24
- presence: PresenceSourceFunction;
25
- /**
26
- * When `presence` returns a single presence: delay before calling it again,
27
- * in milliseconds (minimum 5000). Without it, it is called once.
28
- */
29
- interval?: number;
30
- /**
31
- * Calls `refresh` whenever the data behind `presence` changes (database
32
- * realtime, webhook…) to apply it right away. Return a cleanup function.
33
- */
34
- watch?: (refresh: () => void) => void | PresenceWatchCleanup | Promise<void | PresenceWatchCleanup>;
35
- }
36
- /**
37
- * - `Presence`: a fixed presence
38
- * - `PresenceStep[]`: a rotation, each step shown for its own `duration`
39
- * - a function: a presence or a rotation computed at runtime
40
- * - `PresenceDefinition`: a function with `interval` and/or `watch`
41
- */
42
- export type PresenceInput = Presence | readonly PresenceStep[] | PresenceSourceFunction | PresenceDefinition;
43
- /** Defines the bot's status and activity in `src/presence.ts`. */
44
- export declare function definePresence<const T extends PresenceInput>(input: T & CheckDurations<T>): T;
45
- type Digit = '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9';
46
- type IntegerPart<S extends string> = S extends `${infer I}.${string}` ? I : S;
47
- type IsAtLeast5000<N extends number> = number extends N ? true : `${N}` extends `-${string}` ? false : `${N}` extends `${string}e+${string}` ? true : IntegerPart<`${N}`> extends `${'5' | '6' | '7' | '8' | '9'}${Digit}${Digit}${Digit}` ? true : IntegerPart<`${N}`> extends `${Exclude<Digit, '0'>}${Digit}${Digit}${Digit}${Digit}${string}` ? true : false;
48
- /** A required key that can't be provided: its name is the error shown in the editor. */
49
- type Fails<Key extends string> = {
50
- [K in Key]: never;
51
- };
52
- type CheckKey<T, Key extends string> = T extends {
53
- readonly [K in Key]: infer N extends number;
54
- } ? IsAtLeast5000<N> extends true ? unknown : Fails<`⛔ ${Key} must be at least 5000 ms`> : unknown;
55
- type CheckDurations<T> = T extends readonly unknown[] ? {
56
- [K in keyof T]: CheckKey<T[K], 'duration'>;
57
- } : CheckKey<T, 'interval'>;
58
- /** Recomputes the presence right away, e.g. after updating it in a database. */
59
- export declare function refreshPresence(): void;
60
- interface NormalizedStep {
61
- /** Without duration, the rotation stops after this step. */
62
- duration?: number;
63
- presence: PresenceFunction;
64
- }
65
- interface PresenceLogger {
66
- error: (error: unknown) => void;
67
- warn: (message: string) => void;
68
- }
69
- /** Every input is normalized into a source giving the steps of each cycle. */
70
- export interface PresenceSource {
71
- load: (context: PresenceContext, warn: (message: string) => void) => Promise<NormalizedStep[]>;
72
- watch?: PresenceDefinition['watch'];
73
- /**
74
- * First presence when it is known without running any code, sent when
75
- * connecting: Discord shows it right away instead of a default presence.
76
- */
77
- initial?: Presence;
78
- }
79
- /**
80
- * Loads `src/presence.ts`, or returns null when the project has none. Errors
81
- * are prefixed with the file (and line when known).
82
- */
83
- export declare function loadPresence(cwd?: string): Promise<PresenceSource | null>;
84
- export declare function watchPresence(onChange: () => void, cwd?: string): import("fs").FSWatcher | null;
85
- /**
86
- * Plays the steps of each cycle in order, then loads the next cycle. Each step
87
- * waits for its `presence` call to settle, then for its `duration`, so slow
88
- * calls never overlap. `refresh` (from `watch` or `refreshPresence`) restarts
89
- * from a fresh cycle. Returns a stop function.
90
- */
91
- export declare function startPresenceLoop(gateway: Gateway, source: PresenceSource, log: PresenceLogger): () => void;
92
- export {};
package/dist/presence.js DELETED
@@ -1,250 +0,0 @@
1
- import { resolve } from 'node:path';
2
- import { describeLoadError, findFile, importFresh, watchFiles } from './utils/modules.js';
3
- /** Defines the bot's status and activity in `src/presence.ts`. */
4
- export function definePresence(input) {
5
- return input;
6
- }
7
- let activeRefresh = null;
8
- /** Recomputes the presence right away, e.g. after updating it in a database. */
9
- export function refreshPresence() {
10
- activeRefresh?.();
11
- }
12
- const PRESENCE_FILES = ['presence.ts', 'presence.mts', 'presence.js', 'presence.mjs'];
13
- /** Matches the client throttle, a shorter duration would only skip updates. */
14
- const MIN_DURATION = 5_000;
15
- /** A `presence` call taking longer is considered failed. */
16
- const PRESENCE_TIMEOUT = 10_000;
17
- /** Delay before calling `presence` again when it gave nothing to show. */
18
- const RETRY_DELAY = 30_000;
19
- /** Groups the refresh calls fired by a burst of changes. */
20
- const REFRESH_DEBOUNCE = 500;
21
- const srcDir = (cwd) => resolve(cwd, 'src');
22
- /**
23
- * Loads `src/presence.ts`, or returns null when the project has none. Errors
24
- * are prefixed with the file (and line when known).
25
- */
26
- export async function loadPresence(cwd = process.cwd()) {
27
- const path = findFile(srcDir(cwd), PRESENCE_FILES);
28
- if (!path)
29
- return null;
30
- try {
31
- const input = (await importFresh(path)).default;
32
- if (!input || (typeof input !== 'object' && typeof input !== 'function')) {
33
- throw new Error("doesn't export a presence. Add at the end of the file: export default definePresence({ activity: 'Hello' })");
34
- }
35
- return normalize(input);
36
- }
37
- catch (error) {
38
- throw new Error(describeLoadError(error, path, cwd), { cause: error });
39
- }
40
- }
41
- function normalize(input) {
42
- if (typeof input === 'function')
43
- return { load: fromFunction(input) };
44
- if (Array.isArray(input)) {
45
- // Written in code: invalid steps are errors, reported before the bot starts
46
- if (input.length === 0)
47
- throw new Error('the list of presences is empty: add at least one.');
48
- const steps = input.map((step, index) => {
49
- assertDuration(step.duration, `step ${index + 1}: duration`);
50
- return { duration: step.duration, presence: toFunction(step) };
51
- });
52
- const first = input[0];
53
- const initial = 'presence' in first && typeof first.presence === 'function' ? undefined : first;
54
- return { load: async () => steps, initial };
55
- }
56
- if ('presence' in input && typeof input.presence === 'function') {
57
- if (input.interval !== undefined)
58
- assertDuration(input.interval, 'interval');
59
- return { load: fromFunction(input.presence, input.interval), watch: input.watch };
60
- }
61
- return { load: async () => [{ presence: () => input }], initial: input };
62
- }
63
- function fromFunction(fn, interval) {
64
- return async (context, warn) => {
65
- const result = await fn(context);
66
- if (Array.isArray(result))
67
- return sanitizeSteps(result, warn);
68
- if (result && typeof result === 'object')
69
- return [{ duration: interval, presence: () => result }];
70
- throw new Error(`presence() returned ${result === undefined ? 'nothing' : JSON.stringify(result)}: it must return a presence, e.g. { activity: 'Hello' }, or a list of steps.`);
71
- };
72
- }
73
- /**
74
- * Steps computed at runtime may come from a database edited by someone else,
75
- * so they are fixed with a warning instead of stopping the bot.
76
- */
77
- function sanitizeSteps(steps, warn) {
78
- const valid = [];
79
- steps.forEach((step, index) => {
80
- const name = `step ${index + 1}`;
81
- if (!step || typeof step !== 'object' || typeof step.duration !== 'number' || !(step.duration > 0)) {
82
- warn(`${name} ignored: it needs a duration in milliseconds, e.g. duration: 10_000.`);
83
- return;
84
- }
85
- let duration = step.duration;
86
- if (duration < MIN_DURATION) {
87
- warn(`${name}: duration ${duration} ms raised to ${MIN_DURATION} ms (Discord limits how often a presence can change).`);
88
- duration = MIN_DURATION;
89
- }
90
- valid.push({ duration, presence: toFunction(step) });
91
- });
92
- return valid;
93
- }
94
- function toFunction(input) {
95
- if ('presence' in input && typeof input.presence === 'function')
96
- return input.presence;
97
- // Extra keys such as `duration` are ignored when sent to Discord
98
- return () => input;
99
- }
100
- function assertDuration(value, name) {
101
- if (typeof value !== 'number' || value < MIN_DURATION) {
102
- throw new Error(`${name} is ${typeof value === 'number' ? `${value} ms` : JSON.stringify(value)}, it must be at least ${MIN_DURATION} ms (${MIN_DURATION / 1000} seconds): ` +
103
- 'Discord limits how often a bot can change its presence.');
104
- }
105
- }
106
- export function watchPresence(onChange, cwd = process.cwd()) {
107
- return watchFiles(srcDir(cwd), PRESENCE_FILES, onChange);
108
- }
109
- /**
110
- * Plays the steps of each cycle in order, then loads the next cycle. Each step
111
- * waits for its `presence` call to settle, then for its `duration`, so slow
112
- * calls never overlap. `refresh` (from `watch` or `refreshPresence`) restarts
113
- * from a fresh cycle. Returns a stop function.
114
- */
115
- export function startPresenceLoop(gateway, source, log) {
116
- const context = { client: gateway.client };
117
- let stopped = false;
118
- /** Incremented on refresh and stop; a run whose generation is outdated exits. */
119
- let generation = 0;
120
- let lastSteps = null;
121
- /**
122
- * Issues of the previous and current cycle: an issue already reported in the
123
- * previous cycle is not logged again, so a bad row isn't reported every cycle.
124
- */
125
- let previousIssues = new Set();
126
- let currentIssues = new Set();
127
- let sleepTimeout;
128
- let wake;
129
- let refreshTimeout;
130
- let cleanupWatch;
131
- const report = (level, issue) => {
132
- const message = issue instanceof Error ? issue.message : String(issue);
133
- const key = `${level}:${message}`;
134
- if (currentIssues.has(key))
135
- return;
136
- currentIssues.add(key);
137
- if (!previousIssues.has(key))
138
- log[level](message);
139
- };
140
- const startCycle = () => {
141
- previousIssues = currentIssues;
142
- currentIssues = new Set();
143
- };
144
- /** Resolves to false if a refresh or stop happened meanwhile. */
145
- const sleep = (ms, id) => new Promise((resolve) => {
146
- wake = resolve;
147
- sleepTimeout = setTimeout(() => resolve(id === generation), ms);
148
- });
149
- const loadSteps = async (id) => {
150
- try {
151
- const warnings = [];
152
- const steps = await withTimeout(source.load(context, (message) => warnings.push(message)), PRESENCE_TIMEOUT);
153
- if (id !== generation)
154
- return null;
155
- for (const message of warnings)
156
- report('warn', message);
157
- if (steps.length > 0)
158
- return (lastSteps = steps);
159
- report('warn', `presence() returned an empty list, trying again in ${RETRY_DELAY / 1000}s.`);
160
- return null;
161
- }
162
- catch (error) {
163
- if (id !== generation)
164
- return null;
165
- report('error', error);
166
- // Keep playing the previous rotation until the next attempt
167
- return lastSteps;
168
- }
169
- };
170
- const run = async (id) => {
171
- while (id === generation) {
172
- startCycle();
173
- const steps = await loadSteps(id);
174
- if (id !== generation)
175
- return;
176
- if (!steps) {
177
- if (!(await sleep(RETRY_DELAY, id)))
178
- return;
179
- continue;
180
- }
181
- for (const step of steps) {
182
- try {
183
- const presence = await withTimeout(Promise.resolve(step.presence(context)), PRESENCE_TIMEOUT);
184
- if (id === generation)
185
- gateway.setPresence(presence);
186
- }
187
- catch (error) {
188
- // The previous presence stays in place, the rotation goes on
189
- if (id === generation)
190
- report('error', error);
191
- }
192
- if (id !== generation || step.duration === undefined)
193
- return;
194
- if (!(await sleep(step.duration, id)))
195
- return;
196
- }
197
- }
198
- };
199
- const restart = () => {
200
- generation++;
201
- clearTimeout(sleepTimeout);
202
- wake?.(false);
203
- void run(generation);
204
- };
205
- const refresh = () => {
206
- if (stopped)
207
- return;
208
- clearTimeout(refreshTimeout);
209
- refreshTimeout = setTimeout(restart, REFRESH_DEBOUNCE);
210
- };
211
- activeRefresh = refresh;
212
- restart();
213
- if (source.watch) {
214
- Promise.resolve()
215
- .then(() => source.watch(refresh))
216
- .then((cleanup) => {
217
- if (!cleanup)
218
- return;
219
- if (stopped)
220
- cleanup();
221
- else
222
- cleanupWatch = cleanup;
223
- })
224
- .catch((error) => report('error', error));
225
- }
226
- return () => {
227
- stopped = true;
228
- generation++;
229
- clearTimeout(sleepTimeout);
230
- clearTimeout(refreshTimeout);
231
- wake?.(false);
232
- if (activeRefresh === refresh)
233
- activeRefresh = null;
234
- try {
235
- cleanupWatch?.();
236
- }
237
- catch (error) {
238
- log.error(error);
239
- }
240
- };
241
- }
242
- function withTimeout(promise, ms) {
243
- let timeout;
244
- return Promise.race([
245
- promise,
246
- new Promise((_, reject) => {
247
- timeout = setTimeout(() => reject(new Error(`presence() took more than ${ms / 1000}s to return, keeping the previous presence.`)), ms);
248
- }),
249
- ]).finally(() => clearTimeout(timeout));
250
- }
@@ -1,110 +0,0 @@
1
- import type { Client } from '../discord/client.js';
2
- import type { APIChannel, Snowflake } from '../discord/types.js';
3
- import { Guild } from './Guild.js';
4
- import { Message } from './Message.js';
5
- import { type MessageOptions } from './utils.js';
6
- export declare const ChannelType: {
7
- readonly GuildText: 0;
8
- readonly DM: 1;
9
- readonly GuildVoice: 2;
10
- readonly GroupDM: 3;
11
- readonly GuildCategory: 4;
12
- readonly GuildAnnouncement: 5;
13
- readonly AnnouncementThread: 10;
14
- readonly PublicThread: 11;
15
- readonly PrivateThread: 12;
16
- readonly GuildStageVoice: 13;
17
- readonly GuildDirectory: 14;
18
- readonly GuildForum: 15;
19
- readonly GuildMedia: 16;
20
- };
21
- export interface FetchMessagesOptions {
22
- /** 1 to 100, defaults to 50. */
23
- limit?: number;
24
- before?: Snowflake;
25
- after?: Snowflake;
26
- around?: Snowflake;
27
- }
28
- export interface CreateThreadOptions {
29
- /** 1 to 100 characters. */
30
- name: string;
31
- /** Minutes of inactivity before the thread is hidden: 60, 1440, 4320 or 10080. */
32
- autoArchiveDuration?: 60 | 1440 | 4320 | 10080;
33
- /** Seconds between two messages of a user, 0 to 21600. */
34
- rateLimitPerUser?: number;
35
- /** `ChannelType.PrivateThread` for a private thread. Without message only. */
36
- type?: number;
37
- /** Whether non-moderators can add other non-moderators. Private threads only. */
38
- invitable?: boolean;
39
- reason?: string;
40
- }
41
- /**
42
- * A channel or thread. Events often only send its id: fields Discord didn't
43
- * send are undefined, `fetch()` returns the full channel.
44
- * https://docs.discord.com/developers/resources/channel#channel-object
45
- */
46
- export declare class Channel {
47
- readonly client: Client;
48
- readonly raw: Partial<APIChannel> & {
49
- id: Snowflake;
50
- };
51
- readonly id: Snowflake;
52
- /** See `ChannelType`. Undefined when only the id is known. */
53
- readonly type: number | undefined;
54
- readonly guildId: Snowflake | null;
55
- readonly name: string | null | undefined;
56
- readonly topic: string | null | undefined;
57
- readonly nsfw: boolean | undefined;
58
- readonly position: number | undefined;
59
- /** Category of a channel, or parent channel of a thread. */
60
- readonly parentId: Snowflake | null | undefined;
61
- readonly lastMessageId: Snowflake | null | undefined;
62
- /** Slowmode, in seconds. */
63
- readonly rateLimitPerUser: number | undefined;
64
- constructor(client: Client, raw: Partial<APIChannel> & {
65
- id: Snowflake;
66
- });
67
- /** Server of the channel, null for DMs. */
68
- get guild(): Guild | null;
69
- get createdAt(): Date;
70
- get url(): string;
71
- isThread(): boolean;
72
- isDM(): boolean;
73
- isVoice(): boolean;
74
- /** Mention, e.g. `${channel}` in a message. */
75
- toString(): string;
76
- /** https://docs.discord.com/developers/resources/message#create-message */
77
- send(options: MessageOptions): Promise<Message>;
78
- /**
79
- * Shows "Bot is typing…" for 10 seconds or until the bot sends a message.
80
- * https://docs.discord.com/developers/resources/channel#trigger-typing-indicator
81
- */
82
- sendTyping(): Promise<void>;
83
- /** https://docs.discord.com/developers/resources/message#get-channel-message */
84
- fetchMessage(id: Snowflake): Promise<Message>;
85
- /** Newest first. https://docs.discord.com/developers/resources/message#get-channel-messages */
86
- fetchMessages(options?: FetchMessagesOptions): Promise<Message[]>;
87
- /**
88
- * Deletes 2 to 100 messages at once, none older than 2 weeks.
89
- * https://docs.discord.com/developers/resources/message#bulk-delete-messages
90
- */
91
- bulkDelete(messageIds: Snowflake[], reason?: string): Promise<void>;
92
- /** https://docs.discord.com/developers/resources/channel#start-thread-without-message */
93
- createThread(options: CreateThreadOptions): Promise<Channel>;
94
- /** https://docs.discord.com/developers/resources/channel#get-channel */
95
- fetch(): Promise<Channel>;
96
- /**
97
- * Updates the channel with fields of the documented JSON params (snake_case).
98
- * https://docs.discord.com/developers/resources/channel#modify-channel
99
- */
100
- edit(data: Record<string, unknown>, reason?: string): Promise<Channel>;
101
- /** Cannot be undone for guild channels. https://docs.discord.com/developers/resources/channel#deleteclose-channel */
102
- delete(reason?: string): Promise<void>;
103
- }
104
- export declare function toThreadBody(options: Omit<CreateThreadOptions, 'reason'>): {
105
- name: string;
106
- type?: number;
107
- invitable?: boolean;
108
- auto_archive_duration?: 60 | 1440 | 4320 | 10080 | undefined;
109
- rate_limit_per_user?: number | undefined;
110
- };
@@ -1,171 +0,0 @@
1
- import { Guild } from './Guild.js';
2
- import { Message } from './Message.js';
3
- import { snowflakeDate, toMessageBody } from './utils.js';
4
- // https://docs.discord.com/developers/resources/channel#channel-object-channel-types
5
- export const ChannelType = {
6
- GuildText: 0,
7
- DM: 1,
8
- GuildVoice: 2,
9
- GroupDM: 3,
10
- GuildCategory: 4,
11
- GuildAnnouncement: 5,
12
- AnnouncementThread: 10,
13
- PublicThread: 11,
14
- PrivateThread: 12,
15
- GuildStageVoice: 13,
16
- GuildDirectory: 14,
17
- GuildForum: 15,
18
- GuildMedia: 16,
19
- };
20
- const THREAD_TYPES = [
21
- ChannelType.AnnouncementThread,
22
- ChannelType.PublicThread,
23
- ChannelType.PrivateThread,
24
- ];
25
- /**
26
- * A channel or thread. Events often only send its id: fields Discord didn't
27
- * send are undefined, `fetch()` returns the full channel.
28
- * https://docs.discord.com/developers/resources/channel#channel-object
29
- */
30
- export class Channel {
31
- client;
32
- raw;
33
- id;
34
- /** See `ChannelType`. Undefined when only the id is known. */
35
- type;
36
- guildId;
37
- name;
38
- topic;
39
- nsfw;
40
- position;
41
- /** Category of a channel, or parent channel of a thread. */
42
- parentId;
43
- lastMessageId;
44
- /** Slowmode, in seconds. */
45
- rateLimitPerUser;
46
- constructor(client, raw) {
47
- this.client = client;
48
- this.raw = raw;
49
- this.id = raw.id;
50
- this.type = raw.type;
51
- this.guildId = raw.guild_id ?? null;
52
- this.name = raw.name;
53
- this.topic = raw.topic;
54
- this.nsfw = raw.nsfw;
55
- this.position = raw.position;
56
- this.parentId = raw.parent_id;
57
- this.lastMessageId = raw.last_message_id;
58
- this.rateLimitPerUser = raw.rate_limit_per_user;
59
- }
60
- /** Server of the channel, null for DMs. */
61
- get guild() {
62
- return this.guildId ? new Guild(this.client, { id: this.guildId }) : null;
63
- }
64
- get createdAt() {
65
- return snowflakeDate(this.id);
66
- }
67
- get url() {
68
- return `https://discord.com/channels/${this.guildId ?? '@me'}/${this.id}`;
69
- }
70
- isThread() {
71
- return this.type !== undefined && THREAD_TYPES.includes(this.type);
72
- }
73
- isDM() {
74
- return this.type === ChannelType.DM || this.type === ChannelType.GroupDM;
75
- }
76
- isVoice() {
77
- return (this.type === ChannelType.GuildVoice ||
78
- this.type === ChannelType.GuildStageVoice);
79
- }
80
- /** Mention, e.g. `${channel}` in a message. */
81
- toString() {
82
- return `<#${this.id}>`;
83
- }
84
- /** https://docs.discord.com/developers/resources/message#create-message */
85
- async send(options) {
86
- const { body, files } = toMessageBody(options);
87
- const message = await this.client.rest.post(`/channels/${this.id}/messages`, {
88
- body,
89
- files,
90
- });
91
- return new Message(this.client, {
92
- guild_id: this.guildId ?? undefined,
93
- ...message,
94
- });
95
- }
96
- /**
97
- * Shows "Bot is typing…" for 10 seconds or until the bot sends a message.
98
- * https://docs.discord.com/developers/resources/channel#trigger-typing-indicator
99
- */
100
- async sendTyping() {
101
- await this.client.rest.post(`/channels/${this.id}/typing`);
102
- }
103
- /** https://docs.discord.com/developers/resources/message#get-channel-message */
104
- async fetchMessage(id) {
105
- const message = await this.client.rest.get(`/channels/${this.id}/messages/${id}`);
106
- return new Message(this.client, {
107
- guild_id: this.guildId ?? undefined,
108
- ...message,
109
- });
110
- }
111
- /** Newest first. https://docs.discord.com/developers/resources/message#get-channel-messages */
112
- async fetchMessages(options = {}) {
113
- const messages = await this.client.rest.get(`/channels/${this.id}/messages`, {
114
- query: { ...options },
115
- });
116
- return messages.map(message => new Message(this.client, {
117
- guild_id: this.guildId ?? undefined,
118
- ...message,
119
- }));
120
- }
121
- /**
122
- * Deletes 2 to 100 messages at once, none older than 2 weeks.
123
- * https://docs.discord.com/developers/resources/message#bulk-delete-messages
124
- */
125
- async bulkDelete(messageIds, reason) {
126
- await this.client.rest.post(`/channels/${this.id}/messages/bulk-delete`, {
127
- body: { messages: messageIds },
128
- reason,
129
- });
130
- }
131
- /** https://docs.discord.com/developers/resources/channel#start-thread-without-message */
132
- async createThread(options) {
133
- const { reason, ...thread } = options;
134
- const channel = await this.client.rest.post(`/channels/${this.id}/threads`, {
135
- body: toThreadBody(thread),
136
- reason,
137
- });
138
- return new Channel(this.client, channel);
139
- }
140
- /** https://docs.discord.com/developers/resources/channel#get-channel */
141
- async fetch() {
142
- return new Channel(this.client, await this.client.rest.get(`/channels/${this.id}`));
143
- }
144
- /**
145
- * Updates the channel with fields of the documented JSON params (snake_case).
146
- * https://docs.discord.com/developers/resources/channel#modify-channel
147
- */
148
- async edit(data, reason) {
149
- const channel = await this.client.rest.patch(`/channels/${this.id}`, {
150
- body: data,
151
- reason,
152
- });
153
- return new Channel(this.client, channel);
154
- }
155
- /** Cannot be undone for guild channels. https://docs.discord.com/developers/resources/channel#deleteclose-channel */
156
- async delete(reason) {
157
- await this.client.rest.delete(`/channels/${this.id}`, { reason });
158
- }
159
- }
160
- export function toThreadBody(options) {
161
- const { autoArchiveDuration, rateLimitPerUser, ...rest } = options;
162
- return {
163
- ...rest,
164
- ...(autoArchiveDuration !== undefined && {
165
- auto_archive_duration: autoArchiveDuration,
166
- }),
167
- ...(rateLimitPerUser !== undefined && {
168
- rate_limit_per_user: rateLimitPerUser,
169
- }),
170
- };
171
- }