beniocord.js 2.0.4 → 2.0.6
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/Client.js +155 -9
- package/helpers/index.js +8 -0
- package/package.json +1 -1
- package/structures/Channel.js +2 -1
- package/structures/Emoji.js +3 -1
- package/structures/Message.js +2 -1
- package/structures/User.js +3 -1
- package/structures/Util.js +1 -3
package/Client.js
CHANGED
|
@@ -83,6 +83,13 @@ class Client extends EventEmitter {
|
|
|
83
83
|
response => response,
|
|
84
84
|
error => this._handleAxiosError(error)
|
|
85
85
|
);
|
|
86
|
+
|
|
87
|
+
setInterval(() => {
|
|
88
|
+
if (this._sentMessages.size > 1000) {
|
|
89
|
+
this._sentMessages.clear();
|
|
90
|
+
}
|
|
91
|
+
}, 30 * 60 * 1000);
|
|
92
|
+
|
|
86
93
|
}
|
|
87
94
|
|
|
88
95
|
_handleAxiosError(error) {
|
|
@@ -194,11 +201,13 @@ class Client extends EventEmitter {
|
|
|
194
201
|
this.isConnected = true;
|
|
195
202
|
this.retryCount = 0;
|
|
196
203
|
this._setupSocketHandlers();
|
|
204
|
+
this._startHeartbeat();
|
|
197
205
|
resolve();
|
|
198
206
|
});
|
|
199
207
|
|
|
200
208
|
this.socket.on("disconnect", (reason) => {
|
|
201
209
|
this.isConnected = false;
|
|
210
|
+
this._stopHeartbeat(); // Para o heartbeat
|
|
202
211
|
this.emit("disconnect", reason);
|
|
203
212
|
|
|
204
213
|
if (reason === "io server disconnect") {
|
|
@@ -239,6 +248,7 @@ class Client extends EventEmitter {
|
|
|
239
248
|
|
|
240
249
|
this.socket.on("reconnect", (attemptNumber) => {
|
|
241
250
|
this.isConnected = true;
|
|
251
|
+
this._startHeartbeat();
|
|
242
252
|
this.emit("reconnect", attemptNumber);
|
|
243
253
|
});
|
|
244
254
|
|
|
@@ -247,6 +257,7 @@ class Client extends EventEmitter {
|
|
|
247
257
|
});
|
|
248
258
|
|
|
249
259
|
this.socket.on("reconnect_failed", () => {
|
|
260
|
+
this._stopHeartbeat();
|
|
250
261
|
this.emit("error", new ClientError(
|
|
251
262
|
"Failed to reconnect after maximum attempts",
|
|
252
263
|
"RECONNECT_FAILED"
|
|
@@ -255,8 +266,87 @@ class Client extends EventEmitter {
|
|
|
255
266
|
});
|
|
256
267
|
}
|
|
257
268
|
|
|
269
|
+
/**
|
|
270
|
+
* Inicia o sistema de heartbeat
|
|
271
|
+
* @private
|
|
272
|
+
*/
|
|
273
|
+
_startHeartbeat() {
|
|
274
|
+
// Para qualquer heartbeat existente
|
|
275
|
+
this._stopHeartbeat();
|
|
276
|
+
|
|
277
|
+
// Intervalo de 30 segundos (mesmo do frontend)
|
|
278
|
+
const HEARTBEAT_INTERVAL = 30000;
|
|
279
|
+
|
|
280
|
+
this.heartbeatInterval = setInterval(() => {
|
|
281
|
+
if (this.socket && this.isConnected) {
|
|
282
|
+
// Envia heartbeat simples para bots
|
|
283
|
+
// Bots não precisam de isPageVisible/isAppFocused
|
|
284
|
+
this.socket.emit("presence:heartbeat", {
|
|
285
|
+
status: this.status || "online",
|
|
286
|
+
clientType: "bot" // Identifica como bot
|
|
287
|
+
});
|
|
288
|
+
}
|
|
289
|
+
}, HEARTBEAT_INTERVAL);
|
|
290
|
+
|
|
291
|
+
// Envia primeiro heartbeat imediatamente
|
|
292
|
+
if (this.socket && this.isConnected) {
|
|
293
|
+
this.socket.emit("presence:heartbeat", {
|
|
294
|
+
status: this.status || "online",
|
|
295
|
+
clientType: "bot"
|
|
296
|
+
});
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
/**
|
|
301
|
+
* Para o sistema de heartbeat
|
|
302
|
+
* @private
|
|
303
|
+
*/
|
|
304
|
+
_stopHeartbeat() {
|
|
305
|
+
if (this.heartbeatInterval) {
|
|
306
|
+
clearInterval(this.heartbeatInterval);
|
|
307
|
+
this.heartbeatInterval = null;
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
/**
|
|
312
|
+
* Desconecta o cliente e limpa recursos
|
|
313
|
+
*/
|
|
314
|
+
disconnect() {
|
|
315
|
+
this._stopHeartbeat();
|
|
316
|
+
|
|
317
|
+
if (this.socket) {
|
|
318
|
+
// Notifica o servidor antes de desconectar
|
|
319
|
+
if (this.isConnected) {
|
|
320
|
+
this.socket.emit("presence:update", {
|
|
321
|
+
isPageVisible: false,
|
|
322
|
+
isAppFocused: false,
|
|
323
|
+
status: "offline",
|
|
324
|
+
clientType: "bot"
|
|
325
|
+
});
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
this._removeSocketHandlers();
|
|
329
|
+
|
|
330
|
+
this.socket.off("connect");
|
|
331
|
+
this.socket.off("disconnect");
|
|
332
|
+
this.socket.off("connect_error");
|
|
333
|
+
this.socket.off("reconnect");
|
|
334
|
+
this.socket.off("reconnect_error");
|
|
335
|
+
this.socket.off("reconnect_failed");
|
|
336
|
+
|
|
337
|
+
this.socket.disconnect();
|
|
338
|
+
this.socket = null;
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
this.isConnected = false;
|
|
342
|
+
this.isReady = false;
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
|
|
258
346
|
_setupSocketHandlers() {
|
|
259
|
-
this.
|
|
347
|
+
this._removeSocketHandlers();
|
|
348
|
+
|
|
349
|
+
this.socket.on('message:new', async (data) => {
|
|
260
350
|
try {
|
|
261
351
|
if (this._sentMessages.has(data.id)) {
|
|
262
352
|
this._sentMessages.delete(data.id);
|
|
@@ -312,6 +402,26 @@ class Client extends EventEmitter {
|
|
|
312
402
|
data.member = member;
|
|
313
403
|
data.channel = channel;
|
|
314
404
|
|
|
405
|
+
// 🔥 Se EU fui adicionado ao canal
|
|
406
|
+
if (data.memberId === this.user?.id) {
|
|
407
|
+
// Adiciona o canal na cache se não existir
|
|
408
|
+
if (channel && !this.cache.channels.has(data.channelId)) {
|
|
409
|
+
this.cache.channels.set(data.channelId, channel);
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
// Entra na room do canal no socket
|
|
413
|
+
this.socket.emit('channel:join', { channelId: data.channelId });
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
// 🔥 Se o canal já existe na cache, adiciona o membro nele
|
|
417
|
+
if (channel && member) {
|
|
418
|
+
// Assumindo que o Channel tem uma lista/Map de membros
|
|
419
|
+
if (!channel.members) {
|
|
420
|
+
channel.members = new Map();
|
|
421
|
+
}
|
|
422
|
+
channel.members.set(member.id, member);
|
|
423
|
+
}
|
|
424
|
+
|
|
315
425
|
this.emit('memberJoin', data);
|
|
316
426
|
console.log('join', data);
|
|
317
427
|
});
|
|
@@ -327,6 +437,20 @@ class Client extends EventEmitter {
|
|
|
327
437
|
data.member = member;
|
|
328
438
|
data.channel = channel;
|
|
329
439
|
|
|
440
|
+
// 🔥 Se EU fui removido do canal
|
|
441
|
+
if (data.memberId === this.user?.id) {
|
|
442
|
+
// Remove o canal da cache
|
|
443
|
+
this.cache.channels.delete(data.channelId);
|
|
444
|
+
|
|
445
|
+
// Sai da room do canal no socket
|
|
446
|
+
this.socket.emit('channel:leave', { channelId: data.channelId });
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
// 🔥 Se o canal existe na cache, remove o membro dele
|
|
450
|
+
if (channel && member && channel.members) {
|
|
451
|
+
channel.members.delete(member.id);
|
|
452
|
+
}
|
|
453
|
+
|
|
330
454
|
this.emit('memberLeave', data);
|
|
331
455
|
console.log('leave', data);
|
|
332
456
|
});
|
|
@@ -346,6 +470,24 @@ class Client extends EventEmitter {
|
|
|
346
470
|
});
|
|
347
471
|
}
|
|
348
472
|
|
|
473
|
+
_removeSocketHandlers() {
|
|
474
|
+
if (!this.socket) return;
|
|
475
|
+
|
|
476
|
+
// Remove todos os listeners customizados
|
|
477
|
+
this.socket.off("message:new");
|
|
478
|
+
this.socket.off("message:deleted");
|
|
479
|
+
this.socket.off("message:edited");
|
|
480
|
+
this.socket.off("typing:user-start");
|
|
481
|
+
this.socket.off("typing:user-stop");
|
|
482
|
+
this.socket.off("user:status-update");
|
|
483
|
+
this.socket.off("presence:update");
|
|
484
|
+
this.socket.off("member:join");
|
|
485
|
+
this.socket.off("member:leave");
|
|
486
|
+
this.socket.off("channel:update");
|
|
487
|
+
this.socket.off("channel:delete");
|
|
488
|
+
this.socket.off("rate:limited");
|
|
489
|
+
}
|
|
490
|
+
|
|
349
491
|
async _processSocketMessage(data) {
|
|
350
492
|
const msg = new Message(data, this);
|
|
351
493
|
|
|
@@ -447,7 +589,8 @@ class Client extends EventEmitter {
|
|
|
447
589
|
}
|
|
448
590
|
|
|
449
591
|
/**
|
|
450
|
-
*
|
|
592
|
+
* Set the user status
|
|
593
|
+
* @param {string} status - Status: "online", "away", "dnd", "offline"
|
|
451
594
|
*/
|
|
452
595
|
async setStatus(status) {
|
|
453
596
|
const validStatuses = ["online", "offline", "away", "dnd"];
|
|
@@ -463,13 +606,7 @@ class Client extends EventEmitter {
|
|
|
463
606
|
this.socket.emit('status:update', { status });
|
|
464
607
|
}
|
|
465
608
|
|
|
466
|
-
|
|
467
|
-
* Envia uma mensagem para um canal
|
|
468
|
-
* @param {string} channelId - ID do canal
|
|
469
|
-
* @param {string|MessageEmbed} content - Conteúdo da mensagem ou MessageEmbed
|
|
470
|
-
* @param {Object|MessageAttachment} opts - Opções adicionais
|
|
471
|
-
* @returns {Promise<Message>}
|
|
472
|
-
*/
|
|
609
|
+
|
|
473
610
|
// async sendMessage(channelId, content, opts = {}) {
|
|
474
611
|
// return new Promise(async (resolve, reject) => {
|
|
475
612
|
// try {
|
|
@@ -542,6 +679,15 @@ class Client extends EventEmitter {
|
|
|
542
679
|
// }
|
|
543
680
|
// });
|
|
544
681
|
// }
|
|
682
|
+
|
|
683
|
+
|
|
684
|
+
/**
|
|
685
|
+
* Send a message
|
|
686
|
+
* @param {string} channelId - Channel ID
|
|
687
|
+
* @param {string|MessageEmbed} content - Message content or MessageEmbed
|
|
688
|
+
* @param {Object|MessageAttachment} opts - Extra options
|
|
689
|
+
* @returns {Promise<Message>}
|
|
690
|
+
*/
|
|
545
691
|
async sendMessage(channelId, content, opts = {}) {
|
|
546
692
|
return new Promise(async (resolve, reject) => {
|
|
547
693
|
try {
|
package/helpers/index.js
ADDED
package/package.json
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
"socket.io-client": "^4.8.1"
|
|
5
5
|
},
|
|
6
6
|
"name": "beniocord.js",
|
|
7
|
-
"version": "2.0.
|
|
7
|
+
"version": "2.0.6",
|
|
8
8
|
"description": "Uma biblioteca leve e intuitiva para integração com APIs de bots em plataformas de mensagens, como Discord. Facilita o envio de mensagens, gerenciamento de canais e interação com usuários, proporcionando uma experiência de desenvolvimento ágil e eficiente.",
|
|
9
9
|
"main": "Client.js",
|
|
10
10
|
"devDependencies": {},
|
package/structures/Channel.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
const { formatUrl } = require('../helpers');
|
|
1
2
|
const MessageCollector = require('./MessageCollector');
|
|
2
3
|
|
|
3
4
|
let client;
|
|
@@ -11,7 +12,7 @@ class Channel {
|
|
|
11
12
|
this.type = data.type || "text";
|
|
12
13
|
this.isPrivate = data.is_private;
|
|
13
14
|
this.isDm = data.is_dm;
|
|
14
|
-
this.iconUrl = data.icon_url
|
|
15
|
+
this.iconUrl = formatUrl(data.icon_url);
|
|
15
16
|
this.createdBy = data.created_by;
|
|
16
17
|
this.createdAt = data.created_at;
|
|
17
18
|
this.updatedAt = data.updated_at;
|
package/structures/Emoji.js
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
|
+
const { formatUrl } = require("../helpers");
|
|
2
|
+
|
|
1
3
|
class Emoji {
|
|
2
4
|
constructor(data) {
|
|
3
5
|
this.id = data.id;
|
|
4
6
|
this.userId = data.user_id;
|
|
5
7
|
this.name = data.name;
|
|
6
|
-
this.url = data.url
|
|
8
|
+
this.url = formatUrl(data.url);
|
|
7
9
|
this.createdAt = data.created_at;
|
|
8
10
|
this.updatedAt = data.updated_at;
|
|
9
11
|
}
|
package/structures/Message.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
const User = require("./User");
|
|
2
2
|
const Channel = require("./Channel");
|
|
3
|
+
const { formatUrl } = require('../helpers/index');
|
|
3
4
|
|
|
4
5
|
let client;
|
|
5
6
|
class Message {
|
|
@@ -7,7 +8,7 @@ class Message {
|
|
|
7
8
|
this.id = data.id;
|
|
8
9
|
this.content = data.content;
|
|
9
10
|
this.messageType = data.message_type || "text";
|
|
10
|
-
this.fileUrl = data.file_url
|
|
11
|
+
this.fileUrl = formatUrl(data.file_url);
|
|
11
12
|
this.fileName = data.file_name;
|
|
12
13
|
this.fileSize = data.file_size;
|
|
13
14
|
this.replyTo = data.reply_to;
|
package/structures/User.js
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
|
+
const { formatUrl } = require("../helpers");
|
|
2
|
+
|
|
1
3
|
class User {
|
|
2
4
|
constructor(data, client) {
|
|
3
5
|
this.id = data.id;
|
|
4
6
|
this.username = data.username;
|
|
5
7
|
this.displayName = data.display_name;
|
|
6
|
-
this.avatarUrl = data.avatar_url
|
|
8
|
+
this.avatarUrl = formatUrl(data.avatar_url);
|
|
7
9
|
this.status = data.status || "offline";
|
|
8
10
|
this.emblems = data.emblems || [];
|
|
9
11
|
this.lastSeen = data.last_seen;
|
package/structures/Util.js
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* MessageEmbed - Criar embeds
|
|
3
|
-
* Mesmas validações do backend para evitar rejeições
|
|
2
|
+
* MessageEmbed - Criar embeds
|
|
4
3
|
* @class
|
|
5
4
|
*/
|
|
6
5
|
class MessageEmbed {
|
|
@@ -483,7 +482,6 @@ class MessageEmbed {
|
|
|
483
482
|
}
|
|
484
483
|
}
|
|
485
484
|
|
|
486
|
-
// Cores predefinidas para facilitar o uso
|
|
487
485
|
MessageEmbed.Colors = {
|
|
488
486
|
DEFAULT: '#5865F2',
|
|
489
487
|
BLUE: '#3498DB',
|