lunibee 0.2.3 → 0.3.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 (86) hide show
  1. package/README.md +3 -3
  2. package/dist/builders/attachment.d.ts +8 -4
  3. package/dist/builders/commands.d.ts +122 -149
  4. package/dist/builders/components.d.ts +10 -150
  5. package/dist/builders/embed.d.ts +66 -37
  6. package/dist/builders/index.d.ts +0 -4
  7. package/dist/builders/index.js +112 -221
  8. package/dist/builders/index.js.map +10 -9
  9. package/dist/collection/cache.d.ts +15 -6
  10. package/dist/collection/index.d.ts +92 -17
  11. package/dist/collection/index.js +471 -279
  12. package/dist/collection/index.js.map +4 -4
  13. package/dist/core/api.d.ts +130 -0
  14. package/dist/core/channel-create.d.ts +72 -0
  15. package/dist/core/commands.d.ts +232 -0
  16. package/dist/core/events.d.ts +24 -7
  17. package/dist/core/handles.d.ts +157 -0
  18. package/dist/core/index.d.ts +68 -4
  19. package/dist/core/index.js +2639 -493
  20. package/dist/core/index.js.map +47 -37
  21. package/dist/core/permissions.d.ts +7 -7
  22. package/dist/formatters/index.js +9 -5
  23. package/dist/formatters/index.js.map +3 -3
  24. package/dist/handlers/index.js +5 -10
  25. package/dist/handlers/index.js.map +3 -3
  26. package/dist/index.d.ts +2 -2
  27. package/dist/index.js +9527 -7809
  28. package/dist/index.js.map +63 -53
  29. package/dist/managers/advanced.d.ts +29 -1
  30. package/dist/managers/base.d.ts +22 -14
  31. package/dist/managers/emoji.d.ts +0 -2
  32. package/dist/managers/guild-resources.d.ts +13 -5
  33. package/dist/managers/guild.d.ts +40 -4
  34. package/dist/managers/index.d.ts +21 -13
  35. package/dist/managers/index.js +969 -386
  36. package/dist/managers/index.js.map +30 -25
  37. package/dist/managers/member.d.ts +9 -2
  38. package/dist/managers/message.d.ts +10 -15
  39. package/dist/managers/role.d.ts +18 -10
  40. package/dist/managers/thread.d.ts +68 -0
  41. package/dist/managers/user.d.ts +18 -0
  42. package/dist/rest/errors.d.ts +14 -7
  43. package/dist/rest/index.d.ts +24 -12
  44. package/dist/rest/index.js +70 -20
  45. package/dist/rest/index.js.map +9 -9
  46. package/dist/rest/redis.d.ts +1 -1
  47. package/dist/rest/route.d.ts +8 -4
  48. package/dist/rest/routes.d.ts +122 -48
  49. package/dist/rest/transport.d.ts +10 -5
  50. package/dist/rest/webhook.d.ts +9 -5
  51. package/dist/sharding/bus.d.ts +47 -19
  52. package/dist/sharding/cluster.d.ts +11 -0
  53. package/dist/sharding/gateway-bot.d.ts +18 -0
  54. package/dist/sharding/index.d.ts +64 -25
  55. package/dist/sharding/index.js +439 -124
  56. package/dist/sharding/index.js.map +19 -14
  57. package/dist/sharding/supervisor.d.ts +32 -0
  58. package/dist/sharding/transport.d.ts +45 -0
  59. package/dist/structures/audit-log.d.ts +99 -2
  60. package/dist/structures/base.d.ts +40 -23
  61. package/dist/structures/channels.d.ts +45 -14
  62. package/dist/structures/index.d.ts +8 -12
  63. package/dist/structures/index.js +280 -132
  64. package/dist/structures/index.js.map +21 -15
  65. package/dist/structures/interactions.d.ts +91 -63
  66. package/dist/structures/resources.d.ts +99 -52
  67. package/dist/structures/sticker.d.ts +33 -0
  68. package/dist/types/channel-kind.d.ts +26 -0
  69. package/dist/types/gateway.d.ts +24 -12
  70. package/dist/types/index.d.ts +115 -113
  71. package/dist/types/index.js +53 -48
  72. package/dist/types/index.js.map +6 -5
  73. package/dist/voice/index.d.ts +12 -4
  74. package/dist/voice/index.js +14 -18
  75. package/dist/voice/index.js.map +3 -3
  76. package/dist/ws/decoder.d.ts +6 -2
  77. package/dist/ws/dispatcher.d.ts +19 -0
  78. package/dist/ws/index.d.ts +61 -15
  79. package/dist/ws/index.js +194 -77
  80. package/dist/ws/index.js.map +13 -11
  81. package/dist/ws/protocol.d.ts +10 -2
  82. package/dist/ws/reconnect.d.ts +10 -0
  83. package/dist/ws/send-budget.d.ts +6 -2
  84. package/dist/ws/session.d.ts +14 -4
  85. package/dist/ws/state.d.ts +22 -11
  86. package/package.json +20 -16
