Skip to content

Commit

Permalink
V2.0.0 DEV 4
Browse files Browse the repository at this point in the history
Implemented charts()
added SQLite to MongoDB for migrate.fromDB()
Fixed various bugs
Lowered package size
  • Loading branch information
Abadima committed Aug 24, 2023
1 parent c66a2c8 commit 02f6769
Show file tree
Hide file tree
Showing 22 changed files with 547 additions and 114 deletions.
5 changes: 3 additions & 2 deletions Mini_Docs/charts.md
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
<a name="charts"></a>

## charts(guildId, options) ⇒ <code>Promise.&lt;void&gt;</code>
## charts(guildId, options) ⇒ <code>Promise.&lt;{attachment: Buffer, description: string, name: string}&gt;</code>

Creates a chart

**Kind**: global function
**Returns**: <code>Promise.&lt;{attachment: Buffer, description: string, name: string}&gt;</code> - Chart attachment
**Throws**:

- <code>XpFatal</code> If invalid parameters are provided
- <code>XpFatal</code> If invalid parameters are provided, or if there are not enough users to create a chart

**Link**: `Documentation:` https://simplyxp.js.org/docs/charts

Expand Down
14 changes: 7 additions & 7 deletions Mini_Docs/reset.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<a name="reset"></a>

## reset(userId, guildId, username, erase) ⇒ <code>Promise.&lt;boolean&gt;</code>
## reset(userId, guildId, erase, username) ⇒ <code>Promise.&lt;boolean&gt;</code>

Reset user levels to 0 in a guild

Expand All @@ -11,10 +11,10 @@ Reset user levels to 0 in a guild

**Link**: `Documentation:` https://simplyxp.js.org/docs/reset

| Param | Type | Default | Description |
|----------|----------------------|--------------------|--------------------------------|
| userId | <code>string</code> | | |
| guildId | <code>string</code> | | |
| erase | <code>boolean</code> | <code>false</code> | Erase user entry from database |
| username | <code>string</code> | | |
| Param | Type | Default | Description |
|----------|----------------------|--------------------|-------------------------------------------|
| userId | <code>string</code> | | |
| guildId | <code>string</code> | | |
| erase | <code>boolean</code> | <code>false</code> | Erase user entry from the database |
| username | <code>string</code> | | Username to use if auto_create is enabled |

14 changes: 8 additions & 6 deletions Mini_Docs/types/ChartOptions.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,18 @@

### Properties

- `backgroundColor` (HexColor, optional): The background color of the chart.
- `limit` (number, optional): The limit of the chart.
- `type` (`"bar" | "line" | "pie" | "doughnut" | "radar" | "polarArea"`, optional): The type of the chart.
- font `(string)`: The font to be used in the chart.
- limit `(2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10)`: The maximum number of users to be displayed in the chart.
- theme `("blue" | "dark" | "discord" | "green" | "orange" | "red" | "space" | "yellow")`: The theme to be used in the chart.
- type `("bar" | "doughnut" | "pie")`: The type of chart to be created.

### Example

```typescript
export interface ChartOptions {
backgroundColor?: HexColor;
limit?: number;
type?: "bar" | "line" | "pie" | "doughnut" | "radar" | "polarArea";
font?: string;
limit?: 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10;
theme?: "blue" | "dark" | "discord" | "green" | "orange" | "red" | "space" | "yellow";
type?: "bar" | "doughnut" | "pie";
}
```
2 changes: 1 addition & 1 deletion Mini_Docs/types/leaderboardCardOptions.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

### Description

An interface representing the options for a rank card.
An interface representing the options for a leaderboard card.

### Properties

