Skip to content

Commit

Permalink
✏️ Rename: Ticket to Template, and new class TemplateBuilder
Browse files Browse the repository at this point in the history
  • Loading branch information
Ashu11-A committed May 27, 2024
1 parent 05fccc7 commit a441964
Show file tree
Hide file tree
Showing 8 changed files with 261 additions and 38 deletions.
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { Database } from "@/controller/database"
import { ButtonBuilder, StringSelectMenuBuilder } from "@/discord/base/CustomIntetaction"
import Template, { TypeTemplate } from "@/entity/Template.entry"
import TemplateTable, { TypeTemplate } from "@/entity/Template.entry"
import { ActionDrawer } from "@/functions/actionDrawer"
import { checkChannel } from "@/functions/checkChannel"
import { ActionRowBuilder, ButtonInteraction, ButtonStyle, CacheType, CommandInteraction, EmbedBuilder, ModalSubmitInteraction, SelectMenuBuilder, StringSelectMenuInteraction } from "discord.js"
const template = new Database<Template>({ table: 'Template' })
const template = new Database<TemplateTable>({ table: 'Template' })
interface TicketOptions {
interaction: CommandInteraction<CacheType> | ModalSubmitInteraction<CacheType> | ButtonInteraction<CacheType> | StringSelectMenuInteraction<CacheType>
}
Expand All @@ -13,23 +13,28 @@ interface TicketCreate {
title: string,
description: string
channelId: string
guildId: string
}

interface GenerateButtons {
messageId?: string
}

