chapterjs 0.1.2 → 0.2.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 (318) 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 +205 -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 +253 -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 +135 -0
  25. package/dist/cli/project.js +517 -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 +360 -0
  31. package/dist/commands/command.js +28 -0
  32. package/dist/commands/declaration.d.ts +77 -0
  33. package/dist/commands/declaration.js +492 -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 +47 -0
  39. package/dist/commands/tree.js +216 -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 +106 -0
  44. package/dist/components/component.d.ts +140 -0
  45. package/dist/components/component.js +39 -0
  46. package/dist/components/custom-id.d.ts +72 -0
  47. package/dist/components/custom-id.js +128 -0
  48. package/dist/components/declaration.d.ts +42 -0
  49. package/dist/components/declaration.js +342 -0
  50. package/dist/components/declared.d.ts +29 -0
  51. package/dist/components/declared.js +49 -0
  52. package/dist/components/embed.d.ts +29 -0
  53. package/dist/components/embed.js +11 -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 +245 -0
  59. package/dist/components/modal.js +398 -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 +19 -0
  65. package/dist/components/router.js +251 -0
  66. package/dist/components/select.d.ts +146 -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/declaration.d.ts +16 -0
  155. package/dist/events/declaration.js +80 -0
  156. package/dist/events/event.d.ts +45 -0
  157. package/dist/events/event.js +34 -0
  158. package/dist/events/registry.d.ts +697 -0
  159. package/dist/events/registry.js +839 -0
  160. package/dist/events/router.d.ts +46 -0
  161. package/dist/events/router.js +133 -0
  162. package/dist/gateway/errors.d.ts +18 -0
  163. package/dist/gateway/errors.js +47 -0
  164. package/dist/gateway/gateway.d.ts +64 -0
  165. package/dist/gateway/gateway.js +117 -0
  166. package/dist/gateway/identify-queue.d.ts +25 -0
  167. package/dist/gateway/identify-queue.js +29 -0
  168. package/dist/gateway/shard.d.ts +94 -0
  169. package/dist/gateway/shard.js +414 -0
  170. package/dist/gateway/state.d.ts +11 -0
  171. package/dist/gateway/state.js +184 -0
  172. package/dist/index.d.ts +57 -18
  173. package/dist/index.js +40 -12
  174. package/dist/interactions/cooldown.d.ts +33 -0
  175. package/dist/interactions/cooldown.js +74 -0
  176. package/dist/interactions/dispatch.d.ts +91 -0
  177. package/dist/interactions/dispatch.js +110 -0
  178. package/dist/loader/generated.d.ts +10 -0
  179. package/dist/loader/generated.js +80 -0
  180. package/dist/loader/hot.d.ts +13 -0
  181. package/dist/loader/hot.js +85 -0
  182. package/dist/loader/loader.d.ts +85 -0
  183. package/dist/loader/loader.js +119 -0
  184. package/dist/loader/locate.d.ts +10 -0
  185. package/dist/loader/locate.js +36 -0
  186. package/dist/loader/watch.d.ts +17 -0
  187. package/dist/loader/watch.js +66 -0
  188. package/dist/main.d.ts +2 -0
  189. package/dist/main.js +5 -0
  190. package/dist/messages/commands.d.ts +23 -0
  191. package/dist/messages/commands.js +142 -0
  192. package/dist/messages/declaration.d.ts +89 -0
  193. package/dist/messages/declaration.js +455 -0
  194. package/dist/messages/messages.d.ts +241 -0
  195. package/dist/messages/messages.js +31 -0
  196. package/dist/messages/phrases.d.ts +23 -0
  197. package/dist/messages/phrases.js +44 -0
  198. package/dist/messages/translate.d.ts +100 -0
  199. package/dist/messages/translate.js +249 -0
  200. package/dist/presence/declaration.d.ts +19 -0
  201. package/dist/presence/declaration.js +118 -0
  202. package/dist/presence/presence.d.ts +57 -0
  203. package/dist/presence/presence.js +27 -0
  204. package/dist/rest/errors.d.ts +55 -0
  205. package/dist/rest/errors.js +92 -0
  206. package/dist/rest/rate-limiter.d.ts +46 -0
  207. package/dist/rest/rate-limiter.js +153 -0
  208. package/dist/rest/rest.d.ts +63 -0
  209. package/dist/rest/rest.js +194 -0
  210. package/dist/structures/base.d.ts +48 -0
  211. package/dist/structures/base.js +84 -0
  212. package/dist/structures/channel.d.ts +380 -0
  213. package/dist/structures/channel.js +627 -0
  214. package/dist/structures/context.d.ts +30 -0
  215. package/dist/structures/context.js +7 -0
  216. package/dist/structures/emoji.d.ts +46 -0
  217. package/dist/structures/emoji.js +65 -0
  218. package/dist/structures/entities.d.ts +62 -0
  219. package/dist/structures/entities.js +226 -0
  220. package/dist/structures/guild.d.ts +348 -0
  221. package/dist/structures/guild.js +466 -0
  222. package/dist/structures/interaction.d.ts +197 -0
  223. package/dist/structures/interaction.js +396 -0
  224. package/dist/structures/invite.d.ts +38 -0
  225. package/dist/structures/invite.js +57 -0
  226. package/dist/structures/known.d.ts +28 -0
  227. package/dist/structures/known.js +58 -0
  228. package/dist/structures/member.d.ts +140 -0
  229. package/dist/structures/member.js +260 -0
  230. package/dist/structures/message.d.ts +197 -0
  231. package/dist/structures/message.js +268 -0
  232. package/dist/structures/payload.d.ts +91 -0
  233. package/dist/structures/payload.js +184 -0
  234. package/dist/structures/role.d.ts +69 -0
  235. package/dist/structures/role.js +112 -0
  236. package/dist/structures/user.d.ts +59 -0
  237. package/dist/structures/user.js +94 -0
  238. package/dist/structures/webhook.d.ts +46 -0
  239. package/dist/structures/webhook.js +79 -0
  240. package/dist/tasks/declaration.d.ts +16 -0
  241. package/dist/tasks/declaration.js +56 -0
  242. package/dist/tasks/schedule.d.ts +54 -0
  243. package/dist/tasks/schedule.js +236 -0
  244. package/dist/tasks/scheduler.d.ts +35 -0
  245. package/dist/tasks/scheduler.js +107 -0
  246. package/dist/tasks/task.d.ts +75 -0
  247. package/dist/tasks/task.js +27 -0
  248. package/dist/util/case.d.ts +13 -0
  249. package/dist/util/case.js +54 -0
  250. package/dist/util/duration.d.ts +8 -0
  251. package/dist/util/duration.js +29 -0
  252. package/dist/util/websocket.d.ts +9 -0
  253. package/dist/util/websocket.js +31 -0
  254. package/dist/voice/connection.d.ts +90 -0
  255. package/dist/voice/connection.js +494 -0
  256. package/dist/voice/dave.d.ts +109 -0
  257. package/dist/voice/dave.js +245 -0
  258. package/dist/voice/opus.d.ts +19 -0
  259. package/dist/voice/opus.js +273 -0
  260. package/dist/voice/session.d.ts +55 -0
  261. package/dist/voice/session.js +405 -0
  262. package/dist/voice/source.d.ts +22 -0
  263. package/dist/voice/source.js +195 -0
  264. package/dist/voice/transport.d.ts +43 -0
  265. package/dist/voice/transport.js +140 -0
  266. package/dist/voice/usage.d.ts +4 -0
  267. package/dist/voice/usage.js +33 -0
  268. package/package.json +26 -7
  269. package/vendor/dave/LICENSE +231 -0
  270. package/vendor/dave/libdave.d.mts +99 -0
  271. package/vendor/dave/libdave.mjs +2 -0
  272. package/vendor/dave/libdave.wasm +0 -0
  273. package/dist/components.d.ts +0 -97
  274. package/dist/components.js +0 -260
  275. package/dist/context.d.ts +0 -72
  276. package/dist/context.js +0 -273
  277. package/dist/discord/client.d.ts +0 -35
  278. package/dist/discord/client.js +0 -66
  279. package/dist/discord/constants.d.ts +0 -49
  280. package/dist/discord/constants.js +0 -61
  281. package/dist/discord/events.d.ts +0 -129
  282. package/dist/discord/events.js +0 -102
  283. package/dist/discord/gateway.d.ts +0 -61
  284. package/dist/discord/gateway.js +0 -320
  285. package/dist/discord/payloads.d.ts +0 -275
  286. package/dist/discord/payloads.js +0 -3
  287. package/dist/discord/presence.d.ts +0 -42
  288. package/dist/discord/presence.js +0 -51
  289. package/dist/discord/rest.d.ts +0 -49
  290. package/dist/discord/rest.js +0 -271
  291. package/dist/discord/types.d.ts +0 -334
  292. package/dist/discord/types.js +0 -4
  293. package/dist/events.d.ts +0 -94
  294. package/dist/events.js +0 -255
  295. package/dist/presence.d.ts +0 -92
  296. package/dist/presence.js +0 -250
  297. package/dist/structures/Channel.d.ts +0 -110
  298. package/dist/structures/Channel.js +0 -171
  299. package/dist/structures/Guild.d.ts +0 -70
  300. package/dist/structures/Guild.js +0 -105
  301. package/dist/structures/Interaction.d.ts +0 -113
  302. package/dist/structures/Interaction.js +0 -274
  303. package/dist/structures/Member.d.ts +0 -70
  304. package/dist/structures/Member.js +0 -124
  305. package/dist/structures/Message.d.ts +0 -87
  306. package/dist/structures/Message.js +0 -182
  307. package/dist/structures/Reaction.d.ts +0 -38
  308. package/dist/structures/Reaction.js +0 -64
  309. package/dist/structures/Role.d.ts +0 -43
  310. package/dist/structures/Role.js +0 -77
  311. package/dist/structures/User.d.ts +0 -41
  312. package/dist/structures/User.js +0 -79
  313. package/dist/structures/utils.d.ts +0 -72
  314. package/dist/structures/utils.js +0 -59
  315. package/dist/utils/errors.d.ts +0 -5
  316. package/dist/utils/errors.js +0 -28
  317. package/dist/utils/modules.d.ts +0 -39
  318. package/dist/utils/modules.js +0 -156
