@elara-services/leveling
Version:
A package for XP/Leveling on Discord.
239 lines (238 loc) • 8.52 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.customLeaderboard = void 0;
const utils_2 = require("@elara-services/utils");
const skia_canvas_1 = require("skia-canvas");
const av = (id) => `https://japi.rest/discord/v1/user/${id}/avatar`;
async function customLeaderboard(users, options = {}) {
const { current: currentUser, prefix: prefixed, suffix, showIndexColor, minify = false, } = options;
users = users.slice(0, 10);
let isPart = false;
if (currentUser && !users.find((c) => c.name === currentUser.name)) {
isPart = true;
}
const canvas = new skia_canvas_1.Canvas(1000, isPart ? 1210 : 1090 - (10 - users.length) * 110);
const ctx = canvas.getContext("2d");
let totalY = 0;
// @ts-ignore
for (let i = 0, y = 0; i < 10; i++) {
if (!users[i]) {
continue;
}
const r = await draw({
data: users[i],
i,
y,
color: users[i].color === null ? null : users[i].color || "",
showIndexColor,
});
y = r.y;
i = r.i;
totalY = r.y;
}
if (isPart && currentUser) {
await draw({
data: currentUser,
y: totalY,
color: currentUser.color === null
? null
: currentUser.color || "#ed4245",
showIndexColor,
});
}
async function draw({ data, i, y, color = null, showIndexColor, }) {
if (!utils_2.is.number(i, false)) {
i = 0;
}
if (utils_2.is.string(data.avatar) && !data.avatar.match(/http(s):\/\//gi)) {
data.avatar = av(data.avatar);
}
// Draw rectangles
ctx.fillStyle = "#000000";
curved(ctx, 0, y, canvas.width, 100, { tl: 50, tr: 10, bl: 50, br: 10 }, true);
ctx.fillStyle = "#121212";
curved(ctx, 0, y, 100, 100, 10, true);
// Draw user info
ctx.save();
ctx.beginPath();
curved(ctx, 0, y, 100, 100, 10, false, false);
ctx.closePath();
ctx.clip();
let image = Buffer.isBuffer(data.avatar)
? data.avatar
: await (0, skia_canvas_1.loadImage)(data.avatar).catch(() => null);
if (!image) {
image = await (0, skia_canvas_1.loadImage)(`https://raw.githubusercontent.com/DevelopmentPerson69420/cdn/main/api/bot/i_n_a.png`).catch(() => null);
}
if (image) {
// @ts-ignore
ctx.drawImage(image, 0, y, 100, 100);
}
ctx.restore();
// Draw index
ctx.font = "bold 40px Raleway";
if (![showIndexColor, data.showIndexColor].some((c) => c === false)) {
ctx.fillStyle =
color || ["#FFD700", "#C0C0C0", "#CD7F32"][i] || "#FFFFFF";
}
else {
ctx.fillStyle = "#FFFFFF";
}
const index = `#${data.index ? data.index : i + 1}`, indexWidth = ctx.measureText(index).width;
ctx.fillText(index, 120, 65 + y);
// Draw circle
ctx.beginPath();
ctx.arc(indexWidth + 135, 53 + y, 5, 0, 2 * Math.PI, false);
ctx.fillStyle = "#C0C0C0";
ctx.fill();
let amount = ``;
let amountWidth = 0;
if (data.total) {
// Draw amount
ctx.fillStyle = "#FFFFFF";
ctx.font = "30px Raleway";
amount = `${prefixed || ""}${minify && utils_2.is.number(data.total)
? Intl.NumberFormat("en", {
notation: "compact",
compactDisplay: "short",
}).format(data.total)
: data.total.toLocaleString()}${suffix || ""}`;
amountWidth = ctx.measureText(amount).width;
ctx.fillStyle = "#121212";
curved(ctx, canvas.width - amountWidth - 30, 20 + y, amountWidth + 15, 55, 10, true);
ctx.fillStyle = "#FFFFFF";
ctx.fillText(amount, canvas.width - amountWidth - 22, 60 + y);
}
// Draw username
ctx.fillStyle = color || "#FFFFFF";
ctx.font = "bold 40px Raleway";
const name = data.name, max = canvas.width - amountWidth - 50 - (indexWidth + 150);
const list = name.split("");
let total = "";
for (let i = 0; i < name.length; i++) {
total += list[i];
if (ctx.measureText(total).width > max) {
break;
}
}
ctx.fillText(total.length !== name.length
? `${total.slice(0, -2)}...${(name.match(/#\d{4}/g)?.[0] || "")}`
: total, indexWidth + 150, 65 + y);
return { y: (y += 110), i };
}
return canvas.toBuffer("png");
}
exports.customLeaderboard = customLeaderboard;
// eslint-disable-next-line @typescript-eslint/no-unused-vars
function minify(value, options) {
const options_1 = {
base: 1000,
decimalSeparator: ".",
lowercase: false,
precision: 2,
space: false,
units: ["", "K", "M", "B", "T", "P", "E"],
};
const utils_1 = {
parseValue: (value) => {
const val = parseFloat(value.toString());
if (isNaN(val)) {
return "N/A";
}
if (val > Number.MAX_SAFE_INTEGER ||
val < Number.MIN_SAFE_INTEGER) {
throw new RangeError("Input value is outside of safe integer range");
}
return val;
},
roundTo: (value, precision) => {
if (!Number.isFinite(value)) {
return "♾";
}
if (Number.isInteger(value)) {
return value;
}
return parseFloat(value.toFixed(precision));
},
};
const opts = options
? Object.assign(Object.assign({}, options_1), options)
: options_1;
if (utils_2.is.object(options, true)) {
if (utils_2.is.boolean(options.lowercase)) {
opts.lowercase = options.lowercase;
}
}
if (!utils_2.is.array(opts.units)) {
throw new Error("Option 'units' must be a non-empty array");
}
let [val, unitIndex, suffix] = [utils_1.parseValue(value), 0, new String()];
const prefix = parseInt(val) < 0 ? "-" : new String();
val = Math.abs(parseInt(val));
for (const result of divider(val, opts.base)) {
(val = result), (unitIndex += 1);
}
const unitIndexOutOfRange = unitIndex >= opts.units.length;
if (!unitIndexOutOfRange) {
const unit = opts.units[unitIndex];
suffix = opts.lowercase ? unit.toLowerCase() : unit;
}
else {
console.warn("[millify] 'options.units' array is of insufficient length. Add another unit to silence this warning.");
}
const [space, rounded] = [
opts.space && !unitIndexOutOfRange ? " " : new String(),
utils_1.roundTo(val, opts.precision),
], formatted = rounded
.toString()
.replace(options_1.decimalSeparator, opts.decimalSeparator);
return `${prefix}${formatted}${space}${suffix}`;
function* divider(value, base) {
let denominator = base;
while (true) {
const result = value / denominator;
if (result < 1) {
return;
}
yield result;
denominator *= base;
}
}
}
function curved(ctx, x, y, width, height, rad = 0, fill, stroke = false) {
const radius = {
tl: 0,
tr: 0,
br: 0,
bl: 0,
};
if (utils_2.is.number(rad)) {
for (const key of (0, utils_2.getKeys)(radius)) {
radius[key] = rad;
}
}
else if (utils_2.is.object(rad, true)) {
for (const key of (0, utils_2.getKeys)(rad)) {
if (utils_2.is.number(rad[key])) {
radius[key] = rad[key] || 0;
}
}
}
ctx.beginPath();
ctx.moveTo(x + radius.tl, y);
ctx.lineTo(x + width - radius.tr, y);
ctx.quadraticCurveTo(x + width, y, x + width, y + radius.tr);
ctx.lineTo(x + width, y + height - radius.br);
ctx.quadraticCurveTo(x + width, y + height, x + width - radius.br, y + height);
ctx.lineTo(x + radius.bl, y + height);
ctx.quadraticCurveTo(x, y + height, x, y + height - radius.bl);
ctx.lineTo(x, y + radius.tl);
ctx.quadraticCurveTo(x, y, x + radius.tl, y);
ctx.closePath();
if (fill) {
ctx.fill();
}
if (stroke) {
ctx.stroke();
}
}