Skip to content

Commit

Permalink
Changed patch mission to modal
Browse files Browse the repository at this point in the history
  • Loading branch information
coinmoles committed Dec 21, 2023
1 parent 91c5291 commit f422953
Show file tree
Hide file tree
Showing 5 changed files with 85 additions and 106 deletions.
18 changes: 5 additions & 13 deletions src/commands/missionGive/patchMission/builders.ts
Original file line number Diff line number Diff line change
@@ -1,28 +1,20 @@
import { ActionRowBuilder, ButtonBuilder, ButtonStyle, EmbedBuilder, MessageActionRowComponentBuilder } from "discord.js"
import { EmbedBuilder } from "discord.js"
import { cancelColor, errorColor, normalColor, successColor } from "../../utils/colors.js"

const commandId = "patch-mission"

const missionNotFoundEmbed = new EmbedBuilder().setTitle("승격조건을 찾을 수 없습니다.").setColor(errorColor)

const noChangeEmbed = new EmbedBuilder().setTitle("수정 사항이 없습니다").setColor(errorColor)
const replyEmbedPrototype = new EmbedBuilder().setTitle("승격조건을 수정합니까?").setColor(normalColor)
const successEmbedPrototype = new EmbedBuilder().setTitle("승격조건을 수정했습니다").setColor(successColor)
const cancelEmbedPrototype = new EmbedBuilder().setTitle("승격조건 수정을 취소했습니다").setColor(cancelColor)

const confirmButtonId = "patch-mission-confirm"
const confirmButton = new ButtonBuilder().setCustomId(confirmButtonId).setLabel("확인").setStyle(ButtonStyle.Success)
const cancelButtonId = "patch-mission-cancel"
const cancelButton = new ButtonBuilder().setCustomId(cancelButtonId).setLabel("취소").setStyle(ButtonStyle.Danger)
const actionRow = new ActionRowBuilder<MessageActionRowComponentBuilder>().addComponents(confirmButton, cancelButton)

export default {
commandId,
missionNotFoundEmbed,
noChangeEmbed,
replyEmbedPrototype,
successEmbedPrototype,
cancelEmbedPrototype,
confirmButtonId,
confirmButton,
cancelButtonId,
cancelButton,
actionRow
cancelEmbedPrototype
}
5 changes: 1 addition & 4 deletions src/commands/missionGive/patchMission/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,7 @@ const patchMission: SlashCommandSubcommandContainer = {
.setDescription(description)
.addUserOption(option => option.setName("대상").setDescription("수정할 승격조건 대상, 공통 조건을 수정하는 경우 자기 자신을 입력").setRequired(true))
.addStringOption(option => option.setName("카테고리").setDescription("수정할 승격조건 카테고리, 카테고리가 없는 경우 \"공통 조건\" 또는 \"개인 조건\" 입력").setRequired(true))
.addNumberOption(option => option.setName("번호").setDescription("수정할 승격조건 번호 (1-base)").setRequired(true))
.addStringOption(option => option.setName("내용").setDescription("수정 후 승격조건 내용"))
.addStringOption(option => option.setName("비고").setDescription("수정 후 승격조건 비고"))
.addNumberOption(option => option.setName("점수").setDescription("수정 후 승격조건 점수")),
.addNumberOption(option => option.setName("번호").setDescription("수정할 승격조건 번호 (1-base)").setRequired(true)),
callback: reply
}

Expand Down
142 changes: 69 additions & 73 deletions src/commands/missionGive/patchMission/operations.ts
Original file line number Diff line number Diff line change
@@ -1,120 +1,116 @@
import { ButtonInteraction, ChatInputCommandInteraction, ComponentType, EmbedBuilder, InteractionResponse, Message, User } from "discord.js"
import { ButtonInteraction, ChatInputCommandInteraction, ComponentType, EmbedBuilder, InteractionResponse, Message, ModalSubmitInteraction, User } from "discord.js"
import { getMission, patchMission } from "../../../db/actions/missionActions.js"
import { Mission, MissionUpdateData } from "../../../interfaces/models/Mission.js"
import { checkAssociate } from "../../utils/checks/checkAssociate.js"
import { createMissionEditPreviewString, createMissionPreviewTitle } from "../../utils/createString/createMissionPreviewString.js"
import { errorEmbed } from "../../utils/errorEmbeds.js"
import { getQuarterDataFooter } from "../../utils/quarterData/getQuarterData.js"
import builders from "./builders.js"
import { createMissionModal, createMissionModalId, getMissionModalMission } from "../../utils/components/missionModal.js"
import { addConfirmCollector, createConfirmActionRow } from "../../utils/components/confirmActionRow.js"