@@ -0,0 +1,232 @@
1
+ import type { InteractionReplyOptions } from "@lunibee/structures";
2
+ import type { CommandInteraction, GuildMember, Message } from "@lunibee/structures";
3
+ import { type APIAttachment, type ChannelKind } from "@lunibee/types";
4
+ import { type PermissionName } from "./permissions.js";
5
+ import type { Client } from "./index.js";
6
+ /** What every option takes. */
7
+ interface OptionConfig {
8
+ /** Shown in Discord's command picker (1-100 characters). Defaults to the option's name. */
9
+ description?: string;
10
+ /** Whether the command cannot run without it. */
11
+ required?: boolean;
12
+ }
13
+ /** A string option. */
14
+ export interface StringConfig extends OptionConfig {
15
+ default?: string;
16
+ /** Shortest and longest accepted text. */
17
+ min?: number;
18
+ max?: number;
19
+ /** Allowed values, as plain text or `{ name, value }` pairs. */
20
+ choices?: readonly (string | {
21
+ name: string;
22
+ value: string;
23
+ })[];
24
+ }
25
+ /** An integer or number option. */
26
+ export interface NumberConfig extends OptionConfig {
27
+ default?: number;
28
+ /** Smallest and largest accepted value. */
29
+ min?: number;
30
+ max?: number;
31
+ choices?: readonly (number | {
32
+ name: string;
33
+ value: number;
34
+ })[];
35
+ }
36
+ /** A true/false option. */
37
+ export interface BooleanConfig extends OptionConfig {
38
+ default?: boolean;
39
+ }
40
+ /** A channel option. */
41
+ export interface ChannelConfig extends OptionConfig {
42
+ /** Only these kinds of channel are accepted (all by default). */
43
+ kinds?: readonly ChannelKind[];
44
+ }
45
+ /** A choice between fixed words. */
46
+ export interface ChoiceConfig<V extends string> extends OptionConfig {
47
+ default?: V;
48
+ }
49
+ /** Which option kind a definition is. */
50
+ type OptionKind = "string" | "integer" | "number" | "boolean" | "user" | "channel" | "role" | "mentionable" | "attachment";
51
+ /** A mention or id that can be either a user or a role. */
52
+ export interface MentionableValue {
53
+ id: string;
54
+ type: "user" | "role";
55
+ }
56
+ /**
57
+ * One option of a command. `T` is the type the handler receives and `C` the
58
+ * configuration it was made with, which decides whether it can be missing.
59
+ * Make one with {@link option}.
60
+ */
61
+ export interface OptionDef<T, C> {
62
+ readonly kind: OptionKind;
63
+ readonly config: C;
64
+ /** Choices for {@link option.choice}; undefined for the other kinds. */
65
+ readonly words?: readonly string[];
66
+ /** Type only: the type the handler receives. Never present at runtime. */
67
+ readonly __type: T;
68
+ }
69
+ type AnyOption = OptionDef<unknown, object>;
70
+ /** The options of a command, by name. */
71
+ export type OptionMap = Record<string, AnyOption>;
72
+ /**
73
+ * Describes the options of a command. The key you give each one in
74
+ * `command({ options })` is its name; the handler gets them typed.
75
+ *
76
+ * - An option is required when `required: true`, and also never missing when it has a `default`.
77
+ * - `user`, `role` and `channel` give the id; `mentionable` gives `{ id, type }`;
78
+ * `attachment` gives the attachment.
79
+ */
80
+ export declare const option: {
81
+ string: <const C extends StringConfig>(config?: C) => OptionDef<string, C>;
82
+ integer: <const C extends NumberConfig>(config?: C) => OptionDef<number, C>;
83
+ number: <const C extends NumberConfig>(config?: C) => OptionDef<number, C>;
84
+ boolean: <const C extends BooleanConfig>(config?: C) => OptionDef<boolean, C>;
85
+ user: <const C extends OptionConfig>(config?: C) => OptionDef<string, C>;
86
+ role: <const C extends OptionConfig>(config?: C) => OptionDef<string, C>;
87
+ channel: <const C extends ChannelConfig>(config?: C) => OptionDef<string, C>;
88
+ mentionable: <const C extends OptionConfig>(config?: C) => OptionDef<MentionableValue, C>;
89
+ attachment: <const C extends OptionConfig>(config?: C) => OptionDef<APIAttachment, C>;
90
+ /** A choice between fixed words; the handler gets the word, typed as the union. */
91
+ choice: <const W extends readonly string[], const C extends ChoiceConfig<W[number]>>(words: W, config?: C) => OptionDef<W[number], C>;
92
+ };
93
+ type IsNeeded<C> = C extends {
94
+ required: true;
95
+ } ? true : C extends {
96
+ default: string | number | boolean;
97
+ } ? true : false;
98
+ type ValueOf<D> = D extends OptionDef<infer T, unknown> ? T : never;
99
+ type ConfigOf<D> = D extends OptionDef<unknown, infer C> ? C : never;
100
+ type RequiredKeys<M extends OptionMap> = {
101
+ [K in keyof M]: IsNeeded<ConfigOf<M[K]>> extends true ? K : never;
102
+ }[keyof M];
103
+ /** The values a handler receives: required (or defaulted) options always, the rest possibly missing. */
104
+ export type OptionValues<M extends OptionMap> = {
105
+ [K in RequiredKeys<M>]: ValueOf<M[K]>;
106
+ } & {
107
+ [K in Exclude<keyof M, RequiredKeys<M>>]?: ValueOf<M[K]>;
108
+ };
109
+ /** What a command handler gets, whether it was run as `/name` or as `!name`. */
110
+ export interface CommandContext<M extends OptionMap = OptionMap> {
111
+ bot: Client;
112
+ /** The command's options, typed from its definition. */
113
+ options: OptionValues<M>;
114
+ /** How it was run. */
115
+ source: "slash" | "prefix";
116
+ guildId: string | undefined;
117
+ channelId: string | undefined;
118
+ /** The id of whoever ran it. */
119
+ userId: string;
120
+ /** The person who ran it as a guild member, when it ran in a guild. */
121
+ member: GuildMember | null;
122
+ /** The slash interaction, when `source` is `"slash"`. */
123
+ interaction: CommandInteraction | undefined;
124
+ /** The message, when `source` is `"prefix"`. */
125
+ message: Message | undefined;
126
+ /**
127
+ * Answers the command: an interaction reply for a slash command (a first
128
+ * reply, an edit after `defer()`, then follow-ups), a message reply for a
129
+ * prefix command. `ephemeral` only means something for slash commands.
130
+ */
131
+ reply(content: string | InteractionReplyOptions): Promise<void>;
132
+ /** Tells Discord the answer will take a while (slash commands only; a no-op for prefix commands). */
133
+ defer(options?: {
134
+ ephemeral?: boolean;
135
+ }): Promise<void>;
136
+ }
137
+ /** The definition `command()` takes. */
138
+ export interface CommandDefinition<M extends OptionMap> {
139
+ /** 1-32 lowercase letters, digits, `-` or `_`. */
140
+ name: string;
141
+ /** 1-100 characters. */
142
+ description: string;
143
+ options?: M;
144
+ /** Permissions the person needs; checked by Discord for slash commands and by Lunibee for prefix commands. Implies `guildOnly`. */
145
+ permissions?: readonly PermissionName[];
146
+ /** Only allow it in servers. */
147
+ guildOnly?: boolean;
148
+ nsfw?: boolean;
149
+ /** Answer `!name args` too, with the same options; `{ aliases }` adds other names. */
150
+ prefix?: boolean | {
151
+ aliases?: readonly string[];
152
+ };
153
+ /** Register it as a slash command (default `true`); `false` makes a prefix-only command. */
154
+ slash?: boolean;
155
+ run(context: CommandContext<M>): unknown;
156
+ }
157
+ /** A command made by {@link command}. */
158
+ export interface Command<M extends OptionMap = OptionMap> {
159
+ readonly name: string;
160
+ readonly description: string;
161
+ readonly options: M;
162
+ readonly permissions: readonly PermissionName[];
163
+ readonly guildOnly: boolean;
164
+ readonly nsfw: boolean;
165
+ /** Whether it is registered as a slash command. */
166
+ readonly slash: boolean;
167
+ /** Whether it answers a prefix, and under which other names. */
168
+ readonly prefix: false | {
169
+ aliases: readonly string[];
170
+ };
171
+ run(context: CommandContext<M>): unknown;
172
+ /** The slash command as Discord expects it. */
173
+ toJSON(): Record<string, unknown>;
174
+ /** The usage line of the prefix form, such as `!timeout <user> [minutes] [reason…]`. */
175
+ usage(prefix: string): string;
176
+ }
177
+ /**
178
+ * Defines a command once; it can be a slash command, a prefix command, or both.
179
+ * @example
180
+ * export default command({
181
+ * name: "timeout",
182
+ * description: "Time a member out",
183
+ * permissions: ["ModerateMembers"],
184
+ * options: {
185
+ * user: option.user({ required: true }),
186
+ * minutes: option.integer({ min: 1, max: 40_320, default: 10 }),
187
+ * reason: option.string({ max: 500 }),
188
+ * },
189
+ * prefix: true,
190
+ * async run({ bot, options, guildId, reply }) {
191
+ * await bot.member(guildId!, options.user).timeout(`${options.minutes}m`, options.reason);
192
+ * await reply(`Timed out <@${options.user}>.`);
193
+ * },
194
+ * });
195
+ * @throws {RangeError} For a name, description or option Discord would refuse.
196
+ * @throws {TypeError} If it is neither a slash nor a prefix command, or a required option follows an optional one.
197
+ */
198
+ export declare function command<const M extends OptionMap = Record<never, never>>(definition: CommandDefinition<M>): Command<M>;
199
+ /** Adds slash and prefix commands and runs them. Reached as `bot.commands`. */
200
+ export declare class CommandRegistry {
201
+ #private;
202
+ constructor(bot: Client);
203
+ /**
204
+ * Adds commands, replacing one with the same name.
205
+ * @throws {TypeError} If a prefix name or alias is already taken by another command.
206
+ */
207
+ add(...commands: Command<OptionMap>[]): this;
208
+ /** The command named `name` (or one of its prefix aliases). */
209
+ get(name: string): Command<OptionMap> | undefined;
210
+ /** Every command, in the order they were added. */
211
+ list(): Command<OptionMap>[];
212
+ /**
213
+ * Registers the slash commands with Discord, replacing the ones already
214
+ * registered. Call it once the client is ready.
215
+ * @param options `guildId` registers them in one guild (instant) instead of globally.
216
+ * @returns How many were registered.
217
+ * @throws {Error} If the client is not ready.
218
+ */
219
+ deploy(options?: {
220
+ guildId?: string;
221
+ }): Promise<number>;
222
+ /**
223
+ * Starts answering: slash commands from interactions and, when `prefix`
224
+ * is given, prefix commands from messages.
225
+ * @param options.prefix The text a message starts with, or several.
226
+ * @throws {TypeError} If called twice.
227
+ */
228
+ listen(options?: {
229
+ prefix?: string | readonly string[];
230
+ }): this;
231
+ }
232
+ export {};
@@ -94,8 +94,8 @@ export type ClientEvents = {
94
94
  action: string;
95
95
  }];
