tsup as bundler | ticket system init
This commit is contained in:
parent
5fa78f5ccd
commit
2b341e5107
14
package.json
14
package.json
@ -4,13 +4,11 @@
|
|||||||
"private": true,
|
"private": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"main": "build/main.js",
|
"main": "build/index.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "tsx watch src/main.ts",
|
"dev": "tsx watch src/index.ts",
|
||||||
"build": "tsc",
|
"build": "tsup",
|
||||||
"build:changelog": "npx @discordx/changelog --src src",
|
"start": "node build/index.mjs"
|
||||||
"start": "node build/main.js",
|
|
||||||
"watch": "nodemon --exec npm run dev --watch src --ext ts"
|
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@discordx/importer": "^1.3.0",
|
"@discordx/importer": "^1.3.0",
|
||||||
@ -23,9 +21,11 @@
|
|||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/node": "^20.14.1",
|
"@types/node": "^20.14.1",
|
||||||
|
"esbuild-plugin-file-path-extensions": "^2.1.1",
|
||||||
|
"esbuild-plugin-version-injector": "^1.2.1",
|
||||||
"nodemon": "^3.1.3",
|
"nodemon": "^3.1.3",
|
||||||
"prettier": "^3.3.0",
|
"prettier": "^3.3.0",
|
||||||
"ts-node": "^10.9.2",
|
"tsup": "^8.1.0",
|
||||||
"tsx": "^4.12.0",
|
"tsx": "^4.12.0",
|
||||||
"typescript": "5.4.5"
|
"typescript": "5.4.5"
|
||||||
},
|
},
|
||||||
|
870
pnpm-lock.yaml
870
pnpm-lock.yaml
File diff suppressed because it is too large
Load Diff
173
src/commands/admin/create-ticket-system.ts
Normal file
173
src/commands/admin/create-ticket-system.ts
Normal file
@ -0,0 +1,173 @@
|
|||||||
|
import { ButtonComponent, Discord, Slash, SlashOption } from 'discordx'
|
||||||
|
import {
|
||||||
|
ActionRowBuilder,
|
||||||
|
ApplicationCommandOptionType,
|
||||||
|
ButtonBuilder,
|
||||||
|
ButtonInteraction,
|
||||||
|
ButtonStyle,
|
||||||
|
channelMention,
|
||||||
|
CommandInteraction,
|
||||||
|
EmbedBuilder,
|
||||||
|
GuildMember,
|
||||||
|
MessageActionRowComponentBuilder,
|
||||||
|
Role,
|
||||||
|
ChannelType,
|
||||||
|
roleMention,
|
||||||
|
userMention,
|
||||||
|
} from 'discord.js'
|
||||||
|
import { db, DBTableEnum } from '../../db'
|
||||||
|
import { Status } from '../../utils/enums'
|
||||||
|
|
||||||
|
@Discord()
|
||||||
|
export class CreateTicketSystem {
|
||||||
|
@Slash({
|
||||||
|
description: 'Create ticket system',
|
||||||
|
name: 'create-ticket-system',
|
||||||
|
defaultMemberPermissions: 'Administrator',
|
||||||
|
})
|
||||||
|
async createTicketSystem(
|
||||||
|
@SlashOption({
|
||||||
|
name: 'role',
|
||||||
|
description: 'Role to be mentioned on ticket creation',
|
||||||
|
type: ApplicationCommandOptionType.Role,
|
||||||
|
required: true,
|
||||||
|
})
|
||||||
|
role: Role,
|
||||||
|
interaction: CommandInteraction,
|
||||||
|
) {
|
||||||
|
const pricesChannelId = await db.get(DBTableEnum.PRICE_CHANNEL)
|
||||||
|
const bannerURL = await db.get(DBTableEnum.BANNER_URL)
|
||||||
|
const workload = await db.get<Status>(DBTableEnum.WORKLOAD)
|
||||||
|
await db.set(DBTableEnum.TICKET_ROLE, role.id)
|
||||||
|
|
||||||
|
// create ticket embed
|
||||||
|
const createBtn = new ButtonBuilder()
|
||||||
|
.setLabel('Open a ticket')
|
||||||
|
.setEmoji('👉')
|
||||||
|
.setStyle(ButtonStyle.Success)
|
||||||
|
.setCustomId('create-btn')
|
||||||
|
|
||||||
|
const row =
|
||||||
|
new ActionRowBuilder<MessageActionRowComponentBuilder>().addComponents(
|
||||||
|
createBtn,
|
||||||
|
)
|
||||||
|
|
||||||
|
let embedCreate = new EmbedBuilder()
|
||||||
|
.setTitle(`Create a ticket`)
|
||||||
|
.setDescription(
|
||||||
|
`Hey, want to order a design?
|
||||||
|
Then open a ticket and we'll answer it in a jiffy!
|
||||||
|
Dear customer, before opening a ticket\n
|
||||||
|
I strongly recommend that you familiarize yourself with the prices of basic interfaces - ` +
|
||||||
|
channelMention(pricesChannelId),
|
||||||
|
)
|
||||||
|
.setImage(bannerURL)
|
||||||
|
|
||||||
|
await interaction.channel?.send({
|
||||||
|
components: [row],
|
||||||
|
embeds: [embedCreate],
|
||||||
|
})
|
||||||
|
|
||||||
|
// workload embed
|
||||||
|
let embedStatus = new EmbedBuilder()
|
||||||
|
.setTitle(`Workload status by orders`)
|
||||||
|
.setDescription('**Status:**\n' + getStatusMessage(workload))
|
||||||
|
|
||||||
|
const workloadMessage = await interaction.channel?.send({
|
||||||
|
embeds: [embedStatus],
|
||||||
|
})
|
||||||
|
|
||||||
|
await db.set(DBTableEnum.WORKLOAD_MESSAGE, workloadMessage?.id)
|
||||||
|
|
||||||
|
await interaction.reply({
|
||||||
|
content: 'Created ticket system',
|
||||||
|
ephemeral: true,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// listen to button
|
||||||
|
@ButtonComponent({ id: 'create-btn' })
|
||||||
|
async createBtn(interaction: ButtonInteraction): Promise<void> {
|
||||||
|
if (
|
||||||
|
!(interaction.member instanceof GuildMember) ||
|
||||||
|
interaction.channel?.type !== ChannelType.GuildText
|
||||||
|
) {
|
||||||
|
await interaction.reply('failed')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const threadChannel = await interaction.channel.threads.create({
|
||||||
|
name: `${interaction.user.username}`,
|
||||||
|
type: ChannelType.PrivateThread,
|
||||||
|
invitable: false,
|
||||||
|
})
|
||||||
|
|
||||||
|
let createdEmbed = new EmbedBuilder()
|
||||||
|
.setTitle(`${interaction.user.username} opened a ticket`)
|
||||||
|
.setDescription(
|
||||||
|
`You successfully opened a ticket. Your ticket: ${channelMention(threadChannel.id)}`,
|
||||||
|
)
|
||||||
|
|
||||||
|
await interaction.reply({ embeds: [createdEmbed], ephemeral: true })
|
||||||
|
|
||||||
|
let threadEmbed = new EmbedBuilder()
|
||||||
|
.setTitle(`${interaction.user.username} opened a ticket`)
|
||||||
|
.setDescription(
|
||||||
|
`You successfully opened a ticket. We will be with you soon`,
|
||||||
|
)
|
||||||
|
.setFooter({
|
||||||
|
text: 'You can close ticket by clicking the button below',
|
||||||
|
})
|
||||||
|
|
||||||
|
const ticketRole = await db.get(DBTableEnum.TICKET_ROLE)
|
||||||
|
|
||||||
|
const closeBtn = new ButtonBuilder()
|
||||||
|
.setLabel('Close ticket')
|
||||||
|
.setStyle(ButtonStyle.Danger)
|
||||||
|
.setCustomId('close-btn')
|
||||||
|
|
||||||
|
const row =
|
||||||
|
new ActionRowBuilder<MessageActionRowComponentBuilder>().addComponents(
|
||||||
|
closeBtn,
|
||||||
|
)
|
||||||
|
|
||||||
|
await threadChannel.send({
|
||||||
|
content: `${userMention(interaction.user.id)} ${roleMention(ticketRole)}`,
|
||||||
|
embeds: [threadEmbed],
|
||||||
|
components: [row],
|
||||||
|
})
|
||||||
|
|
||||||
|
const user = await interaction.guild?.members.fetch(interaction.user.id)
|
||||||
|
const role = await interaction.guild?.roles.fetch(ticketRole)
|
||||||
|
|
||||||
|
role?.members.map(
|
||||||
|
async members => await threadChannel.members.add(members),
|
||||||
|
)
|
||||||
|
|
||||||
|
if (!user) return
|
||||||
|
|
||||||
|
await threadChannel.members.add(user)
|
||||||
|
}
|
||||||
|
|
||||||
|
@ButtonComponent({ id: 'close-btn' })
|
||||||
|
async closeBtn(interaction: ButtonInteraction): Promise<void> {
|
||||||
|
console.log('close button')
|
||||||
|
await interaction.channel?.delete()
|
||||||
|
|
||||||
|
await interaction.reply('Deleted')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function getStatusMessage(status: Status | null) {
|
||||||
|
if (!status) return 'No information provided'
|
||||||
|
switch (status) {
|
||||||
|
case Status.AVAILABLE:
|
||||||
|
return ':green_circle: - Available for orders'
|
||||||
|
case Status.BUSY:
|
||||||
|
return ':yellow_circle: - Available for orders, but there may be delays'
|
||||||
|
case Status.NOT_AVAILABLE:
|
||||||
|
return ':red_circle: - Currently unavailable for orders'
|
||||||
|
default:
|
||||||
|
return 'No information provided'
|
||||||
|
}
|
||||||
|
}
|
@ -4,7 +4,7 @@ import {
|
|||||||
CommandInteraction,
|
CommandInteraction,
|
||||||
TextChannel,
|
TextChannel,
|
||||||
} from 'discord.js'
|
} from 'discord.js'
|
||||||
import { db, DBTableEnum } from '../../db.ts'
|
import { db, DBTableEnum } from '../../db'
|
||||||
|
|
||||||
@Discord()
|
@Discord()
|
||||||
export class SetFeedbackChannel {
|
export class SetFeedbackChannel {
|
@ -4,7 +4,7 @@ import {
|
|||||||
CommandInteraction,
|
CommandInteraction,
|
||||||
TextChannel,
|
TextChannel,
|
||||||
} from 'discord.js'
|
} from 'discord.js'
|
||||||
import { db, DBTableEnum } from '../../db.ts'
|
import { db, DBTableEnum } from '../../db'
|
||||||
|
|
||||||
@Discord()
|
@Discord()
|
||||||
export class SetFeedbackChannel {
|
export class SetFeedbackChannel {
|
@ -4,7 +4,7 @@ import {
|
|||||||
CommandInteraction,
|
CommandInteraction,
|
||||||
TextChannel,
|
TextChannel,
|
||||||
} from 'discord.js'
|
} from 'discord.js'
|
||||||
import { db, DBTableEnum } from '../../db.ts'
|
import { db, DBTableEnum } from '../../db'
|
||||||
|
|
||||||
@Discord()
|
@Discord()
|
||||||
export class SetOrderChannel {
|
export class SetOrderChannel {
|
@ -4,7 +4,7 @@ import {
|
|||||||
CommandInteraction,
|
CommandInteraction,
|
||||||
TextChannel,
|
TextChannel,
|
||||||
} from 'discord.js'
|
} from 'discord.js'
|
||||||
import { db, DBTableEnum } from '../../db.ts'
|
import { db, DBTableEnum } from '../../db'
|
||||||
|
|
||||||
@Discord()
|
@Discord()
|
||||||
export class SetPortfolioChannel {
|
export class SetPortfolioChannel {
|
@ -4,7 +4,7 @@ import {
|
|||||||
CommandInteraction,
|
CommandInteraction,
|
||||||
TextChannel,
|
TextChannel,
|
||||||
} from 'discord.js'
|
} from 'discord.js'
|
||||||
import { db, DBTableEnum } from '../../db.ts'
|
import { db, DBTableEnum } from '../../db'
|
||||||
|
|
||||||
@Discord()
|
@Discord()
|
||||||
export class SetPriceChannel {
|
export class SetPriceChannel {
|
@ -1,12 +1,7 @@
|
|||||||
import { Discord, Slash, SlashChoice, SlashOption } from 'discordx'
|
import { Discord, Slash, SlashChoice, SlashOption } from 'discordx'
|
||||||
import { ApplicationCommandOptionType, CommandInteraction } from 'discord.js'
|
import { ApplicationCommandOptionType, CommandInteraction } from 'discord.js'
|
||||||
import { db, DBTableEnum } from '../../db.js'
|
import { db, DBTableEnum } from '../../db'
|
||||||
|
import { Status } from '../../utils/enums.ts'
|
||||||
enum Status {
|
|
||||||
AVAILABLE = 'AVAILABLE',
|
|
||||||
BUSY = 'BUSY',
|
|
||||||
NOT_AVAILABLE = 'NOT_AVAILABLE',
|
|
||||||
}
|
|
||||||
|
|
||||||
@Discord()
|
@Discord()
|
||||||
export class SetStatus {
|
export class SetStatus {
|
@ -5,7 +5,7 @@ import {
|
|||||||
Role,
|
Role,
|
||||||
TextChannel,
|
TextChannel,
|
||||||
} from 'discord.js'
|
} from 'discord.js'
|
||||||
import { db, DBTableEnum } from '../../db.ts'
|
import { db, DBTableEnum } from '../../db'
|
||||||
|
|
||||||
@Discord()
|
@Discord()
|
||||||
export class SetWelcomeChannel {
|
export class SetWelcomeChannel {
|
@ -4,7 +4,7 @@ import {
|
|||||||
CommandInteraction,
|
CommandInteraction,
|
||||||
EmbedBuilder,
|
EmbedBuilder,
|
||||||
} from 'discord.js'
|
} from 'discord.js'
|
||||||
import { db, DBTableEnum } from '../db.ts'
|
import { db, DBTableEnum } from '../db'
|
||||||
|
|
||||||
@Discord()
|
@Discord()
|
||||||
export class Feedback {
|
export class Feedback {
|
||||||
|
@ -4,11 +4,12 @@ export const db = new QuickDB()
|
|||||||
export enum DBTableEnum {
|
export enum DBTableEnum {
|
||||||
WELCOME_CHANNEL = 'WELCOME_CHANNEL',
|
WELCOME_CHANNEL = 'WELCOME_CHANNEL',
|
||||||
WELCOME_ROLE = 'WELCOME_ROLE',
|
WELCOME_ROLE = 'WELCOME_ROLE',
|
||||||
TICKET_CHANNEL = 'TICKET_CHANNEL',
|
|
||||||
FEEDBACK_CHANNEL = 'FEEDBACK_CHANNEL',
|
FEEDBACK_CHANNEL = 'FEEDBACK_CHANNEL',
|
||||||
PORTFOLIO_CHANNEL = 'PORTFOLIO_CHANNEL',
|
PORTFOLIO_CHANNEL = 'PORTFOLIO_CHANNEL',
|
||||||
MAKE_AN_ORDER_CHANNEL = 'MAKE_AN_ORDER_CHANNEL',
|
MAKE_AN_ORDER_CHANNEL = 'MAKE_AN_ORDER_CHANNEL',
|
||||||
PRICE_CHANNEL = 'PRICE_CHANNEL',
|
PRICE_CHANNEL = 'PRICE_CHANNEL',
|
||||||
BANNER_URL = 'BANNER_URL',
|
BANNER_URL = 'BANNER_URL',
|
||||||
WORKLOAD = 'STATUS',
|
WORKLOAD = 'WORKLOAD',
|
||||||
|
WORKLOAD_MESSAGE = 'WORKLOAD_MESSAGE',
|
||||||
|
TICKET_ROLE = 'TICKET_ROLE',
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { ArgsOf, Discord, On } from 'discordx'
|
import { ArgsOf, Discord, On } from 'discordx'
|
||||||
import { EmbedBuilder, channelMention, userMention } from 'discord.js'
|
import { EmbedBuilder, channelMention, userMention } from 'discord.js'
|
||||||
import { db, DBTableEnum } from '../db.ts'
|
import { db, DBTableEnum } from '../db'
|
||||||
|
|
||||||
@Discord()
|
@Discord()
|
||||||
export class GuildMemberAdd {
|
export class GuildMemberAdd {
|
||||||
|
@ -41,7 +41,7 @@ bot.on('messageCreate', async (message: Message) => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
async function run() {
|
async function run() {
|
||||||
await importx(`${dirname(import.meta.url)}/{events,commands}/**/*.{ts,js}`)
|
await importx(`${dirname(import.meta.url)}/{events,commands}/**/*.{ts,mjs}`)
|
||||||
|
|
||||||
if (!process.env.BOT_TOKEN) {
|
if (!process.env.BOT_TOKEN) {
|
||||||
throw Error('Could not find BOT_TOKEN in your environment')
|
throw Error('Could not find BOT_TOKEN in your environment')
|
5
src/utils/enums.ts
Normal file
5
src/utils/enums.ts
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
export enum Status {
|
||||||
|
AVAILABLE = 'AVAILABLE',
|
||||||
|
BUSY = 'BUSY',
|
||||||
|
NOT_AVAILABLE = 'NOT_AVAILABLE',
|
||||||
|
}
|
35
tsup.config.ts
Normal file
35
tsup.config.ts
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
import { esbuildPluginFilePathExtensions } from 'esbuild-plugin-file-path-extensions'
|
||||||
|
import { esbuildPluginVersionInjector } from 'esbuild-plugin-version-injector'
|
||||||
|
import { defineConfig, type Options } from 'tsup'
|
||||||
|
|
||||||
|
const baseOptions: Options = {
|
||||||
|
clean: true,
|
||||||
|
entry: ['src/**/*.ts'],
|
||||||
|
dts: false,
|
||||||
|
minify: true,
|
||||||
|
skipNodeModulesBundle: true,
|
||||||
|
sourcemap: false,
|
||||||
|
target: 'es2021',
|
||||||
|
tsconfig: 'tsconfig.json',
|
||||||
|
keepNames: true,
|
||||||
|
esbuildPlugins: [
|
||||||
|
esbuildPluginVersionInjector(),
|
||||||
|
esbuildPluginFilePathExtensions(),
|
||||||
|
],
|
||||||
|
treeshake: true,
|
||||||
|
}
|
||||||
|
|
||||||
|
export default [
|
||||||
|
// defineConfig({
|
||||||
|
// ...baseOptions,
|
||||||
|
// outDir: 'dist/cjs',
|
||||||
|
// format: 'cjs',
|
||||||
|
// outExtension: () => ({ js: '.cjs' }),
|
||||||
|
// }),
|
||||||
|
defineConfig({
|
||||||
|
...baseOptions,
|
||||||
|
outDir: 'build',
|
||||||
|
format: 'esm',
|
||||||
|
outExtension: () => ({ js: '.mjs' }),
|
||||||
|
}),
|
||||||
|
]
|
Loading…
Reference in New Issue
Block a user