Expand Down
Binary file added Tests/charts.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified Tests/leaderboard.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified Tests/rankcard.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
45 changes: 30 additions & 15 deletions Tests/test.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -7,46 +7,44 @@ async function test(dbType) {
switch (dbType) {
case "mongodb":
await xp.connect(MongoURL, {
auto_create: true,
type: "mongodb",
debug: true
});
break;
case "sqlite":
await xp.connect("Tests/test.db", {
auto_create: true,
type: "sqlite",
debug: true
});
break;
}

await xp.create("1234567890", "0987654321", "Abadima");
/* await xp.create("1234567890", "0987654321", "Abadima")
await xp.create("1234567891", "0987654321", "Elizabeth");
await xp.create("1234567891", "0987654321", "Elizabeth");
await xp.create("1234567892", "0987654321", "Jena");
await xp.create("1234567892", "0987654321", "Jena").then(console.log)
await xp.create("1234567893", "0987654321", "Rahul");
await xp.create("1234567893", "0987654321", "Rahul");
await xp.create("1234567894", "0987654321", "Snowball");
await xp.create("1234567894", "0987654321", "Snowball");*/

await xp.setLevel("1234567890", "0987654321", Infinity);
await xp.setLevel("1234567890", "0987654321", 25, "Abadima");

await xp.setLevel("1234567891", "0987654321", 50);
await xp.setLevel("1234567893", "0987654321", 20, "Rahul");

await xp.setLevel("1234567893", "0987654321", 420690000);
await xp.setLevel("1234567894", "0987654321", 15, "Jena");

await xp.setLevel("1234567892", "0987654321", 0);
await xp.addLevel("1234567892", "0987654321", 10, "Ash");

await xp.addXP("1234567892", "0987654321", 650);

await xp.reset("1234567892", "0987654321").then(console.log);

await xp.fetch("1234567892", "0987654321").then(console.log);
await xp.setLevel("1234567891", "0987654321", 5, "Elizabeth");

await xp.rankCard(
{id: "0987654321", name: "SimplyTests"},
{
avatarURL: "https://cdn.discordapp.com/avatars/326815959358898189/02ed1eef72af8eca955f35e309f8f3aa.webp",
avatarURL: "https://cdn.discordapp.com/avatars/326815959358898189/67f99af24216f6d98d8d61a3b127d160.webp",
id: "1234567890", username: "Abadima"
},
{background: "https://img.freepik.com/free-vector/gradient-wavy-purple-background_23-2149117433.jpg"}
Expand All @@ -67,6 +65,23 @@ async function test(dbType) {
require("fs").writeFileSync("Tests/leaderboard.png", results.attachment);
});
});

await xp.charts("0987654321", {
theme: "space",
type: "doughnut"
}).then(results => {
require("fs").writeFileSync("Tests/charts.png", results.attachment);
});

await xp.reset("1234567890", "0987654321", true);

await xp.reset("1234567893", "0987654321", true);

await xp.reset("1234567894", "0987654321", true);

await xp.reset("1234567892", "0987654321", true);

await xp.reset("1234567891", "0987654321", true);
}

test("mongodb");
20 changes: 19 additions & 1 deletion [email protected]
Original file line number Diff line number Diff line change
@@ -1,5 +1,23 @@
# VERSION 2@DEV CHANGELOGS

## [DEV 4](https://github.com/Abadima/simply-xp/releases/tag/v2.0.0-dev.4)

### Additions

- `charts()` is now added, starting with `bar`, `doughnut` and `pie` types, and many themes to choose from.
- `migrate.fromDB()` now supports migrating from SQLite to MongoDB.

### Bug Fixes

- Fix `db.createOne()` not returning created user (MongoDB), this should fix multiple functions not working properly.
- Fix `db.addXP()` throwing unnecessary error when checking if new user is considered levelled up.
- `rankCard()` and `leaderboardCard()` now throws better error when image(s) provided can't be loaded.

### Improvements

- Optimized font file, lowers package size (~57.31%)
- Updated JSDocs to improve accuracy.

## [DEV 3 FIX 2](https://github.com/Abadima/simply-xp/releases/tag/v2.0.0-dev.3)

### Bug Fixes
Expand Down Expand Up @@ -55,7 +73,7 @@
### Changes

- Updated JSDocs, changed some types to interfaces.
- Optimized font file, lowers package size.
- Optimized font file, lowers package size (~32.12%)

## [DEV 1](https://github.com/Abadima/simply-xp/releases/tag/v2.0.0-dev.1)