const {
commandId,
missionNotFoundEmbed,
noChangeEmbed,
replyEmbedPrototype,
successEmbedPrototype,
cancelEmbedPrototype,
confirmButtonId,
cancelButtonId,
actionRow
cancelEmbedPrototype
} = builders

const readOptions = (interaction: ChatInputCommandInteraction) => ({
export const readOptions = (interaction: ChatInputCommandInteraction) => ({
target: interaction.options.getUser("대상", true),
category: interaction.options.getString("카테고리", true),
index: interaction.options.getNumber("번호", true) - 1,
content: interaction.options.getString("내용"),
note: interaction.options.getString("비고"),
score: interaction.options.getNumber("점수")
})

const doConfirm = async (
interaction: ChatInputCommandInteraction, buttonInteraction: ButtonInteraction,
target: User, category: string, index: number, missionUpdateData: MissionUpdateData,
const onConfirm = (
interaction: ModalSubmitInteraction,
target: User, category: string, index: number,
missionNew: Mission, missionLast: Mission
) => {
await buttonInteraction.deferReply({ephemeral: true})
) =>
async (buttonInteraction: ButtonInteraction) => {
await buttonInteraction.deferReply({ ephemeral: true })

const success = await patchMission(interaction.user.id, target.id, category, index, missionUpdateData)
const success = await patchMission(interaction.user.id, target.id, category, index, missionNew)

if (success) {
const successEmbed = new EmbedBuilder(successEmbedPrototype.toJSON())
.addFields({ name: createMissionPreviewTitle(missionNew, target), value: createMissionEditPreviewString(missionNew, missionLast, target) })
if (success) {
const successEmbed = new EmbedBuilder(successEmbedPrototype.toJSON())
.addFields({ name: createMissionPreviewTitle(missionNew, target), value: createMissionEditPreviewString(missionNew, missionLast, target) })

await buttonInteraction.deleteReply()
await interaction.editReply({ embeds: [successEmbed.setFooter(await getQuarterDataFooter())], components: [] })
await buttonInteraction.deleteReply()
await interaction.editReply({ embeds: [successEmbed.setFooter(await getQuarterDataFooter())], components: [] })
}
else
await buttonInteraction.editReply({ embeds: [errorEmbed] })
}
else
await buttonInteraction.editReply({ embeds: [errorEmbed] })
}

const doCancel = async (
interaction: ChatInputCommandInteraction, buttonInteraction: ButtonInteraction,
target: User, category: string, index: number, missionUpdateData: MissionUpdateData,
const onCancel = (
interaction: ModalSubmitInteraction,
target: User, category: string, index: number,
missionNew: Mission, missionLast: Mission
) => {
await buttonInteraction.deferUpdate()

const cancelEmbed = new EmbedBuilder(cancelEmbedPrototype.toJSON())
.addFields({ name: createMissionPreviewTitle(missionNew, target), value: createMissionEditPreviewString(missionNew, missionLast, target) })
) =>
async (buttonInteraction: ButtonInteraction) => {
await buttonInteraction.deferUpdate()

await interaction.editReply({ embeds: [cancelEmbed.setFooter(await getQuarterDataFooter())], components: [] })
}
const cancelEmbed = new EmbedBuilder(cancelEmbedPrototype.toJSON())
.addFields({ name: createMissionPreviewTitle(missionNew, target), value: createMissionEditPreviewString(missionNew, missionLast, target) })

const addCollector = (
interaction: ChatInputCommandInteraction, reply: Message<boolean> | InteractionResponse<boolean>,
target: User, category: string, index: number, missionUpdateData: MissionUpdateData,
missionNew: Mission, missionLast: Mission
) => {
const collector = reply.createMessageComponentCollector({
filter: i => i.user === interaction.user,
componentType: ComponentType.Button
})

collector.on("collect", async buttonInteraction => {
if (buttonInteraction.customId === confirmButtonId)
doConfirm(interaction, buttonInteraction, target, category, index, missionUpdateData, missionNew, missionLast)
else if (buttonInteraction.customId === cancelButtonId)
doCancel(interaction, buttonInteraction, target, category, index, missionUpdateData, missionNew, missionLast)
})
}

const doReply = async (interaction: ChatInputCommandInteraction, target: User, category: string, index: number, missionUpdateData: MissionUpdateData, isEditing: boolean = false) => {
if (!isEditing)
await interaction.deferReply({ephemeral: true})
await interaction.editReply({ embeds: [cancelEmbed.setFooter(await getQuarterDataFooter())], components: [] })
}

export const doReply = async (interaction: ChatInputCommandInteraction, target: User, category: string, index: number, isEditing: boolean = false) => {
if (!await checkAssociate(interaction, target.id, true))
return

if (missionUpdateData.content === undefined && missionUpdateData.note === undefined && missionUpdateData.score === undefined) {
await interaction.editReply({ embeds: [noChangeEmbed] })
return
}

const missionLast = await getMission(interaction.user.id, target.id, category, index)

if (missionLast === null) {
await interaction.editReply({ embeds: [missionNotFoundEmbed] })
await interaction.reply({ embeds: [missionNotFoundEmbed] })
return
}
if (missionLast === undefined) {
await interaction.editReply({ embeds: [errorEmbed] })
await interaction.reply({ embeds: [errorEmbed] })
return
}

const missionNew: Mission = {
...missionLast,
...missionUpdateData
await interaction.showModal(createMissionModal(
commandId, interaction.user, target,
missionLast.category, missionLast.content, missionLast.score, missionLast.note
))

const modalInteraction = await interaction.awaitModalSubmit({
filter: mI => mI.customId === createMissionModalId(commandId, interaction.user),
time: 60_000
}).catch(_ => null)
if (modalInteraction === null)
return

const missionNew = getMissionModalMission(modalInteraction, target, missionLast.completed)
if (missionNew === undefined) {
await modalInteraction.reply("점수가 숫자가 아닙니다!")
return
}
else if (missionNew.content === missionLast.content && missionNew.note === missionLast.note && missionNew.score === missionLast.score) {
await modalInteraction.reply({ embeds: [noChangeEmbed] })
return
}

const replyEmbed = new EmbedBuilder(replyEmbedPrototype.toJSON())
.addFields({ name: createMissionPreviewTitle(missionNew, target), value: createMissionEditPreviewString(missionNew, missionLast, target) })
const reply = await interaction.editReply({ embeds: [replyEmbed.setFooter(await getQuarterDataFooter())], components: [actionRow] });
const reply = await modalInteraction.reply({
embeds: [
EmbedBuilder.from(replyEmbedPrototype)
.addFields({ name: createMissionPreviewTitle(missionNew, target), value: createMissionEditPreviewString(missionNew, missionLast, target) })
.setFooter(await getQuarterDataFooter())
],
components: [createConfirmActionRow(commandId, modalInteraction.user)],
ephemeral: true,
fetchReply: true
});

if (!isEditing)
addCollector(interaction, reply, target, category, index, missionUpdateData, missionNew, missionLast)
}

export default {
readOptions,
doReply
await addConfirmCollector(
commandId, modalInteraction, reply,
onConfirm(modalInteraction, target, category, index, missionNew, missionLast),
onCancel(modalInteraction, target, category, index, missionNew, missionLast)
)
}
13 changes: 3 additions & 10 deletions src/commands/missionGive/patchMission/reply.ts
Original file line number Diff line number Diff line change
@@ -1,21 +1,14 @@
import assert from "assert"
import { InteractionOperation } from "../../../interfaces/commands/InteractionOperation.js"
import { MissionUpdateData } from "../../../interfaces/models/Mission.js"
import operations from "./operations.js"

const { readOptions, doReply } = operations
import { doReply, readOptions } from "./operations.js"

const reply: InteractionOperation = async interaction => {
assert(interaction.isChatInputCommand())

const { target, index, category, content, note, score } = readOptions(interaction)

const missionUpdateData: MissionUpdateData = {}
if (content !== null) missionUpdateData.content = content
if (note !== null) missionUpdateData.note = note
if (score !== null) missionUpdateData.score = score
const { target, index, category } = readOptions(interaction)

await doReply(interaction, target, category, index, missionUpdateData)
await doReply(interaction, target, category, index)
}

export default reply
13 changes: 7 additions & 6 deletions src/commands/missionGive/postMission/operations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ export const doReply = async (interaction: ChatInputCommandInteraction, target:
await modalInteraction.reply("점수가 숫자가 아닙니다!")
return
}

const reply = await modalInteraction.reply({
embeds: [
EmbedBuilder.from(replyEmbedPrototype)
Expand All @@ -77,9 +77,10 @@ export const doReply = async (interaction: ChatInputCommandInteraction, target:
fetchReply: true
});

await addConfirmCollector(
commandId, modalInteraction, reply,
onConfirm(modalInteraction, target, mission),
onCancel(modalInteraction, target, mission)
)
if (!isEditing)
await addConfirmCollector(
commandId, modalInteraction, reply,
onConfirm(modalInteraction, target, mission),
onCancel(modalInteraction, target, mission)
)
}

0 comments on commit f422953

Please sign in to comment.