qaut.js 1.0.3 → 1.0.5

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 (3) hide show
  1. package/package.json +1 -1
  2. package/src/index.d.ts +99 -104
  3. package/src/index.js +424 -269
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "qaut.js",
3
- "version": "1.0.3",
3
+ "version": "1.0.5",
4
4
  "description": "Official QauT bot framework for building bots and integrations.",
5
5
  "main": "src/index.js",
6
6
  "types": "src/index.d.ts",
package/src/index.d.ts CHANGED
@@ -1,137 +1,132 @@
1
1
  /// <reference types="node" />
2
2
  import { EventEmitter } from 'events';
3
3
 
4
- export declare const Events: {
5
- readonly ClientReady: 'clientReady';
6
- readonly Debug: 'debug';
7
- readonly Error: 'error';
8
- readonly MessageCreate: 'messageCreate';
9
- readonly MessageUpdate: 'messageUpdate';
10
- readonly MessageDelete: 'messageDelete';
11
- readonly InteractionCreate: 'interactionCreate';
12
- readonly GuildCreate: 'guildCreate';
13
- readonly GuildUpdate: 'guildUpdate';
14
- readonly GuildDelete: 'guildDelete';
15
- readonly GuildMemberAdd: 'guildMemberAdd';
16
- readonly GuildMemberRemove: 'guildMemberRemove';
17
- readonly PresenceUpdate: 'presenceUpdate';
18
- readonly WebhookEvent: 'webhookEvent';
19
- };
20
-
4
+ export declare const DefaultRestBase: string;
5
+ export declare const Events: Record<string, string>;
21
6
  export declare const GatewayIntentBits: Record<string, number>;
7
+ export declare const Partials: Record<string, string>;
22
8
  export declare const Status: Record<string, string>;
23
9
  export declare const ActivityType: Record<string, number>;
24
10
  export declare const PermissionFlagsBits: Record<string, bigint>;
25
- export declare const DefaultRestBase = "https://qaut.gg/api";
26
11
 