96
96
  messageCreate: [message: Message];
97
- /** `previous` is the cached version, available when `messageCache` is enabled. */
98
- messageUpdate: [message: Message, previous?: Message];
97
+ /** `previous` is the cached version, or `null` unless `messageCache` is enabled and the message was cached. */
98
+ messageUpdate: [message: Message, previous: Message | null];
99
99
  /** `message` is the cached message, available when `messageCache` is enabled. */
100
100
  messageDelete: [data: APIMessageDeleteEvent, message?: Message];
101
101
  /** `messages` are the cached messages that were deleted (empty without `messageCache`). */
@@ -161,12 +161,20 @@ export type ClientEvents = {
161
161
  guild_id: string;
162
162
  }];
163
163
  guildScheduledEventCreate: [data: APIGuildScheduledEvent];
164
- guildScheduledEventUpdate: [data: APIGuildScheduledEvent];
164
+ /** `previous` is the cached event, or `null` if it was not cached. */
165
+ guildScheduledEventUpdate: [
166
+ data: APIGuildScheduledEvent,
167
+ previous: APIGuildScheduledEvent | null
168
+ ];
165
169
  guildScheduledEventDelete: [data: APIGuildScheduledEvent];
166
170
  guildScheduledEventUserAdd: [data: APIGuildScheduledEventUserEvent];
