discord-self-lite 0.1.9 → 0.1.11
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 +9 -118
- package/package.json +2 -3
- package/src/classes/Channel.js +1 -0
- package/src/classes/Client.js +63 -19
- package/src/classes/Guild.js +1 -1
- package/src/classes/Message.js +12 -14
- package/src/connection/rest/RestManager.js +13 -5
- package/src/connection/ws/WebSocket.js +36 -16
- package/src/classes/WebSocketError.js +0 -18
package/README.md
CHANGED
|
@@ -45,126 +45,17 @@ client.on("messageCreate", async (message) => {
|
|
|
45
45
|
|
|
46
46
|
## API Reference
|
|
47
47
|
|
|
48
|
-
|
|
48
|
+
The full API documentation is available in the [`docs/api/`](docs/api/README.md) directory. Here are the core classes:
|
|
49
49
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
- `client.login(token)` - Login with user token
|
|
58
|
-
- `client.getChannel(channelId)` - Get cached channel
|
|
59
|
-
- `client.fetchChannel(channelId)` - Fetch channel from API
|
|
60
|
-
- `client.fetchMessage(channelId, messageId)` - Fetch specific message
|
|
61
|
-
|
|
62
|
-
#### Properties
|
|
63
|
-
|
|
64
|
-
- `client.user` - Current user object (available after ready event)
|
|
65
|
-
- `client.guilds` - Map of cached guild instances
|
|
66
|
-
- `client.channels` - Map of cached channel instances
|
|
67
|
-
- `client.sessionId` - Session ID from Discord
|
|
68
|
-
|
|
69
|
-
#### Events
|
|
70
|
-
|
|
71
|
-
- `ready` - Fired when client is ready
|
|
72
|
-
- `messageCreate` - Fired when a message is created
|
|
73
|
-
|
|
74
|
-
### User
|
|
75
|
-
|
|
76
|
-
#### Methods
|
|
77
|
-
|
|
78
|
-
- `user.setStatus(status)` - Set user status ('online', 'idle', 'dnd', 'invisible')
|
|
79
|
-
- `user.setPresence(presence)` - Set full presence data
|
|
80
|
-
- `user.setActivity(activity)` - Set user activity
|
|
81
|
-
|
|
82
|
-
#### Properties
|
|
83
|
-
|
|
84
|
-
- `user.id` - User ID
|
|
85
|
-
- `user.username` - Username
|
|
86
|
-
- `user.discriminator` - Discriminator (4-digit number)
|
|
87
|
-
- `user.avatar` - Avatar hash
|
|
88
|
-
|
|
89
|
-
### Message
|
|
90
|
-
|
|
91
|
-
#### Methods
|
|
92
|
-
|
|
93
|
-
- `message.reply(content, options)` - Reply to the message
|
|
94
|
-
- `message.react(emoji)` - React to the message
|
|
95
|
-
- `message.clickButton(identifier)` - Click a button on the message
|
|
96
|
-
- `identifier` can be:
|
|
97
|
-
- `null` or omitted: clicks first button
|
|
98
|
-
- `number`: clicks button at index (0-based)
|
|
99
|
-
- `string`: clicks button with custom ID
|
|
100
|
-
|
|
101
|
-
#### Properties
|
|
102
|
-
|
|
103
|
-
- `message.content` - Message content
|
|
104
|
-
- `message.author` - Message author
|
|
105
|
-
- `message.channel` - Message channel
|
|
106
|
-
- `message.guild` - Message guild (null for DMs)
|
|
107
|
-
- `message.components` - Message components (buttons, etc.)
|
|
108
|
-
|
|
109
|
-
### Channel
|
|
110
|
-
|
|
111
|
-
#### Methods
|
|
112
|
-
|
|
113
|
-
- `channel.send(content, options)` - Send a message to the channel
|
|
114
|
-
- `channel.fetchMessages(options)` - Fetch messages from the channel
|
|
115
|
-
|
|
116
|
-
#### Properties
|
|
117
|
-
|
|
118
|
-
- `channel.id` - Channel ID
|
|
119
|
-
- `channel.name` - Channel name
|
|
120
|
-
- `channel.type` - Channel type
|
|
121
|
-
|
|
122
|
-
### Guild
|
|
123
|
-
|
|
124
|
-
#### Methods
|
|
125
|
-
|
|
126
|
-
- `guild.getChannels()` - Get cached channels for this guild
|
|
127
|
-
- `guild.fetchChannels()` - Fetch all channels for this guild from API
|
|
128
|
-
- `guild.getChannel(channelId)` - Get a specific channel from cache
|
|
129
|
-
- `guild.fetchChannel(channelId)` - Fetch a specific channel from API
|
|
130
|
-
|
|
131
|
-
#### Properties
|
|
132
|
-
|
|
133
|
-
- `guild.id` - Guild ID
|
|
134
|
-
- `guild.name` - Guild name
|
|
135
|
-
- `guild.icon` - Guild icon hash
|
|
136
|
-
- `guild.ownerId` - Guild owner ID
|
|
137
|
-
|
|
138
|
-
### WebhookClient
|
|
139
|
-
|
|
140
|
-
Send messages to Discord webhooks with support for embeds and more.
|
|
141
|
-
|
|
142
|
-
```javascript
|
|
143
|
-
const { WebhookClient } = require("discord-self-lite");
|
|
144
|
-
const webhook = new WebhookClient("YOUR_WEBHOOK_URL", {
|
|
145
|
-
username: "My Bot",
|
|
146
|
-
avatarURL: "https://example.com/avatar.png",
|
|
147
|
-
});
|
|
148
|
-
```
|
|
149
|
-
|
|
150
|
-
#### Constructor
|
|
151
|
-
|
|
152
|
-
- `new WebhookClient(url, options)` - Create a webhook client
|
|
153
|
-
- `url` - Discord webhook URL
|
|
154
|
-
- `options.username` - Default username for messages
|
|
155
|
-
- `options.avatarURL` - Default avatar URL for messages
|
|
156
|
-
|
|
157
|
-
#### Methods
|
|
158
|
-
|
|
159
|
-
- `webhook.send(content, options)` - Send a message (supports text, embeds, and objects)
|
|
160
|
-
- `webhook.edit(messageId, content, options)` - Edit a message
|
|
161
|
-
- `webhook.delete(messageId)` - Delete a message
|
|
162
|
-
- `webhook.fetchMessage(messageId)` - Fetch a message
|
|
163
|
-
|
|
164
|
-
#### Static Methods
|
|
50
|
+
- **[`Client`](docs/api/Client.md)** - Main entry point, connection manager, and cache storage.
|
|
51
|
+
- **[`User`](docs/api/User.md) & [`ClientUser`](docs/api/ClientUser.md)** - Represents Discord users and the logged-in selfbot.
|
|
52
|
+
- **[`Message`](docs/api/Message.md)** - Represents text messages, supports replying, reacting, and clicking buttons.
|
|
53
|
+
- **[`Channel`](docs/api/Channel.md)** - Represents Text, DM, or Voice channels to fetch or send messages.
|
|
54
|
+
- **[`Guild`](docs/api/Guild.md) & [`GuildMember`](docs/api/GuildMember.md)** - Represents Discord servers and their members.
|
|
55
|
+
- **[`WebhookClient`](docs/api/WebhookClient.md)** - Standalone client to send requests via webhooks.
|
|
56
|
+
- **[`Permissions`](docs/api/Permissions.md) & [`BitField`](docs/api/BitField.md)** - Utility classes for resolving and checking Discord permissions.
|
|
165
57
|
|
|
166
|
-
|
|
167
|
-
- `WebhookClient.parseURL(url)` - Parse webhook URL to get ID and token
|
|
58
|
+
_Check the [Complete API Reference](docs/api/README.md) for full properties, methods, and examples of each._
|
|
168
59
|
|
|
169
60
|
## Examples
|
|
170
61
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "discord-self-lite",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.11",
|
|
4
4
|
"description": "Lightweight Discord selfbot library",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"discord",
|
|
@@ -32,8 +32,7 @@
|
|
|
32
32
|
"test": "eslint . && prettier --check .",
|
|
33
33
|
"format": "prettier --write .",
|
|
34
34
|
"fix": "eslint . --fix && prettier --write .",
|
|
35
|
-
"docs": "echo \"📚 Documentation available at docs/README.md\""
|
|
36
|
-
"docs:html": "jsdoc -c jsdoc.conf.json"
|
|
35
|
+
"docs": "echo \"📚 Documentation available at docs/README.md\""
|
|
37
36
|
},
|
|
38
37
|
"repository": {
|
|
39
38
|
"type": "git",
|
package/src/classes/Channel.js
CHANGED
package/src/classes/Client.js
CHANGED
|
@@ -49,7 +49,27 @@ class Client extends EventEmitter {
|
|
|
49
49
|
async login(token) {
|
|
50
50
|
this.token = token;
|
|
51
51
|
this.rest = new RestManager(this.token, this.options.apiVersion || 9);
|
|
52
|
-
|
|
52
|
+
|
|
53
|
+
return new Promise((resolve, reject) => {
|
|
54
|
+
const onReady = () => {
|
|
55
|
+
this.removeListener("error", onError);
|
|
56
|
+
resolve();
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
const onError = (msg) => {
|
|
60
|
+
this.removeListener("ready", onReady);
|
|
61
|
+
reject(new Error(msg));
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
this.once("ready", onReady);
|
|
65
|
+
this.once("error", onError);
|
|
66
|
+
|
|
67
|
+
this.connect().catch((err) => {
|
|
68
|
+
this.removeListener("ready", onReady);
|
|
69
|
+
this.removeListener("error", onError);
|
|
70
|
+
reject(err);
|
|
71
|
+
});
|
|
72
|
+
});
|
|
53
73
|
}
|
|
54
74
|
|
|
55
75
|
/**
|
|
@@ -99,39 +119,63 @@ class Client extends EventEmitter {
|
|
|
99
119
|
}
|
|
100
120
|
|
|
101
121
|
/**
|
|
102
|
-
* Get channel from cache
|
|
122
|
+
* Get channel from cache
|
|
103
123
|
* @param {string} id - The channel ID
|
|
104
|
-
* @returns {Channel} The channel instance
|
|
124
|
+
* @returns {Channel|null} The cached channel instance or null
|
|
105
125
|
*/
|
|
106
126
|
getChannel(id) {
|
|
107
|
-
|
|
108
|
-
this.channels.set(id, new Channel(this, this.rest, id));
|
|
109
|
-
}
|
|
110
|
-
return this.channels.get(id);
|
|
127
|
+
return this.channels.get(id) || null;
|
|
111
128
|
}
|
|
112
129
|
|
|
113
130
|
/**
|
|
114
|
-
*
|
|
131
|
+
* Resolve channel from cache or fetch from API
|
|
132
|
+
* @param {string} id - The channel ID
|
|
133
|
+
* @returns {Promise<Channel>} The resolved channel instance
|
|
134
|
+
*/
|
|
135
|
+
async resolveChannel(id) {
|
|
136
|
+
const cached = this.getChannel(id);
|
|
137
|
+
if (cached) return cached;
|
|
138
|
+
return await this.fetchChannel(id);
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* Get guild from cache
|
|
115
143
|
* @param {string} id - The guild ID
|
|
116
|
-
* @returns {Guild} The guild instance
|
|
144
|
+
* @returns {Guild|null} The cached guild instance or null
|
|
117
145
|
*/
|
|
118
146
|
getGuild(id) {
|
|
119
|
-
|
|
120
|
-
this.guilds.set(id, new Guild(this, this.rest, id));
|
|
121
|
-
}
|
|
122
|
-
return this.guilds.get(id);
|
|
147
|
+
return this.guilds.get(id) || null;
|
|
123
148
|
}
|
|
124
149
|
|
|
125
150
|
/**
|
|
126
|
-
*
|
|
151
|
+
* Resolve guild from cache or fetch from API
|
|
152
|
+
* @param {string} id - The guild ID
|
|
153
|
+
* @returns {Promise<Guild>} The resolved guild instance
|
|
154
|
+
*/
|
|
155
|
+
async resolveGuild(id) {
|
|
156
|
+
const cached = this.getGuild(id);
|
|
157
|
+
if (cached) return cached;
|
|
158
|
+
return await this.fetchGuild(id);
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
/**
|
|
162
|
+
* Get user from cache
|
|
127
163
|
* @param {string} id - The user ID
|
|
128
|
-
* @returns {User} The
|
|
164
|
+
* @returns {User|null} The cached user instance or null
|
|
129
165
|
*/
|
|
130
166
|
getUser(id) {
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
167
|
+
return this.users.get(id) || null;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
/**
|
|
171
|
+
* Resolve user from cache or fetch from API
|
|
172
|
+
* @param {string} id - The user ID
|
|
173
|
+
* @returns {Promise<User>} The resolved user instance
|
|
174
|
+
*/
|
|
175
|
+
async resolveUser(id) {
|
|
176
|
+
const cached = this.getUser(id);
|
|
177
|
+
if (cached) return cached;
|
|
178
|
+
return await this.fetchUser(id);
|
|
135
179
|
}
|
|
136
180
|
|
|
137
181
|
/**
|
package/src/classes/Guild.js
CHANGED
|
@@ -44,7 +44,7 @@ class Guild {
|
|
|
44
44
|
/**
|
|
45
45
|
* Get a channel from this guild (from cache)
|
|
46
46
|
* @param {string} channelId - The channel ID
|
|
47
|
-
* @returns {Channel} The channel instance
|
|
47
|
+
* @returns {Channel|null} The cached channel instance or null
|
|
48
48
|
*/
|
|
49
49
|
getChannel(channelId) {
|
|
50
50
|
const channel = this.client.getChannel(channelId);
|
package/src/classes/Message.js
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
const WebSocketError = require("./WebSocketError");
|
|
2
1
|
const User = require("./User");
|
|
3
2
|
|
|
4
3
|
/**
|
|
@@ -38,11 +37,12 @@ class Message {
|
|
|
38
37
|
this.mentions = this.mentions || [];
|
|
39
38
|
this.mentionRoles = this.mentionRoles || [];
|
|
40
39
|
this.reactions = this.reactions || [];
|
|
40
|
+
this.url = `https://discord.com/channels/${this.guildId ? this.guildId : "@me"}/${this.channelId}/${this.id}`;
|
|
41
41
|
}
|
|
42
42
|
|
|
43
43
|
/**
|
|
44
44
|
* Get the channel this message was sent in
|
|
45
|
-
* @returns {Channel} The channel instance
|
|
45
|
+
* @returns {Channel|null} The cached channel instance, or null if not cached
|
|
46
46
|
*/
|
|
47
47
|
get channel() {
|
|
48
48
|
return this.client.getChannel(this.channelId);
|
|
@@ -89,11 +89,12 @@ class Message {
|
|
|
89
89
|
* @returns {Promise<object>} The sent reply message data
|
|
90
90
|
*/
|
|
91
91
|
async reply(payload) {
|
|
92
|
+
const channel = await this.client.resolveChannel(this.channelId);
|
|
92
93
|
const replyPayload =
|
|
93
94
|
typeof payload === "string"
|
|
94
95
|
? { content: payload, message_reference: { message_id: this.id } }
|
|
95
96
|
: { ...payload, message_reference: { message_id: this.id } };
|
|
96
|
-
return await
|
|
97
|
+
return await channel.send(replyPayload);
|
|
97
98
|
}
|
|
98
99
|
|
|
99
100
|
/**
|
|
@@ -159,8 +160,8 @@ class Message {
|
|
|
159
160
|
const messageFlags = this.data.flags || 0;
|
|
160
161
|
|
|
161
162
|
if (!this.client.sessionId) {
|
|
162
|
-
throw new
|
|
163
|
-
"No session ID available - client not properly connected",
|
|
163
|
+
throw new Error(
|
|
164
|
+
"No session ID available - client not properly connected (yet).",
|
|
164
165
|
);
|
|
165
166
|
}
|
|
166
167
|
|
|
@@ -196,21 +197,18 @@ class Message {
|
|
|
196
197
|
* Returns the referenced `Message` instance or `null` if not available.
|
|
197
198
|
*/
|
|
198
199
|
async fetchReference() {
|
|
199
|
-
const ref = this.
|
|
200
|
+
const ref = this.data?.message_reference;
|
|
200
201
|
if (!ref) return null;
|
|
201
202
|
|
|
202
203
|
const messageId = ref.messageId || ref.message_id;
|
|
203
204
|
const channelId = ref.channelId || ref.channel_id || this.channelId;
|
|
204
205
|
if (!messageId || !channelId) return null;
|
|
205
206
|
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
} catch {
|
|
212
|
-
return null;
|
|
213
|
-
}
|
|
207
|
+
let channel;
|
|
208
|
+
try {
|
|
209
|
+
channel = await this.client.resolveChannel(channelId);
|
|
210
|
+
} catch {
|
|
211
|
+
return null;
|
|
214
212
|
}
|
|
215
213
|
|
|
216
214
|
try {
|
|
@@ -74,7 +74,7 @@ class RestManager {
|
|
|
74
74
|
});
|
|
75
75
|
|
|
76
76
|
console.log(
|
|
77
|
-
`⏸️
|
|
77
|
+
`⏸️ Suspending route ${routeKey} for 2 minutes (pre-emptive)`,
|
|
78
78
|
);
|
|
79
79
|
|
|
80
80
|
// Clear queued requests for this route
|
|
@@ -192,7 +192,7 @@ class RestManager {
|
|
|
192
192
|
});
|
|
193
193
|
|
|
194
194
|
console.log(
|
|
195
|
-
`⏸️
|
|
195
|
+
`⏸️ Suspending route ${routeKey} for 2 minutes (queue processing)`,
|
|
196
196
|
);
|
|
197
197
|
|
|
198
198
|
// Clear remaining queued requests for this route
|
|
@@ -267,15 +267,14 @@ class RestManager {
|
|
|
267
267
|
`⏳ Global rate limit set, waiting ${retryAfter + 2000}ms`,
|
|
268
268
|
);
|
|
269
269
|
} else {
|
|
270
|
-
|
|
271
|
-
const suspensionTime = 2 * 60 * 1000;
|
|
270
|
+
const suspensionTime = retryAfter + 500;
|
|
272
271
|
this.suspendedRoutes.set(routeKey, {
|
|
273
272
|
suspendedUntil: Date.now() + suspensionTime,
|
|
274
273
|
reason: `429 response on attempt ${attempt + 1}`,
|
|
275
274
|
});
|
|
276
275
|
|
|
277
276
|
console.log(
|
|
278
|
-
`⏸️
|
|
277
|
+
`⏸️ Suspending route ${routeKey} for ${suspensionTime}ms (429 response)`,
|
|
279
278
|
);
|
|
280
279
|
|
|
281
280
|
// Clear queue for this route
|
|
@@ -353,6 +352,15 @@ class RestManager {
|
|
|
353
352
|
|
|
354
353
|
return await response.json();
|
|
355
354
|
} catch (error) {
|
|
355
|
+
// Do not retry on Missing Permissions (50013)
|
|
356
|
+
if (
|
|
357
|
+
error.name === "DiscordAPIError" &&
|
|
358
|
+
error.fullError &&
|
|
359
|
+
error.fullError.code === 50013
|
|
360
|
+
) {
|
|
361
|
+
throw error;
|
|
362
|
+
}
|
|
363
|
+
|
|
356
364
|
if (attempt === maxRetries - 1) {
|
|
357
365
|
throw error;
|
|
358
366
|
}
|
|
@@ -4,8 +4,6 @@ const Message = require("../../classes/Message");
|
|
|
4
4
|
const Guild = require("../../classes/Guild");
|
|
5
5
|
const Channel = require("../../classes/Channel");
|
|
6
6
|
const ClientUser = require("../../classes/ClientUser");
|
|
7
|
-
const WebSocketError = require("../../classes/WebSocketError");
|
|
8
|
-
|
|
9
7
|
class DiscordWebSocket extends EventEmitter {
|
|
10
8
|
constructor(client, token, options = {}) {
|
|
11
9
|
super();
|
|
@@ -31,7 +29,7 @@ class DiscordWebSocket extends EventEmitter {
|
|
|
31
29
|
this.ws = new WebSocket(this.gatewayUrl);
|
|
32
30
|
|
|
33
31
|
this.ws.on("open", () => {
|
|
34
|
-
|
|
32
|
+
this.client.emit("debug", "WebSocket connected");
|
|
35
33
|
this.client.emit("connected");
|
|
36
34
|
});
|
|
37
35
|
|
|
@@ -40,23 +38,47 @@ class DiscordWebSocket extends EventEmitter {
|
|
|
40
38
|
});
|
|
41
39
|
|
|
42
40
|
this.ws.on("close", (code, reason) => {
|
|
43
|
-
|
|
41
|
+
this.client.emit("debug", `WebSocket closed: ${code} - ${reason}`);
|
|
44
42
|
this.ready = false;
|
|
45
43
|
if (this.heartbeatInterval) {
|
|
46
44
|
clearInterval(this.heartbeatInterval);
|
|
47
45
|
this.heartbeatInterval = null;
|
|
48
46
|
}
|
|
49
47
|
this.client.emit("disconnected", code, reason);
|
|
48
|
+
const terminalCodes = [4004, 4010, 4011, 4012, 4013, 4014];
|
|
49
|
+
|
|
50
|
+
if (terminalCodes.includes(code)) {
|
|
51
|
+
if (code === 4004) {
|
|
52
|
+
try {
|
|
53
|
+
if (this.ws) this.ws.terminate();
|
|
54
|
+
} catch {
|
|
55
|
+
/* ignore */
|
|
56
|
+
}
|
|
57
|
+
this.ws = null;
|
|
58
|
+
this.client.emit(
|
|
59
|
+
"error",
|
|
60
|
+
`Authentication failed (close code ${code}). Please check your token and try again.`,
|
|
61
|
+
);
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
this.client.emit(
|
|
66
|
+
"debug",
|
|
67
|
+
`Terminal error received (${code}). Connection will not be restarted. (Reason: ${reason})`,
|
|
68
|
+
);
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
|
|
50
72
|
if (code !== 1000) {
|
|
51
|
-
// Not a clean close
|
|
52
73
|
this.reconnect();
|
|
53
74
|
}
|
|
54
75
|
});
|
|
55
76
|
|
|
56
77
|
this.ws.on("error", (error) => {
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
78
|
+
this.client.emit(
|
|
79
|
+
"error",
|
|
80
|
+
`WebSocket error: ${error && error.message ? error.message : String(error)}`,
|
|
81
|
+
);
|
|
60
82
|
});
|
|
61
83
|
}
|
|
62
84
|
|
|
@@ -87,7 +109,7 @@ class DiscordWebSocket extends EventEmitter {
|
|
|
87
109
|
this.handleDispatch(message);
|
|
88
110
|
break;
|
|
89
111
|
default:
|
|
90
|
-
|
|
112
|
+
this.client.emit("debug", `Unhandled op: ${message.op}`);
|
|
91
113
|
}
|
|
92
114
|
}
|
|
93
115
|
|
|
@@ -185,9 +207,9 @@ class DiscordWebSocket extends EventEmitter {
|
|
|
185
207
|
const member = new GuildMember(this.client, memberData, guild);
|
|
186
208
|
guild._members.set(this.client.user.id, member);
|
|
187
209
|
} catch (err) {
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
err.message
|
|
210
|
+
this.client.emit(
|
|
211
|
+
"debug",
|
|
212
|
+
`Failed to fetch member for guild ${guild.id}: ${err && err.message ? err.message : String(err)}`,
|
|
191
213
|
);
|
|
192
214
|
}
|
|
193
215
|
}
|
|
@@ -197,16 +219,14 @@ class DiscordWebSocket extends EventEmitter {
|
|
|
197
219
|
|
|
198
220
|
reconnect() {
|
|
199
221
|
if (this.reconnectAttempts >= this.maxReconnectAttempts) {
|
|
200
|
-
|
|
201
|
-
console.error(err);
|
|
202
|
-
this.client.emit("error", err);
|
|
222
|
+
this.client.emit("error", "Max reconnect attempts reached");
|
|
203
223
|
this.client.emit("maxReconnects");
|
|
204
224
|
return;
|
|
205
225
|
}
|
|
206
226
|
|
|
207
227
|
this.reconnectAttempts++;
|
|
208
228
|
const delay = Math.min(1000 * Math.pow(2, this.reconnectAttempts), 30000); // Exponential backoff
|
|
209
|
-
|
|
229
|
+
this.client.emit("debug", `Reconnecting in ${delay}ms...`);
|
|
210
230
|
setTimeout(() => {
|
|
211
231
|
this.connect();
|
|
212
232
|
}, delay);
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Represents an error related to the WebSocket connection
|
|
3
|
-
* @extends Error
|
|
4
|
-
*/
|
|
5
|
-
class WebSocketError extends Error {
|
|
6
|
-
/**
|
|
7
|
-
* Create a new WebSocketError
|
|
8
|
-
* @param {string} message - The error message
|
|
9
|
-
* @param {number} [code] - The WebSocket close code
|
|
10
|
-
*/
|
|
11
|
-
constructor(message, code) {
|
|
12
|
-
super(message);
|
|
13
|
-
this.name = "WebSocketError";
|
|
14
|
-
this.code = code;
|
|
15
|
-
}
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
module.exports = WebSocketError;
|