Merge branch 'dev' into 'main'

Dev

See merge request illegitimate/illegitimate-bot!344
This commit is contained in:
2025-06-01 20:51:44 +02:00
19 changed files with 106 additions and 70 deletions

View File

@@ -6,13 +6,13 @@ import { log } from "../src/utils/Logger"
const rest = new REST({ version: "10" }).setToken(env.dev.DEVTOKEN) const rest = new REST({ version: "10" }).setToken(env.dev.DEVTOKEN)
const [error] = await tryCatch(deleteCommands()) const [error] = await tryCatch(deleteCommands())
if (error) log(error, "error") if (error) log.error(error)
async function deleteCommands() { async function deleteCommands() {
log("Started deleting application (/) commands.", "info") log.info("Started deleting application (/) commands.")
await rest.put( await rest.put(
Routes.applicationGuildCommands(env.dev.DEVID, env.dev.GUILDID), Routes.applicationGuildCommands(env.dev.DEVID, env.dev.GUILDID),
{ body: [] } { body: [] }
) )
log("Successfully deleted application (/) commands.", "info") log.info("Successfully deleted application (/) commands.")
} }

View File

@@ -20,19 +20,19 @@ for (const file of contentMenuCommands) {
} }
const [error] = await tryCatch(updateCommands()) const [error] = await tryCatch(updateCommands())
if (error) log(error, "error") if (error) log.error(error)
async function updateCommands() { async function updateCommands() {
log(`Started refreshing ${commands.length} application (/) commands.`, "info", { type: "preset", color: "green" }) log.custom(`Started refreshing ${commands.length} application (/) commands.`, "info", { type: "preset", color: "green" })
const commandsString = commands.map(command => " " + command.name) const commandsString = commands.map(command => " " + command.name)
log(commandsString.join("\n"), "info", { type: "preset", color: "lavender" }) log.custom(commandsString.join("\n"), "info", { type: "preset", color: "lavender" })
await rest.put( await rest.put(
Routes.applicationCommands(env.dev.CLIENTID), Routes.applicationCommands(env.dev.CLIENTID),
{ body: commands } { body: commands }
).then(() => { ).then(() => {
log(`Successfully reloaded ${commands.length} application (/) commands.`, "info", { type: "preset", color: "green" }) log.custom(`Successfully reloaded ${commands.length} application (/) commands.`, "info", { type: "preset", color: "green" })
process.exit(0) process.exit(0)
}) })
} }

View File

@@ -24,16 +24,16 @@ for (const file of contentMenuCommands) {
} }
const [error] = await tryCatch(updateCommands()) const [error] = await tryCatch(updateCommands())
if (error) log(error, "error") if (error) log.error(error)
async function updateCommands() { async function updateCommands() {
log(`Started refreshing ${commands.length} application (/) commands.`, "info") log.info(`Started refreshing ${commands.length} application (/) commands.`)
await rest.put( await rest.put(
Routes.applicationGuildCommands(env.dev.DEVID, env.dev.GUILDID), Routes.applicationGuildCommands(env.dev.DEVID, env.dev.GUILDID),
{ body: commands } { body: commands }
).then(() => { ).then(() => {
log(`Successfully reloaded ${commands.length} application (/) commands.`, "info") log.info(`Successfully reloaded ${commands.length} application (/) commands.`)
process.exit(0) process.exit(0)
}) })
} }

View File

