Merge branch 'dev' into 'main'

Dev

See merge request illegitimate/illegitimate-bot!293
This commit is contained in:
2024-10-02 21:48:49 +00:00
45 changed files with 1164 additions and 294 deletions

View File

@@ -15,4 +15,5 @@ scripts
docker-compose.yml
Dockerfile
dprint.json
drizzle.config.ts
eslint.config.mjs

View File

@@ -4,6 +4,7 @@ WORKDIR /cache
COPY package.json .
COPY pnpm-lock.yaml .
COPY patches ./patches
RUN corepack enable
RUN pnpm install

12
drizzle.config.ts Normal file
View File

@@ -0,0 +1,12 @@
import { defineConfig } from "drizzle-kit"
export default defineConfig({
schema: "./src/db/schema.ts",
out: "./src/db/migrations",
dialect: "postgresql",
strict: true,
verbose: true,
dbCredentials: {
url: process.env.POSTGRESURI!
}
})

View File

@@ -1,10 +1,10 @@
import { FlatCompat } from "@eslint/eslintrc"
import js from "@eslint/js"
import typescriptEslint from "@typescript-eslint/eslint-plugin"
import globals from "globals"
import tsParser from "@typescript-eslint/parser"
import globals from "globals"
import path from "node:path"
import { fileURLToPath } from "node:url"
import js from "@eslint/js"
import { FlatCompat } from "@eslint/eslintrc"
// eslint-disable-next-line no-redeclare
const __filename = fileURLToPath(import.meta.url)
@@ -18,28 +18,28 @@ const compat = new FlatCompat({
export default [
{
ignores: ["**/node_modules", "**/dist"]
ignores: ["**/node_modules", "**/dist", "**/dev"]
},
...compat.extends("eslint:recommended", "plugin:@typescript-eslint/recommended"),
{
plugins: {
"@typescript-eslint": typescriptEslint,
"@typescript-eslint": typescriptEslint
},
languageOptions: {
globals: {
...globals.node,
...globals.browser,
...globals.browser
},
parser: tsParser,
ecmaVersion: "latest",
sourceType: "module",
sourceType: "module"
},
rules: {
indent: ["error", 4, {
SwitchCase: 1,
SwitchCase: 1
}],
"linebreak-style": ["error", "unix"],
@@ -52,7 +52,7 @@ export default [
"no-multiple-empty-lines": ["error", {
max: 2,
maxEOF: 1,
maxBOF: 0,
maxBOF: 0
}],
"no-lonely-if": "error",
@@ -62,13 +62,13 @@ export default [
"arrow-spacing": ["warn", {
before: true,
after: true,
after: true
}],
"space-before-function-paren": ["error", {
anonymous: "never",
named: "never",
asyncArrow: "always",
asyncArrow: "always"
}],
"comma-spacing": "error",
@@ -78,7 +78,7 @@ export default [
"@typescript-eslint/no-unused-vars": ["warn", {
vars: "all",
args: "after-used",
ignoreRestSiblings: false,
ignoreRestSiblings: false
}],
"@typescript-eslint/no-empty-object-type": "off",
"@typescript-eslint/no-require-imports": "off",
@@ -86,17 +86,18 @@ export default [
"ts-expect-error": "allow-with-description",
"ts-ignore": "allow-with-description",
"ts-nocheck": "allow-with-description",
"ts-check": "allow-with-description",
}],
"ts-check": "allow-with-description"
}]
}
},
}, {
{
languageOptions: {
globals: {
...globals.node,
...globals.node
},
ecmaVersion: 5,
sourceType: "commonjs",
},
sourceType: "commonjs"
}
}
]

View File

@@ -19,11 +19,14 @@
"dev:ts": "nodemon --config .nodemon/ts.json src/index.ts",
"dev:ts:inspect": "nodemon --config .nodemon/debug.json src/index.ts",
"dev:js": "nodemon --config .nodemon/js.json dist/index.js",
"format": "dprint fmt \"**/*.ts\"",
"fmt": "dprint fmt \"**/*.ts\"",
"check": "pnpm tscheck && pnpm lint",
"tscheck": "tsc && echo \"TypeScript check passed!\"",
"lint": "eslint && echo \"Linting passed!\"",
"lint:fix": "eslint --fix",
"db:generate": "drizzle-kit generate",
"db:migrate": "drizzle-kit migrate",
"db:studio": "drizzle-kit studio",
"push:prod": "tsx scripts/deploy-commands.ts",
"push:dev": "tsx scripts/dev-deploy.ts",
"delete:dev": "tsx scripts/delete-commands.ts"
@@ -41,11 +44,11 @@
"discord-player-youtubei": "^1.3.2",
"discord.js": "^14.16.2",
"dotenv": "^16.4.5",
"drizzle-orm": "^0.33.0",
"ioredis": "^5.4.1",
"mongoose": "^8.6.3",
"ms": "^2.1.3",
"pg": "^8.13.0",
"pg-hstore": "^2.3.4",
"postgres": "^3.4.4",
"pretty-ms": "^9.1.0",
"sequelize": "^6.37.3"
},
@@ -56,16 +59,22 @@
"@swc/core": "^1.7.28",
"@types/ms": "^0.7.34",
"@types/node": "^22.7.2",
"@types/pg": "^8.11.10",
"@typescript-eslint/eslint-plugin": "^8.7.0",
"@typescript-eslint/parser": "^8.7.0",
"chokidar": "^4.0.1",
"dprint": "^0.47.2",
"drizzle-kit": "^0.24.2",
"eslint": "^9.11.1",
"globals": "^15.9.0",
"sqlite3": "^5.1.7",
"tsx": "^4.19.1",
"typescript": "^5.6.2"
},
"packageManager": "pnpm@9.11.0+sha256.1c0e33f70e5df9eede84a357bdfa0b1f9dba6e58194628d48a1055756f553754"
"packageManager": "pnpm@9.11.0+sha256.1c0e33f70e5df9eede84a357bdfa0b1f9dba6e58194628d48a1055756f553754",
"pnpm": {
"patchedDependencies": {
"whatwg-url@5.0.0": "patches/whatwg-url@5.0.0.patch",
"tr46@0.0.3": "patches/tr46@0.0.3.patch"
}
}
}

