지금까지 내용 커밋
This commit is contained in:
134
bot/src/commands/channel.ts
Normal file
134
bot/src/commands/channel.ts
Normal file
@@ -0,0 +1,134 @@
|
||||
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";
|
||||
|
||||
/** 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) => {
|
||||
console.error(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: "채널 생성/등록 완료",
|
||||
description: `채널: <#${channel.id}>`,
|
||||
});
|
||||
}
|
||||
27
bot/src/commands/example.ts
Normal file
27
bot/src/commands/example.ts
Normal file
@@ -0,0 +1,27 @@
|
||||
import { client } from "../index";
|
||||
import { Command } from "../types/Command";
|
||||
import { Message, ChatInputApplicationCommandData, ChatInputCommandInteraction, ChannelType } from "discord.js";
|
||||
|
||||
/** example 명령어 */
|
||||
export default class implements Command {
|
||||
/** 해당 명령어 설명 */
|
||||
name = "example";
|
||||
visible = false;
|
||||
aliases: string[] = ["예시"];
|
||||
description: string = "예시 명령어";
|
||||
metaData: ChatInputApplicationCommandData = {
|
||||
name: this.name,
|
||||
description: this.description,
|
||||
};
|
||||
|
||||
/** 실행되는 부분 */
|
||||
async slashRun(interaction: ChatInputCommandInteraction) {
|
||||
await interaction.editReply({ embeds: [ client.mkembed({
|
||||
title: "예시 명령어",
|
||||
}) ] });
|
||||
}
|
||||
async messageRun(message: Message) {
|
||||
if (message.channel?.type !== ChannelType.GuildText) return;
|
||||
return await message.channel.send({ content: "예시 명령어" }).then(m => client.msgDelete(m, 5));
|
||||
}
|
||||
}
|
||||
105
bot/src/commands/help.ts
Normal file
105
bot/src/commands/help.ts
Normal file
@@ -0,0 +1,105 @@
|
||||
import { client, handler } from "../index";
|
||||
import { Command } from "../types/Command";
|
||||
import { CacheType, Message, ActionRowBuilder, EmbedBuilder, ChatInputApplicationCommandData, StringSelectMenuBuilder, StringSelectMenuInteraction, ApplicationCommandOptionType, ChannelType, ChatInputCommandInteraction } from "discord.js";
|
||||
|
||||
/** help 명령어 */
|
||||
export default class implements Command {
|
||||
/** 해당 명령어 설명 */
|
||||
name = "help";
|
||||
visible = true;
|
||||
aliases: string[] = ["도움말"];
|
||||
description: string = "명령어 확인";
|
||||
metaData: ChatInputApplicationCommandData = {
|
||||
name: this.name,
|
||||
description: this.description,
|
||||
};
|
||||
|
||||
/** 실행되는 부분 */
|
||||
async slashRun(interaction: ChatInputCommandInteraction) {
|
||||
await interaction.editReply(this.getHelp());
|
||||
}
|
||||
async messageRun(message: Message) {
|
||||
if (message.channel?.type !== ChannelType.GuildText) return;
|
||||
return await message.channel.send(this.getHelp()).then(m => client.msgDelete(m, 5));
|
||||
}
|
||||
async menuRun(interaction: StringSelectMenuInteraction<CacheType>, args: string[]) {
|
||||
const command = handler.commands.get(args[0]);
|
||||
var embed = client.mkembed({});
|
||||
var embed2: EmbedBuilder | undefined = undefined;
|
||||
if (command) {
|
||||
embed.setTitle(`\` /${args[0]} 도움말 \``)
|
||||
.setDescription(`이름: ${args[0]}\n설명: ${command.description}`);
|
||||
embed2 = helpData(command.metaData.name, command.metaData);
|
||||
} else {
|
||||
embed.setTitle(`\` ${args[0]} 도움말 \``)
|
||||
.setDescription(`명령어를 찾을수 없습니다.`)
|
||||
.setFooter({ text: `도움말: /help` })
|
||||
.setColor('DarkRed');
|
||||
}
|
||||
if (embed2) {
|
||||
await interaction.editReply({ embeds: [ embed, embed2 ] });
|
||||
return;
|
||||
}
|
||||
await interaction.editReply({ embeds: [ embed ] });
|
||||
}
|
||||
|
||||
getHelp(): { embeds: EmbedBuilder[], components: ActionRowBuilder<StringSelectMenuBuilder>[] } {
|
||||
const slashcmdembed = client.mkembed({
|
||||
title: `\` slash (/) 도움말 \``,
|
||||
description: `명령어\n명령어 설명`
|
||||
});
|
||||
const msgcmdembed = client.mkembed({
|
||||
title: `\` 기본 (${client.prefix}) 도움말 \``,
|
||||
description: `명령어 [같은 명령어]\n명령어 설명`,
|
||||
footer: { text: `PREFIX: ${client.prefix}` }
|
||||
});
|
||||
let cmdlist: { label: string, description: string, value: string }[] = [];
|
||||
handler.commands.forEach((cmd) => {
|
||||
if (cmd.slashRun && cmd.visible) {
|
||||
cmdlist.push({ label: `/${cmd.name}`, description: `${cmd.description}`, value: `${cmd.name}` });
|
||||
slashcmdembed.addFields([{ name: `**/${cmd.name}**`, value: `${cmd.description}`, inline: true }]);
|
||||
}
|
||||
});
|
||||
handler.commands.forEach((cmd) => {
|
||||
if (cmd.messageRun && cmd.visible) {
|
||||
msgcmdembed.addFields([{ name: `**${client.prefix}${cmd.name}${cmd.aliases ? ` [ ${cmd.aliases} ]` : ""}**`, value: `${cmd.description}`, inline: true }]);
|
||||
}
|
||||
});
|
||||
const rowhelp = client.mkembed({
|
||||
title: '\` 명령어 상세보기 \`',
|
||||
description: `명령어의 자세한 내용은\n아래의 선택박스에서 선택해\n확인할수있습니다.`,
|
||||
footer: { text: '여러번 가능' }
|
||||
});
|
||||
const row = new ActionRowBuilder<StringSelectMenuBuilder>().addComponents(
|
||||
new StringSelectMenuBuilder()
|
||||
.setCustomId('help')
|
||||
.setPlaceholder('명령어를 선택해주세요.')
|
||||
.addOptions(cmdlist)
|
||||
);
|
||||
return { embeds: [ slashcmdembed, msgcmdembed, rowhelp ], components: [ row ] };
|
||||
}
|
||||
}
|
||||
|
||||
function helpData(name: string, metadata: ChatInputApplicationCommandData): EmbedBuilder | undefined {
|
||||
var text = "";
|
||||
metadata.options?.forEach((opt) => {
|
||||
text += `/${name} ${opt.name}`;
|
||||
if (opt.type === ApplicationCommandOptionType.Subcommand && opt.options) {
|
||||
if (opt.options.length > 1) {
|
||||
text = "";
|
||||
opt.options.forEach((opt2) => {
|
||||
text += `/${name} ${opt.name} [${opt2.type}] : ${opt.description}\n`;
|
||||
});
|
||||
} else {
|
||||
text += ` [${opt.options[0].type}] : ${opt.description}\n`;
|
||||
}
|
||||
} else {
|
||||
text += ` : ${opt.description}\n`;
|
||||
}
|
||||
});
|
||||
if (!text || text.length == 0) return undefined;
|
||||
return client.mkembed({
|
||||
title: `\` ${name} 명령어 \``,
|
||||
description: text,
|
||||
});
|
||||
}
|
||||
93
bot/src/commands/join.ts
Normal file
93
bot/src/commands/join.ts
Normal file
@@ -0,0 +1,93 @@
|
||||
import { Message, ChatInputApplicationCommandData, Guild, ChatInputCommandInteraction, EmbedBuilder, ApplicationCommandOptionType, ChannelType } from "discord.js";
|
||||
import { client, lavalinkManager } from "../index";
|
||||
import { Command } from "../types/Command";
|
||||
import { GuildPlayer } from "../classes/GuildPlayer";
|
||||
import { getTextChannelAndMsg } from "../utils/music/Channel";
|
||||
|
||||
/** join 명령어 */
|
||||
export default class implements Command {
|
||||
/** 해당 명령어 설명 */
|
||||
name = "join";
|
||||
visible = true;
|
||||
aliases: string[] = [];
|
||||
description: string = "음성채널 참가";
|
||||
metaData: ChatInputApplicationCommandData = {
|
||||
name: this.name,
|
||||
description: this.description,
|
||||
options: [
|
||||
{
|
||||
type: ApplicationCommandOptionType.Channel,
|
||||
name: "channel",
|
||||
description: "등록할 채널 (선택)",
|
||||
channel_types: [ChannelType.GuildVoice],
|
||||
},
|
||||
{
|
||||
type: ApplicationCommandOptionType.String,
|
||||
name: "channel_id",
|
||||
description: "채널 ID 또는 #멘션 (선택)",
|
||||
},
|
||||
]
|
||||
};
|
||||
|
||||
/** 실행되는 부분 */
|
||||
async slashRun(interaction: ChatInputCommandInteraction) {
|
||||
const channel = interaction.options.getChannel("channel");
|
||||
const channelId = interaction.options.getString("channel_id");
|
||||
await interaction.editReply({ embeds: [ (await channelJoin(interaction.guild, channel?.id || channelId)).embed ] });
|
||||
return;
|
||||
}
|
||||
async messageRun(message: Message) {
|
||||
if (message.channel?.type !== ChannelType.GuildText) return;
|
||||
return;
|
||||
// return await message.channel.send({ content: "예시 명령어" }).then(m => client.msgDelete(m, 5));
|
||||
}
|
||||
}
|
||||
|
||||
export async function channelJoin(guild: Guild | null, voiceChannelId: string | null): Promise<{
|
||||
embed: EmbedBuilder;
|
||||
player?: GuildPlayer;
|
||||
}> {
|
||||
if (!guild) return { embed: client.mkembed({
|
||||
title: "guild를 가져올수 없습니다.",
|
||||
color: "DarkRed",
|
||||
}) };
|
||||
const { channel, msg, reason } = await getTextChannelAndMsg(guild);
|
||||
if (reason || !channel || !msg) return { embed: client.mkembed({
|
||||
title: reason ?? "오류발생",
|
||||
color: "DarkRed",
|
||||
}) };
|
||||
|
||||
if (!voiceChannelId) return { embed: client.mkembed({
|
||||
title: "채널 아이디 가져오기 오류",
|
||||
color: "DarkRed",
|
||||
}) };
|
||||
const voiceChannel = guild.channels.cache.get(voiceChannelId.replace(/\<|\#|\!|\>/g,"").trim());
|
||||
if (!voiceChannel?.id) return { embed: client.mkembed({
|
||||
title: `${voiceChannelId} 채널 가져오기 오류`,
|
||||
color: "DarkRed",
|
||||
}) };
|
||||
if (voiceChannel.type !== ChannelType.GuildVoice) return { embed: client.mkembed({
|
||||
title: `<#${voiceChannelId}> 음성 채널이 아닙니다.`,
|
||||
color: "DarkRed",
|
||||
}) };
|
||||
|
||||
let player = lavalinkManager.getPlayer(guild.id);
|
||||
if (player) return { embed: client.mkembed({ title: `이미 <#${player.voiceChannelId} 참가중입니다.` }), player };
|
||||
player = new GuildPlayer(
|
||||
guild,
|
||||
await lavalinkManager.shoukaku.joinVoiceChannel({
|
||||
guildId: guild.id,
|
||||
channelId: voiceChannel.id,
|
||||
shardId: guild.shardId,
|
||||
deaf: true,
|
||||
mute: false,
|
||||
}),
|
||||
voiceChannel.id,
|
||||
channel,
|
||||
msg,
|
||||
);
|
||||
lavalinkManager.addPlayer(guild.id, player);
|
||||
return { embed: client.mkembed({
|
||||
title: `<#${voiceChannelId}> 참가 완료`,
|
||||
}), player };
|
||||
}
|
||||
49
bot/src/commands/ping.ts
Normal file
49
bot/src/commands/ping.ts
Normal file
@@ -0,0 +1,49 @@
|
||||
import { client } from "../index";
|
||||
import { Command } from "../types/Command";
|
||||
import { Message, ChatInputApplicationCommandData, ChatInputCommandInteraction, ChannelType } from "discord.js";
|
||||
|
||||
/** ping 명령어 */
|
||||
export default class implements Command {
|
||||
/** 해당 명령어 설명 */
|
||||
name = "ping";
|
||||
visible = true;
|
||||
aliases: string[] = ["핑"];
|
||||
description: string = "기본 명령어";
|
||||
metaData: ChatInputApplicationCommandData = {
|
||||
name: this.name,
|
||||
description: this.description,
|
||||
};
|
||||
|
||||
/** 실행되는 부분 */
|
||||
async slashRun(interaction: ChatInputCommandInteraction) {
|
||||
const msg = await interaction.editReply({ embeds: [ client.mkembed({
|
||||
title: "핑...",
|
||||
description: "계산중...",
|
||||
}) ] });
|
||||
if (!(msg instanceof Message)) {
|
||||
await interaction.editReply({ embeds: [ client.mkembed({
|
||||
title: "오류",
|
||||
description: `메시지 타입 불일치`,
|
||||
color: "DarkRed",
|
||||
}) ] });
|
||||
return;
|
||||
}
|
||||
const ping = msg.createdTimestamp - interaction.createdTimestamp;
|
||||
await interaction.editReply({ embeds: [ client.mkembed({
|
||||
title: "퐁!!",
|
||||
description: `${ping}ms`,
|
||||
}) ] });
|
||||
}
|
||||
async messageRun(message: Message) {
|
||||
if (message.channel?.type !== ChannelType.GuildText) return;
|
||||
const msg = await message.channel.send({ embeds: [ client.mkembed({
|
||||
title: "핑...",
|
||||
description: "계산중...",
|
||||
}) ] });
|
||||
const ping = msg.createdTimestamp - message.createdTimestamp;
|
||||
return await msg.edit({ embeds: [ client.mkembed({
|
||||
title: "퐁!!",
|
||||
description: `${ping}ms`,
|
||||
}) ] }).then(m => client.msgDelete(m, 1));
|
||||
}
|
||||
}
|
||||
83
bot/src/commands/seek.ts
Normal file
83
bot/src/commands/seek.ts
Normal file
@@ -0,0 +1,83 @@
|
||||
import { client, lavalinkManager } from "../index";
|
||||
import { Command } from "../types/Command";
|
||||
import { Message, ChatInputApplicationCommandData, ChannelType, ChatInputCommandInteraction, ApplicationCommandOptionType, Guild } from "discord.js";
|
||||
|
||||
const formatTime = (sec: number): string => {
|
||||
const s = Math.max(0, Math.floor(sec));
|
||||
return [
|
||||
Math.floor(s / 3600),
|
||||
Math.floor((s % 3600) / 60),
|
||||
s % 60,
|
||||
].map(v => v.toString().padStart(2,"0")).join(":");
|
||||
}
|
||||
|
||||
/** seek 명령어 */
|
||||
export default class implements Command {
|
||||
/** 해당 명령어 설명 */
|
||||
name = "seek";
|
||||
visible = true;
|
||||
aliases: string[] = [];
|
||||
description: string = "특정시간부터 재생";
|
||||
metaData: ChatInputApplicationCommandData = {
|
||||
name: this.name,
|
||||
description: this.description,
|
||||
options: [
|
||||
{
|
||||
type: ApplicationCommandOptionType.Integer,
|
||||
name: "hour",
|
||||
description: "시간",
|
||||
min_value: 0,
|
||||
},
|
||||
{
|
||||
type: ApplicationCommandOptionType.Integer,
|
||||
name: "min",
|
||||
description: "분",
|
||||
min_value: 0,
|
||||
},
|
||||
{
|
||||
type: ApplicationCommandOptionType.Integer,
|
||||
name: "sec",
|
||||
description: "초",
|
||||
min_value: 0,
|
||||
},
|
||||
]
|
||||
};
|
||||
|
||||
/** 실행되는 부분 */
|
||||
async slashRun(interaction: ChatInputCommandInteraction) {
|
||||
const hour = interaction.options.getInteger("hour");
|
||||
const min = interaction.options.getInteger("min");
|
||||
const sec = interaction.options.getInteger("sec");
|
||||
await interaction.editReply({ embeds: [ await this.playSeek(interaction.guild, hour, min, sec) ] });
|
||||
}
|
||||
async messageRun(message: Message) {
|
||||
if (message.channel?.type !== ChannelType.GuildText) return;
|
||||
return await message.channel.send({ content: "예시 명령어" }).then(m => client.msgDelete(m, 5));
|
||||
}
|
||||
|
||||
async playSeek(guild: Guild | null, hour: number | null, min: number | null, sec: number | null) {
|
||||
if (!guild) return client.mkembed({
|
||||
title: "guild를 가져올수 없습니다.",
|
||||
color: "DarkRed",
|
||||
});
|
||||
const seek = ((hour ?? 0)*3600 + (min ?? 0)*60 + (sec ?? 0))*1000;
|
||||
const player = lavalinkManager.getPlayer(guild.id);
|
||||
if (!player) return client.mkembed({
|
||||
title: "player를 가져올수 없습니다.",
|
||||
color: "DarkRed",
|
||||
});
|
||||
if (!player.isPlaying || !player.nowTrack) return client.mkembed({
|
||||
title: "현재 노래가 재생되지 않았습니다.",
|
||||
color: "DarkRed",
|
||||
});
|
||||
if (player.nowTrack.info.length <= seek) return client.mkembed({
|
||||
title: "노래 총시간이 더 작습니다.",
|
||||
description: `총시간: ${formatTime(player.nowTrack.info.length)}\n설정시간: ${formatTime(seek)}`,
|
||||
color: "DarkRed",
|
||||
});
|
||||
player.seek(seek);
|
||||
return client.mkembed({
|
||||
title: "재생 설정 성공",
|
||||
});
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user