Start on database schema

This commit is contained in:
Isaac 2022-03-21 23:28:20 +00:00
parent 5ae4da227e
commit e569642240
10 changed files with 149 additions and 29 deletions

View File

@ -12,6 +12,9 @@
"ecmaVersion": 12, "ecmaVersion": 12,
"sourceType": "module" "sourceType": "module"
}, },
"plugins": [
"unused-imports"
],
"root": true, "root": true,
"rules": { "rules": {
"array-bracket-newline": [ "array-bracket-newline": [
@ -145,6 +148,9 @@
"no-unneeded-ternary": [ "no-unneeded-ternary": [
"error" "error"
], ],
"no-unused-expressions": [
"error"
],
"no-var": [ "no-var": [
"error" "error"
], ],
@ -204,6 +210,16 @@
"spaced-comment": [ "spaced-comment": [
"error", "error",
"always" "always"
],
"unused-imports/no-unused-imports": "error",
"unused-imports/no-unused-vars": [
"warn",
{
"vars": "all",
"varsIgnorePattern": "^_",
"args": "after-used",
"argsIgnorePattern": "^_"
}
] ]
} }
} }

4
README.md Normal file
View File

@ -0,0 +1,4 @@
CONFIG_PATH=./user/config.yml
DISCORD_TOKEN=
DB_ENCRYPTION_KEY=
DB_CONNECTION_URL=""

View File

@ -5,7 +5,7 @@
"moduleResolution": "Node", "moduleResolution": "Node",
"baseUrl": "src", "baseUrl": "src",
"resolveJsonModule": true, "resolveJsonModule": true,
"checkJs": true, "checkJs": false,
"paths": { "paths": {
"@/*": ["*.mjs"], "@/*": ["*.mjs"],
"#/*": ["*.json"] "#/*": ["*.json"]

View File

@ -33,9 +33,11 @@
}, },
"dependencies": { "dependencies": {
"@eartharoid/dtf": "^2.0.1", "@eartharoid/dtf": "^2.0.1",
"@prisma/client": "^3.11.0",
"@sapphire/framework": "^2.4.1", "@sapphire/framework": "^2.4.1",
"discord.js": "^13.6.0", "discord.js": "^13.6.0",
"dotenv-cra": "^3.0.2", "dotenv": "^16.0.0",
"figlet": "^1.5.2",
"leeks.js": "^0.2.4", "leeks.js": "^0.2.4",
"leekslazylogger": "^4.1.7", "leekslazylogger": "^4.1.7",
"semver": "^7.3.5", "semver": "^7.3.5",
@ -44,6 +46,8 @@
}, },
"devDependencies": { "devDependencies": {
"all-contributors-cli": "^6.20.0", "all-contributors-cli": "^6.20.0",
"eslint": "^8.11.0" "eslint": "^8.11.0",
"eslint-plugin-unused-imports": "^2.0.0",
"prisma": "^3.11.0"
} }
} }

75
prisma/schema.prisma Normal file
View File

@ -0,0 +1,75 @@
// This is your Prisma schema file,
// learn more about it in the docs: https://pris.ly/d/prisma-schema
generator client {
provider = "prisma-client-js"
}
datasource db {
provider = "mysql"
url = env("DB_CONNECTION_URL")
}
model Category {
id String @id @unique @db.VarChar(19)
tickets Ticket[]
@@map("categories")
}
model Guild {
id String @id @unique @db.VarChar(19)
archive Boolean @default(true)
errorColour String @default("RED")
primaryColour String @default("#009999")
successColour String @default("GREEN")
tags Tag[]
tickets Ticket[]
@@map("guilds")
}
model Tag {
content String @db.Text
guild Guild @relation(fields: [guildId], references: [id])
guildId String @db.VarChar(19)
name String
@@id([guildId, name])
@@unique([guildId, name])
@@map("tags")
}
model Ticket {
id String @id @unique @db.VarChar(19)
category Category @relation(fields: [categoryId], references: [id])
categoryId String @db.VarChar(19)
claimedBy User? @relation(name: "ClaimedTickets", fields: [claimedById], references: [id])
claimedById String @db.VarChar(19)
closedBy User? @relation(name: "ClosedTickets", fields: [closedById], references: [id])
closedById String @db.VarChar(19)
closedReason String?
createdBy User? @relation(name: "CreatedTickets", fields: [createdById], references: [id])
createdById String @db.VarChar(19)
firstResponse DateTime?
guild Guild @relation(fields: [guildId], references: [id])
guildId String @db.VarChar(19)
lastMessage DateTime?
number Int
open Boolean @default(true)
openingMessage String @db.VarChar(19)
pinnedMessages Json @default("[]")
topic String?
@@unique([guildId, number])
@@map("tickets")
}
model User {
id String @id @unique @db.VarChar(19)
ticketsCreated Ticket[] @relation("CreatedTickets")
ticketsClosed Ticket[] @relation("ClosedTickets")
ticketsClaimed Ticket[] @relation("ClaimedTickets")
@@map("users")
}

View File

@ -4,5 +4,5 @@ import { short } from 'leeks.js';
console.log(short( console.log(short(
'Set the "DB_ENCRYPTION_KEY" environment variable to: \n&1&!f' + 'Set the "DB_ENCRYPTION_KEY" environment variable to: \n&1&!f' +
randomBytes(24).toString('hex') + randomBytes(24).toString('hex') +
'&r\n\n&0&!e WARNING &r &e&lDo not lose the encryption key or most of the data in the database will be unreadable, requiring a new key and a full reset.' '&r\n\n&0&!e WARNING &r &e&lIf you lose the encryption key, most of the data in the database will become unreadable, requiring a new key and a full reset.'
)); ));

