discord-self-lite 0.1.11 → 0.1.13

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.11",
3
+ "version": "0.1.13",
4
4
  "description": "Lightweight Discord selfbot library",
5
5
  "keywords": [
6
6
  "discord",
@@ -135,7 +135,7 @@ class Channel {
135
135
  * @returns {Guild|null} The guild instance or null if not a guild channel
136
136
  */
137
137
  getGuild() {
138
- const guildId = this.data.guild_id;
138
+ const guildId = this.guildId;
139
139
  if (!guildId) return null;
140
140
  return this.client.getGuild(guildId);
141
141
  }
@@ -145,7 +145,7 @@ class Channel {
145
145
  * @returns {Promise<Guild|null>} The guild instance or null if not a guild channel
146
146
  */
147
147
  async fetchGuild() {
148
- const guildId = this.data.guild_id;
148
+ const guildId = this.guildId;
149
149
  if (!guildId) return null;
150
150
  return await this.client.fetchGuild(guildId);
151
151
  }
@@ -214,7 +214,7 @@ class Channel {
214
214
  if (this.isDM() || this.isGroupDM()) {
215
215
  return `https://discord.com/channels/@me/${this.id}`;
216
216
  }
217
- const guildId = this.data.guild_id;
217
+ const guildId = this.guildId;
218
218
  return `https://discord.com/channels/${guildId}/${this.id}`;
219
219
  }
220
220
 
@@ -235,8 +235,8 @@ class Channel {
235
235
  }
236
236
 
237
237
  // Apply channel permission overwrites
238
- if (this.data.permission_overwrites) {
239
- const overwrites = this.data.permission_overwrites;
238
+ if (this.permissionOverwrites) {
239
+ const overwrites = this.permissionOverwrites;
240
240
 
241
241
  // Role overwrites (deny takes precedence over allow)
242
242
  const memberRoles = member.roles || [];
@@ -245,7 +245,7 @@ class Channel {
245
245
  // Role overwrite
246
246
  if (
247
247
  memberRoles.includes(overwrite.id) ||
248
- overwrite.id === this.data.guild_id
248
+ overwrite.id === this.guildId
249
249
  ) {
250
250
  permissions &= ~toBigInt(overwrite.deny || 0);
251
251
  permissions |= toBigInt(overwrite.allow || 0);
@@ -105,10 +105,10 @@ class Guild {
105
105
  * @returns {string|null} The icon URL or null if no icon
106
106
  */
107
107
  getIconURL(options = {}) {
108
- if (!this.data.icon) return null;
108
+ if (!this.icon) return null;
109
109
  const size = options.size || 512;
110
110
  const format = options.format || "png";
111
- return `https://cdn.discordapp.com/icons/${this.id}/${this.data.icon}.${format}?size=${size}`;
111
+ return `https://cdn.discordapp.com/icons/${this.id}/${this.icon}.${format}?size=${size}`;
112
112
  }
113
113
 
114
114
  /**
@@ -119,10 +119,10 @@ class Guild {
119
119
  * @returns {string|null} The banner URL or null if no banner
120
120
  */
121
121
  getBannerURL(options = {}) {
122
- if (!this.data.banner) return null;
122
+ if (!this.banner) return null;
123
123
  const size = options.size || 512;
124
124
  const format = options.format || "png";
125
- return `https://cdn.discordapp.com/banners/${this.id}/${this.data.banner}.${format}?size=${size}`;
125
+ return `https://cdn.discordapp.com/banners/${this.id}/${this.banner}.${format}?size=${size}`;
126
126
  }
127
127
 
128
128
  /**
@@ -1,5 +1,21 @@
1
1
  const User = require("./User");
2
2
 
3
+ function camelCaseKeys(obj) {
4
+ if (Array.isArray(obj)) {
5
+ return obj.map((item) => camelCaseKeys(item));
6
+ } else if (obj !== null && typeof obj === "object") {
7
+ const newObj = {};
8
+ for (const [key, value] of Object.entries(obj)) {
9
+ const camelKey = key.replace(/_([a-z])/g, (_, letter) =>
10
+ letter.toUpperCase(),
11
+ );
12
+ newObj[camelKey] = camelCaseKeys(value);
13
+ }
14
+ return newObj;
15
+ }
16
+ return obj;
17
+ }
18
+
3
19
  /**
4
20
  * Represents a Discord message
5
21
  */
@@ -31,12 +47,14 @@ class Message {
31
47
  }
32
48
  }
33
49
 
34
- this.components = this.components || [];
50
+ this.components = camelCaseKeys(this.components || []);
35
51
  this.attachments = this.attachments || [];
36
- this.embeds = this.embeds || [];
52
+ this.embeds = camelCaseKeys(this.embeds || []);
37
53
  this.mentions = this.mentions || [];
38
54
  this.mentionRoles = this.mentionRoles || [];
39
55
  this.reactions = this.reactions || [];
56
+ this.guildId =
57
+ this.guildId || this.client.getChannel(this.channelId)?.guildId || null;
40
58
  this.url = `https://discord.com/channels/${this.guildId ? this.guildId : "@me"}/${this.channelId}/${this.id}`;
41
59
  }
42
60
 
@@ -65,9 +83,9 @@ class Message {
65
83
  this[camelKey] = value;
66
84
  }
67
85
 
68
- this.components = this.components || [];
86
+ this.components = camelCaseKeys(this.components || []);
69
87
  this.attachments = this.attachments || [];
70
- this.embeds = this.embeds || [];
88
+ this.embeds = camelCaseKeys(this.embeds || []);
71
89
  this.mentions = this.mentions || [];
72
90
  this.mentionRoles = this.mentionRoles || [];
73
91
  this.reactions = this.reactions || [];
@@ -117,11 +135,11 @@ class Message {
117
135
 
118
136
  // Get all buttons from components
119
137
  const buttons = [];
120
- if (this.data.components && Array.isArray(this.data.components)) {
121
- for (const row of this.data.components) {
138
+ if (this.components && Array.isArray(this.components)) {
139
+ for (const row of this.components) {
122
140
  if (row.components && Array.isArray(row.components)) {
123
141
  for (const component of row.components) {
124
- if (component.type === 2 && component.custom_id) {
142
+ if (component.type === 2 && component.customId) {
125
143
  // Type 2 is button
126
144
  buttons.push(component);
127
145
  }
@@ -137,7 +155,7 @@ class Message {
137
155
  // Handle different input types
138
156
  if (input === null) {
139
157
  // No input: click first button
140
- customId = buttons[0].custom_id;
158
+ customId = buttons[0].customId;
141
159
  } else if (typeof input === "number") {
142
160
  // Integer input: click button at that index
143
161
  if (input < 0 || input >= buttons.length) {
@@ -147,17 +165,17 @@ class Message {
147
165
  } button(s) (0-${buttons.length - 1})`,
148
166
  );
149
167
  }
150
- customId = buttons[input].custom_id;
168
+ customId = buttons[input].customId;
151
169
  } else if (typeof input === "string") {
152
- // String input: use as custom_id directly (preserving original behavior)
170
+ // String input: use as customId directly
153
171
  customId = input;
154
172
  } else {
155
173
  throw new Error("Invalid input type. Expected null, number, or string.");
156
174
  }
157
175
 
158
176
  // Get required data for button interaction
159
- const applicationId = this.data.application_id || this.author.id;
160
- const messageFlags = this.data.flags || 0;
177
+ const applicationId = this.applicationId || this.author.id;
178
+ const messageFlags = this.flags || 0;
161
179
 
162
180
  if (!this.client.sessionId) {
163
181
  throw new Error(
@@ -207,13 +225,15 @@ class Message {
207
225
  let channel;
208
226
  try {
209
227
  channel = await this.client.resolveChannel(channelId);
210
- } catch {
228
+ } catch (error) {
229
+ console.error(error);
211
230
  return null;
212
231
  }
213
232
 
214
233
  try {
215
234
  return await channel.fetchMessage(messageId);
216
- } catch {
235
+ } catch (error) {
236
+ console.error(error);
217
237
  return null;
218
238
  }
219
239
  }
@@ -680,7 +680,19 @@ class RestManager {
680
680
  * @returns {Promise<object>} Message data
681
681
  */
682
682
  async fetchMessage(channelId, messageId) {
683
- return await this.request(`/channels/${channelId}/messages/${messageId}`);
683
+ const messages = await this.request(
684
+ `/channels/${channelId}/messages?limit=1&around=${messageId}`,
685
+ );
686
+ if (Array.isArray(messages)) {
687
+ const message = messages.find((m) => m.id === messageId);
688
+ if (message) return message;
689
+ }
690
+ throw new DiscordAPIError(
691
+ "Unknown Message",
692
+ 404,
693
+ `/channels/${channelId}/messages/${messageId}`,
694
+ { message: "Unknown Message", code: 10008 },
695
+ );
684
696
  }
685
697
 
686
698
  /**
@@ -22,18 +22,79 @@ function resolveColor(color) {
22
22
  class WebhookClient {
23
23
  /**
24
24
  * Create a new WebhookClient
25
- * @param {string} url - The webhook URL
26
- * @param {object} [options={}] - Default options for the webhook
27
- * @param {string} [options.username] - Default username for the webhook
28
- * @param {string} [options.avatarURL] - Default avatar URL for the webhook
25
+ * @param {string|object} urlOrId - The webhook URL, an object containing `id` and `token` (or `url`), or just the webhook ID
26
+ * @param {string|object} [tokenOrOptions={}] - The webhook token (if first arg is ID) or default options
27
+ * @param {object} [options={}] - Default options for the webhook (if first two args are ID and token)
29
28
  */
30
- constructor(url, options = {}) {
31
- this.url = url;
32
- this.options = {
33
- username: options.username || null,
34
- avatarURL: options.avatarURL || null,
35
- ...options,
36
- };
29
+ constructor(urlOrId, tokenOrOptions = {}, options = {}) {
30
+ if (typeof urlOrId === "object" && urlOrId !== null) {
31
+ // constructor({ id, token, url, ...options }, options)
32
+ const data = urlOrId;
33
+ const opts = tokenOrOptions || {};
34
+
35
+ if (data.url) {
36
+ this.url = data.url;
37
+ try {
38
+ const parsed = WebhookClient.parseURL(data.url);
39
+ this.id = parsed.id;
40
+ this.token = parsed.token;
41
+ } catch {
42
+ // Ignore parse errors for custom/mock URLs
43
+ }
44
+ } else if (data.id && data.token) {
45
+ this.id = data.id.toString();
46
+ this.token = data.token;
47
+ this.url = `https://discord.com/api/webhooks/${this.id}/${this.token}`;
48
+ } else {
49
+ throw new Error(
50
+ "WebhookClient requires either a URL or an ID and Token",
51
+ );
52
+ }
53
+
54
+ this.options = {
55
+ username: data.username || opts.username || null,
56
+ avatarURL: data.avatarURL || opts.avatarURL || null,
57
+ ...data,
58
+ ...opts,
59
+ };
60
+
61
+ // Clean up internal keys from options
62
+ delete this.options.id;
63
+ delete this.options.token;
64
+ delete this.options.url;
65
+ } else if (
66
+ typeof urlOrId === "string" &&
67
+ typeof tokenOrOptions === "string"
68
+ ) {
69
+ // constructor(id, token, options)
70
+ this.id = urlOrId;
71
+ this.token = tokenOrOptions;
72
+ this.url = `https://discord.com/api/webhooks/${this.id}/${this.token}`;
73
+ this.options = {
74
+ username: options.username || null,
75
+ avatarURL: options.avatarURL || null,
76
+ ...options,
77
+ };
78
+ } else if (typeof urlOrId === "string") {
79
+ // constructor(url, options)
80
+ this.url = urlOrId;
81
+ try {
82
+ const parsed = WebhookClient.parseURL(urlOrId);
83
+ this.id = parsed.id;
84
+ this.token = parsed.token;
85
+ } catch {
86
+ // Ignore parse errors for custom/mock URLs
87
+ }
88
+ this.options = {
89
+ username: tokenOrOptions.username || null,
90
+ avatarURL: tokenOrOptions.avatarURL || null,
91
+ ...tokenOrOptions,
92
+ };
93
+ } else {
94
+ throw new Error(
95
+ "Invalid parameters provided to WebhookClient constructor",
96
+ );
97
+ }
37
98
  }
38
99
 
39
100
  /**