167
171
  guildScheduledEventUserRemove: [data: APIGuildScheduledEventUserEvent];
168
172
  autoModerationRuleCreate: [data: APIAutoModerationRule];
169
- autoModerationRuleUpdate: [data: APIAutoModerationRule];
173
+ /** `previous` is the cached rule, or `null` if it was not cached. */
174
+ autoModerationRuleUpdate: [
175
+ data: APIAutoModerationRule,
176
+ previous: APIAutoModerationRule | null
177
+ ];
170
178
  autoModerationRuleDelete: [data: APIAutoModerationRule];
171
179
  autoModerationActionExecution: [data: APIAutoModerationActionExecution];
172
180
  channelCreate: [channel: Channel];
@@ -184,14 +192,23 @@ export type ClientEvents = {
184
192
  threadMembersUpdate: [data: APIThreadMembersUpdate];
185
193
  threadMemberUpdate: [data: APIThreadMember];
186
194
  stageInstanceCreate: [data: APIStageInstance];
187
- stageInstanceUpdate: [data: APIStageInstance];
195
+ /** `previous` is the cached stage instance, or `null` if it was not cached. */
196
+ stageInstanceUpdate: [
197
+ data: APIStageInstance,
198
+ previous: APIStageInstance | null
199
+ ];
188
200
  stageInstanceDelete: [data: APIStageInstance];
189
201
  inviteCreate: [data: APIInviteCreate];
190
202
  inviteDelete: [data: APIInviteDelete];
191
203
  webhooksUpdate: [data: APIWebhooksUpdate];
192
- voiceStateUpdate: [data: APIVoiceState];
204
+ /** `previous` is the user's last known voice state in that guild, or `null` (first sighting, or not in a guild). */
205
+ voiceStateUpdate: [data: APIVoiceState, previous: APIVoiceState | null];
193
206
  voiceServerUpdate: [data: APIVoiceServerUpdate];
194
- presenceUpdate: [data: APIPresenceUpdate];
207
+ /** `previous` is the last presence seen, available with `cache: { presences: true }`; otherwise `null`. */
208
+ presenceUpdate: [
209
+ data: APIPresenceUpdate,
210
+ previous: APIPresenceUpdate | null
211
+ ];
195
212
  typingStart: [data: APITypingStart];
196
213
  interactionCreate: [interaction: Interaction];
197
214
  };
