Skip to content

Commit 31cd10f

Browse files
authored
Merge pull request #2 from Exhabition/development
Version 1.0.3
2 parents 5b10dd5 + b16f7ea commit 31cd10f

10 files changed

+423
-52
lines changed

additions/Client/userCount.js

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
const { addPrototype } = require("erisify/helper/prototype");
2+
3+
/**
4+
* @param {import("eris")} Eris
5+
*/
6+
module.exports.init = (Eris) => {
7+
addPrototype(Eris, "Client", function userCount() {
8+
return this.guilds?.size > 0 ? this.guilds.map(guild => guild.memberCount).reduce((total, memberCount) => total + memberCount, 0) : 0;
9+
}, true);
10+
};

additions/Eris/MessageButton.js

+53-4
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,60 @@
1+
const { addImport } = require("erisify/helper/prototype");
2+
3+
const BUTTON_STYLES = {
4+
blurple: 1,
5+
grey: 2,
6+
green: 3,
7+
red: 4,
8+
link: 5,
9+
};
10+
111
class MessageButton {
2-
constructor() {
3-
this.useful = true;
12+
constructor(options = {}) {
13+
this.disabled = false;
14+
this.type = 2;
15+
16+
return this;
17+
}
18+
19+
setStyle(style) {
20+
if (!style || typeof style !== "string" && typeof style !== "number") throw new TypeError("An invalid button style was provided");
21+
22+
if (typeof style === "number") {
23+
if (style > 0 && style < BUTTON_STYLES.length) this.style = style;
24+
else throw new TypeError(`A button style value must be higher than 0 and lower than ${BUTTON_STYLES}`);
25+
} else if (typeof style === "string") {
26+
if (BUTTON_STYLES.includes(style.toLowerCase())) this.style = BUTTON_STYLES[style.toLowerCase()];
27+
else throw new TypeError(`"${style}" is not a valid button style`);
28+
}
29+
30+
return this;
31+
}
32+
33+
setLabel(label) {
34+
this.label = label.toString().slice(0, 80);
35+
36+
return this;
37+
}
38+
39+
// setEmoji(emoji) {
40+
// this.emoji = { name, id, animated };
41+
42+
// return this;
43+
// }
44+
45+
setUrl(url) {
46+
this.url = url;
47+
48+
return this;
49+
}
50+
51+
disable(disable = true) {
52+
this.disabled = disable;
453

554
return this;
655
}
756
}
857

9-
module.exports = Eris => {
10-
Eris.MessageButton = MessageButton;
58+
module.exports.init = Eris => {
59+
addImport(Eris, MessageButton);
1160
};

additions/Eris/MessageEmbed.js

+171-22
Original file line numberDiff line numberDiff line change
@@ -1,82 +1,231 @@
1+
const { addImport } = require("erisify/helper/prototype");
2+
const { truncate } = require("erisify/helper/formatting");
3+
4+
const { preventErrors } = require("erisify/index.js").options;
5+
6+
/** TODO:
7+
* Turn values into strings when possible.
8+
* Stricter checking for HEX strings is
9+
* Take a look at `setTimestamp` again
10+
* Check the types of values, a boolean parameter shouldn't receive a number for example
11+
*/
12+
113
class MessageEmbed {
2-
constructor() {
14+
/**
15+
* @param {Object} options
16+
* @param {Boolean} [options.preventErrors] [Overrides initial options of erisify] Try and fix errors such as making strings shorter instead of throwing an error if the string is too long for this specific embed
17+
* @param {String} [options.truncate] If a present values that are too long will get truncated and will end into the string passed in this option
18+
*/
19+
constructor(options = { preventErrors }) {
20+
this.options = options;
321
this.fields = [];
422

523
return this;
624
}
725

8-
setAuthor(name, icon_url, url) {
9-
this.author = { name, icon_url, url };
26+
/**
27+
* @param {String} name
28+
* @param {String} [iconUrl]
29+
* @param {String} [url]
30+
*/
31+
setAuthor(name, iconUrl, url) {
32+
const tempAuthor = {};
33+
34+
if (this.options.truncate || this.options.preventErrors) {
35+
const suffix = this.options.truncate || "";
36+
tempAuthor.name = truncate(name, 256, suffix);
37+
if (iconUrl) tempAuthor.icon_url = truncate(iconUrl, 2048, suffix);
38+
if (url) tempAuthor.url = truncate(url, 2048, suffix);
39+
} else {
40+
if (name.length > 0 && name.length <= 256) tempAuthor.name = name;
41+
else throw new RangeError("[MessageEmbed.setAuthor] 'name' must be a string longer than 0 characters and shorter than or equal to 256 characters");
42+
43+
if (iconUrl) {
44+
if (iconUrl.length > 0 && iconUrl.length <= 2048) tempAuthor.icon_url = iconUrl;
45+
else throw new RangeError("[MessageEmbed.setAuthor] 'iconUrl' must be a string longer than 0 characters and shorter than or equal to 2048 characters");
46+
}
47+
48+
if (url) {
49+
if (url.length > 0 && url.length <= 2048) tempAuthor.url = url;
50+
else throw new RangeError("[MessageEmbed.setAuthor] 'url' must be a string longer than 0 characters and shorter than or equal to 2048 characters");
51+
}
52+
}
53+
54+
this.author = tempAuthor;
1055

1156
return this;
1257
}
1358

59+
/**
60+
* @param {Number|Array|String} color Either a HEX string, array with RGB values or number
61+
*/
1462
setColor(color) {
15-
if (color.startsWith("#")) this.color = parseInt(color, 16);
16-
else this.color = color;
63+
if (typeof color == "number") {
64+
if (color > 0 && color < 16777215)
65+
this.color = color;
66+
else if (!this.options.preventErrors)
67+
throw new RangeError("[MessageEmbed.setColor] 'color' must be a number higher than 0 and lower than or equal to 16777216777215");
68+
} else if (Array.isArray(color)) {
69+
if (color.length < 3 && !this.options.preventErrors)
70+
throw new RangeError("[MessageEmbed.setColor] RGB arrays must be at least 3 items long");
71+
else if (color.length < 3)
72+
return this;
73+
74+
if (color.some(item => !Number.isInteger(item)) && !this.options.preventErrors)
75+
throw new TypeError("[MessageEmbed.setColor] RGB values must be integers");
76+
else if (color.some(item => !Number.isInteger(item)))
77+
return this;
78+
79+
const [r, g, b] = color;
80+
81+
this.color = parseInt(((1 << 24) + (r << 16) + (g << 8) + b).toString(16).slice(1), 16);
82+
} else if (color.startsWith("#")) {
83+
this.color = parseInt(color.slice(1, color.length), 16);
84+
} else if (!this.options.preventErrors) throw new Error("[MessageEmbed.setColor] Invalid HEX string passed as 'color'");
1785

1886
return this;
1987
}
2088

89+
/**
90+
* @param {String} title Prefers a string, but numbers or arrays are turned into strings too
91+
*/
2192
setTitle(title) {
22-
this.title = title.toString().slice(256);
93+
if (this.options.truncate) this.title = truncate(title, 256, this.options.truncate);
94+
else if (this.options.preventErrors) his.title = truncate(title, 256);
95+
else if (title.length > 0 && title.length <= 256) this.title = title;
96+
else throw new RangeError("[MessageEmbed.setTitle] 'title' must be a string longer than 0 and shorter or equal to 256 characters");
2397

2498
return this;
2599
}
26100

27-
setUrl(url) {
28-
this.url = url;
101+
/**
102+
* @param {String} url
103+
*/
104+
setURL(url) {
105+
// No clue why url limits are not documented...
106+
if (url.length > 0 && url.length <= 2048) this.url = url;
107+
else throw new RangeError("[MessageEmbed.setURL] 'url' must be a well-formed URL longer than 0 and shorter or equal to 2048 characters");
29108

30109
return this;
31110
}
32111

112+
/**
113+
* @param {String} description
114+
*/
33115
setDescription(description) {
34-
this.description = description.toString().slice(2048);
116+
if (this.options.truncate || this.options.preventErrors) this.description = truncate(description.toString(), 4096, this.options.truncate || "");
117+
else if (description.length > 0 && description.length <= 4096) this.description = description;
118+
else throw new RangeError("[MessageEmbed.setDescription] 'description' must be a string longer than 0 and shorter or equal to 4096 characters");
35119

36120
return this;
37121
}
38122

123+
/**
124+
* @param {String} url An url pointing to an image asset
125+
*/
39126
setThumbnail(url) {
40-
this.thumbnail = { url };
127+
if (url.length > 0 && url.length <= 2048) this.thumbnail = { url };
128+
else throw new RangeError("[MessageEmbed.setThumbnail] 'url' must be a well-formed URL longer than 0 and shorter or equal to 2048 characters");
41129

42130
return this;
43131
}
44132

133+
/**
134+
* @param {String} url An url pointing to an image asset
135+
*/
45136
setImage(url) {
46-
this.image = { url };
137+
if (url.length > 0 && url.length <= 2048) this.image = { url };
138+
else throw new RangeError("[MessageEmbed.setImage] 'url' must be a well-formed URL longer than 0 and shorter or equal to 2048 characters");
47139

48140
return this;
49141
}
50142

143+
/**
144+
* @param {DateConstructor} [time]
145+
*/
51146
setTimestamp(time = new Date()) {
52-
this.timestamp = time;
147+
if (Number.isNaN(new Date(time).getTime())) {
148+
if (!this.options.preventErrors) throw new Error("[MessageEmbed.setTimestamp] Invalid data passed");
149+
else time = new Date();
150+
}
151+
152+
this.timestamp = new Date(time);
53153

54154
return this;
55155
}
56156

57-
setFooter(text, icon_url) {
58-
this.footer = { text: text.toString().slice(2048), icon_url };
157+
/**
158+
* @param {String} text
159+
* @param {String} [iconUrl]
160+
*/
161+
setFooter(text, iconUrl) {
162+
const tempFooter = {};
163+
164+
if (this.options.truncate || this.options.preventErrors) {
165+
tempFooter.text = truncate(text, 2048, this.options.truncate || "");
166+
if (iconUrl) tempFooter.icon_url = truncate(iconUrl, 2048, this.options.truncate || "");
167+
} else {
168+
if (text.length > 0 && text.length <= 2048) tempFooter.text = text;
169+
else throw new RangeError("[MessageEmbed.setFooter] 'text' must be a string longer than 0 characters and shorter than or equal to 2048 characters");
170+
171+
if (iconUrl) {
172+
if (iconUrl.length > 0 && iconUrl.length <= 2048) tempFooter.icon_url = iconUrl;
173+
else throw new RangeError("[MessageEmbed.setFooter] 'iconUrl' must be a string longer than 0 characters and shorter than or equal to 2048 characters");
174+
}
175+
}
176+
177+
this.footer = tempFooter;
59178

60179
return this;
61180
}
62181

182+
/**
183+
* @param {String} name
184+
* @param {String} value
185+
* @param {Boolean} [inline=true]
186+
*/
63187
addField(name, value, inline = false) {
188+
if (Array.isArray(value)) value = value.join("\n");
189+
64190
if (this.fields.length >= 25) {
65-
console.warn("Limit of 25 fields exceeded, no field was added");
66-
return this;
67-
} else if (!name || !value) {
68-
console.warn("Both a name & value are needed, no field was addded");
69-
return this;
191+
if (this.options.preventErrors) {
192+
console.warn("[MessageEmbed.addField] A max of 25 fields are allowed, current field couldn't be added");
193+
return this;
194+
} else {
195+
throw new Error("[MessageEmbed.addField] A max of 25 fields are allowed, current field would exceed limit");
196+
}
70197
}
71198

72-
this.fields.push({ name: toString().slice(256), value: value.toString().slice(256), inline });
199+
if (!name || !value && !this.options.preventErrors) throw new Error("[MessageEmbed.addField] both 'name' & 'value' are required");
200+
201+
const tempField = { name: "Not set", value: "Not set", inline };
202+
203+
if (this.options.truncate || this.options.preventErrors) {
204+
tempField.name = truncate(name, 256, this.options.truncate || "");
205+
tempField.value = truncate(value, 1024, this.options.truncate || "");
206+
} else {
207+
if (name.length > 0 && name.length <= 256) tempField.name = name;
208+
else throw new RangeError("[MessageEmbed.addField] 'name' must be a string longer than 0 characters and shorter than or equal 256 characters");
209+
210+
if (value.length > 0 && value.length <= 1048) tempField.value = value;
211+
else throw new RangeError("[MessageEmbed.addField] 'value' must be a string longer than 0 characters and shorter than or equal 1048 characters");
212+
}
213+
214+
this.fields.push(tempField);
215+
216+
return this;
73217
}
74218

219+
/**
220+
* @description Clears all fields
221+
*/
75222
clearFields() {
76223
this.fields = [];
224+
225+
return this;
77226
}
78227
}
79228

80-
module.exports = Eris => {
81-
Eris.MessageEmbed = MessageEmbed;
229+
module.exports.init = Eris => {
230+
addImport(Eris, MessageEmbed);
82231
};

additions/Eris/Timestamp.js

+54
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
const { addImport } = require("erisify/helper/prototype");
2+
3+
const TIMESTAMP_STYLES = {
4+
SHORT_TIME: "t",
5+
LONG_TIME: "T",
6+
SHORT_DATE: "d",
7+
LONG_DATE: "D",
8+
SHORT_DATE_TIME: "f",
9+
LONG_DATE_TIME: "F",
10+
RELATIVE_TIME: "R",
11+
};
12+
13+
Object.freeze(TIMESTAMP_STYLES);
14+
15+
class Timestamp {
16+
constructor(options = {}) {
17+
this.timestamp = Date.now();
18+
this.style = TIMESTAMP_STYLES.SHORT_DATE_TIME;
19+
20+
return this;
21+
}
22+
23+
get() {
24+
return `<t:${this.timestamp}:${this.style}>`;
25+
}
26+
27+
setStyle(style) {
28+
if (!style || typeof style !== "string") throw new TypeError("An invalid timestamp style was provided");
29+
else if (!Object.values(TIMESTAMP_STYLES).includes(style)) throw new TypeError("An invalid timestamp style was provided");
30+
31+
this.style = style;
32+
33+
return this;
34+
}
35+
36+
/**
37+
* @param {DateConstructor} [time]
38+
*/
39+
setTimestamp(time = new Date()) {
40+
if (Number.isNaN(new Date(time).getTime())) {
41+
if (!this.options.preventErrors) throw new Error("[MessageEmbed.setTimestamp] Invalid data passed");
42+
else time = new Date();
43+
}
44+
45+
this.timestamp = new Date(time);
46+
47+
return this;
48+
}
49+
}
50+
51+
module.exports.init = Eris => {
52+
addImport(Eris, Timestamp);
53+
// TODO addImport(Eris, TIMESTAMP_STYLES);
54+
};

helper/formatting.js

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
module.exports = {
2+
truncate: function (text, maxLength, suffix = "") {
3+
if (text.length > maxLength) {
4+
return `${text.slice(0, maxLength - suffix.length)}${suffix}`;
5+
}
6+
7+
return text;
8+
},
9+
};

0 commit comments

Comments
 (0)