- GuildPlayer: 타이머 레이스 컨디션 수정, 모든 타이머 정리 로직 통합 (clearAllTimers) - GuildPlayer: 이벤트 핸들러에 try-catch 추가 (end, exception, stuck) - GuildPlayer: start 이벤트에서 endTimer 정리, autoPlay tracks 길이 검증 추가 - RedisClient: player_seek, player_volume에 누락된 return ���가 - RedisClient: queue_remove 인덱스 검증 주석 명확화 - Handler: runCommand에 try-catch 추가하여 에러 시 사용자에게 응답 - Channel: getGuildById에 누락된 await 추가, getMemberById/getVoiceChannelById 안전한 에러 처리 - Command.d.ts: 잘못된 타입 ChatInputChatInputCommandInteraction → ChatInputCommandInteraction 수정 - join.ts: 채널 멘션 닫는 괄호 누락 수정 - shuffle.ts: 제네릭 타입 적용, 불필요한 5회 반복 제거 - import 경로 대소문자 수정 (Shuffle → shuffle) - Linux 호환 - YoutubeMusic/Spotify: 하드코딩된 IP를 환경변수로 분리 - console.log/error → Logger 통일 (YoutubeMusic, Button, channel) - interactionCreate: 전체 try-catch 추가, silent catch에 로깅 추가 - Database: schema 경로 __dirname 기반으로 수정, 컬럼 화이트리스트 추가 - 사용하지 않는 코드 정리 (axios 의존성, 주석처리된 user 관련 코드) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
135 lines
4.3 KiB
TypeScript
135 lines
4.3 KiB
TypeScript
import { ApplicationCommandOptionType, ChannelType, ChatInputApplicationCommandData, ChatInputCommandInteraction, EmbedBuilder, Guild } from "discord.js";
|
|
import { client } from "../index";
|
|
import { Command } from "../types/Command";
|
|
import { clearAllMsg } from "../utils/music/Utils";
|
|
import { default_content, default_embed, default_image, getButtons } from "../utils/music/Config";
|
|
import { DB } from "../utils/Database";
|
|
import { Logger } from "../utils/Logger";
|
|
|
|
/** channel 명령어 */
|
|
export default class implements Command {
|
|
/** 해당 명령어 설명 */
|
|
name = "channel";
|
|
visible = true;
|
|
aliases: string[] = [];
|
|
description: string = "채널 생성 또는 연결";
|
|
metaData: ChatInputApplicationCommandData = {
|
|
name: this.name,
|
|
description: this.description,
|
|
options: [
|
|
{
|
|
type: ApplicationCommandOptionType.Subcommand,
|
|
name: "make",
|
|
description: "채널 만들기",
|
|
},
|
|
{
|
|
type: ApplicationCommandOptionType.Subcommand,
|
|
name: "register",
|
|
description: "기존 채팅채널 등록",
|
|
options: [
|
|
{
|
|
type: ApplicationCommandOptionType.Channel,
|
|
name: "channel",
|
|
description: "등록할 채널 (선택)",
|
|
channel_types: [ChannelType.GuildText],
|
|
},
|
|
{
|
|
type: ApplicationCommandOptionType.String,
|
|
name: "channel_id",
|
|
description: "채널 ID 또는 #멘션 (선택)",
|
|
},
|
|
]
|
|
},
|
|
],
|
|
};
|
|
|
|
/** 실행되는 부분 */
|
|
async slashRun(interaction: ChatInputCommandInteraction) {
|
|
const cmd = interaction.options.getSubcommand();
|
|
if (cmd === "make") {
|
|
await interaction.editReply({ embeds: [ await this.channelCreate(interaction.guild) ] });
|
|
return;
|
|
}
|
|
if (cmd === "register") {
|
|
const channel = interaction.options.getChannel("channel");
|
|
const channelId = interaction.options.getString("channel_id");
|
|
await interaction.editReply({ embeds: [ await channelRegister(interaction.guild, channel?.id || channelId) ] });
|
|
return;
|
|
}
|
|
}
|
|
|
|
async channelCreate(guild: Guild | null): Promise<EmbedBuilder> {
|
|
if (!guild) return client.mkembed({
|
|
title: "guild를 가져올수 없습니다.",
|
|
color: "DarkRed",
|
|
});
|
|
const channel = await guild.channels.create({
|
|
name: "MUSIC채널",
|
|
type: ChannelType.GuildText,
|
|
topic: "채팅에 노래제목 또는 주소를 입력해 사용하세요.",
|
|
}).catch(() => null);
|
|
if (!channel) return client.mkembed({
|
|
title: "채널 생성 오류",
|
|
color: "DarkRed"
|
|
});
|
|
return channelRegister(guild, channel.id);
|
|
}
|
|
}
|
|
|
|
export async function channelRegister(guild: Guild | null, channelId: string | null): Promise<EmbedBuilder> {
|
|
if (!guild) return client.mkembed({
|
|
title: "guild를 가져올수 없습니다.",
|
|
color: "DarkRed",
|
|
});
|
|
if (!channelId) return client.mkembed({
|
|
title: "채널 아이디 가져오기 오류",
|
|
color: "DarkRed",
|
|
});
|
|
const channel = guild.channels.cache.get(channelId.replace(/\<|\#|\!|\>/g,"").trim());
|
|
if (!channel?.id) return client.mkembed({
|
|
title: `${channelId} 채널 가져오기 오류`,
|
|
color: "DarkRed",
|
|
});
|
|
if (channel.type !== ChannelType.GuildText) return client.mkembed({
|
|
title: `<#${channelId}> 채팅 채널이 아닙니다.`,
|
|
color: "DarkRed",
|
|
});
|
|
await clearAllMsg(channel);
|
|
const msg = await channel.send({
|
|
content: default_content,
|
|
embeds: [ default_embed(guild.id) ],
|
|
components: [ getButtons() ],
|
|
files: [ default_image ],
|
|
}).catch((err) => {
|
|
Logger.error(`[Channel] 메세지 생성 실패: ${String(err)}`);
|
|
return null;
|
|
});
|
|
if (!msg) return client.mkembed({
|
|
title: "메세지 생성 오류",
|
|
color: "DarkRed"
|
|
});
|
|
if (!DB.guild.get(guild.id)) DB.guild.set({
|
|
id: guild.id,
|
|
name: guild.name,
|
|
channel_id: "",
|
|
msg_id: "",
|
|
options: { recommend: false }
|
|
});
|
|
const gdb = DB.guild.get(guild.id);
|
|
if (!gdb) return client.mkembed({
|
|
title: "DB 생성 오류",
|
|
color: "DarkRed",
|
|
});
|
|
if (!DB.guild.update({
|
|
...gdb,
|
|
channel_id: channel.id,
|
|
msg_id: msg.id,
|
|
})) return client.mkembed({
|
|
title: "DB 등록 오류",
|
|
color: "DarkRed",
|
|
});
|
|
return client.mkembed({
|
|
title: `채널(${channel.name}) 생성/등록 완료`,
|
|
description: `채널: <#${channel.id}>`,
|
|
});
|
|
} |