@@ -0,0 +1,157 @@
1
+ import type { Collection } from "@lunibee/collection";
2
+ import type { ChannelKind, UnknownChannelKind } from "@lunibee/types";
3
+ import type { BanOptions, ChannelEditOptions, GuildManager, MemberEditOptions, MessageCreateOptions, MessageEditOptions, MessageQueryOptions, RoleEditOptions } from "@lunibee/managers";
4
+ import type { Channel, ChannelOfKind, Guild, GuildMember, Message, Role, User } from "@lunibee/structures";
5
+ import type { Client } from "./index.js";
6
+ import { type CreateChannelOptions } from "./channel-create.js";
7
+ /** A length of time: milliseconds, or text such as `"90s"`, `"10m"`, `"2h"`, `"1d"`, `"1w"` or `"1h30m"`. */
8
+ export type Duration = number | string;
9
+ /**
10
+ * Turns a {@link Duration} into milliseconds.
11
+ * @throws {RangeError} If a number is negative or not finite, or the text is not a duration.
12
+ */
13
+ export declare function parseDuration(value: Duration): number;
14
+ /** Message text, or a full payload. */
15
+ export type MessageInput = string | MessageCreateOptions;
16
+ /**
17
+ * A reference to one Discord thing by its ids. A handle holds no data, so it
18
+ * is cheap to create, can be made before the thing is cached, and fails only
19
+ * when you use it.
20
+ *
21
+ * - `peek()` reads the cache and returns `undefined` when it is not there.
22
+ * - `get()` reads the cache, and asks Discord when it is not there.
23
+ * - `fetch()` asks Discord now and refreshes the cache.
24
+ */
25
+ export interface Handle<T> {
26
+ peek(): T | undefined;
27
+ get(): Promise<T>;
28
+ fetch(): Promise<T>;
29
+ }
30
+ /** A user, by id. Made by `bot.person(id)`. */
31
+ export declare class UserHandle implements Handle<User> {
32
+ private readonly bot;
33
+ readonly id: string;
34
+ constructor(bot: Client, id: string);
35
+ peek(): User | undefined;
36
+ get(): Promise<User>;
37
+ fetch(): Promise<User>;
38
+ /** Opens (or reuses) the direct-message channel with this user. */
39
+ dm(): Promise<ChannelHandle>;
40
+ /** Sends this user a direct message. */
41
+ send(message: MessageInput): Promise<Message>;
42
+ }
43
+ /** A guild, by id. Made by `bot.guild(id)`. */
44
+ export declare class GuildHandle implements Handle<Guild> {
45
+ private readonly bot;
46
+ readonly id: string;
47
+ constructor(bot: Client, id: string);
48
+ peek(): Guild | undefined;
49
+ get(): Promise<Guild>;
50
+ fetch(): Promise<Guild>;
51
+ /** The cached members, live: it changes as the Gateway updates them. */
52
+ get members(): Collection<string, GuildMember>;
53
+ /** The cached roles, live. */
54
+ get roles(): Collection<string, Role>;
55
+ /** The cached channels of this guild, as a snapshot taken when you read it. */
56
+ get channels(): Collection<string, Channel>;
57
+ member(userId: string): MemberHandle;
58
+ role(roleId: string): RoleHandle;
59
+ channel(channelId: string): ChannelHandle;
60
+ /**
61
+ * Creates a channel. `kind` decides which other options apply, and the
62
+ * result is typed to match: a `"voice"` option gives a `VoiceChannel`.
63
+ * @example await bot.guild(id).createChannel({ kind: "text", name: "general", parent: categoryId });
64
+ */
65
+ createChannel<O extends CreateChannelOptions>(options: O): Promise<ChannelOfKind<O["kind"]>>;
66
+ /** Bans a user, whether or not they are a member. */
67
+ ban(userId: string, options?: BanOptions): Promise<void>;
68
+ /** Lifts a ban. */
69
+ unban(userId: string, reason?: string): Promise<void>;
70
+ /** Changes the guild's settings; `reason` is the audit-log reason. */
71
+ edit(options: Parameters<GuildManager["edit"]>[1]): Promise<Guild>;
72
+ /** Makes the bot leave the guild. */
73
+ leave(): Promise<void>;
74
+ }
75
+ /** A guild member, by guild id and user id. Made by `bot.member(guildId, userId)`. */
76
+ export declare class MemberHandle implements Handle<GuildMember> {
77
+ private readonly bot;
78
+ readonly guildId: string;
79
+ readonly userId: string;
80
+ constructor(bot: Client, guildId: string, userId: string);
81
+ private get members();
82
+ peek(): GuildMember | undefined;
83
+ get(): Promise<GuildMember>;
84
+ fetch(): Promise<GuildMember>;
85
+ guild(): GuildHandle;
86
+ user(): UserHandle;
87
+ kick(reason?: string): Promise<void>;
88
+ ban(options?: BanOptions): Promise<void>;
89
+ unban(reason?: string): Promise<void>;
90
+ /** Changes nickname, roles, mute or deafen; put the audit-log reason in `options.reason`. */
91
+ edit(options: MemberEditOptions): Promise<GuildMember>;
92
+ addRole(roleId: string, reason?: string): Promise<void>;
93
+ removeRole(roleId: string, reason?: string): Promise<void>;
94
+ /**
95
+ * Times the member out for `duration` (`"10m"`, `"2h"`, 90_000), or lifts
96
+ * the timeout with `null`.
97
+ */
98
+ timeout(duration: Duration | null, reason?: string): Promise<GuildMember>;
99
+ }
100
+ /** A role, by guild id and role id. Made by `bot.role(guildId, roleId)`. */
101
+ export declare class RoleHandle implements Handle<Role> {
102
+ private readonly bot;
103
+ readonly guildId: string;
104
+ readonly roleId: string;
105
+ constructor(bot: Client, guildId: string, roleId: string);
106
+ private get roles();
107
+ peek(): Role | undefined;
108
+ get(): Promise<Role>;
109
+ fetch(): Promise<Role>;
110
+ edit(options: RoleEditOptions): Promise<Role>;
111
+ delete(reason?: string): Promise<void>;
112
+ }
113
+ /** A channel, by id. Made by `bot.channel(id)`. */
114
+ export declare class ChannelHandle implements Handle<Channel> {
115
+ private readonly bot;
116
+ readonly id: string;
117
+ constructor(bot: Client, id: string);
118
+ peek(): Channel | undefined;
119
+ get(): Promise<Channel>;
120
+ fetch(): Promise<Channel>;
121
+ message(messageId: string): MessageHandle;
122
+ /**
123
+ * Gets the channel (cache, else Discord) and returns it typed as one of
124
+ * `kinds`.
125
+ * @throws {TypeError} If it is a different kind.
126
+ */
127
+ as<K extends ChannelKind | UnknownChannelKind>(...kinds: K[]): Promise<ChannelOfKind<K>>;
128
+ /** Sends a message: text, or a full payload (`embeds`, `components`, `files`, …). */
129
+ send(message: MessageInput): Promise<Message>;
130
+ /** Reads messages: the latest, or around / before / after one. */
131
+ messages(query?: MessageQueryOptions): Promise<Message[]>;
132
+ edit(options: ChannelEditOptions): Promise<Channel>;
133
+ delete(reason?: string): Promise<void>;
134
+ /** Deletes up to 100 messages younger than 14 days. */
135
+ bulkDelete(messageIds: Iterable<string>, reason?: string): Promise<void>;
136
+ }
137
+ /** A message, by channel id and message id. Made by `bot.message(channelId, messageId)`. */
138
+ export declare class MessageHandle implements Handle<Message> {
139
+ private readonly bot;
140
+ readonly channelId: string;
141
+ readonly messageId: string;
142
+ constructor(bot: Client, channelId: string, messageId: string);
143
+ peek(): Message | undefined;
144
+ get(): Promise<Message>;
145
+ fetch(): Promise<Message>;
146
+ channel(): ChannelHandle;
147
+ edit(message: string | MessageEditOptions): Promise<Message>;
148
+ delete(reason?: string): Promise<void>;
149
+ /** Sends a message that replies to this one. */
150
+ reply(message: MessageInput): Promise<Message>;
151
+ /** Adds the bot's reaction (`"👍"`, or `"name:id"` for a custom emoji). */
152
+ react(emoji: string): Promise<void>;
153
+ pin(reason?: string): Promise<void>;
154
+ unpin(reason?: string): Promise<void>;
155
+ /** Publishes the message from an announcement channel. */
156
+ crosspost(): Promise<Message>;
157
+ }
@@ -1,10 +1,14 @@
1
- export { Permission, Permissions, PermissionFlagsBits, PermissionSet, PermissionsBitField, PermissionOverwriteEnum, PermissionOverwriteType, computePermissions, type PermissionContext, type PermissionOverwrite, type PermissionRole, type PermissionName, } from "./permissions.js";
1
+ export { Permission, Permissions, PermissionFlagsBits, PermissionSet, PermissionsBitField, PermissionOverwriteEnum, computePermissions, type PermissionContext, type PermissionOverwrite, type PermissionRole, type PermissionName, } from "./permissions.js";
2
2
  export { ClientEvent,
3
3
  /** Discord.js-familiar alias for {@link ClientEvent}. */
4
4
  ClientEvent as Events, type ClientEventName, type ClientEvents, type ClientListener, } from "./events.js";