@@ -71,12 +71,12 @@ const cmd: SubCommand = async ({ interaction }) => {
for (const gmember of guildMembers) { for (const gmember of guildMembers) {
const memberData = verifiedUsers.find(user => user.userID === gmember.id) const memberData = verifiedUsers.find(user => user.userID === gmember.id)
log(`Updating ${gmember.member.user.username} [${i}/${guildMembers.length}]`, "info", { type: "preset", color: "green" }) log.custom(`Updating ${gmember.member.user.username} [${i}/${guildMembers.length}]`, "info", { type: "preset", color: "green" })
i++ i++
if (!memberData) { if (!memberData) {
if (gmember.member.user.bot) { if (gmember.member.user.bot) {
log(` Skipped bot [${gmember.member.user.username}]`, "info", { type: "preset", color: "lavender" }) log.custom(` Skipped bot [${gmember.member.user.username}]`, "info", { type: "preset", color: "lavender" })
continue continue
} }
const roles = roleManage("defaultnoverify") const roles = roleManage("defaultnoverify")
@@ -85,7 +85,7 @@ const cmd: SubCommand = async ({ interaction }) => {
await gmember.member.setNickname(`${gmember.member.user.username} (X)`, "Updating all discord members").catch(() => { await gmember.member.setNickname(`${gmember.member.user.username} (X)`, "Updating all discord members").catch(() => {
// Do nothing // Do nothing
}) })
log(`${gmember.member.user.username} [X]`, "info", { type: "preset", color: "lavender" }) log.custom(`${gmember.member.user.username} [X]`, "info", { type: "preset", color: "lavender" })
} else { } else {
const uuid = memberData.uuid const uuid = memberData.uuid
const ign = await getIGN(uuid) const ign = await getIGN(uuid)
@@ -94,10 +94,10 @@ const cmd: SubCommand = async ({ interaction }) => {
const roles = roleManage("default") const roles = roleManage("default")
await gmember.member.roles.remove(roles.rolesToRemove, "Updating all discord members") await gmember.member.roles.remove(roles.rolesToRemove, "Updating all discord members")
await gmember.member.roles.add(roles.rolesToAdd, "Updating all discord members") await gmember.member.roles.add(roles.rolesToAdd, "Updating all discord members")
log(`${gmember.member.user.username} [Default]`, "info", { type: "preset", color: "lavender" }) log.custom(`${gmember.member.user.username} [Default]`, "info", { type: "preset", color: "lavender" })
} else if (guildMemberIDs.includes(memberData!.uuid)) { } else if (guildMemberIDs.includes(memberData!.uuid)) {
const guildMemberRank = hypixelGuildMembers.find(gmember => gmember.uuid === memberData!.uuid)!.rank const guildMemberRank = hypixelGuildMembers.find(gmember => gmember.uuid === memberData!.uuid)!.rank
log(" Updating roles for " + gmember.member.user.username, "info", { type: "preset", color: "lavender" }) log.custom(" Updating roles for " + gmember.member.user.username, "info", { type: "preset", color: "lavender" })
const rank = getGuildRank(guildMemberRank) const rank = getGuildRank(guildMemberRank)
if (rank) { if (rank) {
@@ -111,7 +111,7 @@ const cmd: SubCommand = async ({ interaction }) => {
} }
} }
log("Successfully updated all roles.", "info") log.info("Successfully updated all roles.")
await channel.send({ await channel.send({
embeds: [{ embeds: [{

View File

@@ -26,7 +26,7 @@ export default {
})) }))
await interaction.respond(results.slice(0, 25)).catch(err => { await interaction.respond(results.slice(0, 25)).catch(err => {
log(err, "error") log.error(err)
}) })
} }
} as IAutocomplete } as IAutocomplete

View File

@@ -1,5 +1,5 @@
import { ActionRowBuilder, ButtonBuilder, ButtonStyle, TextChannel } from "discord.js" import { ActionRowBuilder, ButtonBuilder, ButtonStyle, TextChannel } from "discord.js"
import { getGuildApp, removeVerify } from "src/drizzle/functions" import { getGuildApp, removeGuildApp } from "src/drizzle/functions"
import { addWaitingList, getWaitingLists, removeWaitingList } from "src/drizzle/functions" import { addWaitingList, getWaitingLists, removeWaitingList } from "src/drizzle/functions"
import { embedColor, hypixelGuildID, waitingListChannel, waitingListMessage } from "~/config/options" import { embedColor, hypixelGuildID, waitingListChannel, waitingListMessage } from "~/config/options"
import { waitingListRole } from "~/config/roles" import { waitingListRole } from "~/config/roles"
@@ -21,8 +21,8 @@ export default {
const embed = message.embeds[0] const embed = message.embeds[0]
const applicantId = embed.footer!.text.split(" ")[1] const applicantId = embed.footer!.text.split(" ")[1]
const applicant = await guild.members.fetch(applicantId) const [, applicant] = await tryCatch(guild.members.fetch(applicantId))
const applicantUsername = applicant.user.username const applicantUsername = applicant?.user.username
await message.edit({ await message.edit({
components: [ components: [
@@ -46,6 +46,17 @@ export default {
] ]
}) })
if (!applicant) {
await interaction.editReply({
embeds: [{
description: "Aplication has left the server and cannot be notified.",
color: embedColor
}]
})
await removeGuildApp({ userID: applicantId })
return
}
await applicant.send({ await applicant.send({
embeds: [{ embeds: [{
description: "Your application for the Illegitimate guild has been accepted.\n\n" + description: "Your application for the Illegitimate guild has been accepted.\n\n" +
@@ -64,8 +75,8 @@ export default {
timestamp: time timestamp: time
}) })
await removeGuildApp({ userID: applicantId, uuid: applicantUUID })
await applicant.roles.add(waitingListRole) await applicant.roles.add(waitingListRole)
await removeVerify({ userID: applicantId })
await interaction.editReply({ await interaction.editReply({
embeds: [{ embeds: [{
@@ -85,7 +96,7 @@ export default {
if (process.env.NODE_ENV === "dev") return if (process.env.NODE_ENV === "dev") return
const [error] = await tryCatch(updateWaitingList()) const [error] = await tryCatch(updateWaitingList())
if (error) return log("Error while trying to update waiting list.", "error") if (error) return log.error("Error while trying to update waiting list.")
async function updateWaitingList() { async function updateWaitingList() {
const channel = guild.channels.cache.get(waitingListChannel) as TextChannel const channel = guild.channels.cache.get(waitingListChannel) as TextChannel

View File

@@ -10,7 +10,7 @@ async function guildWeekly() {
const channel = client.channels.cache.get(guildLogChannel) as TextChannel const channel = client.channels.cache.get(guildLogChannel) as TextChannel
if (!channel) { if (!channel) {
log("Guild log channel not found", "error") log.error("Guild log channel not found")
return return
} }

View File

@@ -3,7 +3,7 @@ import { log } from "~/utils/Logger"
export const once = true export const once = true
const event: Event<"ready"> = (client) => { const event: Event<"ready"> = (client) => {
log("Logged in as " + client.user!.tag + "!", "info", { type: "preset", color: "green" }) log.custom("Logged in as " + client.user!.tag + "!", "info", { type: "preset", color: "green" })
} }
export default event export default event

View File

@@ -73,33 +73,33 @@ export default async function autoDeployCommands(fileType: FileType, client: Ext
// }).join("\n") // }).join("\n")
if (JSON.stringify(commandData) === JSON.stringify(currentCommandsData)) { if (JSON.stringify(commandData) === JSON.stringify(currentCommandsData)) {
log("Commands are up to date.", "info", { type: "preset", color: "green" }) log.custom("Commands are up to date.", "info", { type: "preset", color: "green" })
// log(nc, "info", { type: "preset", color: "lavender" }) // log.custom(nc, "info", { type: "preset", color: "lavender" })
nc.forEach(c => log(c, "info", { type: "preset", color: "lavender" })) nc.forEach(c => log.custom(c, "info", { type: "preset", color: "lavender" }))
} else { } else {
log("Commands are not up to date.", "info", { type: "preset", color: "red" }) log.custom("Commands are not up to date.", "info", { type: "preset", color: "red" })
if (currentCommands.size === 0) { if (currentCommands.size === 0) {
for (const cmd of commands) { for (const cmd of commands) {
await guildclient.commands.create(cmd) await guildclient.commands.create(cmd)
} }
// log(nc, "info", { type: "preset", color: "lavender" }) // log.custom(nc, "info", { type: "preset", color: "lavender" })
nc.forEach(c => log(c, "info", { type: "preset", color: "lavender" })) nc.forEach(c => log.custom(c, "info", { type: "preset", color: "lavender" }))
log("All commands were registered.", "info", { type: "preset", color: "green" }) log.custom("All commands were registered.", "info", { type: "preset", color: "green" })
return return
} }
for (const cmd of currentCommandsData) { for (const cmd of currentCommandsData) {
if (!commandData.find(c => c.name === cmd.name)) { if (!commandData.find(c => c.name === cmd.name)) {
await guildclient.commands.delete(currentCommands.find(c => c.name === cmd.name)!.id) await guildclient.commands.delete(currentCommands.find(c => c.name === cmd.name)!.id)
log(" " + cmd.name + " was unregistered.", "info", { type: "preset", color: "red" }) log.custom(" " + cmd.name + " was unregistered.", "info", { type: "preset", color: "red" })
} }
} }
for (const cmd of commandData) { for (const cmd of commandData) {
if (!currentCommandsData.find(c => c.name === cmd.name)) { if (!currentCommandsData.find(c => c.name === cmd.name)) {
await guildclient.commands.create(commands.find(c => c.name === cmd.name)!) await guildclient.commands.create(commands.find(c => c.name === cmd.name)!)
log(" " + cmd.name + " was registered.", "info", { type: "preset", color: "lavender" }) log.custom(" " + cmd.name + " was registered.", "info", { type: "preset", color: "lavender" })
} }
} }
@@ -111,13 +111,13 @@ export default async function autoDeployCommands(fileType: FileType, client: Ext
if (JSON.stringify(cmd) !== JSON.stringify(currentCommandData)) { if (JSON.stringify(cmd) !== JSON.stringify(currentCommandData)) {
await guildclient.commands.edit(currentCommand.id, cmd) await guildclient.commands.edit(currentCommand.id, cmd)
log(" " + cmd.name + " was updated.", "info", { type: "preset", color: "lavender" }) log.custom(" " + cmd.name + " was updated.", "info", { type: "preset", color: "lavender" })
} }
} }
log("-------------", "info", { type: "preset", color: "lavender" }) log.custom("-------------", "info", { type: "preset", color: "lavender" })
// log(nc, "info", { type: "preset", color: "lavender" }) // log.custom(nc, "info", { type: "preset", color: "lavender" })
nc.forEach(c => log(c, "info", { type: "preset", color: "lavender" })) nc.forEach(c => log.custom(c, "info", { type: "preset", color: "lavender" }))
} }
}) })
} }

View File

@@ -33,15 +33,15 @@ export class ExtendedClient extends Client {
async start() { async start() {
let token: string let token: string
if (process.env.NODE_ENV === "dev" && process.env.TYPESCRIPT === "true") { if (process.env.NODE_ENV === "dev" && process.env.TYPESCRIPT === "true") {
log("Running in development mode. [tsx]", "info", { type: "preset", color: "lavender" }) log.custom("Running in development mode. [tsx]", "info", { type: "preset", color: "lavender" })
token = env.dev.DEVTOKEN token = env.dev.DEVTOKEN
autoDeployCommands("ts", this) autoDeployCommands("ts", this)
} else if (process.env.NODE_ENV === "dev" && !process.env.TYPESCRIPT) { } else if (process.env.NODE_ENV === "dev" && !process.env.TYPESCRIPT) {
log("Running in development mode.", "info", { type: "preset", color: "lavender" }) log.custom("Running in development mode.", "info", { type: "preset", color: "lavender" })
token = env.dev.DEVTOKEN token = env.dev.DEVTOKEN
autoDeployCommands("js", this) autoDeployCommands("js", this)
} else { } else {
log("Running in production mode.", "info", { type: "preset", color: "green" }) log.custom("Running in production mode.", "info", { type: "preset", color: "green" })
token = env.prod.TOKEN token = env.prod.TOKEN
} }

View File

@@ -25,7 +25,7 @@ export default async function loadAutocompleteEvents(client: Client, ft: FileTyp
const autocomplete = client.autocomplete.get(interaction.commandName) const autocomplete = client.autocomplete.get(interaction.commandName)
if (!autocomplete) { if (!autocomplete) {
log(`No autocomplete matching ${interaction.commandName} was found.`, "error") log.error(`No autocomplete matching ${interaction.commandName} was found.`)
return return
} }
@@ -45,6 +45,6 @@ export default async function loadAutocompleteEvents(client: Client, ft: FileTyp
}] }]
}) })
} }
log(error, "error") log.error(error)
}) })
} }

View File

@@ -32,7 +32,7 @@ export default async function loadButtonEvents(client: Client, ft: FileType) {
content: "Button logic not implemented. This is most likely an old button", content: "Button logic not implemented. This is most likely an old button",
flags: MessageFlags.Ephemeral flags: MessageFlags.Ephemeral
}) })
log(`No event matching ${interaction.customId} was found.`, "error") log.error(`No event matching ${interaction.customId} was found.`)
return return
} }
@@ -53,7 +53,7 @@ export default async function loadButtonEvents(client: Client, ft: FileType) {
}) })
} }
log(error, "error") log.error(error)
if (!interaction.deferred) { if (!interaction.deferred) {
await interaction.reply({ await interaction.reply({
embeds: [{ embeds: [{
@@ -65,7 +65,7 @@ export default async function loadButtonEvents(client: Client, ft: FileType) {
} else { } else {
await interaction.editReply({ await interaction.editReply({
embeds: [{ embeds: [{
description: "There was an error while executing this button! 2", description: "There was an error while executing this button!",
color: embedColor color: embedColor
}] }]
}) })

View File

@@ -30,7 +30,7 @@ export default async function loadSlashCommandsEvents(client: Client, ft: FileTy
content: "Command logic not implemented. This is most likely an old command", content: "Command logic not implemented. This is most likely an old command",
flags: MessageFlags.Ephemeral flags: MessageFlags.Ephemeral
}) })
log(`No command matching ${interaction.commandName} was found.`, "error") log.error(`No command matching ${interaction.commandName} was found.`)
return return
} }
@@ -51,7 +51,7 @@ export default async function loadSlashCommandsEvents(client: Client, ft: FileTy
}) })
} }
log(error, "error") log.error(error)
if (!interaction.deferred) { if (!interaction.deferred) {
await interaction.reply({ await interaction.reply({
embeds: [{ embeds: [{

View File

@@ -30,7 +30,7 @@ export default async function loadContextMenuEvents(client: Client, ft: FileType
content: "Command logic not implemented. This is most likely an old command", content: "Command logic not implemented. This is most likely an old command",
flags: MessageFlags.Ephemeral flags: MessageFlags.Ephemeral
}) })
log(`No command matching ${interaction.commandName} was found.`, "error") log.error(`No command matching ${interaction.commandName} was found.`)
return return
} }
@@ -51,7 +51,7 @@ export default async function loadContextMenuEvents(client: Client, ft: FileType
}) })
} }
log(error, "error") log.error(error)
if (!interaction.deferred) { if (!interaction.deferred) {
await interaction.reply({ await interaction.reply({
embeds: [{ embeds: [{

View File

@@ -9,11 +9,11 @@ import loadEvents from "./events"
import loadModalEvents from "./modal" import loadModalEvents from "./modal"
export default async function loadAllEvents(client: Client, ft: "js" | "ts") { export default async function loadAllEvents(client: Client, ft: "js" | "ts") {
await loadEvents(client, ft).then(() => log("Events loaded", "info")) await loadEvents(client, ft).then(() => log.info("Events loaded"))
await loadButtonEvents(client, ft).then(() => log("Button events loaded", "info")) await loadButtonEvents(client, ft).then(() => log.info("Button events loaded"))
await loadSlashCommandsEvents(client, ft).then(() => log("Slash commands loaded", "info")) await loadSlashCommandsEvents(client, ft).then(() => log.info("Slash commands loaded"))
await loadContextMenuEvents(client, ft).then(() => log("Context menu events loaded", "info")) await loadContextMenuEvents(client, ft).then(() => log.info("Context menu events loaded"))
await loadModalEvents(client, ft).then(() => log("Modal events loaded", "info")) await loadModalEvents(client, ft).then(() => log.info("Modal events loaded"))
await loadAutocompleteEvents(client, ft).then(() => log("Autocomplete events loaded", "info")) await loadAutocompleteEvents(client, ft).then(() => log.info("Autocomplete events loaded"))
await loadCronEvents(ft).then(() => log("Cron events loaded", "info")) await loadCronEvents(ft).then(() => log.info("Cron events loaded"))
} }

View File

@@ -29,7 +29,7 @@ export default async function loadModalEvents(client: Client, ft: FileType) {
content: "Modal logic not implemented. This is most likely an old modal", content: "Modal logic not implemented. This is most likely an old modal",
flags: MessageFlags.Ephemeral flags: MessageFlags.Ephemeral
}) })
log(`No modal matching ${interaction.customId} was found.`, "error") log.error(`No modal matching ${interaction.customId} was found.`)
return return
} }
@@ -50,7 +50,7 @@ export default async function loadModalEvents(client: Client, ft: FileType) {
}) })
} }
log(error, "error") log.error(error)
if (!interaction.deferred) { if (!interaction.deferred) {
await interaction.reply({ await interaction.reply({
embeds: [{ embeds: [{

View File

@@ -25,7 +25,7 @@ export default async function logToChannel(channel: Channel, message: MessageCre
} }
if (!logChannel) { if (!logChannel) {
log(`[ERROR] Could not find channel used for ${channel} logging.`, "error") log.error(`[ERROR] Could not find channel used for ${channel} logging.`)
return return
} }

View File

@@ -24,7 +24,7 @@ class Illegitimate {
private async databases() { private async databases() {
redis.on("ready", () => { redis.on("ready", () => {
log("Connected to Redis", "info", { type: "preset", color: "green" }) log.custom("Connected to Redis", "info", { type: "preset", color: "green" })
}) })
} }

View File

@@ -28,17 +28,32 @@ type CustomColorProps = {
color: string color: string
} }
export function log(m: any, t: LogType, c?: CustomColorProps): void { const date = new Date()
const date = new Date() const time = logTimeFormatter(date)
const time = logTimeFormatter(date)
const logType = AllLogs[t].m
const logColor = AllLogs[t].c
const message = `${time} - [${logType}] | ${m}` function info(msg: any) {
if (!c) { const message = `${time} - [${AllLogs.info.m}] | ${msg}`
console.log(cc(message, logColor)) console.log(cc(message, AllLogs.info.c))
return }
}
function warn(msg: any) {
const message = `${time} - [${AllLogs.warn.m}] | ${msg}`
console.log(cc(message, AllLogs.warn.c))
}
function error(msg: any) {
const message = `${time} - [${AllLogs.error.m}] | ${msg}`
console.error(cc(message, AllLogs.error.c))
}
function critical(msg: any) {
const message = `${time} - [${AllLogs.critical.m}] | ${msg}`
console.error(cc(message, AllLogs.critical.c))
}
function custom(msg: any, type: LogType, c: CustomColorProps) {
const log = AllLogs[type].m
const message = `${time} - [${log}] | ${msg}`
if (c.type === "preset") { if (c.type === "preset") {
const color = colors[c.color] const color = colors[c.color]
@@ -51,3 +66,13 @@ export function log(m: any, t: LogType, c?: CustomColorProps): void {
function cc(text: string, color: string) { function cc(text: string, color: string) {
return chalk.hex(color)(text) return chalk.hex(color)(text)
} }
const log = {
info,
warn,
error,
critical,
custom
}
export { cc, log }