Skip to content
This repository was archived by the owner on Feb 24, 2025. It is now read-only.

Commit 0cbd174

Browse files
committed
feat: add better help command and command module
1 parent 767c1af commit 0cbd174

File tree

17 files changed

+255
-199
lines changed

17 files changed

+255
-199
lines changed

biome.json

Lines changed: 9 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,21 @@
11
{
22
"$schema": "https://biomejs.dev/schemas/1.8.3/schema.json",
3+
"organizeImports": { "enabled": true },
4+
"formatter": {
5+
"enabled": true,
6+
"lineWidth": 100,
7+
"lineEnding": "lf",
8+
"indentWidth": 4,
9+
"indentStyle": "space",
10+
"formatWithErrors": true
11+
},
312
"javascript": {
413
"formatter": {
514
"semicolons": "asNeeded",
615
"quoteStyle": "double",
716
"trailingCommas": "es5"
817
}
918
},
10-
"organizeImports": {
11-
"enabled": true
12-
},
1319
"json": {
1420
"formatter": {
1521
"enabled": true,
@@ -19,14 +25,6 @@
1925
"indentStyle": "space"
2026
}
2127
},
22-
"formatter": {
23-
"enabled": true,
24-
"lineWidth": 100,
25-
"lineEnding": "lf",
26-
"indentWidth": 4,
27-
"indentStyle": "space",
28-
"formatWithErrors": true
29-
},
3028
"linter": {
3129
"ignore": ["dist", "**/dist", "commitlint.config.js", "pre-commit.js"],
3230
"enabled": true,
@@ -83,7 +81,6 @@
8381
"useConst": "error"
8482
},
8583
"suspicious": {
86-
"noConsoleLog": "info",
8784
"noAsyncPromiseExecutor": "error",
8885
"noCatchAssign": "error",
8986
"noClassAssign": "error",

bun.lockb

2.25 KB
Binary file not shown.

package.json

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -7,16 +7,16 @@
77
"main": "src/index.ts",
88
"scripts": {
99
"start": "bun run dist/index.js",
10-
"build:start": "bun exec tsc && bun run dist/.",
10+
"build:start": "bun run --bun tsc && bun run dist/.",
1111
"nodemon": "nodemon dist/.",
1212
"dev": "bun run --watch src/index.ts",
13-
"build": "tsc",
14-
"watch": "tsc -w",
13+
"build": "bun run --bun tsc",
14+
"watch": "bun run --bun tsc -w",
1515
"prepare": "bunx husky",
16-
"lint": "biome lint",
17-
"lint:fix": "biome lint --fix",
16+
"lint": "biome lint --no-errors-on-unmatched",
17+
"lint:fix": "biome lint --fix --no-errors-on-unmatched",
1818
"format": "biome check --write --no-errors-on-unmatched --linter-enabled=false --formatter-enabled=true --organize-imports-enabled=true",
19-
"ci": "biome ci --no-errors-on-unmatched --formatter-enabled=true --linter-enabled=true --organize-imports-enabled=true ."
19+
"ci": "biome ci --no-errors-on-unmatched --formatter-enabled=true --linter-enabled=true --organize-imports-enabled=true"
2020
},
2121
"lint-staged": {
2222
"*.{ts,cts,mts,js,cjs,mjs}": "biome lint --fix",
@@ -26,16 +26,17 @@
2626
"license": "MIT",
2727
"devDependencies": {
2828
"@biomejs/biome": "^1.8.3",
29-
"@commitlint/cli": "^19.4.0",
30-
"@commitlint/config-conventional": "^19.2.2",
29+
"@commitlint/cli": "^19.4.1",
30+
"@commitlint/config-conventional": "^19.4.1",
31+
"@types/bun": "^1.1.8",
3132
"@types/glob": "^8.1.0",
32-
"@types/node": "^22.5.0",
33-
"commitlint": "^19.4.0",
33+
"@types/node": "^22.5.3",
34+
"commitlint": "^19.4.1",
3435
"typescript": "^5.5.4"
3536
},
3637
"dependencies": {
37-
"chalk": "^4.1.2",
38-
"discord.js": "^14.15.3",
38+
"chalk": "^5.3.0",
39+
"discord.js": "^14.16.1",
3940
"dotenv": "^16.4.5",
4041
"glob": "^11.0.0",
4142
"smol-toml": "^1.3.0",
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
import { EmbedBuilder, type EmbedField, codeBlock } from "discord.js"
2+
import { string } from "zod"
3+
import Command from "../../../../structures/Command.js"
4+
import type { CommandType } from "../../../../typings/Commands.js"
5+
6+
// A sub commands of help
7+
export default new Command({
8+
data: {
9+
name: "list",
10+
description: "Get a list of all available commands.",
11+
},
12+
async run(command) {
13+
const commands = Array.from(command.client.commands)
14+
15+
if (commands.length < 1) return await command.reply("There are no commands available")
16+
17+
type SimplifiedHelpCommand = { name: string; body: CommandType }
18+
const helpMap = new Map<string, SimplifiedHelpCommand[]>()
19+
for (const [name, body] of commands) {
20+
const commandHelp = { name, body }
21+
22+
// biome-ignore lint/style/noNonNullAssertion: Categories are set during command modules register
23+
const category = body.category!
24+
25+
const existingCommandHelp = helpMap.get(category)
26+
if (Array.isArray(existingCommandHelp)) {
27+
helpMap.set(category, [...existingCommandHelp, commandHelp])
28+
} else {
29+
helpMap.set(category, [commandHelp])
30+
}
31+
}
32+
33+
const helpArr = Array.from(helpMap).sort(([categoryA], [categoryB]) => {
34+
return categoryA.localeCompare(categoryB)
35+
})
36+
37+
let content = "## List of all available commands"
38+
for (const [category, commands] of helpArr) {
39+
content += `\n### ${category}`
40+
for (const cmd of commands.toSorted((a, b) => a.name.localeCompare(b.name))) {
41+
content += `\n\`/${cmd.name.replace("-", " ")}\`: ${cmd.body.data.description}`
42+
}
43+
}
44+
45+
await command.reply(content)
46+
},
47+
})

src/commands/Miscellaneous/help/commands.ts

Lines changed: 0 additions & 39 deletions
This file was deleted.

src/events/ready.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,12 @@ export default new Event("ready", async (baseClient) => {
66
// HACK: This one just for setting proper type
77
const client = baseClient as ExtendedClient
88
LogStart(client)
9+
910
for (const guildId of global.config.devGuilds) {
10-
await client.registerCommands(guildId)
11+
try {
12+
await client.registerCommands(guildId)
13+
} catch (error) {
14+
console.error(error)
15+
}
1116
}
1217
})

src/functions/log/Color.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import chalk from "chalk"
2+
3+
export default class Print {
4+
static title(...text: unknown[]) {
5+
console.log(chalk.bold(chalk.green(...text)))
6+
}
7+
8+
static gray(...text: unknown[]) {
9+
console.log(chalk.bold(chalk.gray(...text)))
10+
}
11+
}

src/functions/log/logger.ts

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,21 +2,20 @@ import chalk from "chalk"
22
import { type DateResolvable, EmbedBuilder, type Guild, WebhookClient } from "discord.js"
33
import type ExtendedClient from "../../structures/Client.js"
44
import { getDynamicTime } from "../discord/getDynamicTime.js"
5+
import Print from "./Color.js"
56

67
const detailedTime = (date: DateResolvable | null | undefined) =>
78
date ? `${getDynamicTime(date, "LONG_TIME_AND_DATE")} ${getDynamicTime(date, "RELATIVE")}` : ""
89

910
export const coloredLog = (text: string, color: string) => {
10-
// biome-ignore lint/suspicious/noConsoleLog: Log
1111
console.log(chalk.hex(color)(text))
1212
}
13-
export const logSuccess = (str: string) => coloredLog(str, "#0f0")
1413
export const LogFail = (str: string | Error) => {
1514
coloredLog(typeof str === "string" ? str : str.message, "#f00")
1615
}
1716

1817
export const LogStart = (client: ExtendedClient) => {
19-
logSuccess(`${client.user.username} is ready.`)
18+
Print.title(`[Ready] ${client.user.username}:${client.user.id}.`)
2019
if (!process.env.LOGIN) return
2120
const webhook = new WebhookClient({ url: process.env.LOGIN })
2221

@@ -73,7 +72,7 @@ export const logError = (error: Error | unknown) => {
7372

7473
export const guildLog = (guild: Guild, event: "CREATE" | "DELETE") => {
7574
event === "CREATE"
76-
? logSuccess(`Guild Create: ${guild.name}`)
75+
? Print.title(`Guild Create: ${guild.name}`)
7776
: LogFail(`Guild Remove: ${guild.name}`)
7877

7978
if (!process.env.GUILDS) return

src/index.ts

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,24 @@
1-
import { config } from "dotenv"
21
import { z } from "zod"
2+
import { logError } from "./functions/log/logger.js"
33
import loadConfig from "./loadConfig.js"
44
import ExtendedClient from "./structures/Client.js"
55

6-
config()
7-
86
await loadConfig()
97

10-
const envSchema = z.object({
11-
DISCORD: z.string(),
12-
})
8+
const envSchema = z.object({ DISCORD: z.string() })
139

1410
envSchema.parse(process.env)
1511

1612
declare global {
17-
// biome-ignore lint/style/noNamespace: <explanation>
13+
// biome-ignore lint/style/noNamespace: Add typing to environment
1814
namespace NodeJS {
1915
interface ProcessEnv extends z.infer<typeof envSchema> {}
2016
}
2117
}
18+
if (global.config.globalErrorHandling) {
19+
process.on("uncaughtException", (error) => logError(error))
20+
process.on("uncaughtExceptionMonitor", (error) => logError(error))
21+
}
2222

2323
const client = new ExtendedClient()
2424

src/loadConfig.ts

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import { readFile, writeFile } from "node:fs/promises"
2-
import chalk from "chalk"
32
import TOML from "smol-toml"
43
import { z } from "zod"
54
import { logError } from "./functions/log/logger.js"
@@ -10,6 +9,7 @@ const configSchema = z
109
developers: z.array(z.string()),
1110
testers: z.array(z.string()),
1211
commandTimeout: z.number(),
12+
globalErrorHandling: z.boolean(),
1313
color: z.number(),
1414
colors: z.object({
1515
default: z.number(),
@@ -46,19 +46,22 @@ export default async function loadConfig() {
4646
logError(config.error)
4747
process.exit(1)
4848
}
49-
} catch (_error) {
49+
} catch (error) {
50+
console.error(error)
51+
5052
const data = TOML.stringify({
5153
devGuilds: [],
5254
developers: [],
5355
testers: [],
5456
commandTimeout: 5_000,
57+
globalErrorHandling: true,
5558
color: 0x2f3136,
5659
colors: {
5760
default: 0x2f3136,
5861
warn: 0xffff00,
5962
error: 0xff0000,
6063
},
61-
})
64+
} satisfies z.infer<typeof configSchema>)
6265

6366
await writeFile("./config.toml", data, "utf8")
6467
}

0 commit comments

Comments
 (0)