5
5
  export { Collector, type CollectorOptions } from "./collector.js";
6
+ export { createApi, type Api, type ApplicationNode, type ChannelNode, type GuildNode, type ListRoute, type MemberNode, type MembersRoute, type MessageNode, type MessagesRoute, type PageOptions, type Route, type RouteId, type RouteOptions, type UserNode, type WebhookNode, } from "./api.js";
7
+ export { command, option, CommandRegistry, type ChannelConfig, type ChoiceConfig, type BooleanConfig, type Command, type CommandContext, type CommandDefinition, type MentionableValue, type NumberConfig, type OptionDef, type OptionMap, type OptionValues, type StringConfig, } from "./commands.js";
8
+ export { channelCreatePayload, type CreateCategoryChannel, type CreateChannelOptions, type CreateForumChannel, type CreateTextChannel, type CreateVoiceChannel, type ForumTagInput, } from "./channel-create.js";
9
+ export { ChannelHandle, GuildHandle, MemberHandle, MessageHandle, RoleHandle, UserHandle, parseDuration, type Duration, type Handle, type MessageInput, } from "./handles.js";
6
10
  export { GatewayIntentBits, IntentBits, Intents, IntentsBitField, resolveGatewayIntents, type GatewayIntentResolvable, } from "@lunibee/types";
