discord-self-lite 0.1.10 → 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/package.json
CHANGED
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
|
/**
|
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,6 +37,7 @@ 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
|
/**
|
|
@@ -160,8 +160,8 @@ class Message {
|
|
|
160
160
|
const messageFlags = this.data.flags || 0;
|
|
161
161
|
|
|
162
162
|
if (!this.client.sessionId) {
|
|
163
|
-
throw new
|
|
164
|
-
"No session ID available - client not properly connected",
|
|
163
|
+
throw new Error(
|
|
164
|
+
"No session ID available - client not properly connected (yet).",
|
|
165
165
|
);
|
|
166
166
|
}
|
|
167
167
|
|
|
@@ -197,7 +197,7 @@ class Message {
|
|
|
197
197
|
* Returns the referenced `Message` instance or `null` if not available.
|
|
198
198
|
*/
|
|
199
199
|
async fetchReference() {
|
|
200
|
-
const ref = this.
|
|
200
|
+
const ref = this.data?.message_reference;
|
|
201
201
|
if (!ref) return null;
|
|
202
202
|
|
|
203
203
|
const messageId = ref.messageId || ref.message_id;
|
|
@@ -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;
|