Expand Down
16 changes: 8 additions & 8 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "simply-xp",
"version": "2.0.0-dev.3-fix.2",
"version": "2.0.0-dev.4",
"description": "The easiest way to implement xp system",
"main": "lib/xp.js",
"scripts": {
Expand Down Expand Up @@ -40,18 +40,18 @@
"url": "git+https://github.com/Rahuletto/simply-xp.git"
},
"dependencies": {
"@napi-rs/canvas": "^0.1.43"
"@napi-rs/canvas": "^0.1.44"
},
"devDependencies": {
"@types/better-sqlite3": "^7.6.4",
"@types/node": "^20.5.0",
"@typescript-eslint/eslint-plugin": "^6.3.0",
"@typescript-eslint/parser": "^6.3.0",
"better-sqlite3": "8.5.0",
"discord.js": "^14.12.1",
"@types/node": "^20.5.4",
"@typescript-eslint/eslint-plugin": "^6.4.1",
"@typescript-eslint/parser": "^6.4.1",
"better-sqlite3": "8.5.1",
"discord.js": "^14.13.0",
"eslint": "^8.47.0",
"jsdoc-to-markdown": "^8.0.0",
"mongodb": "^5.7.0",
"mongodb": "^5.8.1",
"typescript": "^5.1.6",
"uglify-js": "^3.17.4"
},
Expand Down
Binary file removed src/Fonts/Baloo-Regular.eot
Binary file not shown.
Binary file added src/Fonts/BalooBhaijaan-Regular.otf
Binary file not shown.
6 changes: 2 additions & 4 deletions src/add.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,7 @@ export async function addLevel(userId: string, guildId: string, level: number, u
if (!user) {
if (xp.auto_create && username) return await db.createOne({
collection: "simply-xps",
data: {
guild: guildId, user: userId, name: username, level, xp: convertFrom(level)
}
data: {guild: guildId, user: userId, name: username, level, xp: convertFrom(level)}
}) as UserResult;
else throw new XpFatal({function: "addLevel()", message: "User does not exist"});
} else {
Expand Down Expand Up @@ -113,5 +111,5 @@ export async function addXP(userId: string, guildId: string,
}) as UserResult;
}