31
src/client.mjs Normal file
View File

@ -0,0 +1,31 @@
import {
container,
SapphireClient
} from '@sapphire/framework';
import { Intents } from 'discord.js';
import prisma from '@prisma/client';
export default class Client extends SapphireClient {
constructor() {
super({
defaultPrefix: 'tickets/',
intents: [
Intents.FLAGS.GUILDS,
Intents.FLAGS.GUILD_MEMBERS,
Intents.FLAGS.GUILD_MESSAGES,
Intents.FLAGS.GUILD_MESSAGE_REACTIONS
],
});
}
async login(token) {
container.prisma = new prisma.PrismaClient();
return super.login(token);
}
async destroy() {
await container.prisma.$disconnect();
return super.destroy();
}
}

View File

@ -21,13 +21,15 @@
* @license GNU-GPLv3 * @license GNU-GPLv3
*/ */
import dotenv from 'dotenv-cra'; import dotenv from 'dotenv';
import fs from 'fs'; import fs from 'fs';
import semver from 'semver'; import semver from 'semver';
import { colours } from 'leeks.js'; import { colours } from 'leeks.js';
import logger from './lib/logger.mjs'; import logger from './lib/logger.mjs';
import banner from './lib/banner.mjs'; import banner from './lib/banner.mjs';
import YAML from 'yaml'; import YAML from 'yaml';
import { container } from '@sapphire/framework';
import Client from './client.mjs';
process.env.NODE_ENV ??= 'development'; // make sure NODE_ENV is set process.env.NODE_ENV ??= 'development'; // make sure NODE_ENV is set
dotenv.config(); // load env file dotenv.config(); // load env file
@ -36,7 +38,7 @@ const pkg = JSON.parse(fs.readFileSync('./package.json', 'utf8'));
// check node version // check node version
if (!semver.satisfies(process.versions.node, pkg.engines.node)) { if (!semver.satisfies(process.versions.node, pkg.engines.node)) {
console.log('\x07' + colours.redBright(`Error: Discord Tickets requires Node.js version ${pkg.engines.node}; you are currently using ${process.versions.node}`)); console.log('\x07' + colours.redBright(`Error: Your current Node.js version, ${process.versions.node}, does not meet the requirement "${pkg.engines.node}".`));
process.exit(1); process.exit(1);
} }
@ -45,8 +47,6 @@ if (process.env.DB_ENCRYPTION_KEY === undefined) {
process.exit(1); process.exit(1);
} }
console.log(banner(pkg.version)); // print big title
process.env.CONFIG_PATH ??= './user/config.yml'; // set default config file path process.env.CONFIG_PATH ??= './user/config.yml'; // set default config file path
if (!fs.existsSync(process.env.CONFIG_PATH)) { if (!fs.existsSync(process.env.CONFIG_PATH)) {
@ -61,10 +61,11 @@ if (!fs.existsSync(process.env.CONFIG_PATH)) {
} }
} }
console.log(banner(pkg.version)); // print big title
const config = YAML.parse(fs.readFileSync(process.env.CONFIG_PATH, 'utf8')); const config = YAML.parse(fs.readFileSync(process.env.CONFIG_PATH, 'utf8'));
const log = logger(config); const log = logger(config);
container.log = log;
process.on('unhandledRejection', error => { process.on('unhandledRejection', error => {
log.notice(`Discord Tickets v${pkg.version} on Node.js v${process.versions.node} (${process.platform})`); log.notice(`Discord Tickets v${pkg.version} on Node.js v${process.versions.node} (${process.platform})`);
@ -73,3 +74,5 @@ process.on('unhandledRejection', error => {
log.error(error); log.error(error);
}); });
const client = new Client();
client.login();

View File

@ -1,22 +1,9 @@
import { colours } from 'leeks.js'; import { colours } from 'leeks.js';
import figlet from 'figlet';
import link from 'terminal-link'; import link from 'terminal-link';
export default version => colours.cyan(` export default version => colours.cyan(figlet.textSync('Discord', { font: 'Banner3' })) +
######## #### ###### ###### ####### ######## ######## colours.cyan('\n\n' + figlet.textSync('Tickets', { font: 'Banner3' })) +
## ## ## ## ## ## ## ## ## ## ## ## ## colours.cyanBright(`\n\n${link('Discord Tickets', 'https://discordtickets.app')} bot v${version} by eartharoid`) +
## ## ## ## ## ## ## ## ## ## ##
## ## ## ###### ## ## ## ######## ## ##
## ## ## ## ## ## ## ## ## ## ##
## ## ## ## ## ## ## ## ## ## ## ## ##
######## #### ###### ###### ####### ## ## ########
######## #### ###### ## ## ######## ######## ######
## ## ## ## ## ## ## ## ## ##
## ## ## ## ## ## ## ##
## ## ## ##### ###### ## ######
## ## ## ## ## ## ## ##
## ## ## ## ## ## ## ## ## ##
## #### ###### ## ## ######## ## ######
`) +
colours.cyanBright(`\n${link('Discord Tickets', 'https://discordtickets.app')} bot v${version} by eartharoid`) +
colours.cyanBright('\n' + link('Sponsor this project', 'https://discordtickets.app/sponsor')) + colours.cyanBright('\n' + link('Sponsor this project', 'https://discordtickets.app/sponsor')) +
'\n\n'; '\n\n';