export class Ticket {
export class Template {
private readonly interaction
constructor ({ interaction }: TicketOptions) {
this.interaction = interaction
}

async createTemplate ({ title, description, channelId }: TicketCreate) {
async create ({ title, description, channelId, guildId }: TicketCreate) {
if (!(this.interaction instanceof CommandInteraction)) return
if (!this.interaction.deferred) await this.interaction.deferReply()
const channel = await checkChannel(channelId, this.interaction)
const template = new Database<Template>({ table: 'Template' })
// const cart = new DefaultTicketCart()
// .setTitle(this.interaction.guild?.name ?? '')
// .setDescription('Teste')
// const image = await cart.build({ format: 'png' })
// const attachment = new AttachmentBuilder(image, { name: 'ticketView.png' })

if (!channel) return

Expand All @@ -43,6 +48,7 @@ export class Ticket {

await channel.send({ embeds: [embed], components: [...buttons, ...select] }).then(async (message) => {
const create = await template.create({
guild: { id: guildId },
messageId: message.id,
channelId: channel.id,
embed: embed.data
Expand Down Expand Up @@ -193,7 +199,7 @@ export class Ticket {
row.push(
new ButtonBuilder({
customId: 'Open',
label: 'Abrir Ticket',
label: 'Abrir Template',
style: ButtonStyle.Success,
emoji: { name: '🎫' }
}),
Expand Down
95 changes: 95 additions & 0 deletions plugins/tickets/src/class/TemplateBuilder.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
import { Database } from "@/controller/database";
import { Error } from "@/discord/base/CustomResponse";
import TemplateTable from "@/entity/Template.entry";
import { EmbedBuilder } from "@discordjs/builders";
import { APIEmbed as APIEmbedDiscord, ButtonInteraction, CacheType, Colors, CommandInteraction, ModalSubmitInteraction, StringSelectMenuInteraction } from "discord.js";
import { Template } from "./Template";

const database = new Database<TemplateTable>({ table: 'Template' })

type Interaction = CommandInteraction<CacheType> | ModalSubmitInteraction<CacheType> | ButtonInteraction<CacheType> | StringSelectMenuInteraction<CacheType>
interface TemplateBuilderOptions {
interaction: Interaction
}

interface APIEmbed {
title: string;
description: string;
color: string;
image: string;
thumbnail: string;
}


export class TemplateBuilder {
private readonly interaction: Interaction
private readonly options!: APIEmbed
private mode!: 'debug' | 'production'

constructor ({ interaction }: TemplateBuilderOptions) {
this.interaction = interaction
this.options = {
title: '',
description: '',
image: '',
thumbnail: '',
color: ''
}
}

setTitle (value: string) { this.options.title = value; return this }
setDescription (value: string) { this.options.description = value; return this }
setThumbnail (value: string) { this.options.thumbnail = value; return this }
setImage (value: string) { this.options.image = value; return this }
setColor (value: string) { this.options.color = value; return this }
setMode (value: 'debug' | 'production') { this.mode = value; return this}

render (original: APIEmbedDiscord): EmbedBuilder {
const { color, description, image, thumbnail, title } = this.options
const embed = new EmbedBuilder(original)

if (title !== '') embed.setTitle(title)
if (description !== '') embed.setDescription(description)
if (image !== '') embed.setImage(image)
if (thumbnail !== '') embed.setThumbnail(thumbnail)
if (color !== '') embed.setColor(Number(color))

return embed
}

async edit ({ messageId }: { messageId: string }) {
const template = new Template({ interaction: this.interaction })
const templateData = await database.findOne({ where: { messageId } })
if (templateData === null) { await new Error({ element: 'o template', interaction: this.interaction }).notFound({ type: 'Database' }).reply(); return }

const channel = await this.interaction.guild?.channels.fetch(templateData.channelId)
if (!channel?.isTextBased()) { await new Error({ element: templateData.channelId, interaction: this.interaction }).notFound({ type: "Channel" }).reply(); return }

const message = await channel.messages.fetch(templateData.messageId)
if (!channel?.isTextBased()) { await new Error({ element: templateData.messageId, interaction: this.interaction }).notFound({ type: "Message" }).reply(); return }

if (Object.values(Colors).find((color) => color === Number(this.options.color)) === undefined) {
await new Error({ element: 'cor', interaction: this.interaction }).invalidProperty('Format').reply()
return
}

const embed = this.render(templateData.embed)

templateData.embed = embed.toJSON()
await database.save(templateData)

switch (this.mode) {
case "debug": {
const [buttons, select] = await template.genEditButtons({ messageId: templateData.messageId })
message.edit({ components: [...buttons, ...select] })
break
}
case "production": {
const components = await template.genProductionButtons({ messageId: templateData.messageId })
message.edit({ components })
break
}
}
await message.edit({ embeds: [embed] })
}
}
119 changes: 119 additions & 0 deletions plugins/tickets/src/discord/commands/ticket.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
import { TemplateBuilder } from "@/class/TemplateBuilder";
import { Database } from "@/controller/database";
import TemplateTable from "@/entity/Template.entry";
import { ApplicationCommandOptionChoiceData, ApplicationCommandOptionType, ApplicationCommandType, ColorResolvable, Colors, resolveColor } from "discord.js";
import { Command } from "../base";

const templateDb = new Database<TemplateTable>({ table: 'Template' })

new Command({
name: 'ticket',
description: 'Sistema de tickets por comando',
type: ApplicationCommandType.ChatInput,
dmPermission: false,
options: [
{
name: 'template',
description: 'Editar Template',
type: ApplicationCommandOptionType.Subcommand,
options: [
{
name: 'message_id',
description: 'Id da mensagem que quer editar',
type: ApplicationCommandOptionType.String,
required: true,
autocomplete: true
},
{
name: 'mode',
description: 'Entrar/Sair do modo edição do template',
type: ApplicationCommandOptionType.String,
choices: [
{ name: 'Edição', value: 'edit' },
{ name: 'Produção', value: 'production' }
]
},
{
name: 'title',
description: 'Alterar título do template',
type: ApplicationCommandOptionType.String,
},
{
name: 'description',
description: 'Alterar descrição do template',
type: ApplicationCommandOptionType.String,
},
{
name: 'thumbnail',
description: 'Alterar Thumbnail do template',
type: ApplicationCommandOptionType.String,
},
{
name: 'image',
description: 'Alterar Imagem do template',
type: ApplicationCommandOptionType.String,
},
{
name: 'color',
description: 'Alterar cor do template',
type: ApplicationCommandOptionType.String,
autocomplete: true
}
]
}
],
async autoComplete(interaction) {
const { options, guildId, } = interaction
const respond: ApplicationCommandOptionChoiceData[] = []
if (guildId === null) return

switch (options.getFocused(true).name) {
case 'message_id': {
const templateData = await templateDb.find({ where: { guild: { id: guildId } } })
respond.push(...templateData.map((template) => ({ name: template?.embed?.title ?? template.messageId, value: template.messageId })))
break
}
case 'color': {
let num = 0
for (const [color, value] of Object.entries(Colors)) {
if (num === 25) continue
if (color.includes('Dark')) continue
respond.push({ name: color, value: String(value) })
num++
}
break
}

}
await interaction.respond(respond)
},
async run(interaction) {
const { options } = interaction
switch (options.getSubcommand()) {
case 'template': {
await interaction.deferReply({ ephemeral: true })
const builder = new TemplateBuilder({ interaction })

const templateId = options.getString('message_id', true)
const switchMode = options.getString('mode')
const title = options.getString('title')
const description = options.getString('description')
const thumbnail = options.getString('thumbnail')
const image = options.getString('image')
const color = options.getString('color')

if (title !== null) builder.setTitle(title)
if (description !== null) builder.setDescription(description)
if (thumbnail !== null) builder.setThumbnail(thumbnail)
if (image !== null) builder.setImage(image)
if (color !== null) builder.setColor(color)
if (switchMode) builder.setMode(switchMode as 'debug' | 'production')

await builder.edit({ messageId: templateId })
if (!interaction.replied) await interaction.deleteReply()
break
}
}

},
})
24 changes: 12 additions & 12 deletions plugins/tickets/src/discord/components/Template/AddElements.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import { Ticket } from "@/class/Ticket";
import { Template } from "@/class/Template";
import { Database } from "@/controller/database";
import { Component } from "@/discord/base";
import { ModalBuilder } from "@/discord/base/CustomIntetaction";
import Template from "@/entity/Template.entry";
import TemplateTable from "@/entity/Template.entry";
import { ActionRowBuilder, APITextInputComponent, ComponentType, EmbedBuilder, TextInputBuilder } from "discord.js";

const template = new Database<Template>({ table: 'Template' })
const templateDb = new Database<TemplateTable>({ table: 'Template' })
const notFound = new EmbedBuilder({
title: '❌ Não encontrei o template no database!'
}).setColor('Red')
Expand Down Expand Up @@ -62,8 +62,8 @@ new Component({
const title = interaction.fields.getTextInputValue('title')
const emoji = interaction.fields.getTextInputValue('emoji')
const description = interaction.fields.getTextInputValue('description')
const templateData = await template.findOne({ where: { messageId: interaction.message?.id } })
const ticket = new Ticket({ interaction })
const templateData = await templateDb.findOne({ where: { messageId: interaction.message?.id } })
const template = new Template({ interaction })

if (templateData === null) {
await interaction.reply({ embeds: [notFound] })
Expand All @@ -72,7 +72,7 @@ new Component({

templateData.selects = [ ...(templateData.selects ?? []), { emoji, title, description }]

await template.save(templateData)
await templateDb.save(templateData)
.then(async () => {
await interaction.reply({
ephemeral: true,
Expand All @@ -83,7 +83,7 @@ new Component({
]
})

const [buttons, select] = await ticket.genEditButtons({ messageId: interaction.message?.id })
const [buttons, select] = await template.genEditButtons({ messageId: interaction.message?.id })

await interaction.message?.edit({ components: [...buttons, ...select] })
})
Expand All @@ -106,13 +106,13 @@ new Component({
type: 'StringSelect',
async run(interaction) {
const { values } = interaction
const ticket = new Ticket({ interaction })
const template = new Template({ interaction })

const templateData = await template.findOne({ where: { messageId: interaction.message.id } })
const templateData = await templateDb.findOne({ where: { messageId: interaction.message.id } })

console.log(values)

const [buttons, select] = await ticket.genEditButtons({ messageId: interaction.message.id })
const [buttons, select] = await template.genEditButtons({ messageId: interaction.message.id })

},
})
Expand Down Expand Up @@ -160,7 +160,7 @@ new Component({
async run(interaction) {
const title = interaction.fields.getTextInputValue('title')
const emoji = interaction.fields.getTextInputValue('emoji')
const templateData = await template.findOne({ where: { messageId: interaction.message?.id } })
const templateData = await templateDb.findOne({ where: { messageId: interaction.message?.id } })

if (templateData === null) {
await interaction.reply({ embeds: [notFound] })
Expand All @@ -169,7 +169,7 @@ new Component({

templateData.categories = [ ...(templateData.categories ?? []), { emoji, title }]

await template.save(templateData)
await templateDb.save(templateData)
.then(async () => {
await interaction.reply({
ephemeral: true,
Expand Down
18 changes: 10 additions & 8 deletions plugins/tickets/src/discord/components/Template/Switch.ts
Original file line number Diff line number Diff line change
@@ -1,26 +1,28 @@
import { Ticket } from "@/class/Ticket";
import { Template } from "@/class/Template";
import { TemplateBuilder } from "@/class/TemplateBuilder";
import { Component } from "@/discord/base";

new Component({
customId: 'Save',
type: "Button",
async run(interaction) {
await interaction.deferReply({ ephemeral: true })
const components = await (new Ticket({ interaction })).genProductionButtons({ messageId: interaction.message.id })
await new TemplateBuilder({ interaction })
.setMode('production')
.edit({ messageId: interaction.message.id })

await interaction.message.edit({ components })
await interaction.deleteReply()
if (!interaction.replied) await interaction.deleteReply()
},
})

new Component({
customId: 'Config',
type: "Button",
async run(interaction) {
await interaction.deferReply({ ephemeral: true })
const [buttons, select] = await (new Ticket({ interaction })).genEditButtons({ messageId: interaction.message.id })
await new TemplateBuilder({ interaction })
.setMode('debug')
.edit({ messageId: interaction.message.id })

await interaction.message.edit({ components: [...buttons, ...select] })
await interaction.deleteReply()
if (!interaction.replied) await interaction.deleteReply()
},
})
Loading

0 comments on commit a441964

Please sign in to comment.