guilds.js 0.0.2 → 0.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,6 +1,10 @@
1
- <p align="center">
2
- <img src="public/logo.png" alt="guilds.js Logo" width="85" />
3
- </p>
1
+ <div align="center">
2
+ <img
3
+ alt="guilds.js Logo"
4
+ width="85"
5
+ src="https://cdn.discordapp.com/attachments/1025091872198250597/1475938039095103669/guilds.js.png?ex=699f4dea&is=699dfc6a&hm=a52d790f5cfa4820e4171126ed454f47ad32f94f5182d781ae08304bb2cdb77e&"
6
+ />
7
+ </div>
4
8
 
5
9
  <div align="center">
6
10
  <a href="https://github.com/andrewdku/guilds.js">GitHub</a> |
@@ -25,14 +29,18 @@ bun add guilds.js
25
29
  ## Example
26
30
 
27
31
  ```js
28
- import { Client } from "guilds.js";
32
+ import { Client, GatewayIntents } from "guilds.js";
29
33
 
30
34
  const client = new Client({
31
35
  // https://discord.com/developers/applications
32
- token: "bot token",
33
-
34
- // client intents (as a number)
35
- intents: 0,
36
+ token: "TOKEN",
37
+
38
+ // client intents
39
+ intents: [
40
+ GatewayIntents.Guilds,
41
+ GatewayIntents.GuildMembers,
42
+ GatewayIntents.GuildMessages,
43
+ ],
36
44
  });
37
45
 
38
46
  client.once("ready", () => {
@@ -49,4 +57,4 @@ client.connect();
49
57
 
50
58
  # License
51
59
 
52
- guilds.js is licensed under the [Apache 2.0 license](LICENSE).
60
+ Licensed under the [Apache License 2.0](LICENSE).
package/dist/index.cjs CHANGED
@@ -1,7 +1,30 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
2
 
3
+ //#region src/utils/color-convert.ts
4
+ /**
5
+ * Converts an integer color to a hex color string
6
+ * @returns Hex string or null
7
+ */
8
+ function colorIntToHex(color, addHashSymbol = false) {
9
+ if (color == null || !Number.isFinite(color)) return null;
10
+ const hex = (color >>> 0 & 16777215).toString(16).padStart(6, "0");
11
+ return addHashSymbol ? `#${hex}` : hex;
12
+ }
13
+ /**
14
+ * Converts a hex color string to an integer color
15
+ * @returns Color integer or null
16
+ */
17
+ function hexToColorInt(hex) {
18
+ if (!hex) return null;
19
+ hex = hex.trim().replace(/^#/, "");
20
+ hex = hex.length === 3 ? hex.split("").map((c) => c + c).join("") : hex;
21
+ if (!/^[0-9a-fA-F]{6}$/.test(hex)) return null;
22
+ return parseInt(hex, 16);
23
+ }
24
+
25
+ //#endregion
3
26
  //#region src/utils/constants.ts
4
- const activityTypes = {
27
+ const ActivityTypes = {
5
28
  Competing: 5,
6
29
  Custom: 4,
7
30
  Listening: 2,
@@ -10,15 +33,30 @@ const activityTypes = {
10
33
  Watching: 3
11
34
  };
12
35
  const baseApiUrl = "https://discord.com/api/v10";
13
- const errorCodes = [
14
- "ClientIntentsError",
15
- "ClientPropsError",
16
- "ClientTokenError",
17
- "DiscordAPIError",
18
- "GatewayError",
19
- "WebSocketError"
20
- ];
21
- const opCodes = {
36
+ const GatewayIntents = {
37
+ AutoModerationConfiguration: 1 << 20,
38
+ AutoModerationExecution: 1 << 21,
39
+ DirectMessagePolls: 1 << 25,
40
+ DirectMessageReactions: 8192,
41
+ DirectMessages: 4096,
42
+ DirectMessageTyping: 16384,
43
+ GuildExpressions: 8,
44
+ GuildIntegrations: 16,
45
+ GuildInvites: 64,
46
+ GuildMembers: 2,
47
+ GuildMessagePolls: 1 << 24,
48
+ GuildMessageReactions: 1024,
49
+ GuildMessages: 512,
50
+ GuildMessageTyping: 2048,
51
+ GuildModeration: 4,
52
+ GuildPresences: 256,
53
+ Guilds: 1,
54
+ GuildScheduledEvents: 65536,
55
+ GuildVoiceStates: 128,
56
+ GuildWebhooks: 32,
57
+ MessageContent: 32768
58
+ };
59
+ const GatewayOpcodes = {
22
60
  Dispatch: 0,
23
61
  Heartbeat: 1,
24
62
  HeartbeatACK: 11,
@@ -33,15 +71,41 @@ const opCodes = {
33
71
  VoiceStateUpdate: 3
34
72
  };
35
73
 
74
+ //#endregion
75
+ //#region src/utils/endpoints.ts
76
+ /** Discord's API v10 endpoints */
77
+ const Endpoints = {
78
+ gateway() {
79
+ return `${baseApiUrl}/gateway`;
80
+ },
81
+ gatewayBot() {
82
+ return `${Endpoints.gateway()}/bot`;
83
+ },
84
+ user(userId = "@me") {
85
+ return `${baseApiUrl}/users/${userId}`;
86
+ }
87
+ };
88
+
36
89
  //#endregion
37
90
  //#region src/classes/EventHandler.ts
91
+ /** Class representing a type-safe EventEmitter */
38
92
  var EventHandler = class {
39
93
  #listeners = {};
94
+ /**
95
+ * Add a new event listener
96
+ * @param event Event name
97
+ * @param listener Listener callback
98
+ */
40
99
  on(event, listener) {
41
100
  if (!this.#listeners[event]) this.#listeners[event] = [];
42
101
  this.#listeners[event].push(listener);
43
102
  return this;
44
103
  }
104
+ /**
105
+ * Add a new event listener which only runs once
106
+ * @param event Event name
107
+ * @param listener Listener callback
108
+ */
45
109
  once(event, listener) {
46
110
  const wrapped = (...args) => {
47
111
  listener(...args);
@@ -50,11 +114,21 @@ var EventHandler = class {
50
114
  this.on(event, wrapped);
51
115
  return this;
52
116
  }
117
+ /**
118
+ * Remove an event name
119
+ * @param event Event name
120
+ * @param listener Listener callback
121
+ */
53
122
  off(event, listener) {
54
123
  if (!this.#listeners[event]) return this;
55
124
  this.#listeners[event] = this.#listeners[event].filter((l) => l !== listener);
56
125
  return this;
57
126
  }
127
+ /**
128
+ * Emit an event
129
+ * @param event Event name
130
+ * @param args Event arguments
131
+ */
58
132
  async emit(event, ...args) {
59
133
  if (!this.#listeners[event]) return false;
60
134
  for (const listener of this.#listeners[event]) await listener(...args);
@@ -64,6 +138,7 @@ var EventHandler = class {
64
138
 
65
139
  //#endregion
66
140
  //#region src/classes/GuildsError.ts
141
+ /** Class representing a library-related error */
67
142
  var GuildsError = class extends Error {
68
143
  static name = "GuildsError";
69
144
  scope;
@@ -78,161 +153,362 @@ var GuildsError = class extends Error {
78
153
  };
79
154
 
80
155
  //#endregion
81
- //#region src/classes/Routes.ts
82
- var Routes = class {
83
- static gateway(bot = false) {
84
- return `${baseApiUrl}/gateway${bot ? "/bot" : ""}`;
156
+ //#region src/classes/RESTManager.ts
157
+ /** Class representing a Discord REST API manager */
158
+ var RESTManager = class {
159
+ #token;
160
+ /**
161
+ * Instantiate a new Discord API manager
162
+ * @param token Client token
163
+ */
164
+ constructor(token) {
165
+ this.#token = token;
85
166
  }
86
- static user(userId = "@me") {
87
- return `${baseApiUrl}/users/${userId}`;
167
+ /**
168
+ * Internal request method
169
+ * @param method HTTP request method
170
+ * @param endpoint Endpoint URI
171
+ * @param init Request data
172
+ */
173
+ async #request(method, endpoint, init) {
174
+ const res = await fetch(endpoint, {
175
+ method,
176
+ headers: {
177
+ Authorization: this.#token,
178
+ "Content-Type": "application/json",
179
+ ...init?.headers ?? {}
180
+ },
181
+ ...init
182
+ });
183
+ if (!res.ok) throw new GuildsError(`${await res.text().catch(() => null) ?? res.statusText} (${res.status})`, "DiscordAPIError");
184
+ const json = await res.json().catch(() => null);
185
+ return Object.assign(res, { data: json });
186
+ }
187
+ /**
188
+ * Create a HTTP DELETE request
189
+ * @param endpoint Endpoint URI
190
+ * @param init Request data
191
+ */
192
+ delete(endpoint, init) {
193
+ return this.#request("DELETE", endpoint, init);
194
+ }
195
+ /**
196
+ * Create a HTTP GET request
197
+ * @param endpoint Endpoint URI
198
+ * @param init Request data
199
+ */
200
+ get(endpoint, init) {
201
+ return this.#request("GET", endpoint, init);
202
+ }
203
+ /**
204
+ * Create a HTTP PATCH request
205
+ * @param endpoint Endpoint URI
206
+ * @param init Request data
207
+ */
208
+ patch(endpoint, init) {
209
+ return this.#request("PATCH", endpoint, init);
210
+ }
211
+ /**
212
+ * Create a HTTP POST request
213
+ * @param endpoint Endpoint URI
214
+ * @param init Request data
215
+ */
216
+ post(endpoint, init) {
217
+ return this.#request("POST", endpoint, init);
218
+ }
219
+ /**
220
+ * Create a HTTP PUT request
221
+ * @param endpoint Endpoint URI
222
+ * @param init Request data
223
+ */
224
+ put(endpoint, init) {
225
+ return this.#request("PUT", endpoint, init);
88
226
  }
89
227
  };
90
228
 
91
229
  //#endregion
92
- //#region src/classes/DiscordAPI.ts
93
- var DiscordAPI = class {
94
- #token;
95
- constructor(token) {
96
- if (!token) throw new GuildsError("Token must be provided", "DiscordAPIError");
97
- this.#token = token;
230
+ //#region src/classes/User.ts
231
+ /**
232
+ * Class representing a Discord user
233
+ * @see https://docs.discord.com/developers/resources/user
234
+ */
235
+ var User = class {
236
+ #client;
237
+ /** The user's banner color as a color integer */
238
+ accentColor;
239
+ /** The user's banner color as a hex color*/
240
+ accentColorHex;
241
+ /** The user's about me (client only) */
242
+ bio;
243
+ /** Whether the user is an application (bot) */
244
+ bot = false;
245
+ /** The user's discriminator, or "0" if they have none */
246
+ discriminator = "0";
247
+ /** The user's display name or bot's application name */
248
+ displayName;
249
+ /** The user's email (user clients only) */
250
+ email;
251
+ /** The user's ID snowflake */
252
+ id;
253
+ /** Whether the user has two factor authentication enabled (user clients only) */
254
+ mfaEnabled;
255
+ /** The data from Discord's API provided as-is */
256
+ rawData;
257
+ /** Whether the user is a Discord system account */
258
+ system = false;
259
+ /** The user's username (not to be confused with display name or tag) */
260
+ username;
261
+ /** Whether the user's email is verified (user clients only) */
262
+ verified;
263
+ constructor(client, data) {
264
+ if (!client || !(client instanceof Client)) throw new GuildsError("Invalid client provided", "DiscordAPIError");
265
+ this.#client = client;
266
+ this.accentColor = data.accent_color;
267
+ this.accentColorHex = colorIntToHex(data.accent_color || null) || null;
268
+ this.bio = data.bio ?? null;
269
+ this.bot = data.bot || false;
270
+ this.discriminator = data.discriminator || "0";
271
+ this.email = data.email;
272
+ this.displayName = data.global_name;
273
+ this.id = data.id;
274
+ this.mfaEnabled = data.mfa_enabled;
275
+ this.rawData = data;
276
+ this.system = data.system || false;
277
+ this.username = data.username;
278
+ this.verified = data.verified;
279
+ return this;
98
280
  }
99
- get token() {
100
- return this.#token;
281
+ /** The client associated with this user */
282
+ get client() {
283
+ return this.#client;
101
284
  }
102
- async get(input, init) {
103
- return await fetch(input, init);
285
+ /** Get the user's avatar as an image URL */
286
+ avatarURL(props) {
287
+ if (!props || !props.size || props.format && typeof props.format !== "string") throw new GuildsError("Invalid user avatar URL props provided", "DiscordAPIError");
288
+ const avatarHash = this.rawData.avatar;
289
+ if (!avatarHash) return null;
290
+ return `https://cdn.discordapp.com/avatars/${this.id}/${avatarHash}.${props.format || (avatarHash.startsWith("a_") ? "gif" : "png")}?size=${props.size}`;
291
+ }
292
+ /** `username#0000` or just `username` (if no discriminator) */
293
+ get tag() {
294
+ return this.discriminator == "0" ? this.username : `${this.username}#${this.discriminator}`;
295
+ }
296
+ /** User mention as a string, e.g. <@123456789> */
297
+ toString() {
298
+ return `<@${this.id}>`;
104
299
  }
105
300
  };
106
301
 
107
302
  //#endregion
108
303
  //#region src/classes/Client.ts
304
+ /** Class representing a Discord client */
109
305
  var Client = class extends EventHandler {
110
- #api;
111
306
  #token;
112
- #heartbeatInterval;
113
- #presence = {
307
+ /** Gateway heartbeat inteval */
308
+ heartbeatInterval;
309
+ /** Last received sequence number */
310
+ sequenceNumber = null;
311
+ /** Gateway session ID */
312
+ sessionId;
313
+ /** REST manager instance to handle API calls */
314
+ rest;
315
+ /** Client intents bitfield */
316
+ intents;
317
+ /** Whether the client is ready */
318
+ ready = false;
319
+ /** WebSocket connection */
320
+ ws;
321
+ /** Client user, or null if not ready */
322
+ user = null;
323
+ /** Current presence information */
324
+ presence = {
114
325
  platform: "desktop",
115
326
  status: "online",
116
327
  activities: []
117
328
  };
118
- #sequenceNumber = null;
119
- #sessionId;
120
- #intents;
121
- #ready = false;
122
- #ws;
123
- get token() {
124
- return this.#token;
125
- }
126
- get intents() {
127
- return this.#intents;
128
- }
129
- get heartbeatInterval() {
130
- return this.#heartbeatInterval;
131
- }
132
- get presence() {
133
- return this.#presence;
134
- }
135
- isReady() {
136
- return this.#ready;
137
- }
329
+ /**
330
+ * Instantiate a new Client
331
+ * @param props Client options
332
+ */
138
333
  constructor(props) {
139
334
  super();
140
- if (!props || typeof props !== "object") throw new GuildsError("Invalid client props were provided", "ClientPropsError");
141
- if (!props.token || typeof props.token !== "string") throw new GuildsError("Invalid token was provided", "ClientTokenError");
142
- if (!props.intents || typeof props.intents !== "number") throw new GuildsError("Invalid intents were provided", "ClientIntentsError");
335
+ if (!props || typeof props !== "object") throw new GuildsError("Invalid client props provided", "ClientPropsError");
336
+ if (!props.token || typeof props.token !== "string") throw new GuildsError("Invalid token provided", "ClientTokenError");
337
+ if (props.intents === null || props.intents === void 0 || Array.isArray(props.intents) == false && typeof props.intents !== "number") throw new GuildsError("Invalid intents provided", "ClientIntentsError");
143
338
  if (props.presence) {
144
339
  if (typeof props.presence !== "object") throw new GuildsError("Invalid client presence was provided", "ClientPropsError");
145
340
  this.setPresence(props.presence);
146
341
  }
147
342
  this.#token = props.token.trim().toLowerCase().startsWith("bot ") ? props.token : `Bot ${props.token}`;
148
- this.#intents = props.intents;
149
- this.#api = new DiscordAPI(this.#token);
343
+ this.rest = new RESTManager(this.#token);
344
+ this.intents = parseIntents(props.intents);
150
345
  return this;
151
346
  }
347
+ /** The client's token */
348
+ get token() {
349
+ return this.#token;
350
+ }
351
+ /** Start the connection to Discord's gateway */
152
352
  async connect() {
153
- const res = await this.#api.get(Routes.gateway(true));
154
- const userRes = await this.#api.get(Routes.user());
155
- if (!res.ok || !userRes.ok || !res || !userRes) throw new GuildsError("Failed to connect to Discord", "GatewayError");
156
- const data = await res.json();
157
- this.#ws = new WebSocket(`${data.url}?v=10&encoding=json`);
158
- this.#ws.onmessage = (event) => {
353
+ const res = await this.rest.get(Endpoints.gatewayBot());
354
+ const userRes = await this.rest.get(Endpoints.user());
355
+ if (!res.ok || !userRes.ok) throw new GuildsError("Failed to connect to Discord", "DiscordAPIError");
356
+ this.user = new User(this, userRes.data);
357
+ this.lastHeartbeatAck = true;
358
+ this.destroyed = false;
359
+ this.#connectWebSocket(res.data.url);
360
+ return this;
361
+ }
362
+ /** Initialize the WebSocket */
363
+ #connectWebSocket(url) {
364
+ if (this.destroyed) return;
365
+ this.ws = new WebSocket(`${url}?v=10&encoding=json`);
366
+ this.ws.onopen = () => this.emit("debug", "WebSocket connected");
367
+ this.ws.onerror = (error) => this.emit("error", `WebSocket error: ${error}`);
368
+ this.ws.onmessage = (event) => {
159
369
  this.#handleGatewayEvent(JSON.parse(event.data.toString()));
160
370
  };
161
- return this;
371
+ this.ws.onclose = (event) => {
372
+ this.emit("debug", `WebSocket closed: ${event.reason} (${event.code})`);
373
+ if (!this.destroyed) setTimeout(() => this.#connectWebSocket(url), 3e3);
374
+ };
162
375
  }
376
+ destroyed = false;
377
+ lastHeartbeatAck = true;
378
+ /** Handle incoming gateway events */
163
379
  #handleGatewayEvent(payload) {
164
- if (payload.s !== void 0 && payload.s !== null) this.#sequenceNumber = payload.s;
380
+ if (payload.s !== void 0 && payload.s !== null) this.sequenceNumber = payload.s;
165
381
  switch (payload.op) {
166
- case opCodes.Hello:
382
+ case GatewayOpcodes.Hello:
167
383
  this.emit("debug", "Received Hello event");
168
- this.#heartbeatInterval = setInterval(() => {
169
- this.#ws?.send(JSON.stringify({
170
- op: opCodes.Heartbeat,
171
- d: this.#sequenceNumber
384
+ if (this.heartbeatInterval) clearInterval(this.heartbeatInterval);
385
+ this.lastHeartbeatAck = true;
386
+ this.heartbeatInterval = setInterval(() => {
387
+ if (!this.lastHeartbeatAck) {
388
+ this.emit("debug", "Heartbeat ACK failed, reconnecting...");
389
+ this.ws?.close(4e3, "Heartbeat failed");
390
+ return;
391
+ }
392
+ this.lastHeartbeatAck = false;
393
+ this.ws?.send(JSON.stringify({
394
+ op: GatewayOpcodes.Heartbeat,
395
+ d: this.sequenceNumber
172
396
  }));
173
397
  }, payload.d.heartbeat_interval);
174
- this.emit("debug", "Identifying...");
175
- this.#ws?.send(JSON.stringify({
176
- op: opCodes.Identify,
177
- d: {
178
- token: this.#token,
179
- intents: this.#intents,
180
- presence: this.#presence,
181
- properties: this.#presence.platform === "desktop" ? {
182
- $os: "linux",
183
- $browser: "guilds.js",
184
- $device: "guilds.js"
185
- } : {
186
- $os: "Discord Android",
187
- $browser: "Discord Android",
188
- $device: "Discord Android"
398
+ if (this.sessionId) {
399
+ this.ws?.send(JSON.stringify({
400
+ op: GatewayOpcodes.Resume,
401
+ d: {
402
+ token: this.#token,
403
+ session_id: this.sessionId,
404
+ seq: this.sequenceNumber
189
405
  }
190
- }
191
- }));
406
+ }));
407
+ this.emit("debug", "Resuming session...");
408
+ } else {
409
+ this.ws?.send(JSON.stringify({
410
+ op: GatewayOpcodes.Identify,
411
+ d: {
412
+ token: this.#token,
413
+ intents: this.intents,
414
+ presence: this.presence,
415
+ properties: this.presence.platform === "desktop" ? {
416
+ $os: "linux",
417
+ $browser: "guilds.js",
418
+ $device: "guilds.js"
419
+ } : {
420
+ $os: "Discord Android",
421
+ $browser: "Discord Android",
422
+ $device: "Discord Android"
423
+ }
424
+ }
425
+ }));
426
+ this.emit("debug", "Identifying...");
427
+ }
428
+ break;
429
+ case GatewayOpcodes.HeartbeatACK:
430
+ this.lastHeartbeatAck = true;
192
431
  break;
193
- case opCodes.Dispatch:
432
+ case GatewayOpcodes.Dispatch:
194
433
  if (payload.t !== "READY") break;
195
- this.#sessionId = payload.d.session_id;
196
- this.#ready = true;
434
+ this.sessionId = payload.d.session_id;
435
+ this.ready = true;
436
+ this.emit("debug", "Received Dispatch (Ready) event");
197
437
  this.emit("ready", this);
198
438
  break;
199
439
  }
200
440
  }
441
+ /** Update the client's user presence */
201
442
  setPresence(presence) {
202
- this.#presence = {
203
- ...this.#presence,
443
+ this.presence = {
444
+ ...this.presence,
204
445
  ...presence
205
446
  };
206
- if (this.#ws) this.#ws.send(JSON.stringify({
207
- op: opCodes.PresenceUpdate,
447
+ if (this.ws) this.ws.send(JSON.stringify({
448
+ op: GatewayOpcodes.PresenceUpdate,
208
449
  d: {
209
- status: this.#presence.status,
450
+ status: this.presence.status,
210
451
  since: null,
211
452
  afk: false,
212
- activities: (this.#presence.activities ?? []).map((a) => ({
453
+ activities: (this.presence.activities ?? []).map((a) => ({
213
454
  ...a,
214
- type: typeof a.type === "string" ? activityTypes[a.type] : a.type
455
+ type: typeof a.type === "string" ? ActivityTypes[a.type] : a.type
215
456
  }))
216
457
  }
217
458
  }));
218
459
  return this;
219
460
  }
220
- async disconnect() {
221
- if (this.#heartbeatInterval) clearInterval(this.#heartbeatInterval);
222
- if (this.#ws) {
223
- this.#ws.close(1e3, "Client disconnected");
224
- this.#ws = void 0;
225
- }
461
+ /** Destroy the connection to Discord's gateway */
462
+ disconnect() {
463
+ if (this.heartbeatInterval) clearInterval(this.heartbeatInterval);
464
+ this.ws?.close(1e3, "Client disconnected");
465
+ this.ws = void 0;
226
466
  }
227
467
  };
228
468
 
229
469
  //#endregion
470
+ //#region src/utils/parse-intents.ts
471
+ /**
472
+ * Parse intents into bitfield
473
+ * @param intents Intents resolvable
474
+ * @returns Parsed intents as a bitfield
475
+ */
476
+ function parseIntents(intents) {
477
+ if (typeof intents === "number") return intents;
478
+ else if (typeof intents === "string") {
479
+ const value = GatewayIntents[intents];
480
+ if (typeof value !== "number") throw new GuildsError("Invalid intents provided", "ClientIntentsError");
481
+ return value;
482
+ } else if (Array.isArray(intents)) {
483
+ let bitfield = 0;
484
+ for (const intent of intents) {
485
+ if (typeof intent === "number") {
486
+ bitfield |= intent;
487
+ continue;
488
+ }
489
+ if (typeof intent === "string") {
490
+ const value = GatewayIntents[intent];
491
+ if (typeof value !== "number") throw new GuildsError("Invalid intents provided", "ClientIntentsError");
492
+ bitfield |= value;
493
+ continue;
494
+ }
495
+ throw new GuildsError("Invalid intents provided", "ClientIntentsError");
496
+ }
497
+ return bitfield;
498
+ } else throw new GuildsError("Invalid intents provided", "ClientIntentsError");
499
+ }
500
+
501
+ //#endregion
502
+ exports.ActivityTypes = ActivityTypes;
230
503
  exports.Client = Client;
231
- exports.DiscordAPI = DiscordAPI;
504
+ exports.Endpoints = Endpoints;
232
505
  exports.EventHandler = EventHandler;
506
+ exports.GatewayIntents = GatewayIntents;
507
+ exports.GatewayOpcodes = GatewayOpcodes;
233
508
  exports.GuildsError = GuildsError;
234
- exports.Routes = Routes;
235
- exports.activityTypes = activityTypes;
509
+ exports.RESTManager = RESTManager;
510
+ exports.User = User;
236
511
  exports.baseApiUrl = baseApiUrl;
237
- exports.errorCodes = errorCodes;
238
- exports.opCodes = opCodes;
512
+ exports.colorIntToHex = colorIntToHex;
513
+ exports.hexToColorInt = hexToColorInt;
514
+ exports.parseIntents = parseIntents;