@skyhelperbot/utils 2.1.0 → 2.2.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.
Files changed (54) hide show
  1. package/dist/index.js +3 -4
  2. package/dist/{classes → types/classes}/SkytimesUtils.d.ts +4 -5
  3. package/dist/types/classes/index.d.ts +3 -0
  4. package/dist/types/classes/shardsUtil.d.ts +77 -0
  5. package/dist/{classes → types/classes}/utils.d.ts +3 -0
  6. package/dist/types/constants/eventDatas.d.ts +31 -0
  7. package/dist/{constants → types/constants}/index.d.ts +1 -0
  8. package/dist/{constants → types/constants}/shardsInfo.d.ts +12 -16
  9. package/dist/{constants → types/constants}/shardsTimeline.d.ts +3 -2
  10. package/dist/{index.d.ts → types/index.d.ts} +1 -0
  11. package/dist/types/typings.d.ts +29 -0
  12. package/dist/types/utils/PermissionUtils.d.ts +84 -0
  13. package/dist/types/utils/getNextTs.d.ts +10 -0
  14. package/dist/types/utils/index.d.ts +16 -0
  15. package/dist/{utils → types/utils}/parseDateFormat.d.ts +1 -0
  16. package/dist/{utils → types/utils}/parsePerms.d.ts +2 -0
  17. package/dist/{utils → types/utils}/postToBin.d.ts +1 -0
  18. package/dist/{utils → types/utils}/recursiveReadDir.d.ts +1 -0
  19. package/dist/{utils → types/utils}/resolveColors.d.ts +1 -0
  20. package/dist/types/utils/v2-builders.d.ts +14 -0
  21. package/package.json +17 -11
  22. package/dist/classes/LeaderBoardCard.d.ts +0 -59
  23. package/dist/classes/LeaderBoardCard.js +0 -249
  24. package/dist/classes/SkytimesUtils.js +0 -116
  25. package/dist/classes/WinnerCard.d.ts +0 -13
  26. package/dist/classes/WinnerCard.js +0 -117
  27. package/dist/classes/index.d.ts +0 -5
  28. package/dist/classes/index.js +0 -5
  29. package/dist/classes/shardsUtil.d.ts +0 -40
  30. package/dist/classes/shardsUtil.js +0 -122
  31. package/dist/classes/utils.js +0 -28
  32. package/dist/constants/eventDatas.d.ts +0 -31
  33. package/dist/constants/eventDatas.js +0 -105
  34. package/dist/constants/index.js +0 -5
  35. package/dist/constants/shardsInfo.js +0 -424
  36. package/dist/constants/shardsTimeline.js +0 -46
  37. package/dist/typings.d.ts +0 -58
  38. package/dist/typings.js +0 -1
  39. package/dist/utils/index.d.ts +0 -5
  40. package/dist/utils/index.js +0 -5
  41. package/dist/utils/parseDateFormat.js +0 -25
  42. package/dist/utils/parsePerms.js +0 -54
  43. package/dist/utils/postToBin.js +0 -15
  44. package/dist/utils/recursiveReadDir.js +0 -37
  45. package/dist/utils/resolveColors.js +0 -63
  46. package/shared/assets/Point.png +0 -0
  47. package/shared/assets/Win.png +0 -0
  48. package/shared/assets/medal_champion_award_winner_olympic_icon_207790.png +0 -0
  49. package/shared/assets/server.svg +0 -41
  50. package/shared/fonts/circularstd-black.otf +0 -0
  51. package/shared/fonts/notoemoji-bold.ttf +0 -0
  52. package/shared/fonts/notosans-black.ttf +0 -0
  53. package/shared/fonts/notosans-jp-black.ttf +0 -0
  54. package/shared/fonts/notosans-kr-black.ttf +0 -0
