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.
- package/dist/assets/asset.d.ts +46 -0
- package/dist/assets/asset.js +86 -0
- package/dist/assets/public.d.ts +19 -0
- package/dist/assets/public.js +120 -0
- package/dist/cache/cache.d.ts +62 -0
- package/dist/cache/cache.js +80 -0
- package/dist/cache/store.d.ts +45 -0
- package/dist/cache/store.js +53 -0
- package/dist/cli/build.d.ts +41 -0
- package/dist/cli/build.js +206 -0
- package/dist/cli/cli.js +108 -25
- package/dist/cli/cluster.d.ts +70 -0
- package/dist/cli/cluster.js +213 -0
- package/dist/cli/dev.d.ts +18 -1
- package/dist/cli/dev.js +252 -198
- package/dist/cli/env.d.ts +31 -0
- package/dist/cli/env.js +93 -0
- package/dist/cli/log.d.ts +13 -0
- package/dist/cli/log.js +17 -0
- package/dist/cli/node-version.d.ts +8 -0
- package/dist/cli/node-version.js +13 -0
- package/dist/cli/preflight.d.ts +36 -0
- package/dist/cli/preflight.js +122 -0
- package/dist/cli/project.d.ts +122 -0
- package/dist/cli/project.js +452 -0
- package/dist/cli/start.d.ts +25 -0
- package/dist/cli/start.js +225 -0
- package/dist/commands/autocomplete.d.ts +13 -0
- package/dist/commands/autocomplete.js +159 -0
- package/dist/commands/command.d.ts +346 -0
- package/dist/commands/command.js +28 -0
- package/dist/commands/convention.d.ts +64 -0
- package/dist/commands/convention.js +464 -0
- package/dist/commands/register.d.ts +18 -0
- package/dist/commands/register.js +42 -0
- package/dist/commands/router.d.ts +20 -0
- package/dist/commands/router.js +228 -0
- package/dist/commands/tree.d.ts +43 -0
- package/dist/commands/tree.js +206 -0
- package/dist/commands/twins.d.ts +15 -0
- package/dist/commands/twins.js +78 -0
- package/dist/components/button.d.ts +79 -0
- package/dist/components/button.js +108 -0
- package/dist/components/component.d.ts +140 -0
- package/dist/components/component.js +39 -0
- package/dist/components/convention.d.ts +35 -0
- package/dist/components/convention.js +339 -0
- package/dist/components/custom-id.d.ts +72 -0
- package/dist/components/custom-id.js +128 -0
- package/dist/components/embed.d.ts +28 -0
- package/dist/components/embed.js +11 -0
- package/dist/components/file.d.ts +30 -0
- package/dist/components/file.js +52 -0
- package/dist/components/instance.d.ts +100 -0
- package/dist/components/instance.js +86 -0
- package/dist/components/layout.d.ts +103 -0
- package/dist/components/layout.js +279 -0
- package/dist/components/modal.d.ts +244 -0
- package/dist/components/modal.js +399 -0
- package/dist/components/options.d.ts +41 -0
- package/dist/components/options.js +101 -0
- package/dist/components/render.d.ts +12 -0
- package/dist/components/render.js +58 -0
- package/dist/components/router.d.ts +18 -0
- package/dist/components/router.js +256 -0
- package/dist/components/select.d.ts +144 -0
- package/dist/components/select.js +179 -0
- package/dist/core/bot.d.ts +99 -0
- package/dist/core/bot.js +174 -0
- package/dist/core/memory.d.ts +66 -0
- package/dist/core/memory.js +115 -0
- package/dist/discord/api.d.ts +112 -0
- package/dist/discord/api.js +115 -0
- package/dist/discord/cdn.d.ts +67 -0
- package/dist/discord/cdn.js +100 -0
- package/dist/discord/codes.d.ts +171 -0
- package/dist/discord/codes.js +421 -0
- package/dist/discord/endpoint.d.ts +56 -0
- package/dist/discord/endpoint.js +53 -0
- package/dist/discord/endpoints.d.ts +1529 -0
- package/dist/discord/endpoints.js +1139 -0
- package/dist/discord/formatting.d.ts +67 -0
- package/dist/discord/formatting.js +87 -0
- package/dist/discord/index.d.ts +10 -0
- package/dist/discord/index.js +13 -0
- package/dist/discord/intents.d.ts +48 -0
- package/dist/discord/intents.js +128 -0
- package/dist/discord/permissions.d.ts +94 -0
- package/dist/discord/permissions.js +185 -0
- package/dist/discord/snowflake.d.ts +21 -0
- package/dist/discord/snowflake.js +36 -0
- package/dist/discord/types/application-command.d.ts +332 -0
- package/dist/discord/types/application-command.js +48 -0
- package/dist/discord/types/application-role-connection-metadata.d.ts +42 -0
- package/dist/discord/types/application-role-connection-metadata.js +22 -0
- package/dist/discord/types/application.d.ts +208 -0
- package/dist/discord/types/application.js +48 -0
- package/dist/discord/types/audit-log.d.ts +255 -0
- package/dist/discord/types/audit-log.js +144 -0
- package/dist/discord/types/auto-moderation.d.ts +167 -0
- package/dist/discord/types/auto-moderation.js +52 -0
- package/dist/discord/types/channel.d.ts +557 -0
- package/dist/discord/types/channel.js +88 -0
- package/dist/discord/types/common.d.ts +54 -0
- package/dist/discord/types/common.js +38 -0
- package/dist/discord/types/component.d.ts +775 -0
- package/dist/discord/types/component.js +76 -0
- package/dist/discord/types/emoji.d.ts +74 -0
- package/dist/discord/types/emoji.js +1 -0
- package/dist/discord/types/entitlement.d.ts +84 -0
- package/dist/discord/types/entitlement.js +22 -0
- package/dist/discord/types/gateway-events.d.ts +1148 -0
- package/dist/discord/types/gateway-events.js +54 -0
- package/dist/discord/types/gateway.d.ts +38 -0
- package/dist/discord/types/gateway.js +1 -0
- package/dist/discord/types/guild-scheduled-event.d.ts +257 -0
- package/dist/discord/types/guild-scheduled-event.js +68 -0
- package/dist/discord/types/guild-template.d.ts +51 -0
- package/dist/discord/types/guild-template.js +1 -0
- package/dist/discord/types/guild.d.ts +910 -0
- package/dist/discord/types/guild.js +153 -0
- package/dist/discord/types/index.d.ts +31 -0
- package/dist/discord/types/index.js +31 -0
- package/dist/discord/types/interaction.d.ts +321 -0
- package/dist/discord/types/interaction.js +47 -0
- package/dist/discord/types/invite.d.ts +158 -0
- package/dist/discord/types/invite.js +39 -0
- package/dist/discord/types/message.d.ts +834 -0
- package/dist/discord/types/message.js +159 -0
- package/dist/discord/types/oauth2.d.ts +22 -0
- package/dist/discord/types/oauth2.js +1 -0
- package/dist/discord/types/permissions.d.ts +183 -0
- package/dist/discord/types/permissions.js +118 -0
- package/dist/discord/types/poll.d.ts +106 -0
- package/dist/discord/types/poll.js +8 -0
- package/dist/discord/types/sku.d.ts +47 -0
- package/dist/discord/types/sku.js +26 -0
- package/dist/discord/types/soundboard.d.ts +71 -0
- package/dist/discord/types/soundboard.js +1 -0
- package/dist/discord/types/stage-instance.d.ts +58 -0
- package/dist/discord/types/stage-instance.js +10 -0
- package/dist/discord/types/sticker.d.ts +115 -0
- package/dist/discord/types/sticker.js +20 -0
- package/dist/discord/types/subscription.d.ts +54 -0
- package/dist/discord/types/subscription.js +12 -0
- package/dist/discord/types/team.d.ts +55 -0
- package/dist/discord/types/team.js +21 -0
- package/dist/discord/types/user.d.ts +273 -0
- package/dist/discord/types/user.js +83 -0
- package/dist/discord/types/voice.d.ts +72 -0
- package/dist/discord/types/voice.js +1 -0
- package/dist/discord/types/webhook.d.ts +184 -0
- package/dist/discord/types/webhook.js +12 -0
- package/dist/events/convention.d.ts +25 -0
- package/dist/events/convention.js +97 -0
- package/dist/events/event.d.ts +8 -0
- package/dist/events/event.js +20 -0
- package/dist/events/registry.d.ts +706 -0
- package/dist/events/registry.js +839 -0
- package/dist/events/router.d.ts +45 -0
- package/dist/events/router.js +133 -0
- package/dist/events/types.d.ts +7 -0
- package/dist/events/types.js +48 -0
- package/dist/gateway/errors.d.ts +18 -0
- package/dist/gateway/errors.js +47 -0
- package/dist/gateway/gateway.d.ts +64 -0
- package/dist/gateway/gateway.js +117 -0
- package/dist/gateway/identify-queue.d.ts +25 -0
- package/dist/gateway/identify-queue.js +29 -0
- package/dist/gateway/shard.d.ts +94 -0
- package/dist/gateway/shard.js +414 -0
- package/dist/gateway/state.d.ts +11 -0
- package/dist/gateway/state.js +184 -0
- package/dist/index.d.ts +55 -18
- package/dist/index.js +38 -12
- package/dist/interactions/cooldown.d.ts +33 -0
- package/dist/interactions/cooldown.js +74 -0
- package/dist/interactions/dispatch.d.ts +91 -0
- package/dist/interactions/dispatch.js +110 -0
- package/dist/loader/generated.d.ts +37 -0
- package/dist/loader/generated.js +114 -0
- package/dist/loader/hot.d.ts +13 -0
- package/dist/loader/hot.js +85 -0
- package/dist/loader/loader.d.ts +72 -0
- package/dist/loader/loader.js +135 -0
- package/dist/loader/locate.d.ts +10 -0
- package/dist/loader/locate.js +36 -0
- package/dist/loader/watch.d.ts +17 -0
- package/dist/loader/watch.js +66 -0
- package/dist/main.d.ts +3 -0
- package/dist/main.js +6 -0
- package/dist/messages/commands.d.ts +23 -0
- package/dist/messages/commands.js +123 -0
- package/dist/messages/convention.d.ts +89 -0
- package/dist/messages/convention.js +347 -0
- package/dist/messages/messages.d.ts +219 -0
- package/dist/messages/messages.js +30 -0
- package/dist/messages/phrases.d.ts +23 -0
- package/dist/messages/phrases.js +44 -0
- package/dist/messages/translate.d.ts +100 -0
- package/dist/messages/translate.js +249 -0
- package/dist/presence/convention.d.ts +26 -0
- package/dist/presence/convention.js +133 -0
- package/dist/presence/presence.d.ts +57 -0
- package/dist/presence/presence.js +27 -0
- package/dist/rest/errors.d.ts +55 -0
- package/dist/rest/errors.js +92 -0
- package/dist/rest/rate-limiter.d.ts +46 -0
- package/dist/rest/rate-limiter.js +153 -0
- package/dist/rest/rest.d.ts +63 -0
- package/dist/rest/rest.js +194 -0
- package/dist/structures/base.d.ts +48 -0
- package/dist/structures/base.js +84 -0
- package/dist/structures/channel.d.ts +380 -0
- package/dist/structures/channel.js +627 -0
- package/dist/structures/context.d.ts +30 -0
- package/dist/structures/context.js +7 -0
- package/dist/structures/emoji.d.ts +46 -0
- package/dist/structures/emoji.js +65 -0
- package/dist/structures/entities.d.ts +62 -0
- package/dist/structures/entities.js +226 -0
- package/dist/structures/guild.d.ts +348 -0
- package/dist/structures/guild.js +466 -0
- package/dist/structures/interaction.d.ts +197 -0
- package/dist/structures/interaction.js +396 -0
- package/dist/structures/invite.d.ts +38 -0
- package/dist/structures/invite.js +57 -0
- package/dist/structures/known.d.ts +28 -0
- package/dist/structures/known.js +58 -0
- package/dist/structures/member.d.ts +140 -0
- package/dist/structures/member.js +260 -0
- package/dist/structures/message.d.ts +197 -0
- package/dist/structures/message.js +268 -0
- package/dist/structures/payload.d.ts +91 -0
- package/dist/structures/payload.js +184 -0
- package/dist/structures/role.d.ts +69 -0
- package/dist/structures/role.js +112 -0
- package/dist/structures/user.d.ts +59 -0
- package/dist/structures/user.js +94 -0
- package/dist/structures/webhook.d.ts +46 -0
- package/dist/structures/webhook.js +79 -0
- package/dist/tasks/convention.d.ts +26 -0
- package/dist/tasks/convention.js +78 -0
- package/dist/tasks/schedule.d.ts +54 -0
- package/dist/tasks/schedule.js +236 -0
- package/dist/tasks/scheduler.d.ts +33 -0
- package/dist/tasks/scheduler.js +107 -0
- package/dist/tasks/task.d.ts +76 -0
- package/dist/tasks/task.js +28 -0
- package/dist/util/case.d.ts +13 -0
- package/dist/util/case.js +54 -0
- package/dist/util/duration.d.ts +8 -0
- package/dist/util/duration.js +29 -0
- package/dist/util/websocket.d.ts +9 -0
- package/dist/util/websocket.js +31 -0
- package/dist/voice/connection.d.ts +90 -0
- package/dist/voice/connection.js +494 -0
- package/dist/voice/dave.d.ts +109 -0
- package/dist/voice/dave.js +245 -0
- package/dist/voice/opus.d.ts +19 -0
- package/dist/voice/opus.js +273 -0
- package/dist/voice/session.d.ts +55 -0
- package/dist/voice/session.js +405 -0
- package/dist/voice/source.d.ts +22 -0
- package/dist/voice/source.js +195 -0
- package/dist/voice/transport.d.ts +43 -0
- package/dist/voice/transport.js +140 -0
- package/dist/voice/usage.d.ts +4 -0
- package/dist/voice/usage.js +33 -0
- package/package.json +26 -7
- package/vendor/dave/LICENSE +231 -0
- package/vendor/dave/libdave.d.mts +99 -0
- package/vendor/dave/libdave.mjs +2 -0
- package/vendor/dave/libdave.wasm +0 -0
- package/dist/components.d.ts +0 -97
- package/dist/components.js +0 -260
- package/dist/context.d.ts +0 -72
- package/dist/context.js +0 -273
- package/dist/discord/client.d.ts +0 -35
- package/dist/discord/client.js +0 -66
- package/dist/discord/constants.d.ts +0 -49
- package/dist/discord/constants.js +0 -61
- package/dist/discord/events.d.ts +0 -129
- package/dist/discord/events.js +0 -102
- package/dist/discord/gateway.d.ts +0 -61
- package/dist/discord/gateway.js +0 -320
- package/dist/discord/payloads.d.ts +0 -275
- package/dist/discord/payloads.js +0 -3
- package/dist/discord/presence.d.ts +0 -42
- package/dist/discord/presence.js +0 -51
- package/dist/discord/rest.d.ts +0 -49
- package/dist/discord/rest.js +0 -271
- package/dist/discord/types.d.ts +0 -334
- package/dist/discord/types.js +0 -4
- package/dist/events.d.ts +0 -94
- package/dist/events.js +0 -255
- package/dist/presence.d.ts +0 -92
- package/dist/presence.js +0 -250
- package/dist/structures/Channel.d.ts +0 -110
- package/dist/structures/Channel.js +0 -171
- package/dist/structures/Guild.d.ts +0 -70
- package/dist/structures/Guild.js +0 -105
- package/dist/structures/Interaction.d.ts +0 -113
- package/dist/structures/Interaction.js +0 -274
- package/dist/structures/Member.d.ts +0 -70
- package/dist/structures/Member.js +0 -124
- package/dist/structures/Message.d.ts +0 -87
- package/dist/structures/Message.js +0 -182
- package/dist/structures/Reaction.d.ts +0 -38
- package/dist/structures/Reaction.js +0 -64
- package/dist/structures/Role.d.ts +0 -43
- package/dist/structures/Role.js +0 -77
- package/dist/structures/User.d.ts +0 -41
- package/dist/structures/User.js +0 -79
- package/dist/structures/utils.d.ts +0 -72
- package/dist/structures/utils.js +0 -59
- package/dist/utils/errors.d.ts +0 -5
- package/dist/utils/errors.js +0 -28
- package/dist/utils/modules.d.ts +0 -39
- 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 EmbedFile } 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 files of `src/components/embeds/`. */
|
|
43
|
+
embeds?: (Embed | EmbedFile<[]>)[];
|
|
44
|
+
/**
|
|
45
|
+
* Buttons, select menus and layout components, made by ChapterJS: the
|
|
46
|
+
* files of `src/components/` 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 { isEmbedFile } 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 files of `src/components/embeds/` 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 (isEmbedFile(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 a file of src/components/embeds/.`);
|
|
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
|
+
}
|