diff --git a/README.md b/README.md index e2dacbc..910c5b2 100644 --- a/README.md +++ b/README.md @@ -79,13 +79,13 @@ An example with two bot services is available in `docker-compose.multi-bot.examp ## Architecture -- `src/framework/types/command.ts`: strict command schema -- `src/framework/commands/defineCommand.ts`: default command completion -- `src/framework/commands/registry.ts`: trigger/name mapping generated from i18n dictionaries -- `src/framework/commands/argParser.ts`: prefix/slash args parsing from schema -- `src/framework/execution/CommandExecutor.ts`: unified pipeline (permissions/cooldown/execute) -- `src/framework/handlers/prefixHandler.ts`: prefix entrypoint -- `src/framework/handlers/slashHandler.ts`: slash entrypoint +- `src/types/command.ts`: strict command schema +- `src/core/commands/defineCommand.ts`: default command completion +- `src/core/commands/registry.ts`: trigger/name mapping generated from i18n dictionaries +- `src/core/commands/argParser.ts`: prefix/slash args parsing from schema +- `src/core/execution/CommandExecutor.ts`: unified pipeline (permissions/cooldown/execute) +- `src/handlers/prefixHandler.ts`: prefix entrypoint +- `src/handlers/slashHandler.ts`: slash entrypoint - `src/database/presence/presenceStore.ts`: PostgreSQL presence storage - `src/types/presenceTypes.ts`: shared presence types/validation - `src/i18n/*.json`: external i18n dictionaries @@ -102,6 +102,6 @@ An example with two bot services is available in `docker-compose.multi-bot.examp ## Adding A Command 1. Create a command object in `src/commands/...` -2. Follow the schema in `src/framework/types/command.ts` +2. Follow the schema in `src/types/command.ts` 3. Add command to `src/commands/index.ts` 4. If `AUTO_DEPLOY_SLASH=true`, restart the bot to sync slash commands automatically diff --git a/src/commands/goodbye.ts b/src/commands/goodbye.ts index 5da5101..e8b81ff 100644 --- a/src/commands/goodbye.ts +++ b/src/commands/goodbye.ts @@ -6,7 +6,7 @@ */ import { PermissionFlagsBits } from "discord.js"; -import { defineCommand } from "../framework/commands/defineCommand.js"; +import { defineCommand } from "../core/commands/defineCommand.js"; import { createMemberMessageExecute } from "./memberMessagePanel.js"; /** Commande `goodbye` — ouvre le panneau de configuration des messages 'goodbye'. */ diff --git a/src/commands/help.ts b/src/commands/help.ts index 82b21d6..d3066fb 100644 --- a/src/commands/help.ts +++ b/src/commands/help.ts @@ -9,8 +9,8 @@ */ import { EmbedBuilder } from "discord.js"; -import { buildPrefixUsage, buildSlashUsage, resolvePrefixTrigger, resolveSlashName } from "../framework/commands/usage.js"; -import { defineCommand } from "../framework/commands/defineCommand.js"; +import { buildPrefixUsage, buildSlashUsage, resolvePrefixTrigger, resolveSlashName } from "../core/commands/usage.js"; +import { defineCommand } from "../core/commands/defineCommand.js"; import type { BotCommand, CommandExecutionContext } from "../types/command.js"; const categoryName = (command: BotCommand): string => command.meta.category; diff --git a/src/commands/kiss.ts b/src/commands/kiss.ts index 93c760b..eff2e16 100644 --- a/src/commands/kiss.ts +++ b/src/commands/kiss.ts @@ -4,7 +4,7 @@ * Envoie une réponse de type `kissing` ciblant un utilisateur mentionné. * Utilise un seul argument `user` de type `user`. */ -import { defineCommand } from "../framework/commands/defineCommand.js"; +import { defineCommand } from "../core/commands/defineCommand.js"; /** Commande `kiss` — envoie un message de type `kiss` vers la cible. */ export const kissCommand = defineCommand({ diff --git a/src/commands/memberMessagePanel.ts b/src/commands/memberMessagePanel.ts index e89b4d4..13dcf2c 100644 --- a/src/commands/memberMessagePanel.ts +++ b/src/commands/memberMessagePanel.ts @@ -22,9 +22,9 @@ import { type Message, } from "discord.js"; -import { env } from "../framework/config/env.js"; +import { env } from "../config/env.js"; import { I18nService } from "../i18n/index.js"; -import { dispatchMemberMessage } from "../framework/memberMessages/memberMessageSender.js"; +import { dispatchMemberMessage } from "../services/memberMessages/memberMessageSender.js"; import { getMemberMessageStore } from "../database/memberMessages/memberMessageStore.js"; import { MEMBER_MESSAGE_RENDER_TYPES, diff --git a/src/commands/ping.ts b/src/commands/ping.ts index 7bf364f..dbc3134 100644 --- a/src/commands/ping.ts +++ b/src/commands/ping.ts @@ -4,7 +4,7 @@ * Répond avec un message court contenant la latence websocket du bot. */ import { MessageFlags } from "discord.js"; -import { defineCommand } from "../framework/commands/defineCommand.js"; +import { defineCommand } from "../core/commands/defineCommand.js"; /** Commande `ping` — affiche la latence du bot. */ export const pingCommand = defineCommand({ diff --git a/src/commands/presence.ts b/src/commands/presence.ts index 007a19d..ad6531f 100644 --- a/src/commands/presence.ts +++ b/src/commands/presence.ts @@ -21,8 +21,8 @@ import { type Client, type Message, } from "discord.js"; -import { defineCommand } from "../framework/commands/defineCommand.js"; -import { env } from "../framework/config/env.js"; +import { defineCommand } from "../core/commands/defineCommand.js"; +import { env } from "../config/env.js"; import type { DiscordPresenceStatus, PresenceActivityTypeValue, @@ -38,7 +38,7 @@ import { containsPresenceTemplateVariables, getPresenceTemplateHelpText, renderPresenceTemplate, -} from "../framework/presence/presenceTemplateVariables.js"; +} from "../services/presence/presenceTemplateVariables.js"; import { PRESENCE_ACTIVITY_TYPES, PRESENCE_STATUSES, diff --git a/src/commands/welcome.ts b/src/commands/welcome.ts index 8fa5327..be3b559 100644 --- a/src/commands/welcome.ts +++ b/src/commands/welcome.ts @@ -6,7 +6,7 @@ */ import { PermissionFlagsBits } from "discord.js"; -import { defineCommand } from "../framework/commands/defineCommand.js"; +import { defineCommand } from "../core/commands/defineCommand.js"; import { createMemberMessageExecute } from "./memberMessagePanel.js"; /** Commande `welcome` — ouvre le panneau de configuration des messages 'welcome'. */ diff --git a/src/framework/config/env.ts b/src/config/env.ts similarity index 94% rename from src/framework/config/env.ts rename to src/config/env.ts index f30b149..ad5f6ee 100644 --- a/src/framework/config/env.ts +++ b/src/config/env.ts @@ -1,7 +1,7 @@ import { config as loadEnv } from "dotenv"; import { z } from "zod"; -import { SUPPORTED_LANGS } from "../../types/command.js"; +import { SUPPORTED_LANGS } from "../types/command.js"; loadEnv(); diff --git a/src/framework/commands/argParser.ts b/src/core/commands/argParser.ts similarity index 100% rename from src/framework/commands/argParser.ts rename to src/core/commands/argParser.ts diff --git a/src/framework/commands/defineCommand.ts b/src/core/commands/defineCommand.ts similarity index 100% rename from src/framework/commands/defineCommand.ts rename to src/core/commands/defineCommand.ts diff --git a/src/framework/commands/deploy.ts b/src/core/commands/deploy.ts similarity index 100% rename from src/framework/commands/deploy.ts rename to src/core/commands/deploy.ts diff --git a/src/framework/commands/registry.ts b/src/core/commands/registry.ts similarity index 100% rename from src/framework/commands/registry.ts rename to src/core/commands/registry.ts diff --git a/src/framework/commands/slashBuilder.ts b/src/core/commands/slashBuilder.ts similarity index 100% rename from src/framework/commands/slashBuilder.ts rename to src/core/commands/slashBuilder.ts diff --git a/src/framework/commands/usage.ts b/src/core/commands/usage.ts similarity index 100% rename from src/framework/commands/usage.ts rename to src/core/commands/usage.ts diff --git a/src/framework/execution/CommandExecutor.ts b/src/core/execution/CommandExecutor.ts similarity index 100% rename from src/framework/execution/CommandExecutor.ts rename to src/core/execution/CommandExecutor.ts diff --git a/src/database/memberMessages/memberMessageStore.ts b/src/database/memberMessages/memberMessageStore.ts index edeca4f..f97676a 100644 --- a/src/database/memberMessages/memberMessageStore.ts +++ b/src/database/memberMessages/memberMessageStore.ts @@ -1,6 +1,6 @@ import { Pool } from "pg"; -import { env } from "../../framework/config/env.js"; +import { env } from "../../config/env.js"; import type { MemberMessageConfig, MemberMessageKind, diff --git a/src/database/presence/presenceStore.ts b/src/database/presence/presenceStore.ts index 2604cc9..9f039f4 100644 --- a/src/database/presence/presenceStore.ts +++ b/src/database/presence/presenceStore.ts @@ -1,6 +1,6 @@ import { Pool } from "pg"; -import { env } from "../../framework/config/env.js"; +import { env } from "../../config/env.js"; import type { PresenceActivityTypeValue, PresenceRow, diff --git a/src/events/guildMemberAdd.ts b/src/events/guildMemberAdd.ts index 107d8ca..9b6213c 100644 --- a/src/events/guildMemberAdd.ts +++ b/src/events/guildMemberAdd.ts @@ -1,6 +1,6 @@ import { Events, type Client } from "discord.js"; import type { I18nService } from "../i18n/index.js"; -import { dispatchMemberMessage } from "../framework/memberMessages/memberMessageSender.js"; +import { dispatchMemberMessage } from "../services/memberMessages/memberMessageSender.js"; /** * Enregistre le listener `guildMemberAdd` et déclenche l'envoi d'un message diff --git a/src/events/guildMemberRemove.ts b/src/events/guildMemberRemove.ts index d941ea4..735ae2b 100644 --- a/src/events/guildMemberRemove.ts +++ b/src/events/guildMemberRemove.ts @@ -1,6 +1,6 @@ import { Events, type Client } from "discord.js"; import type { I18nService } from "../i18n/index.js"; -import { dispatchMemberMessage } from "../framework/memberMessages/memberMessageSender.js"; +import { dispatchMemberMessage } from "../services/memberMessages/memberMessageSender.js"; /** * Enregistre le listener `guildMemberRemove` et déclenche l'envoi d'un message diff --git a/src/events/index.ts b/src/events/index.ts index a7f1725..6e8c294 100644 --- a/src/events/index.ts +++ b/src/events/index.ts @@ -8,7 +8,7 @@ import { registerGuildMemberRemove } from "./guildMemberRemove.js"; import { registerGuildCreate } from "./guildCreate.js"; import { registerGuildDelete } from "./guildDelete.js"; import { registerClientReady } from "./ready.js"; -import type { CommandRegistry } from "../framework/commands/registry.js"; +import type { CommandRegistry } from "../core/commands/registry.js"; /** * Regroupe l'enregistrement des événements Discord les plus courants. diff --git a/src/events/ready.ts b/src/events/ready.ts index 3f9c6e3..6b9e1e4 100644 --- a/src/events/ready.ts +++ b/src/events/ready.ts @@ -1,8 +1,8 @@ import { Events, type Client } from "discord.js"; -import { deployApplicationCommands } from "../framework/commands/deploy.js"; -import { env } from "../framework/config/env.js"; +import { deployApplicationCommands } from "../core/commands/deploy.js"; +import { env } from "../config/env.js"; import { restorePresenceFromStorage } from "../commands/presence.js"; -import type { CommandRegistry } from "../framework/commands/registry.js"; +import type { CommandRegistry } from "../core/commands/registry.js"; import type { I18nService } from "../i18n/index.js"; /** diff --git a/src/handlers/prefixHandler.ts b/src/handlers/prefixHandler.ts index 041bd61..eaadff3 100644 --- a/src/handlers/prefixHandler.ts +++ b/src/handlers/prefixHandler.ts @@ -2,8 +2,8 @@ import type { Message } from "discord.js"; import type { BotCommand, SupportedLang } from "../types/command.js"; import type { PrefixHandlerDeps } from "../types/handlers.js"; -import { parsePrefixArgs } from "../framework/commands/argParser.js"; -import { buildPrefixUsage } from "../framework/commands/usage.js"; +import { parsePrefixArgs } from "../core/commands/argParser.js"; +import { buildPrefixUsage } from "../core/commands/usage.js"; import { buildCommandExecutionContext, createTranslator, diff --git a/src/handlers/slashHandler.ts b/src/handlers/slashHandler.ts index 85f5593..52b96cf 100644 --- a/src/handlers/slashHandler.ts +++ b/src/handlers/slashHandler.ts @@ -1,8 +1,8 @@ import { MessageFlags, type ChatInputCommandInteraction } from "discord.js"; import type { SlashHandlerDeps } from "../types/handlers.js"; -import { parseSlashArgs } from "../framework/commands/argParser.js"; -import { buildSlashUsage } from "../framework/commands/usage.js"; +import { parseSlashArgs } from "../core/commands/argParser.js"; +import { buildSlashUsage } from "../core/commands/usage.js"; import { buildCommandExecutionContext, createTranslator, diff --git a/src/index.ts b/src/index.ts index 951e1a1..0921f7b 100644 --- a/src/index.ts +++ b/src/index.ts @@ -13,9 +13,9 @@ import { Client, GatewayIntentBits } from "discord.js"; import { commandList } from "./commands/index.js"; import { shutdownPresenceRuntime } from "./commands/presence.js"; import { registerEvents } from "./events/index.js"; -import { CommandRegistry } from "./framework/commands/registry.js"; -import { env } from "./framework/config/env.js"; -import { CommandExecutor } from "./framework/execution/CommandExecutor.js"; +import { CommandRegistry } from "./core/commands/registry.js"; +import { env } from "./config/env.js"; +import { CommandExecutor } from "./core/execution/CommandExecutor.js"; import { createPrefixHandler } from "./handlers/prefixHandler.js"; import { createSlashHandler } from "./handlers/slashHandler.js"; import { I18nService } from "./i18n/index.js"; diff --git a/src/framework/memberMessages/memberMessageImage.ts b/src/services/memberMessages/memberMessageImage.ts similarity index 100% rename from src/framework/memberMessages/memberMessageImage.ts rename to src/services/memberMessages/memberMessageImage.ts diff --git a/src/framework/memberMessages/memberMessageSender.ts b/src/services/memberMessages/memberMessageSender.ts similarity index 100% rename from src/framework/memberMessages/memberMessageSender.ts rename to src/services/memberMessages/memberMessageSender.ts diff --git a/src/framework/presence/presenceTemplateVariables.ts b/src/services/presence/presenceTemplateVariables.ts similarity index 95% rename from src/framework/presence/presenceTemplateVariables.ts rename to src/services/presence/presenceTemplateVariables.ts index 2f8a291..cf730c2 100644 --- a/src/framework/presence/presenceTemplateVariables.ts +++ b/src/services/presence/presenceTemplateVariables.ts @@ -1,7 +1,7 @@ import type { Client } from "discord.js"; -import { env } from "../config/env.js"; -import { hasTemplateVariable, renderTemplate } from "../utils/templateVariables.js"; +import { env } from "../../config/env.js"; +import { hasTemplateVariable, renderTemplate } from "../../utils/templateVariables.js"; import { sanitizeActivityText } from "../../types/presenceTypes.js"; export const PRESENCE_TEMPLATE_REFRESH_INTERVAL_MS = 60_000; diff --git a/src/types/deploy.ts b/src/types/deploy.ts index 228eda9..da28ae8 100644 --- a/src/types/deploy.ts +++ b/src/types/deploy.ts @@ -1,4 +1,4 @@ -import type { CommandRegistry } from "../framework/commands/registry.js"; +import type { CommandRegistry } from "../core/commands/registry.js"; import type { I18nService } from "../i18n/index.js"; export interface DeployCommandsOptions { diff --git a/src/types/handlers.ts b/src/types/handlers.ts index 7c1ce28..a1f48df 100644 --- a/src/types/handlers.ts +++ b/src/types/handlers.ts @@ -1,5 +1,5 @@ -import type { CommandRegistry } from "../framework/commands/registry.js"; -import type { CommandExecutor } from "../framework/execution/CommandExecutor.js"; +import type { CommandRegistry } from "../core/commands/registry.js"; +import type { CommandExecutor } from "../core/execution/CommandExecutor.js"; import type { I18nService } from "../i18n/index.js"; import type { BotCommand, diff --git a/src/framework/utils/templateVariables.ts b/src/utils/templateVariables.ts similarity index 97% rename from src/framework/utils/templateVariables.ts rename to src/utils/templateVariables.ts index 3ed9839..cae9818 100644 --- a/src/framework/utils/templateVariables.ts +++ b/src/utils/templateVariables.ts @@ -1,4 +1,4 @@ -import type { TemplateRenderOptions } from "../../types/templateVariables.js"; +import type { TemplateRenderOptions } from "../types/templateVariables.js"; const createTemplateTokenRegex = (): RegExp => /\{\{([a-zA-Z0-9_]+)\}\}/g; diff --git a/tests/argTokenizer.test.ts b/tests/argTokenizer.test.ts index 94e4939..caeb4ce 100644 --- a/tests/argTokenizer.test.ts +++ b/tests/argTokenizer.test.ts @@ -1,7 +1,7 @@ import assert from "node:assert/strict"; import test from "node:test"; -import { tokenizePrefixInput } from "../src/framework/commands/argParser.js"; +import { tokenizePrefixInput } from "../src/core/commands/argParser.js"; test("tokenizePrefixInput parse les quotes simples et doubles", () => { const tokens = tokenizePrefixInput('"hello world" test \'foo bar\''); diff --git a/tests/defineCommand.test.ts b/tests/defineCommand.test.ts index f8cd76f..26d571b 100644 --- a/tests/defineCommand.test.ts +++ b/tests/defineCommand.test.ts @@ -1,7 +1,7 @@ import assert from "node:assert/strict"; import test from "node:test"; -import { defineCommand } from "../src/framework/commands/defineCommand.js"; +import { defineCommand } from "../src/core/commands/defineCommand.js"; test("defineCommand refuse un argument requis apres un optionnel", () => { assert.throws(() => { diff --git a/tests/templateVariables.test.ts b/tests/templateVariables.test.ts index b452b59..3375aa7 100644 --- a/tests/templateVariables.test.ts +++ b/tests/templateVariables.test.ts @@ -5,7 +5,7 @@ import { extractTemplateVariables, hasTemplateVariable, renderTemplate, -} from "../src/framework/utils/templateVariables.js"; +} from "../src/utils/templateVariables.js"; test("renderTemplate remplace les variables et applique les alias", () => { const output = renderTemplate(