Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions deno.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,6 @@
"drizzle-orm": "npm:drizzle-orm@^0.38.3",
"drizzle-kit": "npm:drizzle-kit@^0.30.1",
"html-entities": "npm:html-entities@^2.3.2",
"moment": "npm:moment@^2.29.1",
"moment-timezone": "npm:moment-timezone@^0.5.34",
"mysql2": "npm:mysql2@^3.10.1",
"node-cron": "npm:node-cron@^3.0.0",
"turndown": "npm:turndown@^7.1.1"
Expand Down
13 changes: 0 additions & 13 deletions deno.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion src/command/ContextFindCommand.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { FetchCharacterService } from "../service/FetchCharacterService.ts";
import { Command } from "./type/Command.ts";
import { DiscordMessageService } from "../service/DiscordMessageService.ts";
import { LodestoneServiceUnavailableError } from "../naagostone/error/LodestoneServiceUnavailableError.ts";
import { DateHelper } from "../helper/DateHelper.ts";

class ContextFindCommand extends Command {
public readonly data = new ContextMenuCommandBuilder()
Expand Down Expand Up @@ -47,7 +48,7 @@ class ContextFindCommand extends Command {

const file = new AttachmentBuilder(profileImage);
const components = ProfileGeneratorService.getComponents("profile", "profile", targetCharacter?.id);
const unix = targetCharacterDataDto.latestUpdate.unix();
const unix = DateHelper.toEpochSeconds(targetCharacterDataDto.latestUpdate);

const cachedHint = targetCharacterDataDto.isCachedDueToUnavailability
? "\n⚠️ *Lodestone is currently unavailable. Showing cached data.*"
Expand Down
7 changes: 5 additions & 2 deletions src/command/ProfileCommand.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import { InvalidSubCommandError } from "./error/InvalidSubCommandError.ts";
import { DiscordMessageService } from "../service/DiscordMessageService.ts";
import { LodestoneServiceUnavailableError } from "../naagostone/error/LodestoneServiceUnavailableError.ts";
import { CommandMentionService } from "../service/CommandMentionService.ts";
import { DateHelper } from "../helper/DateHelper.ts";

class ProfileCommand extends Command {
public readonly data = new SlashCommandBuilder()
Expand Down Expand Up @@ -152,9 +153,10 @@ class ProfileCommand extends Command {

const file = new AttachmentBuilder(profileImage);
const components = ProfileGeneratorService.getComponents(profilePage, "profile", characterId);
const unix = DateHelper.toEpochSeconds(characterDataDto.latestUpdate);

await interaction.editReply({
content: `Latest Update: <t:${characterDataDto.latestUpdate.unix()}:R>${cachedHint}`,
content: `Latest Update: <t:${unix}:R>${cachedHint}`,
files: [file],
embeds: [],
attachments: [],
Expand Down Expand Up @@ -246,13 +248,14 @@ class ProfileCommand extends Command {

const file = new AttachmentBuilder(profileImage);
const components = ProfileGeneratorService.getComponents("profile", "profile", characterId);
const unix = DateHelper.toEpochSeconds(characterDataDto.latestUpdate);

const cachedHint = characterDataDto.isCachedDueToUnavailability
? "\n⚠️ *Lodestone is currently unavailable. Showing cached data.*"
: "";

await interaction.editReply({
content: `Latest Update: <t:${characterDataDto.latestUpdate.unix()}:R>${cachedHint}`,
content: `Latest Update: <t:${unix}:R>${cachedHint}`,
files: [file],
embeds: [],
attachments: [],
Expand Down
4 changes: 1 addition & 3 deletions src/database/repository/CharacterDataRepository.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { database } from "../connection.ts";
import { CharacterData, characterData } from "../schema/character-data.ts";
import { eq } from "drizzle-orm";
import moment from "moment-timezone";
import { Character } from "../../naagostone/type/CharacterTypes.ts";

export class CharacterDataRepository {
Expand All @@ -18,8 +17,7 @@ export class CharacterDataRepository {
}

public static async set(character: Character): Promise<void> {
const now = Date.now();
const nowSQL = moment(now).tz("UTC").toDate();
const nowSQL = new Date();
await database
.insert(characterData)
.values({
Expand Down
13 changes: 4 additions & 9 deletions src/database/repository/MaintenancesRepository.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { and, eq, gt, gte, lte } from "drizzle-orm";
import { database } from "../connection.ts";
import moment from "moment";
import { AlreadyInDatabaseError } from "../error/AlreadyInDatabaseError.ts";
import { MaintenanceData, maintenanceData } from "../schema/lodestone-news.ts";
import { Maintenance } from "../../naagostone/type/Maintenance.ts";
Expand All @@ -10,15 +9,13 @@ export class MaintenancesRepository {
title: string,
date: Date,
): Promise<MaintenanceData | null> {
const dateSQL = moment(date).tz("Europe/London").toDate();

const result = await database
.select()
.from(maintenanceData)
.where(
and(
eq(maintenanceData.title, title),
eq(maintenanceData.date, dateSQL),
eq(maintenanceData.date, date),
),
)
.limit(1);
Expand All @@ -27,7 +24,7 @@ export class MaintenancesRepository {
}

public static async add(maintenance: Maintenance): Promise<number> {
const dateSQL = moment(maintenance.date).tz("Europe/London").toDate();
const dateSQL = new Date(maintenance.date);
const currentMaintenance = await this.find(maintenance.title, dateSQL);
if (currentMaintenance) {
throw new AlreadyInDatabaseError(
Expand All @@ -44,10 +41,8 @@ export class MaintenancesRepository {
date: dateSQL,
description: maintenance.description.markdown,
descriptionV2: maintenance.description.discord_components_v2 ?? null,
startDate: maintenance.start_timestamp
? moment(maintenance.start_timestamp).tz("Europe/London").toDate()
: null,
endDate: maintenance.end_timestamp ? moment(maintenance.end_timestamp).tz("Europe/London").toDate() : null,
startDate: maintenance.start_timestamp ? new Date(maintenance.start_timestamp) : null,
endDate: maintenance.end_timestamp ? new Date(maintenance.end_timestamp) : null,
})
.$returningId();

Expand Down
7 changes: 2 additions & 5 deletions src/database/repository/NoticesRepository.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { and, eq } from "drizzle-orm";
import { database } from "../connection.ts";
import moment from "moment-timezone";
import { AlreadyInDatabaseError } from "../error/AlreadyInDatabaseError.ts";
import { NoticeData, noticeData } from "../schema/lodestone-news.ts";
import { Notice } from "../../naagostone/type/Notice.ts";
Expand All @@ -10,15 +9,13 @@ export class NoticesRepository {
title: string,
date: Date,
): Promise<NoticeData | null> {
const dateSQL = moment(date).tz("Europe/London").toDate();

const result = await database
.select()
.from(noticeData)
.where(
and(
eq(noticeData.title, title),
eq(noticeData.date, dateSQL),
eq(noticeData.date, date),
),
)
.limit(1);
Expand All @@ -27,7 +24,7 @@ export class NoticesRepository {
}

public static async add(notice: Notice): Promise<number> {
const dateSQL = moment(notice.date).tz("Europe/London").toDate();
const dateSQL = new Date(notice.date);
const currentNotice = await this.find(notice.title, dateSQL);
if (currentNotice) {
throw new AlreadyInDatabaseError(
Expand Down
7 changes: 2 additions & 5 deletions src/database/repository/StatusesRepository.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { and, eq } from "drizzle-orm";
import { database } from "../connection.ts";
import moment from "moment-timezone";
import { AlreadyInDatabaseError } from "../error/AlreadyInDatabaseError.ts";
import { StatusData, statusData } from "../schema/lodestone-news.ts";
import { Status } from "../../naagostone/type/Status.ts";
Expand All @@ -10,15 +9,13 @@ export class StatusesRepository {
title: string,
date: Date,
): Promise<StatusData | null> {
const dateSQL = moment(date).tz("Europe/London").toDate();

const result = await database
.select()
.from(statusData)
.where(
and(
eq(statusData.title, title),
eq(statusData.date, dateSQL),
eq(statusData.date, date),
),
)
.limit(1);
Expand All @@ -27,7 +24,7 @@ export class StatusesRepository {
}

public static async add(status: Status): Promise<number> {
const dateSQL = moment(status.date).tz("Europe/London").toDate();
const dateSQL = new Date(status.date);
const currentStatus = await this.find(status.title, dateSQL);
if (currentStatus) {
throw new AlreadyInDatabaseError(
Expand Down
7 changes: 2 additions & 5 deletions src/database/repository/TopicsRepository.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { and, desc, eq, gt, gte, isNotNull, lte, ne, or, sql } from "drizzle-orm";
import { database } from "../connection.ts";
import { TopicData, topicData } from "../schema/lodestone-news.ts";
import moment from "moment-timezone";
import { AlreadyInDatabaseError } from "../error/AlreadyInDatabaseError.ts";
import { Topic } from "../../naagostone/type/Topic.ts";

Expand All @@ -15,15 +14,13 @@ export class TopicsRepository {
title: string,
date: Date,
): Promise<TopicData | null> {
const dateSQL = moment(date).tz("Europe/London").toDate();

const result = await database
.select()
.from(topicData)
.where(
and(
eq(topicData.title, title),
eq(topicData.date, dateSQL),
eq(topicData.date, date),
),
)
.limit(1);
Expand All @@ -42,7 +39,7 @@ export class TopicsRepository {
}

public static async add(topic: Topic): Promise<number> {
const dateSQL = moment(topic.date).tz("Europe/London").toDate();
const dateSQL = new Date(topic.date);
const currentTopic = await this.find(topic.title, dateSQL);
if (currentTopic) {
throw new AlreadyInDatabaseError("This topic is already in the database");
Expand Down
7 changes: 2 additions & 5 deletions src/database/repository/UpdatesRepository.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { and, eq } from "drizzle-orm";
import { database } from "../connection.ts";
import moment from "moment-timezone";
import { AlreadyInDatabaseError } from "../error/AlreadyInDatabaseError.ts";
import { UpdateData, updateData } from "../schema/lodestone-news.ts";
import { Update } from "../../naagostone/type/Updates.ts";
Expand All @@ -10,15 +9,13 @@ export class UpdatesRepository {
title: string,
date: Date,
): Promise<UpdateData | null> {
const dateSQL = moment(date).tz("Europe/London").toDate();

const result = await database
.select()
.from(updateData)
.where(
and(
eq(updateData.title, title),
eq(updateData.date, dateSQL),
eq(updateData.date, date),
),
)
.limit(1);
Expand All @@ -27,7 +24,7 @@ export class UpdatesRepository {
}

public static async add(update: Update): Promise<number> {
const dateSQL = moment(update.date).tz("Europe/London").toDate();
const dateSQL = new Date(update.date);
const currentUpdate = await this.find(update.title, dateSQL);
if (currentUpdate) {
throw new AlreadyInDatabaseError(
Expand Down
75 changes: 75 additions & 0 deletions src/helper/DateHelper.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
const MONTHS_SHORT = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];

export class DateHelper {
static setUtcTime(date: Date, hours: number, minutes = 0, seconds = 0, milliseconds = 0): Date {
const clonedDate = new Date(date.getTime());
clonedDate.setUTCHours(hours, minutes, seconds, milliseconds);
return clonedDate;
}

static setUtcDayOfWeek(date: Date, targetDay: number, hours: number, minutes = 0, seconds = 0, ms = 0): Date {
const clonedDate = new Date(date.getTime());
const diff = targetDay - clonedDate.getUTCDay();
clonedDate.setUTCDate(clonedDate.getUTCDate() + diff);
clonedDate.setUTCHours(hours, minutes, seconds, ms);
return clonedDate;
}

static addDays(date: Date, days: number): Date {
const clonedDate = new Date(date.getTime());
clonedDate.setUTCDate(clonedDate.getUTCDate() + days);
return clonedDate;
}

static addWeeks(date: Date, weeks: number): Date {
return DateHelper.addDays(date, weeks * 7);
}

static addMilliseconds(date: Date, milliseconds: number): Date {
return new Date(date.getTime() + milliseconds);
}

static subtractMinutes(date: Date, minutes: number): Date {
return new Date(date.getTime() - minutes * 60 * 1000);
}

static formatLog(date: Date): string {
const pad = (value: number, length = 2) => value.toString().padStart(length, "0");

const year = date.getFullYear();
const month = pad(date.getMonth() + 1);
const day = pad(date.getDate());
const hours = pad(date.getHours());
const minutes = pad(date.getMinutes());
const seconds = pad(date.getSeconds());
const milliseconds = pad(date.getMilliseconds(), 3);

const offset = -date.getTimezoneOffset();
const sign = offset >= 0 ? "+" : "-";
const absOffset = Math.abs(offset);
const offsetHours = pad(Math.floor(absOffset / 60));
const offsetMinutes = pad(absOffset % 60);

return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}.${milliseconds} ${sign}${offsetHours}${offsetMinutes}`;
}

static formatOrdinalDate(date: Date): string {
const day = date.getUTCDate();
const suffix = DateHelper.getOrdinalSuffix(day);
return `${day}${suffix} ${MONTHS_SHORT[date.getUTCMonth()]} ${date.getUTCFullYear()}`;
}

static formatMediumDate(date: Date): string {
return `${MONTHS_SHORT[date.getUTCMonth()]} ${date.getUTCDate()}, ${date.getUTCFullYear()}`;
}

private static getOrdinalSuffix(day: number): string {
const suffixes = ["th", "st", "nd", "rd"];
const remainder = day % 100;
return suffixes[(remainder - 20) % 10] || suffixes[remainder] || suffixes[0];
}

static toEpochSeconds(date: Date): number {
return Math.floor(date.getTime() / 1000);
}
}
3 changes: 1 addition & 2 deletions src/helper/HelpCommandHelper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import {
} from "discord.js";
import { DiscordColorService } from "../service/DiscordColorService.ts";
import { InvalidHelpPageError } from "./error/InvalidHelpPageError.ts";
import moment from "moment";
import { DiscordEmojiService } from "../service/DiscordEmojiService.ts";
import { CommandMentionService } from "../service/CommandMentionService.ts";

Expand Down Expand Up @@ -263,7 +262,7 @@ export class HelpCommandHelper {
): Promise<{ embeds: EmbedBuilder[]; components: ActionRowBuilder<ButtonBuilder>[] }> {
const client = interaction.client;
const components = HelpCommandHelper.getButtons("about");
const uptimeFormatted = time(moment().subtract(client.uptime!, "ms").toDate(), "R");
const uptimeFormatted = time(new Date(Date.now() - client.uptime!), "R");
const deploymentHash = Deno.env.get("DEPLOYMENT_HASH");
const embed = new EmbedBuilder()
.setColor(await DiscordColorService.getBotColorByInteraction(interaction))
Expand Down
Loading
Loading