beniocord.js 2.0.9 → 2.1.0
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 +84 -23
- package/package.json +1 -1
- package/structures/Message.js +52 -2
- package/structures/User.js +21 -8
- package/structures/Util.js +103 -54
package/Client.js
CHANGED
|
@@ -11,29 +11,40 @@ const Channel = require("./structures/Channel");
|
|
|
11
11
|
const Emoji = require("./structures/Emoji");
|
|
12
12
|
const { MessageEmbed, MessageAttachment } = require("./structures/Util");
|
|
13
13
|
|
|
14
|
-
class ClientError extends Error {
|
|
15
|
-
constructor(message, code) {
|
|
16
|
-
super(message);
|
|
17
|
-
this.name = 'ClientError';
|
|
18
|
-
this.code = code;
|
|
19
|
-
}
|
|
20
|
-
}
|
|
21
|
-
|
|
22
14
|
let global = {
|
|
23
15
|
token: "",
|
|
24
16
|
apiUrl: "https://api-bots.beniocord.site"
|
|
25
17
|
};
|
|
26
18
|
|
|
27
|
-
/**
|
|
28
|
-
* @fires Client#ready
|
|
29
|
-
* @fires Client#messageCreate
|
|
30
|
-
* @fires Client#messageDelete
|
|
31
|
-
* @fires Client#messageEdit
|
|
32
|
-
* @fires Client#error
|
|
33
|
-
* @fires Client#disconnect
|
|
34
|
-
* @fires Client#reconnect
|
|
35
|
-
*/
|
|
36
19
|
class Client extends EventEmitter {
|
|
20
|
+
/**
|
|
21
|
+
* @fires Client#ready
|
|
22
|
+
* @fires Client#messageCreate
|
|
23
|
+
* @fires Client#messageDelete
|
|
24
|
+
* @fires Client#messageEdit
|
|
25
|
+
* @fires Client#error
|
|
26
|
+
* @fires Client#disconnect
|
|
27
|
+
* @fires Client#reconnect
|
|
28
|
+
* @fires Client#emojiCreate
|
|
29
|
+
* @fires Client#emojiDelete
|
|
30
|
+
* @fires Client#stickerCreate
|
|
31
|
+
* @fires Client#stickerDelete
|
|
32
|
+
* @fires Client#channelCreate
|
|
33
|
+
* @fires Client#channelDelete
|
|
34
|
+
* @fires Client#channelUpdate
|
|
35
|
+
* @fires Client#channelMemberAdd
|
|
36
|
+
* @fires Client#channelMemberRemove
|
|
37
|
+
* @fires Client#channelMemberUpdate
|
|
38
|
+
* @fires Client#typingStart
|
|
39
|
+
* @fires Client#typingStop
|
|
40
|
+
* @class Client
|
|
41
|
+
* @description Classe principal do BenioCord.js - Gerencia a comunicação com a API e eventos do bot
|
|
42
|
+
* @param {Object} options - Opções de configuração do cliente
|
|
43
|
+
* @param {string} options.token - Token do bot para autenticação
|
|
44
|
+
* @example
|
|
45
|
+
* const { Client } = require('beniocord.js');
|
|
46
|
+
* const client = new Client({ token: 'YOUR_BOT_TOKEN' });
|
|
47
|
+
*/
|
|
37
48
|
constructor({ token }) {
|
|
38
49
|
super();
|
|
39
50
|
|
|
@@ -141,6 +152,10 @@ class Client extends EventEmitter {
|
|
|
141
152
|
await this._joinAllChannelRooms();
|
|
142
153
|
|
|
143
154
|
this.isReady = true;
|
|
155
|
+
|
|
156
|
+
/**
|
|
157
|
+
* @event Client#ready
|
|
158
|
+
*/
|
|
144
159
|
this.emit("ready", this.user);
|
|
145
160
|
|
|
146
161
|
return this.user;
|
|
@@ -216,7 +231,7 @@ class Client extends EventEmitter {
|
|
|
216
231
|
|
|
217
232
|
/**
|
|
218
233
|
* Fetches information about the bot user
|
|
219
|
-
* @param {boolean} force - Force fetch from API instead of cache
|
|
234
|
+
* @param {boolean} [force=false] - Force fetch from API instead of cache
|
|
220
235
|
* @returns {Promise<User>} Bot user object
|
|
221
236
|
*/
|
|
222
237
|
async fetchMe(force = false) {
|
|
@@ -240,7 +255,7 @@ class Client extends EventEmitter {
|
|
|
240
255
|
/**
|
|
241
256
|
* Fetches a user by ID
|
|
242
257
|
* @param {string} id - User ID
|
|
243
|
-
* @param {boolean} force - Force fetch from API instead of cache
|
|
258
|
+
* @param {boolean} [force=false] - Force fetch from API instead of cache
|
|
244
259
|
* @returns {Promise<User>} User object
|
|
245
260
|
*/
|
|
246
261
|
async fetchUser(id, force = false) {
|
|
@@ -286,7 +301,7 @@ class Client extends EventEmitter {
|
|
|
286
301
|
/**
|
|
287
302
|
* Fetches a specific channel by ID
|
|
288
303
|
* @param {string} id - Channel ID
|
|
289
|
-
* @param {boolean} force - Force fetch from API instead of cache
|
|
304
|
+
* @param {boolean} [force=false] - Force fetch from API instead of cache
|
|
290
305
|
* @returns {Promise<Channel>} Channel object
|
|
291
306
|
*/
|
|
292
307
|
async fetchChannel(id, force = false) {
|
|
@@ -708,7 +723,7 @@ class Client extends EventEmitter {
|
|
|
708
723
|
/**
|
|
709
724
|
* Fetches an emoji by ID
|
|
710
725
|
* @param {string} id - Emoji ID
|
|
711
|
-
* @param {boolean} force - Force fetch from API instead of cache
|
|
726
|
+
* @param {boolean} [force=false] - Force fetch from API instead of cache
|
|
712
727
|
* @returns {Promise<Emoji>} Emoji object
|
|
713
728
|
*/
|
|
714
729
|
async fetchEmoji(id, force = false) {
|
|
@@ -760,7 +775,7 @@ class Client extends EventEmitter {
|
|
|
760
775
|
/**
|
|
761
776
|
* Fetches a sticker by ID
|
|
762
777
|
* @param {string} id - Sticker ID
|
|
763
|
-
* @param {boolean} force - Force fetch from API instead of cache
|
|
778
|
+
* @param {boolean} [force=false] - Force fetch from API instead of cache
|
|
764
779
|
* @returns {Promise<Object>} Sticker data
|
|
765
780
|
*/
|
|
766
781
|
async fetchSticker(id, force = false) {
|
|
@@ -968,6 +983,9 @@ class Client extends EventEmitter {
|
|
|
968
983
|
_setupSocketHandlers() {
|
|
969
984
|
this._removeSocketHandlers();
|
|
970
985
|
|
|
986
|
+
/**
|
|
987
|
+
* @event Client#messageCreate
|
|
988
|
+
*/
|
|
971
989
|
this.socket.on('message:new', async (data) => {
|
|
972
990
|
try {
|
|
973
991
|
if (this._sentMessages.has(data.id)) {
|
|
@@ -983,31 +1001,49 @@ class Client extends EventEmitter {
|
|
|
983
1001
|
}
|
|
984
1002
|
});
|
|
985
1003
|
|
|
1004
|
+
/**
|
|
1005
|
+
* @event Client#messageDelete
|
|
1006
|
+
*/
|
|
986
1007
|
this.socket.on('message:deleted', (data) => {
|
|
987
1008
|
const { messageId } = data;
|
|
988
1009
|
this._markMessageDeleted(messageId);
|
|
989
1010
|
this.emit('messageDelete', data);
|
|
990
1011
|
});
|
|
991
1012
|
|
|
1013
|
+
/**
|
|
1014
|
+
* @event Client#messageEdit
|
|
1015
|
+
*/
|
|
992
1016
|
this.socket.on('message:edited', (data) => {
|
|
993
1017
|
const { messageId, content, editedAt } = data;
|
|
994
1018
|
this._updateMessageContent(messageId, content, editedAt);
|
|
995
1019
|
this.emit('messageEdit', data);
|
|
996
1020
|
});
|
|
997
1021
|
|
|
1022
|
+
/**
|
|
1023
|
+
* @event Client#typingStart
|
|
1024
|
+
*/
|
|
998
1025
|
this.socket.on('typing:user-start', (data) => {
|
|
999
1026
|
this.emit('typingStart', data);
|
|
1000
1027
|
});
|
|
1001
1028
|
|
|
1029
|
+
/**
|
|
1030
|
+
* @event Client#typingStop
|
|
1031
|
+
*/
|
|
1002
1032
|
this.socket.on('typing:user-stop', (data) => {
|
|
1003
1033
|
this.emit('typingStop', data);
|
|
1004
1034
|
});
|
|
1005
1035
|
|
|
1036
|
+
/**
|
|
1037
|
+
* @event Client#userStatusUpdate
|
|
1038
|
+
*/
|
|
1006
1039
|
this.socket.on('user:status-update', (data) => {
|
|
1007
1040
|
this._updateUserStatus(data);
|
|
1008
1041
|
this.emit('userStatusUpdate', data);
|
|
1009
1042
|
});
|
|
1010
1043
|
|
|
1044
|
+
/**
|
|
1045
|
+
* @event Client#memberJoin
|
|
1046
|
+
*/
|
|
1011
1047
|
this.socket.on('member:join', async (data) => {
|
|
1012
1048
|
const member = await this.fetchUser(data.memberId).catch(() => null);
|
|
1013
1049
|
const channel = this.cache.channels.get(data.channelId);
|
|
@@ -1017,6 +1053,9 @@ class Client extends EventEmitter {
|
|
|
1017
1053
|
this.emit('memberJoin', { channel, member });
|
|
1018
1054
|
});
|
|
1019
1055
|
|
|
1056
|
+
/**
|
|
1057
|
+
* @event Client#memberLeave
|
|
1058
|
+
*/
|
|
1020
1059
|
this.socket.on('member:leave', async (data) => {
|
|
1021
1060
|
const channel = this.cache.channels.get(data.channelId);
|
|
1022
1061
|
const member = this.cache.users.get(data.memberId);
|
|
@@ -1032,16 +1071,25 @@ class Client extends EventEmitter {
|
|
|
1032
1071
|
this.emit('memberLeave', { channel, member });
|
|
1033
1072
|
});
|
|
1034
1073
|
|
|
1074
|
+
/**
|
|
1075
|
+
* @event Client#channelUpdate
|
|
1076
|
+
*/
|
|
1035
1077
|
this.socket.on('channel:update', (data) => {
|
|
1036
1078
|
this._updateChannel(data);
|
|
1037
1079
|
this.emit('channelUpdate', data);
|
|
1038
1080
|
});
|
|
1039
1081
|
|
|
1082
|
+
/**
|
|
1083
|
+
* @event Client#channelDelete
|
|
1084
|
+
*/
|
|
1040
1085
|
this.socket.on('channel:delete', (data) => {
|
|
1041
1086
|
this.cache.channels.delete(data.channelId);
|
|
1042
1087
|
this.emit('channelDelete', data);
|
|
1043
1088
|
});
|
|
1044
1089
|
|
|
1090
|
+
/**
|
|
1091
|
+
* @event Client#rateLimited
|
|
1092
|
+
*/
|
|
1045
1093
|
this.socket.on('rate:limited', (data) => {
|
|
1046
1094
|
this.emit('rateLimited', data);
|
|
1047
1095
|
});
|
|
@@ -1389,6 +1437,19 @@ class Client extends EventEmitter {
|
|
|
1389
1437
|
}
|
|
1390
1438
|
}
|
|
1391
1439
|
|
|
1440
|
+
class ClientError extends Error {
|
|
1441
|
+
/**
|
|
1442
|
+
* @private
|
|
1443
|
+
* @param {string} message - Error message
|
|
1444
|
+
* @param {string} code - Error code
|
|
1445
|
+
*/
|
|
1446
|
+
constructor(message, code) {
|
|
1447
|
+
super(message);
|
|
1448
|
+
this.name = 'ClientError';
|
|
1449
|
+
this.code = code;
|
|
1450
|
+
}
|
|
1451
|
+
}
|
|
1452
|
+
|
|
1392
1453
|
Client.MessageEmbed = MessageEmbed;
|
|
1393
|
-
Client.ClientError = ClientError;
|
|
1454
|
+
// Client.ClientError = ClientError;
|
|
1394
1455
|
module.exports = Client;
|
package/package.json
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
"socket.io-client": "^4.8.1"
|
|
6
6
|
},
|
|
7
7
|
"name": "beniocord.js",
|
|
8
|
-
"version": "2.0
|
|
8
|
+
"version": "2.1.0",
|
|
9
9
|
"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.",
|
|
10
10
|
"main": "Client.js",
|
|
11
11
|
"scripts": {
|
package/structures/Message.js
CHANGED
|
@@ -3,7 +3,32 @@ const Channel = require("./Channel");
|
|
|
3
3
|
const { formatUrl } = require('../helpers/index');
|
|
4
4
|
|
|
5
5
|
let client;
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Represents a message in a channel.
|
|
9
|
+
*/
|
|
6
10
|
class Message {
|
|
11
|
+
/**
|
|
12
|
+
* Creates a new Message instance.
|
|
13
|
+
* @param {Object} data - Raw message data.
|
|
14
|
+
* @param {string|number} data.id - The unique ID of the message.
|
|
15
|
+
* @param {string} data.content - The content of the message.
|
|
16
|
+
* @param {string} [data.message_type="text"] - The type of the message (text, file, etc.).
|
|
17
|
+
* @param {string} [data.file_url] - URL of the attached file.
|
|
18
|
+
* @param {string} [data.file_name] - Name of the attached file.
|
|
19
|
+
* @param {number} [data.file_size] - Size of the attached file in bytes.
|
|
20
|
+
* @param {Object} [data.user] - Author user data.
|
|
21
|
+
* @param {Object} [data.channel] - Channel data where the message was sent.
|
|
22
|
+
* @param {string|number} [data.reply_to] - ID of the message this is replying to.
|
|
23
|
+
* @param {string|number} [data.sticker_id] - ID of a sticker attached to the message.
|
|
24
|
+
* @param {string|number|Date} [data.edited_at] - Timestamp when the message was edited.
|
|
25
|
+
* @param {string|number|Date} [data.created_at] - Timestamp when the message was created.
|
|
26
|
+
* @param {Object} clientInstance - The client instance to send/edit/delete messages.
|
|
27
|
+
* @example
|
|
28
|
+
* // Creating a message instance
|
|
29
|
+
* const msg = new Message({ id: 1, content: "Hello!" }, client);
|
|
30
|
+
*
|
|
31
|
+
*/
|
|
7
32
|
constructor(data, clientInstance) {
|
|
8
33
|
this.id = data.id;
|
|
9
34
|
this.content = data.content;
|
|
@@ -25,13 +50,21 @@ class Message {
|
|
|
25
50
|
});
|
|
26
51
|
}
|
|
27
52
|
|
|
28
|
-
// this.author = data.user ? new User(data.user, this) : null;
|
|
29
53
|
this.author = data.user ? new User(data.user, clientInstance) : null;
|
|
30
54
|
this.channel = data.channel ? new Channel(data.channel, clientInstance) : null;
|
|
31
|
-
// this.member = { user: this.author }
|
|
32
55
|
client = clientInstance;
|
|
33
56
|
}
|
|
34
57
|
|
|
58
|
+
/**
|
|
59
|
+
* Replies to this message.
|
|
60
|
+
* @param {string} content - Content of the reply.
|
|
61
|
+
* @param {Object} [opts={}] - Additional options for the reply.
|
|
62
|
+
* @returns {Promise<Message>} The sent reply message.
|
|
63
|
+
*
|
|
64
|
+
* @example
|
|
65
|
+
* // Replying to a message
|
|
66
|
+
* await msg.reply("Thanks for your message!");
|
|
67
|
+
*/
|
|
35
68
|
async reply(content, opts = {}) {
|
|
36
69
|
return client.sendMessage(this.channel.id, content, {
|
|
37
70
|
replyTo: this.id,
|
|
@@ -39,10 +72,27 @@ class Message {
|
|
|
39
72
|
});
|
|
40
73
|
}
|
|
41
74
|
|
|
75
|
+
/**
|
|
76
|
+
* Edits this message.
|
|
77
|
+
* @param {string} content - New content for the message.
|
|
78
|
+
* @returns {Promise<Message>} The edited message.
|
|
79
|
+
*
|
|
80
|
+
* @example
|
|
81
|
+
* // Editing a message
|
|
82
|
+
* await msg.edit("Updated content!");
|
|
83
|
+
*/
|
|
42
84
|
async edit(content) {
|
|
43
85
|
return client.editMessage(this.id, content);
|
|
44
86
|
}
|
|
45
87
|
|
|
88
|
+
/**
|
|
89
|
+
* Deletes this message.
|
|
90
|
+
* @returns {Promise<void>}
|
|
91
|
+
*
|
|
92
|
+
* @example
|
|
93
|
+
* // Deleting a message
|
|
94
|
+
* await msg.delete();
|
|
95
|
+
*/
|
|
46
96
|
async delete() {
|
|
47
97
|
return client.deleteMessage(this.id);
|
|
48
98
|
}
|
package/structures/User.js
CHANGED
|
@@ -1,6 +1,21 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Represents a user.
|
|
3
|
+
*/
|
|
3
4
|
class User {
|
|
5
|
+
/**
|
|
6
|
+
* Creates a new User instance.
|
|
7
|
+
* @param {Object} data - Raw user data.
|
|
8
|
+
* @param {string|number} data.id - The unique ID of the user.
|
|
9
|
+
* @param {string} data.username - The username of the user.
|
|
10
|
+
* @param {string} data.display_name - The display name of the user.
|
|
11
|
+
* @param {string} data.avatar_url - The URL of the user's avatar.
|
|
12
|
+
* @param {string} [data.status='offline'] - The user's status.
|
|
13
|
+
* @param {Array<string>} [data.emblems=[]] - Array of user emblems.
|
|
14
|
+
* @param {boolean} data.is_bot - Whether the user is a bot.
|
|
15
|
+
* @param {string|number|Date} data.last_seen - Last seen timestamp.
|
|
16
|
+
* @param {string|number|Date} data.created_at - Account creation timestamp.
|
|
17
|
+
* @param {Object} client - The client instance (optional, internal use).
|
|
18
|
+
*/
|
|
4
19
|
constructor(data, client) {
|
|
5
20
|
this.id = data.id;
|
|
6
21
|
this.username = data.username;
|
|
@@ -11,14 +26,12 @@ class User {
|
|
|
11
26
|
this.isBot = data.is_bot;
|
|
12
27
|
this.lastSeen = data.last_seen;
|
|
13
28
|
this.createdAt = data.created_at;
|
|
14
|
-
// this.email = data.email;
|
|
15
|
-
// this.updatedAt = data.updated_at;
|
|
16
29
|
}
|
|
17
30
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
31
|
+
/**
|
|
32
|
+
* Returns the avatar URL of the user.
|
|
33
|
+
* @returns {string} The avatar URL.
|
|
34
|
+
*/
|
|
22
35
|
avatarURL() {
|
|
23
36
|
return this.avatarUrl;
|
|
24
37
|
}
|
package/structures/Util.js
CHANGED
|
@@ -1,9 +1,4 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* MessageEmbed - Criar embeds
|
|
3
|
-
* @class
|
|
4
|
-
*/
|
|
5
1
|
class MessageEmbed {
|
|
6
|
-
// Limites rigorosos (mesmo do backend)
|
|
7
2
|
static LIMITS = {
|
|
8
3
|
TITLE: 256,
|
|
9
4
|
DESCRIPTION: 4096,
|
|
@@ -15,12 +10,43 @@ class MessageEmbed {
|
|
|
15
10
|
URL_MAX: 2048
|
|
16
11
|
};
|
|
17
12
|
|
|
18
|
-
// Regex para URLs válidas (HTTP/HTTPS apenas)
|
|
19
13
|
static URL_REGEX = /^https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_\+.~#?&//=]*)$/;
|
|
20
|
-
|
|
21
|
-
// Regex para cores hex
|
|
22
14
|
static COLOR_REGEX = /^#[0-9A-Fa-f]{6}$/;
|
|
23
15
|
|
|
16
|
+
/**
|
|
17
|
+
* Creates a new MessageEmbed instance.
|
|
18
|
+
*
|
|
19
|
+
* @param {Object} [data] - Initial embed data
|
|
20
|
+
* @param {string} data.color - Embed color in hex format (#RRGGBB)
|
|
21
|
+
* @param {Object} data.author - Author options
|
|
22
|
+
* @param {string} data.author.name - Author name
|
|
23
|
+
* @param {string} data.author.iconUrl - Author icon URL
|
|
24
|
+
* @param {string} data.author.url - Author URL
|
|
25
|
+
* @param {string} data.title - Embed title
|
|
26
|
+
* @param {string} data.url - Embed title URL
|
|
27
|
+
* @param {string} data.description - Embed description
|
|
28
|
+
* @param {Array<Object>} data.fields - Array of embed fields
|
|
29
|
+
* @param {string} data.thumbnail - Thumbnail image URL
|
|
30
|
+
* @param {string} data.image - Main image URL
|
|
31
|
+
* @param {Object} data.footer - Footer data
|
|
32
|
+
* @param {string} data.footer.text - Footer text
|
|
33
|
+
* @param {string} data.footer.iconUrl - Footer icon URL
|
|
34
|
+
* @param {Date|number|string} data.timestamp - Timestamp
|
|
35
|
+
*
|
|
36
|
+
* @example
|
|
37
|
+
* const embed = new Client.MessageEmbed()
|
|
38
|
+
* .setColor('#FF0000')
|
|
39
|
+
* .setAuthor('Bot Name', 'https://example.com/icon.png')
|
|
40
|
+
* .setTitle('Hello World')
|
|
41
|
+
* .setURL('https://example.com')
|
|
42
|
+
* .setDescription('This is a complete embed example.')
|
|
43
|
+
* .addField('Field 1', 'Some value here')
|
|
44
|
+
* .addField('Inline Field', 'Inline value', true)
|
|
45
|
+
* .setThumbnail('https://example.com/thumb.png')
|
|
46
|
+
* .setImage('https://example.com/image.png')
|
|
47
|
+
* .setFooter('Footer text', 'https://example.com/footer.png')
|
|
48
|
+
* .setTimestamp();
|
|
49
|
+
*/
|
|
24
50
|
constructor(data = {}) {
|
|
25
51
|
this.color = null;
|
|
26
52
|
this.author = null;
|
|
@@ -39,7 +65,7 @@ class MessageEmbed {
|
|
|
39
65
|
if (data.title) this.setTitle(data.title);
|
|
40
66
|
if (data.url) this.setURL(data.url);
|
|
41
67
|
if (data.description) this.setDescription(data.description);
|
|
42
|
-
if (data.fields) data.fields.forEach(f => this.addField(f.name, f.value, f
|
|
68
|
+
if (data.fields) data.fields.forEach(f => this.addField(f.name, f.value, f?.inline));
|
|
43
69
|
if (data.thumbnail) this.setThumbnail(data.thumbnail);
|
|
44
70
|
if (data.image) this.setImage(data.image);
|
|
45
71
|
if (data.footer) this.setFooter(data.footer.text, data.footer.iconUrl);
|
|
@@ -47,7 +73,11 @@ class MessageEmbed {
|
|
|
47
73
|
}
|
|
48
74
|
|
|
49
75
|
/**
|
|
50
|
-
*
|
|
76
|
+
* Checks if a string is valid: non-empty, not disguised JSON, and optionally within a maximum length.
|
|
77
|
+
* @param {string} value - The string to validate.
|
|
78
|
+
* @param {number} [maxLength=null] - Optional maximum allowed length for the string.
|
|
79
|
+
* @returns {boolean} True if the string is valid.
|
|
80
|
+
* @throws {Error} Throws if the string is empty, too long, or contains JSON content.
|
|
51
81
|
*/
|
|
52
82
|
static _isValidString(value, maxLength = null) {
|
|
53
83
|
if (typeof value !== 'string') {
|
|
@@ -78,7 +108,10 @@ class MessageEmbed {
|
|
|
78
108
|
}
|
|
79
109
|
|
|
80
110
|
/**
|
|
81
|
-
*
|
|
111
|
+
* Validates a URL string against allowed format and dangerous protocols.
|
|
112
|
+
* @param {string} url - The URL to validate.
|
|
113
|
+
* @returns {boolean} True if the URL is valid.
|
|
114
|
+
* @throws {Error} Throws if the URL is invalid, too long, or contains dangerous protocols.
|
|
82
115
|
*/
|
|
83
116
|
static _isValidUrl(url) {
|
|
84
117
|
if (typeof url !== 'string') {
|
|
@@ -104,7 +137,9 @@ class MessageEmbed {
|
|
|
104
137
|
}
|
|
105
138
|
|
|
106
139
|
/**
|
|
107
|
-
*
|
|
140
|
+
* Sanitizes a string by removing dangerous or non-printable characters.
|
|
141
|
+
* @param {string} str - The string to sanitize.
|
|
142
|
+
* @returns {string} The sanitized string.
|
|
108
143
|
*/
|
|
109
144
|
static _isValidColor(color) {
|
|
110
145
|
if (typeof color !== 'string') return false;
|
|
@@ -121,8 +156,9 @@ class MessageEmbed {
|
|
|
121
156
|
}
|
|
122
157
|
|
|
123
158
|
/**
|
|
124
|
-
*
|
|
125
|
-
*
|
|
159
|
+
* Sets the embed color.
|
|
160
|
+
*
|
|
161
|
+
* @param {string|number} color Hex color (#RRGGBB) or a numeric value
|
|
126
162
|
* @returns {MessageEmbed}
|
|
127
163
|
*/
|
|
128
164
|
setColor(color) {
|
|
@@ -135,7 +171,7 @@ class MessageEmbed {
|
|
|
135
171
|
} else if (typeof color === 'string') {
|
|
136
172
|
let hexColor = color.startsWith('#') ? color : `#${color}`;
|
|
137
173
|
hexColor = hexColor.toUpperCase();
|
|
138
|
-
|
|
174
|
+
|
|
139
175
|
if (!MessageEmbed._isValidColor(hexColor)) {
|
|
140
176
|
throw new Error('Color must be a valid hex color (e.g., #FF0000 or FF0000)');
|
|
141
177
|
}
|
|
@@ -147,16 +183,17 @@ class MessageEmbed {
|
|
|
147
183
|
}
|
|
148
184
|
|
|
149
185
|
/**
|
|
150
|
-
*
|
|
151
|
-
*
|
|
152
|
-
* @param {string}
|
|
153
|
-
* @param {string}
|
|
186
|
+
* Sets the embed author.
|
|
187
|
+
*
|
|
188
|
+
* @param {string} name Author name
|
|
189
|
+
* @param {string} [iconUrl] Author icon URL
|
|
190
|
+
* @param {string} [url] Author link URL
|
|
154
191
|
* @returns {MessageEmbed}
|
|
155
192
|
*/
|
|
156
193
|
setAuthor(name, iconUrl = null, url = null) {
|
|
157
194
|
MessageEmbed._isValidString(name, MessageEmbed.LIMITS.AUTHOR_NAME);
|
|
158
|
-
|
|
159
|
-
this.author = {
|
|
195
|
+
|
|
196
|
+
this.author = {
|
|
160
197
|
name: MessageEmbed._sanitizeString(name)
|
|
161
198
|
};
|
|
162
199
|
|
|
@@ -174,8 +211,9 @@ class MessageEmbed {
|
|
|
174
211
|
}
|
|
175
212
|
|
|
176
213
|
/**
|
|
177
|
-
*
|
|
178
|
-
*
|
|
214
|
+
* Sets the embed title.
|
|
215
|
+
*
|
|
216
|
+
* @param {string} title Title text
|
|
179
217
|
* @returns {MessageEmbed}
|
|
180
218
|
*/
|
|
181
219
|
setTitle(title) {
|
|
@@ -185,8 +223,9 @@ class MessageEmbed {
|
|
|
185
223
|
}
|
|
186
224
|
|
|
187
225
|
/**
|
|
188
|
-
*
|
|
189
|
-
*
|
|
226
|
+
* Sets the title URL.
|
|
227
|
+
*
|
|
228
|
+
* @param {string} url Valid HTTP/HTTPS URL
|
|
190
229
|
* @returns {MessageEmbed}
|
|
191
230
|
*/
|
|
192
231
|
setURL(url) {
|
|
@@ -196,8 +235,9 @@ class MessageEmbed {
|
|
|
196
235
|
}
|
|
197
236
|
|
|
198
237
|
/**
|
|
199
|
-
*
|
|
200
|
-
*
|
|
238
|
+
* Sets the embed description.
|
|
239
|
+
*
|
|
240
|
+
* @param {string} description Description text
|
|
201
241
|
* @returns {MessageEmbed}
|
|
202
242
|
*/
|
|
203
243
|
setDescription(description) {
|
|
@@ -207,10 +247,11 @@ class MessageEmbed {
|
|
|
207
247
|
}
|
|
208
248
|
|
|
209
249
|
/**
|
|
210
|
-
*
|
|
211
|
-
*
|
|
212
|
-
* @param {string}
|
|
213
|
-
* @param {
|
|
250
|
+
* Adds a field to the embed.
|
|
251
|
+
*
|
|
252
|
+
* @param {string} name Field name
|
|
253
|
+
* @param {string} value Field value
|
|
254
|
+
* @param {boolean} [inline=false] Whether the field should be inline
|
|
214
255
|
* @returns {MessageEmbed}
|
|
215
256
|
*/
|
|
216
257
|
addField(name, value, inline = false) {
|
|
@@ -233,18 +274,19 @@ class MessageEmbed {
|
|
|
233
274
|
throw new Error('Field inline must be a boolean');
|
|
234
275
|
}
|
|
235
276
|
|
|
236
|
-
this.fields.push({
|
|
237
|
-
name: MessageEmbed._sanitizeString(name),
|
|
238
|
-
value: MessageEmbed._sanitizeString(value),
|
|
239
|
-
inline
|
|
277
|
+
this.fields.push({
|
|
278
|
+
name: MessageEmbed._sanitizeString(name),
|
|
279
|
+
value: MessageEmbed._sanitizeString(value),
|
|
280
|
+
inline
|
|
240
281
|
});
|
|
241
282
|
|
|
242
283
|
return this;
|
|
243
284
|
}
|
|
244
285
|
|
|
245
286
|
/**
|
|
246
|
-
*
|
|
247
|
-
*
|
|
287
|
+
* Adds multiple fields at once.
|
|
288
|
+
*
|
|
289
|
+
* @param {...Object} fields Array of field objects
|
|
248
290
|
* @returns {MessageEmbed}
|
|
249
291
|
*/
|
|
250
292
|
addFields(...fields) {
|
|
@@ -264,8 +306,9 @@ class MessageEmbed {
|
|
|
264
306
|
}
|
|
265
307
|
|
|
266
308
|
/**
|
|
267
|
-
*
|
|
268
|
-
*
|
|
309
|
+
* Sets the thumbnail image.
|
|
310
|
+
*
|
|
311
|
+
* @param {string} url Thumbnail URL
|
|
269
312
|
* @returns {MessageEmbed}
|
|
270
313
|
*/
|
|
271
314
|
setThumbnail(url) {
|
|
@@ -275,8 +318,9 @@ class MessageEmbed {
|
|
|
275
318
|
}
|
|
276
319
|
|
|
277
320
|
/**
|
|
278
|
-
*
|
|
279
|
-
*
|
|
321
|
+
* Sets the main embed image.
|
|
322
|
+
*
|
|
323
|
+
* @param {string} url Image URL
|
|
280
324
|
* @returns {MessageEmbed}
|
|
281
325
|
*/
|
|
282
326
|
setImage(url) {
|
|
@@ -286,15 +330,16 @@ class MessageEmbed {
|
|
|
286
330
|
}
|
|
287
331
|
|
|
288
332
|
/**
|
|
289
|
-
*
|
|
290
|
-
*
|
|
291
|
-
* @param {string}
|
|
333
|
+
* Sets the embed footer.
|
|
334
|
+
*
|
|
335
|
+
* @param {string} text Footer text
|
|
336
|
+
* @param {string} [iconUrl] Footer icon URL
|
|
292
337
|
* @returns {MessageEmbed}
|
|
293
338
|
*/
|
|
294
339
|
setFooter(text, iconUrl = null) {
|
|
295
340
|
MessageEmbed._isValidString(text, MessageEmbed.LIMITS.FOOTER_TEXT);
|
|
296
|
-
|
|
297
|
-
this.footer = {
|
|
341
|
+
|
|
342
|
+
this.footer = {
|
|
298
343
|
text: MessageEmbed._sanitizeString(text)
|
|
299
344
|
};
|
|
300
345
|
|
|
@@ -307,8 +352,9 @@ class MessageEmbed {
|
|
|
307
352
|
}
|
|
308
353
|
|
|
309
354
|
/**
|
|
310
|
-
*
|
|
311
|
-
*
|
|
355
|
+
* Sets the embed timestamp.
|
|
356
|
+
*
|
|
357
|
+
* @param {Date|number|string} [timestamp] Date object, timestamp number or ISO string
|
|
312
358
|
* @returns {MessageEmbed}
|
|
313
359
|
*/
|
|
314
360
|
setTimestamp(timestamp = null) {
|
|
@@ -339,8 +385,9 @@ class MessageEmbed {
|
|
|
339
385
|
}
|
|
340
386
|
|
|
341
387
|
/**
|
|
342
|
-
*
|
|
343
|
-
*
|
|
388
|
+
* Converts the embed into a JSON object compatible with the BenioCord API.
|
|
389
|
+
*
|
|
390
|
+
* @returns {Object} Embed JSON representation
|
|
344
391
|
*/
|
|
345
392
|
toJSON() {
|
|
346
393
|
// Valida antes de converter
|
|
@@ -363,7 +410,8 @@ class MessageEmbed {
|
|
|
363
410
|
}
|
|
364
411
|
|
|
365
412
|
/**
|
|
366
|
-
*
|
|
413
|
+
* Converts the embed into a plain-text fallback format.
|
|
414
|
+
*
|
|
367
415
|
* @returns {string}
|
|
368
416
|
*/
|
|
369
417
|
toText() {
|
|
@@ -396,9 +444,10 @@ class MessageEmbed {
|
|
|
396
444
|
}
|
|
397
445
|
|
|
398
446
|
/**
|
|
399
|
-
*
|
|
400
|
-
*
|
|
401
|
-
* @throws {Error}
|
|
447
|
+
* Validates the embed content and size limits.
|
|
448
|
+
*
|
|
449
|
+
* @throws {Error} If the embed contains invalid data
|
|
450
|
+
* @returns {boolean} Whether the embed is valid
|
|
402
451
|
*/
|
|
403
452
|
validate() {
|
|
404
453
|
// Pelo menos título ou descrição deve existir
|