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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "discord-self-lite",
3
- "version": "0.1.10",
3
+ "version": "0.1.11",
4
4
  "description": "Lightweight Discord selfbot library",
5
5
  "keywords": [
6
6
  "discord",
@@ -55,6 +55,7 @@ class Channel {
55
55
  */
56
56
  async send(payload) {
57
57
  const data = await this.rest.sendMessage(this.id, payload);
58
+ if (!data) return null;
58
59
  return new Message(this.client, data);
59
60
  }
60
61
 
@@ -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
- await this.connect();
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
  /**
@@ -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 WebSocketError(
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.messageReference || this.data?.message_reference;
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
- `⏸️ Suspending route ${routeKey} for 2 minutes (pre-emptive)`,
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
- `⏸️ Suspending route ${routeKey} for 2 minutes (queue processing)`,
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
- // Immediately suspend the route for 2 minutes on first 429
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
- `⏸️ Suspending route ${routeKey} for 2 minutes (429 response)`,
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
- console.log("WebSocket connected");
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
- console.log(`WebSocket closed: ${code} - ${reason}`);
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
- const wsError = new WebSocketError(`WebSocket error: ${error.message}`);
58
- console.error(wsError);
59
- this.client.emit("error", wsError);
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
- console.log("Unhandled op:", message.op);
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
- console.warn(
189
- `Failed to fetch member for guild ${guild.id}:`,
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
- const err = new WebSocketError("Max reconnect attempts reached");
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
- console.log(`Reconnecting in ${delay}ms...`);
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;