15
patches/tr46@0.0.3.patch Normal file
View File

@@ -0,0 +1,15 @@
diff --git a/.npmignore b/.npmignore
deleted file mode 100644
index 96e9161fde31e9906718f689d5cc135e507a51e1..0000000000000000000000000000000000000000
diff --git a/index.js b/index.js
index 9ce12ca2d026fa202f7a0d32e0a7c8526660ed78..7c3b5d7ff1624d2bfbb5b83f69a9b460e38dbeab 100644
--- a/index.js
+++ b/index.js
@@ -1,6 +1,6 @@
"use strict";
-var punycode = require("punycode");
+var punycode = require("punycode/");
var mappingTable = require("./lib/mappingTable.json");
var PROCESSING_OPTIONS = {

View File

@@ -0,0 +1,11 @@
diff --git a/lib/url-state-machine.js b/lib/url-state-machine.js
index c25dbc2c486289fbd7446baed24dc6343f0226f6..e1681d27501013c5e6aa9b720b32338c177b692c 100644
--- a/lib/url-state-machine.js
+++ b/lib/url-state-machine.js
@@ -1,5 +1,5 @@
"use strict";
-const punycode = require("punycode");
+const punycode = require("punycode/");
const tr46 = require("tr46");
const specialSchemes = {

732
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,8 +1,10 @@
import { devMessage, embedColor, hypixelGuildID } from "config/options.js"
import { waitingListRole } from "config/roles.js"
import { ApplicationCommandType, ContextMenuCommandBuilder, PermissionFlagsBits, userMention } from "discord.js"
import { eq } from "drizzle-orm"
import { IContextMenu } from "interfaces"
import verify from "schemas/verifyTag.js"
import db from "src/db/db.js"
import { verifies } from "src/db/schema.js"
import roleManage from "utils/functions/rolesmanage.js"
import { getGuild, getHeadURL, getIGN } from "utils/Hypixel.js"
@@ -22,7 +24,9 @@ export default {
const targetId = interaction.targetId
const user = await interaction.guild!.members.fetch(targetId)
const usermentioned = userMention(user.user.id)
const verifyData = await verify.findOne({ where: { userID: user.user.id } })
const verifyData = await db.query.verifies.findFirst({
where: eq(verifies.userID, user.user.id)
})
if (!verifyData) {
await user.setNickname(`${user.user.username} (X)`, "User used the update command").catch(() => {

View File

@@ -1,7 +1,8 @@
import { embedColor } from "config/options.js"
import { InteractionContextType, PermissionFlagsBits, SlashCommandBuilder } from "discord.js"
import { ICommand } from "interfaces"
import settings from "schemas/settingsTag.js"
import db from "src/db/db.js"
import { settings } from "src/db/schema.js"
export default {
name: "config",
@@ -36,10 +37,12 @@ export default {
const setting = interaction.options.getString("setting")!
const value = interaction.options.getString("value")!
const settingsData = await settings.findOne({ where: { name: setting } })
const settingsData = await db.query.settings.findFirst({
where: (settings, { eq }) => eq(settings.name, setting)
})
if (!settingsData) {
await settings.create({
await db.insert(settings).values({
name: setting,
value: value
})
@@ -51,7 +54,9 @@ export default {
}]
})
} else {
await settingsData.destroy()
await db.update(settings).set({
value: value
})
await interaction.editReply({
embeds: [{

View File

@@ -1,7 +1,9 @@
import { devMessage, embedColor } from "config/options.js"
import { InteractionContextType, PermissionFlagsBits, SlashCommandBuilder, userMention } from "discord.js"
import { eq } from "drizzle-orm"
import { ICommand } from "interfaces"
import verify from "schemas/verifyTag.js"
import db from "src/db/db.js"
import { verifies } from "src/db/schema.js"
import { getHeadURL, getIGN, getUUID } from "utils/Hypixel.js"
export default {
@@ -37,7 +39,9 @@ export default {
return
}
const verifyData = await verify.findOne({ where: { uuid: uuid } })
const verifyData = await db.query.verifies.findFirst({
where: eq(verifies.uuid, uuid)
})
if (!verifyData) {
await interaction.editReply({
embeds: [{

View File

@@ -1,7 +1,9 @@
import { devMessage, embedColor } from "config/options.js"
import { GuildMember, InteractionContextType, PermissionFlagsBits, SlashCommandBuilder, userMention } from "discord.js"
import { eq } from "drizzle-orm"
import { ICommand } from "interfaces"
import verify from "schemas/verifyTag.js"
import db from "src/db/db.js"
import { verifies } from "src/db/schema.js"
import logToChannel from "utils/functions/logtochannel.js"
import roleManage from "utils/functions/rolesmanage.js"
import { getIGN } from "utils/Hypixel.js"
@@ -26,7 +28,9 @@ export default {
async execute({ interaction }) {
const member = interaction.options.getMember("user") as GuildMember
const verifiedUser = await verify.findOne({ where: { userID: member.user.id } })
const verifiedUser = await db.query.verifies.findFirst({
where: eq(verifies.userID, member.user.id)
})
const mod = interaction.user
if (!verifiedUser) {
@@ -41,7 +45,7 @@ export default {
const uuid = verifiedUser.uuid
const ign = await getIGN(uuid)
await verifiedUser.destroy()
await db.delete(verifies).where(eq(verifies.userID, member.user.id))
await member.roles.remove(
roleManage("all").rolesToRemove,
"User force unverified by " + interaction.user.username

View File

@@ -1,8 +1,10 @@
import { devMessage, embedColor, hypixelGuildID } from "config/options.js"
import { waitingListRole } from "config/roles.js"
import { GuildMember, InteractionContextType, PermissionFlagsBits, SlashCommandBuilder, userMention } from "discord.js"
import { eq } from "drizzle-orm"
import { ICommand } from "interfaces"
import verify from "schemas/verifyTag.js"
import db from "src/db/db.js"
import { verifies } from "src/db/schema.js"
import roleManage from "utils/functions/rolesmanage.js"
import { getGuild, getHeadURL, getIGN } from "utils/Hypixel.js"
@@ -29,7 +31,9 @@ export default {
const user = interaction.options.getMember("user") as GuildMember
const usermentioned = userMention(user.user.id)
const verifyData = await verify.findOne({ where: { userID: user.user.id } })
const verifyData = await db.query.verifies.findFirst({
where: eq(verifies.userID, user.user.id)
})
if (!verifyData) {
await user.setNickname(`${user.user.username} (X)`, "User used the update command").catch(() => {

View File

@@ -1,7 +1,9 @@
import { devMessage, embedColor, hypixelGuildID } from "config/options.js"
import { GuildMember, InteractionContextType, PermissionFlagsBits, SlashCommandBuilder, userMention } from "discord.js"
import { eq } from "drizzle-orm"
import { ICommand } from "interfaces"
import verify from "schemas/verifyTag.js"
import db from "src/db/db.js"
import { verifies } from "src/db/schema.js"
import logToChannel from "utils/functions/logtochannel.js"
import roleManage from "utils/functions/rolesmanage.js"
import { getGuild, getHeadURL, getPlayer, getUUID } from "utils/Hypixel.js"
@@ -35,7 +37,9 @@ export default {
const ign = interaction.options.getString("ign")
const mod = interaction.user
const verifyData = await verify.findOne({ where: { userID: user.user.id } })
const verifyData = await db.query.verifies.findFirst({
where: eq(verifies.userID, user.user.id)
})
if (verifyData) {
interaction.editReply("That user is already verified.")
return
@@ -160,7 +164,7 @@ export default {
// Do nothing
})
await verify.create({
await db.insert(verifies).values({
userID: user.user.id,
uuid: uuid
})

View File

@@ -110,20 +110,7 @@ export default async function guildInfo(interaction: ChatInputCommandInteraction
const guildExp = new Intl.NumberFormat("en-US").format(guildExpUnformatted)
const guildLvl = guildLevel(guildExpUnformatted)
const guildMembers = guild!.members
const guildCreatedDate = guildCreated.getDate()
const guildCreatedMonth = guildCreated.getMonth() + 1
const guildCreatedYear = guildCreated.getFullYear()
const guildCreatedHour = guildCreated.getHours()
const guildCreatedMinute = guildCreated.getMinutes()
const guildCreatedSecond = guildCreated.getSeconds()
const guildCreatedTime = guildCreatedDate + "." +
guildCreatedMonth + "." +
guildCreatedYear + " " +
guildCreatedHour + ":" +
guildCreatedMinute + ":" +
guildCreatedSecond
const guildCreatedTime = guildCreated.toLocaleString("hr-HR", {})
const guildOwner = guildMembers.find(m => m.rank === "Guild Master")!.uuid
const guildOwnerName = await getIGN(guildOwner)

View File

@@ -111,19 +111,7 @@ export default async function guildMember(interaction: ChatInputCommandInteracti
const guildMemberJoinMS = guildMember!.joined
const guildMemberJoinTime = new Date(guildMemberJoinMS)
const guildMemberJoinDate = guildMemberJoinTime.getDate()
const guildMemberJoinMonth = guildMemberJoinTime.getMonth() + 1
const guildMemberJoinYear = guildMemberJoinTime.getFullYear()
const guildMemberJoinHours = guildMemberJoinTime.getHours()
const guildMemberJoinMinutes = guildMemberJoinTime.getMinutes()
const guildMemberJoinSeconds = guildMemberJoinTime.getSeconds()
const guildMemberJoin = guildMemberJoinDate + "." +
guildMemberJoinMonth + "." +
guildMemberJoinYear + " " +
guildMemberJoinHours + ":" +
guildMemberJoinMinutes + ":" +
guildMemberJoinSeconds
const guildMemberJoin = guildMemberJoinTime.toLocaleString("hr-HR", {})
await interaction.editReply({
embeds: [{

View File

@@ -1,5 +1,5 @@
import { devMessage, embedColor } from "config/options.js"
import { ChannelType, ChatInputCommandInteraction } from "discord.js"
import { ChatInputCommandInteraction } from "discord.js"
import { IGuildData } from "interfaces"
import { getGuild, getIGN, getPlayer, getUUID } from "utils/Hypixel.js"
import { redis } from "utils/Illegitimate.js"
@@ -12,16 +12,6 @@ export default async function guildTop(interaction: ChatInputCommandInteraction)
let amount = interaction.options.getNumber("amount") || 10
let guild: IGuildData | null
if (interaction.channel!.type === ChannelType.DM) {
interaction.editReply({
embeds: [{
description: "You can't use this command in DMs!",
color: embedColor
}]
})
return
}
if (type === "ign") {
await interaction.editReply({
embeds: [{

View File

@@ -1,8 +1,10 @@
import { devMessage, embedColor } from "config/options.js"
import { waitingListRole } from "config/roles.js"
import { GuildMember, InteractionContextType, PermissionFlagsBits, SlashCommandBuilder, userMention } from "discord.js"
import { eq } from "drizzle-orm"
import { ICommand } from "interfaces"
import waitinglist from "schemas/waitinglistTag.js"
import db from "src/db/db.js"
import { waitingLists } from "src/db/schema.js"
import logToChannel from "utils/functions/logtochannel.js"
export default {
@@ -35,9 +37,11 @@ export default {
const member = interaction.options.getMember("user") as GuildMember
const reason = interaction.options.getString("reason") ?? "No reason provided."
const mod = interaction.user!
const waiting = await waitinglist.findOne({ where: { userID: member.user.id } })
const waiting = await db.query.waitingLists.findFirst({
where: eq(waitingLists.userID, member.user.id)
})
if (!waitinglist) {
if (!waiting) {
await interaction.editReply({
embeds: [{
description: userMention(member.user.id) + " is not on the waiting list.",
@@ -47,7 +51,7 @@ export default {
return
}
await waiting?.destroy()
await db.delete(waitingLists).where(eq(waitingLists.userID, member.user.id))
await member.roles.remove(waitingListRole, "Removed from waiting list.")
await logToChannel("mod", {

View File

@@ -1,7 +1,7 @@
import { embedColor, hypixelGuildID } from "config/options.js"
import { ChatInputCommandInteraction, GuildMember } from "discord.js"
import { IGuildData } from "interfaces"
import verify from "schemas/verifyTag.js"
import db from "src/db/db.js"
import env from "utils/Env.js"
import roleManage from "utils/functions/rolesmanage.js"
import { getGuild } from "utils/Hypixel.js"
@@ -35,7 +35,7 @@ export default async function removeGuildRoles(interaction: ChatInputCommandInte
const hypixelGuildMembers = guildData.members.map(gmember => gmember.uuid)
const verifiedUsers = await verify.findAll({})
const verifiedUsers = await db.query.verifies.findMany({})
for (const gmember of guildMembers) {
const gmemberuuid = verifiedUsers.find(user => user.userID === gmember.id)?.uuid

View File

@@ -1,7 +1,7 @@
import { embedColor, hypixelGuildID } from "config/options.js"
import { ChannelType, ChatInputCommandInteraction, GuildMember } from "discord.js"
import { IGuildData } from "interfaces"
import verify from "schemas/verifyTag.js"
import db from "src/db/db.js"
import env from "utils/Env.js"
import { color } from "utils/functions/colors.js"
import roleManage from "utils/functions/rolesmanage.js"
@@ -53,7 +53,7 @@ export default async function updateAll(interaction: ChatInputCommandInteraction
})
const guildMemberIDs = hypixelGuildMembers.map(gmember => gmember.uuid)
const verifiedUsers = await verify.findAll({})
const verifiedUsers = await db.query.verifies.findMany()
await interaction.editReply({
embeds: [{

View File

@@ -1,8 +1,10 @@
import { devMessage, embedColor, hypixelGuildID } from "config/options.js"
import { waitingListRole } from "config/roles.js"
import { GuildMember, InteractionContextType, SlashCommandBuilder } from "discord.js"
import { eq } from "drizzle-orm"
import { ICommand } from "interfaces"
import verify from "schemas/verifyTag.js"
import db from "src/db/db.js"
import { verifies } from "src/db/schema.js"
import roleManage from "utils/functions/rolesmanage.js"
import { getGuild, getHeadURL, getIGN } from "utils/Hypixel.js"
@@ -21,7 +23,9 @@ export default {
await interaction.deferReply()
const user = interaction.member as GuildMember
const verifyData = await verify.findOne({ where: { userID: user.user.id } })
const verifyData = await db.query.verifies.findFirst({
where: eq(verifies.userID, user.user.id)
})
if (!verifyData) {
await user.setNickname(`${user.user.username} (X)`, "User used the update command").catch(() => {

View File

@@ -1,9 +1,11 @@
import { devMessage, embedColor, hypixelGuildID } from "config/options.js"
import { GuildMember, InteractionContextType, SlashCommandBuilder } from "discord.js"
import { eq } from "drizzle-orm"
import { ICommand } from "interfaces"
import { IPlayerData } from "interfaces"
import { IGuildData } from "interfaces"
import verify from "schemas/verifyTag.js"
import db from "src/db/db.js"
import { verifies } from "src/db/schema.js"
import roleManage from "utils/functions/rolesmanage.js"
import { getGuild, getHeadURL, getPlayer, getUUID } from "utils/Hypixel.js"
@@ -32,7 +34,9 @@ export default {
const user = interaction.member! as GuildMember
const ign = interaction.options.getString("ign")!
const verifyData = await verify.findOne({ where: { userID: user.id } })
const verifyData = await db.query.verifies.findFirst({
where: eq(verifies.userID, user.user.id)
})
if (verifyData) {
interaction.editReply("You are already verified.\n" + "Try running /update to update your roles.")
return
@@ -178,7 +182,7 @@ export default {
// Do nothing
})
await verify.create({
await db.insert(verifies).values({
userID: user.id,
uuid: uuid
})

View File

@@ -1,7 +1,9 @@
import { devMessage, embedColor } from "config/options.js"
import { InteractionContextType, SlashCommandBuilder, userMention } from "discord.js"
import { eq } from "drizzle-orm"
import { ICommand } from "interfaces"
import verify from "schemas/verifyTag.js"
import db from "src/db/db.js"
import { verifies } from "src/db/schema.js"
import { getHeadURL, getIGN } from "utils/Hypixel.js"
export default {
@@ -19,7 +21,9 @@ export default {
await interaction.deferReply()
const user = interaction.user
const verifyData = await verify.findOne({ where: { userID: user.id } })
const verifyData = await db.query.verifies.findFirst({
where: eq(verifies.userID, user.id)
})
if (!verifyData) {
await interaction.editReply({

View File

@@ -1,7 +1,9 @@
import { devMessage, embedColor } from "config/options.js"
import { InteractionContextType, PermissionFlagsBits, SlashCommandBuilder, userMention } from "discord.js"
import { eq } from "drizzle-orm"
import { ICommand } from "interfaces"
import verify from "schemas/verifyTag.js"
import db from "src/db/db.js"
import { verifies } from "src/db/schema.js"
import { getHeadURL, getIGN } from "utils/Hypixel.js"
export default {
@@ -26,7 +28,9 @@ export default {
await interaction.deferReply()
const user = interaction.options.getUser("user")!
const verifiedUser = await verify.findOne({ where: { userID: user.id } })
const verifiedUser = await db.query.verifies.findFirst({
where: eq(verifies.userID, user.id)
})
if (!verifiedUser) {
interaction.editReply({
embeds: [{

View File

@@ -1,7 +1,9 @@
import { devMessage, embedColor } from "config/options.js"
import { bwfkdr, bwstars, bwwins, duelswins, duelswlr, swkdr, swstars } from "config/reqs.js"
import { eq } from "drizzle-orm"
import { IButton } from "interfaces"
import guildapp from "schemas/guildAppTag.js"
import db from "src/db/db.js"
import { guildApps } from "src/db/schema.js"
import { bedwarsLevel, getGuild, getHeadURL, getPlayer, hypixelLevel, skywarsLevel } from "utils/Hypixel.js"
export default {
@@ -14,7 +16,9 @@ export default {
const message = interaction.message
const embed = message.embeds[0]
const applicantId = embed.footer!.text.split(" ")[1]
const guildappdata = await guildapp.findOne({ where: { userID: applicantId } })
const guildappdata = await db.query.guildApps.findFirst({
where: eq(guildApps.userID, applicantId)
})
const uuid = guildappdata!.uuid
const player = await getPlayer(uuid)

View File

@@ -1,9 +1,10 @@
import { embedColor, hypixelGuildID, waitingListChannel, waitingListMessage } from "config/options.js"
import { waitingListRole } from "config/roles.js"
import { ActionRowBuilder, ButtonBuilder, ButtonStyle, TextChannel } from "discord.js"
import { eq } from "drizzle-orm"
import { IButton } from "interfaces"
import guildapp from "schemas/guildAppTag.js"
import waitingList from "schemas/waitinglistTag.js"
import db from "src/db/db.js"
import { guildApps, waitingLists } from "src/db/schema.js"
import { color } from "utils/functions/colors.js"
import { getGuild, getIGN } from "utils/Hypixel.js"
@@ -53,18 +54,20 @@ export default {
}]
})
const applicantEntry = await guildapp.findOne({ where: { userID: applicantId } })
const applicantEntry = await db.query.guildApps.findFirst({
where: eq(guildApps.userID, applicantId)
})
const applicantUUID = applicantEntry!.uuid
const time = Date.now()
await waitingList.create({
await db.insert(waitingLists).values({
userID: applicantId,
uuid: applicantUUID,
timestamp: time
})
await applicant.roles.add(waitingListRole)
await applicantEntry?.destroy()
await db.delete(guildApps).where(eq(guildApps.userID, applicantId))
await interaction.editReply({
embeds: [{
@@ -87,14 +90,14 @@ export default {
const wlmessage = await channel!.messages.fetch(waitingListMessage)
const wlembed = wlmessage.embeds[0]
const accepted = await waitingList.findAll()
const accepted = await db.query.waitingLists.findMany()
for (let i = 0; i < accepted.length; i++) {
const uuid = accepted[i].uuid
const guild = await getGuild(uuid)
if (guild && guild._id === hypixelGuildID) {
await waitingList.destroy({ where: { uuid: uuid } })
await db.delete(waitingLists).where(eq(waitingLists.uuid, uuid))
continue
}
}

View File

@@ -3,8 +3,10 @@ import { applicationsChannel, embedColor } from "config/options.js"
import { guild as guildQuestions } from "config/questions.js"
import { guildRole } from "config/roles.js"
import { ActionRowBuilder, ButtonBuilder, ButtonStyle, GuildMember, TextChannel } from "discord.js"
import { eq } from "drizzle-orm"
import { IButton } from "interfaces"
import guildapp from "schemas/guildAppTag.js"
import db from "src/db/db.js"
import { guildApps } from "src/db/schema.js"
import applicationQuestions from "utils/functions/applicationquestions.js"
export default {
@@ -30,7 +32,9 @@ export default {
return
}
const application = await guildapp.findOne({ where: { userID: user.user.id } })
const application = await db.query.guildApps.findFirst({
where: eq(guildApps.userID, user.user.id)
})
if (application) {
await interaction.editReply("You already have an application in progress.")
@@ -248,7 +252,7 @@ export default {
}]
})
await guildapp.create({
await db.insert(guildApps).values({
userID: user.user.id,
uuid: uuid
})

View File

@@ -1,7 +1,9 @@
import { embedColor } from "config/options.js"
import { ActionRowBuilder, ButtonBuilder, ButtonStyle } from "discord.js"
import { eq } from "drizzle-orm"
import { IButton } from "interfaces"
import staffapp from "schemas/staffAppTag.js"
import db from "src/db/db.js"
import { staffApps } from "src/db/schema.js"
export default {
name: "staffapplicationaccept",
@@ -43,8 +45,7 @@ export default {
]
})
const app = await staffapp.findOne({ where: { userID: applicantId } })
await app?.destroy()
await db.delete(staffApps).where(eq(staffApps.userID, applicantId))
await interaction.editReply({
embeds: [{

View File

@@ -3,9 +3,10 @@ import { embedColor, staffApplicationsChannel } from "config/options.js"
import { staff as staffQuestions } from "config/questions.js"
import { guildRole, guildStaff } from "config/roles.js"
import { ActionRowBuilder, ButtonBuilder, ButtonStyle, GuildMember, TextChannel } from "discord.js"
import { eq } from "drizzle-orm"
import { IButton } from "interfaces"
import settings from "schemas/settingsTag.js"
import staffapp from "schemas/staffAppTag.js"
import db from "src/db/db.js"
import { settings, staffApps } from "src/db/schema.js"
import env from "utils/Env.js"
import applicationQuestions from "utils/functions/applicationquestions.js"
@@ -17,7 +18,9 @@ export default {
const user = interaction.member as GuildMember
const guild = interaction.guild!
const userRoles = user.roles.cache
const setting = await settings.findOne({ where: { name: "staffAppStatus" } })
const setting = await db.query.settings.findFirst({
where: eq(settings.name, "staffApplications")
})
const status = setting?.value || "0"
function sq(n: number): string {
@@ -48,7 +51,9 @@ export default {
return
}
const application = await staffapp.findOne({ where: { userID: user.user.id } })
const application = await db.query.staffApps.findFirst({
where: eq(staffApps.userID, user.user.id)
})
if (application) {
await interaction.editReply("You already have an application in progress.")
@@ -221,7 +226,7 @@ export default {
}]
})
await staffapp.create({
await db.insert(staffApps).values({
userID: user.user.id,
uuid: uuid
})

View File

@@ -1,6 +1,8 @@
import { hypixelGuildID } from "config/options.js"
import { eq } from "drizzle-orm"
import { IButton } from "interfaces"
import waitinglist from "schemas/waitinglistTag.js"
import db from "src/db/db.js"
import { waitingLists } from "src/db/schema.js"
import { getGuild, getIGN } from "utils/Hypixel.js"
export default {
@@ -13,14 +15,14 @@ export default {
const user = interaction.user
const message = interaction.message
const embed = message.embeds[0]
const accepted = await waitinglist.findAll()
const accepted = await db.query.waitingLists.findMany()
for (let i = 0; i < accepted.length; i++) {
const uuid = accepted[i].uuid
const guild = await getGuild(uuid)
if (guild && guild._id === hypixelGuildID) {
await accepted[i].destroy()
await db.delete(waitingLists).where(eq(waitingLists.uuid, uuid))
continue
}
}

View File

@@ -1,7 +1,9 @@
import { embedColor } from "config/options.js"
import { ActionRowBuilder, ButtonBuilder, ButtonStyle, EmbedBuilder, GuildMember, Message } from "discord.js"
import { eq } from "drizzle-orm"
import { IModal } from "interfaces"
import guildapp from "schemas/guildAppTag.js"
import db from "src/db/db.js"
import { guildApps } from "src/db/schema.js"
export default {
name: "denyreasonbox",
@@ -81,8 +83,7 @@ export default {
responseEmbeds = [responseEmbed]
}
const app = await guildapp.findOne({ where: { userID: applicantId } })
await app?.destroy()
await db.delete(guildApps).where(eq(guildApps.userID, applicantId))
await interaction.editReply({
embeds: responseEmbeds

View File

@@ -1,7 +1,9 @@
import { embedColor } from "config/options.js"
import { ActionRowBuilder, ButtonBuilder, ButtonStyle, EmbedBuilder } from "discord.js"
import { eq } from "drizzle-orm"
import { IModal } from "interfaces"
import staffapp from "schemas/staffAppTag.js"
import db from "src/db/db.js"
import { staffApps } from "src/db/schema.js"
export default {
name: "staffdenyreasonbox",
@@ -43,8 +45,7 @@ export default {
await applicant.send({ embeds: [dmMessage] })
const app = await staffapp.findOne({ where: { userID: applicantId } })
await app?.destroy()
await db.delete(staffApps).where(eq(staffApps.userID, applicantId))
await interaction.editReply({
embeds: [{

View File

@@ -1,7 +1,9 @@
import { devMessage, embedColor, hypixelGuildID } from "config/options.js"
import { GuildMember } from "discord.js"
import { eq } from "drizzle-orm"
import { IModal } from "interfaces"
import verify from "schemas/verifyTag.js"
import db from "src/db/db.js"
import { verifies } from "src/db/schema.js"
import roleManage from "utils/functions/rolesmanage.js"
import { getGuild, getHeadURL, getPlayer, getUUID } from "utils/Hypixel.js"
@@ -14,7 +16,9 @@ export default {
const user = interaction.member as GuildMember
const ign = interaction.fields.fields.get("verifyign")!.value
const verifyData = await verify.findOne({ where: { userID: user.user.id } })
const verifyData = await db.query.verifies.findFirst({
where: eq(verifies.userID, user.user.id)
})
if (verifyData) {
interaction.editReply("You are already verified.\n" + "Try running /update to update your roles.")
return
@@ -149,7 +153,7 @@ export default {
// Do nothing
})
await verify.create({
await db.insert(verifies).values({
userID: user.id,
uuid: uuid
})

11
src/db/db.ts Normal file
View File

@@ -0,0 +1,11 @@
import { drizzle } from "drizzle-orm/postgres-js"
import postgres from "postgres"
import env from "utils/Env.js"
import * as schema from "./schema.js"
const queryClient = postgres(env.prod.postgresURI)
const db = drizzle(queryClient, {
schema
})
export default db

View File

@@ -0,0 +1,30 @@
CREATE TABLE IF NOT EXISTS "guildApps" (
"id" serial PRIMARY KEY NOT NULL,
"userID" text NOT NULL,
"uuid" text NOT NULL
);
--> statement-breakpoint
CREATE TABLE IF NOT EXISTS "settings" (
"id" serial PRIMARY KEY NOT NULL,
"name" text NOT NULL,
"value" text NOT NULL
);
--> statement-breakpoint
CREATE TABLE IF NOT EXISTS "staffApps" (
"id" serial PRIMARY KEY NOT NULL,
"userID" text NOT NULL,
"uuid" text NOT NULL
);
--> statement-breakpoint
CREATE TABLE IF NOT EXISTS "verifies" (
"id" serial PRIMARY KEY NOT NULL,
"userID" text NOT NULL,
"uuid" text NOT NULL
);
--> statement-breakpoint
CREATE TABLE IF NOT EXISTS "waitingLists" (
"id" serial PRIMARY KEY NOT NULL,
"userID" text NOT NULL,
"uuid" text NOT NULL,
"timestamp" bigint NOT NULL
);

View File

@@ -0,0 +1,162 @@
{
"id": "fc9135a5-9614-429b-880c-ac41f9192a8e",
"prevId": "00000000-0000-0000-0000-000000000000",
"version": "7",
"dialect": "postgresql",
"tables": {
"public.guildApps": {
"name": "guildApps",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "serial",
"primaryKey": true,
"notNull": true
},
"userID": {
"name": "userID",
"type": "text",
"primaryKey": false,
"notNull": true
},
"uuid": {
"name": "uuid",
"type": "text",
"primaryKey": false,
"notNull": true
}
},
"indexes": {},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {}
},
"public.settings": {
"name": "settings",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "serial",
"primaryKey": true,
"notNull": true
},
"name": {
"name": "name",
"type": "text",
"primaryKey": false,
"notNull": true
},
"value": {
"name": "value",
"type": "text",
"primaryKey": false,
"notNull": true
}
},
"indexes": {},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {}
},
"public.staffApps": {
"name": "staffApps",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "serial",
"primaryKey": true,
"notNull": true
},
"userID": {
"name": "userID",
"type": "text",
"primaryKey": false,
"notNull": true
},
"uuid": {
"name": "uuid",
"type": "text",
"primaryKey": false,
"notNull": true
}
},
"indexes": {},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {}
},
"public.verifies": {
"name": "verifies",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "serial",
"primaryKey": true,
"notNull": true
},
"userID": {
"name": "userID",
"type": "text",
"primaryKey": false,
"notNull": true
},
"uuid": {
"name": "uuid",
"type": "text",
"primaryKey": false,
"notNull": true
}
},
"indexes": {},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {}
},
"public.waitingLists": {
"name": "waitingLists",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "serial",
"primaryKey": true,
"notNull": true
},
"userID": {
"name": "userID",
"type": "text",
"primaryKey": false,
"notNull": true
},
"uuid": {
"name": "uuid",
"type": "text",
"primaryKey": false,
"notNull": true
},
"timestamp": {
"name": "timestamp",
"type": "bigint",
"primaryKey": false,
"notNull": true
}
},
"indexes": {},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {}
}
},
"enums": {},
"schemas": {},
"sequences": {},
"_meta": {
"columns": {},
"schemas": {},
"tables": {}
}
}

View File

@@ -0,0 +1,13 @@
{
"version": "7",
"dialect": "postgresql",
"entries": [
{
"idx": 0,
"version": "7",
"when": 1727898828198,
"tag": "0000_shocking_gladiator",
"breakpoints": true
}
]
}

32
src/db/schema.ts Normal file
View File

@@ -0,0 +1,32 @@
import { bigint, pgTable, serial, text } from "drizzle-orm/pg-core"
export const verifies = pgTable("verifies", {
id: serial("id").primaryKey(),
userID: text("userID").notNull(),
uuid: text("uuid").notNull()
})
export const guildApps = pgTable("guildApps", {
id: serial("id").primaryKey(),
userID: text("userID").notNull(),
uuid: text("uuid").notNull()
})
export const staffApps = pgTable("staffApps", {
id: serial("id").primaryKey(),
userID: text("userID").notNull(),
uuid: text("uuid").notNull()
})
export const waitingLists = pgTable("waitingLists", {
id: serial("id").primaryKey(),
userID: text("userID").notNull(),
uuid: text("uuid").notNull(),
timestamp: bigint("timestamp", { mode: "number" }).notNull()
})
export const settings = pgTable("settings", {
id: serial("id").primaryKey(),
name: text("name").notNull(),
value: text("value").notNull()
})

View File

@@ -1,20 +0,0 @@
import Sequelize, { InferAttributes, InferCreationAttributes, Model } from "sequelize"
import { sequelize } from "utils/Illegitimate.js"
interface GuildApp extends Model<InferAttributes<GuildApp>, InferCreationAttributes<GuildApp>> {
userID: string
uuid: string
}
const tag = sequelize.define<GuildApp>("guildApp", {
userID: {
type: Sequelize.STRING,
allowNull: false
},
uuid: {
type: Sequelize.STRING,
allowNull: false
}
})
export default tag

View File

@@ -1,20 +0,0 @@
import Sequelize, { InferAttributes, InferCreationAttributes, Model } from "sequelize"
import { sequelize } from "utils/Illegitimate.js"
interface Settings extends Model<InferAttributes<Settings>, InferCreationAttributes<Settings>> {
name: string
value: string
}
const tag = sequelize.define<Settings>("settings", {
name: {
type: Sequelize.STRING,
allowNull: false
},
value: {
type: Sequelize.STRING,
allowNull: false
}
})
export default tag

View File

@@ -1,20 +0,0 @@
import Sequelize, { InferAttributes, InferCreationAttributes, Model } from "sequelize"
import { sequelize } from "utils/Illegitimate.js"
interface StaffApp extends Model<InferAttributes<StaffApp>, InferCreationAttributes<StaffApp>> {
userID: string
uuid: string
}
const tag = sequelize.define<StaffApp>("staffApp", {
userID: {
type: Sequelize.STRING,
allowNull: false
},
uuid: {
type: Sequelize.STRING,
allowNull: false
}
})
export default tag

View File

@@ -1,20 +0,0 @@
import Sequelize, { InferAttributes, InferCreationAttributes, Model } from "sequelize"
import { sequelize } from "utils/Illegitimate.js"
interface Verify extends Model<InferAttributes<Verify>, InferCreationAttributes<Verify>> {
userID: string
uuid: string
}
const tag = sequelize.define<Verify>("verify", {
userID: {
type: Sequelize.STRING,
allowNull: false
},
uuid: {
type: Sequelize.STRING,
allowNull: false
}
})
export default tag

View File

@@ -1,25 +0,0 @@
import Sequelize, { InferAttributes, InferCreationAttributes, Model } from "sequelize"
import { sequelize } from "utils/Illegitimate.js"
interface WaitingList extends Model<InferAttributes<WaitingList>, InferCreationAttributes<WaitingList>> {
userID: string
uuid: string
timestamp: number
}
const tag = sequelize.define<WaitingList>("waitingList", {
userID: {
type: Sequelize.STRING,
allowNull: false
},
uuid: {
type: Sequelize.STRING,
allowNull: false
},
timestamp: {
type: Sequelize.BIGINT,
allowNull: false
}
})
export default tag

View File

@@ -33,7 +33,7 @@ export class ExtendedClient extends Client {
async start() {
let token: string
if (process.env.NODE_ENV === "dev" && process.env.TYPESCRIPT === "true") {
console.log(color("Running in development mode. [ts-node]", "lavender"))
console.log(color("Running in development mode. [tsx]", "lavender"))
token = env.dev.devtoken
autoDeployCommands("ts", this)
} else if (process.env.NODE_ENV === "dev" && !process.env.TYPESCRIPT) {

View File

@@ -5,23 +5,17 @@ import { color } from "utils/functions/colors.js"
// import { connect } from "mongoose"
import { Player } from "discord-player"
import { YoutubeiExtractor } from "discord-player-youtubei"
import { Sequelize } from "sequelize"
// import { Sequelize } from "sequelize"
import { MissingEnvVarsError } from "./Classes.js"
import loadAllEvents from "./Events/loadevents.js"
const client = new Client()
const redis = new Redis(env.prod.redisURI)
const player = new Player(client)
let sequelize: Sequelize
if (process.env.NODE_ENV === "dev") {
sequelize = new Sequelize({
dialect: "sqlite",
storage: "dev/db.sqlite"
})
} else {
sequelize = new Sequelize(env.prod.postgresURI, { dialect: "postgres" })
}
// const sequelize = new Sequelize({
// dialect: "sqlite",
// storage: "dev/db.sqlite"
// })
let ft: "js" | "ts"
if (process.env.NODE_ENV === "dev" && process.env.TYPESCRIPT === "true") {
@@ -46,11 +40,11 @@ class Illegitimate {
redis.on("ready", () => {
console.log(color("Connected to Redis", "green"))
})
if (process.env.NODE_ENV === "dev") {
sequelize.sync().then(() => {
console.log(color("Synced the db [dev]", "green"))
})
}
// if (process.env.NODE_ENV === "dev") {
// sequelize.sync({ logging: false }).then(() => {
// console.log(color("Synced the db [dev]", "green"))
// })
// }
// connect(env.prod.mongoURI, {}).then(() => {
// console.log(color("Connected to MongoDB", "green"))
// })
@@ -85,4 +79,4 @@ class Illegitimate {
}
}
export { client, Illegitimate, redis, sequelize }
export { client, Illegitimate, redis }