7
- import { ApplicationCommandManager, ChannelManager, GuildManager, MonetizationManager, StageInstanceManager, UserManager } from "@lunibee/managers";
11
+ import { ApplicationCommandManager, ChannelManager, GuildManager, MonetizationManager, ApplicationEmojiManager, StageInstanceManager, UserManager } from "@lunibee/managers";
8
12
  import { REST } from "@lunibee/rest";
9
13
  import { type InteractionClient, type ResourceContext } from "@lunibee/structures";
10
14
  import { Gateway } from "@lunibee/ws";
@@ -12,6 +16,9 @@ import type { APISoundboardSound, ClientOptions, ClientUser } from "@lunibee/typ
12
16
  import { type ClientEvents } from "./events.js";
13
17
  import { Collector, type CollectorOptions } from "./collector.js";
14
18
  import { PermissionSet } from "./permissions.js";
19
+ import { type Api } from "./api.js";
20
+ import { CommandRegistry } from "./commands.js";
21
+ import { ChannelHandle, GuildHandle, MemberHandle, MessageHandle, RoleHandle, UserHandle } from "./handles.js";
15
22
  /** Lifecycle state of a client. */
16
23
  export type ClientState = "idle" | "connecting" | "ready" | "destroyed";
17
24
  type Listener<T extends unknown[]> = (...args: T) => unknown;
