diff --git a/src/commands/help.ts b/src/commands/help.ts index f257cb3..82b21d6 100644 --- a/src/commands/help.ts +++ b/src/commands/help.ts @@ -11,7 +11,7 @@ import { EmbedBuilder } from "discord.js"; import { buildPrefixUsage, buildSlashUsage, resolvePrefixTrigger, resolveSlashName } from "../framework/commands/usage.js"; import { defineCommand } from "../framework/commands/defineCommand.js"; -import type { BotCommand, CommandExecutionContext } from "../framework/types/command.js"; +import type { BotCommand, CommandExecutionContext } from "../types/command.js"; const categoryName = (command: BotCommand): string => command.meta.category; diff --git a/src/commands/index.ts b/src/commands/index.ts index 16cce2f..5372092 100644 --- a/src/commands/index.ts +++ b/src/commands/index.ts @@ -11,7 +11,7 @@ import { presenceCommand } from "./presence.js"; import { pingCommand } from "./ping.js"; import { welcomeCommand } from "./welcome.js"; -import type { BotCommand } from "../framework/types/command.js"; +import type { BotCommand } from "../types/command.js"; /** CommandList: tableau ordonné des commandes disponibles. */ export const commandList: BotCommand[] = [ diff --git a/src/commands/memberMessagePanel.ts b/src/commands/memberMessagePanel.ts index 402fc04..b10cba9 100644 --- a/src/commands/memberMessagePanel.ts +++ b/src/commands/memberMessagePanel.ts @@ -29,32 +29,19 @@ import { getMemberMessageStore } from "../framework/memberMessages/memberMessage import { MEMBER_MESSAGE_RENDER_TYPES, isMemberMessageRenderTypeValue, - type MemberMessageConfig, - type MemberMessageKind, - type MemberMessageRenderType, } from "../framework/memberMessages/memberMessageTypes.js"; -import type { CommandExecutionContext } from "../framework/types/command.js"; +import type { CommandExecutionContext } from "../types/command.js"; +import type { + MemberMessageConfig, + MemberMessageCustomIds, + MemberMessageKind, + MemberMessagePanelSession, + MemberMessagePanelUiState, + MemberMessageRenderType, +} from "../types/memberMessages.js"; const memberMessageI18n = new I18nService(env.DEFAULT_LANG); -interface MemberMessageCustomIds { - toggleButton: string; - channelButton: string; - channelCancelButton: string; - typeSelect: string; - channelSelect: string; - testButton: string; -} - -interface MemberMessagePanelUiState { - channelPickerOpen: boolean; -} - -interface MemberMessagePanelSession { - collector: ReturnType; - disable: () => Promise; -} - const activePanelsByUser = new Map(); const panelSessionKey = (kind: MemberMessageKind, guildId: string, userId: string): string => { diff --git a/src/commands/presence.ts b/src/commands/presence.ts index b3a2caf..9624824 100644 --- a/src/commands/presence.ts +++ b/src/commands/presence.ts @@ -23,6 +23,15 @@ import { } from "discord.js"; import { defineCommand } from "../framework/commands/defineCommand.js"; import { env } from "../framework/config/env.js"; +import type { + DiscordPresenceStatus, + PresenceActivityTypeValue, + PresenceCustomIds, + PresencePanelSession, + PresenceRuntimeState, + PresenceState, + PresenceStatusValue, +} from "../types/presence.js"; import { getPresenceStore } from "../framework/presence/presenceStore.js"; import { PRESENCE_TEMPLATE_REFRESH_INTERVAL_MS, @@ -42,34 +51,8 @@ import { sanitizeActivityText, sanitizeActivityTexts, sanitizePresenceRotationIntervalSeconds, - type PresenceActivityTypeValue, - type PresenceState, - type PresenceStatusValue, } from "../framework/presence/presenceTypes.js"; -import type { CommandExecutionContext } from "../framework/types/command.js"; - -interface PresenceCustomIds { - statusSelect: string; - activitySelect: string; - textButton: string; - intervalButton: string; - textModal: string; - textInput: string; - intervalModal: string; - intervalInput: string; -} - -interface PresencePanelSession { - collector: ReturnType; - disable: () => Promise; -} - -interface PresenceRuntimeState { - dynamicPresenceRefreshTimer: NodeJS.Timeout | null; - presenceRotationTimer: NodeJS.Timeout | null; - activePresenceTextIndex: number; - activePanelsByUserId: Map; -} +import type { CommandExecutionContext } from "../types/command.js"; const presenceRuntimeByBotId = new Map(); @@ -129,8 +112,6 @@ const DISCORD_ACTIVITY_TYPES: Record = CUSTOM: ActivityType.Custom, }; -type DiscordPresenceStatus = "online" | "idle" | "dnd" | "invisible"; - const resolveDiscordStatus = (status: PresenceStatusValue): DiscordPresenceStatus => status === "streaming" ? "online" : status; diff --git a/src/framework/commands/argParser.ts b/src/framework/commands/argParser.ts index af1476a..35d0fc3 100644 --- a/src/framework/commands/argParser.ts +++ b/src/framework/commands/argParser.ts @@ -1,16 +1,7 @@ import type { ChatInputCommandInteraction, GuildBasedChannel, Message } from "discord.js"; -import type { CommandArgValue, CommandArgument, TranslationVars } from "../types/command.js"; - -export interface ArgumentParseError { - key: string; - vars?: TranslationVars; -} - -export interface ParsedArgumentsResult { - values: Record; - errors: ArgumentParseError[]; -} +import type { ArgumentParseError, ParsedArgumentsResult } from "../../types/argParser.js"; +import type { CommandArgValue, CommandArgument } from "../../types/command.js"; const USER_MENTION_PATTERN = /^<@!?(\d{16,22})>$/; const CHANNEL_MENTION_PATTERN = /^<#(\d{16,22})>$/; diff --git a/src/framework/commands/defineCommand.ts b/src/framework/commands/defineCommand.ts index 7fdd5fb..5fe8edc 100644 --- a/src/framework/commands/defineCommand.ts +++ b/src/framework/commands/defineCommand.ts @@ -1,4 +1,4 @@ -import type { BotCommand, BotCommandInput } from "../types/command.js"; +import type { BotCommand, BotCommandInput } from "../../types/command.js"; const assertRequiredArgsBeforeOptional = (input: BotCommandInput): void => { const args = input.args ?? []; diff --git a/src/framework/commands/deploy.ts b/src/framework/commands/deploy.ts index 4e108ec..8d747d0 100644 --- a/src/framework/commands/deploy.ts +++ b/src/framework/commands/deploy.ts @@ -1,21 +1,7 @@ import { REST, Routes } from "discord.js"; import { buildSlashPayload } from "./slashBuilder.js"; -import type { CommandRegistry } from "./registry.js"; -import type { I18nService } from "../../i18n/index.js"; - -export interface DeployCommandsOptions { - token: string; - clientId: string; - guildId?: string; - registry: CommandRegistry; - i18n: I18nService; -} - -export interface DeployCommandsResult { - scope: "guild" | "global"; - count: number; -} +import type { DeployCommandsOptions, DeployCommandsResult } from "../../types/deploy.js"; export const deployApplicationCommands = async (options: DeployCommandsOptions): Promise => { const body = buildSlashPayload(options.registry.getAll(), options.i18n); diff --git a/src/framework/commands/registry.ts b/src/framework/commands/registry.ts index 23200f9..f4bc16a 100644 --- a/src/framework/commands/registry.ts +++ b/src/framework/commands/registry.ts @@ -1,5 +1,5 @@ -import type { BotCommand, PrefixTriggerMatch } from "../types/command.js"; -import { SUPPORTED_LANGS } from "../types/command.js"; +import type { BotCommand, PrefixTriggerMatch } from "../../types/command.js"; +import { SUPPORTED_LANGS } from "../../types/command.js"; import type { I18nService } from "../../i18n/index.js"; const normalize = (value: string): string => value.trim().toLowerCase(); diff --git a/src/framework/commands/slashBuilder.ts b/src/framework/commands/slashBuilder.ts index 30099af..488247b 100644 --- a/src/framework/commands/slashBuilder.ts +++ b/src/framework/commands/slashBuilder.ts @@ -4,7 +4,7 @@ import { type RESTPostAPIChatInputApplicationCommandsJSONBody, } from "discord.js"; -import type { BotCommand, CommandArgument, SupportedLang } from "../types/command.js"; +import type { BotCommand, CommandArgument, SupportedLang } from "../../types/command.js"; import type { I18nService } from "../../i18n/index.js"; const LANG_TO_DISCORD_LOCALE: Record = { diff --git a/src/framework/commands/usage.ts b/src/framework/commands/usage.ts index c9791c7..6f0d1d7 100644 --- a/src/framework/commands/usage.ts +++ b/src/framework/commands/usage.ts @@ -1,4 +1,4 @@ -import type { BotCommand, CommandI18nTools, SupportedLang } from "../types/command.js"; +import type { BotCommand, CommandI18nTools, SupportedLang } from "../../types/command.js"; const formatArgToken = (name: string, required: boolean): string => required ? `<${name}>` : `[${name}]`; diff --git a/src/framework/config/env.ts b/src/framework/config/env.ts index ad5f6ee..f30b149 100644 --- a/src/framework/config/env.ts +++ b/src/framework/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/execution/CommandExecutor.ts b/src/framework/execution/CommandExecutor.ts index 61c2ab5..6c9fdb9 100644 --- a/src/framework/execution/CommandExecutor.ts +++ b/src/framework/execution/CommandExecutor.ts @@ -5,7 +5,7 @@ import { type PermissionResolvable, } from "discord.js"; -import type { BotCommand, CommandExecutionContext } from "../types/command.js"; +import type { BotCommand, CommandExecutionContext } from "../../types/command.js"; const COOLDOWN_SWEEP_INTERVAL_MS = 60_000; const COOLDOWN_SWEEP_MIN_ENTRIES = 512; diff --git a/src/framework/memberMessages/memberMessageImage.ts b/src/framework/memberMessages/memberMessageImage.ts index 195f69c..f311ace 100644 --- a/src/framework/memberMessages/memberMessageImage.ts +++ b/src/framework/memberMessages/memberMessageImage.ts @@ -1,14 +1,6 @@ import { createCanvas, loadImage, type SKRSContext2D } from "@napi-rs/canvas"; -import type { MemberMessageKind } from "./memberMessageTypes.js"; - -interface MemberMessageImageInput { - kind: MemberMessageKind; - title: string; - subtitle: string; - username: string; - avatarUrl: string; -} +import type { MemberMessageImageInput } from "../../types/memberMessages.js"; const CARD_WIDTH = 1024; const CARD_HEIGHT = 320; diff --git a/src/framework/memberMessages/memberMessageSender.ts b/src/framework/memberMessages/memberMessageSender.ts index 15f08ca..a4fda82 100644 --- a/src/framework/memberMessages/memberMessageSender.ts +++ b/src/framework/memberMessages/memberMessageSender.ts @@ -5,48 +5,27 @@ import { MessageFlags, PermissionFlagsBits, TextDisplayBuilder, - type Client, type Guild, type MessageCreateOptions, type User, } from "discord.js"; import type { I18nService } from "../../i18n/index.js"; -import type { SupportedLang } from "../types/command.js"; +import type { SupportedLang } from "../../types/command.js"; +import type { + DispatchMemberMessageInput, + DispatchMemberMessageResult, + MemberMessageKind, + MemberMessageRenderType, + SendableChannel, + TemplateSuffix, +} from "../../types/memberMessages.js"; import { renderMemberMessageImage } from "./memberMessageImage.js"; import { getMemberMessageStore } from "./memberMessageStore.js"; -import { - type MemberMessageKind, - type MemberMessageRenderType, -} from "./memberMessageTypes.js"; - -export type DispatchMemberMessageFailureReason = - | "bot_not_ready" - | "disabled" - | "missing_channel" - | "channel_not_found" - | "channel_not_sendable" - | "missing_permissions" - | "send_failed"; - -export interface DispatchMemberMessageResult { - sent: boolean; - reason: DispatchMemberMessageFailureReason | "sent"; - channelId: string | null; -} - -interface DispatchMemberMessageInput { - client: Client; - i18n?: I18nService; - guild: Guild; - user: User; - kind: MemberMessageKind; - ignoreEnabled?: boolean; -} - -interface SendableChannel { - send: (payload: string | MessageCreateOptions) => Promise; -} +export type { + DispatchMemberMessageFailureReason, + DispatchMemberMessageResult, +} from "../../types/memberMessages.js"; const hasSendMethod = (value: unknown): value is SendableChannel => { if (!value || typeof value !== "object") { @@ -74,15 +53,6 @@ const messageColor = (kind: MemberMessageKind): number => { return kind === "welcome" ? 0x57f287 : 0xed4245; }; -type TemplateSuffix = - | "simple" - | "embedTitle" - | "embedDescription" - | "containerTitle" - | "containerDescription" - | "imageTitle" - | "imageDescription"; - const defaultTemplate = ( kind: MemberMessageKind, suffix: TemplateSuffix, diff --git a/src/framework/memberMessages/memberMessageStore.ts b/src/framework/memberMessages/memberMessageStore.ts index 6759c66..6025bd8 100644 --- a/src/framework/memberMessages/memberMessageStore.ts +++ b/src/framework/memberMessages/memberMessageStore.ts @@ -1,19 +1,16 @@ import { Pool } from "pg"; import { env } from "../config/env.js"; +import type { + MemberMessageConfig, + MemberMessageKind, + MemberMessageRow, +} from "../../types/memberMessages.js"; import { createDefaultMemberMessageConfig, isMemberMessageRenderTypeValue, - type MemberMessageConfig, - type MemberMessageKind, } from "./memberMessageTypes.js"; -interface MemberMessageRow { - enabled: boolean; - channel_id: string | null; - message_type: string; -} - const tableSql = ` CREATE TABLE IF NOT EXISTS bot_member_message_configs ( bot_id TEXT NOT NULL, diff --git a/src/framework/memberMessages/memberMessageTypes.ts b/src/framework/memberMessages/memberMessageTypes.ts index 3e0c4a5..e7ad973 100644 --- a/src/framework/memberMessages/memberMessageTypes.ts +++ b/src/framework/memberMessages/memberMessageTypes.ts @@ -1,17 +1,17 @@ -export const MEMBER_MESSAGE_KINDS = ["welcome", "goodbye"] as const; -export type MemberMessageKind = (typeof MEMBER_MESSAGE_KINDS)[number]; +import type { + MemberMessageConfig, + MemberMessageKind, + MemberMessageRenderType, +} from "../../types/memberMessages.js"; -export const MEMBER_MESSAGE_RENDER_TYPES = ["simple", "embed", "container", "image"] as const; -export type MemberMessageRenderType = (typeof MEMBER_MESSAGE_RENDER_TYPES)[number]; +export type { MemberMessageConfig, MemberMessageKind, MemberMessageRenderType } from "../../types/memberMessages.js"; + +export const MEMBER_MESSAGE_KINDS: readonly MemberMessageKind[] = ["welcome", "goodbye"]; + +export const MEMBER_MESSAGE_RENDER_TYPES: readonly MemberMessageRenderType[] = ["simple", "embed", "container", "image"]; export const DEFAULT_MEMBER_MESSAGE_RENDER_TYPE: MemberMessageRenderType = "simple"; -export interface MemberMessageConfig { - enabled: boolean; - channelId: string | null; - messageType: MemberMessageRenderType; -} - export const createDefaultMemberMessageConfig = (): MemberMessageConfig => ({ enabled: false, channelId: null, diff --git a/src/framework/presence/presenceStore.ts b/src/framework/presence/presenceStore.ts index c159140..3c9c0fa 100644 --- a/src/framework/presence/presenceStore.ts +++ b/src/framework/presence/presenceStore.ts @@ -1,6 +1,12 @@ import { Pool } from "pg"; import { env } from "../config/env.js"; +import type { + PresenceActivityTypeValue, + PresenceRow, + PresenceState, + PresenceStatusValue, +} from "../../types/presence.js"; import { DEFAULT_ACTIVITY_ROTATION_INTERVAL_SECONDS, createDefaultPresenceState, @@ -9,19 +15,8 @@ import { sanitizeActivityText, sanitizeActivityTexts, sanitizePresenceRotationIntervalSeconds, - type PresenceActivityTypeValue, - type PresenceState, - type PresenceStatusValue, } from "./presenceTypes.js"; -interface PresenceRow { - status: string; - activity_type: string; - activity_text: string; - activity_texts: string | null; - rotation_interval_seconds: number | null; -} - const tableSql = ` CREATE TABLE IF NOT EXISTS bot_presence_states ( bot_id TEXT PRIMARY KEY, diff --git a/src/framework/presence/presenceTypes.ts b/src/framework/presence/presenceTypes.ts index a1f2e33..62ef2cc 100644 --- a/src/framework/presence/presenceTypes.ts +++ b/src/framework/presence/presenceTypes.ts @@ -1,15 +1,18 @@ -export const PRESENCE_STATUSES = ["online", "idle", "dnd", "invisible", "streaming"] as const; -export const PRESENCE_ACTIVITY_TYPES = [ +import type { + PresenceActivityTypeValue, + PresenceState, + PresenceStatusValue, +} from "../../types/presence.js"; + +export const PRESENCE_STATUSES: readonly PresenceStatusValue[] = ["online", "idle", "dnd", "invisible", "streaming"]; +export const PRESENCE_ACTIVITY_TYPES: readonly PresenceActivityTypeValue[] = [ "PLAYING", "STREAMING", "WATCHING", "LISTENING", "COMPETING", "CUSTOM", -] as const; - -export type PresenceStatusValue = (typeof PRESENCE_STATUSES)[number]; -export type PresenceActivityTypeValue = (typeof PRESENCE_ACTIVITY_TYPES)[number]; +]; export const DEFAULT_ACTIVITY_TEXT = "Ready to help"; export const DEFAULT_ACTIVITY_ROTATION_INTERVAL_SECONDS = 30; @@ -17,16 +20,6 @@ export const MIN_ACTIVITY_ROTATION_INTERVAL_SECONDS = 5; export const MAX_ACTIVITY_ROTATION_INTERVAL_SECONDS = 3_600; export const MAX_ACTIVITY_ROTATION_TEXTS = 10; -export interface PresenceState { - status: PresenceStatusValue; - activity: { - type: PresenceActivityTypeValue; - text: string; - texts: string[]; - rotationIntervalSeconds: number; - }; -} - export const createDefaultPresenceState = (): PresenceState => ({ status: "online", activity: { @@ -38,10 +31,10 @@ export const createDefaultPresenceState = (): PresenceState => ({ }); export const isPresenceStatusValue = (value: string): value is PresenceStatusValue => - (PRESENCE_STATUSES as readonly string[]).includes(value); + PRESENCE_STATUSES.includes(value as PresenceStatusValue); export const isPresenceActivityTypeValue = (value: string): value is PresenceActivityTypeValue => - (PRESENCE_ACTIVITY_TYPES as readonly string[]).includes(value); + PRESENCE_ACTIVITY_TYPES.includes(value as PresenceActivityTypeValue); export const sanitizeActivityText = (value: string): string => { const trimmed = value.trim(); diff --git a/src/framework/utils/templateVariables.ts b/src/framework/utils/templateVariables.ts index c7969d1..3ed9839 100644 --- a/src/framework/utils/templateVariables.ts +++ b/src/framework/utils/templateVariables.ts @@ -1,7 +1,4 @@ -export interface TemplateRenderOptions { - aliases?: Record; - keepUnknown?: boolean; -} +import type { TemplateRenderOptions } from "../../types/templateVariables.js"; const createTemplateTokenRegex = (): RegExp => /\{\{([a-zA-Z0-9_]+)\}\}/g; diff --git a/src/framework/handlers/commandExecutionContext.ts b/src/handlers/commandExecutionContext.ts similarity index 63% rename from src/framework/handlers/commandExecutionContext.ts rename to src/handlers/commandExecutionContext.ts index f0e36d5..3cc7cf3 100644 --- a/src/framework/handlers/commandExecutionContext.ts +++ b/src/handlers/commandExecutionContext.ts @@ -1,32 +1,10 @@ -import type { CommandRegistry } from "../commands/registry.js"; -import type { I18nService } from "../../i18n/index.js"; import type { - BotCommand, CommandExecutionContext, - CommandSource, SupportedLang, TranslationVars, } from "../types/command.js"; - -export interface HandlerExecutionDeps { - registry: CommandRegistry; - i18n: I18nService; - prefix: string; - defaultLang: SupportedLang; -} - -interface BuildExecutionContextInput { - command: BotCommand; - source: CommandSource; - lang: SupportedLang; - args: CommandExecutionContext["args"]; - client: CommandExecutionContext["client"]; - user: CommandExecutionContext["user"]; - guild: CommandExecutionContext["guild"]; - channel: CommandExecutionContext["channel"]; - raw: CommandExecutionContext["raw"]; - reply: CommandExecutionContext["reply"]; -} +import type { BuildExecutionContextInput, HandlerExecutionDeps } from "../types/handlers.js"; +import type { I18nService } from "../i18n/index.js"; export const createTranslator = ( i18n: I18nService, diff --git a/src/framework/handlers/prefixHandler.ts b/src/handlers/prefixHandler.ts similarity index 88% rename from src/framework/handlers/prefixHandler.ts rename to src/handlers/prefixHandler.ts index 12e150f..041bd61 100644 --- a/src/framework/handlers/prefixHandler.ts +++ b/src/handlers/prefixHandler.ts @@ -1,20 +1,15 @@ import type { Message } from "discord.js"; import type { BotCommand, SupportedLang } from "../types/command.js"; +import type { PrefixHandlerDeps } from "../types/handlers.js"; -import { parsePrefixArgs } from "../commands/argParser.js"; -import { buildPrefixUsage } from "../commands/usage.js"; -import { CommandExecutor } from "../execution/CommandExecutor.js"; +import { parsePrefixArgs } from "../framework/commands/argParser.js"; +import { buildPrefixUsage } from "../framework/commands/usage.js"; import { buildCommandExecutionContext, createTranslator, - type HandlerExecutionDeps, } from "./commandExecutionContext.js"; import { createPrefixReply } from "./replyAdapter.js"; -interface PrefixHandlerDeps extends HandlerExecutionDeps { - executor: CommandExecutor; -} - const resolvePrefixLang = ( deps: PrefixHandlerDeps, command: BotCommand, diff --git a/src/framework/handlers/replyAdapter.ts b/src/handlers/replyAdapter.ts similarity index 98% rename from src/framework/handlers/replyAdapter.ts rename to src/handlers/replyAdapter.ts index f6891d4..e1af9db 100644 --- a/src/framework/handlers/replyAdapter.ts +++ b/src/handlers/replyAdapter.ts @@ -6,6 +6,7 @@ import type { } from "discord.js"; import type { ReplyPayload } from "../types/command.js"; +import type { PrefixReplyObject } from "../types/reply.js"; const PREFIX_EPHEMERAL_DELETE_DELAY_MS = 10_000; @@ -18,8 +19,6 @@ const SLASH_ALLOWED_MENTIONS_DEFAULT: NonNullable; - const EPHEMERAL_FLAG = 64n; const FLAG_NAME_TO_BITS: Record = { Ephemeral: 64n, diff --git a/src/framework/handlers/slashHandler.ts b/src/handlers/slashHandler.ts similarity index 83% rename from src/framework/handlers/slashHandler.ts rename to src/handlers/slashHandler.ts index 8e01b5e..85f5593 100644 --- a/src/framework/handlers/slashHandler.ts +++ b/src/handlers/slashHandler.ts @@ -1,19 +1,14 @@ import { MessageFlags, type ChatInputCommandInteraction } from "discord.js"; +import type { SlashHandlerDeps } from "../types/handlers.js"; -import { parseSlashArgs } from "../commands/argParser.js"; -import { buildSlashUsage } from "../commands/usage.js"; -import { CommandExecutor } from "../execution/CommandExecutor.js"; +import { parseSlashArgs } from "../framework/commands/argParser.js"; +import { buildSlashUsage } from "../framework/commands/usage.js"; import { buildCommandExecutionContext, createTranslator, - type HandlerExecutionDeps, } from "./commandExecutionContext.js"; import { createSlashReply } from "./replyAdapter.js"; -interface SlashHandlerDeps extends HandlerExecutionDeps { - executor: CommandExecutor; -} - export const createSlashHandler = (deps: SlashHandlerDeps) => { return async (interaction: ChatInputCommandInteraction): Promise => { const command = deps.registry.findBySlashTrigger(interaction.commandName); diff --git a/src/i18n/index.ts b/src/i18n/index.ts index f08589a..4720808 100644 --- a/src/i18n/index.ts +++ b/src/i18n/index.ts @@ -2,9 +2,8 @@ import { existsSync, readFileSync } from "node:fs"; import path from "node:path"; import { fileURLToPath } from "node:url"; -import { SUPPORTED_LANGS, type SupportedLang, type TranslationVars } from "../framework/types/command.js"; - -type JsonObject = Record; +import { SUPPORTED_LANGS, type SupportedLang, type TranslationVars } from "../types/command.js"; +import type { JsonObject } from "../types/i18n.js"; const DISCORD_LOCALE_MAP: Record = { en: "en", diff --git a/src/index.ts b/src/index.ts index 0a39444..ed630b2 100644 --- a/src/index.ts +++ b/src/index.ts @@ -16,8 +16,8 @@ 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 { createPrefixHandler } from "./framework/handlers/prefixHandler.js"; -import { createSlashHandler } from "./framework/handlers/slashHandler.js"; +import { createPrefixHandler } from "./handlers/prefixHandler.js"; +import { createSlashHandler } from "./handlers/slashHandler.js"; import { I18nService } from "./i18n/index.js"; import { initMemberMessageStore, diff --git a/src/types/argParser.ts b/src/types/argParser.ts new file mode 100644 index 0000000..41b9593 --- /dev/null +++ b/src/types/argParser.ts @@ -0,0 +1,11 @@ +import type { CommandArgValue, TranslationVars } from "./command.js"; + +export interface ArgumentParseError { + key: string; + vars?: TranslationVars; +} + +export interface ParsedArgumentsResult { + values: Record; + errors: ArgumentParseError[]; +} \ No newline at end of file diff --git a/src/framework/types/command.ts b/src/types/command.ts similarity index 100% rename from src/framework/types/command.ts rename to src/types/command.ts diff --git a/src/types/deploy.ts b/src/types/deploy.ts new file mode 100644 index 0000000..228eda9 --- /dev/null +++ b/src/types/deploy.ts @@ -0,0 +1,15 @@ +import type { CommandRegistry } from "../framework/commands/registry.js"; +import type { I18nService } from "../i18n/index.js"; + +export interface DeployCommandsOptions { + token: string; + clientId: string; + guildId?: string; + registry: CommandRegistry; + i18n: I18nService; +} + +export interface DeployCommandsResult { + scope: "guild" | "global"; + count: number; +} \ No newline at end of file diff --git a/src/types/handlers.ts b/src/types/handlers.ts new file mode 100644 index 0000000..7c1ce28 --- /dev/null +++ b/src/types/handlers.ts @@ -0,0 +1,37 @@ +import type { CommandRegistry } from "../framework/commands/registry.js"; +import type { CommandExecutor } from "../framework/execution/CommandExecutor.js"; +import type { I18nService } from "../i18n/index.js"; +import type { + BotCommand, + CommandExecutionContext, + CommandSource, + SupportedLang, +} from "./command.js"; + +export interface HandlerExecutionDeps { + registry: CommandRegistry; + i18n: I18nService; + prefix: string; + defaultLang: SupportedLang; +} + +export interface BuildExecutionContextInput { + command: BotCommand; + source: CommandSource; + lang: SupportedLang; + args: CommandExecutionContext["args"]; + client: CommandExecutionContext["client"]; + user: CommandExecutionContext["user"]; + guild: CommandExecutionContext["guild"]; + channel: CommandExecutionContext["channel"]; + raw: CommandExecutionContext["raw"]; + reply: CommandExecutionContext["reply"]; +} + +export interface PrefixHandlerDeps extends HandlerExecutionDeps { + executor: CommandExecutor; +} + +export interface SlashHandlerDeps extends HandlerExecutionDeps { + executor: CommandExecutor; +} \ No newline at end of file diff --git a/src/types/i18n.ts b/src/types/i18n.ts new file mode 100644 index 0000000..fb1394a --- /dev/null +++ b/src/types/i18n.ts @@ -0,0 +1 @@ +export type JsonObject = Record; \ No newline at end of file diff --git a/src/types/memberMessages.ts b/src/types/memberMessages.ts new file mode 100644 index 0000000..7a5b533 --- /dev/null +++ b/src/types/memberMessages.ts @@ -0,0 +1,87 @@ +import type { + Client, + Guild, + Message, + MessageCreateOptions, + User, +} from "discord.js"; + +import type { I18nService } from "../i18n/index.js"; + +export type MemberMessageKind = "welcome" | "goodbye"; +export type MemberMessageRenderType = "simple" | "embed" | "container" | "image"; + +export interface MemberMessageConfig { + enabled: boolean; + channelId: string | null; + messageType: MemberMessageRenderType; +} + +export type DispatchMemberMessageFailureReason = + | "bot_not_ready" + | "disabled" + | "missing_channel" + | "channel_not_found" + | "channel_not_sendable" + | "missing_permissions" + | "send_failed"; + +export interface DispatchMemberMessageResult { + sent: boolean; + reason: DispatchMemberMessageFailureReason | "sent"; + channelId: string | null; +} + +export interface DispatchMemberMessageInput { + client: Client; + i18n?: I18nService; + guild: Guild; + user: User; + kind: MemberMessageKind; + ignoreEnabled?: boolean; +} + +export interface SendableChannel { + send: (payload: string | MessageCreateOptions) => Promise; +} + +export type TemplateSuffix = + | "simple" + | "embedTitle" + | "embedDescription" + | "containerTitle" + | "containerDescription" + | "imageTitle" + | "imageDescription"; + +export interface MemberMessageImageInput { + kind: MemberMessageKind; + title: string; + subtitle: string; + username: string; + avatarUrl: string; +} + +export interface MemberMessageRow { + enabled: boolean; + channel_id: string | null; + message_type: string; +} + +export interface MemberMessageCustomIds { + toggleButton: string; + channelButton: string; + channelCancelButton: string; + typeSelect: string; + channelSelect: string; + testButton: string; +} + +export interface MemberMessagePanelUiState { + channelPickerOpen: boolean; +} + +export interface MemberMessagePanelSession { + collector: ReturnType; + disable: () => Promise; +} \ No newline at end of file diff --git a/src/types/presence.ts b/src/types/presence.ts new file mode 100644 index 0000000..a8e3043 --- /dev/null +++ b/src/types/presence.ts @@ -0,0 +1,49 @@ +import type { Message } from "discord.js"; + +export type PresenceStatusValue = "online" | "idle" | "dnd" | "invisible" | "streaming"; +export type PresenceActivityTypeValue = "PLAYING" | "STREAMING" | "WATCHING" | "LISTENING" | "COMPETING" | "CUSTOM"; + +export interface PresenceActivityState { + type: PresenceActivityTypeValue; + text: string; + texts: string[]; + rotationIntervalSeconds: number; +} + +export interface PresenceState { + status: PresenceStatusValue; + activity: PresenceActivityState; +} + +export interface PresenceRow { + status: string; + activity_type: string; + activity_text: string; + activity_texts: string | null; + rotation_interval_seconds: number | null; +} + +export interface PresenceCustomIds { + statusSelect: string; + activitySelect: string; + textButton: string; + intervalButton: string; + textModal: string; + textInput: string; + intervalModal: string; + intervalInput: string; +} + +export interface PresencePanelSession { + collector: ReturnType; + disable: () => Promise; +} + +export interface PresenceRuntimeState { + dynamicPresenceRefreshTimer: NodeJS.Timeout | null; + presenceRotationTimer: NodeJS.Timeout | null; + activePresenceTextIndex: number; + activePanelsByUserId: Map; +} + +export type DiscordPresenceStatus = "online" | "idle" | "dnd" | "invisible"; \ No newline at end of file diff --git a/src/types/reply.ts b/src/types/reply.ts new file mode 100644 index 0000000..c09c69d --- /dev/null +++ b/src/types/reply.ts @@ -0,0 +1,3 @@ +import type { ReplyPayload } from "./command.js"; + +export type PrefixReplyObject = Exclude; \ No newline at end of file diff --git a/src/types/templateVariables.ts b/src/types/templateVariables.ts new file mode 100644 index 0000000..2a33846 --- /dev/null +++ b/src/types/templateVariables.ts @@ -0,0 +1,4 @@ +export interface TemplateRenderOptions { + aliases?: Record; + keepUnknown?: boolean; +} \ No newline at end of file