27
- export declare class QauTError extends Error {
28
- details?: unknown;
12
+ export declare class QauTError extends Error { details?: unknown; }
13
+ export declare class Collection<K = string, V = any> extends Map<K, V> {
14
+ find(fn: (value: V, key: K, collection: this) => boolean): V | undefined;
15
+ filter(fn: (value: V, key: K, collection: this) => boolean): Collection<K, V>;
16
+ map<T>(fn: (value: V, key: K, collection: this) => T): T[];
17
+ reduce<T>(fn: (acc: T, value: V, key: K, collection: this) => T, initial: T): T;
18
+ sort(fn: (a: V, b: V, aKey: K, bKey: K) => number): Collection<K, V>;
19
+ some(fn: (value: V, key: K, collection: this) => boolean): boolean;
20
+ every(fn: (value: V, key: K, collection: this) => boolean): boolean;
21
+ concat(...collections: Collection<K, V>[]): Collection<K, V>;
22
+ merge(other: Collection<K, V>, whenInSelf?: Function, whenInOther?: Function, whenInBoth?: Function): Collection<K, V>;
23
+ sweep(fn: (value: V, key: K, collection: this) => boolean): number;
24
+ random(): V | undefined;
25
+ randomKey(): K | undefined;
26
+ first(amount?: number): V | V[] | undefined;
27
+ firstKey(amount?: number): K | K[] | undefined;
28
+ last(amount?: number): V | V[] | undefined;
29
+ lastKey(amount?: number): K | K[] | undefined;
30
+ at(index: number): V | undefined;
31
+ clone(): Collection<K, V>;
32
+ reverse(): Collection<K, V>;
33
+ partition(fn: (value: V, key: K, collection: this) => boolean): [Collection<K, V>, Collection<K, V>];
29
34
  }
30
35
 
31
36
  export declare class BitField {
32
37
  bitfield: bigint;
33
38
  constructor(bits?: bigint | number | string | Array<bigint | number | string>);
34
39
  has(bit: bigint | number | string): boolean;
35
- add(...bits: Array<bigint | number | string | Array<bigint | number | string>>): this;
36
- remove(...bits: Array<bigint | number | string | Array<bigint | number | string>>): this;
40
+ add(...bits: any[]): this;
41
+ remove(...bits: any[]): this;
37
42
  toString(): string;
38
43
  valueOf(): bigint;
39
44
  }
45
+ export declare class PermissionsBitField extends BitField { static Flags: typeof PermissionFlagsBits; }
46
+ export declare class PermissionBitField extends PermissionsBitField {}
47
+ export declare class IntentBitField extends BitField { static Flags: typeof GatewayIntentBits; }
40
48
 
41
- export declare class PermissionBitField extends BitField {}
42
- export declare class IntentBitField extends BitField {}
43
-
44
- export declare class EmbedBuilder {
45
- constructor(data?: Record<string, unknown>);
46
- setTitle(title: string): this;
47
- setDescription(description: string): this;
48
- setColor(color: string | number): this;
49
- setURL(url: string): this;
50
- setTimestamp(timestamp?: Date | string | number): this;
51
- setAuthor(author: string | Record<string, unknown>): this;
52
- setFooter(footer: string | Record<string, unknown>): this;
53
- setImage(url: string): this;
54
- setThumbnail(url: string): this;
55
- addFields(...fields: Array<{ name: string; value: string; inline?: boolean } | Array<{ name: string; value: string; inline?: boolean }>>): this;
56
- toJSON(): Record<string, unknown>;
49
+ declare class Builder<T = any> {
50
+ data: T;
51
+ constructor(data?: Partial<T>);
52
+ toJSON(): T;
57
53
  }
58
-
59
- export declare class ButtonBuilder {
60
- constructor(data?: Record<string, unknown>);
61
- setCustomId(customId: string): this;
62
- setLabel(label: string): this;
63
- setStyle(style: string): this;
64
- setURL(url: string): this;
65
- setDisabled(disabled?: boolean): this;
66
- toJSON(): Record<string, unknown>;
54
+ export declare class EmbedBuilder extends Builder {
55
+ setTitle(v: string): this; setDescription(v: string): this; setURL(v: string): this; setColor(v: string | number): this;
56
+ setAuthor(v: string | object): this; setFooter(v: string | object): this; setThumbnail(v: string): this; setImage(v: string): this;
57
+ setTimestamp(v?: string | number | Date): this; setFields(...fields: any[]): this; addFields(...fields: any[]): this;
67
58
  }
68
-
69
- export declare class ActionRowBuilder {
70
- constructor(data?: { components?: unknown[] });
71
- addComponents(...components: unknown[]): this;
72
- toJSON(): Record<string, unknown>;
73
- }
74
-
75
- export declare class SlashCommandBuilder {
76
- constructor(data?: Record<string, unknown>);
77
- setName(name: string): this;
78
- setDescription(description: string): this;
79
- addStringOption(option: Record<string, unknown>): this;
80
- addIntegerOption(option: Record<string, unknown>): this;
81
- addBooleanOption(option: Record<string, unknown>): this;
82
- toJSON(): Record<string, unknown>;
59
+ export declare class ButtonBuilder extends Builder { setCustomId(v: string): this; setLabel(v: string): this; setStyle(v: string): this; setEmoji(v: any): this; setURL(v: string): this; setDisabled(v?: boolean): this; }
60
+ export declare class ActionRowBuilder extends Builder { addComponents(...components: any[]): this; setComponents(...components: any[]): this; }
61
+ export declare class SelectMenuBuilder extends Builder { setCustomId(v: string): this; setPlaceholder(v: string): this; addOptions(...options: any[]): this; setMinValues(v: number): this; setMaxValues(v: number): this; setDisabled(v?: boolean): this; }
62
+ export declare class StringSelectMenuBuilder extends SelectMenuBuilder {}
63
+ export declare class UserSelectMenuBuilder extends SelectMenuBuilder {}
64
+ export declare class RoleSelectMenuBuilder extends SelectMenuBuilder {}
65
+ export declare class MentionableSelectMenuBuilder extends SelectMenuBuilder {}
66
+ export declare class ChannelSelectMenuBuilder extends SelectMenuBuilder {}
67
+ export declare class ModalBuilder extends Builder { setCustomId(v: string): this; setTitle(v: string): this; addComponents(...components: any[]): this; }
68
+ export declare class TextInputBuilder extends Builder { setCustomId(v: string): this; setLabel(v: string): this; setStyle(v: string): this; setPlaceholder(v: string): this; setRequired(v?: boolean): this; setMinLength(v: number): this; setMaxLength(v: number): this; setValue(v: string): this; }
69
+ export declare class SlashCommandBuilder extends Builder {
70
+ setName(v: string): this; setDescription(v: string): this; setDefaultMemberPermissions(v: any): this; setDMPermission(v: boolean): this;
71
+ addStringOption(o: any): this; addIntegerOption(o: any): this; addBooleanOption(o: any): this; addUserOption(o: any): this;
72
+ addRoleOption(o: any): this; addMentionableOption(o: any): this; addNumberOption(o: any): this; addChannelOption(o: any): this;
73
+ addAttachmentOption(o: any): this; addSubcommand(o: any): this; addSubcommandGroup(o: any): this;
83
74
  }
75
+ export declare class ContextMenuCommandBuilder extends Builder { setName(v: string): this; setType(v: any): this; setDefaultMemberPermissions(v: any): this; setDMPermission(v: boolean): this; }
76
+ export declare const StringOption: typeof SlashCommandBuilder;
77
+ export declare const IntegerOption: typeof SlashCommandBuilder;
78
+ export declare const BooleanOption: typeof SlashCommandBuilder;
79
+ export declare const UserOption: typeof SlashCommandBuilder;
80
+ export declare const RoleOption: typeof SlashCommandBuilder;
81
+ export declare const MentionableOption: typeof SlashCommandBuilder;
82
+ export declare const NumberOption: typeof SlashCommandBuilder;
83
+ export declare const ChannelOption: typeof SlashCommandBuilder;
84
+ export declare const AttachmentOption: typeof SlashCommandBuilder;
85
+ export declare class AttachmentBuilder extends Builder { setFile(v: any): this; setName(v: string): this; setDescription(v: string): this; setSpoiler(v?: boolean): this; }
84
86
 
85
87
  export declare class REST {
86
88
  constructor(options?: { token?: string; baseUrl?: string; authPrefix?: string });
87
89
  setToken(token: string): this;
88
- request(method: string, route: string, body?: unknown): Promise<unknown>;
89
- get(route: string): Promise<unknown>;
90
- post(route: string, body?: unknown): Promise<unknown>;
91
- patch(route: string, body?: unknown): Promise<unknown>;
92
- delete(route: string, body?: unknown): Promise<unknown>;
90
+ request(method: string, route: string, body?: any): Promise<any>;
91
+ get(route: string): Promise<any>; post(route: string, body?: any): Promise<any>; put(route: string, body?: any): Promise<any>;
92
+ patch(route: string, body?: any): Promise<any>; delete(route: string, body?: any): Promise<any>;
93
93
  }
94
94
 
95
- export declare class TextChannel {
96
- id: string;
97
- constructor(client: Client, data?: Record<string, unknown>);
98
- send(payload: string | Record<string, unknown>): Promise<unknown>;
99
- }
100
-
101
- export declare class User {
102
- id: string;
103
- constructor(client: Client, data?: Record<string, unknown>);
104
- send(payload: string | Record<string, unknown>): Promise<unknown>;
105
- }
106
-
107
- export declare class Message {
95
+ declare class Entity {
108
96
  client: Client;
109
- channel: TextChannel | null;
110
- author: User | null;
111
- content?: string;
112
- constructor(client: Client, data?: Record<string, unknown>);
113
- reply(payload: string | Record<string, unknown>): Promise<unknown>;
97
+ id: string;
98
+ [key: string]: any;
99
+ constructor(client: Client, data?: any);
114
100
  }
101
+ export declare class Guild extends Entity { [key: string]: any; }
102
+ export declare class Channel extends Entity { [key: string]: any; send(payload: any): Promise<any>; }
103
+ export declare class TextChannel extends Channel {}
104
+ export declare class Message extends Entity { [key: string]: any; reply(payload: any): Promise<any>; }
105
+ export declare class User extends Entity { [key: string]: any; send(payload: any): Promise<any>; }
106
+ export declare class GuildMember extends Entity { [key: string]: any; }
107
+ export declare class Role extends Entity { [key: string]: any; }
108
+ export declare class Interaction extends Entity { [key: string]: any; }
109
+ export declare class Reaction extends Entity { [key: string]: any; }
110
+ export declare class Invite extends Entity { [key: string]: any; }
111
+ export declare class Webhook extends Entity { [key: string]: any; }
112
+ export declare class Thread extends Channel { [key: string]: any; }
113
+ export declare class Sticker extends Entity { [key: string]: any; }
114
+ export declare class Emoji extends Entity { [key: string]: any; }
115
+ export declare class ScheduledEvent extends Entity { [key: string]: any; }
116
+ export declare class Collector extends EventEmitter { collected: Collection; next: Promise<any>; stop(reason?: string): void; resetTimer(): this; }
115
117
 
116
118
  export declare class Client extends EventEmitter {
117
- token: string;
118
- rest: REST;
119
- user: unknown;
120
- intents: IntentBitField;
121
- polling: boolean;
122
- pollIntervalMs: number;
123
- keepAlive: boolean;
124
- constructor(options?: { token?: string; intents?: Array<number | bigint | string> | number | bigint | string; restBaseUrl?: string; keepAlive?: boolean; polling?: boolean; pollIntervalMs?: number; registerProcessShutdown?: boolean });
125
- login(token?: string): Promise<string>;
126
- startKeepAlive(): this;
127
- startPolling(): this;
128
- destroy(options?: { setOffline?: boolean }): Promise<this>;
129
- attachProcessShutdown(): this;
130
- setPresence(presence?: Record<string, unknown>): Promise<unknown>;
131
- setStatus(status: string): Promise<unknown>;
132
- channel(id: string): TextChannel;
133
- user(id: string): User;
134
- emitGatewayEvent(eventName: string, payload: unknown): boolean;
119
+ token: string; rest: REST; user: any; guilds: Collection; channels: Collection; users: Collection;
120
+ constructor(options?: { token?: string; intents?: any; restBaseUrl?: string; keepAlive?: boolean; polling?: boolean; pollIntervalMs?: number; registerProcessShutdown?: boolean });
121
+ login(token?: string): Promise<string>; destroy(options?: { setOffline?: boolean }): Promise<this>; isReady(): boolean;
122
+ generateInvite(options?: any): string; fetchInvite(code: string): Promise<any>; fetchWebhook(id: string): Promise<any>; fetchGuildPreview(id: string): Promise<any>;
123
+ fetchSticker(id: string): Promise<any>; fetchVoiceRegions(): Promise<any>; fetchPremiumStickerPacks(): Promise<any>; fetchApplicationEmojis(): Promise<any>;
124
+ fetchGuildTemplate(code: string): Promise<any>; fetchStageInstance(id: string): Promise<any>; fetchGuildWidget(id: string): Promise<any>;
125
+ fetchGuildWidgetImage(id: string): string; fetchGuildWidgetSettings(id: string): Promise<any>; setPresence(presence?: any): Promise<any>; setStatus(status: string): Promise<any>;
126
+ channel(id: string): Channel; guild(id: string): Guild; user(id: string): User;
135
127
  }
136
128
 
137
- export declare function CreateEmbed(data?: Record<string, unknown>): EmbedBuilder;
129
+ export declare function CreateEmbed(data?: any): EmbedBuilder;
130
+ export declare function joinVoiceChannel(options?: any): any; export declare function createAudioPlayer(): any; export declare function createAudioResource(input: any, options?: any): any; export declare function createAudioReceiver(): any; export declare function entersState(target: any): Promise<any>; export declare function getVoiceConnection(): any;
131
+ export declare function time(date?: any, style?: string): string; export declare function userMention(id: any): string; export declare function roleMention(id: any): string; export declare function channelMention(id: any): string; export declare function chatInputApplicationCommandMention(name: string, id: string): string;
132
+ export declare function inlineCode(v: any): string; export declare function codeBlock(lang: string, code?: string): string; export declare function bold(v: any): string; export declare function italic(v: any): string; export declare function underline(v: any): string; export declare function strikethrough(v: any): string; export declare function spoiler(v: any): string; export declare function quoteBlock(v: any): string; export declare function blockQuote(v: any): string; export declare function escapeMarkdown(v: any): string; export declare function hideLinkEmbed(url: string): string; export declare function hyperlink(text: string, url: string): string;
package/src/index.js CHANGED
@@ -5,8 +5,10 @@ const { EventEmitter } = require('events');
5
5
  const DefaultRestBase = 'https://qaut.gg/api';
6
6
 
7
7
  const Events = Object.freeze({
8
- ClientReady: 'clientReady',
8
+ ClientReady: 'ready',
9
+ Ready: 'ready',
9
10
  Debug: 'debug',
11
+ Warn: 'warn',
10
12
  Error: 'error',
11
13
  MessageCreate: 'messageCreate',
12
14
  MessageUpdate: 'messageUpdate',
@@ -17,7 +19,29 @@ const Events = Object.freeze({
17
19
  GuildDelete: 'guildDelete',
18
20
  GuildMemberAdd: 'guildMemberAdd',
19
21
  GuildMemberRemove: 'guildMemberRemove',
22
+ GuildBanAdd: 'guildBanAdd',
23
+ GuildBanRemove: 'guildBanRemove',
24
+ VoiceStateUpdate: 'voiceStateUpdate',
20
25
  PresenceUpdate: 'presenceUpdate',
26
+ TypingStart: 'typingStart',
27
+ ChannelCreate: 'channelCreate',
28
+ ChannelDelete: 'channelDelete',
29
+ ChannelUpdate: 'channelUpdate',
30
+ RoleCreate: 'roleCreate',
31
+ RoleDelete: 'roleDelete',
32
+ RoleUpdate: 'roleUpdate',
33
+ EmojiCreate: 'emojiCreate',
34
+ EmojiDelete: 'emojiDelete',
35
+ EmojiUpdate: 'emojiUpdate',
36
+ StickerCreate: 'stickerCreate',
37
+ StickerDelete: 'stickerDelete',
38
+ StickerUpdate: 'stickerUpdate',
39
+ ThreadCreate: 'threadCreate',
40
+ ThreadDelete: 'threadDelete',
41
+ ThreadUpdate: 'threadUpdate',
42
+ InviteCreate: 'inviteCreate',
43
+ InviteDelete: 'inviteDelete',
44
+ WebhooksUpdate: 'webhooksUpdate',
21
45
  WebhookEvent: 'webhookEvent'
22
46
  });
23
47
 
@@ -27,8 +51,23 @@ const GatewayIntentBits = Object.freeze({
27
51
  GuildMessages: 1 << 2,
28
52
  MessageContent: 1 << 3,
29
53
  GuildPresences: 1 << 4,
30
- DirectMessages: 1 << 5,
31
- Webhooks: 1 << 6
54
+ GuildVoiceStates: 1 << 5,
55
+ GuildInvites: 1 << 6,
56
+ GuildWebhooks: 1 << 7,
57
+ GuildEmojisAndStickers: 1 << 8,
58
+ DirectMessages: 1 << 9,
59
+ DirectMessageTyping: 1 << 10,
60
+ DirectMessageReactions: 1 << 11,
61
+ Webhooks: 1 << 7
62
+ });
63
+
64
+ const Partials = Object.freeze({
65
+ User: 'USER',
66
+ Channel: 'CHANNEL',
67
+ GuildMember: 'GUILD_MEMBER',
68
+ Message: 'MESSAGE',
69
+ Reaction: 'REACTION',
70
+ ThreadMember: 'THREAD_MEMBER'
32
71
  });
33
72
 
34
73
  const Status = Object.freeze({
@@ -39,18 +78,12 @@ const Status = Object.freeze({
39
78
  Offline: 'offline'
40
79
  });
41
80
 
42
- const ActivityType = Object.freeze({
43
- Playing: 0,
44
- Streaming: 1,
45
- Listening: 2,
46
- Watching: 3,
47
- Custom: 4,
48
- Competing: 5
49
- });
81
+ const ActivityType = Object.freeze({ Playing: 0, Streaming: 1, Listening: 2, Watching: 3, Custom: 4, Competing: 5 });
50
82
 
51
83
  const PermissionFlagsBits = Object.freeze({
52
84
  Administrator: 1n << 0n,
53
85
  ViewAuditLog: 1n << 1n,
86
+ ManageGuild: 1n << 2n,
54
87
  ManageServer: 1n << 2n,
55
88
  ManageRoles: 1n << 3n,
56
89
  ManageChannels: 1n << 4n,
@@ -58,7 +91,9 @@ const PermissionFlagsBits = Object.freeze({
58
91
  BanMembers: 1n << 6n,
59
92
  CreateInstantInvite: 1n << 7n,
60
93
  ManageWebhooks: 1n << 11n,
94
+ ViewChannel: 1n << 12n,
61
95
  ViewChannels: 1n << 12n,
96
+ ModerateMembers: 1n << 14n,
62
97
  SendMessages: 1n << 20n,
63
98
  ManageMessages: 1n << 24n,
64
99
  EmbedLinks: 1n << 25n,
@@ -83,168 +118,337 @@ class QauTError extends Error {
83
118
  }
84
119
  }
85
120
 
86
- class BitField {
87
- constructor(bits = 0n) {
88
- this.bitfield = Array.isArray(bits) ? bits.reduce((total, bit) => total | BigInt(bit), 0n) : BigInt(bits);
89
- }
90
-
91
- has(bit) {
92
- return (this.bitfield & BigInt(bit)) === BigInt(bit);
93
- }
94
-
95
- add(...bits) {
96
- bits.flat().forEach(bit => { this.bitfield |= BigInt(bit); });
97
- return this;
98
- }
99
-
100
- remove(...bits) {
101
- bits.flat().forEach(bit => { this.bitfield &= ~BigInt(bit); });
102
- return this;
103
- }
104
-
105
- toString() {
106
- return this.bitfield.toString();
107
- }
108
-
109
- valueOf() {
110
- return this.bitfield;
121
+ class Collection extends Map {
122
+ find(fn) { for (const item of this.values()) if (fn(item, item?.id, this)) return item; return undefined; }
123
+ filter(fn) { const out = new Collection(); for (const [k, v] of this) if (fn(v, k, this)) out.set(k, v); return out; }
124
+ map(fn) { return [...this].map(([k, v]) => fn(v, k, this)); }
125
+ reduce(fn, initial) { let acc = initial; for (const [k, v] of this) acc = fn(acc, v, k, this); return acc; }
126
+ sort(fn) { return new Collection([...this].sort((a, b) => fn(a[1], b[1], a[0], b[0]))); }
127
+ some(fn) { for (const [k, v] of this) if (fn(v, k, this)) return true; return false; }
128
+ every(fn) { for (const [k, v] of this) if (!fn(v, k, this)) return false; return true; }
129
+ concat(...cols) { const out = this.clone(); cols.forEach(col => [...col].forEach(([k, v]) => out.set(k, v))); return out; }
130
+ merge(other, whenInSelf = (_old, val) => val, whenInOther = val => val, whenInBoth = (_old, val) => val) {
131
+ const out = new Collection();
132
+ for (const [k, v] of this) out.set(k, other.has(k) ? whenInBoth(v, other.get(k), k) : whenInSelf(v, k));
133
+ for (const [k, v] of other) if (!this.has(k)) out.set(k, whenInOther(v, k));
134
+ return out;
111
135
  }
136
+ sweep(fn) { let count = 0; for (const [k, v] of this) if (fn(v, k, this)) { this.delete(k); count++; } return count; }
137
+ random() { const arr = [...this.values()]; return arr[Math.floor(Math.random() * arr.length)]; }
138
+ randomKey() { const arr = [...this.keys()]; return arr[Math.floor(Math.random() * arr.length)]; }
139
+ first(amount) { const arr = [...this.values()]; return amount ? arr.slice(0, amount) : arr[0]; }
140
+ firstKey(amount) { const arr = [...this.keys()]; return amount ? arr.slice(0, amount) : arr[0]; }
141
+ last(amount) { const arr = [...this.values()]; return amount ? arr.slice(-amount) : arr[arr.length - 1]; }
142
+ lastKey(amount) { const arr = [...this.keys()]; return amount ? arr.slice(-amount) : arr[arr.length - 1]; }
143
+ at(index) { return [...this.values()].at(index); }
144
+ clone() { return new Collection(this); }
145
+ reverse() { return new Collection([...this].reverse()); }
146
+ partition(fn) { const yes = new Collection(); const no = new Collection(); for (const [k, v] of this) (fn(v, k, this) ? yes : no).set(k, v); return [yes, no]; }
112
147
  }
113
148
 
114
- class PermissionBitField extends BitField {
115
- static Flags = PermissionFlagsBits;
149
+ class BitField {
150
+ constructor(bits = 0n) { this.bitfield = Array.isArray(bits) ? bits.reduce((t, b) => t | BigInt(b), 0n) : BigInt(bits); }
151
+ has(bit) { return (this.bitfield & BigInt(bit)) === BigInt(bit); }
152
+ add(...bits) { bits.flat().forEach(bit => { this.bitfield |= BigInt(bit); }); return this; }
153
+ remove(...bits) { bits.flat().forEach(bit => { this.bitfield &= ~BigInt(bit); }); return this; }
154
+ toString() { return this.bitfield.toString(); }
155
+ valueOf() { return this.bitfield; }
116
156
  }
157
+ class PermissionsBitField extends BitField { static Flags = PermissionFlagsBits; }
158
+ class PermissionBitField extends PermissionsBitField {}
159
+ class IntentBitField extends BitField { static Flags = GatewayIntentBits; }
117
160
 
118
- class IntentBitField extends BitField {
119
- static Flags = GatewayIntentBits;
161
+ class DataBuilder {
162
+ constructor(data = {}) { this.data = { ...data }; }
163
+ toJSON() { return structuredCloneSafe(this.data); }
120
164
  }
121
165
 
122
- class EmbedBuilder {
123
- constructor(data = {}) {
124
- this.data = { ...data };
125
- }
126
-
127
- setTitle(title) { this.data.title = String(title).slice(0, 256); return this; }
128
- setDescription(description) { this.data.description = String(description).slice(0, 4096); return this; }
129
- setColor(color) { this.data.color = normalizeColor(color); return this; }
130
- setURL(url) { this.data.url = String(url); return this; }
131
- setTimestamp(timestamp = new Date()) { this.data.timestamp = new Date(timestamp).toISOString(); return this; }
132
- setAuthor(author) { this.data.author = typeof author === 'string' ? { name: author } : { ...author }; return this; }
133
- setFooter(footer) { this.data.footer = typeof footer === 'string' ? { text: footer } : { ...footer }; return this; }
134
- setImage(url) { this.data.image = { url: String(url) }; return this; }
135
- setThumbnail(url) { this.data.thumbnail = { url: String(url) }; return this; }
136
-
137
- addFields(...fields) {
138
- this.data.fields ||= [];
139
- this.data.fields.push(...fields.flat().map(field => ({
140
- name: String(field.name).slice(0, 256),
141
- value: String(field.value).slice(0, 1024),
142
- inline: Boolean(field.inline)
143
- })));
144
- this.data.fields = this.data.fields.slice(0, 25);
145
- return this;
146
- }
166
+ class EmbedBuilder extends DataBuilder {
167
+ setTitle(v) { this.data.title = String(v).slice(0, 256); return this; }
168
+ setDescription(v) { this.data.description = String(v).slice(0, 4096); return this; }
169
+ setURL(v) { this.data.url = String(v); return this; }
170
+ setColor(v) { this.data.color = normalizeColor(v); return this; }
171
+ setAuthor(v) { this.data.author = typeof v === 'string' ? { name: v } : { ...v }; return this; }
172
+ setFooter(v) { this.data.footer = typeof v === 'string' ? { text: v } : { ...v }; return this; }
173
+ setThumbnail(v) { this.data.thumbnail = { url: String(v) }; return this; }
174
+ setImage(v) { this.data.image = { url: String(v) }; return this; }
175
+ setTimestamp(v = new Date()) { this.data.timestamp = new Date(v).toISOString(); return this; }
176
+ setFields(...fields) { this.data.fields = []; return this.addFields(...fields); }
177
+ addFields(...fields) { this.data.fields ||= []; this.data.fields.push(...fields.flat().map(normalizeField)); this.data.fields = this.data.fields.slice(0, 25); return this; }
178
+ }
147
179
 
148
- toJSON() {
149
- return { ...this.data };
150
- }
180
+ class ButtonBuilder extends DataBuilder {
181
+ constructor(data = {}) { super({ type: 'button', style: 'primary', ...data }); }
182
+ setCustomId(v) { this.data.custom_id = String(v); return this; }
183
+ setLabel(v) { this.data.label = String(v).slice(0, 80); return this; }
184
+ setStyle(v) { this.data.style = v; return this; }
185
+ setEmoji(v) { this.data.emoji = v; return this; }
186
+ setURL(v) { this.data.url = String(v); this.data.style = 'link'; return this; }
187
+ setDisabled(v = true) { this.data.disabled = Boolean(v); return this; }
151
188
  }
152
189
 
153
- class ButtonBuilder {
154
- constructor(data = {}) { this.data = { type: 'button', style: 'primary', ...data }; }
155
- setCustomId(customId) { this.data.custom_id = String(customId); return this; }
156
- setLabel(label) { this.data.label = String(label).slice(0, 80); return this; }
157
- setStyle(style) { this.data.style = style; return this; }
158
- setURL(url) { this.data.url = String(url); this.data.style = 'link'; return this; }
159
- setDisabled(disabled = true) { this.data.disabled = Boolean(disabled); return this; }
160
- toJSON() { return { ...this.data }; }
190
+ class ActionRowBuilder extends DataBuilder {
191
+ constructor(data = {}) { super({ type: 'action_row', components: data.components || [] }); }
192
+ addComponents(...components) { this.data.components.push(...components.flat()); return this; }
193
+ setComponents(...components) { this.data.components = components.flat(); return this; }
194
+ toJSON() { return { ...this.data, components: this.data.components.map(toJSON) }; }
161
195
  }
162
196
 
163
- class ActionRowBuilder {
164
- constructor(data = {}) { this.components = data.components || []; }
165
- addComponents(...components) { this.components.push(...components.flat()); return this; }
166
- toJSON() { return { type: 'action_row', components: this.components.map(component => toJSON(component)) }; }
197
+ class SelectMenuBuilder extends DataBuilder {
198
+ constructor(type = 'string_select', data = {}) { super({ type, options: [], ...data }); }
199
+ setCustomId(v) { this.data.custom_id = String(v); return this; }
200
+ setPlaceholder(v) { this.data.placeholder = String(v); return this; }
201
+ addOptions(...options) { this.data.options ||= []; this.data.options.push(...options.flat()); return this; }
202
+ setMinValues(v) { this.data.min_values = Number(v); return this; }
203
+ setMaxValues(v) { this.data.max_values = Number(v); return this; }
204
+ setDisabled(v = true) { this.data.disabled = Boolean(v); return this; }
205
+ }
206
+ class StringSelectMenuBuilder extends SelectMenuBuilder { constructor(data) { super('string_select', data); } }
207
+ class UserSelectMenuBuilder extends SelectMenuBuilder { constructor(data) { super('user_select', data); } }
208
+ class RoleSelectMenuBuilder extends SelectMenuBuilder { constructor(data) { super('role_select', data); } }
209
+ class MentionableSelectMenuBuilder extends SelectMenuBuilder { constructor(data) { super('mentionable_select', data); } }
210
+ class ChannelSelectMenuBuilder extends SelectMenuBuilder { constructor(data) { super('channel_select', data); } }
211
+
212
+ class ModalBuilder extends DataBuilder {
213
+ constructor(data = {}) { super({ components: [], ...data }); }
214
+ setCustomId(v) { this.data.custom_id = String(v); return this; }
215
+ setTitle(v) { this.data.title = String(v).slice(0, 45); return this; }
216
+ addComponents(...components) { this.data.components.push(...components.flat()); return this; }
167
217
  }
168
218
 
169
- class SlashCommandBuilder {
170
- constructor(data = {}) {
171
- this.data = { type: 'chat_input', options: [], ...data };
172
- }
219
+ class TextInputBuilder extends DataBuilder {
220
+ constructor(data = {}) { super({ type: 'text_input', ...data }); }
221
+ setCustomId(v) { this.data.custom_id = String(v); return this; }
222
+ setLabel(v) { this.data.label = String(v); return this; }
223
+ setStyle(v) { this.data.style = v; return this; }
224
+ setPlaceholder(v) { this.data.placeholder = String(v); return this; }
225
+ setRequired(v = true) { this.data.required = Boolean(v); return this; }
226
+ setMinLength(v) { this.data.min_length = Number(v); return this; }
227
+ setMaxLength(v) { this.data.max_length = Number(v); return this; }
228
+ setValue(v) { this.data.value = String(v); return this; }
229
+ }
173
230
 
174
- setName(name) { this.data.name = String(name).toLowerCase().replace(/\s+/g, '-').slice(0, 32); return this; }
175
- setDescription(description) { this.data.description = String(description).slice(0, 100); return this; }
176
- addStringOption(option) { this.data.options.push({ type: 'string', ...option }); return this; }
177
- addIntegerOption(option) { this.data.options.push({ type: 'integer', ...option }); return this; }
178
- addBooleanOption(option) { this.data.options.push({ type: 'boolean', ...option }); return this; }
179
- toJSON() { return { ...this.data, options: [...this.data.options] }; }
231
+ class SlashCommandBuilder extends DataBuilder {
232
+ constructor(data = {}) { super({ type: 'chat_input', options: [], ...data }); }
233
+ setName(v) { this.data.name = String(v).toLowerCase().replace(/\s+/g, '-').slice(0, 32); return this; }
234
+ setDescription(v) { this.data.description = String(v).slice(0, 100); return this; }
235
+ setDefaultMemberPermissions(v) { this.data.default_member_permissions = v?.toString?.() || String(v); return this; }
236
+ setDMPermission(v) { this.data.dm_permission = Boolean(v); return this; }
237
+ addStringOption(o) { return this.addOption('string', o); }
238
+ addIntegerOption(o) { return this.addOption('integer', o); }
239
+ addBooleanOption(o) { return this.addOption('boolean', o); }
240
+ addUserOption(o) { return this.addOption('user', o); }
241
+ addRoleOption(o) { return this.addOption('role', o); }
242
+ addMentionableOption(o) { return this.addOption('mentionable', o); }
243
+ addNumberOption(o) { return this.addOption('number', o); }
244
+ addChannelOption(o) { return this.addOption('channel', o); }
245
+ addAttachmentOption(o) { return this.addOption('attachment', o); }
246
+ addSubcommand(o) { return this.addOption('subcommand', o); }
247
+ addSubcommandGroup(o) { return this.addOption('subcommand_group', o); }
248
+ addOption(type, option) { this.data.options.push(normalizeOption(type, option)); return this; }
249
+ }
250
+ class ContextMenuCommandBuilder extends DataBuilder {
251
+ setName(v) { this.data.name = String(v); return this; }
252
+ setType(v) { this.data.type = v; return this; }
253
+ setDefaultMemberPermissions(v) { this.data.default_member_permissions = v?.toString?.() || String(v); return this; }
254
+ setDMPermission(v) { this.data.dm_permission = Boolean(v); return this; }
255
+ }
256
+ const StringOption = SlashCommandBuilder;
257
+ const IntegerOption = SlashCommandBuilder;
258
+ const BooleanOption = SlashCommandBuilder;
259
+ const UserOption = SlashCommandBuilder;
260
+ const RoleOption = SlashCommandBuilder;
261
+ const MentionableOption = SlashCommandBuilder;
262
+ const NumberOption = SlashCommandBuilder;
263
+ const ChannelOption = SlashCommandBuilder;
264
+ const AttachmentOption = SlashCommandBuilder;
265
+
266
+ class AttachmentBuilder extends DataBuilder {
267
+ setFile(v) { this.data.file = v; return this; }
268
+ setName(v) { this.data.name = String(v); return this; }
269
+ setDescription(v) { this.data.description = String(v); return this; }
270
+ setSpoiler(v = true) { this.data.spoiler = Boolean(v); return this; }
180
271
  }
181
272
 
182
273
  class REST {
183
- constructor(options = {}) {
184
- this.baseUrl = String(options.baseUrl || DefaultRestBase).replace(/\/+$/, '');
185
- this.token = options.token || '';
186
- this.authPrefix = options.authPrefix || 'Bot';
187
- }
188
-
189
- setToken(token) {
190
- this.token = token;
191
- return this;
192
- }
193
-
274
+ constructor(options = {}) { this.baseUrl = String(options.baseUrl || DefaultRestBase).replace(/\/+$/, ''); this.token = options.token || ''; this.authPrefix = options.authPrefix || 'Bot'; }
275
+ setToken(token) { this.token = token; return this; }
194
276
  async request(method, route, body) {
195
277
  const response = await fetch(`${this.baseUrl}${route}`, {
196
278
  method,
197
- headers: {
198
- Authorization: `${this.authPrefix} ${this.token}`,
199
- 'Content-Type': 'application/json'
200
- },
279
+ headers: { Authorization: `${this.authPrefix} ${this.token}`, 'Content-Type': 'application/json' },
201
280
  body: body === undefined ? undefined : JSON.stringify(serialize(body))
202
281
  });
203
282
  const data = await response.json().catch(() => null);
204
283
  if (!response.ok) throw new QauTError(data?.error || response.statusText, { status: response.status, data });
205
284
  return data;
206
285
  }
207
-
208
286
  get(route) { return this.request('GET', route); }
209
287
  post(route, body) { return this.request('POST', route, body); }
288
+ put(route, body) { return this.request('PUT', route, body); }
210
289
  patch(route, body) { return this.request('PATCH', route, body); }
211
290
  delete(route, body) { return this.request('DELETE', route, body); }
212
291
  }
213
292
 
214
- class TextChannel {
215
- constructor(client, data = {}) {
216
- this.client = client;
217
- Object.assign(this, data);
218
- }
293
+ class Base {
294
+ constructor(client, data = {}) { this.client = client; Object.assign(this, data); }
295
+ notImplemented(name) { throw new QauTError(`${name} is not implemented by the QauT API yet`, { code: 'NOT_IMPLEMENTED' }); }
296
+ }
219
297
 
220
- send(payload) {
221
- return this.client.rest.post(`/bot/channels/${this.id}/messages`, normalizeMessagePayload(payload));
222
- }
298
+ class Guild extends Base {
299
+ fetch() { return this.client.rest.get(`/bot/guilds/${this.id}`); }
300
+ leave() { return this.client.rest.delete(`/bot/guilds/${this.id}/members/@me`); }
301
+ delete() { return this.client.rest.delete(`/bot/guilds/${this.id}`); }
302
+ edit(data) { return this.client.rest.patch(`/bot/guilds/${this.id}`, data); }
303
+ setName(v) { return this.edit({ name: v }); }
304
+ setIcon(v) { return this.edit({ icon: v }); }
305
+ setBanner(v) { return this.edit({ banner: v }); }
306
+ setSplash(v) { return this.edit({ splash: v }); }
307
+ setDescription(v) { return this.edit({ description: v }); }
308
+ setVerificationLevel(v) { return this.edit({ verificationLevel: v }); }
309
+ setExplicitContentFilter(v) { return this.edit({ explicitContentFilter: v }); }
310
+ setDefaultMessageNotifications(v) { return this.edit({ defaultNotifications: v }); }
311
+ setAFKChannel(v) { return this.edit({ afkChannelId: idOf(v) }); }
312
+ setAFKTimeout(v) { return this.edit({ afkTimeout: v }); }
313
+ setOwner(v) { return this.edit({ ownerId: idOf(v) }); }
314
+ fetchAuditLogs() { return this.client.rest.get(`/bot/guilds/${this.id}/audit-logs`); }
315
+ fetchOwner() { return this.client.rest.get(`/bot/guilds/${this.id}/owner`); }
316
+ fetchPreview() { return this.client.fetchGuildPreview(this.id); }
317
+ fetchTemplates() { return this.client.rest.get(`/bot/guilds/${this.id}/templates`); }
318
+ fetchVanityData() { return this.client.rest.get(`/bot/guilds/${this.id}/vanity`); }
319
+ fetchWebhooks() { return this.client.rest.get(`/bot/guilds/${this.id}/webhooks`); }
320
+ fetchIntegrations() { return this.client.rest.get(`/bot/guilds/${this.id}/integrations`); }
321
+ fetchInvites() { return this.client.rest.get(`/bot/guilds/${this.id}/invites`); }
322
+ fetchWidget() { return this.client.fetchGuildWidget(this.id); }
323
+ fetchWidgetSettings() { return this.client.fetchGuildWidgetSettings(this.id); }
324
+ setWidgetSettings(data) { return this.client.rest.patch(`/bot/guilds/${this.id}/widget`, data); }
325
+ createEmoji(data) { return this.client.rest.post(`/bot/guilds/${this.id}/emojis`, data); }
326
+ createSticker(data) { return this.client.rest.post(`/bot/guilds/${this.id}/stickers`, data); }
327
+ createTemplate(data) { return this.client.rest.post(`/bot/guilds/${this.id}/templates`, data); }
328
+ createChannel(data) { return this.client.rest.post(`/bot/guilds/${this.id}/channels`, data); }
329
+ createRole(data) { return this.client.rest.post(`/bot/guilds/${this.id}/roles`, data); }
330
+ createScheduledEvent(data) { return this.client.rest.post(`/bot/guilds/${this.id}/scheduled-events`, data); }
331
+ get commands() { return commandManager(this.client, `/bot/guilds/${this.id}/commands`); }
223
332
  }
224
333
 
225
- class User {
226
- constructor(client, data = {}) {
227
- this.client = client;
228
- Object.assign(this, data);
229
- }
334
+ class Channel extends Base {
335
+ send(payload) { return this.client.rest.post(`/bot/channels/${this.id}/messages`, normalizeMessagePayload(payload)); }
336
+ sendTyping() { return this.client.rest.post(`/bot/channels/${this.id}/typing`, {}); }
337
+ fetch() { return this.client.rest.get(`/bot/channels/${this.id}`); }
338
+ edit(data) { return this.client.rest.patch(`/bot/channels/${this.id}`, data); }
339
+ delete() { return this.client.rest.delete(`/bot/channels/${this.id}`); }
340
+ clone(data) { return this.client.rest.post(`/bot/channels/${this.id}/clone`, data || {}); }
341
+ setName(v) { return this.edit({ name: v }); }
342
+ setTopic(v) { return this.edit({ topic: v }); }
343
+ setNSFW(v = true) { return this.edit({ nsfw: Boolean(v) }); }
344
+ setParent(v) { return this.edit({ parentId: idOf(v) }); }
345
+ setPosition(v) { return this.edit({ position: v }); }
346
+ setRateLimitPerUser(v) { return this.edit({ rateLimitPerUser: v }); }
347
+ setBitrate(v) { return this.edit({ bitrate: v }); }
348
+ setUserLimit(v) { return this.edit({ userLimit: v }); }
349
+ setRTCRegion(v) { return this.edit({ rtcRegion: v }); }
350
+ lockPermissions() { return this.edit({ lockPermissions: true }); }
351
+ bulkDelete(messages) { return this.client.rest.post(`/bot/channels/${this.id}/messages/bulk-delete`, { messages: idsOf(messages) }); }
352
+ createWebhook(data) { return this.client.rest.post(`/bot/channels/${this.id}/webhooks`, data); }
353
+ fetchWebhooks() { return this.client.rest.get(`/bot/channels/${this.id}/webhooks`); }
354
+ createInvite(data) { return this.client.rest.post(`/bot/channels/${this.id}/invites`, data || {}); }
355
+ fetchInvites() { return this.client.rest.get(`/bot/channels/${this.id}/invites`); }
356
+ awaitMessages() { return Promise.resolve(new Collection()); }
357
+ createMessageCollector(options) { return new Collector(options); }
358
+ createMessageComponentCollector(options) { return new Collector(options); }
359
+ get threads() { return { create: data => this.client.rest.post(`/bot/channels/${this.id}/threads`, data) }; }
360
+ get messages() { return { fetch: id => this.client.rest.get(id ? `/bot/channels/${this.id}/messages/${id}` : `/bot/channels/${this.id}/messages`) }; }
361
+ get permissionOverwrites() { return permissionOverwriteManager(this.client, `/bot/channels/${this.id}/permissions`); }
362
+ }
363
+ const TextChannel = Channel;
364
+
365
+ class Message extends Base {
366
+ constructor(client, data = {}) { super(client, data); this.channel = data.channel || (data.channelId ? new Channel(client, { id: data.channelId }) : null); this.author = data.author ? new User(client, data.author) : null; }
367
+ reply(payload) { if (!this.channel) throw new QauTError('Cannot reply without channel information'); return this.channel.send(payload); }
368
+ react(emoji) { return this.client.rest.post(`/bot/messages/${this.id}/reactions`, { emoji }); }
369
+ delete() { return this.client.rest.delete(`/bot/messages/${this.id}`); }
370
+ edit(payload) { return this.client.rest.patch(`/bot/messages/${this.id}`, normalizeMessagePayload(payload)); }
371
+ fetch() { return this.client.rest.get(`/bot/messages/${this.id}`); }
372
+ pin() { return this.client.rest.put(`/bot/messages/${this.id}/pin`, {}); }
373
+ unpin() { return this.client.rest.delete(`/bot/messages/${this.id}/pin`); }
374
+ crosspost() { return this.client.rest.post(`/bot/messages/${this.id}/crosspost`, {}); }
375
+ forward(channel) { return new Channel(this.client, { id: idOf(channel) }).send({ content: this.content, embeds: this.embeds, attachments: this.attachments }); }
376
+ startThread(data) { return this.client.rest.post(`/bot/messages/${this.id}/thread`, data || {}); }
377
+ removeAttachments() { return this.edit({ attachments: [] }); }
378
+ suppressEmbeds(v = true) { return this.edit({ suppressEmbeds: Boolean(v) }); }
379
+ createReactionCollector(options) { return new Collector(options); }
380
+ awaitReactions() { return Promise.resolve(new Collection()); }
381
+ createMessageComponentCollector(options) { return new Collector(options); }
382
+ awaitMessageComponent() { return new Promise(resolve => this.createMessageComponentCollector({ max: 1 }).once('collect', resolve)); }
383
+ }
230
384
 
231
- send(payload) {
232
- return this.client.rest.post(`/bot/users/${this.id}/messages`, normalizeMessagePayload(payload));
233
- }
385
+ class User extends Base {
386
+ fetch() { return this.client.rest.get(`/bot/users/${this.id}`); }
387
+ send(payload) { return this.client.rest.post(`/bot/users/${this.id}/messages`, normalizeMessagePayload(payload)); }
388
+ createDM() { return this.client.rest.post(`/bot/users/${this.id}/dm`, {}); }
389
+ displayAvatarURL() { return this.avatarURL(); }
390
+ avatarURL() { return this.avatar || this.defaultAvatarURL(); }
391
+ bannerURL() { return this.banner || null; }
392
+ defaultAvatarURL() { return `${DefaultRestBase.replace('/api', '')}/assets/qautapp.png`; }
393
+ fetchFlags() { return Promise.resolve(this.flags || []); }
234
394
  }
235
395
 
236
- class Message {
237
- constructor(client, data = {}) {
238
- this.client = client;
239
- Object.assign(this, data);
240
- this.channel = data.channel || (data.channelId ? new TextChannel(client, { id: data.channelId }) : null);
241
- this.author = data.author ? new User(client, data.author) : null;
242
- }
396
+ class GuildMember extends Base {
397
+ fetch() { return this.client.rest.get(`/bot/guilds/${this.guildId}/members/${this.id}`); }
398
+ edit(data) { return this.client.rest.patch(`/bot/guilds/${this.guildId}/members/${this.id}`, data); }
399
+ kick(reason) { return this.client.rest.delete(`/bot/guilds/${this.guildId}/members/${this.id}`, { reason }); }
400
+ ban(data) { return this.client.rest.post(`/bot/guilds/${this.guildId}/bans`, { userId: this.id, ...data }); }
401
+ timeout(ms, reason) { return this.disableCommunicationUntil(Date.now() + ms, reason); }
402
+ disableCommunicationUntil(time, reason) { return this.edit({ communicationDisabledUntil: new Date(time).toISOString(), reason }); }
403
+ send(payload) { return new User(this.client, { id: this.id }).send(payload); }
404
+ setNickname(v) { return this.edit({ nickname: v }); }
405
+ setAvatar(v) { return this.edit({ avatar: v }); }
406
+ setBanner(v) { return this.edit({ banner: v }); }
407
+ setCommunicationDisabledUntil(v) { return this.disableCommunicationUntil(v); }
408
+ get roles() { return roleMemberManager(this.client, this.guildId, this.id); }
409
+ get voice() { return voiceMemberManager(this.client, this.guildId, this.id); }
410
+ }
243
411
 
244
- reply(payload) {
245
- if (!this.channel) throw new QauTError('Cannot reply without channel information');
246
- return this.channel.send(payload);
247
- }
412
+ class Role extends Base {
413
+ edit(data) { return this.client.rest.patch(`/bot/guilds/${this.guildId}/roles/${this.id}`, data); }
414
+ delete() { return this.client.rest.delete(`/bot/guilds/${this.guildId}/roles/${this.id}`); }
415
+ setName(v) { return this.edit({ name: v }); }
416
+ setColor(v) { return this.edit({ color: v }); }
417
+ setColors(v) { return this.edit({ colors: v }); }
418
+ setPermissions(v) { return this.edit({ permissions: v?.toString?.() || v }); }
419
+ setMentionable(v = true) { return this.edit({ mentionable: Boolean(v) }); }
420
+ setHoist(v = true) { return this.edit({ hoist: Boolean(v) }); }
421
+ setPosition(v) { return this.edit({ position: v }); }
422
+ comparePositionTo(role) { return (this.position || 0) - (role.position || 0); }
423
+ }
424
+
425
+ class Interaction extends Base {
426
+ reply(payload) { return this.client.rest.post(`/bot/interactions/${this.id}/reply`, normalizeMessagePayload(payload)); }
427
+ editReply(payload) { return this.client.rest.patch(`/bot/interactions/${this.id}/reply`, normalizeMessagePayload(payload)); }
428
+ deferReply(data) { return this.client.rest.post(`/bot/interactions/${this.id}/defer`, data || {}); }
429
+ followUp(payload) { return this.client.rest.post(`/bot/interactions/${this.id}/followups`, normalizeMessagePayload(payload)); }
430
+ deleteReply() { return this.client.rest.delete(`/bot/interactions/${this.id}/reply`); }
431
+ fetchReply() { return this.client.rest.get(`/bot/interactions/${this.id}/reply`); }
432
+ showModal(modal) { return this.client.rest.post(`/bot/interactions/${this.id}/modal`, toJSON(modal)); }
433
+ awaitModalSubmit() { return Promise.resolve(null); }
434
+ update(payload) { return this.client.rest.patch(`/bot/interactions/${this.id}/message`, normalizeMessagePayload(payload)); }
435
+ deferUpdate() { return this.client.rest.post(`/bot/interactions/${this.id}/defer-update`, {}); }
436
+ }
437
+
438
+ class Reaction extends Base { fetch() { return this.client.rest.get(`/bot/reactions/${this.id}`); } remove() { return this.client.rest.delete(`/bot/reactions/${this.id}`); } get users() { return { fetch: () => this.client.rest.get(`/bot/reactions/${this.id}/users`), remove: id => this.client.rest.delete(`/bot/reactions/${this.id}/users/${id}`) }; } }
439
+ class Invite extends Base { fetch() { return this.client.fetchInvite(this.code || this.id); } delete() { return this.client.rest.delete(`/bot/invites/${this.code || this.id}`); } }
440
+ class Webhook extends Base { send(p) { return this.client.rest.post(`/bot/webhooks/${this.id}`, normalizeMessagePayload(p)); } edit(d) { return this.client.rest.patch(`/bot/webhooks/${this.id}`, d); } delete() { return this.client.rest.delete(`/bot/webhooks/${this.id}`); } fetchMessage(id) { return this.client.rest.get(`/bot/webhooks/${this.id}/messages/${id}`); } editMessage(id, p) { return this.client.rest.patch(`/bot/webhooks/${this.id}/messages/${id}`, normalizeMessagePayload(p)); } deleteMessage(id) { return this.client.rest.delete(`/bot/webhooks/${this.id}/messages/${id}`); } }
441
+ class Thread extends Channel { join() { return this.client.rest.put(`/bot/threads/${this.id}/members/@me`, {}); } leave() { return this.client.rest.delete(`/bot/threads/${this.id}/members/@me`); } setArchived(v = true) { return this.edit({ archived: Boolean(v) }); } setLocked(v = true) { return this.edit({ locked: Boolean(v) }); } setInvitable(v = true) { return this.edit({ invitable: Boolean(v) }); } get members() { return { add: id => this.client.rest.put(`/bot/threads/${this.id}/members/${id}`, {}), remove: id => this.client.rest.delete(`/bot/threads/${this.id}/members/${id}`) }; } }
442
+ class Sticker extends Base { fetch() { return this.client.fetchSticker(this.id); } edit(d) { return this.client.rest.patch(`/bot/stickers/${this.id}`, d); } delete() { return this.client.rest.delete(`/bot/stickers/${this.id}`); } }
443
+ class Emoji extends Base { fetchAuthor() { return this.client.rest.get(`/bot/emojis/${this.id}/author`); } edit(d) { return this.client.rest.patch(`/bot/emojis/${this.id}`, d); } delete() { return this.client.rest.delete(`/bot/emojis/${this.id}`); } }
444
+ class ScheduledEvent extends Base { fetch() { return this.client.rest.get(`/bot/scheduled-events/${this.id}`); } edit(d) { return this.client.rest.patch(`/bot/scheduled-events/${this.id}`, d); } delete() { return this.client.rest.delete(`/bot/scheduled-events/${this.id}`); } setName(v) { return this.edit({ name: v }); } setDescription(v) { return this.edit({ description: v }); } setLocation(v) { return this.edit({ location: v }); } setEntityType(v) { return this.edit({ entityType: v }); } setStatus(v) { return this.edit({ status: v }); } }
445
+
446
+ class Collector extends EventEmitter {
447
+ constructor(options = {}) { super(); this.options = options; this.ended = false; this.collected = new Collection(); this.next = new Promise(resolve => this.once('collect', resolve)); }
448
+ collect(item) { if (this.ended) return; this.collected.set(item.id || Date.now().toString(), item); this.emit('collect', item); }
449
+ dispose(item) { this.emit('dispose', item); }
450
+ stop(reason = 'user') { if (this.ended) return; this.ended = true; this.emit('end', this.collected, reason); }
451
+ resetTimer() { return this; }
248
452
  }
249
453
 
250
454
  class Client extends EventEmitter {
@@ -255,153 +459,104 @@ class Client extends EventEmitter {
255
459
  this.intents = new IntentBitField(options.intents || 0);
256
460
  this.rest = new REST({ token: this.token, baseUrl: options.restBaseUrl || DefaultRestBase });
257
461
  this.user = null;
462
+ this.guilds = new Collection();
463
+ this.channels = new Collection();
464
+ this.users = new Collection();
258
465
  this.keepAlive = options.keepAlive !== false;
259
- this.keepAliveInterval = null;
260
466
  this.polling = options.polling !== false;
261
467
  this.pollIntervalMs = Number(options.pollIntervalMs || 1500);
468
+ this.keepAliveInterval = null;
262
469
  this.pollInterval = null;
263
470
  this.gatewayCursor = null;
264
471
  this.destroyed = false;
265
472
  this.registerProcessShutdown = options.registerProcessShutdown !== false;
266
473
  this.boundShutdown = null;
267
474
  }
268
-
269
- async login(token = this.token) {
270
- if (!token) throw new QauTError('Bot token is required');
271
- this.token = token;
272
- this.rest.setToken(token);
273
- const me = await this.rest.get('/bot/me');
274
- this.user = me;
275
- if (this.keepAlive) this.startKeepAlive();
276
- if (this.polling) this.startPolling();
277
- if (this.registerProcessShutdown) this.attachProcessShutdown();
278
- this.emit(Events.ClientReady, me);
279
- return token;
280
- }
281
-
282
- startKeepAlive() {
283
- if (this.keepAliveInterval) return this;
284
- this.keepAliveInterval = setInterval(() => {
285
- this.emit(Events.Debug, 'QauT.js keep-alive heartbeat');
286
- }, 30_000);
287
- return this;
288
- }
289
-
290
- async destroy(options = {}) {
291
- if (this.destroyed) return this;
292
- this.destroyed = true;
293
- if (options.setOffline !== false && this.token) {
294
- try {
295
- await this.setPresence({ status: Status.Offline });
296
- } catch (err) {
297
- this.emit(Events.Debug, `Failed to set offline presence: ${err.message}`);
298
- }
299
- }
300
- if (this.keepAliveInterval) clearInterval(this.keepAliveInterval);
301
- if (this.pollInterval) clearInterval(this.pollInterval);
302
- this.keepAliveInterval = null;
303
- this.pollInterval = null;
304
- this.user = null;
305
- return this;
306
- }
307
-
308
- attachProcessShutdown() {
309
- if (this.boundShutdown || typeof process === 'undefined') return this;
310
- this.boundShutdown = async () => {
311
- await this.destroy();
312
- process.exit(0);
313
- };
314
- process.once('SIGINT', this.boundShutdown);
315
- process.once('SIGTERM', this.boundShutdown);
316
- return this;
317
- }
318
-
319
- startPolling() {
320
- if (this.pollInterval) return this;
321
- this.gatewayCursor = new Date().toISOString();
322
- const tick = async () => {
323
- try {
324
- const query = this.gatewayCursor ? `?after=${encodeURIComponent(this.gatewayCursor)}` : '';
325
- const data = await this.rest.get(`/bot/gateway/messages${query}`);
326
- this.gatewayCursor = data.cursor || new Date().toISOString();
327
- for (const payload of data.messages || []) {
328
- this.emitGatewayEvent(Events.MessageCreate, payload);
329
- }
330
- } catch (err) {
331
- this.emit(Events.Error, err);
332
- }
333
- };
334
- this.pollInterval = setInterval(tick, this.pollIntervalMs);
335
- return this;
336
- }
337
-
338
- async setPresence(presence = {}) {
339
- return this.rest.patch('/bot/presence', presence);
340
- }
341
-
342
- async setStatus(status) {
343
- return this.setPresence({ status });
344
- }
345
-
346
- channel(id) {
347
- return new TextChannel(this, { id });
348
- }
349
-
350
- user(id) {
351
- return new User(this, { id });
352
- }
353
-
354
- emitGatewayEvent(eventName, payload) {
355
- if (eventName === Events.MessageCreate) return this.emit(eventName, new Message(this, payload));
356
- return this.emit(eventName, payload);
357
- }
475
+ isReady() { return Boolean(this.user && !this.destroyed); }
476
+ async login(token = this.token) { if (!token) throw new QauTError('Bot token is required'); this.token = token; this.rest.setToken(token); this.user = await this.rest.get('/bot/me'); if (this.keepAlive) this.startKeepAlive(); if (this.polling) this.startPolling(); if (this.registerProcessShutdown) this.attachProcessShutdown(); this.emit(Events.ClientReady, this.user); return token; }
477
+ async destroy(options = {}) { if (this.destroyed) return this; this.destroyed = true; if (options.setOffline !== false && this.token) await this.setPresence({ status: Status.Offline }).catch(err => this.emit(Events.Debug, `Failed to set offline presence: ${err.message}`)); if (this.keepAliveInterval) clearInterval(this.keepAliveInterval); if (this.pollInterval) clearInterval(this.pollInterval); this.keepAliveInterval = null; this.pollInterval = null; this.user = null; return this; }
478
+ attachProcessShutdown() { if (this.boundShutdown || typeof process === 'undefined') return this; this.boundShutdown = async () => { await this.destroy(); process.exit(0); }; process.once('SIGINT', this.boundShutdown); process.once('SIGTERM', this.boundShutdown); return this; }
479
+ startKeepAlive() { if (!this.keepAliveInterval) this.keepAliveInterval = setInterval(() => this.emit(Events.Debug, 'QauT.js keep-alive heartbeat'), 30_000); return this; }
480
+ startPolling() { if (this.pollInterval) return this; this.gatewayCursor = new Date().toISOString(); const tick = async () => { try { const q = this.gatewayCursor ? `?after=${encodeURIComponent(this.gatewayCursor)}` : ''; const data = await this.rest.get(`/bot/gateway/messages${q}`); this.gatewayCursor = data.cursor || new Date().toISOString(); for (const payload of data.messages || []) this.emitGatewayEvent(Events.MessageCreate, payload); } catch (err) { this.emit(Events.Error, err); } }; this.pollInterval = setInterval(tick, this.pollIntervalMs); return this; }
481
+ setPresence(presence = {}) { return this.rest.patch('/bot/presence', presence); }
482
+ setStatus(status) { return this.setPresence({ status }); }
483
+ generateInvite(options = {}) { const params = new URLSearchParams({ client_id: options.clientId || this.user?.applicationId || this.user?.id || '', scope: (options.scopes || ['bot', 'applications.commands']).join(' '), permissions: String(options.permissions || 0) }); return `https://qaut.gg/oauth2/authorize?${params}`; }
484
+ fetchInvite(code) { return this.rest.get(`/bot/invites/${code}`); }
485
+ fetchWebhook(id) { return this.rest.get(`/bot/webhooks/${id}`); }
486
+ fetchGuildPreview(id) { return this.rest.get(`/bot/guilds/${id}/preview`); }
487
+ fetchSticker(id) { return this.rest.get(`/bot/stickers/${id}`); }
488
+ fetchVoiceRegions() { return this.rest.get('/bot/voice-regions'); }
489
+ fetchPremiumStickerPacks() { return this.rest.get('/bot/sticker-packs'); }
490
+ fetchApplicationEmojis() { return this.rest.get('/bot/application/emojis'); }
491
+ fetchGuildTemplate(code) { return this.rest.get(`/bot/guild-templates/${code}`); }
492
+ fetchStageInstance(id) { return this.rest.get(`/bot/stage-instances/${id}`); }
493
+ fetchGuildWidget(id) { return this.rest.get(`/bot/guilds/${id}/widget`); }
494
+ fetchGuildWidgetImage(id) { return `${this.rest.baseUrl}/bot/guilds/${id}/widget.png`; }
495
+ fetchGuildWidgetSettings(id) { return this.rest.get(`/bot/guilds/${id}/widget/settings`); }
496
+ channel(id) { return new Channel(this, { id }); }
497
+ guild(id) { return new Guild(this, { id }); }
498
+ user(id) { return new User(this, { id }); }
499
+ emitGatewayEvent(eventName, payload) { if (eventName === Events.MessageCreate || eventName === 'messageCreate') return this.emit('messageCreate', new Message(this, payload)); return this.emit(eventName, payload); }
358
500
  }
359
501
 
360
- function CreateEmbed(data) {
361
- return new EmbedBuilder(data);
362
- }
363
-
364
- function normalizeMessagePayload(payload) {
365
- if (typeof payload === 'string') return { content: payload };
366
- const output = { ...payload };
367
- if (output.embeds) output.embeds = output.embeds.map(toJSON);
368
- if (output.components) output.components = output.components.map(toJSON);
369
- return output;
370
- }
371
-
372
- function normalizeColor(color) {
373
- if (typeof color === 'number') return color;
374
- const value = String(color).replace('#', '');
375
- return Number.parseInt(value, 16);
376
- }
377
-
378
- function toJSON(value) {
379
- return value && typeof value.toJSON === 'function' ? value.toJSON() : value;
380
- }
381
-
382
- function serialize(value) {
383
- return JSON.parse(JSON.stringify(value, (_key, item) => typeof item === 'bigint' ? item.toString() : toJSON(item)));
384
- }
502
+ function commandManager(client, base) { return { create: data => client.rest.post(base, toJSON(data)), fetch: id => client.rest.get(id ? `${base}/${id}` : base), edit: (id, data) => client.rest.patch(`${base}/${id}`, toJSON(data)), delete: id => client.rest.delete(`${base}/${id}`) }; }
503
+ function permissionOverwriteManager(client, base) { return { create: (id, data) => client.rest.put(`${base}/${id}`, data), edit: (id, data) => client.rest.patch(`${base}/${id}`, data), delete: id => client.rest.delete(`${base}/${id}`) }; }
504
+ function roleMemberManager(client, guildId, memberId) { return { add: id => client.rest.put(`/bot/guilds/${guildId}/members/${memberId}/roles/${id}`, {}), remove: id => client.rest.delete(`/bot/guilds/${guildId}/members/${memberId}/roles/${id}`), set: ids => client.rest.patch(`/bot/guilds/${guildId}/members/${memberId}/roles`, { roleIds: idsOf(ids) }), fetch: () => client.rest.get(`/bot/guilds/${guildId}/members/${memberId}/roles`) }; }
505
+ function voiceMemberManager(client, guildId, memberId) { return { disconnect: () => client.rest.delete(`/bot/guilds/${guildId}/members/${memberId}/voice`), setMute: v => client.rest.patch(`/bot/guilds/${guildId}/members/${memberId}/voice`, { muted: Boolean(v) }), setDeaf: v => client.rest.patch(`/bot/guilds/${guildId}/members/${memberId}/voice`, { deafened: Boolean(v) }), setChannel: id => client.rest.patch(`/bot/guilds/${guildId}/members/${memberId}/voice`, { channelId: idOf(id) }), setSuppressed: v => client.rest.patch(`/bot/guilds/${guildId}/members/${memberId}/voice`, { suppressed: Boolean(v) }), setRequestToSpeak: v => client.rest.patch(`/bot/guilds/${guildId}/members/${memberId}/voice`, { requestToSpeak: Boolean(v) }) }; }
506
+
507
+ function joinVoiceChannel(options = {}) { return new VoiceConnection(options); }
508
+ function createAudioPlayer() { return new AudioPlayer(); }
509
+ function createAudioResource(input, options = {}) { return { input, ...options }; }
510
+ function createAudioReceiver() { return new EventEmitter(); }
511
+ function entersState(target) { return Promise.resolve(target); }
512
+ function getVoiceConnection() { return null; }
513
+ class AudioPlayer extends EventEmitter { play(resource) { this.resource = resource; this.emit('play', resource); return this; } pause() { this.paused = true; return true; } unpause() { this.paused = false; return true; } stop() { this.emit('stop'); return true; } }
514
+ class VoiceConnection extends EventEmitter { constructor(options) { super(); this.options = options; } subscribe(player) { this.player = player; return { unsubscribe() {} }; } destroy() { this.emit('destroy'); } }
515
+
516
+ function time(date = new Date(), style) { const ts = Math.floor(new Date(date).getTime() / 1000); return style ? `<t:${ts}:${style}>` : `<t:${ts}>`; }
517
+ const userMention = id => `<@${idOf(id)}>`;
518
+ const roleMention = id => `<@&${idOf(id)}>`;
519
+ const channelMention = id => `<#${idOf(id)}>`;
520
+ const chatInputApplicationCommandMention = (name, id) => `</${name}:${id}>`;
521
+ const inlineCode = v => `\`${escapeMarkdown(String(v))}\``;
522
+ const codeBlock = (lang, code) => code === undefined ? `\`\`\`\n${lang}\n\`\`\`` : `\`\`\`${lang}\n${code}\n\`\`\``;
523
+ const bold = v => `**${v}**`;
524
+ const italic = v => `*${v}*`;
525
+ const underline = v => `__${v}__`;
526
+ const strikethrough = v => `~~${v}~~`;
527
+ const spoiler = v => `||${v}||`;
528
+ const quoteBlock = v => `>>> ${v}`;
529
+ const blockQuote = quoteBlock;
530
+ const escapeMarkdown = v => String(v).replace(/([\\`*_{}[\]()#+\-.!|>~])/g, '\\$1');
531
+ const hideLinkEmbed = url => `<${url}>`;
532
+ const hyperlink = (text, url) => `[${text}](${url})`;
533
+
534
+ function CreateEmbed(data) { return new EmbedBuilder(data); }
535
+ function normalizeMessagePayload(payload) { if (typeof payload === 'string') return { content: payload }; const out = { ...payload }; if (out.embeds) out.embeds = out.embeds.map(toJSON); if (out.components) out.components = out.components.map(toJSON); return out; }
536
+ function normalizeColor(color) { if (typeof color === 'number') return color; return Number.parseInt(String(color).replace('#', ''), 16); }
537
+ function normalizeField(field) { return { name: String(field.name).slice(0, 256), value: String(field.value).slice(0, 1024), inline: Boolean(field.inline) }; }
538
+ function normalizeOption(type, option) { const data = typeof option?.toJSON === 'function' ? option.toJSON() : option || {}; return { type, ...data }; }
539
+ function toJSON(value) { return value && typeof value.toJSON === 'function' ? value.toJSON() : value; }
540
+ function serialize(value) { return JSON.parse(JSON.stringify(value, (_k, item) => typeof item === 'bigint' ? item.toString() : toJSON(item))); }
541
+ function structuredCloneSafe(value) { return JSON.parse(JSON.stringify(value, (_k, item) => typeof item === 'bigint' ? item.toString() : toJSON(item))); }
542
+ function idOf(value) { return typeof value === 'object' && value ? value.id : value; }
543
+ function idsOf(values) { return Array.isArray(values) ? values.map(idOf) : [idOf(values)]; }
544
+
545
+ Object.defineProperty(User.prototype, 'displayName', {
546
+ configurable: true,
547
+ get() { return this.globalName || this.username || this.id; }
548
+ });
385
549
 
386
550
  module.exports = {
387
- ActionRowBuilder,
388
- ActivityType,
389
- BitField,
390
- ButtonBuilder,
391
- Client,
392
- CreateEmbed,
393
- DefaultRestBase,
394
- EmbedBuilder,
395
- Events,
396
- GatewayIntentBits,
397
- IntentBitField,
398
- Message,
399
- PermissionBitField,
400
- PermissionFlagsBits,
401
- QauTError,
402
- REST,
403
- SlashCommandBuilder,
404
- Status,
405
- TextChannel
406
- , User
551
+ ActionRowBuilder, ActivityType, AttachmentBuilder, BitField, ButtonBuilder, Channel, ChannelSelectMenuBuilder,
552
+ Client, Collection, ContextMenuCommandBuilder, CreateEmbed, DefaultRestBase, EmbedBuilder, Emoji, Events,
553
+ GatewayIntentBits, Guild, GuildMember, IntentBitField, Interaction, Invite, Message, ModalBuilder,
554
+ PermissionBitField, PermissionsBitField, PermissionFlagsBits, Partials, QauTError, REST, Reaction, Role,
555
+ RoleSelectMenuBuilder, ScheduledEvent, SelectMenuBuilder, SlashCommandBuilder, Status, Sticker,
556
+ StringSelectMenuBuilder, TextChannel, TextInputBuilder, Thread, User, UserSelectMenuBuilder, Webhook,
557
+ MentionableSelectMenuBuilder, StringOption, IntegerOption, BooleanOption, UserOption, RoleOption,
558
+ MentionableOption, NumberOption, ChannelOption, AttachmentOption,
559
+ joinVoiceChannel, createAudioPlayer, createAudioResource, createAudioReceiver, entersState, getVoiceConnection,
560
+ time, userMention, roleMention, channelMention, chatInputApplicationCommandMention, inlineCode, codeBlock,
561
+ bold, italic, underline, strikethrough, spoiler, quoteBlock, blockQuote, escapeMarkdown, hideLinkEmbed, hyperlink
407
562
  };