mise au bonne endroit des type

This commit is contained in:
Puechberty Arthur
2026-04-13 20:23:49 +02:00
parent 3eb23eb27a
commit 7ff76cdaba
34 changed files with 298 additions and 236 deletions
+1 -1
View File
@@ -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;
+1 -1
View File
@@ -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[] = [
+9 -22
View File
@@ -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<Message["createMessageComponentCollector"]>;
disable: () => Promise<void>;
}
const activePanelsByUser = new Map<string, MemberMessagePanelSession>();
const panelSessionKey = (kind: MemberMessageKind, guildId: string, userId: string): string => {
+10 -29
View File
@@ -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<Message["createMessageComponentCollector"]>;
disable: () => Promise<void>;
}
interface PresenceRuntimeState {
dynamicPresenceRefreshTimer: NodeJS.Timeout | null;
presenceRotationTimer: NodeJS.Timeout | null;
activePresenceTextIndex: number;
activePanelsByUserId: Map<string, PresencePanelSession>;
}
import type { CommandExecutionContext } from "../types/command.js";
const presenceRuntimeByBotId = new Map<string, PresenceRuntimeState>();
@@ -129,8 +112,6 @@ const DISCORD_ACTIVITY_TYPES: Record<PresenceActivityTypeValue, ActivityType> =
CUSTOM: ActivityType.Custom,
};
type DiscordPresenceStatus = "online" | "idle" | "dnd" | "invisible";
const resolveDiscordStatus = (status: PresenceStatusValue): DiscordPresenceStatus =>
status === "streaming" ? "online" : status;
+2 -11
View File
@@ -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<string, CommandArgValue>;
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})>$/;
+1 -1
View File
@@ -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 ?? [];
+1 -15
View File
@@ -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<DeployCommandsResult> => {
const body = buildSlashPayload(options.registry.getAll(), options.i18n);
+2 -2
View File
@@ -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();
+1 -1
View File
@@ -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<SupportedLang, string> = {
+1 -1
View File
@@ -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}]`;
+1 -1
View File
@@ -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();
+1 -1
View File
@@ -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;
@@ -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;
@@ -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<unknown>;
}
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,
@@ -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,
@@ -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,
+6 -11
View File
@@ -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,
+11 -18
View File
@@ -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();
+1 -4
View File
@@ -1,7 +1,4 @@
export interface TemplateRenderOptions {
aliases?: Record<string, string>;
keepUnknown?: boolean;
}
import type { TemplateRenderOptions } from "../../types/templateVariables.js";
const createTemplateTokenRegex = (): RegExp => /\{\{([a-zA-Z0-9_]+)\}\}/g;
@@ -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,
@@ -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,
@@ -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<InteractionReplyOptions["allow
parse: [],
};
type PrefixReplyObject = Exclude<ReplyPayload, string>;
const EPHEMERAL_FLAG = 64n;
const FLAG_NAME_TO_BITS: Record<string, bigint> = {
Ephemeral: 64n,
@@ -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<void> => {
const command = deps.registry.findBySlashTrigger(interaction.commandName);
+2 -3
View File
@@ -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<string, unknown>;
import { SUPPORTED_LANGS, type SupportedLang, type TranslationVars } from "../types/command.js";
import type { JsonObject } from "../types/i18n.js";
const DISCORD_LOCALE_MAP: Record<string, SupportedLang> = {
en: "en",
+2 -2
View File
@@ -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,
+11
View File
@@ -0,0 +1,11 @@
import type { CommandArgValue, TranslationVars } from "./command.js";
export interface ArgumentParseError {
key: string;
vars?: TranslationVars;
}
export interface ParsedArgumentsResult {
values: Record<string, CommandArgValue>;
errors: ArgumentParseError[];
}
+15
View File
@@ -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;
}
+37
View File
@@ -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;
}
+1
View File
@@ -0,0 +1 @@
export type JsonObject = Record<string, unknown>;
+87
View File
@@ -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<unknown>;
}
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<Message["createMessageComponentCollector"]>;
disable: () => Promise<void>;
}
+49
View File
@@ -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<Message["createMessageComponentCollector"]>;
disable: () => Promise<void>;
}
export interface PresenceRuntimeState {
dynamicPresenceRefreshTimer: NodeJS.Timeout | null;
presenceRotationTimer: NodeJS.Timeout | null;
activePresenceTextIndex: number;
activePanelsByUserId: Map<string, PresencePanelSession>;
}
export type DiscordPresenceStatus = "online" | "idle" | "dnd" | "invisible";
+3
View File
@@ -0,0 +1,3 @@
import type { ReplyPayload } from "./command.js";
export type PrefixReplyObject = Exclude<ReplyPayload, string>;
+4
View File
@@ -0,0 +1,4 @@
export interface TemplateRenderOptions {
aliases?: Record<string, string>;
keepUnknown?: boolean;
}