return {...data, hasLevelledUp: data.level > user.level};
return {...data, hasLevelledUp: user ? data.level > user.level : true};
}
74 changes: 57 additions & 17 deletions src/cards.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,14 @@ export type rankLocales = {
* @returns {Promise<{attachment: Buffer, description: string, name: string}>}
* @throws {XpFatal} - If parameters are not provided correctly
*/
export async function rankCard(guild: { id: string, name: string }, user: UserOptions, options: RankCardOptions = {}, locales: rankLocales = {}): Promise<{ attachment: Buffer; description: string; name: string; }> {
export async function rankCard(guild: {
id: string,
name: string
}, user: UserOptions, options: RankCardOptions = {}, locales: rankLocales = {}): Promise<{
attachment: Buffer;
description: string;
name: string;
}> {
if (!guild) throw new XpFatal({function: "rankCard()", message: "No Guild Provided"});
if (!user) throw new XpFatal({function: "rankCard()", message: "No User Provided"});

Expand All @@ -91,34 +98,44 @@ export async function rankCard(guild: { id: string, name: string }, user: UserOp
if (!locales?.xp) locales.xp = "XP";

XpLog.debug("rankCard()", "LEGACY MODE ENABLED");
XpLog.info("rankCard()", "Modern RankCard is not supported yet, coming soon!");
XpLog.info("rankCard()", "Modern RankCard is coming in dev.5");

if (!user?.avatarURL.endsWith(".png") && !user.avatarURL.endsWith(".jpg") && !user.avatarURL.endsWith(".webp")) {
throw new XpFatal({
function: "rankCard()", message: "Invalid avatar image, avatar image must be a png, jpg, or webp"
});
}

// check if user.id and user.username and user.displayAvatarURL() exists

if (!user || !user.id || !user.username) {
throw new XpFatal({
function: "rankCard()", message: "Invalid User Provided, user must contain id, username, and avatarURL."
});
}

GlobalFonts.registerFromPath(options?.font || join(__dirname, "Fonts", "Baloo-Regular.eot"), "Sans Serif");
GlobalFonts.registerFromPath(options?.font || join(__dirname, "Fonts", "BalooBhaijaan-Regular.otf"), "Sans Serif");

if (!cachedRankImage) cachedRankImage = await loadImage(options?.background || "https://i.ibb.co/dck2Tnt/rank-card.webp").catch(() => {
throw new XpFatal({
function: "rankCard()", message: "Unable to load background image, is it valid?"
});
});

if (!cachedRankImage) cachedRankImage = await loadImage(options?.background || "https://i.ibb.co/dck2Tnt/rank-card.webp");
const avatarURL = await loadImage(user.avatarURL).catch(() => {
throw new XpFatal({
function: "rankCard()", message: "Unable to load user's AvatarURL, is it reachable?"
});
});

let dbUser = await db.findOne({collection: "simply-xps", data: {guild: guild.id, user: user.id}}) as User;
if (!dbUser) {
if (xp.auto_create) dbUser = await create(user.id, guild.id, user.username);
if (xp.auto_create) dbUser = await create(user.id, guild.id, user.username) as User;
else throw new XpFatal({function: "rankCard()", message: "User not found in database"});
}

const users = await db.find({collection: "simply-xps", data: {guild: guild.id}}) as User[];

const position: number = users.sort((a, b) => b.xp - a.xp).findIndex((u) => u.user === user.id) + 1;
dbUser.position = users.sort((a, b) => b.xp - a.xp).findIndex((u) => u.user === user.id) + 1;

if (options?.legacy) {
const Username = user.username.replace(/[\u007f-\uffff]/g, ""),
Expand Down Expand Up @@ -162,7 +179,7 @@ export async function rankCard(guild: { id: string, name: string }, user: UserOp
context.lineWidth = 15;
context.stroke();
context.clip();
context.drawImage(await loadImage(user.avatarURL), 70, 30, 180, 180);
context.drawImage(avatarURL, 70, 30, 180, 180);
context.restore();

context.save();
Expand Down Expand Up @@ -212,7 +229,7 @@ export async function rankCard(guild: { id: string, name: string }, user: UserOp
context.shadowOffsetX = 1;
context.shadowOffsetY = 1;
context.font = "55px \"Sans Serif\"";
context.fillText("#" + position, canvas.width - 55, 80);
context.fillText("#" + dbUser.position, canvas.width - 55, 80);
context.restore();

context.save();
Expand Down Expand Up @@ -263,7 +280,7 @@ export async function rankCard(guild: { id: string, name: string }, user: UserOp
context.fillText(textXPEdited, 730, 180);

} else {
// TODO: Add support for modern mode\
// TODO: Add support for modern mode

canvas = createCanvas(1080, 360);
}
Expand All @@ -286,13 +303,29 @@ export async function rankCard(guild: { id: string, name: string }, user: UserOp
* @returns {Promise<{attachment: Buffer, description: string, name: string}>}
* @throws {XpFatal} - If parameters are not provided correctly
*/
export async function leaderboardCard(data: Array<User>, options: LeaderboardOptions = {}, guildInfo?: { name: string, imageURL: string, memberCount: number }, locales: LeaderboardLocales = {}): Promise<{ attachment: Buffer; description: string; name: string; }> {
if (!data || data.length < 1) throw new XpFatal({function: "leaderboardCard()", message: "There must be at least 1 user in the data array"});
export async function leaderboardCard(data: Array<User>, options: LeaderboardOptions = {}, guildInfo?: {
name: string,
imageURL: string,
memberCount: number
}, locales: LeaderboardLocales = {}): Promise<{ attachment: Buffer; description: string; name: string; }> {
if (!data || data.length < 1) throw new XpFatal({
function: "leaderboardCard()",
message: "There must be at least 1 user in the data array"
});

if (!cachedLeaderboardArtwork && options?.artworkImage) cachedLeaderboardArtwork = await loadImage(options.artworkImage).catch(() => {
throw new XpFatal({
function: "leaderboardCard()", message: "Unable to load artwork image, is it valid?"
});
});

if (!cachedLeaderboardArtwork && options?.artworkImage) cachedLeaderboardArtwork = await loadImage(options.artworkImage);
if (!cachedLeaderboardImage && options?.backgroundImage) cachedLeaderboardImage = await loadImage(options.backgroundImage);
if (!cachedLeaderboardImage && options?.backgroundImage) cachedLeaderboardImage = await loadImage(options.backgroundImage).catch(() => {
throw new XpFatal({
function: "leaderboardCard()", message: "Unable to load background image, is it valid?"
});
});

GlobalFonts.registerFromPath(options?.font || join(__dirname, "Fonts", "Baloo-Regular.eot"), "Sans Serif");
GlobalFonts.registerFromPath(options?.font || join(__dirname, "Fonts", "BalooBhaijaan-Regular.otf"), "Sans Serif");

if (!locales.level) locales.level = "LEVEL";
if (!locales.members) locales.members = "Members";
Expand Down Expand Up @@ -440,13 +473,20 @@ export async function leaderboardCard(data: Array<User>, options: LeaderboardOpt
};
}

function RoundedBox(ctx: {
/**
* @constructor
* @private
*/
export function RoundedBox(ctx: {
beginPath: () => void;
moveTo: (arg0: number, arg1: number) => void;
lineTo: (arg0: number, arg1: number) => void;
quadraticCurveTo: (arg0: number, arg1: number, arg2: number, arg3: number) => void;
closePath: () => void;
}, x: number, y: number, width: number, height: number, radius: number, roundCorners: { top?: boolean, bottom?: boolean } = {top: true, bottom: true}) {
}, x: number, y: number, width: number, height: number, radius: number, roundCorners: {
top?: boolean,
bottom?: boolean
} = {top: true, bottom: true}) {
ctx.beginPath();
ctx.moveTo(x + (roundCorners.top ? radius : 0), y);
ctx.lineTo(x + width - (roundCorners.top ? radius : 0), y);
Expand Down
Loading

0 comments on commit 02f6769

Please sign in to comment.