From 8d2fba1c21674cb03c7f28e31c2676b07d581968 Mon Sep 17 00:00:00 2001 From: Taken Date: Sun, 2 Mar 2025 20:35:52 +0100 Subject: [PATCH 1/2] Updated compose file --- docker-compose.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker-compose.yml b/docker-compose.yml index 7603f3f..6675dd4 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -19,7 +19,7 @@ services: image: postgres:16.4 restart: unless-stopped volumes: - - ${DB_PATH}:/var/lib/postgresql/data + - ./db:/var/lib/postgresql/data ports: - 127.0.0.1:5432:5432 environment: From 0f4d317935792264fdedddfb084faf120e747853 Mon Sep 17 00:00:00 2001 From: Taken Date: Sun, 2 Mar 2025 21:09:43 +0100 Subject: [PATCH 2/2] Updated env --- package.json | 1 + pnpm-lock.yaml | 22 ++++++++ scripts/delete-commands.ts | 2 +- scripts/deploy-commands.ts | 2 +- scripts/dev-deploy.ts | 2 +- src/commands/pp.ts | 2 +- src/commands/staff/prune.ts | 2 +- src/commands/staff/removeguildroles.ts | 2 +- src/commands/staff/updateall.ts | 2 +- src/commands/timeout.ts | 2 + src/components/buttons/staffapply.ts | 2 +- src/drizzle/db.ts | 2 +- src/utils/Autodeploy.ts | 2 +- src/utils/Client.ts | 6 +-- src/utils/Env.ts | 69 ++++++++++++-------------- src/utils/HypixelFunctions/account.ts | 2 +- src/utils/Illegitimate.ts | 2 +- 17 files changed, 72 insertions(+), 52 deletions(-) diff --git a/package.json b/package.json index 20c6e22..799e7ae 100644 --- a/package.json +++ b/package.json @@ -40,6 +40,7 @@ "@discord-player/extractor": "^7.1.0", "@swc/cli": "^0.6.0", "@swc/core": "^1.11.5", + "@t3-oss/env-core": "^0.12.0", "anilist": "^0.12.4", "axios": "^1.8.1", "chalk": "^5.4.1", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index aee5ee5..4182278 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -25,6 +25,9 @@ importers: '@swc/core': specifier: ^1.11.5 version: 1.11.5 + '@t3-oss/env-core': + specifier: ^0.12.0 + version: 0.12.0(typescript@5.8.2)(zod@3.24.2) anilist: specifier: ^0.12.4 version: 0.12.4 @@ -1063,6 +1066,20 @@ packages: resolution: {integrity: sha512-+PmQX0PiAYPMeVYe237LJAYvOMYW1j2rH5YROyS3b4CTVJum34HfRvKvAzozHAQG0TnHNdUfY9nCeUyRAs//cw==} engines: {node: '>=14.16'} + '@t3-oss/env-core@0.12.0': + resolution: {integrity: sha512-lOPj8d9nJJTt81mMuN9GMk8x5veOt7q9m11OSnCBJhwp1QrL/qR+M8Y467ULBSm9SunosryWNbmQQbgoiMgcdw==} + peerDependencies: + typescript: '>=5.0.0' + valibot: ^1.0.0-beta.7 || ^1.0.0 + zod: ^3.24.0 + peerDependenciesMeta: + typescript: + optional: true + valibot: + optional: true + zod: + optional: true + '@tokenizer/token@0.3.0': resolution: {integrity: sha512-OvjF+z51L3ov0OyAU0duzsYuvO01PH7x4t6DJx+guahgTnBHkhJdG7soQeTSFLWN3efnHyibZ4Z8l2EuWwJN3A==} @@ -3785,6 +3802,11 @@ snapshots: dependencies: defer-to-connect: 2.0.1 + '@t3-oss/env-core@0.12.0(typescript@5.8.2)(zod@3.24.2)': + optionalDependencies: + typescript: 5.8.2 + zod: 3.24.2 + '@tokenizer/token@0.3.0': {} '@tootallnate/once@1.1.2': diff --git a/scripts/delete-commands.ts b/scripts/delete-commands.ts index 702c513..9fb9ac7 100644 --- a/scripts/delete-commands.ts +++ b/scripts/delete-commands.ts @@ -2,7 +2,7 @@ import { REST, Routes } from "discord.js" import env from "../src/utils/Env" import { log } from "../src/utils/Logger.js" -const rest = new REST({ version: "10" }).setToken(env.dev.devtoken) +const rest = new REST({ version: "10" }).setToken(env.dev.DEVTOKEN) try { log("Started deleting application (/) commands.", "info") diff --git a/scripts/deploy-commands.ts b/scripts/deploy-commands.ts index 857c854..6298926 100644 --- a/scripts/deploy-commands.ts +++ b/scripts/deploy-commands.ts @@ -3,7 +3,7 @@ import fs from "node:fs" import { ICommand } from "../src/interfaces" import env from "../src/utils/Env" import { log } from "../src/utils/Logger.js" -const rest = new REST({ version: "10" }).setToken(env.prod.token) +const rest = new REST({ version: "10" }).setToken(env.prod.TOKEN) const commands: RESTPutAPIApplicationCommandsJSONBody = [] const commandFiles = fs.readdirSync("./src/commands").filter(file => file.endsWith(".ts")) diff --git a/scripts/dev-deploy.ts b/scripts/dev-deploy.ts index 18e8c8a..c9e61b0 100644 --- a/scripts/dev-deploy.ts +++ b/scripts/dev-deploy.ts @@ -3,7 +3,7 @@ import fs from "fs" import { ICommand } from "../src/interfaces" import env from "../src/utils/Env" import { log } from "../src/utils/Logger.js" -const rest = new REST({ version: "10" }).setToken(env.dev.devtoken) +const rest = new REST({ version: "10" }).setToken(env.dev.DEVTOKEN) const commands: RESTPutAPIApplicationCommandsJSONBody = [] const commandFiles = fs.readdirSync("./src/commands/").filter(file => file.endsWith(".ts")) diff --git a/src/commands/pp.ts b/src/commands/pp.ts index 1840e4c..b610546 100644 --- a/src/commands/pp.ts +++ b/src/commands/pp.ts @@ -24,7 +24,7 @@ export default { const user = (interaction.options.getUser("user") || interaction.user) as User let size: number - if (user.id === env.prod.dev) { + if (user.id === env.prod.DEV) { size = Math.floor(Math.random() * 30) + 1 } else { size = Math.floor(Math.random() * 10) + 1 diff --git a/src/commands/staff/prune.ts b/src/commands/staff/prune.ts index 7d3e54f..e0e711a 100644 --- a/src/commands/staff/prune.ts +++ b/src/commands/staff/prune.ts @@ -6,7 +6,7 @@ import env from "~/utils/Env.js" const cmd: SubCommand = async (interaction) => { await interaction.deferReply() - if (interaction.user.id !== env.prod.dev) { + if (interaction.user.id !== env.prod.DEV) { await interaction.editReply("You are not allowed to use this command.") return } diff --git a/src/commands/staff/removeguildroles.ts b/src/commands/staff/removeguildroles.ts index 58fab8a..6be6799 100644 --- a/src/commands/staff/removeguildroles.ts +++ b/src/commands/staff/removeguildroles.ts @@ -11,7 +11,7 @@ const cmd: SubCommand = async (interaction) => { const discordMember = interaction.member as GuildMember - if (discordMember.user.id !== env.prod.dev) { + if (discordMember.user.id !== env.prod.DEV) { await interaction.editReply({ embeds: [{ description: "You do not have permission to use this command.", diff --git a/src/commands/staff/updateall.ts b/src/commands/staff/updateall.ts index df42da4..92fbce1 100644 --- a/src/commands/staff/updateall.ts +++ b/src/commands/staff/updateall.ts @@ -24,7 +24,7 @@ const cmd: SubCommand = async (interaction) => { return } - if (discordMember.user.id !== env.prod.dev) { + if (discordMember.user.id !== env.prod.DEV) { await interaction.editReply({ embeds: [{ description: "You do not have permission to use this command.", diff --git a/src/commands/timeout.ts b/src/commands/timeout.ts index 6545708..f233574 100644 --- a/src/commands/timeout.ts +++ b/src/commands/timeout.ts @@ -41,6 +41,8 @@ export default { const timeString = interaction.options.getString("time")! const reason = interaction.options.getString("reason") || "No reason provided" const mod = interaction.member! as GuildMember + // FIXME: report error to ms manitainer + // @ts-expect-error: i'll file a bu report later const time = ms(timeString) if (!time) { diff --git a/src/components/buttons/staffapply.ts b/src/components/buttons/staffapply.ts index 5df8b65..566c5c9 100644 --- a/src/components/buttons/staffapply.ts +++ b/src/components/buttons/staffapply.ts @@ -30,7 +30,7 @@ export default { if (interaction.customId === "staffapply") { await interaction.deferReply({ flags: MessageFlags.Ephemeral }) - if (user.user.id !== env.prod.dev) { + if (user.user.id !== env.prod.DEV) { if (status === "0") { await interaction.editReply("Staff applications are currently closed.") return diff --git a/src/drizzle/db.ts b/src/drizzle/db.ts index ccbc785..66d11d5 100644 --- a/src/drizzle/db.ts +++ b/src/drizzle/db.ts @@ -4,7 +4,7 @@ import * as schema from "./schema.js" const db = drizzle({ connection: { - url: env.prod.postgresURI + url: env.prod.POSTGRESURI }, schema: schema }) diff --git a/src/utils/Autodeploy.ts b/src/utils/Autodeploy.ts index 40a1153..93c0ebd 100644 --- a/src/utils/Autodeploy.ts +++ b/src/utils/Autodeploy.ts @@ -49,7 +49,7 @@ export default async function autoDeployCommands(fileType: FileType, client: Ext }).sort((a, b) => a.name > b.name ? 1 : -1) client.on("ready", async (c) => { - const guildclient = c.guilds.cache.get(env.dev.guildid)! + const guildclient = c.guilds.cache.get(env.dev.GUILDID)! const currentCommands = await guildclient.commands.fetch() if (!currentCommands) return diff --git a/src/utils/Client.ts b/src/utils/Client.ts index a335510..d2b70ad 100644 --- a/src/utils/Client.ts +++ b/src/utils/Client.ts @@ -34,15 +34,15 @@ export class ExtendedClient extends Client { let token: string if (process.env.NODE_ENV === "dev" && process.env.TYPESCRIPT === "true") { log("Running in development mode. [tsx]", "info", { type: "preset", color: "lavender" }) - token = env.dev.devtoken + token = env.dev.DEVTOKEN autoDeployCommands("ts", this) } else if (process.env.NODE_ENV === "dev" && !process.env.TYPESCRIPT) { log("Running in development mode.", "info", { type: "preset", color: "lavender" }) - token = env.dev.devtoken + token = env.dev.DEVTOKEN autoDeployCommands("js", this) } else { log("Running in production mode.", "info", { type: "preset", color: "green" }) - token = env.prod.token + token = env.prod.TOKEN } this.login(token) diff --git a/src/utils/Env.ts b/src/utils/Env.ts index 2494620..a404d99 100644 --- a/src/utils/Env.ts +++ b/src/utils/Env.ts @@ -1,47 +1,42 @@ +import { createEnv } from "@t3-oss/env-core" import { z } from "zod" import { MissingEnvVarsError } from "./Classes/EnvVarError.js" -const prodEnvSchema = z.object({ - token: z.string({ message: "Missing or invalid TOKEN" }), - dev: z.string({ message: "Missing or invalid DEV" }), - hypixelapikey: z.string({ message: "Missing or invalid HYPIXELAPIKEY" }), - redisURI: z.string({ message: "Missing or invalid REDISURI" }), - postgresURI: z.string({ message: "Missing or invalid POSTGRESURI" }) +const prodEnv = createEnv({ + server: { + TOKEN: z.string({ message: "TOKEN" }).min(1), + DEV: z.string({ message: "DEV" }).min(1), + HYPIXELAPIKEY: z.string({ message: "HYPIXELAPIKEY" }).min(1), + REDISURI: z.string({ message: "REDISURI" }).min(1), + POSTGRESURI: z.string({ message: "POSTGRESURI" }).min(1) + }, + runtimeEnv: process.env, + onValidationError: (e) => { + const allErrors = e.map(err => err.message).join(" ") + + throw new MissingEnvVarsError(`[PROD]: ${allErrors}`) + } }) -const devEnvSchema = z.object({ - devtoken: z.string({ message: "Missing or invalid DEVTOKEN" }), - clientid: z.string({ message: "Missing or invalid CLIENTID" }), - devid: z.string({ message: "Missing or invalid DEVID" }), - guildid: z.string({ message: "Missing or invalid GUILDID" }) +const devEnv = createEnv({ + server: { + DEVTOKEN: z.string({ message: "DEVTOKEN" }).min(1), + CLIENTID: z.string({ message: "CLIENTID" }).min(1), + DEVID: z.string({ message: "DEVID" }).min(1), + GUILDID: z.string({ message: "GUILDID" }).min(1) + }, + runtimeEnv: process.env, + skipValidation: process.env.NODE_ENV !== "dev", + onValidationError: (e) => { + const allErrors = e.map(err => err.message).join(" ") + + throw new MissingEnvVarsError(`[DEV]: ${allErrors}`) + } }) -const parsedProdEnv = prodEnvSchema.safeParse({ - token: process.env.TOKEN, - dev: process.env.DEV, - hypixelapikey: process.env.HYPIXELAPIKEY, - redisURI: process.env.REDISURI, - postgresURI: process.env.POSTGRESURI -}) - -const parsedDevEnv = devEnvSchema.safeParse({ - devtoken: process.env.DEVTOKEN, - clientid: process.env.CLIENTID, - devid: process.env.DEVID, - guildid: process.env.GUILDID -}) - -if (!parsedProdEnv.success) { - throw new MissingEnvVarsError(parsedProdEnv.error.errors[0].message) -} - -if (!parsedDevEnv.success && process.env.NODE_ENV === "dev") { - throw new MissingEnvVarsError(parsedDevEnv.error.errors[0].message) -} - const env = { - prod: parsedProdEnv.data, - dev: parsedDevEnv.data -} as { prod: z.infer, dev: z.infer } + prod: prodEnv, + dev: devEnv +} export default env diff --git a/src/utils/HypixelFunctions/account.ts b/src/utils/HypixelFunctions/account.ts index 6a0a478..92093af 100644 --- a/src/utils/HypixelFunctions/account.ts +++ b/src/utils/HypixelFunctions/account.ts @@ -1,7 +1,7 @@ import axios from "axios" import { IGuild, IGuildData, IPlayer, IPlayerData } from "~/typings" import env from "~/utils/Env.js" -const apikey = env.prod.hypixelapikey +const apikey = env.prod.HYPIXELAPIKEY const mojang = "https://api.mojang.com/users/profiles/minecraft/" const mojanguuid = "https://sessionserver.mojang.com/session/minecraft/profile/" const hypixel = "https://api.hypixel.net/v2/player" diff --git a/src/utils/Illegitimate.ts b/src/utils/Illegitimate.ts index c056839..328de49 100644 --- a/src/utils/Illegitimate.ts +++ b/src/utils/Illegitimate.ts @@ -8,7 +8,7 @@ import loadAllEvents from "./Events/loadevents.js" import { log } from "./Logger.js" const client = new Client() -const redis = new Redis(env.prod.redisURI) +const redis = new Redis(env.prod.REDISURI) const player = new Player(client) let ft: "js" | "ts"