help command + limit users on amount of tickets
This commit is contained in:
parent
637c2800d4
commit
56e2dcfff6
@ -9,8 +9,9 @@ import {
|
||||
GuildTextThreadCreateOptions,
|
||||
MessageCreateOptions,
|
||||
Role,
|
||||
roleMention, ThreadChannel,
|
||||
userMention
|
||||
roleMention,
|
||||
ThreadChannel,
|
||||
userMention,
|
||||
} from 'discord.js'
|
||||
|
||||
import { db, DBTableEnum } from '../../db'
|
||||
@ -25,6 +26,8 @@ import {
|
||||
} from '../../utils'
|
||||
import { logger } from '../../lib'
|
||||
|
||||
type Ticket = { user: string; channel: string }
|
||||
|
||||
@Discord()
|
||||
export class CreateTicketSystem {
|
||||
@Slash({
|
||||
@ -124,15 +127,15 @@ export class CreateTicketSystem {
|
||||
return
|
||||
}
|
||||
|
||||
// prevent creating ticket for users with 3 or more tickets
|
||||
const allThreads = await interaction.channel.threads.fetch()
|
||||
const ownedThreads = allThreads.threads.reduce((total, thread) => {
|
||||
if (thread.ownerId === interaction.user.id && (!thread.archived || !thread.locked)) total += 1
|
||||
return total
|
||||
}, 0)
|
||||
if (ownedThreads >= 3 && interaction.user.id !== interaction.guild.ownerId) {
|
||||
logger.action('Denied ticket creation', `User: ${interaction.user.username}(${interaction.user.id})\nActive tickets: ${ownedThreads}`)
|
||||
await interaction.editReply('❌ You already have too many tickets')
|
||||
const hasOpenedTicket = await db
|
||||
.get<Ticket[]>(DBTableEnum.TICKET_OWNERS)
|
||||
.then(r =>
|
||||
Array.isArray(r)
|
||||
? !!r.find(ticket => ticket.user === interaction.user.id)
|
||||
: false,
|
||||
)
|
||||
if (hasOpenedTicket) {
|
||||
await interaction.editReply(`❌ You already have an active ticket`)
|
||||
return
|
||||
}
|
||||
|
||||
@ -143,7 +146,7 @@ export class CreateTicketSystem {
|
||||
// create ticket channel
|
||||
const threadChannelSettings: GuildTextThreadCreateOptions<AllowedThreadTypeForTextChannel> =
|
||||
{
|
||||
name: `${interaction.user.username}-${(new Date).toLocaleDateString().replaceAll('/', '-')}`,
|
||||
name: `${interaction.user.username}-${new Date().toLocaleDateString().replaceAll('/', '-')}`,
|
||||
type: ChannelType.PrivateThread,
|
||||
invitable: false,
|
||||
}
|
||||
@ -155,6 +158,22 @@ export class CreateTicketSystem {
|
||||
return
|
||||
}
|
||||
|
||||
await db
|
||||
.push<Ticket>(DBTableEnum.TICKET_OWNERS, {
|
||||
user: interaction.user.id,
|
||||
channel: threadChannel.id,
|
||||
})
|
||||
.then(() => {
|
||||
logger.database(
|
||||
'Updated active tickets',
|
||||
`Added User: ${interaction.user.id}\n Channel: ${threadChannel.id}`,
|
||||
)
|
||||
})
|
||||
logger.database(
|
||||
'Updated active tickets',
|
||||
`Removed channel ${interaction.channel.id}`,
|
||||
)
|
||||
|
||||
// welcoming message in ticket
|
||||
const threadChannelMessage: MessageCreateOptions = {
|
||||
content: `${userMention(interaction.user.id)} ${roleMention(ticketRole)}`,
|
||||
@ -186,7 +205,10 @@ export class CreateTicketSystem {
|
||||
await threadChannel.members.add(user)
|
||||
await threadChannel.members.add(owner)
|
||||
|
||||
logger.action('Created ticket', `User: ${user.user.username}(${user.id})\nChannel: ${threadChannel.name}(${threadChannel.id})`)
|
||||
logger.action(
|
||||
'Created ticket',
|
||||
`User: ${user.user.username}(${user.id})\nChannel: ${threadChannel.name}(${threadChannel.id})`,
|
||||
)
|
||||
|
||||
// close interaction
|
||||
await interaction.editReply({
|
||||
@ -203,7 +225,10 @@ export class CreateTicketSystem {
|
||||
async closeBtn(interaction: ButtonInteraction): Promise<void> {
|
||||
await interaction.deferReply()
|
||||
|
||||
logger.action('Ticket close attempt', `User: ${interaction.user.username}(${interaction.user.id})\nChannel: ${interaction.channel?.id}`)
|
||||
logger.action(
|
||||
'Ticket close attempt',
|
||||
`User: ${interaction.user.username}(${interaction.user.id})\nChannel: ${interaction.channel?.id}`,
|
||||
)
|
||||
|
||||
if (!interaction.channel || !interaction.guild) {
|
||||
await interaction.editReply('❌ Ticket channel does not exist')
|
||||
@ -216,18 +241,42 @@ export class CreateTicketSystem {
|
||||
await interaction.editReply('Closing ticket..')
|
||||
|
||||
try {
|
||||
// remove ticket owner if exists
|
||||
const ticketOwner = interaction.channel.ownerId ? await interaction.guild.members.fetch(interaction.channel.ownerId) : null
|
||||
ticketOwner ? await interaction.channel.members.remove(ticketOwner) : null
|
||||
|
||||
// lock + archive thread
|
||||
await interaction.channel.setLocked(true, `Locked by ${userMention(interaction.user.id)}(${interaction.user.id})`)
|
||||
await interaction.channel.setArchived(true, `Archived by ${userMention(interaction.user.id)}(${interaction.user.id})`)
|
||||
await interaction.channel.setLocked(
|
||||
true,
|
||||
`Locked by ${userMention(interaction.user.id)}(${interaction.user.id})`,
|
||||
)
|
||||
await interaction.channel.setArchived(
|
||||
true,
|
||||
`Archived by ${userMention(interaction.user.id)}(${interaction.user.id})`,
|
||||
)
|
||||
} catch (e) {
|
||||
logger.error('Closing ticket', e)
|
||||
return
|
||||
}
|
||||
|
||||
logger.action('Ticket close attempt successful', `User: ${interaction.user.username}(${interaction.user.id})\nChannel: ${interaction.channel?.id}`)
|
||||
const tickets = await db.get<Ticket[]>(DBTableEnum.TICKET_OWNERS)
|
||||
if (tickets) {
|
||||
const res = tickets.reduce<Ticket[]>((res, ticket) => {
|
||||
if (
|
||||
interaction.channel &&
|
||||
ticket.channel === interaction.channel.id
|
||||
) {
|
||||
res.push(ticket)
|
||||
}
|
||||
return res
|
||||
}, [])
|
||||
await db.set(DBTableEnum.TICKET_OWNERS, res).then(() => {
|
||||
logger.database(
|
||||
'Updated active tickets',
|
||||
`Removed channel ${interaction.channel?.id}`,
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
logger.action(
|
||||
'Ticket close attempt successful',
|
||||
`User: ${interaction.user.username}(${interaction.user.id})\nChannel: ${interaction.channel?.id}`,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
44
src/commands/admin/help.ts
Normal file
44
src/commands/admin/help.ts
Normal file
@ -0,0 +1,44 @@
|
||||
import { Discord, Slash } from 'discordx'
|
||||
import { CommandInteraction, EmbedBuilder } from 'discord.js'
|
||||
|
||||
@Discord()
|
||||
export class Payments {
|
||||
@Slash({
|
||||
name: 'payments',
|
||||
description: 'See available payments',
|
||||
defaultMemberPermissions: 'Administrator',
|
||||
})
|
||||
async payments(interaction: CommandInteraction) {
|
||||
await interaction.deferReply({ ephemeral: true })
|
||||
|
||||
const embed = new EmbedBuilder().setTitle(`Commands`).setFields([
|
||||
{
|
||||
name: 'Users',
|
||||
value: '```/feedback\n' + '/payments```',
|
||||
},
|
||||
{
|
||||
name: 'Setters',
|
||||
value:
|
||||
'```/set-banner-ticket\n' +
|
||||
'/set-banner-welcome\n' +
|
||||
'/set-feedback-channel\n' +
|
||||
'/set-portfolio-channel\n' +
|
||||
'/set-price-channel\n' +
|
||||
'/set-order-channel\n' +
|
||||
'/set-welcome-channel\n' +
|
||||
'/set-status\n```',
|
||||
},
|
||||
{
|
||||
name: 'Admin',
|
||||
value:
|
||||
'```/ping - потому что могу\n\n' +
|
||||
'/help - без понятия\n\n' +
|
||||
'/create-ticket-system - Создать систему тикетов отталкиваясь от текущего канала.\n' +
|
||||
'Требует /set-banner-ticket /set-prices-channel /set-status\n\n' +
|
||||
'/remove-active-ticket - удалить из базы все активные тикеты пользователя если что-то произошло и они не удалились при архивации тикета```',
|
||||
},
|
||||
])
|
||||
|
||||
await interaction.editReply({ embeds: [embed] })
|
||||
}
|
||||
}
|
59
src/commands/admin/remove-active-ticket.ts
Normal file
59
src/commands/admin/remove-active-ticket.ts
Normal file
@ -0,0 +1,59 @@
|
||||
import { Discord, Slash, SlashChoice, SlashOption } from 'discordx'
|
||||
import {
|
||||
ApplicationCommandOptionType,
|
||||
CommandInteraction,
|
||||
User,
|
||||
} from 'discord.js'
|
||||
|
||||
import { db, DBTableEnum } from '../../db'
|
||||
import { logger } from '../../lib'
|
||||
import { feedbackEmbed } from '../../utils'
|
||||
|
||||
type Ticket = {
|
||||
user: string
|
||||
channel: string
|
||||
}
|
||||
|
||||
@Discord()
|
||||
export class RemoveActiveTicket {
|
||||
@Slash({
|
||||
name: 'remove-active-ticket',
|
||||
description: 'Remove user from database in case of need',
|
||||
defaultMemberPermissions: 'Administrator',
|
||||
})
|
||||
async feedback(
|
||||
@SlashOption({
|
||||
name: 'user',
|
||||
description: 'User to be removed',
|
||||
required: true,
|
||||
type: ApplicationCommandOptionType.User,
|
||||
})
|
||||
user: User,
|
||||
interaction: CommandInteraction,
|
||||
) {
|
||||
await interaction.deferReply({ ephemeral: true })
|
||||
|
||||
const activeTickets = await db.get<Ticket[]>(DBTableEnum.TICKET_OWNERS)
|
||||
if (!activeTickets || !activeTickets.length) {
|
||||
await interaction.editReply('❌ No active tickets found for server')
|
||||
return
|
||||
}
|
||||
|
||||
const res = activeTickets.reduce<Ticket[]>((r, ticket) => {
|
||||
if (ticket.user !== user.id) {
|
||||
r.push(ticket)
|
||||
}
|
||||
return r
|
||||
}, [])
|
||||
await db
|
||||
.set(DBTableEnum.TICKET_OWNERS, res)
|
||||
.then(() =>
|
||||
logger.database(
|
||||
DBTableEnum.TICKET_OWNERS,
|
||||
`Removed ${user.id}\nCaller: ${interaction.user.id}`,
|
||||
),
|
||||
)
|
||||
|
||||
await interaction.editReply('✔️ User tickets cleared successfully')
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user