feat: Add deleteLearnData
This commit is contained in:
parent
c5211c06d4
commit
78f2da5646
3 changed files with 242 additions and 0 deletions
148
src/commands/deleteLearnedData.ts
Normal file
148
src/commands/deleteLearnedData.ts
Normal file
|
@ -0,0 +1,148 @@
|
|||
import { MuffinCustomId } from '../lib/customId'
|
||||
import { Learn } from '../lib/databases'
|
||||
import { ApplyOptions } from '@sapphire/decorators'
|
||||
import { Args, Command } from '@sapphire/framework'
|
||||
import {
|
||||
ActionRowBuilder,
|
||||
ButtonBuilder,
|
||||
ButtonStyle,
|
||||
ChatInputCommandInteraction,
|
||||
codeBlock,
|
||||
EmbedBuilder,
|
||||
Message,
|
||||
MessageFlags,
|
||||
StringSelectMenuBuilder,
|
||||
StringSelectMenuOptionBuilder,
|
||||
} from 'discord.js'
|
||||
|
||||
@ApplyOptions<Command.Options>({
|
||||
name: '삭제',
|
||||
aliases: ['잊어', '지워'],
|
||||
description: '당신이 가르쳐준 단ㅇ어를 삭제해요.',
|
||||
detailedDescription: {
|
||||
usage: '머핀아 삭제 (삭제할 단어)',
|
||||
examples: ['머핀아 삭제 머핀'],
|
||||
},
|
||||
})
|
||||
export default class DeleteLearnedData extends Command {
|
||||
public registerApplicationCommand(registry: Command.Registry) {
|
||||
registry.registerChatInputCommand(builder =>
|
||||
builder
|
||||
.setName(this.name)
|
||||
.setDescription(this.description)
|
||||
.addStringOption(option =>
|
||||
option
|
||||
.setName('단어')
|
||||
.setDescription('삭제할 단어를 입ㄹ력해주세요.')
|
||||
.setRequired(true),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
public async messageRun(msg: Message<true>, args: Args) {
|
||||
return await this._run(msg, args)
|
||||
}
|
||||
|
||||
public async chatInputRun(
|
||||
interaction: ChatInputCommandInteraction<'cached'>,
|
||||
) {
|
||||
return await this._run(interaction)
|
||||
}
|
||||
|
||||
private async _run(
|
||||
ctx: Message<true> | ChatInputCommandInteraction<'cached'>,
|
||||
args?: Args,
|
||||
) {
|
||||
let command: string | undefined
|
||||
let userId: string
|
||||
|
||||
if (typeof this.detailedDescription === 'string') return
|
||||
if (ctx instanceof Message) {
|
||||
if (!args) return
|
||||
command = await args.rest('string').catch(() => undefined)
|
||||
userId = ctx.author.id
|
||||
} else {
|
||||
command = ctx.options.getString('단어', true)
|
||||
userId = ctx.user.id
|
||||
}
|
||||
|
||||
if (!command) {
|
||||
// 오직 메세지 커맨드로 사용하였을 때만 표출되는 오류 메세지
|
||||
return await ctx.reply({
|
||||
embeds: [
|
||||
new EmbedBuilder()
|
||||
.setTitle('❌ 오류')
|
||||
.setDescription('올바르지 않ㅇ은 용법이에요.')
|
||||
.addFields(
|
||||
{
|
||||
name: '사용법',
|
||||
value: `\`${this.detailedDescription.usage}\``,
|
||||
},
|
||||
{
|
||||
name: '예시',
|
||||
value: this.detailedDescription
|
||||
.examples!.map(example => `\`${example}\``)
|
||||
.join('\n'),
|
||||
},
|
||||
)
|
||||
.setColor(this.container.embedColors.fail),
|
||||
],
|
||||
})
|
||||
}
|
||||
|
||||
const datas = await Learn.find({
|
||||
command,
|
||||
user_id: userId,
|
||||
})
|
||||
|
||||
if (!datas.length)
|
||||
return await ctx.reply({
|
||||
embeds: [
|
||||
new EmbedBuilder()
|
||||
.setTitle('❌ 오류')
|
||||
.setDescription('해당 하는 지식ㅇ을 찾을 수 없어요.')
|
||||
.setColor(this.container.embedColors.fail),
|
||||
],
|
||||
})
|
||||
|
||||
const options: StringSelectMenuOptionBuilder[] = []
|
||||
let description = ''
|
||||
|
||||
for (let i = 1; i <= datas.length; i++) {
|
||||
const data = datas[i - 1]
|
||||
options.push(
|
||||
new StringSelectMenuOptionBuilder()
|
||||
.setLabel(`${i}번 지식`)
|
||||
.setDescription(data.result)
|
||||
.setValue(MuffinCustomId.DeleteLearnedData + data.id + `&No.${i}`),
|
||||
)
|
||||
description += `${i}. ${data.result}\n`
|
||||
}
|
||||
|
||||
return await ctx.reply({
|
||||
embeds: [
|
||||
new EmbedBuilder()
|
||||
.setTitle(`${command} 삭제`)
|
||||
.setDescription(
|
||||
`${command}에 대한 대답 중 하나를 선ㅌ택하여 삭제해주세요.\n` +
|
||||
codeBlock('md', description),
|
||||
)
|
||||
.setColor(this.container.embedColors.default),
|
||||
],
|
||||
components: [
|
||||
new ActionRowBuilder<StringSelectMenuBuilder>().addComponents(
|
||||
new StringSelectMenuBuilder()
|
||||
.setCustomId(MuffinCustomId.DeleteLearnedDataUserId + userId)
|
||||
.addOptions(options)
|
||||
.setPlaceholder('ㅈ지울 응답을 선택해주세요.'),
|
||||
),
|
||||
new ActionRowBuilder<ButtonBuilder>().addComponents(
|
||||
new ButtonBuilder()
|
||||
.setCustomId(MuffinCustomId.DeleteLearnedDataCancel + userId)
|
||||
.setLabel('취소하기')
|
||||
.setStyle(ButtonStyle.Danger),
|
||||
),
|
||||
],
|
||||
})
|
||||
}
|
||||
}
|
89
src/interaction-handlers/deleteLearnedData.ts
Normal file
89
src/interaction-handlers/deleteLearnedData.ts
Normal file
|
@ -0,0 +1,89 @@
|
|||
import { MuffinCustomId } from '../lib/customId'
|
||||
import { Learn } from '../lib/databases'
|
||||
import { ApplyOptions } from '@sapphire/decorators'
|
||||
import {
|
||||
InteractionHandler,
|
||||
InteractionHandlerTypes,
|
||||
} from '@sapphire/framework'
|
||||
import {
|
||||
EmbedBuilder,
|
||||
MessageFlags,
|
||||
type ButtonInteraction,
|
||||
type StringSelectMenuInteraction,
|
||||
} from 'discord.js'
|
||||
|
||||
@ApplyOptions<InteractionHandler.Options>({
|
||||
interactionHandlerType: InteractionHandlerTypes.MessageComponent,
|
||||
})
|
||||
export default class DeleteLearnedDataHandler extends InteractionHandler {
|
||||
public async parse(
|
||||
interaction: StringSelectMenuInteraction | ButtonInteraction,
|
||||
) {
|
||||
const userId = interaction.isButton()
|
||||
? interaction.customId.slice(
|
||||
MuffinCustomId.DeleteLearnedDataCancel.length,
|
||||
)
|
||||
: interaction.customId.slice(
|
||||
MuffinCustomId.DeleteLearnedDataUserId.length,
|
||||
)
|
||||
|
||||
if (interaction.user.id !== userId) {
|
||||
await interaction.reply({
|
||||
flags: [MessageFlags.Ephemeral],
|
||||
embeds: [
|
||||
new EmbedBuilder()
|
||||
.setTitle('❌ 오류')
|
||||
.setDescription('당신은 해당 권한이 없ㅇ어요.')
|
||||
.setColor(this.container.embedColors.fail),
|
||||
],
|
||||
})
|
||||
}
|
||||
if (interaction.isButton()) {
|
||||
if (
|
||||
!interaction.customId.startsWith(MuffinCustomId.DeleteLearnedDataCancel)
|
||||
)
|
||||
return this.none()
|
||||
await interaction.update({
|
||||
embeds: [
|
||||
new EmbedBuilder()
|
||||
.setTitle('❌ 취소')
|
||||
.setDescription(`지식 삭제 작업ㅇ을 취소했어요.`)
|
||||
.setColor(this.container.embedColors.fail),
|
||||
],
|
||||
components: [],
|
||||
})
|
||||
return this.none()
|
||||
}
|
||||
|
||||
if (
|
||||
!interaction.customId.startsWith(MuffinCustomId.DeleteLearnedDataUserId)
|
||||
)
|
||||
return this.none()
|
||||
|
||||
return this.some()
|
||||
}
|
||||
|
||||
public async run(interaction: StringSelectMenuInteraction) {
|
||||
await interaction.deferUpdate()
|
||||
|
||||
const itemIdRegexp = /No.\d+/
|
||||
|
||||
const id = interaction.values[0]
|
||||
.slice(MuffinCustomId.DeleteLearnedData.length)
|
||||
.replace(itemIdRegexp, '')
|
||||
.replaceAll('&', '')
|
||||
const itemId = interaction.values[0].match(itemIdRegexp)!.join()
|
||||
|
||||
await Learn.findByIdAndDelete(id)
|
||||
|
||||
return await interaction.editReply({
|
||||
embeds: [
|
||||
new EmbedBuilder()
|
||||
.setTitle('✅ 삭제 완료')
|
||||
.setDescription(`${itemId.slice(3)}번을 삭ㅈ제했어요.`)
|
||||
.setColor(this.container.embedColors.success),
|
||||
],
|
||||
components: [],
|
||||
})
|
||||
}
|
||||
}
|
5
src/lib/customId.ts
Normal file
5
src/lib/customId.ts
Normal file
|
@ -0,0 +1,5 @@
|
|||
export enum MuffinCustomId {
|
||||
DeleteLearnedData = '#muffin/deleteLearnedData$',
|
||||
DeleteLearnedDataUserId = '#muffin/deleteLearnedData@',
|
||||
DeleteLearnedDataCancel = '#muffin/deleteLearnedData/cancel@',
|
||||
}
|
Reference in a new issue