changes:
- prisma migration - better ticket handling - better error handling
This commit is contained in:
parent
ef1c5be2b7
commit
fd558bd975
Binary file not shown.
@ -1,21 +1,21 @@
|
|||||||
-- CreateTable
|
-- CreateTable
|
||||||
CREATE TABLE "Settings" (
|
CREATE TABLE "Settings" (
|
||||||
"id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
|
"id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
|
||||||
"welcomeChannelId" INTEGER NOT NULL,
|
"welcomeChannelId" TEXT NOT NULL,
|
||||||
"feedbackChannelId" INTEGER NOT NULL,
|
"feedbackChannelId" TEXT NOT NULL,
|
||||||
"portfolioChannelId" INTEGER NOT NULL,
|
"portfolioChannelId" TEXT NOT NULL,
|
||||||
"makeAnOrderChannelId" INTEGER NOT NULL,
|
"makeAnOrderChannelId" TEXT NOT NULL,
|
||||||
"priceChannelId" INTEGER NOT NULL,
|
"priceChannelId" TEXT NOT NULL,
|
||||||
"workLoadChannelId" INTEGER NOT NULL,
|
"workLoadChannelId" TEXT NOT NULL,
|
||||||
"worlLoadStatus" INTEGER NOT NULL,
|
"worlLoadStatus" TEXT NOT NULL,
|
||||||
"workloadMessageId" INTEGER NOT NULL
|
"workloadMessageId" TEXT NOT NULL
|
||||||
);
|
);
|
||||||
|
|
||||||
-- CreateTable
|
-- CreateTable
|
||||||
CREATE TABLE "Role" (
|
CREATE TABLE "Role" (
|
||||||
"id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
|
"id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
|
||||||
"welcomeRoleId" INTEGER NOT NULL,
|
"welcomeRoleId" TEXT NOT NULL,
|
||||||
"tickerRoleId" INTEGER NOT NULL
|
"tickerRoleId" TEXT NOT NULL
|
||||||
);
|
);
|
||||||
|
|
||||||
-- CreateTable
|
-- CreateTable
|
||||||
@ -28,13 +28,13 @@ CREATE TABLE "Banner" (
|
|||||||
-- CreateTable
|
-- CreateTable
|
||||||
CREATE TABLE "User" (
|
CREATE TABLE "User" (
|
||||||
"id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
|
"id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
|
||||||
"discordId" INTEGER NOT NULL
|
"discordId" TEXT NOT NULL
|
||||||
);
|
);
|
||||||
|
|
||||||
-- CreateTable
|
-- CreateTable
|
||||||
CREATE TABLE "Ticket" (
|
CREATE TABLE "Ticket" (
|
||||||
"id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
|
"id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
|
||||||
"channelId" INTEGER NOT NULL,
|
"channelId" TEXT NOT NULL,
|
||||||
"closed" BOOLEAN NOT NULL,
|
"closed" BOOLEAN NOT NULL,
|
||||||
"userId" INTEGER,
|
"userId" INTEGER,
|
||||||
CONSTRAINT "Ticket_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User" ("id") ON DELETE SET NULL ON UPDATE CASCADE
|
CONSTRAINT "Ticket_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User" ("id") ON DELETE SET NULL ON UPDATE CASCADE
|
58
prisma/migrations/20240805230451_fixes/migration.sql
Normal file
58
prisma/migrations/20240805230451_fixes/migration.sql
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
/*
|
||||||
|
Warnings:
|
||||||
|
|
||||||
|
- You are about to drop the column `tickerRoleId` on the `Role` table. All the data in the column will be lost.
|
||||||
|
- You are about to drop the column `worlLoadStatus` on the `Settings` table. All the data in the column will be lost.
|
||||||
|
- The primary key for the `Ticket` table will be changed. If it partially fails, the table could be left without primary key constraint.
|
||||||
|
- You are about to drop the column `id` on the `Ticket` table. All the data in the column will be lost.
|
||||||
|
- The primary key for the `User` table will be changed. If it partially fails, the table could be left without primary key constraint.
|
||||||
|
- You are about to drop the column `id` on the `User` table. All the data in the column will be lost.
|
||||||
|
- Added the required column `ticketRoleId` to the `Role` table without a default value. This is not possible if the table is not empty.
|
||||||
|
- Added the required column `workLoadStatus` to the `Settings` table without a default value. This is not possible if the table is not empty.
|
||||||
|
- Made the column `userId` on table `Ticket` required. This step will fail if there are existing NULL values in that column.
|
||||||
|
|
||||||
|
*/
|
||||||
|
-- RedefineTables
|
||||||
|
PRAGMA defer_foreign_keys=ON;
|
||||||
|
PRAGMA foreign_keys=OFF;
|
||||||
|
CREATE TABLE "new_Role" (
|
||||||
|
"id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
|
||||||
|
"welcomeRoleId" TEXT NOT NULL,
|
||||||
|
"ticketRoleId" TEXT NOT NULL
|
||||||
|
);
|
||||||
|
INSERT INTO "new_Role" ("id", "welcomeRoleId") SELECT "id", "welcomeRoleId" FROM "Role";
|
||||||
|
DROP TABLE "Role";
|
||||||
|
ALTER TABLE "new_Role" RENAME TO "Role";
|
||||||
|
CREATE TABLE "new_Settings" (
|
||||||
|
"id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
|
||||||
|
"welcomeChannelId" TEXT NOT NULL,
|
||||||
|
"feedbackChannelId" TEXT NOT NULL,
|
||||||
|
"portfolioChannelId" TEXT NOT NULL,
|
||||||
|
"makeAnOrderChannelId" TEXT NOT NULL,
|
||||||
|
"priceChannelId" TEXT NOT NULL,
|
||||||
|
"workLoadChannelId" TEXT NOT NULL,
|
||||||
|
"workLoadStatus" TEXT NOT NULL,
|
||||||
|
"workloadMessageId" TEXT NOT NULL
|
||||||
|
);
|
||||||
|
INSERT INTO "new_Settings" ("feedbackChannelId", "id", "makeAnOrderChannelId", "portfolioChannelId", "priceChannelId", "welcomeChannelId", "workLoadChannelId", "workloadMessageId") SELECT "feedbackChannelId", "id", "makeAnOrderChannelId", "portfolioChannelId", "priceChannelId", "welcomeChannelId", "workLoadChannelId", "workloadMessageId" FROM "Settings";
|
||||||
|
DROP TABLE "Settings";
|
||||||
|
ALTER TABLE "new_Settings" RENAME TO "Settings";
|
||||||
|
CREATE TABLE "new_Ticket" (
|
||||||
|
"channelId" TEXT NOT NULL,
|
||||||
|
"closed" BOOLEAN NOT NULL,
|
||||||
|
"userId" TEXT NOT NULL,
|
||||||
|
CONSTRAINT "Ticket_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User" ("discordId") ON DELETE RESTRICT ON UPDATE CASCADE
|
||||||
|
);
|
||||||
|
INSERT INTO "new_Ticket" ("channelId", "closed", "userId") SELECT "channelId", "closed", "userId" FROM "Ticket";
|
||||||
|
DROP TABLE "Ticket";
|
||||||
|
ALTER TABLE "new_Ticket" RENAME TO "Ticket";
|
||||||
|
CREATE UNIQUE INDEX "Ticket_channelId_key" ON "Ticket"("channelId");
|
||||||
|
CREATE TABLE "new_User" (
|
||||||
|
"discordId" TEXT NOT NULL
|
||||||
|
);
|
||||||
|
INSERT INTO "new_User" ("discordId") SELECT "discordId" FROM "User";
|
||||||
|
DROP TABLE "User";
|
||||||
|
ALTER TABLE "new_User" RENAME TO "User";
|
||||||
|
CREATE UNIQUE INDEX "User_discordId_key" ON "User"("discordId");
|
||||||
|
PRAGMA foreign_keys=ON;
|
||||||
|
PRAGMA defer_foreign_keys=OFF;
|
@ -9,20 +9,20 @@ datasource db {
|
|||||||
|
|
||||||
model Settings {
|
model Settings {
|
||||||
id Int @id @default(autoincrement())
|
id Int @id @default(autoincrement())
|
||||||
welcomeChannelId Int
|
welcomeChannelId String
|
||||||
feedbackChannelId Int
|
feedbackChannelId String
|
||||||
portfolioChannelId Int
|
portfolioChannelId String
|
||||||
makeAnOrderChannelId Int
|
makeAnOrderChannelId String
|
||||||
priceChannelId Int
|
priceChannelId String
|
||||||
workLoadChannelId Int
|
workLoadChannelId String
|
||||||
worlLoadStatus Int
|
workLoadStatus String
|
||||||
workloadMessageId Int
|
workloadMessageId String
|
||||||
}
|
}
|
||||||
|
|
||||||
model Role {
|
model Role {
|
||||||
id Int @id @default(autoincrement())
|
id Int @id @default(autoincrement())
|
||||||
welcomeRoleId Int
|
welcomeRoleId String
|
||||||
tickerRoleId Int
|
ticketRoleId String
|
||||||
}
|
}
|
||||||
|
|
||||||
model Banner {
|
model Banner {
|
||||||
@ -32,15 +32,13 @@ model Banner {
|
|||||||
}
|
}
|
||||||
|
|
||||||
model User {
|
model User {
|
||||||
id Int @id @default(autoincrement())
|
discordId String @unique
|
||||||
discordId Int
|
|
||||||
tickets Ticket[]
|
tickets Ticket[]
|
||||||
}
|
}
|
||||||
|
|
||||||
model Ticket {
|
model Ticket {
|
||||||
id Int @id
|
channelId String @unique
|
||||||
channelId Int
|
|
||||||
closed Boolean
|
closed Boolean
|
||||||
User User? @relation(fields: [userId], references: [id])
|
User User @relation(fields: [userId], references: [discordId])
|
||||||
userId Int?
|
userId String
|
||||||
}
|
}
|
||||||
|
@ -14,7 +14,7 @@ import {
|
|||||||
userMention,
|
userMention,
|
||||||
} from 'discord.js'
|
} from 'discord.js'
|
||||||
|
|
||||||
import { db, DBTableEnum } from '../../db'
|
import * as db from '../../db'
|
||||||
import {
|
import {
|
||||||
Workload,
|
Workload,
|
||||||
ticketCreateButton,
|
ticketCreateButton,
|
||||||
@ -26,8 +26,6 @@ import {
|
|||||||
} from '../../utils'
|
} from '../../utils'
|
||||||
import { logger } from '../../lib'
|
import { logger } from '../../lib'
|
||||||
|
|
||||||
type Ticket = { user: string; channel: string }
|
|
||||||
|
|
||||||
@Discord()
|
@Discord()
|
||||||
export class CreateTicketSystem {
|
export class CreateTicketSystem {
|
||||||
@Slash({
|
@Slash({
|
||||||
@ -55,11 +53,10 @@ export class CreateTicketSystem {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
const pricesChannelId = await db.get(DBTableEnum.PRICE_CHANNEL)
|
const settings = await db.getSettings()
|
||||||
const bannerURL = await db.get(DBTableEnum.BANNER_TICKET)
|
const banners = await db.getBanner()
|
||||||
const workload = await db.get<Workload>(DBTableEnum.WORKLOAD)
|
|
||||||
|
|
||||||
if (!pricesChannelId) {
|
if (!settings || !settings.priceChannelId) {
|
||||||
logger.error(
|
logger.error(
|
||||||
'Missing prices channel',
|
'Missing prices channel',
|
||||||
'Set using /set-prices-channel',
|
'Set using /set-prices-channel',
|
||||||
@ -69,14 +66,14 @@ export class CreateTicketSystem {
|
|||||||
)
|
)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if (!bannerURL) {
|
if (!banners || !banners.ticketUrl) {
|
||||||
logger.error('Missing banner', 'Set using /set-banner-ticket')
|
logger.error('Missing banner', 'Set using /set-banner-ticket')
|
||||||
await interaction.editReply(
|
await interaction.editReply(
|
||||||
'❌ Missing banner\nSet using /set-banner-ticket',
|
'❌ Missing banner\nSet using /set-banner-ticket',
|
||||||
)
|
)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if (!workload) {
|
if (!settings.workLoadStatus) {
|
||||||
logger.error(
|
logger.error(
|
||||||
'Missing workload status',
|
'Missing workload status',
|
||||||
'Set using /set-workload-status',
|
'Set using /set-workload-status',
|
||||||
@ -88,21 +85,35 @@ export class CreateTicketSystem {
|
|||||||
}
|
}
|
||||||
|
|
||||||
await db
|
await db
|
||||||
.set(DBTableEnum.TICKET_ROLE, role.id)
|
.setRole('ticketRoleId', role.id)
|
||||||
.then(() => logger.database(DBTableEnum.TICKET_ROLE, role.id))
|
.then(() => logger.database('Ticket role', role.id))
|
||||||
|
.catch(async () => {
|
||||||
|
logger.error('Ticket role id', 'Failed to set ticket role id')
|
||||||
|
await interaction.editReply('❌ Failed to set ticket role id')
|
||||||
|
return
|
||||||
|
})
|
||||||
|
|
||||||
// create ticket embed + button
|
// create ticket embed + button
|
||||||
await interaction.channel.send({
|
await interaction.channel.send({
|
||||||
components: [ticketCreateButton()],
|
components: [ticketCreateButton()],
|
||||||
embeds: [ticketCreateEmbed({ bannerURL, pricesChannelId })],
|
embeds: [
|
||||||
|
ticketCreateEmbed({
|
||||||
|
bannerURL: banners.ticketUrl,
|
||||||
|
pricesChannelId: settings.priceChannelId,
|
||||||
|
}),
|
||||||
|
],
|
||||||
})
|
})
|
||||||
|
|
||||||
// workload embed
|
// workload embed
|
||||||
const workloadMessage = await interaction.channel.send({
|
const workloadMessage = await interaction.channel.send({
|
||||||
embeds: [ticketWorkloadEmbed({ workload })],
|
embeds: [
|
||||||
|
ticketWorkloadEmbed({
|
||||||
|
workload: settings.workLoadStatus as Workload,
|
||||||
|
}),
|
||||||
|
],
|
||||||
})
|
})
|
||||||
await db.set(DBTableEnum.WORKLOAD_MESSAGE, workloadMessage.id)
|
await db.setSettings('workloadMessageId', workloadMessage.id)
|
||||||
await db.set(DBTableEnum.WORKLOAD_CHANNEL, interaction.channel.id)
|
await db.setSettings('workLoadChannelId', interaction.channel.id)
|
||||||
|
|
||||||
// close interaction
|
// close interaction
|
||||||
await interaction.editReply('✔️ Created ticket system')
|
await interaction.editReply('✔️ Created ticket system')
|
||||||
@ -127,19 +138,16 @@ export class CreateTicketSystem {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
const hasOpenedTicket = await db
|
const hasManyTickets =
|
||||||
.get<Ticket[]>(DBTableEnum.TICKET_OWNERS)
|
(await db.getUserOpenedTicketsAmount(interaction.user.id)) > 3
|
||||||
.then(r =>
|
if (hasManyTickets) {
|
||||||
Array.isArray(r)
|
await interaction.editReply(`❌ You already have 3 opened tickets`)
|
||||||
? !!r.find(ticket => ticket.user === interaction.user.id)
|
|
||||||
: false,
|
|
||||||
)
|
|
||||||
if (hasOpenedTicket) {
|
|
||||||
await interaction.editReply(`❌ You already have an active ticket`)
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
const ticketRole = await db.get(DBTableEnum.TICKET_ROLE)
|
const roles = await db.getRole()
|
||||||
|
|
||||||
|
const ticketRole = roles?.ticketRoleId
|
||||||
let threadChannel: ThreadChannel<boolean>
|
let threadChannel: ThreadChannel<boolean>
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@ -159,9 +167,9 @@ export class CreateTicketSystem {
|
|||||||
}
|
}
|
||||||
|
|
||||||
await db
|
await db
|
||||||
.push<Ticket>(DBTableEnum.TICKET_OWNERS, {
|
.createUser(interaction.user.id, {
|
||||||
user: interaction.user.id,
|
closed: false,
|
||||||
channel: threadChannel.id,
|
channelId: threadChannel.id,
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
logger.database(
|
logger.database(
|
||||||
@ -169,14 +177,10 @@ export class CreateTicketSystem {
|
|||||||
`Added User: ${interaction.user.id}\n Channel: ${threadChannel.id}`,
|
`Added User: ${interaction.user.id}\n Channel: ${threadChannel.id}`,
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
logger.database(
|
|
||||||
'Updated active tickets',
|
|
||||||
`Removed channel ${interaction.channel.id}`,
|
|
||||||
)
|
|
||||||
|
|
||||||
// welcoming message in ticket
|
// welcoming message in ticket
|
||||||
const threadChannelMessage: MessageCreateOptions = {
|
const threadChannelMessage: MessageCreateOptions = {
|
||||||
content: `${userMention(interaction.user.id)} ${roleMention(ticketRole)}`,
|
content: `${userMention(interaction.user.id)} ${roleMention(ticketRole!)}`,
|
||||||
embeds: [
|
embeds: [
|
||||||
ticketEntityEmbed({
|
ticketEntityEmbed({
|
||||||
username: interaction.user.username,
|
username: interaction.user.username,
|
||||||
@ -188,7 +192,7 @@ export class CreateTicketSystem {
|
|||||||
|
|
||||||
// add role members and ticket owner
|
// add role members and ticket owner
|
||||||
const user = await interaction.guild.members.fetch(interaction.user.id)
|
const user = await interaction.guild.members.fetch(interaction.user.id)
|
||||||
const role = await interaction.guild.roles.fetch(ticketRole)
|
const role = await interaction.guild.roles.fetch(ticketRole!)
|
||||||
const owner = await interaction.guild.fetchOwner()
|
const owner = await interaction.guild.fetchOwner()
|
||||||
|
|
||||||
if (!role) {
|
if (!role) {
|
||||||
@ -259,24 +263,12 @@ export class CreateTicketSystem {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
const tickets = await db.get<Ticket[]>(DBTableEnum.TICKET_OWNERS)
|
await db.closeTicket(interaction.channel.id).then(() => {
|
||||||
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(
|
logger.database(
|
||||||
'Updated active tickets',
|
'Updated active tickets',
|
||||||
`Removed channel ${interaction.channel?.id}`,
|
`Removed channel ${interaction.channel?.id}`,
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
}
|
|
||||||
|
|
||||||
logger.action(
|
logger.action(
|
||||||
'Ticket close attempt successful',
|
'Ticket close attempt successful',
|
||||||
|
@ -17,7 +17,7 @@ export class Help {
|
|||||||
value: '```/feedback\n' + '/payments```',
|
value: '```/feedback\n' + '/payments```',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'Setters',
|
name: 'Setters (preferably in order)',
|
||||||
value:
|
value:
|
||||||
'```/set-banner-ticket\n' +
|
'```/set-banner-ticket\n' +
|
||||||
'/set-banner-welcome\n' +
|
'/set-banner-welcome\n' +
|
||||||
@ -31,11 +31,11 @@ export class Help {
|
|||||||
{
|
{
|
||||||
name: 'Admin',
|
name: 'Admin',
|
||||||
value:
|
value:
|
||||||
'```/ping - потому что могу\n\n' +
|
'```/ping\n\n' +
|
||||||
'/help - без понятия\n\n' +
|
'/help\n\n' +
|
||||||
'/create-ticket-system - Создать систему тикетов отталкиваясь от текущего канала.\n' +
|
'/create-ticket-system - Create ticket system based on channel where the command is executed.\n' +
|
||||||
'Требует /set-banner-ticket /set-prices-channel /set-status\n\n' +
|
'Requires /set-banner-ticket /set-prices-channel /set-status\n\n' +
|
||||||
'/remove-active-ticket - удалить из базы все активные тикеты пользователя если что-то произошло и они не удалились при архивации тикета```',
|
'/remove-active-ticket - forces closing of all user tickets in case of errors```',
|
||||||
},
|
},
|
||||||
])
|
])
|
||||||
|
|
||||||
|
@ -5,19 +5,19 @@ import {
|
|||||||
User,
|
User,
|
||||||
} from 'discord.js'
|
} from 'discord.js'
|
||||||
|
|
||||||
import { db, DBTableEnum } from '../../db'
|
import {
|
||||||
|
getUser,
|
||||||
|
closeUserTickets,
|
||||||
|
createUserSilent,
|
||||||
|
getUserOpenedTicketsAmount,
|
||||||
|
} from '../../db'
|
||||||
import { logger } from '../../lib'
|
import { logger } from '../../lib'
|
||||||
|
|
||||||
type Ticket = {
|
|
||||||
user: string
|
|
||||||
channel: string
|
|
||||||
}
|
|
||||||
|
|
||||||
@Discord()
|
@Discord()
|
||||||
export class RemoveActiveTicket {
|
export class RemoveActiveTicket {
|
||||||
@Slash({
|
@Slash({
|
||||||
name: 'remove-active-ticket',
|
name: 'remove-active-ticket',
|
||||||
description: 'Remove user from database in case of need',
|
description: 'Closes all user tickets manually if needed',
|
||||||
defaultMemberPermissions: 'Administrator',
|
defaultMemberPermissions: 'Administrator',
|
||||||
})
|
})
|
||||||
async removeActiveTicket(
|
async removeActiveTicket(
|
||||||
@ -32,27 +32,20 @@ export class RemoveActiveTicket {
|
|||||||
) {
|
) {
|
||||||
await interaction.deferReply({ ephemeral: true })
|
await interaction.deferReply({ ephemeral: true })
|
||||||
|
|
||||||
const activeTickets = await db.get<Ticket[]>(DBTableEnum.TICKET_OWNERS)
|
const userDB = await getUser(user.id)
|
||||||
if (!activeTickets || !activeTickets.length) {
|
if (!userDB || !(await getUserOpenedTicketsAmount(user.id))) {
|
||||||
await interaction.editReply('❌ No active tickets found for server')
|
await createUserSilent(user.id)
|
||||||
|
await interaction.editReply('❌ No active tickets found for user')
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
const res = activeTickets.reduce<Ticket[]>((r, ticket) => {
|
await closeUserTickets(user.id).then(() =>
|
||||||
if (ticket.user !== user.id) {
|
logger.action(
|
||||||
r.push(ticket)
|
'Changed user',
|
||||||
}
|
`Forced close all tickets for ${user.globalName}(${user.id})`,
|
||||||
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')
|
await interaction.editReply('✔️ User tickets closed successfully')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,11 @@
|
|||||||
import { Discord, Slash, SlashChoice, SlashOption } from 'discordx'
|
import { Discord, Slash, SlashChoice, SlashOption } from 'discordx'
|
||||||
import { ApplicationCommandOptionType, CommandInteraction } from 'discord.js'
|
import {
|
||||||
|
ApplicationCommandOptionType,
|
||||||
|
CommandInteraction,
|
||||||
|
SnowflakeUtil,
|
||||||
|
} from 'discord.js'
|
||||||
|
|
||||||
import { db, DBTableEnum } from '../db'
|
import { getSettings } from '../db'
|
||||||
import { logger } from '../lib'
|
import { logger } from '../lib'
|
||||||
import { feedbackEmbed } from '../utils'
|
import { feedbackEmbed } from '../utils'
|
||||||
|
|
||||||
@ -33,8 +37,8 @@ export class Feedback {
|
|||||||
|
|
||||||
if (!interaction.guild) return
|
if (!interaction.guild) return
|
||||||
|
|
||||||
const reviewChannelID = await db.get(DBTableEnum.FEEDBACK_CHANNEL)
|
const settings = await getSettings()
|
||||||
if (!reviewChannelID) {
|
if (!settings || !settings.feedbackChannelId) {
|
||||||
logger.error(
|
logger.error(
|
||||||
'Missing feedback channel in database',
|
'Missing feedback channel in database',
|
||||||
'Recreate using /set-feedback-channel',
|
'Recreate using /set-feedback-channel',
|
||||||
@ -42,14 +46,16 @@ export class Feedback {
|
|||||||
await interaction.editReply(
|
await interaction.editReply(
|
||||||
'❌ Feedback channel is not set. Please try again later',
|
'❌ Feedback channel is not set. Please try again later',
|
||||||
)
|
)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
const reviewChannel =
|
const reviewChannel = await interaction.guild.channels.fetch(
|
||||||
await interaction.guild.channels.fetch(reviewChannelID)
|
settings.feedbackChannelId,
|
||||||
|
)
|
||||||
if (!reviewChannel) {
|
if (!reviewChannel) {
|
||||||
logger.error(
|
logger.error(
|
||||||
'Missing feedback discord channel',
|
'Missing feedback discord channel',
|
||||||
`Feedback channel id exists in database (${reviewChannelID}) but is not found in channels list`,
|
`Feedback channel id exists in database (${settings.feedbackChannelId}) but is not found in channels list`,
|
||||||
)
|
)
|
||||||
await interaction.editReply(
|
await interaction.editReply(
|
||||||
'❌ Feedback channel is not set. Please try again later',
|
'❌ Feedback channel is not set. Please try again later',
|
||||||
@ -59,7 +65,7 @@ export class Feedback {
|
|||||||
if (!reviewChannel || !reviewChannel.isTextBased()) {
|
if (!reviewChannel || !reviewChannel.isTextBased()) {
|
||||||
logger.error(
|
logger.error(
|
||||||
'Missing feedback discord channel',
|
'Missing feedback discord channel',
|
||||||
`Feedback channel id exists in database (${reviewChannelID}) but is not a text channel or is not found in channels list`,
|
`Feedback channel id exists in database (${settings.feedbackChannelId}) but is not a text channel or is not found in channels list`,
|
||||||
)
|
)
|
||||||
await interaction.editReply(
|
await interaction.editReply(
|
||||||
'❌ Feedback channel is not set. Please try again later',
|
'❌ Feedback channel is not set. Please try again later',
|
||||||
@ -67,6 +73,8 @@ export class Feedback {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const nonce = SnowflakeUtil.generate().toString()
|
||||||
|
|
||||||
await reviewChannel.send({
|
await reviewChannel.send({
|
||||||
embeds: [
|
embeds: [
|
||||||
feedbackEmbed({
|
feedbackEmbed({
|
||||||
@ -75,6 +83,7 @@ export class Feedback {
|
|||||||
rating,
|
rating,
|
||||||
}),
|
}),
|
||||||
],
|
],
|
||||||
|
nonce,
|
||||||
})
|
})
|
||||||
|
|
||||||
await interaction.editReply('✔️ Review sent successfully!')
|
await interaction.editReply('✔️ Review sent successfully!')
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { Discord, Slash, SlashOption } from 'discordx'
|
import { Discord, Slash, SlashOption } from 'discordx'
|
||||||
import { ApplicationCommandOptionType, CommandInteraction } from 'discord.js'
|
import { ApplicationCommandOptionType, CommandInteraction } from 'discord.js'
|
||||||
|
|
||||||
import { db, DBTableEnum } from '../../db'
|
import { setBanner } from '../../db'
|
||||||
import { logger } from '../../lib'
|
import { logger } from '../../lib'
|
||||||
|
|
||||||
@Discord()
|
@Discord()
|
||||||
@ -22,13 +22,16 @@ export class SetBannerTicket {
|
|||||||
interaction: CommandInteraction,
|
interaction: CommandInteraction,
|
||||||
) {
|
) {
|
||||||
await interaction.deferReply({ ephemeral: true })
|
await interaction.deferReply({ ephemeral: true })
|
||||||
await db.set(DBTableEnum.BANNER_TICKET, url).catch(async () => {
|
|
||||||
|
await setBanner('ticketUrl', url)
|
||||||
|
.then(() => logger.database('Banner Ticket URL', url))
|
||||||
|
.catch(async () => {
|
||||||
await interaction.editReply({
|
await interaction.editReply({
|
||||||
content: `❌ Failed to set banner`,
|
content: `❌ Failed to set banner`,
|
||||||
})
|
})
|
||||||
return
|
return
|
||||||
})
|
})
|
||||||
logger.database(DBTableEnum.BANNER_TICKET, url)
|
|
||||||
await interaction.editReply({
|
await interaction.editReply({
|
||||||
content: `✔️ Set banner URL to ${url}`,
|
content: `✔️ Set banner URL to ${url}`,
|
||||||
})
|
})
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { Discord, Slash, SlashOption } from 'discordx'
|
import { Discord, Slash, SlashOption } from 'discordx'
|
||||||
import { ApplicationCommandOptionType, CommandInteraction } from 'discord.js'
|
import { ApplicationCommandOptionType, CommandInteraction } from 'discord.js'
|
||||||
|
|
||||||
import { db, DBTableEnum } from '../../db'
|
import { setBanner } from '../../db'
|
||||||
import { logger } from '../../lib'
|
import { logger } from '../../lib'
|
||||||
|
|
||||||
@Discord()
|
@Discord()
|
||||||
@ -22,13 +22,16 @@ export class SetBannerWelcome {
|
|||||||
interaction: CommandInteraction,
|
interaction: CommandInteraction,
|
||||||
) {
|
) {
|
||||||
await interaction.deferReply({ ephemeral: true })
|
await interaction.deferReply({ ephemeral: true })
|
||||||
await db.set(DBTableEnum.BANNER_WELCOME, url).catch(async () => {
|
|
||||||
|
await setBanner('welcomeUrl', url)
|
||||||
|
.then(() => logger.database('Welcome Ticket URL', url))
|
||||||
|
.catch(async () => {
|
||||||
await interaction.editReply({
|
await interaction.editReply({
|
||||||
content: `❌ Failed to set banner`,
|
content: `❌ Failed to set banner`,
|
||||||
})
|
})
|
||||||
return
|
return
|
||||||
})
|
})
|
||||||
logger.database(DBTableEnum.BANNER_WELCOME, url)
|
|
||||||
await interaction.editReply({
|
await interaction.editReply({
|
||||||
content: `✔️ Set banner URL to ${url}`,
|
content: `✔️ Set banner URL to ${url}`,
|
||||||
})
|
})
|
||||||
|
@ -5,7 +5,7 @@ import {
|
|||||||
TextChannel,
|
TextChannel,
|
||||||
} from 'discord.js'
|
} from 'discord.js'
|
||||||
|
|
||||||
import { db, DBTableEnum } from '../../db'
|
import { setSettings } from '../../db'
|
||||||
import { logger } from '../../lib'
|
import { logger } from '../../lib'
|
||||||
|
|
||||||
@Discord()
|
@Discord()
|
||||||
@ -26,15 +26,15 @@ export class SetFeedbackChannel {
|
|||||||
interaction: CommandInteraction,
|
interaction: CommandInteraction,
|
||||||
) {
|
) {
|
||||||
await interaction.deferReply({ ephemeral: true })
|
await interaction.deferReply({ ephemeral: true })
|
||||||
await db
|
|
||||||
.set(DBTableEnum.FEEDBACK_CHANNEL, channel.id)
|
await setSettings('feedbackChannelId', channel.id)
|
||||||
|
.then(() => logger.database('Feedback Channel', channel.id))
|
||||||
.catch(async () => {
|
.catch(async () => {
|
||||||
await interaction.editReply({
|
await interaction.editReply({
|
||||||
content: `❌ Failed to set feedback channel`,
|
content: `❌ Failed to set feedback channel`,
|
||||||
})
|
})
|
||||||
return
|
return
|
||||||
})
|
})
|
||||||
logger.database(DBTableEnum.FEEDBACK_CHANNEL, channel.id)
|
|
||||||
await interaction.editReply({
|
await interaction.editReply({
|
||||||
content: `✔️ Set feedback channel to ${channel.id}`,
|
content: `✔️ Set feedback channel to ${channel.id}`,
|
||||||
})
|
})
|
||||||
|
@ -5,7 +5,7 @@ import {
|
|||||||
TextChannel,
|
TextChannel,
|
||||||
} from 'discord.js'
|
} from 'discord.js'
|
||||||
|
|
||||||
import { db, DBTableEnum } from '../../db'
|
import { setSettings } from '../../db'
|
||||||
import { logger } from '../../lib'
|
import { logger } from '../../lib'
|
||||||
|
|
||||||
@Discord()
|
@Discord()
|
||||||
@ -26,15 +26,16 @@ export class SetOrderChannel {
|
|||||||
interaction: CommandInteraction,
|
interaction: CommandInteraction,
|
||||||
) {
|
) {
|
||||||
await interaction.deferReply({ ephemeral: true })
|
await interaction.deferReply({ ephemeral: true })
|
||||||
await db
|
|
||||||
.set(DBTableEnum.MAKE_AN_ORDER_CHANNEL, channel.id)
|
await setSettings('makeAnOrderChannelId', channel.id)
|
||||||
|
.then(() => logger.database('Order Channel', channel.id))
|
||||||
.catch(async () => {
|
.catch(async () => {
|
||||||
await interaction.editReply({
|
await interaction.editReply({
|
||||||
content: `❌ Failed to set make an order channel`,
|
content: `❌ Failed to set make an order channel`,
|
||||||
})
|
})
|
||||||
return
|
return
|
||||||
})
|
})
|
||||||
logger.database(DBTableEnum.MAKE_AN_ORDER_CHANNEL, channel.id)
|
|
||||||
await interaction.editReply({
|
await interaction.editReply({
|
||||||
content: `✔️ Set make an order channel to ${channel.id}`,
|
content: `✔️ Set make an order channel to ${channel.id}`,
|
||||||
})
|
})
|
||||||
|
@ -5,7 +5,7 @@ import {
|
|||||||
TextChannel,
|
TextChannel,
|
||||||
} from 'discord.js'
|
} from 'discord.js'
|
||||||
|
|
||||||
import { db, DBTableEnum } from '../../db'
|
import { setSettings } from '../../db'
|
||||||
import { logger } from '../../lib'
|
import { logger } from '../../lib'
|
||||||
|
|
||||||
@Discord()
|
@Discord()
|
||||||
@ -26,15 +26,16 @@ export class SetPortfolioChannel {
|
|||||||
interaction: CommandInteraction,
|
interaction: CommandInteraction,
|
||||||
) {
|
) {
|
||||||
await interaction.deferReply({ ephemeral: true })
|
await interaction.deferReply({ ephemeral: true })
|
||||||
await db
|
|
||||||
.set(DBTableEnum.PORTFOLIO_CHANNEL, channel.id)
|
await setSettings('portfolioChannelId', channel.id)
|
||||||
|
.then(() => logger.database('Portfolio Channel', channel.id))
|
||||||
.catch(async () => {
|
.catch(async () => {
|
||||||
await interaction.editReply({
|
await interaction.editReply({
|
||||||
content: `❌ Failed to set portfolio channel`,
|
content: `❌ Failed to set portfolio channel`,
|
||||||
})
|
})
|
||||||
return
|
return
|
||||||
})
|
})
|
||||||
logger.database(DBTableEnum.PORTFOLIO_CHANNEL, channel.id)
|
|
||||||
await interaction.editReply({
|
await interaction.editReply({
|
||||||
content: `✔️ Set portfolio channel to ${channel.id}`,
|
content: `✔️ Set portfolio channel to ${channel.id}`,
|
||||||
})
|
})
|
||||||
|
@ -5,7 +5,7 @@ import {
|
|||||||
TextChannel,
|
TextChannel,
|
||||||
} from 'discord.js'
|
} from 'discord.js'
|
||||||
|
|
||||||
import { db, DBTableEnum } from '../../db'
|
import { setSettings } from '../../db'
|
||||||
import { logger } from '../../lib'
|
import { logger } from '../../lib'
|
||||||
|
|
||||||
@Discord()
|
@Discord()
|
||||||
@ -26,13 +26,16 @@ export class SetPriceChannel {
|
|||||||
interaction: CommandInteraction,
|
interaction: CommandInteraction,
|
||||||
) {
|
) {
|
||||||
await interaction.deferReply({ ephemeral: true })
|
await interaction.deferReply({ ephemeral: true })
|
||||||
await db.set(DBTableEnum.PRICE_CHANNEL, channel.id).catch(async () => {
|
|
||||||
|
await setSettings('priceChannelId', channel.id)
|
||||||
|
.then(() => logger.database('Price Channel', channel.id))
|
||||||
|
.catch(async () => {
|
||||||
await interaction.editReply({
|
await interaction.editReply({
|
||||||
content: `❌ Failed to set price channel`,
|
content: `❌ Failed to set price channel`,
|
||||||
})
|
})
|
||||||
return
|
return
|
||||||
})
|
})
|
||||||
logger.database(DBTableEnum.PRICE_CHANNEL, channel.id)
|
|
||||||
await interaction.editReply({
|
await interaction.editReply({
|
||||||
content: `✔️ Set price channel to ${channel.id}`,
|
content: `✔️ Set price channel to ${channel.id}`,
|
||||||
})
|
})
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { Discord, Slash, SlashChoice, SlashOption } from 'discordx'
|
import { Discord, Slash, SlashChoice, SlashOption } from 'discordx'
|
||||||
import { ApplicationCommandOptionType, CommandInteraction, GuildBasedChannel } from 'discord.js'
|
import { ApplicationCommandOptionType, CommandInteraction } from 'discord.js'
|
||||||
|
|
||||||
import { db, DBTableEnum } from '../../db'
|
import { setSettings, getSettings } from '../../db'
|
||||||
import { ticketWorkloadEmbed, Workload } from '../../utils'
|
import { ticketWorkloadEmbed, Workload } from '../../utils'
|
||||||
import { logger } from '../../lib'
|
import { logger } from '../../lib'
|
||||||
|
|
||||||
@ -24,25 +24,38 @@ export class SetStatus {
|
|||||||
interaction: CommandInteraction,
|
interaction: CommandInteraction,
|
||||||
) {
|
) {
|
||||||
await interaction.deferReply({ ephemeral: true })
|
await interaction.deferReply({ ephemeral: true })
|
||||||
await db.set(DBTableEnum.WORKLOAD, status).catch(async () => {
|
|
||||||
|
await setSettings('workLoadStatus', status)
|
||||||
|
.then(() => logger.database('Workload Status', status))
|
||||||
|
.catch(async () => {
|
||||||
await interaction.editReply({
|
await interaction.editReply({
|
||||||
content: `❌ Failed to workload status`,
|
content: `❌ Failed to workload status`,
|
||||||
})
|
})
|
||||||
return
|
return
|
||||||
})
|
})
|
||||||
|
|
||||||
const statusMsg = await db.get(DBTableEnum.WORKLOAD_MESSAGE)
|
const settings = await getSettings()
|
||||||
const statusChannelId = await db.get(DBTableEnum.WORKLOAD_CHANNEL)
|
|
||||||
if (statusMsg && statusChannelId) {
|
if (!settings || !settings.workLoadChannelId)
|
||||||
const statusChannel = await interaction.guild?.channels.fetch(statusChannelId)
|
return await interaction.editReply({
|
||||||
|
content: `❌ Failed to find workload channel`,
|
||||||
|
})
|
||||||
|
|
||||||
|
if (settings.workLoadStatus && settings.workLoadChannelId) {
|
||||||
|
const statusChannel = await interaction.guild?.channels.fetch(
|
||||||
|
settings.workLoadChannelId,
|
||||||
|
)
|
||||||
|
|
||||||
if (!statusChannel || !statusChannel.isTextBased()) return
|
if (!statusChannel || !statusChannel.isTextBased()) return
|
||||||
const workloadMsg = await statusChannel.messages.fetch(statusMsg)
|
|
||||||
|
const workloadMsg = await statusChannel.messages.fetch(
|
||||||
|
settings.workloadMessageId,
|
||||||
|
)
|
||||||
await workloadMsg.edit({
|
await workloadMsg.edit({
|
||||||
embeds: [ticketWorkloadEmbed({ workload: status as Workload })]
|
embeds: [ticketWorkloadEmbed({ workload: status as Workload })],
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.database(DBTableEnum.WORKLOAD, status)
|
|
||||||
await interaction.editReply({
|
await interaction.editReply({
|
||||||
content: `✔️ Set workload status to ${status}`,
|
content: `✔️ Set workload status to ${status}`,
|
||||||
})
|
})
|
||||||
|
@ -1,13 +1,12 @@
|
|||||||
import { Client, Discord, Slash, SlashOption } from 'discordx'
|
import { Discord, Slash, SlashOption } from 'discordx'
|
||||||
import {
|
import {
|
||||||
ApplicationCommandOptionType,
|
ApplicationCommandOptionType,
|
||||||
CommandInteraction,
|
CommandInteraction,
|
||||||
Role,
|
Role,
|
||||||
TextChannel,
|
TextChannel,
|
||||||
} from 'discord.js'
|
} from 'discord.js'
|
||||||
import { db, DBTableEnum } from '../../db'
|
import { setSettings, getSettings, setRole } from '../../db'
|
||||||
import { logger } from '../../lib'
|
import { logger } from '../../lib'
|
||||||
import { Workload } from '../../utils'
|
|
||||||
|
|
||||||
@Discord()
|
@Discord()
|
||||||
export class SetWelcomeChannel {
|
export class SetWelcomeChannel {
|
||||||
@ -35,8 +34,8 @@ export class SetWelcomeChannel {
|
|||||||
) {
|
) {
|
||||||
await interaction.deferReply({ ephemeral: true })
|
await interaction.deferReply({ ephemeral: true })
|
||||||
|
|
||||||
const portfolioChannelId = await db.get(DBTableEnum.PORTFOLIO_CHANNEL)
|
const settings = await getSettings()
|
||||||
if (!portfolioChannelId) {
|
if (!settings || !settings.portfolioChannelId) {
|
||||||
logger.error(
|
logger.error(
|
||||||
'Missing portfolio channel',
|
'Missing portfolio channel',
|
||||||
'Set using /set-portfolio-channel',
|
'Set using /set-portfolio-channel',
|
||||||
@ -47,8 +46,7 @@ export class SetWelcomeChannel {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
const orderChannelId = await db.get(DBTableEnum.MAKE_AN_ORDER_CHANNEL)
|
if (!settings.makeAnOrderChannelId) {
|
||||||
if (!orderChannelId) {
|
|
||||||
logger.error(
|
logger.error(
|
||||||
'Missing make an order channel',
|
'Missing make an order channel',
|
||||||
'Set using /set-order-channel',
|
'Set using /set-order-channel',
|
||||||
@ -59,23 +57,23 @@ export class SetWelcomeChannel {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
await db
|
await setSettings('welcomeChannelId', channel.id)
|
||||||
.set(DBTableEnum.WELCOME_CHANNEL, channel.id)
|
.then(() => logger.database('Welcome channel', channel.id))
|
||||||
.catch(async () => {
|
.catch(async () => {
|
||||||
await interaction.editReply({
|
await interaction.editReply({
|
||||||
content: `❌ Failed to welcome channel`,
|
content: `❌ Failed to welcome channel`,
|
||||||
})
|
})
|
||||||
return
|
return
|
||||||
})
|
})
|
||||||
logger.database(DBTableEnum.WELCOME_CHANNEL, channel.id)
|
|
||||||
|
|
||||||
await db.set(DBTableEnum.WELCOME_ROLE, role.id).catch(async () => {
|
await setRole('welcomeRoleId', role.id)
|
||||||
|
.then(() => logger.database('Welcome role', role.id))
|
||||||
|
.catch(async () => {
|
||||||
await interaction.editReply({
|
await interaction.editReply({
|
||||||
content: `❌ Failed to entry role`,
|
content: `❌ Failed to set entry role`,
|
||||||
})
|
})
|
||||||
return
|
return
|
||||||
})
|
})
|
||||||
logger.database(DBTableEnum.WELCOME_ROLE, role.id)
|
|
||||||
|
|
||||||
await interaction.editReply({
|
await interaction.editReply({
|
||||||
content: `✔️ Set welcome channel to ${channel.id}\n✔️ Set entry role to ${role.id}`,
|
content: `✔️ Set welcome channel to ${channel.id}\n✔️ Set entry role to ${role.id}`,
|
||||||
|
@ -1,3 +0,0 @@
|
|||||||
import { PrismaClient } from '@prisma/client'
|
|
||||||
|
|
||||||
export const db = new PrismaClient()
|
|
13
src/db/banner.ts
Normal file
13
src/db/banner.ts
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
import { Prisma } from '@prisma/client'
|
||||||
|
import { db } from './'
|
||||||
|
|
||||||
|
export function getBanner() {
|
||||||
|
return db.banner.findFirst()
|
||||||
|
}
|
||||||
|
|
||||||
|
export function setBanner<T extends keyof Prisma.BannerCreateInput>(key: T, value: Prisma.BannerCreateInput[T]) {
|
||||||
|
return db.banner.update({
|
||||||
|
where: { id: 0 },
|
||||||
|
data: { [key]: value }
|
||||||
|
})
|
||||||
|
}
|
9
src/db/index.ts
Normal file
9
src/db/index.ts
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
import { PrismaClient } from '@prisma/client'
|
||||||
|
|
||||||
|
export const db = new PrismaClient()
|
||||||
|
|
||||||
|
export * from './banner'
|
||||||
|
export * from './role'
|
||||||
|
export * from './settings'
|
||||||
|
export * from './ticket'
|
||||||
|
export * from './user'
|
13
src/db/role.ts
Normal file
13
src/db/role.ts
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
import { Prisma } from '@prisma/client'
|
||||||
|
import { db } from './'
|
||||||
|
|
||||||
|
export function getRole() {
|
||||||
|
return db.role.findFirst()
|
||||||
|
}
|
||||||
|
|
||||||
|
export function setRole<T extends keyof Prisma.RoleCreateInput>(key: T, value: Prisma.RoleCreateInput[T]) {
|
||||||
|
return db.role.update({
|
||||||
|
where: { id: 0 },
|
||||||
|
data: { [key]: value }
|
||||||
|
})
|
||||||
|
}
|
16
src/db/settings.ts
Normal file
16
src/db/settings.ts
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
import { Prisma } from '@prisma/client'
|
||||||
|
import { db } from './'
|
||||||
|
|
||||||
|
export async function getSettings() {
|
||||||
|
return db.settings.findFirst()
|
||||||
|
}
|
||||||
|
|
||||||
|
export function setSettings<T extends keyof Prisma.SettingsCreateInput>(
|
||||||
|
key: T,
|
||||||
|
value: Prisma.SettingsCreateInput[T],
|
||||||
|
) {
|
||||||
|
return db.settings.update({
|
||||||
|
where: { id: 0 },
|
||||||
|
data: { [key]: value },
|
||||||
|
})
|
||||||
|
}
|
19
src/db/ticket.ts
Normal file
19
src/db/ticket.ts
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
import { db } from './'
|
||||||
|
import { Prisma } from '@prisma/client'
|
||||||
|
|
||||||
|
export async function createTicket(ticket: Prisma.TicketCreateInput, userId: string) {
|
||||||
|
return db.ticket.create({
|
||||||
|
data: {
|
||||||
|
channelId: ticket.channelId,
|
||||||
|
userId,
|
||||||
|
closed: ticket.closed,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function closeTicket(channelId: string) {
|
||||||
|
return db.ticket.update({
|
||||||
|
where: { channelId },
|
||||||
|
data: { closed: true }
|
||||||
|
})
|
||||||
|
}
|
82
src/db/user.ts
Normal file
82
src/db/user.ts
Normal file
@ -0,0 +1,82 @@
|
|||||||
|
import { db } from './'
|
||||||
|
import { Prisma } from '@prisma/client'
|
||||||
|
|
||||||
|
export async function getUser(id: string) {
|
||||||
|
return db.user.findFirst({
|
||||||
|
where: {
|
||||||
|
discordId: id,
|
||||||
|
},
|
||||||
|
include: {
|
||||||
|
tickets: true,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function getUserOpenedTicketsAmount(discordId: string) {
|
||||||
|
const data = await db.user.findFirst({
|
||||||
|
where: { discordId },
|
||||||
|
include: {
|
||||||
|
tickets: {
|
||||||
|
where: {
|
||||||
|
closed: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
if (!data) return 0
|
||||||
|
|
||||||
|
return data.tickets.length
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function createUser(
|
||||||
|
discordId: string,
|
||||||
|
ticket: Omit<Prisma.TicketCreateInput, 'User'>,
|
||||||
|
) {
|
||||||
|
const user = await getUser(discordId)
|
||||||
|
|
||||||
|
if (user) {
|
||||||
|
await db.ticket.create({
|
||||||
|
data: {
|
||||||
|
channelId: ticket.channelId,
|
||||||
|
closed: ticket.closed,
|
||||||
|
userId: user.discordId,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
return user
|
||||||
|
}
|
||||||
|
|
||||||
|
return db.user.create({
|
||||||
|
data: {
|
||||||
|
discordId,
|
||||||
|
tickets: {
|
||||||
|
create: {
|
||||||
|
channelId: ticket.channelId,
|
||||||
|
closed: ticket.closed,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function createUserSilent(discordId: string) {
|
||||||
|
return db.user.create({ data: { discordId } })
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function closeUserTickets(discordId: string) {
|
||||||
|
return db.user.update({
|
||||||
|
where: { discordId },
|
||||||
|
data: {
|
||||||
|
tickets: {
|
||||||
|
updateMany: {
|
||||||
|
where: {
|
||||||
|
closed: false,
|
||||||
|
},
|
||||||
|
data: {
|
||||||
|
closed: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
@ -3,10 +3,9 @@ import {
|
|||||||
EmbedBuilder,
|
EmbedBuilder,
|
||||||
channelMention,
|
channelMention,
|
||||||
userMention,
|
userMention,
|
||||||
User,
|
|
||||||
SnowflakeUtil,
|
SnowflakeUtil,
|
||||||
} from 'discord.js'
|
} from 'discord.js'
|
||||||
import { db, DBTableEnum } from '../db'
|
import { getSettings, getBanner, getRole } from '../db'
|
||||||
import { logger } from '../lib'
|
import { logger } from '../lib'
|
||||||
|
|
||||||
let lastJoinedUser: {
|
let lastJoinedUser: {
|
||||||
@ -27,29 +26,32 @@ export class GuildMemberAdd {
|
|||||||
)
|
)
|
||||||
return
|
return
|
||||||
|
|
||||||
const portfolioChannelID = await db.get(DBTableEnum.PORTFOLIO_CHANNEL)
|
const settings = await getSettings()
|
||||||
const makeAnOrderChannelID = await db.get(
|
const banner = await getBanner()
|
||||||
DBTableEnum.MAKE_AN_ORDER_CHANNEL,
|
const roles = await getRole()
|
||||||
)
|
|
||||||
const welcomeChannelID = await db.get(DBTableEnum.WELCOME_CHANNEL)
|
|
||||||
const imageURL = await db.get(DBTableEnum.BANNER_WELCOME)
|
|
||||||
|
|
||||||
const roleID = await db.get(DBTableEnum.WELCOME_ROLE)
|
if (!settings || !banner || !roles)
|
||||||
|
return logger.error(
|
||||||
|
'Missing settings',
|
||||||
|
'Please set all required fields',
|
||||||
|
)
|
||||||
|
|
||||||
let embed = new EmbedBuilder()
|
let embed = new EmbedBuilder()
|
||||||
.setTitle(
|
.setTitle(
|
||||||
`I'm glad to see you on my server. Let me give you a little tour.`,
|
`I'm glad to see you on my server. Let me give you a little tour.`,
|
||||||
)
|
)
|
||||||
.setDescription(
|
.setDescription(
|
||||||
`> 1. In the ${channelMention(portfolioChannelID)} - you can see my previous works.
|
`> 1. In the ${channelMention(settings.portfolioChannelId)} - you can see my previous works.
|
||||||
> 2. Here ${channelMention(makeAnOrderChannelID)} you might open a ticket.`,
|
> 2. Here ${channelMention(settings.makeAnOrderChannelId)} you might open a ticket.`,
|
||||||
)
|
)
|
||||||
.setImage(imageURL)
|
.setImage(banner.welcomeUrl)
|
||||||
|
|
||||||
const nonce = SnowflakeUtil.generate().toString()
|
const nonce = SnowflakeUtil.generate().toString()
|
||||||
|
|
||||||
const channel = await member.guild.channels.fetch(welcomeChannelID)
|
const channel = await member.guild.channels.fetch(
|
||||||
const role = await member.guild.roles.fetch(roleID)
|
settings.welcomeChannelId,
|
||||||
|
)
|
||||||
|
const role = await member.guild.roles.fetch(roles.welcomeRoleId)
|
||||||
|
|
||||||
if (channel && channel.isTextBased() && role) {
|
if (channel && channel.isTextBased() && role) {
|
||||||
await channel
|
await channel
|
||||||
|
Loading…
Reference in New Issue
Block a user