feat: onBotPermissionsFail

This commit is contained in:
MARCROCK22 2024-03-31 16:08:59 -04:00
parent 1c06184b53
commit 43cb84f54f
7 changed files with 52 additions and 36 deletions

View File

@ -30,7 +30,7 @@ export async function onInteractionCreate(
{
const parentCommand = self.commands?.values.find(x => {
if (body.data.guild_id) {
return x.guild_id?.includes(body.data.guild_id) && x.name === body.data.name;
return x.guildId?.includes(body.data.guild_id) && x.name === body.data.name;
}
return x.name === body.data.name;
});
@ -78,7 +78,7 @@ export async function onInteractionCreate(
{
const command = self.commands?.values.find(x => {
if (body.data.guild_id) {
return x.guild_id?.includes(body.data.guild_id) && x.name === body.data.name;
return x.guildId?.includes(body.data.guild_id) && x.name === body.data.name;
}
return x.name === body.data.name;
}) as ContextMenuCommand;
@ -96,8 +96,8 @@ export async function onInteractionCreate(
const permissions = interaction.appPermissions.missings(
...interaction.appPermissions.values([command.botPermissions]),
);
if (permissions.length) {
return command.onPermissionsFail?.(context, interaction.appPermissions.keys(permissions));
if (!interaction.appPermissions.has('Administrator') && permissions.length) {
return command.onBotPermissionsFail?.(context, interaction.appPermissions.keys(permissions));
}
}
const resultRunGlobalMiddlewares = await command.__runGlobalMiddlewares(context);
@ -136,7 +136,7 @@ export async function onInteractionCreate(
{
const parentCommand = self.commands?.values.find(x => {
if (body.data.guild_id) {
return x.guild_id?.includes(body.data.guild_id) && x.name === body.data.name;
return x.guildId?.includes(body.data.guild_id) && x.name === body.data.name;
}
return x.name === body.data.name;
});
@ -159,8 +159,8 @@ export async function onInteractionCreate(
const permissions = interaction.appPermissions.missings(
...interaction.appPermissions.values([command.botPermissions]),
);
if (permissions.length) {
return command.onPermissionsFail?.(context, interaction.appPermissions.keys(permissions));
if (!interaction.appPermissions.has('Administrator') && permissions.length) {
return command.onBotPermissionsFail?.(context, interaction.appPermissions.keys(permissions));
}
}
const [erroredOptions, result] = await command.__runOptions(context, optionsResolver);

View File

@ -91,7 +91,7 @@ export async function onMessageCreate(
if (!command.run) return self.logger.warn(`${fullCommandName} command does not have 'run' callback`);
if (!command.contexts?.includes(InteractionContextTypes.BOT_DM) && !message.guildId) return;
if (command.guild_id && !command.guild_id?.includes(message.guildId!)) return;
if (command.guildId && !command.guildId?.includes(message.guildId!)) return;
const resolved: MakeRequired<ContextOptionsResolved> = {
channels: {},
@ -108,13 +108,20 @@ export async function onMessageCreate(
const extendContext = self.options?.context?.(message) ?? {};
Object.assign(context, extendContext);
try {
if (command.defaultMemberPermissions && message.guildId) {
const memberPermissions = await self.members.permissions(message.guildId, message.author.id);
const permissions = memberPermissions.missings(...memberPermissions.values([command.defaultMemberPermissions]));
if (!memberPermissions.has('Administrator') && permissions.length) {
return command.onPermissionsFail?.(context, memberPermissions.keys(permissions));
}
}
if (command.botPermissions && message.guildId) {
const meMember = await self.cache.members?.get(self.botId, message.guildId);
if (!meMember) return; //enable member cache and "Guilds" intent, lol
const appPermissions = await meMember.fetchPermissions();
const permissions = appPermissions.missings(...appPermissions.values([command.botPermissions]));
if (permissions.length) {
return command.onPermissionsFail?.(context, appPermissions.keys(permissions));
if (!appPermissions.has('Administrator') && permissions.length) {
return command.onBotPermissionsFail?.(context, appPermissions.keys(permissions));
}
}
if (errors.length) {

View File

@ -1,14 +1,14 @@
import {
ApplicationCommandOptionType,
ApplicationCommandType,
type APIApplicationCommandBasicOption,
type APIApplicationCommandOption,
type APIApplicationCommandSubcommandGroupOption,
ApplicationCommandOptionType,
ApplicationCommandType,
type LocaleString,
} from 'discord-api-types/v10';
import type { PermissionStrings, SeyfertNumberOption, SeyfertStringOption } from '../..';
import type { Attachment } from '../../builders';
import { type FlatObjectKeys, magicImport } from '../../common';
import { magicImport, type FlatObjectKeys } from '../../common';
import type { AllChannels, AutocompleteInteraction, GuildRole, InteractionGuildMember, User } from '../../structures';
import type { Groups, IntegrationTypes, InteractionContextTypes, RegisteredMiddlewares } from '../decorators';
import type { OptionResolver } from '../optionresolver';
@ -117,13 +117,13 @@ class BaseCommand {
}
>;
guild_id?: string[];
guildId?: string[];
name!: string;
type!: number; // ApplicationCommandType.ChatInput | ApplicationCommandOptionType.Subcommand
nsfw?: boolean;
description!: string;
default_member_permissions?: string;
integration_types?: IntegrationTypes[];
defaultMemberPermissions?: bigint;
integrationTypes?: IntegrationTypes[];
contexts?: InteractionContextTypes[];
botPermissions?: bigint;
name_localizations?: Partial<Record<LocaleString, string>>;
@ -247,10 +247,10 @@ class BaseCommand {
description: this.description,
name_localizations: this.name_localizations,
description_localizations: this.description_localizations,
guild_id: this.guild_id,
default_member_permissions: this.default_member_permissions,
guild_id: this.guildId,
default_member_permissions: this.defaultMemberPermissions ? this.defaultMemberPermissions.toString() : '',
contexts: this.contexts,
integration_types: this.integration_types,
integration_types: this.integrationTypes,
} as {
name: BaseCommand['name'];
type: BaseCommand['type'];
@ -258,10 +258,10 @@ class BaseCommand {
description: BaseCommand['description'];
name_localizations: BaseCommand['name_localizations'];
description_localizations: BaseCommand['description_localizations'];
guild_id: BaseCommand['guild_id'];
default_member_permissions: BaseCommand['default_member_permissions'];
guild_id: BaseCommand['guildId'];
default_member_permissions: string;
contexts: BaseCommand['contexts'];
integration_types: BaseCommand['integration_types'];
integration_types: BaseCommand['integrationTypes'];
};
return data;
}
@ -284,6 +284,7 @@ class BaseCommand {
onRunError?(context: CommandContext<any>, error: unknown): any;
onOptionsError?(context: CommandContext<{}, never>, metadata: OnOptionsReturnObject): any;
onMiddlewaresError?(context: CommandContext<{}, never>, error: string): any;
onBotPermissionsFail?(context: CommandContext<{}, never>, permissions: PermissionStrings): any;
onPermissionsFail?(context: CommandContext<{}, never>, permissions: PermissionStrings): any;
onInternalError?(client: UsingClient, error?: unknown): any;
}
@ -333,6 +334,9 @@ export class Command extends BaseCommand {
onMiddlewaresError(context: CommandContext<{}, never>, error: string): any {
context.client.logger.fatal(`${this.name}.<onMiddlewaresError>`, context.author.id, error);
}
onBotPermissionsFail(context: CommandContext<{}, never>, permissions: PermissionStrings): any {
context.client.logger.fatal(`${this.name}.<onBotPermissionsFail>`, context.author.id, permissions);
}
onPermissionsFail(context: CommandContext<{}, never>, permissions: PermissionStrings): any {
context.client.logger.fatal(`${this.name}.<onPermissionsFail>`, context.author.id, permissions);
}

View File

@ -1,5 +1,5 @@
import type { ApplicationCommandType, LocaleString } from 'discord-api-types/v10';
import { type PermissionStrings, magicImport } from '../../common';
import { magicImport, type PermissionStrings } from '../../common';
import type { IntegrationTypes, InteractionContextTypes, RegisteredMiddlewares } from '../decorators';
import type { MenuCommandContext } from './menucontext';
import type { PassFunction, StopFunction, UsingClient } from './shared';
@ -10,14 +10,14 @@ export abstract class ContextMenuCommand {
__filePath?: string;
__t?: { name: string | undefined; description: string | undefined };
guild_id?: string[];
guildId?: string[];
name!: string;
type!: ApplicationCommandType.User | ApplicationCommandType.Message;
nsfw?: boolean;
integration_types?: IntegrationTypes[];
integrationTypes?: IntegrationTypes[];
contexts?: InteractionContextTypes[];
description!: string;
default_member_permissions?: string;
defaultMemberPermissions?: string;
botPermissions?: bigint;
dm?: boolean;
name_localizations?: Partial<Record<LocaleString, string>>;
@ -91,11 +91,11 @@ export abstract class ContextMenuCommand {
description: this.description,
name_localizations: this.name_localizations,
description_localizations: this.description_localizations,
guild_id: this.guild_id,
guild_id: this.guildId,
dm_permission: this.dm,
default_member_permissions: this.default_member_permissions,
default_member_permissions: this.defaultMemberPermissions,
contexts: this.contexts,
integration_types: this.integration_types,
integration_types: this.integrationTypes,
};
}
@ -114,6 +114,9 @@ export abstract class ContextMenuCommand {
onMiddlewaresError(context: MenuCommandContext<any, never>, error: string): any {
context.client.logger.fatal(`${this.name}.<onMiddlewaresError>`, context.author.id, error);
}
onBotPermissionsFail(context: MenuCommandContext<any, never>, permissions: PermissionStrings): any {
context.client.logger.fatal(`${this.name}.<onBotPermissionsFail>`, context.author.id, permissions);
}
onPermissionsFail(context: MenuCommandContext<any, never>, permissions: PermissionStrings): any {
context.client.logger.fatal(`${this.name}.<onPermissionsFail>`, context.author.id, permissions);
}

View File

@ -1,4 +1,4 @@
import { ApplicationCommandType, type LocaleString, PermissionFlagsBits } from 'discord-api-types/v10';
import { ApplicationCommandType, PermissionFlagsBits, type LocaleString } from 'discord-api-types/v10';
import type { FlatObjectKeys, PermissionStrings } from '../common';
import type { CommandOption, OptionsRecord, SubCommand } from './applications/chat';
import type { DefaultLocale, MiddlewareContext } from './applications/shared';
@ -140,21 +140,21 @@ export function Declare(declare: DeclareOptions) {
name = declare.name;
nsfw = declare.nsfw;
contexts = declare.contexts?.map(i => InteractionContextTypes[i]);
integration_types = declare.integrationTypes?.map(i => IntegrationTypes[i]);
default_member_permissions = Array.isArray(declare.defaultMemberPermissions)
? declare.defaultMemberPermissions?.reduce((acc, prev) => acc | PermissionFlagsBits[prev], BigInt(0)).toString()
integrationTypes = declare.integrationTypes?.map(i => IntegrationTypes[i]);
defaultMemberPermissions = Array.isArray(declare.defaultMemberPermissions)
? declare.defaultMemberPermissions?.reduce((acc, prev) => acc | PermissionFlagsBits[prev], BigInt(0))
: declare.defaultMemberPermissions;
botPermissions = Array.isArray(declare.botPermissions)
? declare.botPermissions?.reduce((acc, prev) => acc | PermissionFlagsBits[prev], BigInt(0))
: declare.botPermissions;
description = '';
type: ApplicationCommandType = ApplicationCommandType.ChatInput;
guild_id?: string[];
guildId?: string[];
constructor(...args: any[]) {
super(...args);
if ('description' in declare) this.description = declare.description;
if ('type' in declare) this.type = declare.type;
if ('guildId' in declare) this.guild_id = declare.guildId;
if ('guildId' in declare) this.guildId = declare.guildId;
// check if all properties are valid
}
};

View File

@ -109,6 +109,8 @@ export class CommandHandler extends BaseHandler {
option.onInternalError =
option.onInternalError?.bind(option) ?? commandInstance.onInternalError?.bind(commandInstance);
option.onAfterRun = option.onAfterRun?.bind(option) ?? commandInstance.onAfterRun?.bind(commandInstance);
option.onBotPermissionsFail =
option.onBotPermissionsFail?.bind(option) ?? commandInstance.onBotPermissionsFail?.bind(commandInstance);
option.onPermissionsFail =
option.onPermissionsFail?.bind(option) ?? commandInstance.onPermissionsFail?.bind(commandInstance);
}

View File

@ -6,7 +6,7 @@ export class PermissionsBitField extends BitField<typeof PermissionFlagsBits> {
Flags = PermissionFlagsBits;
static All = Object.values(PermissionFlagsBits).reduce((acc, value) => acc | value, 0n);
declare keys: (bits: BitFieldResolvable<typeof PermissionFlagsBits>[]) => PermissionStrings;
declare keys: (bits?: BitFieldResolvable<typeof PermissionFlagsBits>[]) => PermissionStrings;
has(...bits: BitFieldResolvable<typeof PermissionFlagsBits>[]) {
return super.has(...bits) || super.has('Administrator');