@@ -1,59 +0,0 @@
1
- import type { userData, colorsType, LeaderboardOptions } from "../typings.js";
2
- /**
3
- * Represents a Quiz Leaderboard Card. A class for generating a leaderboard card for a quiz or game.
4
- * @returns - The generated image buffer.
5
- */
6
- export declare class LeaderboardCard {
7
- private usersData;
8
- private background;
9
- private abbreviateNumber;
10
- private opacity;
11
- private scoreMessage;
12
- private colors;
13
- constructor(options: LeaderboardOptions);
14
- /**
15
- * .setUsersData
16
- * @param usersData ```js
17
- * [{ top: int, avatar: "string", tag: "string", score: int}, games: int]
18
- * ```
19
- * @example setUsersData([{top:1,avatar:"https://someone-image.png",tag:"fivesobes",score:5, games:8}])
20
- */
21
- setUsersData(usersData: userData[]): this;
22
- /**
23
- * .setScoreMessage
24
- * @param message Set Custom Score Message
25
- * @example setScoreMessage("Message")
26
- */
27
- setScoreMessage(message: string): this;
28
- /**
29
- * .setColors
30
- * @param colors ```json
31
- * {box: "hexcolor", username: "hexcolor", score: "hexcolor", firstRank: "hexcolor", secondRank: "hexcolor", thirdRank: "hexcolor"}
32
- * ```
33
- * @example
34
- * setColors({ box: '#212121', username: '#ffffff', score: '#ffffff', firstRank: '#f7c716', secondRank: '#9e9e9e', thirdRank: '#94610f' })
35
- */
36
- setColors(colors: colorsType): this;
37
- /**
38
- * .setabbreviateNumber
39
- * @param bool must be "true" or "false"
40
- * @example setabbreviateNumber(true)
41
- */
42
- setabbreviateNumber(bool: boolean): this;
43
- /**
44
- * .setOpacity
45
- * @param opacity must be between 0 and 1
46
- * @example setOpacity(0.6)
47
- */
48
- setOpacity(opacity?: number): this;
49
- /**
50
- * .setBackground
51
- * @param type "image" or "color"
52
- * @param value "url" or "hexcolor"
53
- * @example setBackground("image","https://someone-image.png")
54
- * @example setBackground("color","#000")
55
- */
56
- setBackground(type: string, value: string): this;
57
- build(): Promise<Buffer>;
58
- private fillRoundRect;
59
- }
@@ -1,249 +0,0 @@
1
- import { createCanvas, loadImage, GlobalFonts } from "@napi-rs/canvas";
2
- import * as path from "node:path";
3
- /**
4
- * Represents a Quiz Leaderboard Card. A class for generating a leaderboard card for a quiz or game.
5
- * @returns - The generated image buffer.
6
- */
7
- export class LeaderboardCard {
8
- usersData;
9
- background;
10
- abbreviateNumber;
11
- opacity;
12
- scoreMessage;
13
- colors;
14
- constructor(options) {
15
- this.usersData = options?.usersData || [];
16
- this.background = {
17
- type: "none",
18
- background: "none",
19
- };
20
- this.abbreviateNumber = false;
21
- this.opacity = 0;
22
- this.scoreMessage = "";
23
- this.colors = options?.colors || {
24
- box: "#212121",
25
- username: "#ffffff",
26
- score: "#ffffff",
27
- firstRank: "#f7c716",
28
- secondRank: "#9e9e9e",
29
- thirdRank: "#94610f",
30
- };
31
- }
32
- /**
33
- * .setUsersData
34
- * @param usersData ```js
35
- * [{ top: int, avatar: "string", tag: "string", score: int}, games: int]
36
- * ```
37
- * @example setUsersData([{top:1,avatar:"https://someone-image.png",tag:"fivesobes",score:5, games:8}])
38
- */
39
- setUsersData(usersData) {
40
- if (usersData.length > 10) {
41
- throw new Error("setUsersData values cannot be greater than 10.");
42
- }
43
- this.usersData = usersData;
44
- return this;
45
- }
46
- /**
47
- * .setScoreMessage
48
- * @param message Set Custom Score Message
49
- * @example setScoreMessage("Message")
50
- */
51
- setScoreMessage(message) {
52
- this.scoreMessage = message;
53
- return this;
54
- }
55
- /**
56
- * .setColors
57
- * @param colors ```json
58
- * {box: "hexcolor", username: "hexcolor", score: "hexcolor", firstRank: "hexcolor", secondRank: "hexcolor", thirdRank: "hexcolor"}
59
- * ```
60
- * @example
61
- * setColors({ box: '#212121', username: '#ffffff', score: '#ffffff', firstRank: '#f7c716', secondRank: '#9e9e9e', thirdRank: '#94610f' })
62
- */
63
- setColors(colors) {
64
- this.colors = colors;
65
- return this;
66
- }
67
- /**
68
- * .setabbreviateNumber
69
- * @param bool must be "true" or "false"
70
- * @example setabbreviateNumber(true)
71
- */
72
- setabbreviateNumber(bool) {
73
- if (typeof bool !== "boolean") {
74
- throw new Error("You must give a abbreviate number true or false argument.");
75
- }
76
- this.abbreviateNumber = bool;
77
- return this;
78
- }
79
- /**
80
- * .setOpacity
81
- * @param opacity must be between 0 and 1
82
- * @example setOpacity(0.6)
83
- */
84
- setOpacity(opacity = 0) {
85
- if (opacity >= 0 && opacity <= 1) {
86
- this.opacity = opacity;
87
- return this;
88
- }
89
- else {
90
- throw new Error("The value of the opacity of setOpacity method must be between 0 and 1 (0 and 1 included).");
91
- }
92
- }
93
- /**
94
- * .setBackground
95
- * @param type "image" or "color"
96
- * @param value "url" or "hexcolor"
97
- * @example setBackground("image","https://someone-image.png")
98
- * @example setBackground("color","#000")
99
- */
100
- setBackground(type, value) {
101
- if (type === "color") {
102
- if (/^#([a-fA-F0-9]{6}|[a-fA-F0-9]{3})$/.test(value)) {
103
- this.background.type = "color";
104
- this.background.background = value;
105
- return this;
106
- }
107
- else {
108
- throw new Error("Invalid color for the second argument in setForeground method. You must give a hexadecimal color.");
109
- }
110
- }
111
- else if (type === "image") {
112
- this.background.type = "image";
113
- this.background.background = value;
114
- return this;
115
- }
116
- else {
117
- throw new Error("The first argument of setBackground must be 'color' or 'image'.");
118
- }
119
- }
120
- async build() {
121
- GlobalFonts.registerFromPath(path.join(import.meta.dirname, `../../shared/fonts/circularstd-black.otf`), "circular-std");
122
- GlobalFonts.registerFromPath(path.join(import.meta.dirname, `../../shared/fonts/notosans-jp-black.ttf`), "noto-sans-jp");
123
- GlobalFonts.registerFromPath(path.join(import.meta.dirname, `../../shared/fonts/notosans-black.ttf`), "noto-sans");
124
- GlobalFonts.registerFromPath(path.join(import.meta.dirname, `../../shared/fonts/notoemoji-bold.ttf`), "noto-emoji");
125
- GlobalFonts.registerFromPath(path.join(import.meta.dirname, `../../shared/fonts/notosans-kr-black.ttf`), "noto-sans-kr");
126
- const abbreviateNumber = (value) => {
127
- let newValue = value;
128
- if (value >= 1000) {
129
- const suffixes = ["", "K", "M", "B", "T"];
130
- const suffixNum = Math.floor(("" + value).length / 3);
131
- let shortValue = "";
132
- for (let precision = 2; precision >= 1; precision--) {
133
- shortValue = parseFloat((suffixNum != 0 ? value / Math.pow(1000, suffixNum) : value).toPrecision(precision));
134
- const dotLessShortValue = (shortValue + "").replace(/[^a-zA-Z 0-9]+/g, "");
135
- if (dotLessShortValue.length <= 2) {
136
- break;
137
- }
138
- }
139
- if (typeof shortValue === "number" && shortValue % 1 != 0)
140
- shortValue = shortValue.toFixed(1);
141
- newValue = shortValue + suffixes[suffixNum];
142
- }
143
- return newValue.toString();
144
- };
145
- const yuksek = this.usersData.length * 74.5;
146
- const canvas = createCanvas(680, yuksek);
147
- const ctx = canvas.getContext("2d");
148
- ctx.globalAlpha = 1;
149
- if (this.background.type === "color") {
150
- ctx.fillStyle = this.background.background;
151
- ctx.fillRect(0, 0, canvas.width, canvas.height);
152
- }
153
- else if (this.background.type === "image") {
154
- try {
155
- ctx.drawImage(await loadImage(this.background.background), 0, 0, canvas.width, canvas.height);
156
- }
157
- catch {
158
- throw new Error("The image given in the second parameter of the setBackground method is not valid or you are not connected to the internet.");
159
- }
160
- }
161
- if (this.usersData) {
162
- let Box_Y = 0, Avatar_Y = 0, Tag_Y = 45, XP_Y = 45, Level_Y = 30, Rank_Y = 45;
163
- for (let i = 0; i < this.usersData.length; i++) {
164
- ctx.save();
165
- ctx.fillStyle = this.colors.box;
166
- ctx.globalAlpha = this.opacity;
167
- this.fillRoundRect(ctx, 0, Box_Y, canvas.width, 70, 15, true, false);
168
- ctx.globalAlpha = 1;
169
- try {
170
- const avatar = await loadImage(this.usersData[i].avatar);
171
- ctx.clip();
172
- ctx.drawImage(avatar, 0, Avatar_Y, 70, 70);
173
- }
174
- catch (err) {
175
- console.error("Failed to load avatar", err);
176
- }
177
- ctx.shadowBlur = 10;
178
- ctx.shadowOffsetX = 8;
179
- ctx.shadowOffsetY = 6;
180
- ctx.shadowColor = "#0a0a0a";
181
- ctx.fillStyle = this.colors.username;
182
- ctx.font = `bold 25px circular-std, noto-emoji, noto-sans-jp, noto-sans, noto-sans-kr`;
183
- ctx.textAlign = "left";
184
- ctx.fillText(this.usersData[i].tag, 80, Tag_Y, 260);
185
- ctx.fillStyle = this.colors.score;
186
- ctx.font = `bold 20px circular-std, noto-emoji, noto-sans-jp, noto-sans, noto-sans-kr`;
187
- ctx.textAlign = "right";
188
- ctx.fillText(`${this.scoreMessage} ${this.abbreviateNumber == true ? `${abbreviateNumber(this.usersData[i].score)}` : `${this.usersData[i].score}`}/${this.abbreviateNumber == true ? `${abbreviateNumber(this.usersData[i].games)}` : `${this.usersData[i].games}`}`, 560, XP_Y, 200);
189
- if (this.usersData[i].top === 1) {
190
- ctx.fillStyle = this.colors.firstRank;
191
- }
192
- else if (this.usersData[i].top === 2) {
193
- ctx.fillStyle = this.colors.secondRank;
194
- }
195
- else if (this.usersData[i].top === 3) {
196
- ctx.fillStyle = this.colors.thirdRank;
197
- }
198
- ctx.font = `bold 30px circular-std, noto-emoji, noto-sans-jp, noto-sans, noto-sans-kr`;
199
- ctx.textAlign = "right";
200
- ctx.fillText("#" + this.usersData[i].top, 660, Rank_Y, 75);
201
- Box_Y = Box_Y + 75;
202
- Avatar_Y = Avatar_Y + 75;
203
- Tag_Y = Tag_Y + 75;
204
- XP_Y = XP_Y + 75;
205
- Level_Y = Level_Y + 75;
206
- Rank_Y = Rank_Y + 75;
207
- ctx.restore();
208
- }
209
- }
210
- else {
211
- ctx.font = `bold 40px circular-std, noto-emoji, noto-sans-jp, noto-sans, noto-sans-kr`;
212
- ctx.fillStyle = "#ffffff";
213
- ctx.textAlign = "center";
214
- ctx.shadowBlur = 10;
215
- ctx.shadowOffsetX = 8;
216
- ctx.shadowOffsetY = 6;
217
- ctx.shadowColor = "#0a0a0a";
218
- ctx.fillText("Not found!", 340, 370, 500);
219
- }
220
- return canvas.toBuffer("image/png");
221
- }
222
- fillRoundRect(ctx, x, y, w, h, r, f, s) {
223
- if (typeof r === "number") {
224
- r = { tl: r, tr: r, br: r, bl: r };
225
- }
226
- else {
227
- const defaultRadius = { tl: 0, tr: 0, br: 0, bl: 0 };
228
- for (const side in defaultRadius) {
229
- r[side] =
230
- r[side] || defaultRadius[side];
231
- }
232
- }
233
- ctx.beginPath();
234
- ctx.moveTo(x + r.tl, y);
235
- ctx.lineTo(x + w - r.tr, y);
236
- ctx.quadraticCurveTo(x + w, y, x + w, y + r.tr);
237
- ctx.lineTo(x + w, y + h - r.br);
238
- ctx.quadraticCurveTo(x + w, y + h, x + w - r.br, y + h);
239
- ctx.lineTo(x + r.bl, y + h);
240
- ctx.quadraticCurveTo(x, y + h, x, y + h - r.bl);
241
- ctx.lineTo(x, y + r.tl);
242
- ctx.quadraticCurveTo(x, y, x + r.tl, y);
243
- ctx.closePath();
244
- if (f)
245
- ctx.fill();
246
- if (s)
247
- ctx.stroke();
248
- }
249
- }
@@ -1,116 +0,0 @@
1
- import { eventData } from "../constants/eventDatas.js";
2
- import { DateTime } from "luxon";
3
- /**
4
- * Utilities for skytimes
5
- */
6
- export class SkytimesUtils {
7
- /** Get all occurrences of an event for the given date
8
- * @param eventTime The DateTime for which to get all occurrences
9
- * @param interval The interval between the event occurrences
10
- */
11
- static getAllTimes(eventTime, interval) {
12
- let clonedTime = eventTime;
13
- const timeBuilt = [];
14
- while (eventTime.hasSame(clonedTime, "day")) {
15
- timeBuilt.push(`<t:${clonedTime.toUnixInteger()}:t>`);
16
- clonedTime = clonedTime.plus({ minutes: interval || 0 });
17
- }
18
- return timeBuilt.join(" • ");
19
- }
20
- /**
21
- * Get the date in DateTime on which the event will occur (if it's not a daily event)
22
- * @param event The event for which to get the date-time
23
- */
24
- static getOccurrenceDay(event) {
25
- let nextOccurrence = DateTime.now().setZone("America/Los_Angeles").startOf("day").plus({ minutes: event.offset }); // Start with the offset from the beginning of the day
26
- if (event.occursOn) {
27
- // If the event occurs on specific weekdays
28
- if (event.occursOn.weekDays) {
29
- while (!event.occursOn.weekDays.includes(nextOccurrence.weekday)) {
30
- nextOccurrence = nextOccurrence.plus({ days: 1 });
31
- }
32
- }
33
- // If the event occurs on a specific day of the month
34
- if (event.occursOn.dayOfTheMonth) {
35
- while (nextOccurrence.day !== event.occursOn.dayOfTheMonth) {
36
- nextOccurrence = nextOccurrence.plus({ days: 1 });
37
- }
38
- }
39
- }
40
- return nextOccurrence;
41
- }
42
- /**
43
- * Get the next occurrence of the event relative to now
44
- * @param eventName The key of the event
45
- */
46
- static getNextEventOccurrence(eventName) {
47
- const event = eventData[eventName];
48
- if (!event)
49
- throw new Error("Unknown Event");
50
- const now = DateTime.now().setZone("America/Los_Angeles"); // Current time
51
- let nextOccurrence = this.getOccurrenceDay(event);
52
- // Loop to calculate the next occurrence based on the interval
53
- while (nextOccurrence < now) {
54
- nextOccurrence = nextOccurrence.plus({ minutes: event.interval || 0 });
55
- }
56
- return nextOccurrence;
57
- }
58
- /**
59
- * Get the details about an event, their status, next occurrence, all occurrences for the day
60
- * @param key The event key
61
- */
62
- static getEventDetails(key) {
63
- const nextOccurence = this.getNextEventOccurrence(key);
64
- return {
65
- event: eventData[key],
66
- nextOccurence,
67
- allOccurences: this.getAllTimes(this.getOccurrenceDay(eventData[key]), eventData[key].interval),
68
- status: this.getEventStatus(eventData[key], nextOccurence),
69
- };
70
- }
71
- /**
72
- * Same as {@apilink SkytimesUtils.getEventDetails | getEventDetails} but for all of the events
73
- * @returns An array of event details
74
- */
75
- static allEventDetails() {
76
- const keys = Object.keys(eventData).sort((a, b) => eventData[a].index - eventData[b].index);
77
- const occurrences = [];
78
- for (const key of keys) {
79
- occurrences.push([key, this.getEventDetails(key)]);
80
- }
81
- return occurrences;
82
- }
83
- /**
84
- * Returns the event status of a given event
85
- * @param event The event to get the status for
86
- * @param nextOccurrence The next occurrence of the event relative to "now"
87
- * @returns The event status (or null if there is no active duration)
88
- */
89
- static getEventStatus(event, nextOccurrence) {
90
- const now = DateTime.now().setZone("America/Los_Angeles");
91
- const BASE = {
92
- active: false,
93
- nextTime: nextOccurrence,
94
- duration: nextOccurrence.diff(now).toFormat("d'd' h'h' m'm' s's'"),
95
- };
96
- if (!event.duration)
97
- return BASE;
98
- // Subtract the interval because nextOccurrence always calculates the next upcoming event
99
- // So we subtract the interval to get the last occurrence, and add the active duration to it, and check if now is between those
100
- const start = nextOccurrence.minus({ minutes: event.interval || 0 });
101
- const end = start.plus({ minutes: event.duration });
102
- // When active
103
- if (now >= start && now <= end) {
104
- return {
105
- active: true,
106
- startTime: start,
107
- endTime: end,
108
- nextTime: nextOccurrence,
109
- duration: end.diff(now).toFormat("d'd' h'h' m'm' s's'"),
110
- };
111
- }
112
- else {
113
- return BASE;
114
- }
115
- }
116
- }
@@ -1,13 +0,0 @@
1
- import type { APIGuildMember, APIUser } from "discord-api-types/v10";
2
- export declare class GameWinnerCard {
3
- readonly clientAvatar: string;
4
- private name;
5
- private thumbnail;
6
- private points;
7
- private total;
8
- constructor(winner: APIUser | APIGuildMember, wins: number, total: number, clientAvatar: string);
9
- private path;
10
- private roundRect;
11
- private changeFontSize;
12
- build(): Promise<Buffer>;
13
- }
@@ -1,117 +0,0 @@
1
- import { createCanvas, loadImage } from "@napi-rs/canvas";
2
- import { colors, fancyCount, getUserAvatar } from "./utils.js";
3
- import { join } from "path";
4
- const size = 100;
5
- // TODO: Integrate it with other game types
6
- export class GameWinnerCard {
7
- clientAvatar;
8
- name;
9
- thumbnail;
10
- points;
11
- total;
12
- constructor(winner, wins, total, clientAvatar) {
13
- this.clientAvatar = clientAvatar;
14
- if ("user" in winner) {
15
- this.name = winner.nick || winner.user?.global_name || winner?.user.username;
16
- this.thumbnail = getUserAvatar(winner.user);
17
- }
18
- else {
19
- this.name = winner?.global_name || winner?.username;
20
- this.thumbnail = getUserAvatar(winner);
21
- }
22
- this.points = wins;
23
- this.total = total;
24
- }
25
- path(strs) {
26
- return join(import.meta.dirname, strs);
27
- }
28
- roundRect(ctx, x, y, w, h, r) {
29
- if (w < 2 * r)
30
- r = w / 2;
31
- if (h < 2 * r)
32
- r = h / 2;
33
- ctx.beginPath();
34
- ctx.moveTo(x + r, y);
35
- ctx.arcTo(x + w, y, x + w, y + h, r);
36
- ctx.arcTo(x + w, y + h, x, y + h, r);
37
- ctx.arcTo(x, y + h, x, y, r);
38
- ctx.arcTo(x, y, x + w, y, r);
39
- ctx.closePath();
40
- return ctx;
41
- }
42
- changeFontSize(ctx, _size) {
43
- const fontArgs = ctx.font.split(" ");
44
- ctx.font = `${_size} ${fontArgs.slice(1).join(" ")}`; // / using the last part
45
- return ctx;
46
- }
47
- async build() {
48
- const canvas = createCanvas(16 * size, 5 * size);
49
- const ctx = canvas.getContext("2d");
50
- const { width: w, height: h } = canvas;
51
- ctx.font = "85px SegoeUI, SegoeUIEmoji";
52
- ctx.fillStyle = colors.darkgrey;
53
- this.roundRect(ctx, 0, 0, w, h, size * 0.75).clip();
54
- ctx.fill();
55
- // box-shadow: 0px 4px 4px rgba(0, 0, 0, 0.25);
56
- // ctx.shadowOffsetY = 40;
57
- // ctx.shadowColor = 'rgba(0, 0, 0, 0.25)';
58
- // ctx.shadowOffsetX = 40;
59
- // Avatar
60
- //
61
- ctx.save();
62
- ctx.lineWidth = 6;
63
- ctx.beginPath();
64
- ctx.arc(h / 2, h / 2, h * 0.3, 0, Math.PI * 2, true);
65
- ctx.closePath();
66
- ctx.clip();
67
- ctx.fillStyle = colors.grey;
68
- ctx.fillRect(h * 0.2, h * 0.2, h * 0.6, h * 0.6);
69
- ctx.drawImage(await loadImage(this.thumbnail), h * 0.2, h * 0.2, h * 0.6, h * 0.6);
70
- ctx.restore();
71
- // Status
72
- ctx.save();
73
- ctx.translate(size * 3.55, size * 3.55);
74
- ctx.fillStyle = colors.darkgrey;
75
- ctx.beginPath();
76
- ctx.arc(0, 0, size * 0.4, 0, Math.PI * 2, true);
77
- ctx.closePath();
78
- ctx.fill();
79
- ctx.drawImage(await loadImage(this.path("../../shared/assets/Win.png")), -size * 0.3, -size * 0.3, size * 0.6, size * 0.6);
80
- ctx.restore();
81
- // User Text
82
- //
83
- ctx.fillStyle = colors.blue;
84
- this.changeFontSize(ctx, h * 0.17 + "px");
85
- ctx.fillText(this.name, w * 0.3, h * 0.45, w * 0.425);
86
- ctx.fillStyle = colors.idle;
87
- ctx.fillText("#", w * 0.3 + w * 0.4375, h * 0.45);
88
- ctx.fillStyle = colors.online;
89
- ctx.fillText("1", w * 0.3 + w * 0.425 + w * 0.05, h * 0.45, w * 0.15625);
90
- // Botlist URL
91
- //
92
- // ctx.textBaseline = 'middle';
93
- ctx.textAlign = "center";
94
- ctx.fillStyle = colors.blue;
95
- this.roundRect(ctx, w * 0.5, -(w * 0.0625), w * 0.5, h * 0.4, w * 0.0625);
96
- ctx.fill();
97
- ctx.fillRect(w * 0.625, 0, w * 0.5, w * 0.0625);
98
- ctx.fillStyle = colors.darkgrey;
99
- this.changeFontSize(ctx, h * 0.15 + "px");
100
- ctx.fillText("Sky CoTL Quiz Game", w * 0.55 + h * 0.65, h * 0.15, w * 0.421875);
101
- // Counters
102
- //
103
- ctx.textAlign = "left";
104
- ctx.fillStyle = colors.lightgrey;
105
- ctx.drawImage(await loadImage(this.path("../../shared/assets/Point.png")), w * 0.3, h * 0.65, w * 0.0625, w * 0.0625);
106
- this.changeFontSize(ctx, h * 0.15 + "px");
107
- ctx.fillText(`${fancyCount(this.points)}/${fancyCount(this.total)} points`, w * 0.25 + h * 0.45, h * 0.65 + h * 0.15, h * 10);
108
- // ctx.drawImage(await loadImage(this.path('../../shared/assets/vote.svg')), w * 0.6, h * 0.65, w * 0.0625, w * 0.0625);
109
- // ctx.fillText(fancyCount(this.total), w * 0.55 + h * 0.45, h * 0.65 + h * 0.15, h * 0.45);
110
- // Library
111
- ctx.fillStyle = colors.grey;
112
- this.roundRect(ctx, w * 0.875, h * 0.6, h * 0.4, h * 0.4, h * 0.15).clip();
113
- ctx.fill();
114
- ctx.drawImage(await loadImage(this.clientAvatar), w * 0.875, h * 0.6, h * 0.4, h * 0.4);
115
- return canvas.toBuffer("image/png");
116
- }
117
- }
@@ -1,5 +0,0 @@
1
- export { LeaderboardCard } from "./LeaderBoardCard.js";
2
- export { GameWinnerCard } from "./WinnerCard.js";
3
- export { ShardsUtil } from "./shardsUtil.js";
4
- export { SkytimesUtils } from "./SkytimesUtils.js";
5
- export * from "./SkytimesUtils.js";
@@ -1,5 +0,0 @@
1
- export { LeaderboardCard } from "./LeaderBoardCard.js";
2
- export { GameWinnerCard } from "./WinnerCard.js";
3
- export { ShardsUtil } from "./shardsUtil.js";
4
- export { SkytimesUtils } from "./SkytimesUtils.js";
5
- export * from "./SkytimesUtils.js";
@@ -1,40 +0,0 @@
1
- import { DateTime } from "luxon";
2
- import type { ShardsCountdown } from "../typings.js";
3
- /**
4
- * Sequence of Shards pattern
5
- */
6
- declare const shardSequence: readonly ["C", "b", "A", "a", "B", "b", "C", "a", "A", "b", "B", "a"];
7
- /**
8
- * Sequence of realms pattern of shard
9
- */
10
- declare const realmSequence: readonly ["prairie", "forest", "valley", "wasteland", "vault"];
11
- /**
12
- * @class shardsUtil
13
- * @classdesc A class to handle shards and realms indexing.
14
- */
15
- export declare class ShardsUtil {
16
- /**
17
- * @method getDate - get provided date in luxon
18
- * @param date - date to get in moment
19
- */
20
- static getDate(date?: string | undefined | null): DateTime | string;
21
- /**
22
- * Returns shards index for a given date
23
- * @param date
24
- */
25
- static shardsIndex(date: DateTime): {
26
- currentShard: (typeof shardSequence)[number];
27
- currentRealm: (typeof realmSequence)[number];
28
- };
29
- /**
30
- * Returns suffix for a given number
31
- * @param number The number to get the suffix for
32
- */
33
- static getSuffix(number: number): string;
34
- /**
35
- * Get all three shards status for a given date relative to the current time
36
- * @param date The date for which to get the status for
37
- */
38
- static getStatus(date: DateTime): ShardsCountdown[] | "No Shard";
39
- }
40
- export {};