@skyhelperbot/utils 2.0.1 → 2.0.2-dev
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/dist/classes/LeaderBoardCard.js +5 -5
- package/dist/classes/SkytimesUtils.d.ts +17 -18
- package/dist/classes/SkytimesUtils.js +38 -41
- package/dist/classes/WinnerCard.d.ts +3 -3
- package/dist/classes/WinnerCard.js +12 -13
- package/dist/classes/index.d.ts +0 -2
- package/dist/classes/index.js +0 -2
- package/dist/classes/shardsUtil.d.ts +5 -5
- package/dist/classes/shardsUtil.js +15 -14
- package/dist/classes/utils.d.ts +2 -0
- package/dist/classes/utils.js +6 -0
- package/dist/constants/shardsInfo.js +2 -2
- package/dist/constants/shardsTimeline.d.ts +6 -6
- package/dist/constants/shardsTimeline.js +4 -15
- package/dist/index.d.ts +1 -2
- package/dist/index.js +1 -2
- package/dist/typings.d.ts +5 -9
- package/dist/typings.js +0 -2
- package/dist/utils/index.d.ts +5 -5
- package/dist/utils/index.js +5 -5
- package/dist/utils/resolveColors.d.ts +79 -0
- package/dist/utils/resolveColors.js +63 -0
- package/package.json +8 -4
|
@@ -118,11 +118,11 @@ export class LeaderboardCard {
|
|
|
118
118
|
}
|
|
119
119
|
}
|
|
120
120
|
async build() {
|
|
121
|
-
GlobalFonts.registerFromPath(path.join(
|
|
122
|
-
GlobalFonts.registerFromPath(path.join(
|
|
123
|
-
GlobalFonts.registerFromPath(path.join(
|
|
124
|
-
GlobalFonts.registerFromPath(path.join(
|
|
125
|
-
GlobalFonts.registerFromPath(path.join(
|
|
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
126
|
const abbreviateNumber = (value) => {
|
|
127
127
|
let newValue = value;
|
|
128
128
|
if (value >= 1000) {
|
|
@@ -1,28 +1,27 @@
|
|
|
1
|
-
import moment from "moment-timezone";
|
|
2
|
-
import "moment-duration-format";
|
|
3
1
|
import { eventData } from "../constants/eventDatas.js";
|
|
2
|
+
import { DateTime } from "luxon";
|
|
4
3
|
type EventKey = keyof typeof eventData;
|
|
5
4
|
/**
|
|
6
5
|
* Utilities for skytimes
|
|
7
6
|
*/
|
|
8
7
|
export declare class SkytimesUtils {
|
|
9
|
-
/** Get all
|
|
10
|
-
* @param eventTime The
|
|
11
|
-
* @param interval The interval between the event
|
|
8
|
+
/** Get all occurrences of an event for the given date
|
|
9
|
+
* @param eventTime The DateTime for which to get all occurrences
|
|
10
|
+
* @param interval The interval between the event occurrences
|
|
12
11
|
*/
|
|
13
|
-
static getAllTimes(eventTime:
|
|
12
|
+
static getAllTimes(eventTime: DateTime, interval?: number): string;
|
|
14
13
|
/**
|
|
15
|
-
* Get the date in
|
|
14
|
+
* Get the date in DateTime on which the event will occur (if it's not a daily event)
|
|
16
15
|
* @param event The event for which to get the date-time
|
|
17
16
|
*/
|
|
18
|
-
private static
|
|
17
|
+
private static getOccurrenceDay;
|
|
19
18
|
/**
|
|
20
|
-
* Get the next
|
|
19
|
+
* Get the next occurrence of the event relative to now
|
|
21
20
|
* @param eventName The key of the event
|
|
22
21
|
*/
|
|
23
22
|
private static getNextEventOccurrence;
|
|
24
23
|
/**
|
|
25
|
-
* Get the details about an event, their status, next
|
|
24
|
+
* Get the details about an event, their status, next occurrence, all occurrences for the day
|
|
26
25
|
* @param key The event key
|
|
27
26
|
*/
|
|
28
27
|
static getEventDetails(key: EventKey): EventDetails;
|
|
@@ -34,16 +33,16 @@ export declare class SkytimesUtils {
|
|
|
34
33
|
/**
|
|
35
34
|
* Returns the event status of a given event
|
|
36
35
|
* @param event The event to get the status for
|
|
37
|
-
* @param
|
|
36
|
+
* @param nextOccurrence The next occurrence of the event relative to "now"
|
|
38
37
|
* @returns The event status (or null if there is no active duration)
|
|
39
38
|
*/
|
|
40
|
-
static getEventStatus(event: (typeof eventData)[keyof typeof eventData],
|
|
39
|
+
static getEventStatus(event: (typeof eventData)[keyof typeof eventData], nextOccurrence: DateTime): Times;
|
|
41
40
|
}
|
|
42
41
|
export interface BaseTimes {
|
|
43
42
|
/** Whether the event is active or not */
|
|
44
43
|
active: boolean;
|
|
45
44
|
/** The time when the event starts */
|
|
46
|
-
nextTime:
|
|
45
|
+
nextTime: DateTime;
|
|
47
46
|
/** This will be the countdown for when the event ends if it's active,
|
|
48
47
|
* otherwise it'll be the countdown to the next occurence
|
|
49
48
|
*/
|
|
@@ -52,21 +51,21 @@ export interface BaseTimes {
|
|
|
52
51
|
export interface ActiveTimes extends BaseTimes {
|
|
53
52
|
active: true;
|
|
54
53
|
/** The time when the event started if active */
|
|
55
|
-
startTime:
|
|
54
|
+
startTime: DateTime;
|
|
56
55
|
/** The time when the event ends if active */
|
|
57
|
-
endTime:
|
|
56
|
+
endTime: DateTime;
|
|
58
57
|
}
|
|
59
58
|
export interface NotActiveTimes extends BaseTimes {
|
|
60
59
|
active: false;
|
|
61
60
|
/** The time when the event started if active */
|
|
62
|
-
startTime?:
|
|
61
|
+
startTime?: DateTime;
|
|
63
62
|
/** The time when the event ends if active */
|
|
64
|
-
endTime?:
|
|
63
|
+
endTime?: DateTime;
|
|
65
64
|
}
|
|
66
65
|
export type Times = ActiveTimes | NotActiveTimes;
|
|
67
66
|
export interface EventDetails {
|
|
68
67
|
event: (typeof eventData)[EventKey];
|
|
69
|
-
nextOccurence:
|
|
68
|
+
nextOccurence: DateTime;
|
|
70
69
|
allOccurences: string;
|
|
71
70
|
status: Times;
|
|
72
71
|
}
|
|
@@ -1,64 +1,62 @@
|
|
|
1
|
-
import { Base, time } from "discord.js";
|
|
2
|
-
import moment from "moment-timezone";
|
|
3
|
-
import "moment-duration-format";
|
|
4
1
|
import { eventData } from "../constants/eventDatas.js";
|
|
2
|
+
import { DateTime } from "luxon";
|
|
5
3
|
/**
|
|
6
4
|
* Utilities for skytimes
|
|
7
5
|
*/
|
|
8
6
|
export class SkytimesUtils {
|
|
9
|
-
/** Get all
|
|
10
|
-
* @param eventTime The
|
|
11
|
-
* @param interval The interval between the event
|
|
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
|
|
12
10
|
*/
|
|
13
11
|
static getAllTimes(eventTime, interval) {
|
|
14
|
-
|
|
12
|
+
let clonedTime = eventTime;
|
|
15
13
|
const timeBuilt = [];
|
|
16
|
-
while (eventTime.
|
|
17
|
-
timeBuilt.push(
|
|
18
|
-
clonedTime.
|
|
14
|
+
while (eventTime.hasSame(clonedTime, "day")) {
|
|
15
|
+
timeBuilt.push(`<t:${clonedTime.toUnixInteger()}:t>`);
|
|
16
|
+
clonedTime = clonedTime.plus({ minutes: interval || 0 });
|
|
19
17
|
}
|
|
20
18
|
return timeBuilt.join(" • ");
|
|
21
19
|
}
|
|
22
20
|
/**
|
|
23
|
-
* Get the date in
|
|
21
|
+
* Get the date in DateTime on which the event will occur (if it's not a daily event)
|
|
24
22
|
* @param event The event for which to get the date-time
|
|
25
23
|
*/
|
|
26
|
-
static
|
|
27
|
-
|
|
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
|
|
28
26
|
if (event.occursOn) {
|
|
29
27
|
// If the event occurs on specific weekdays
|
|
30
28
|
if (event.occursOn.weekDays) {
|
|
31
|
-
while (!event.occursOn.weekDays.includes(nextOccurrence.
|
|
32
|
-
nextOccurrence.
|
|
29
|
+
while (!event.occursOn.weekDays.includes(nextOccurrence.weekday)) {
|
|
30
|
+
nextOccurrence = nextOccurrence.plus({ days: 1 });
|
|
33
31
|
}
|
|
34
32
|
}
|
|
35
33
|
// If the event occurs on a specific day of the month
|
|
36
34
|
if (event.occursOn.dayOfTheMonth) {
|
|
37
|
-
while (nextOccurrence.
|
|
38
|
-
nextOccurrence.
|
|
35
|
+
while (nextOccurrence.day !== event.occursOn.dayOfTheMonth) {
|
|
36
|
+
nextOccurrence = nextOccurrence.plus({ days: 1 });
|
|
39
37
|
}
|
|
40
38
|
}
|
|
41
39
|
}
|
|
42
40
|
return nextOccurrence;
|
|
43
41
|
}
|
|
44
42
|
/**
|
|
45
|
-
* Get the next
|
|
43
|
+
* Get the next occurrence of the event relative to now
|
|
46
44
|
* @param eventName The key of the event
|
|
47
45
|
*/
|
|
48
46
|
static getNextEventOccurrence(eventName) {
|
|
49
47
|
const event = eventData[eventName];
|
|
50
48
|
if (!event)
|
|
51
|
-
throw new Error("
|
|
52
|
-
const now =
|
|
53
|
-
|
|
49
|
+
throw new Error("Unknown Event");
|
|
50
|
+
const now = DateTime.now().setZone("America/Los_Angeles"); // Current time
|
|
51
|
+
let nextOccurrence = this.getOccurrenceDay(event);
|
|
54
52
|
// Loop to calculate the next occurrence based on the interval
|
|
55
|
-
while (nextOccurrence
|
|
56
|
-
nextOccurrence.
|
|
53
|
+
while (nextOccurrence < now) {
|
|
54
|
+
nextOccurrence = nextOccurrence.plus({ minutes: event.interval || 0 });
|
|
57
55
|
}
|
|
58
56
|
return nextOccurrence;
|
|
59
57
|
}
|
|
60
58
|
/**
|
|
61
|
-
* Get the details about an event, their status, next
|
|
59
|
+
* Get the details about an event, their status, next occurrence, all occurrences for the day
|
|
62
60
|
* @param key The event key
|
|
63
61
|
*/
|
|
64
62
|
static getEventDetails(key) {
|
|
@@ -66,7 +64,7 @@ export class SkytimesUtils {
|
|
|
66
64
|
return {
|
|
67
65
|
event: eventData[key],
|
|
68
66
|
nextOccurence,
|
|
69
|
-
allOccurences: this.getAllTimes(this.
|
|
67
|
+
allOccurences: this.getAllTimes(this.getOccurrenceDay(eventData[key]), eventData[key].interval),
|
|
70
68
|
status: this.getEventStatus(eventData[key], nextOccurence),
|
|
71
69
|
};
|
|
72
70
|
}
|
|
@@ -76,40 +74,39 @@ export class SkytimesUtils {
|
|
|
76
74
|
*/
|
|
77
75
|
static allEventDetails() {
|
|
78
76
|
const keys = Object.keys(eventData).sort((a, b) => eventData[a].index - eventData[b].index);
|
|
79
|
-
const
|
|
77
|
+
const occurrences = [];
|
|
80
78
|
for (const key of keys) {
|
|
81
|
-
|
|
79
|
+
occurrences.push([key, this.getEventDetails(key)]);
|
|
82
80
|
}
|
|
83
|
-
return
|
|
81
|
+
return occurrences;
|
|
84
82
|
}
|
|
85
83
|
/**
|
|
86
84
|
* Returns the event status of a given event
|
|
87
85
|
* @param event The event to get the status for
|
|
88
|
-
* @param
|
|
86
|
+
* @param nextOccurrence The next occurrence of the event relative to "now"
|
|
89
87
|
* @returns The event status (or null if there is no active duration)
|
|
90
88
|
*/
|
|
91
|
-
static getEventStatus(event,
|
|
92
|
-
const now =
|
|
89
|
+
static getEventStatus(event, nextOccurrence) {
|
|
90
|
+
const now = DateTime.now().setZone("America/Los_Angeles");
|
|
93
91
|
const BASE = {
|
|
94
92
|
active: false,
|
|
95
|
-
nextTime:
|
|
96
|
-
duration:
|
|
93
|
+
nextTime: nextOccurrence,
|
|
94
|
+
duration: nextOccurrence.diff(now).toFormat("d'd' h'h' m'm' s's'"),
|
|
97
95
|
};
|
|
98
96
|
if (!event.duration)
|
|
99
97
|
return BASE;
|
|
100
|
-
//
|
|
101
|
-
// So we
|
|
102
|
-
const start =
|
|
103
|
-
const end = start.
|
|
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 });
|
|
104
102
|
// When active
|
|
105
|
-
if (now
|
|
103
|
+
if (now >= start && now <= end) {
|
|
106
104
|
return {
|
|
107
105
|
active: true,
|
|
108
106
|
startTime: start,
|
|
109
107
|
endTime: end,
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
duration: moment.duration(end.diff(now)).format("d[d] h[h] m[m] s[s]"),
|
|
108
|
+
nextTime: nextOccurrence,
|
|
109
|
+
duration: end.diff(now).toFormat("d'd' h'h' m'm' s's'"),
|
|
113
110
|
};
|
|
114
111
|
}
|
|
115
112
|
else {
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { APIGuildMember, APIUser } from "discord-api-types/v10";
|
|
2
2
|
export declare class GameWinnerCard {
|
|
3
|
+
readonly clientAvatar: string;
|
|
3
4
|
private name;
|
|
4
|
-
private client;
|
|
5
5
|
private thumbnail;
|
|
6
6
|
private points;
|
|
7
7
|
private total;
|
|
8
|
-
constructor(winner:
|
|
8
|
+
constructor(winner: APIUser | APIGuildMember, wins: number, total: number, clientAvatar: string);
|
|
9
9
|
private path;
|
|
10
10
|
private roundRect;
|
|
11
11
|
private changeFontSize;
|
|
@@ -1,30 +1,29 @@
|
|
|
1
1
|
import { createCanvas, loadImage } from "@napi-rs/canvas";
|
|
2
|
-
import {
|
|
3
|
-
import { colors, fancyCount } from "./utils.js";
|
|
2
|
+
import { colors, fancyCount, getUserAvatar } from "./utils.js";
|
|
4
3
|
import { join } from "path";
|
|
5
4
|
const size = 100;
|
|
6
5
|
// TODO: Integrate it with other game types
|
|
7
6
|
export class GameWinnerCard {
|
|
7
|
+
clientAvatar;
|
|
8
8
|
name;
|
|
9
|
-
client;
|
|
10
9
|
thumbnail;
|
|
11
10
|
points;
|
|
12
11
|
total;
|
|
13
|
-
constructor(winner, wins, total,
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
this.
|
|
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
17
|
}
|
|
18
|
-
|
|
19
|
-
this.name = winner
|
|
20
|
-
this.thumbnail = winner
|
|
18
|
+
else {
|
|
19
|
+
this.name = winner?.global_name || winner?.username;
|
|
20
|
+
this.thumbnail = getUserAvatar(winner);
|
|
21
21
|
}
|
|
22
|
-
this.client = client;
|
|
23
22
|
this.points = wins;
|
|
24
23
|
this.total = total;
|
|
25
24
|
}
|
|
26
25
|
path(strs) {
|
|
27
|
-
return join(
|
|
26
|
+
return join(import.meta.dirname, strs);
|
|
28
27
|
}
|
|
29
28
|
roundRect(ctx, x, y, w, h, r) {
|
|
30
29
|
if (w < 2 * r)
|
|
@@ -112,7 +111,7 @@ export class GameWinnerCard {
|
|
|
112
111
|
ctx.fillStyle = colors.grey;
|
|
113
112
|
this.roundRect(ctx, w * 0.875, h * 0.6, h * 0.4, h * 0.4, h * 0.15).clip();
|
|
114
113
|
ctx.fill();
|
|
115
|
-
ctx.drawImage(await loadImage(this.
|
|
114
|
+
ctx.drawImage(await loadImage(this.clientAvatar), w * 0.875, h * 0.6, h * 0.4, h * 0.4);
|
|
116
115
|
return canvas.toBuffer("image/png");
|
|
117
116
|
}
|
|
118
117
|
}
|
package/dist/classes/index.d.ts
CHANGED
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
export { LeaderboardCard } from "./LeaderBoardCard.js";
|
|
2
2
|
export { GameWinnerCard } from "./WinnerCard.js";
|
|
3
|
-
export { UpdateTS } from "./UpdateTs.js";
|
|
4
|
-
export { UpdateEvent } from "./UpdateEvent.js";
|
|
5
3
|
export { ShardsUtil } from "./shardsUtil.js";
|
|
6
4
|
export { SkytimesUtils } from "./SkytimesUtils.js";
|
|
7
5
|
export * from "./SkytimesUtils.js";
|
package/dist/classes/index.js
CHANGED
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
export { LeaderboardCard } from "./LeaderBoardCard.js";
|
|
2
2
|
export { GameWinnerCard } from "./WinnerCard.js";
|
|
3
|
-
export { UpdateTS } from "./UpdateTs.js";
|
|
4
|
-
export { UpdateEvent } from "./UpdateEvent.js";
|
|
5
3
|
export { ShardsUtil } from "./shardsUtil.js";
|
|
6
4
|
export { SkytimesUtils } from "./SkytimesUtils.js";
|
|
7
5
|
export * from "./SkytimesUtils.js";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import moment from "moment-timezone";
|
|
2
1
|
import "moment-duration-format";
|
|
2
|
+
import { DateTime } from "luxon";
|
|
3
3
|
import type { ShardsCountdown } from "../typings.js";
|
|
4
4
|
/**
|
|
5
5
|
* Sequence of Shards pattern
|
|
@@ -15,15 +15,15 @@ declare const realmSequence: readonly ["prairie", "forest", "valley", "wasteland
|
|
|
15
15
|
*/
|
|
16
16
|
export declare class ShardsUtil {
|
|
17
17
|
/**
|
|
18
|
-
* @method getDate - get provided date in
|
|
18
|
+
* @method getDate - get provided date in luxon
|
|
19
19
|
* @param date - date to get in moment
|
|
20
20
|
*/
|
|
21
|
-
static getDate(date?: string | undefined | null):
|
|
21
|
+
static getDate(date?: string | undefined | null): DateTime | string;
|
|
22
22
|
/**
|
|
23
23
|
* Returns shards index for a given date
|
|
24
24
|
* @param date
|
|
25
25
|
*/
|
|
26
|
-
static shardsIndex(date:
|
|
26
|
+
static shardsIndex(date: DateTime): {
|
|
27
27
|
currentShard: (typeof shardSequence)[number];
|
|
28
28
|
currentRealm: (typeof realmSequence)[number];
|
|
29
29
|
};
|
|
@@ -36,6 +36,6 @@ export declare class ShardsUtil {
|
|
|
36
36
|
* Get all three shards status for a given date relative to the current time
|
|
37
37
|
* @param date The date for which to get the status for
|
|
38
38
|
*/
|
|
39
|
-
static getStatus(date:
|
|
39
|
+
static getStatus(date: DateTime): ShardsCountdown[] | "No Shard";
|
|
40
40
|
}
|
|
41
41
|
export {};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import moment from "moment-timezone";
|
|
2
1
|
import "moment-duration-format";
|
|
2
|
+
import { DateTime } from "luxon";
|
|
3
3
|
import { shardsTimeline, shardConfig } from "../constants/index.js";
|
|
4
4
|
/**
|
|
5
5
|
* Sequence of Shards pattern
|
|
@@ -15,7 +15,7 @@ const realmSequence = ["prairie", "forest", "valley", "wasteland", "vault"];
|
|
|
15
15
|
*/
|
|
16
16
|
export class ShardsUtil {
|
|
17
17
|
/**
|
|
18
|
-
* @method getDate - get provided date in
|
|
18
|
+
* @method getDate - get provided date in luxon
|
|
19
19
|
* @param date - date to get in moment
|
|
20
20
|
*/
|
|
21
21
|
static getDate(date) {
|
|
@@ -23,12 +23,13 @@ export class ShardsUtil {
|
|
|
23
23
|
let currentDate;
|
|
24
24
|
try {
|
|
25
25
|
if (date) {
|
|
26
|
-
|
|
26
|
+
const [year, month, day] = date.split("-").map(Number);
|
|
27
|
+
currentDate = DateTime.fromObject({ year, month, day }, { zone: timezone }).startOf("day");
|
|
27
28
|
}
|
|
28
29
|
else {
|
|
29
|
-
currentDate =
|
|
30
|
+
currentDate = DateTime.now().setZone(timezone).startOf("day");
|
|
30
31
|
}
|
|
31
|
-
if (!currentDate.isValid
|
|
32
|
+
if (!currentDate.isValid) {
|
|
32
33
|
return "invalid";
|
|
33
34
|
}
|
|
34
35
|
else {
|
|
@@ -44,7 +45,7 @@ export class ShardsUtil {
|
|
|
44
45
|
* @param date
|
|
45
46
|
*/
|
|
46
47
|
static shardsIndex(date) {
|
|
47
|
-
const dayOfMonth = date.
|
|
48
|
+
const dayOfMonth = date.day;
|
|
48
49
|
const shardIndex = (dayOfMonth - 1) % shardSequence.length;
|
|
49
50
|
const currentShard = shardSequence[shardIndex];
|
|
50
51
|
const realmIndex = (dayOfMonth - 1) % realmSequence.length;
|
|
@@ -76,43 +77,43 @@ export class ShardsUtil {
|
|
|
76
77
|
const timezone = "America/Los_Angeles";
|
|
77
78
|
const { currentShard } = this.shardsIndex(date);
|
|
78
79
|
const timings = shardsTimeline(date)[currentShard];
|
|
79
|
-
const present =
|
|
80
|
-
const isNoShard = shardConfig[currentShard].weekdays.includes(date.
|
|
80
|
+
const present = DateTime.now().setZone(timezone);
|
|
81
|
+
const isNoShard = shardConfig[currentShard].weekdays.includes(date.weekday);
|
|
81
82
|
if (isNoShard)
|
|
82
83
|
return "No Shard";
|
|
83
84
|
const toReturn = [];
|
|
84
85
|
for (let i = 0; i < timings.length; i++) {
|
|
85
86
|
const eventTiming = timings[i];
|
|
86
87
|
// Active
|
|
87
|
-
if (present
|
|
88
|
+
if (present >= eventTiming.start && present <= eventTiming.end) {
|
|
88
89
|
toReturn.push({
|
|
89
90
|
index: i + 1,
|
|
90
91
|
active: true,
|
|
91
92
|
start: eventTiming.start,
|
|
92
93
|
end: eventTiming.end,
|
|
93
|
-
duration:
|
|
94
|
+
duration: eventTiming.end.diff(present, ["days", "hours", "minutes", "seconds"]).toFormat("dd'd' hh'h' mm'm' ss's'"),
|
|
94
95
|
});
|
|
95
96
|
continue;
|
|
96
97
|
// Yet to fall
|
|
97
98
|
}
|
|
98
|
-
else if (present
|
|
99
|
+
else if (present < eventTiming.start) {
|
|
99
100
|
toReturn.push({
|
|
100
101
|
index: i + 1,
|
|
101
102
|
active: false,
|
|
102
103
|
start: eventTiming.start,
|
|
103
104
|
end: eventTiming.end,
|
|
104
|
-
duration:
|
|
105
|
+
duration: eventTiming.start.diff(present, ["days", "hours", "minutes", "seconds"]).toFormat("dd'd' hh'h' mm'm' ss's'"),
|
|
105
106
|
});
|
|
106
107
|
continue;
|
|
107
108
|
// All ended
|
|
108
109
|
}
|
|
109
|
-
else if (present
|
|
110
|
+
else if (present > eventTiming.end) {
|
|
110
111
|
toReturn.push({
|
|
111
112
|
index: i + 1,
|
|
112
113
|
ended: true,
|
|
113
114
|
start: eventTiming.start,
|
|
114
115
|
end: eventTiming.end,
|
|
115
|
-
duration:
|
|
116
|
+
duration: present.diff(eventTiming.end, ["days", "hours", "minutes", "seconds"]).toFormat("dd'd' hh'h' mm'm' ss's'"),
|
|
116
117
|
});
|
|
117
118
|
continue;
|
|
118
119
|
}
|
package/dist/classes/utils.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { type APIUser } from "discord-api-types/v10";
|
|
1
2
|
export declare const colors: {
|
|
2
3
|
blue: string;
|
|
3
4
|
white: string;
|
|
@@ -11,3 +12,4 @@ export declare const colors: {
|
|
|
11
12
|
idle: string;
|
|
12
13
|
};
|
|
13
14
|
export declare function fancyCount(n: number): string;
|
|
15
|
+
export declare function getUserAvatar(user: APIUser): string;
|
package/dist/classes/utils.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { CDNRoutes } from "discord-api-types/v10";
|
|
1
2
|
export const colors = {
|
|
2
3
|
blue: "#7289DA",
|
|
3
4
|
white: "#FFFFFF",
|
|
@@ -20,3 +21,8 @@ export function fancyCount(n) {
|
|
|
20
21
|
}
|
|
21
22
|
return Math.floor(n) + "";
|
|
22
23
|
}
|
|
24
|
+
export function getUserAvatar(user) {
|
|
25
|
+
return user.avatar
|
|
26
|
+
? CDNRoutes.userAvatar(user.id, user.avatar, "png")
|
|
27
|
+
: CDNRoutes.defaultUserAvatar(Number((BigInt(user.id) >> 22n) % 5n));
|
|
28
|
+
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
export const shardConfig = {
|
|
2
|
-
a: { type: "<:ShardBlue:1233057106903699497> Black Shard", colors: "#000000", weekdays: [6,
|
|
2
|
+
a: { type: "<:ShardBlue:1233057106903699497> Black Shard", colors: "#000000", weekdays: [6, 7] },
|
|
3
3
|
A: { type: "<:ShardRed:1233057065799254106> Red Shard", colors: "#FF0000", weekdays: [2, 3] },
|
|
4
|
-
b: { type: "<:ShardBlue:1233057106903699497> Black Shard", colors: "#000000", weekdays: [
|
|
4
|
+
b: { type: "<:ShardBlue:1233057106903699497> Black Shard", colors: "#000000", weekdays: [7, 1] },
|
|
5
5
|
B: { type: "<:ShardRed:1233057065799254106> Red Shard", colors: "#FF0000", weekdays: [3, 4] },
|
|
6
6
|
C: { type: "<:ShardRed:1233057065799254106> Red Shard", colors: "#FF0000", weekdays: [1, 2] },
|
|
7
7
|
};
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import
|
|
1
|
+
import type { DateTime } from "luxon";
|
|
2
2
|
declare const shardSequence: readonly ["C", "b", "A", "a", "B", "b", "C", "a", "A", "b", "B", "a"];
|
|
3
3
|
export type TimelineType = {
|
|
4
|
-
readonly earlySky:
|
|
5
|
-
readonly gateShard:
|
|
6
|
-
readonly start:
|
|
7
|
-
readonly end:
|
|
4
|
+
readonly earlySky: DateTime;
|
|
5
|
+
readonly gateShard: DateTime;
|
|
6
|
+
readonly start: DateTime;
|
|
7
|
+
readonly end: DateTime;
|
|
8
8
|
readonly shardMusic: string;
|
|
9
9
|
};
|
|
10
10
|
export type TimelineReturnType = Record<(typeof shardSequence)[number], [TimelineType, TimelineType, TimelineType]>;
|
|
@@ -15,5 +15,5 @@ export type TimelineReturnType = Record<(typeof shardSequence)[number], [Timelin
|
|
|
15
15
|
* const timelines = shardsTimeline(moment())
|
|
16
16
|
* const times = timelines[currentShard]
|
|
17
17
|
*/
|
|
18
|
-
export declare const shardsTimeline: (currentDate:
|
|
18
|
+
export declare const shardsTimeline: (currentDate: DateTime) => TimelineReturnType;
|
|
19
19
|
export {};
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import moment from "moment-timezone";
|
|
2
1
|
const shardSequence = ["C", "b", "A", "a", "B", "b", "C", "a", "A", "b", "B", "a"];
|
|
3
2
|
/**
|
|
4
3
|
* Returns shards fall - end times for a given date
|
|
@@ -10,20 +9,10 @@ const shardSequence = ["C", "b", "A", "a", "B", "b", "C", "a", "A", "b", "B", "a
|
|
|
10
9
|
export const shardsTimeline = (currentDate) => {
|
|
11
10
|
const getTimes = (earlySkyHours, earlySkyMinutes, earlySkySeconds, gateShardHours, gateShardMinutes, shardLandHours, shardLandMinutes, shardLandSeconds, shardEndHours, shardEndMinutes, shardMusic) => {
|
|
12
11
|
return {
|
|
13
|
-
earlySky: currentDate
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
.add(earlySkyMinutes, "minutes")
|
|
18
|
-
.add(earlySkySeconds, "seconds"),
|
|
19
|
-
gateShard: currentDate.clone().startOf("day").add(gateShardHours, "hours").add(gateShardMinutes, "minutes"),
|
|
20
|
-
start: currentDate
|
|
21
|
-
.clone()
|
|
22
|
-
.startOf("day")
|
|
23
|
-
.add(shardLandHours, "hours")
|
|
24
|
-
.add(shardLandMinutes, "minutes")
|
|
25
|
-
.add(shardLandSeconds, "seconds"),
|
|
26
|
-
end: currentDate.clone().startOf("day").add(shardEndHours, "hours").add(shardEndMinutes, "minutes"),
|
|
12
|
+
earlySky: currentDate.startOf("day").plus({ hours: earlySkyHours, minutes: earlySkyMinutes, seconds: earlySkySeconds }),
|
|
13
|
+
gateShard: currentDate.startOf("day").plus({ hours: gateShardHours, minutes: gateShardMinutes }),
|
|
14
|
+
start: currentDate.startOf("day").plus({ hours: shardLandHours, minutes: shardLandMinutes, seconds: shardLandSeconds }),
|
|
15
|
+
end: currentDate.startOf("day").plus({ hours: shardEndHours, minutes: shardEndMinutes }),
|
|
27
16
|
shardMusic: shardMusic,
|
|
28
17
|
};
|
|
29
18
|
};
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
|
|
1
|
+
export * from "./utils/index.js";
|
|
2
2
|
export * from "./classes/index.js";
|
|
3
3
|
export { type Permission } from "./utils/parsePerms.js";
|
|
4
|
-
export { buildTimesHTML, parsePerms, postToHaste, parseDateFormat, type Field, recursiveReadDir };
|
|
5
4
|
export * from "./constants/index.js";
|
|
6
5
|
export type * from "./typings.ts";
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
|
|
1
|
+
export * from "./utils/index.js";
|
|
2
2
|
export * from "./classes/index.js";
|
|
3
3
|
export {} from "./utils/parsePerms.js";
|
|
4
|
-
export { buildTimesHTML, parsePerms, postToHaste, parseDateFormat, recursiveReadDir };
|
|
5
4
|
export * from "./constants/index.js";
|
package/dist/typings.d.ts
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import moment from "moment-timezone";
|
|
1
|
+
import type { DateTime } from "luxon";
|
|
3
2
|
import { Document } from "mongoose";
|
|
4
3
|
/** Data of users provided for making a game leaderboard card */
|
|
5
4
|
export interface userData {
|
|
@@ -34,13 +33,10 @@ export interface Background {
|
|
|
34
33
|
export interface SkyEvent {
|
|
35
34
|
eventActive: Boolean;
|
|
36
35
|
eventName: string;
|
|
37
|
-
eventStarts:
|
|
38
|
-
eventEnds:
|
|
36
|
+
eventStarts: DateTime;
|
|
37
|
+
eventEnds: DateTime;
|
|
39
38
|
eventDuration: string;
|
|
40
39
|
}
|
|
41
|
-
export interface SkyHelper extends Client {
|
|
42
|
-
skyEvents: Collection<string, SkyEvent>;
|
|
43
|
-
}
|
|
44
40
|
export interface TSData extends Document {
|
|
45
41
|
name: string;
|
|
46
42
|
visitDate: string;
|
|
@@ -56,7 +52,7 @@ export interface ShardsCountdown {
|
|
|
56
52
|
index: number;
|
|
57
53
|
active?: boolean;
|
|
58
54
|
ended?: boolean;
|
|
59
|
-
start:
|
|
60
|
-
end:
|
|
55
|
+
start: DateTime;
|
|
56
|
+
end: DateTime;
|
|
61
57
|
duration: string;
|
|
62
58
|
}
|
package/dist/typings.js
CHANGED
package/dist/utils/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
export
|
|
2
|
-
export
|
|
3
|
-
export
|
|
4
|
-
export
|
|
5
|
-
export
|
|
1
|
+
export * from "./postToBin.js";
|
|
2
|
+
export * from "./parsePerms.js";
|
|
3
|
+
export * from "./recursiveReadDir.js";
|
|
4
|
+
export * from "./parseDateFormat.js";
|
|
5
|
+
export * from "./resolveColors.js";
|
package/dist/utils/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
export
|
|
2
|
-
export
|
|
3
|
-
export
|
|
4
|
-
export
|
|
5
|
-
export
|
|
1
|
+
export * from "./postToBin.js";
|
|
2
|
+
export * from "./parsePerms.js";
|
|
3
|
+
export * from "./recursiveReadDir.js";
|
|
4
|
+
export * from "./parseDateFormat.js";
|
|
5
|
+
export * from "./resolveColors.js";
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
/** Original code credit to discord.js */
|
|
2
|
+
/**
|
|
3
|
+
* Can be a number, hex string, an RGB array like:
|
|
4
|
+
* ```js
|
|
5
|
+
* [255, 0, 255] // purple
|
|
6
|
+
* ```
|
|
7
|
+
* or one of the following strings:
|
|
8
|
+
* - `Default`
|
|
9
|
+
* - `White`
|
|
10
|
+
* - `Aqua`
|
|
11
|
+
* - `Green`
|
|
12
|
+
* - `Blue`
|
|
13
|
+
* - `Yellow`
|
|
14
|
+
* - `Purple`
|
|
15
|
+
* - `LuminousVividPink`
|
|
16
|
+
* - `Fuchsia`
|
|
17
|
+
* - `Gold`
|
|
18
|
+
* - `Orange`
|
|
19
|
+
* - `Red`
|
|
20
|
+
* - `Grey`
|
|
21
|
+
* - `Navy`
|
|
22
|
+
* - `DarkAqua`
|
|
23
|
+
* - `DarkGreen`
|
|
24
|
+
* - `DarkBlue`
|
|
25
|
+
* - `DarkPurple`
|
|
26
|
+
* - `DarkVividPink`
|
|
27
|
+
* - `DarkGold`
|
|
28
|
+
* - `DarkOrange`
|
|
29
|
+
* - `DarkRed`
|
|
30
|
+
* - `DarkGrey`
|
|
31
|
+
* - `DarkerGrey`
|
|
32
|
+
* - `LightGrey`
|
|
33
|
+
* - `DarkNavy`
|
|
34
|
+
* - `Blurple`
|
|
35
|
+
* - `Greyple`
|
|
36
|
+
* - `DarkButNotBlack`
|
|
37
|
+
* - `NotQuiteBlack`
|
|
38
|
+
* - `Random`
|
|
39
|
+
*/
|
|
40
|
+
export type ColorResolvable = keyof typeof Colors | "Random" | "Default" | `#${string}` | number | number[];
|
|
41
|
+
/**
|
|
42
|
+
* Resolves a ColorResolvable into a color number.
|
|
43
|
+
* @param color Color to resolve
|
|
44
|
+
* @returns A color
|
|
45
|
+
*/
|
|
46
|
+
export declare function resolveColor(color: ColorResolvable): number;
|
|
47
|
+
declare const Colors: {
|
|
48
|
+
Default: number;
|
|
49
|
+
White: number;
|
|
50
|
+
Aqua: number;
|
|
51
|
+
Green: number;
|
|
52
|
+
Blue: number;
|
|
53
|
+
Yellow: number;
|
|
54
|
+
Purple: number;
|
|
55
|
+
LuminousVividPink: number;
|
|
56
|
+
Fuchsia: number;
|
|
57
|
+
Gold: number;
|
|
58
|
+
Orange: number;
|
|
59
|
+
Red: number;
|
|
60
|
+
Grey: number;
|
|
61
|
+
Navy: number;
|
|
62
|
+
DarkAqua: number;
|
|
63
|
+
DarkGreen: number;
|
|
64
|
+
DarkBlue: number;
|
|
65
|
+
DarkPurple: number;
|
|
66
|
+
DarkVividPink: number;
|
|
67
|
+
DarkGold: number;
|
|
68
|
+
DarkOrange: number;
|
|
69
|
+
DarkRed: number;
|
|
70
|
+
DarkGrey: number;
|
|
71
|
+
DarkerGrey: number;
|
|
72
|
+
LightGrey: number;
|
|
73
|
+
DarkNavy: number;
|
|
74
|
+
Blurple: number;
|
|
75
|
+
Greyple: number;
|
|
76
|
+
DarkButNotBlack: number;
|
|
77
|
+
NotQuiteBlack: number;
|
|
78
|
+
};
|
|
79
|
+
export {};
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/** Original code credit to discord.js */
|
|
2
|
+
/**
|
|
3
|
+
* Resolves a ColorResolvable into a color number.
|
|
4
|
+
* @param color Color to resolve
|
|
5
|
+
* @returns A color
|
|
6
|
+
*/
|
|
7
|
+
export function resolveColor(color) {
|
|
8
|
+
let resolvedColor;
|
|
9
|
+
if (typeof color === "string") {
|
|
10
|
+
if (color === "Random")
|
|
11
|
+
return Math.floor(Math.random() * (0xffffff + 1));
|
|
12
|
+
if (color === "Default")
|
|
13
|
+
return 0;
|
|
14
|
+
if (/^#?[\da-f]{6}$/i.test(color))
|
|
15
|
+
return parseInt(color.replace("#", ""), 16);
|
|
16
|
+
resolvedColor = Colors[color];
|
|
17
|
+
}
|
|
18
|
+
else if (Array.isArray(color)) {
|
|
19
|
+
resolvedColor = (color[0] << 16) + (color[1] << 8) + color[2];
|
|
20
|
+
}
|
|
21
|
+
else {
|
|
22
|
+
resolvedColor = color;
|
|
23
|
+
}
|
|
24
|
+
if (!Number.isInteger(resolvedColor)) {
|
|
25
|
+
throw new Error("Not a number");
|
|
26
|
+
}
|
|
27
|
+
if (resolvedColor < 0 || resolvedColor > 0xffffff) {
|
|
28
|
+
throw new Error("Not in color range");
|
|
29
|
+
}
|
|
30
|
+
return resolvedColor;
|
|
31
|
+
}
|
|
32
|
+
const Colors = {
|
|
33
|
+
Default: 0x000000,
|
|
34
|
+
White: 0xffffff,
|
|
35
|
+
Aqua: 0x1abc9c,
|
|
36
|
+
Green: 0x57f287,
|
|
37
|
+
Blue: 0x3498db,
|
|
38
|
+
Yellow: 0xfee75c,
|
|
39
|
+
Purple: 0x9b59b6,
|
|
40
|
+
LuminousVividPink: 0xe91e63,
|
|
41
|
+
Fuchsia: 0xeb459e,
|
|
42
|
+
Gold: 0xf1c40f,
|
|
43
|
+
Orange: 0xe67e22,
|
|
44
|
+
Red: 0xed4245,
|
|
45
|
+
Grey: 0x95a5a6,
|
|
46
|
+
Navy: 0x34495e,
|
|
47
|
+
DarkAqua: 0x11806a,
|
|
48
|
+
DarkGreen: 0x1f8b4c,
|
|
49
|
+
DarkBlue: 0x206694,
|
|
50
|
+
DarkPurple: 0x71368a,
|
|
51
|
+
DarkVividPink: 0xad1457,
|
|
52
|
+
DarkGold: 0xc27c0e,
|
|
53
|
+
DarkOrange: 0xa84300,
|
|
54
|
+
DarkRed: 0x992d22,
|
|
55
|
+
DarkGrey: 0x979c9f,
|
|
56
|
+
DarkerGrey: 0x7f8c8d,
|
|
57
|
+
LightGrey: 0xbcc0c0,
|
|
58
|
+
DarkNavy: 0x2c3e50,
|
|
59
|
+
Blurple: 0x5865f2,
|
|
60
|
+
Greyple: 0x99aab5,
|
|
61
|
+
DarkButNotBlack: 0x2c2f33,
|
|
62
|
+
NotQuiteBlack: 0x23272a,
|
|
63
|
+
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@skyhelperbot/utils",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.2-dev",
|
|
4
4
|
"description": "Utilities for SkyHelper bot",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -27,16 +27,20 @@
|
|
|
27
27
|
"homepage": "https://github.com/imnaiyar/skyhelper/packages/utils#readme",
|
|
28
28
|
"dependencies": {
|
|
29
29
|
"@napi-rs/canvas": "^0.1.51",
|
|
30
|
-
"discord
|
|
30
|
+
"discord-api-types": "^0.37.93",
|
|
31
31
|
"moment-duration-format": "^2.3.2",
|
|
32
|
-
"moment-timezone": "^0.5.45",
|
|
33
32
|
"typescript": "^5.4.3",
|
|
34
|
-
"undici": "^
|
|
33
|
+
"undici": "^7.2.3"
|
|
35
34
|
},
|
|
36
35
|
"devDependencies": {
|
|
36
|
+
"@types/luxon": "^3.4.2",
|
|
37
37
|
"@types/moment-duration-format": "^2.2.6",
|
|
38
|
+
"luxon": "^3.5.0",
|
|
38
39
|
"mongoose": "^8.3.2"
|
|
39
40
|
},
|
|
41
|
+
"peerDependencies": {
|
|
42
|
+
"luxon": "^3.5.0"
|
|
43
|
+
},
|
|
40
44
|
"scripts": {
|
|
41
45
|
"build": "tsc && echo 'Files compiled'",
|
|
42
46
|
"build:docs": "typedoc"
|