Kord/src/commands/minigame.ts

134 lines
4.7 KiB
TypeScript

import {
SlashCommandBuilder,
ChatInputCommandInteraction,
PermissionFlagsBits,
EmbedBuilder,
Colors,
ChannelType
} from 'discord.js';
import { prisma } from '../database';
import { t, SupportedLocale } from '../i18n';
import { MINI_GAMES, getAllMiniGames } from '../services/MiniGameRegistry';
export default {
data: new SlashCommandBuilder()
.setName('minigame')
.setDescription('Manage mini-games for the server.')
.setDescriptionLocalizations({
ko: '서버의 미니게임을 관리합니다.',
})
.setDefaultMemberPermissions(PermissionFlagsBits.Administrator)
// --- Toggle Subcommand ---
.addSubcommand(subcommand =>
subcommand
.setName('toggle')
.setDescription('Enable or disable a specific mini-game.')
.addStringOption(option =>
option.setName('game')
.setDescription('Mini-game to toggle')
.setRequired(true)
.addChoices(...Object.values(MINI_GAMES).map(g => ({ name: g.name, value: g.key })))
)
.addBooleanOption(option =>
option.setName('enable')
.setDescription('Whether to enable the mini-game')
.setRequired(true)
)
)
// --- Status Subcommand ---
.addSubcommand(subcommand =>
subcommand
.setName('status')
.setDescription('View the current status of all mini-games.')
)
// --- Channel Subcommand ---
.addSubcommand(subcommand =>
subcommand
.setName('channel')
.setDescription('Set a dedicated channel for a mini-game.')
.addStringOption(option =>
option.setName('game')
.setDescription('Mini-game to set channel for')
.setRequired(true)
.addChoices(...Object.values(MINI_GAMES).map(g => ({ name: g.name, value: g.key })))
)
.addChannelOption(option =>
option.setName('channel')
.setDescription('The channel to use (empty to allow all)')
.addChannelTypes(ChannelType.GuildText)
)
),
async execute(interaction: ChatInputCommandInteraction, locale: SupportedLocale) {
if (!interaction.guildId) return;
const subcommand = interaction.options.getSubcommand();
if (subcommand === 'toggle') {
const gameKey = interaction.options.getString('game', true);
const enable = interaction.options.getBoolean('enable', true);
await prisma.miniGameConfig.upsert({
where: { guildId_gameKey: { guildId: interaction.guildId, gameKey } },
update: { enabled: enable },
create: { guildId: interaction.guildId, gameKey, enabled: enable },
});
const game = MINI_GAMES[gameKey];
const state = enable ? '활성화' : '비활성화';
const embed = new EmbedBuilder()
.setColor(enable ? Colors.Green : Colors.Grey)
.setTitle('🎮 미니게임 설정 변경')
.setDescription(`${game.name} 미니게임이 **${state}**되었습니다.`);
return interaction.reply({ embeds: [embed], ephemeral: true });
}
if (subcommand === 'status') {
const configs = await prisma.miniGameConfig.findMany({
where: { guildId: interaction.guildId },
});
const embed = new EmbedBuilder()
.setColor(Colors.Blue)
.setTitle('🎮 미니게임 현황')
.setDescription('현재 서버의 미니게임 활성화 상태입니다.');
getAllMiniGames().forEach(game => {
const config = configs.find(c => c.gameKey === game.key);
const isEnabled = config?.enabled ?? false;
const channel = config?.channelId ? `<#${config.channelId}>` : '모든 채널';
embed.addFields({
name: game.name,
value: `상태: ${isEnabled ? '✅ 활성' : '❌ 비활성'}\n채널: ${channel}`,
inline: true,
});
});
return interaction.reply({ embeds: [embed], ephemeral: true });
}
if (subcommand === 'channel') {
const gameKey = interaction.options.getString('game', true);
const channel = interaction.options.getChannel('channel');
await prisma.miniGameConfig.upsert({
where: { guildId_gameKey: { guildId: interaction.guildId, gameKey } },
update: { channelId: channel?.id || null },
create: { guildId: interaction.guildId, gameKey, channelId: channel?.id || null },
});
const game = MINI_GAMES[gameKey];
const channelMsg = channel ? `<#${channel.id}>` : '모든 채널';
const embed = new EmbedBuilder()
.setColor(Colors.Gold)
.setTitle('🎮 미니게임 채널 설정')
.setDescription(`${game.name} 미니게임 전용 채널이 **${channelMsg}**로 설정되었습니다.`);
return interaction.reply({ embeds: [embed], ephemeral: true });
}
},
};