Merge branch 'dev' into 'main'

Dev

See merge request illegitimate/illegitimate-bot!362
This commit is contained in:
2025-08-21 16:55:43 +02:00
41 changed files with 143 additions and 88 deletions

View File

@@ -8,6 +8,7 @@ export default {
description: "Anime subcommands", description: "Anime subcommands",
public: true, public: true,
dev: false, dev: false,
requiredRole: "none",
data: new SlashCommandBuilder() data: new SlashCommandBuilder()
.setName("anime") .setName("anime")

View File

@@ -9,6 +9,7 @@ export default {
description: "Ban a user", description: "Ban a user",
dev: false, dev: false,
public: false, public: false,
requiredRole: "admin",
data: new SlashCommandBuilder() data: new SlashCommandBuilder()
.setName("ban") .setName("ban")
@@ -55,12 +56,6 @@ export default {
const mod = await interaction.guild!.members.fetch(interaction.user.id) const mod = await interaction.guild!.members.fetch(interaction.user.id)
const memberRoles = member.roles.cache.map(role => role.id) const memberRoles = member.roles.cache.map(role => role.id)
const modRoles = mod.roles.cache.map(role => role.id)
if (!modRoles.includes(admin)) {
await interaction.editReply("You do not have permission to use this command.")
return
}
if (interaction.guild!.members.me!.roles.highest.position <= member.roles.highest.position) { if (interaction.guild!.members.me!.roles.highest.position <= member.roles.highest.position) {
await interaction.editReply("I cannot ban this member.") await interaction.editReply("I cannot ban this member.")

View File

@@ -11,6 +11,7 @@ export default {
description: "Get information about the bot", description: "Get information about the bot",
dev: false, dev: false,
public: true, public: true,
requiredRole: "none",
data: new SlashCommandBuilder() data: new SlashCommandBuilder()
.setName("botinfo") .setName("botinfo")

View File

@@ -10,6 +10,7 @@ export default {
description: "Check a player's stats.", description: "Check a player's stats.",
dev: false, dev: false,
public: true, public: true,
requiredRole: "none",
data: new SlashCommandBuilder() data: new SlashCommandBuilder()
.setName("check") .setName("check")

View File

@@ -8,6 +8,7 @@ export default {
description: "Clears messages", description: "Clears messages",
dev: false, dev: false,
public: false, public: false,
requiredRole: "admin",
data: new SlashCommandBuilder() data: new SlashCommandBuilder()
.setName("clear") .setName("clear")

View File

@@ -8,6 +8,7 @@ export default {
description: "Configure the bot", description: "Configure the bot",
dev: false, dev: false,
public: false, public: false,
requiredRole: "superadmin",
data: new SlashCommandBuilder() data: new SlashCommandBuilder()
.setName("config") .setName("config")

View File

@@ -9,6 +9,7 @@ export default {
description: "Find a person by the ign", description: "Find a person by the ign",
dev: false, dev: false,
public: false, public: false,
requiredRole: "helper",
data: new SlashCommandBuilder() data: new SlashCommandBuilder()
.setName("find") .setName("find")

View File

@@ -11,6 +11,7 @@ export default {
description: "Force unverify a user", description: "Force unverify a user",
dev: false, dev: false,
public: false, public: false,
requiredRole: "superadmin",
data: new SlashCommandBuilder() data: new SlashCommandBuilder()
.setName("forceunverify") .setName("forceunverify")

View File

@@ -12,6 +12,7 @@ export default {
description: "Force update the user", description: "Force update the user",
dev: false, dev: false,
public: false, public: false,
requiredRole: "helper",
data: new SlashCommandBuilder() data: new SlashCommandBuilder()
.setName("forceupdate") .setName("forceupdate")

View File

@@ -13,6 +13,7 @@ export default {
description: "Force verify a user.", description: "Force verify a user.",
dev: false, dev: false,
public: false, public: false,
requiredRole: "admin",
data: new SlashCommandBuilder() data: new SlashCommandBuilder()
.setName("forceverify") .setName("forceverify")

View File

@@ -11,6 +11,7 @@ export default {
dev: false, dev: false,
public: true, public: true,
subcommands: true, subcommands: true,
requiredRole: "none",
data: new SlashCommandBuilder() data: new SlashCommandBuilder()
.setName("guild") .setName("guild")

View File

@@ -7,6 +7,7 @@ export default {
description: "Help command", description: "Help command",
dev: false, dev: false,
public: true, public: true,
requiredRole: "none",
data: new SlashCommandBuilder() data: new SlashCommandBuilder()
.setName("help") .setName("help")

View File

@@ -9,6 +9,7 @@ export default {
description: "Kick a member from the server.", description: "Kick a member from the server.",
dev: false, dev: false,
public: false, public: false,
requiredRole: "helper",
data: new SlashCommandBuilder() data: new SlashCommandBuilder()
.setName("kick") .setName("kick")
@@ -34,12 +35,6 @@ export default {
const reason = interaction.options.getString("reason") ?? "No reason provided." const reason = interaction.options.getString("reason") ?? "No reason provided."
const mod = await interaction.guild!.members.fetch(interaction.user.id) const mod = await interaction.guild!.members.fetch(interaction.user.id)
const memberRoles = member.roles.cache.map(role => role.id) const memberRoles = member.roles.cache.map(role => role.id)
const modRoles = mod.roles.cache.map(role => role.id)
if (!modRoles.includes(helper) && !modRoles.includes(admin)) {
await interaction.editReply("You do not have permission to use this command.")
return
}
if (member.id === interaction.applicationId) { if (member.id === interaction.applicationId) {
await interaction.editReply("I cannot kick myself.") await interaction.editReply("I cannot kick myself.")

View File

@@ -7,6 +7,7 @@ export default {
description: "Get the bot's ping.", description: "Get the bot's ping.",
dev: false, dev: false,
public: true, public: true,
requiredRole: "none",
data: new SlashCommandBuilder() data: new SlashCommandBuilder()
.setName("ping") .setName("ping")

View File

@@ -8,6 +8,7 @@ export default {
description: "Shows pp size", description: "Shows pp size",
public: true, public: true,
dev: false, dev: false,
requiredRole: "none",
data: new SlashCommandBuilder() data: new SlashCommandBuilder()
.setName("pp") .setName("pp")

View File

@@ -10,6 +10,7 @@ export default {
description: "Remove a person on the waiting list.", description: "Remove a person on the waiting list.",
dev: false, dev: false,
public: false, public: false,
requiredRole: "helper",
data: new SlashCommandBuilder() data: new SlashCommandBuilder()
.setName("remove") .setName("remove")

View File

@@ -8,6 +8,7 @@ export default {
description: "Displays the requirements for the guild.", description: "Displays the requirements for the guild.",
dev: false, dev: false,
public: true, public: true,
requiredRole: "none",
data: new SlashCommandBuilder() data: new SlashCommandBuilder()
.setName("reqs") .setName("reqs")

View File

@@ -7,6 +7,7 @@ export default {
description: "Send a message to a channel.", description: "Send a message to a channel.",
dev: false, dev: false,
public: false, public: false,
requiredRole: "superadmin",
data: new SlashCommandBuilder() data: new SlashCommandBuilder()
.setName("send") .setName("send")

View File

@@ -8,6 +8,7 @@ export default {
description: "Set your nickname", description: "Set your nickname",
dev: false, dev: false,
public: false, public: false,
requiredRole: "admin",
data: new SlashCommandBuilder() data: new SlashCommandBuilder()
.setName("setnick") .setName("setnick")

View File

@@ -15,9 +15,10 @@ import { ICommand } from "~/typings"
export default { export default {
name: "setup", name: "setup",
description: "Used for setup of the bot.", description: "Used for setup of the bot.",
dev: true, dev: false,
public: false, public: false,
subcommands: true, subcommands: true,
requiredRole: "superadmin",
data: new SlashCommandBuilder() data: new SlashCommandBuilder()
.setName("setup") .setName("setup")

View File

@@ -17,6 +17,7 @@ export default {
description: "Set the slowmode of a channel.", description: "Set the slowmode of a channel.",
dev: false, dev: false,
public: false, public: false,
requiredRole: "admin",
data: new SlashCommandBuilder() data: new SlashCommandBuilder()
.setName("slowmode") .setName("slowmode")

View File

@@ -13,6 +13,7 @@ export default {
dev: false, dev: false,
public: false, public: false,
subcommands: true, subcommands: true,
requiredRole: "helper",
data: new SlashCommandBuilder() data: new SlashCommandBuilder()
.setName("staff") .setName("staff")

View File

@@ -10,6 +10,7 @@ export default {
description: "Times out a memeber", description: "Times out a memeber",
dev: false, dev: false,
public: false, public: false,
requiredRole: "helper",
data: new SlashCommandBuilder() data: new SlashCommandBuilder()
.setName("timeout") .setName("timeout")

View File

@@ -9,6 +9,7 @@ export default {
description: "Unban a user from the server", description: "Unban a user from the server",
dev: false, dev: false,
public: false, public: false,
requiredRole: "admin",
data: new SlashCommandBuilder() data: new SlashCommandBuilder()
.setName("unban") .setName("unban")

View File

@@ -12,6 +12,7 @@ export default {
description: "Update your guild rank.", description: "Update your guild rank.",
dev: false, dev: false,
public: true, public: true,
requiredRole: "none",
data: new SlashCommandBuilder() data: new SlashCommandBuilder()
.setName("update") .setName("update")

View File

@@ -9,6 +9,7 @@ export default {
description: "Get a player's UUID", description: "Get a player's UUID",
dev: false, dev: false,
public: true, public: true,
requiredRole: "none",
data: new SlashCommandBuilder() data: new SlashCommandBuilder()
.setName("uuid") .setName("uuid")

View File

@@ -12,6 +12,7 @@ export default {
description: "Verify yourself as a member of the server.", description: "Verify yourself as a member of the server.",
dev: false, dev: false,
public: true, public: true,
requiredRole: "none",
data: new SlashCommandBuilder() data: new SlashCommandBuilder()
.setName("verify") .setName("verify")

View File

@@ -9,6 +9,7 @@ export default {
description: "Get your user info", description: "Get your user info",
public: true, public: true,
dev: false, dev: false,
requiredRole: "none",
data: new SlashCommandBuilder() data: new SlashCommandBuilder()
.setName("whoami") .setName("whoami")

View File

@@ -9,6 +9,7 @@ export default {
description: "Get's the ign of a user.", description: "Get's the ign of a user.",
dev: false, dev: false,
public: false, public: false,
requiredRole: "helper",
data: new SlashCommandBuilder() data: new SlashCommandBuilder()
.setName("whois") .setName("whois")

View File

@@ -1,8 +0,0 @@
import { AutocompleteInteraction } from "discord.js"
import { ExtendedClient } from "~/utils/Client"
export interface IAutocomplete {
name: string
description: string
execute: (arg: { interaction: AutocompleteInteraction, client: ExtendedClient }) => Promise<void>
}

View File

@@ -1,8 +0,0 @@
import { ButtonInteraction } from "discord.js"
import { ExtendedClient } from "~/utils/Client"
export interface IButton {
name: string
description: string
execute: (arg: { interaction: ButtonInteraction, client: ExtendedClient }) => Promise<void>
}

View File

@@ -1,12 +0,0 @@
import { ChatInputCommandInteraction, SlashCommandBuilder } from "discord.js"
import { ExtendedClient as Client } from "~/utils/Client"
export interface ICommand {
name: string
description: string
dev?: boolean
public: boolean
subcommands?: boolean
data: SlashCommandBuilder
execute: (arg: { interaction: ChatInputCommandInteraction, client: Client }) => Promise<void>
}

View File

@@ -1,10 +0,0 @@
import { ContextMenuCommandBuilder, ContextMenuCommandInteraction } from "discord.js"
import { ExtendedClient } from "~/utils/Client"
export interface IContextMenu {
name: string
description: string
dev?: boolean
data: ContextMenuCommandBuilder
execute: (arg: { interaction: ContextMenuCommandInteraction, client: ExtendedClient }) => Promise<void>
}

56
src/typings/Discord.ts Normal file
View File

@@ -0,0 +1,56 @@
import {
AutocompleteInteraction,
ButtonInteraction,
ChatInputCommandInteraction,
ClientEvents,
ContextMenuCommandBuilder,
ContextMenuCommandInteraction,
ModalSubmitInteraction,
SlashCommandBuilder
} from "discord.js"
import { ExtendedClient } from "~/utils/Client"
export interface ICommand {
name: string
description: string
dev?: boolean
public: boolean
subcommands?: boolean
requiredRole?: "none" | "helper" | "admin" | "superadmin"
data: SlashCommandBuilder
execute: (arg: { interaction: ChatInputCommandInteraction, client: ExtendedClient }) => Promise<void>
}
export interface IContextMenu {
name: string
description: string
dev?: boolean
data: ContextMenuCommandBuilder
execute: (arg: { interaction: ContextMenuCommandInteraction, client: ExtendedClient }) => Promise<void>
}
export type SubCommand<T extends boolean = false> = (
arg: T extends true ? {
interaction: ChatInputCommandInteraction
client: ExtendedClient
} :
{
interaction: ChatInputCommandInteraction
}
) => Promise<void>
export interface IAutocomplete {
name: string
description: string
execute: (arg: { interaction: AutocompleteInteraction, client: ExtendedClient }) => Promise<void>
}
export interface IButton {
name: string
description: string
execute: (arg: { interaction: ButtonInteraction, client: ExtendedClient }) => Promise<void>
}
export interface IModal {
name: string
description: string
execute: (arg: { interaction: ModalSubmitInteraction, client: ExtendedClient }) => Promise<void>
}
export type Event<E extends keyof ClientEvents> = (...args: ClientEvents[E]) => void

View File

@@ -1,3 +0,0 @@
import { ClientEvents } from "discord.js"
export type Event<E extends keyof ClientEvents> = (...args: ClientEvents[E]) => void

View File

@@ -1,8 +0,0 @@
import { ModalSubmitInteraction } from "discord.js"
import { ExtendedClient } from "~/utils/Client"
export interface IModal {
name: string
description: string
execute: (arg: { interaction: ModalSubmitInteraction, client: ExtendedClient }) => Promise<void>
}

View File

@@ -1,14 +0,0 @@
import { ChatInputCommandInteraction } from "discord.js"
import { ExtendedClient } from "~/utils/Client"
type InteractionObject = {
interaction: ChatInputCommandInteraction
}
type ClientObject = {
client: ExtendedClient
}
type SubCommandObject<T extends boolean> = T extends true ? InteractionObject & ClientObject : InteractionObject
export type SubCommand<T extends boolean = false> = (arg: SubCommandObject<T>) => Promise<void>

View File

@@ -1,4 +1,4 @@
type TimeZonesArray = [ export type TimeZones = [
"Africa/Abidjan", "Africa/Abidjan",
"Africa/Accra", "Africa/Accra",
"Africa/Addis_Ababa", "Africa/Addis_Ababa",
@@ -427,6 +427,4 @@ type TimeZonesArray = [
"Pacific/Truk", "Pacific/Truk",
"Pacific/Wake", "Pacific/Wake",
"Pacific/Wallis" "Pacific/Wallis"
] ][number]
export type TimeZones = TimeZonesArray[number]

View File

@@ -1,11 +1,6 @@
export * from "./Autocomplete"
export * from "./Button"
export * from "./Command"
export * from "./ContextMenu"
export * from "./Cron" export * from "./Cron"
export * from "./Event" export * from "./Discord"
export * from "./General" export * from "./General"
export * from "./Guild" export * from "./Guild"
export * from "./Modal"
export * from "./Player" export * from "./Player"
export * from "./SubCommand" export * from "./TimeZones"

View File

@@ -1,10 +1,11 @@
import { Events, MessageFlags } from "discord.js" import { Events, GuildMember, MessageFlags } from "discord.js"
import fs from "fs" import fs from "fs"
import path from "path" import path from "path"
import { embedColor } from "~/config/options" import { embedColor } from "~/config/options"
import { ICommand, LoadEventsOptions } from "~/typings" import { ICommand, LoadEventsOptions } from "~/typings"
import { ExtendedClient as Client } from "~/utils/Client" import { ExtendedClient as Client } from "~/utils/Client"
import logToChannel from "~/utils/Functions/logtochannel" import logToChannel from "~/utils/Functions/logtochannel"
import { isAdmin, isHelper, isSuperAdmin } from "../Functions/staff"
import tryCatch from "../Functions/trycatch" import tryCatch from "../Functions/trycatch"
import { log } from "../Logger" import { log } from "../Logger"
@@ -33,6 +34,43 @@ export default async function loadSlashCommandsEvents(client: Client, { ft, dir
return return
} }
if (!command.requiredRole && !isSuperAdmin(interaction.member as GuildMember)) {
await interaction.reply({
content: "You do not have permission to use this command.",
flags: MessageFlags.Ephemeral
})
return
}
switch (command.requiredRole) {
case "superadmin":
if (!isSuperAdmin(interaction.member as GuildMember)) {
await interaction.reply({
content: "You do not have permission to use this command.",
flags: MessageFlags.Ephemeral
})
}
break
case "admin":
if (!isAdmin(interaction.member as GuildMember)) {
await interaction.reply({
content: "You do not have permission to use this command.",
flags: MessageFlags.Ephemeral
})
}
break
case "helper":
if (!isHelper(interaction.member as GuildMember)) {
await interaction.reply({
content: "You do not have permission to use this command.",
flags: MessageFlags.Ephemeral
})
}
break
case "none":
break
}
const [error] = await tryCatch(command.execute({ interaction, client })) const [error] = await tryCatch(command.execute({ interaction, client }))
if (!error) return if (!error) return

View File

@@ -0,0 +1,14 @@
import { GuildMember, PermissionFlagsBits } from "discord.js"
import { admin, helper } from "~/config/roles"
export function isSuperAdmin(member: GuildMember) {
return member.permissions.has(PermissionFlagsBits.Administrator)
}
export function isAdmin(member: GuildMember) {
return member.roles.cache.has(admin) || member.permissions.has(PermissionFlagsBits.Administrator)
}
export function isHelper(member: GuildMember) {
return member.roles.cache.has(helper) || member.roles.cache.has(admin) || member.permissions.has(PermissionFlagsBits.Administrator)
}