@@ -0,0 +1,268 @@
1
+ import { CreateMessage, CreateReaction, CrosspostMessage, DeleteAllReactions, DeleteAllReactionsForEmoji, DeleteMessage, DeleteOwnReaction, DeleteUserReaction, EditMessage, GetChannelMessage, GetReactions, PinMessage, StartThreadFromMessage, UnpinMessage, } from '../discord/endpoints.js';
2
+ import { reactionEmoji } from '../discord/formatting.js';
3
+ import { MessageFlags, MessageType, } from '../discord/types/message.js';
4
+ import { toCamelCase, toSnakeCase } from '../util/case.js';
5
+ import { ctxOf, dataOf, idOf, IdStructure, toDate } from './base.js';
6
+ import { findGuild, knownChannel, knownMember } from './known.js';
7
+ import { buildMessage, } from './payload.js';
8
+ import { translatorOf } from '../messages/translate.js';
9
+ function emojiPath(emoji) {
10
+ if (typeof emoji !== 'string')
11
+ return reactionEmoji(emoji);
12
+ // Accepts what users copy from Discord: `<:name:id>` and `<a:name:id>`.
13
+ const custom = /^<a?:(\w+):(\d+)>$/.exec(emoji.trim());
14
+ if (custom)
15
+ return `${custom[1]}:${custom[2]}`;
16
+ if (emoji.trim() === '') {
17
+ throw new TypeError('The emoji is empty: pass one like "👍".');
18
+ }
19
+ return emoji.trim();
20
+ }
21
+ /**
22
+ * A message sent in a channel.
23
+ * @see https://docs.discord.com/developers/resources/message#message-object
24
+ */
25
+ export class Message extends IdStructure {
26
+ /** Who wrote the message. */
27
+ author;
28
+ /** The users mentioned in the message. */
29
+ mentions;
30
+ constructor(ctx, data, author, mentions) {
31
+ super(ctx, data);
32
+ this.author = author;
33
+ this.mentions = mentions;
34
+ }
35
+ /** The id of the channel of the message. */
36
+ get channelId() {
37
+ return dataOf(this).channel_id;
38
+ }
39
+ /** The id of the server; `null` for a private message. */
40
+ get guildId() {
41
+ return (dataOf(this).guild_id ??
42
+ ctxOf(this).cache.channels.get(this.channelId)?.guildId ??
43
+ null);
44
+ }
45
+ /** The channel of the message, when it is known. */
46
+ get channel() {
47
+ const channel = ctxOf(this).cache.channels.get(this.channelId) ?? knownChannel(this);
48
+ return channel?.isTextBased() ? channel : null;
49
+ }
50
+ /** The server of the message; `null` for a private message. */
51
+ get guild() {
52
+ return findGuild(this, this.guildId);
53
+ }
54
+ /** The author as a member of the server, when it is known. */
55
+ get member() {
56
+ return this.guild?.members.get(this.author.id) ?? knownMember(this) ?? null;
57
+ }
58
+ /**
59
+ * The text of the message. Empty when the bot is not allowed to read it:
60
+ * reading the messages of others needs the Message Content intent.
61
+ */
62
+ get content() {
63
+ return dataOf(this).content ?? '';
64
+ }
65
+ /** The kind of message, as a value of `MessageType` (a regular one, a reply, a join notice...). */
66
+ get type() {
67
+ return dataOf(this).type;
68
+ }
69
+ /** When the message was last edited; `null` when it never was. */
70
+ get editedAt() {
71
+ return toDate(dataOf(this).edited_timestamp);
72
+ }
73
+ /** Whether the message is pinned. */
74
+ get pinned() {
75
+ return dataOf(this).pinned ?? false;
76
+ }
77
+ /** Whether the message was read aloud. */
78
+ get tts() {
79
+ return dataOf(this).tts ?? false;
80
+ }
81
+ /** The embeds of the message. */
82
+ get embeds() {
83
+ return toCamelCase(dataOf(this).embeds ?? []);
84
+ }
85
+ /** The files attached to the message. */
86
+ get attachments() {
87
+ return toCamelCase(dataOf(this).attachments ?? []);
88
+ }
89
+ /** The reactions on the message, one entry per emoji. */
90
+ get reactions() {
91
+ return toCamelCase(dataOf(this).reactions ?? []);
92
+ }
93
+ /** Whether the message mentions @everyone or @here. */
94
+ get mentionsEveryone() {
95
+ return dataOf(this).mention_everyone ?? false;
96
+ }
97
+ /** The ids of the roles mentioned in the message. */
98
+ get mentionedRoleIds() {
99
+ return dataOf(this).mention_roles ?? [];
100
+ }
101
+ /** The flags of the message, by name (`Ephemeral`, `SuppressEmbeds`...). */
102
+ get flags() {
103
+ const bits = dataOf(this).flags ?? 0;
104
+ return Object.keys(MessageFlags).filter(name => (bits & MessageFlags[name]) !== 0);
105
+ }
106
+ /** The id of the webhook that sent the message, when one did. */
107
+ get webhookId() {
108
+ return dataOf(this).webhook_id ?? null;
109
+ }
110
+ /** The id of the message this one replies to, when it is a reply. */
111
+ get repliedMessageId() {
112
+ return dataOf(this).message_reference?.message_id ?? null;
113
+ }
114
+ /** Whether a person wrote it: not a bot, a webhook or Discord itself. */
115
+ get isFromUser() {
116
+ return (!this.author.bot &&
117
+ !this.author.system &&
118
+ this.webhookId === null &&
119
+ (this.type === MessageType.Default || this.type === MessageType.Reply));
120
+ }
121
+ /** The link that opens the message in Discord. */
122
+ get url() {
123
+ return `https://discord.com/channels/${this.guildId ?? '@me'}/${this.channelId}/${this.id}`;
124
+ }
125
+ /** Asks Discord for the latest version of the message. */
126
+ async fetch() {
127
+ const { rest, entities } = ctxOf(this);
128
+ const raw = await rest.request(GetChannelMessage, [
129
+ this.channelId,
130
+ this.id,
131
+ ]);
132
+ return entities.message(raw, this.guildId ?? undefined);
133
+ }
134
+ /**
135
+ * Answers the message, in the same channel.
136
+ * @see https://docs.discord.com/developers/resources/message#create-message
137
+ */
138
+ async reply(message) {
139
+ const options = typeof message === 'string' ? { content: message } : message;
140
+ return sendMessage(ctxOf(this), this.channelId, { ...options, replyTo: this.id }, this.guildId ?? undefined);
141
+ }
142
+ /**
143
+ * Changes the message. Only the content, embeds, components and files of
144
+ * a message the bot wrote can change.
145
+ * @see https://docs.discord.com/developers/resources/message#edit-message
146
+ */
147
+ async edit(message) {
148
+ const { rest, entities } = ctxOf(this);
149
+ const { body, files } = buildMessage(message, {
150
+ edit: true,
151
+ t: translatorOf(ctxOf(this), { guild: this.guild }),
152
+ });
153
+ const raw = await rest.request(EditMessage, [this.channelId, this.id], {
154
+ body,
155
+ files,
156
+ });
157
+ return entities.message(raw, this.guildId ?? undefined);
158
+ }
159
+ /**
160
+ * Deletes the message.
161
+ * @see https://docs.discord.com/developers/resources/message#delete-message
162
+ */
163
+ async delete(reason) {
164
+ await ctxOf(this).rest.request(DeleteMessage, [this.channelId, this.id], {
165
+ reason,
166
+ });
167
+ }
168
+ /**
169
+ * Adds a reaction of the bot to the message.
170
+ * @see https://docs.discord.com/developers/resources/message#create-reaction
171
+ */
172
+ async react(emoji) {
173
+ await ctxOf(this).rest.request(CreateReaction, [
174
+ this.channelId,
175
+ this.id,
176
+ emojiPath(emoji),
177
+ ]);
178
+ }
179
+ /**
180
+ * Removes a reaction: of the bot, or of the given user.
181
+ * @see https://docs.discord.com/developers/resources/message#delete-user-reaction
182
+ */
183
+ async removeReaction(emoji, user) {
184
+ const { rest } = ctxOf(this);
185
+ const path = [this.channelId, this.id, emojiPath(emoji)];
186
+ if (user === undefined)
187
+ await rest.request(DeleteOwnReaction, [...path]);
188
+ else
189
+ await rest.request(DeleteUserReaction, [...path, idOf(user)]);
190
+ }
191
+ /**
192
+ * Removes every reaction of the message, or every reaction of one emoji.
193
+ * @see https://docs.discord.com/developers/resources/message#delete-all-reactions
194
+ */
195
+ async clearReactions(emoji) {
196
+ const { rest } = ctxOf(this);
197
+ if (emoji === undefined) {
198
+ await rest.request(DeleteAllReactions, [this.channelId, this.id]);
199
+ }
200
+ else {
201
+ await rest.request(DeleteAllReactionsForEmoji, [
202
+ this.channelId,
203
+ this.id,
204
+ emojiPath(emoji),
205
+ ]);
206
+ }
207
+ }
208
+ /**
209
+ * The users who reacted with an emoji (100 at most per call).
210
+ * @see https://docs.discord.com/developers/resources/message#get-reactions
211
+ */
212
+ async fetchReactionUsers(emoji, options = {}) {
213
+ const { rest, entities } = ctxOf(this);
214
+ const raw = await rest.request(GetReactions, [this.channelId, this.id, emojiPath(emoji)], { query: options });
215
+ return raw.map(user => entities.user(user));
216
+ }
217
+ /**
218
+ * Pins the message in its channel.
219
+ * @see https://docs.discord.com/developers/resources/message#pin-message
220
+ */
221
+ async pin(reason) {
222
+ await ctxOf(this).rest.request(PinMessage, [this.channelId, this.id], {
223
+ reason,
224
+ });
225
+ }
226
+ /**
227
+ * Unpins the message.
228
+ * @see https://docs.discord.com/developers/resources/message#unpin-message
229
+ */
230
+ async unpin(reason) {
231
+ await ctxOf(this).rest.request(UnpinMessage, [this.channelId, this.id], {
232
+ reason,
233
+ });
234
+ }
235
+ /**
236
+ * Publishes a message of an announcement channel to the servers that
237
+ * follow it.
238
+ * @see https://docs.discord.com/developers/resources/message#crosspost-message
239
+ */
240
+ async crosspost() {
241
+ const { rest, entities } = ctxOf(this);
242
+ const raw = await rest.request(CrosspostMessage, [this.channelId, this.id]);
243
+ return entities.message(raw, this.guildId ?? undefined);
244
+ }
245
+ /**
246
+ * Starts a thread from the message.
247
+ * @see https://docs.discord.com/developers/resources/channel#start-thread-from-message
248
+ */
249
+ async startThread(options, reason) {
250
+ const { rest, entities } = ctxOf(this);
251
+ const raw = await rest.request(StartThreadFromMessage, [this.channelId, this.id], { body: toSnakeCase(options), reason });
252
+ return entities.channel(raw);
253
+ }
254
+ }
255
+ /** One mechanism to send a message, used by channels, replies and users. */
256
+ export async function sendMessage(ctx, channelId, message, guildId) {
257
+ const { body, files } = buildMessage(message, {
258
+ // What the server reads, or the default language in private messages.
259
+ t: translatorOf(ctx, {
260
+ guild: guildId ? ctx.cache.guilds.get(guildId) : null,
261
+ }),
262
+ });
263
+ const raw = await ctx.rest.request(CreateMessage, [channelId], {
264
+ body,
265
+ files,
266
+ });
267
+ return ctx.entities.message(raw, guildId);
268
+ }
@@ -0,0 +1,91 @@
1
+ import { type AssetFile } from '../assets/asset.js';
2
+ import { type EmbedDeclaration } from '../components/embed.js';
3
+ import type { MessageComponent } from '../components/instance.js';
4
+ import type { Snowflake } from '../discord/types/common.js';
5
+ import { type CreateMessageJSONParams, type RawAllowedMentions, type RawEmbed } from '../discord/types/message.js';
6
+ import type { RawPollCreateRequest } from '../discord/types/poll.js';
7
+ import type { RestFile } from '../rest/rest.js';
8
+ import { type Camelize } from '../util/case.js';
9
+ import type { Translator } from '../messages/messages.js';
10
+ /**
11
+ * A rich box in a message: title, description, fields, image...
12
+ * @see https://docs.discord.com/developers/resources/message#embed-object
13
+ */
14
+ export type Embed = Camelize<RawEmbed>;
15
+ /**
16
+ * Who a message is allowed to notify.
17
+ * @see https://docs.discord.com/developers/resources/message#allowed-mentions-object
18
+ */
19
+ export type AllowedMentions = Camelize<RawAllowedMentions>;
20
+ /**
21
+ * A poll to attach to a message.
22
+ * @see https://docs.discord.com/developers/resources/poll#poll-create-request-object
23
+ */
24
+ export type PollInput = Camelize<RawPollCreateRequest>;
25
+ /** A file to attach to a message. */
26
+ export interface FileInput {
27
+ /** The name of the file, with its extension: `chart.png`. */
28
+ name: string;
29
+ /** The content of the file. */
30
+ data: Blob | Uint8Array | ArrayBuffer | string;
31
+ /** What the file shows, for people who can't see it. */
32
+ description?: string;
33
+ /** Hides the file until it is clicked. */
34
+ spoiler?: boolean;
35
+ /** The media type of the file (`image/png`); guessed from the name when missing. */
36
+ contentType?: string;
37
+ }
38
+ /** What a message can contain, and how it is sent. */
39
+ export interface MessageOptions {
40
+ /** The text of the message (up to 2000 characters). */
41
+ content?: string;
42
+ /** Up to 10 embeds: written here, or declared with `embed()`. */
43
+ embeds?: (Embed | EmbedDeclaration<[]>)[];
44
+ /**
45
+ * Buttons, select menus and layout components, made by ChapterJS: the
46
+ * components declared with `button()`, `select()`... and `row()`, `text()`, `container()`...
47
+ */
48
+ components?: MessageComponent[];
49
+ /** Up to 10 files to attach: their content, or `asset()` for a file of `public/`. */
50
+ files?: (FileInput | AssetFile)[];
51
+ /** Who the message is allowed to notify. */
52
+ allowedMentions?: AllowedMentions;
53
+ /** The ids of up to 3 stickers of the server. */
54
+ stickers?: Snowflake[];
55
+ /** A poll to attach to the message. */
56
+ poll?: PollInput;
57
+ /** Reads the message aloud. */
58
+ tts?: boolean;
59
+ /** Sends the message without a notification sound. */
60
+ silent?: boolean;
61
+ /** Does not show the previews of the links of the message. */
62
+ suppressEmbeds?: boolean;
63
+ /** The message to reply to. */
64
+ replyTo?: Snowflake | {
65
+ id: Snowflake;
66
+ };
67
+ }
68
+ /** A message to send: its text, or its options. */
69
+ export type MessageInput = string | MessageOptions;
70
+ /** What can be changed in a message that was already sent. */
71
+ export type MessageEditOptions = Pick<MessageOptions, 'content' | 'embeds' | 'components' | 'files' | 'allowedMentions' | 'suppressEmbeds'>;
72
+ export interface BuiltMessage {
73
+ body: CreateMessageJSONParams;
74
+ files: RestFile[] | undefined;
75
+ }
76
+ /**
77
+ * Checks one embed against the limits of Discord. `name` is how the embed
78
+ * is called in messages ("embed 1", "this embed").
79
+ * @returns how many characters it holds, which add up per message
80
+ * @see https://docs.discord.com/developers/resources/message#embed-object-embed-limits
81
+ */
82
+ export declare function checkEmbed(embed: Embed, name: string): number;
83
+ /**
84
+ * Validates a message and builds the request that sends it (or edits it).
85
+ * @see https://docs.discord.com/developers/resources/message#create-message
86
+ */
87
+ export declare function buildMessage(input: MessageInput, { t, edit, }?: {
88
+ /** `t` for who will read the message: what its components may be computed from. */
89
+ t?: Translator;
90
+ edit?: boolean;
91
+ }): BuiltMessage;
@@ -0,0 +1,184 @@
1
+ // Turns what users pass to send or edit a message into what Discord
2
+ // expects. Used by everything that sends a message: channels, replies,
3
+ // webhooks, and later interactions.
4
+ import { isAssetFile, readAsset } from '../assets/asset.js';
5
+ import { isEmbedDeclaration, } from '../components/embed.js';
6
+ import { renderComponents } from '../components/render.js';
7
+ import { Limits } from '../discord/api.js';
8
+ import { MessageFlags, } from '../discord/types/message.js';
9
+ import { toSnakeCase } from '../util/case.js';
10
+ import { missingTranslator } from '../messages/translate.js';
11
+ const count = (text) => text?.trim().length ?? 0;
12
+ /**
13
+ * Checks one embed against the limits of Discord. `name` is how the embed
14
+ * is called in messages ("embed 1", "this embed").
15
+ * @returns how many characters it holds, which add up per message
16
+ * @see https://docs.discord.com/developers/resources/message#embed-object-embed-limits
17
+ */
18
+ export function checkEmbed(embed, name) {
19
+ if (typeof embed !== 'object' || embed === null) {
20
+ throw new TypeError(`${name} is an object like { title: '...' }, got ${embed === null ? 'null' : typeof embed}.`);
21
+ }
22
+ let total = 0;
23
+ const check = (what, text, max) => {
24
+ const length = count(text);
25
+ total += length;
26
+ if (length > max) {
27
+ throw new RangeError(`The ${what} of ${name} is ${length} characters long: Discord accepts ${max} at most.`);
28
+ }
29
+ };
30
+ check('title', embed.title, Limits.EmbedTitle);
31
+ check('description', embed.description, Limits.EmbedDescription);
32
+ check('footer text', embed.footer?.text, Limits.EmbedFooterText);
33
+ check('author name', embed.author?.name, Limits.EmbedAuthorName);
34
+ const fields = embed.fields ?? [];
35
+ if (fields.length > Limits.EmbedFields) {
36
+ throw new RangeError(`${name[0].toUpperCase()}${name.slice(1)} has ${fields.length} fields: Discord accepts ${Limits.EmbedFields} at most.`);
37
+ }
38
+ fields.forEach((field, at) => {
39
+ check(`name of field ${at + 1}`, field.name, Limits.EmbedFieldName);
40
+ check(`value of field ${at + 1}`, field.value, Limits.EmbedFieldValue);
41
+ });
42
+ return total;
43
+ }
44
+ /** The embeds of a message, with the ones declared with `embed()` called. */
45
+ function resolveEmbeds(embeds) {
46
+ if (!Array.isArray(embeds)) {
47
+ throw new TypeError(`The embeds of a message are a list, got ${typeof embeds}.`);
48
+ }
49
+ return embeds.map((embed, index) => {
50
+ if (isEmbedDeclaration(embed))
51
+ return embed();
52
+ if (typeof embed === 'function') {
53
+ throw new TypeError(`Embed ${index + 1} of the message is a function: an embed is an object like { title: '...' }, or one declared with embed().`);
54
+ }
55
+ return embed;
56
+ });
57
+ }
58
+ function checkEmbeds(embeds) {
59
+ if (embeds.length > Limits.MessageEmbeds) {
60
+ throw new RangeError(`A message has ${Limits.MessageEmbeds} embeds at most, got ${embeds.length}.`);
61
+ }
62
+ let total = 0;
63
+ embeds.forEach((embed, index) => {
64
+ total += checkEmbed(embed, `embed ${index + 1}`);
65
+ });
66
+ if (total > Limits.EmbedTotal) {
67
+ throw new RangeError(`The embeds of the message contain ${total} characters in total: Discord accepts ${Limits.EmbedTotal} at most.`);
68
+ }
69
+ }
70
+ /**
71
+ * Validates a message and builds the request that sends it (or edits it).
72
+ * @see https://docs.discord.com/developers/resources/message#create-message
73
+ */
74
+ export function buildMessage(input, { t = missingTranslator(null), edit = false, } = {}) {
75
+ if (typeof input === 'string')
76
+ input = { content: input };
77
+ if (typeof input !== 'object' || input === null) {
78
+ throw new TypeError(`A message is a text or an object like { content: "Hello" }, got ${input === null ? 'null' : typeof input}.`);
79
+ }
80
+ const { content, components, files, stickers, poll } = input;
81
+ const embeds = input.embeds ? resolveEmbeds(input.embeds) : undefined;
82
+ if (content !== undefined && typeof content !== 'string') {
83
+ throw new TypeError(`The content of a message is a text, got ${typeof content}.`);
84
+ }
85
+ if (content !== undefined && content.length > Limits.MessageContent) {
86
+ throw new RangeError(`The message is ${content.length} characters long: Discord accepts ${Limits.MessageContent} at most. Split it in several messages or put the text in a file.`);
87
+ }
88
+ if (embeds)
89
+ checkEmbeds(embeds);
90
+ const rendered = components ? renderComponents(components, t) : undefined;
91
+ if (rendered?.v2 && (count(content) > 0 || embeds?.length)) {
92
+ throw new TypeError('A message built with texts, sections, galleries, files, separators or containers takes no content and no embeds: Discord shows components only. Put the text in text() and the embed in a container().');
93
+ }
94
+ if (rendered?.v2 && poll) {
95
+ throw new TypeError("A message built with components only can't have a poll.");
96
+ }
97
+ if (stickers && stickers.length > Limits.MessageStickers) {
98
+ throw new RangeError(`A message has ${Limits.MessageStickers} stickers at most, got ${stickers.length}.`);
99
+ }
100
+ if (files && files.length > Limits.MessageAttachments) {
101
+ throw new RangeError(`A message has ${Limits.MessageAttachments} files at most, got ${files.length}.`);
102
+ }
103
+ const empty = count(content) === 0 &&
104
+ !embeds?.length &&
105
+ !rendered?.raw.length &&
106
+ !files?.length &&
107
+ !stickers?.length &&
108
+ !poll;
109
+ if (empty && !edit) {
110
+ throw new TypeError('The message is empty: give it a content, an embed, a file, a component, a sticker or a poll.');
111
+ }
112
+ const body = {};
113
+ if (content !== undefined)
114
+ body.content = content;
115
+ if (embeds)
116
+ body.embeds = toSnakeCase(embeds);
117
+ if (rendered)
118
+ body.components = rendered.raw;
119
+ if (input.allowedMentions) {
120
+ body.allowed_mentions = toSnakeCase(input.allowedMentions);
121
+ }
122
+ if (stickers)
123
+ body.sticker_ids = stickers;
124
+ if (poll)
125
+ body.poll = toSnakeCase(poll);
126
+ if (input.tts)
127
+ body.tts = true;
128
+ let flags = 0;
129
+ if (input.silent)
130
+ flags |= MessageFlags.SuppressNotifications;
131
+ if (input.suppressEmbeds)
132
+ flags |= MessageFlags.SuppressEmbeds;
133
+ // Discord wants to be told when a message is made of components only.
134
+ if (rendered?.v2)
135
+ flags |= MessageFlags.IsComponentsV2;
136
+ if (flags !== 0 || (edit && input.suppressEmbeds === false)) {
137
+ body.flags = flags;
138
+ }
139
+ if (input.replyTo !== undefined) {
140
+ const id = typeof input.replyTo === 'string' ? input.replyTo : input.replyTo.id;
141
+ body.message_reference = { message_id: id };
142
+ }
143
+ let restFiles;
144
+ if (files?.length) {
145
+ restFiles = files.map(file => {
146
+ if (typeof file?.name !== 'string' || file.name.trim() === '') {
147
+ throw new TypeError('Every file needs a name with its extension, like "chart.png".');
148
+ }
149
+ if (isAssetFile(file)) {
150
+ return {
151
+ name: file.name,
152
+ data: () => readAsset(file),
153
+ contentType: file.contentType,
154
+ };
155
+ }
156
+ if (typeof file.data === 'function' ||
157
+ (typeof file.data !== 'string' && typeof file.data !== 'object') ||
158
+ file.data === null) {
159
+ throw new TypeError(`The data of the file ${file.name} is its content (a text, a Buffer, an ArrayBuffer or a Blob), or asset('...') for a file of public/.`);
160
+ }
161
+ return {
162
+ name: file.name,
163
+ data: file.data,
164
+ contentType: file.contentType,
165
+ };
166
+ });
167
+ const names = new Set();
168
+ for (const { name } of restFiles) {
169
+ if (names.has(name)) {
170
+ throw new TypeError(`Two files of the message are named ${name}: Discord tells them apart by their name. Give one another name (asset(path, { name: '...' })).`);
171
+ }
172
+ names.add(name);
173
+ }
174
+ // Each file is described by the attachment whose id is its index.
175
+ // https://docs.discord.com/developers/reference#uploading-files
176
+ body.attachments = files.map((file, index) => ({
177
+ id: index,
178
+ filename: file.name,
179
+ ...(file.description ? { description: file.description } : {}),
180
+ ...(file.spoiler ? { is_spoiler: true } : {}),
181
+ }));
182
+ }
183
+ return { body, files: restFiles };
184
+ }
@@ -0,0 +1,69 @@
1
+ import { type ImageOptions } from '../discord/cdn.js';
2
+ import { Permissions } from '../discord/permissions.js';
3
+ import type { Snowflake } from '../discord/types/common.js';
4
+ import type { ModifyGuildRoleJSONParams } from '../discord/types/guild.js';
5
+ import type { RawRole } from '../discord/types/permissions.js';
6
+ import { type Camelize } from '../util/case.js';
7
+ import { IdStructure } from './base.js';
8
+ import type { Context } from './context.js';
9
+ import type { Guild } from './guild.js';
10
+ import type { GuildMember } from './member.js';
11
+ /**
12
+ * What `edit()` takes on a role: only what is passed changes. Permissions
13
+ * are given by name, as a list of names or as a `Permissions` set.
14
+ * @see https://docs.discord.com/developers/resources/guild#modify-guild-role-json-params
15
+ */
16
+ export type RoleEditOptions = Camelize<Omit<ModifyGuildRoleJSONParams, 'permissions'>> & {
17
+ permissions?: Permissions | ConstructorParameters<typeof Permissions>[0];
18
+ };
19
+ /**
20
+ * A role of a server.
21
+ * @see https://docs.discord.com/developers/topics/permissions#role-object
22
+ */
23
+ export declare class Role extends IdStructure<RawRole> {
24
+ /** The id of the server of the role. */
25
+ readonly guildId: Snowflake;
26
+ constructor(ctx: Context, data: RawRole, guildId: Snowflake);
27
+ /** The server of the role. */
28
+ get guild(): Guild;
29
+ /** The name of the role. */
30
+ get name(): string;
31
+ /** The color as a number (`0xff0000`); `0` means no color. */
32
+ get color(): number;
33
+ /** Whether members with this role are shown apart in the member list. */
34
+ get hoist(): boolean;
35
+ /** Where the role is in the hierarchy: the higher, the more powerful. */
36
+ get position(): number;
37
+ /** What the role allows in the server. */
38
+ get permissions(): Permissions;
39
+ /** Whether the role belongs to an integration (a bot, boosters...). */
40
+ get managed(): boolean;
41
+ /** Whether everyone can mention the role. */
42
+ get mentionable(): boolean;
43
+ /** The standard emoji shown next to the role, when it has one. */
44
+ get unicodeEmoji(): string | null;
45
+ /** Whether this is the @everyone role, which every member has. */
46
+ get isEveryone(): boolean;
47
+ /** The members that have this role, among the ones the bot knows. */
48
+ get members(): GuildMember[];
49
+ /** The URL of the icon of the role, when it has one. */
50
+ iconURL(options?: ImageOptions): string | null;
51
+ /**
52
+ * Whether this role is above another one in the hierarchy. With the same
53
+ * position, the oldest role is above.
54
+ * @see https://docs.discord.com/developers/topics/permissions#permission-hierarchy
55
+ */
56
+ isHigherThan(other: Role): boolean;
57
+ /**
58
+ * Changes the role.
59
+ * @see https://docs.discord.com/developers/resources/guild#modify-guild-role
60
+ */
61
+ edit(options: RoleEditOptions, reason?: string): Promise<Role>;
62
+ /**
63
+ * Deletes the role.
64
+ * @see https://docs.discord.com/developers/resources/guild#delete-guild-role
65
+ */
66
+ delete(reason?: string): Promise<void>;
67
+ /** `<@&id>`: mentions the role when put in a message. */
68
+ toString(): string;
69
+ }