@@ -20,6 +27,8 @@ declare class EventEmitter<Events extends {
20
27
  [K in keyof Events]: unknown[];
21
28
  }> {
22
29
  #private;
30
+ /** Removes secrets from text this emitter prints; the client removes its token. */
31
+ protected readonly redactSecrets: (text: string) => string;
23
32
  on<K extends keyof Events>(event: K, listener: Listener<Events[K]>): this;
24
33
  once<K extends keyof Events>(event: K, listener: Listener<Events[K]>): this;
25
34
  off<K extends keyof Events>(event: K, listener: Listener<Events[K]>): this;
@@ -41,8 +50,17 @@ export declare class Client extends EventEmitter<ClientEvents> implements Intera
41
50
  readonly application: {
42
51
  commands: ApplicationCommandManager;
43
52
  };
53
+ /**
54
+ * Discord's REST API as a chained path: `bot.api.guilds(id).members(userId).patch({ nick })`.
55
+ * Uses this client's rate limiting and retries; `bot.rest` and `Routes` stay available.
56
+ */
57
+ get api(): Api;
58
+ /** Slash and prefix commands made with `command()`: `add`, `deploy` and `listen`. */
59
+ readonly commands: CommandRegistry;
44
60
  /** SKUs, entitlements and subscriptions; available after READY (application ID known). */
45
61
  monetization?: MonetizationManager;
62
+ /** The application's own emojis; available after READY (application ID known). */
63
+ applicationEmojis?: ApplicationEmojiManager;
46
64
  get ws(): Gateway;
47
65
  get gateway(): Gateway;
48
66
  user?: ClientUser;
@@ -52,6 +70,8 @@ export declare class Client extends EventEmitter<ClientEvents> implements Intera
52
70
  * The bot token this client is authenticated with, or `null` once the
53
71
  * client has been destroyed. Mirrors `Client#token` in Discord.js.
54
72
  */
73
+ /** Replaces the bot token in text Lunibee prints (listener warnings). */
74
+ protected readonly redactSecrets: (text: string) => string;
55
75
  get token(): string | null;
56
76
  get uptime(): number | null;
57
77
  get ping(): number;
@@ -59,8 +79,32 @@ export declare class Client extends EventEmitter<ClientEvents> implements Intera
59
79
  isReady(): boolean;
60
80
  /** Sets the bot's presence / status. @param data Presence payload. @returns Whether the payload was sent. */
61
81
  setPresence(data: import("@lunibee/types").GatewayPresence): boolean;
82
+ /**
83
+ * Sets what the bot is doing: "Playing chess", "Watching the logs". Pass
84
+ * `null` to clear it. For a custom status (type `ActivityEnum.Custom`) the
85
+ * text shown is `state`, so it is set to `name` unless you give one.
86
+ * @example bot.setActivity("the logs", { type: ActivityEnum.Watching, status: "idle" });
87
+ * @returns Whether the update was sent (false while the Gateway is not connected).
88
+ */
89
+ setActivity(name: string | null, options?: {
90
+ type?: import("@lunibee/types").ActivityEnum;
91
+ url?: string;
92
+ state?: string;
93
+ status?: import("@lunibee/types").GatewayPresence["status"];
94
+ }): boolean;
62
95
  /** Sends a voice state update. @param data Voice state payload. @returns Whether it was sent. */
63
96
  setVoiceState(data: Record<string, unknown>): boolean;
97
+ /**
98
+ * Joins, moves or leaves a voice channel (op 4). Stable public voice API.
99
+ * Returns `false` (never throws) when disconnected, rate limited, or when
100
+ * the guild belongs to another shard of a sharded setup.
101
+ * @param guildId Guild snowflake. @param channelId Channel to join or move to; `null` leaves.
102
+ * @param options `selfMute` and `selfDeaf`. @returns Whether it was sent.
103
+ */
104
+ sendVoiceState(guildId: string, channelId: string | null, options?: {
105
+ selfMute?: boolean;
106
+ selfDeaf?: boolean;
107
+ }): boolean;
64
108
  /** Requests guild members. @param data Guild member request payload. @returns Whether it was sent. */
65
109
  requestGuildMembers(data: Record<string, unknown>): boolean;
66
110
  constructor(options: ClientOptions);
@@ -72,6 +116,24 @@ export declare class Client extends EventEmitter<ClientEvents> implements Intera
72
116
  createCollector<E extends keyof ClientEvents>(event: E, options?: CollectorOptions<ClientEvents[E][0]> & {
73
117
  key?: (item: ClientEvents[E][0]) => string;
74
118
  }): Collector<string, ClientEvents[E][0]>;
119
+ /**
120
+ * Names a guild by id. The handle reads it (`peek()` from the cache, `get()`
121
+ * from the cache or Discord, `fetch()` from Discord) and acts on it.
122
+ */
123
+ guild(id: string): GuildHandle;
124
+ /** Names a channel by id; see {@link Client.guild} for the read methods. */
125
+ channel(id: string): ChannelHandle;
126
+ /**
127
+ * Names a user by id; see {@link Client.guild} for the read methods.
128
+ * (`bot.user` is the bot's own account, hence the different name.)
129
+ */
130
+ person(id: string): UserHandle;
131
+ /** Names a guild member by guild id and user id. */
132
+ member(guildId: string, userId: string): MemberHandle;
133
+ /** Names a role by guild id and role id. */
134
+ role(guildId: string, roleId: string): RoleHandle;
135
+ /** Names a message by channel id and message id. */
136
+ message(channelId: string, messageId: string): MessageHandle;
75
137
  /** Structures built by this client (members from interactions...) act through this. */
76
138
  get resourceContext(): ResourceContext;
77
139
  /**
@@ -82,6 +144,10 @@ export declare class Client extends EventEmitter<ClientEvents> implements Intera
82
144
  permissionsFor(memberId: string, guildOrChannelId: string): PermissionSet | null;
83
145
  /** Fetches Discord's default soundboard sounds. */
84
146
  fetchDefaultSoundboardSounds(): Promise<APISoundboardSound[]>;
147
+ /**
148
+ * Connects to the Gateway. Resolves with the token used, like discord.js;
149
+ * do not log the return value.
150
+ */
85
151
  login(token?: string): Promise<string>;
86
152
  /**
87
153
  * Destroys the client, permanently closing the Gateway connection.
@@ -101,8 +167,6 @@ export declare class Client extends EventEmitter<ClientEvents> implements Intera
101
167
  /** Fetches an invite from Discord. */
102
168
  fetchInvite(code: string, options?: {
103
169
  withCounts?: boolean;
104
- /** @deprecated No effect: Discord always returns `expires_at` and deprecated `with_expiration`. Removed in 0.3.0. */
105
- withExpiration?: boolean;
106
170
  guildScheduledEventId?: string;
107
171
  }): Promise<Record<string, unknown>>;
108
172
  /** Fetches a sticker from Discord. */