chore: remove validator functions

This commit is contained in:
Skillz4Killz
2021-11-24 03:13:16 +00:00
committed by GitHub
parent b6c9b065f3
commit a33e96a2b8
11 changed files with 0 additions and 295 deletions

View File

@@ -62,10 +62,6 @@ import {
delay,
formatImageURL,
hasProperty,
validateComponents,
validateSlashCommands,
validateSlashOptionChoices,
validateSlashOptions,
} from "./util/utils.ts";
import { iconBigintToHash, iconHashToBigInt } from "./util/hash.ts";
import { calculateShardId } from "./util/calculateShardId.ts";
@@ -312,13 +308,9 @@ export function createUtils(options: Partial<HelperUtils>) {
iconHashToBigInt,
iconBigintToHash,
validateLength,
validateSlashOptions,
validateSlashOptionChoices,
validateComponents,
hasProperty,
urlToBase64,
formatImageURL,
validateSlashCommands,
calculateBits,
calculatePermissions,
};
@@ -332,13 +324,9 @@ export interface HelperUtils {
iconHashToBigInt: typeof iconHashToBigInt;
iconBigintToHash: typeof iconBigintToHash;
validateLength: typeof validateLength;
validateSlashOptions: typeof validateSlashOptions;
validateSlashOptionChoices: typeof validateSlashOptionChoices;
validateComponents: typeof validateComponents;
hasProperty: typeof hasProperty;
urlToBase64: typeof urlToBase64;
formatImageURL: typeof formatImageURL;
validateSlashCommands: typeof validateSlashCommands;
calculateBits: typeof calculateBits;
calculatePermissions: typeof calculatePermissions;
}

View File

@@ -15,8 +15,6 @@ import { ApplicationCommandOption } from "../../../types/interactions/commands/a
* Guild commands update **instantly**. We recommend you use guild commands for quick testing, and global commands when they're ready for public use.
*/
export async function createSlashCommand(bot: Bot, options: CreateGlobalApplicationCommand, guildId?: bigint) {
[options] = bot.utils.validateSlashCommands(bot, [options], true) as CreateGlobalApplicationCommand[];
return await bot.rest.runMethod<ApplicationCommand>(
bot.rest,
"post",

View File

@@ -9,10 +9,6 @@ export async function editSlashResponse(bot: Bot, token: string, options: Discor
throw Error(bot.constants.Errors.MESSAGE_MAX_LENGTH);
}
if (options.components?.length) {
bot.utils.validateComponents(bot, options.components);
}
if (options.embeds && options.embeds.length > 10) {
options.embeds.splice(10);
}

View File

@@ -12,8 +12,6 @@ export async function upsertSlashCommand(
options: EditGlobalApplicationCommand,
guildId?: bigint
) {
[options] = bot.utils.validateSlashCommands(bot, [options]);
return await bot.rest.runMethod<ApplicationCommand>(
bot.rest,
"patch",

View File

@@ -13,8 +13,6 @@ export async function upsertSlashCommands(
options: MakeRequired<EditGlobalApplicationCommand, "name">[],
guildId?: bigint
) {
options = bot.utils.validateSlashCommands(bot, options) as MakeRequired<EditGlobalApplicationCommand, "name">[];
return await bot.rest.runMethod<ApplicationCommand[]>(
bot.rest,
"put",

View File

@@ -41,10 +41,6 @@ export async function editFollowupMessage(
}
}
if (options.components?.length) {
bot.utils.validateComponents(bot, options.components);
}
const result = await bot.rest.runMethod<Message>(
bot.rest,
"patch",

View File

@@ -15,9 +15,6 @@ export async function sendInteractionResponse(
token: string,
options: DiscordenoInteractionResponse
) {
// TODO: add more options validations
if (options.data?.components) bot.utils.validateComponents(bot, options.data.components);
// If the user wants this as a private message mark it ephemeral
if (options.private) {
options.data = { ...options.data, flags: 64 };

View File

@@ -7,10 +7,6 @@ import { MessageComponentTypes } from "../../types/messages/components/messageCo
export async function editMessage(bot: Bot, channelId: bigint, messageId: bigint, content: string | EditMessage) {
if (typeof content === "string") content = { content };
if (content.components?.length) {
bot.utils.validateComponents(bot, content.components);
}
content.embeds?.splice(10);
if (content.content && content.content.length > 2000) {

View File

@@ -13,10 +13,6 @@ export async function sendMessage(bot: Bot, channelId: bigint, content: string |
throw new Error(bot.constants.Errors.MESSAGE_MAX_LENGTH);
}
if (content.components?.length) {
bot.utils.validateComponents(bot, content.components);
}
if (content.allowedMentions) {
if (content.allowedMentions.users?.length) {
if (content.allowedMentions.parse?.includes(AllowedMentionsTypes.UserMentions)) {

View File

@@ -40,10 +40,6 @@ export async function editWebhookMessage(
}
}
if (options.components?.length) {
bot.utils.validateComponents(bot, options.components);
}
const result = await bot.rest.runMethod<Message>(
bot.rest,
"patch",

View File

@@ -1,17 +1,5 @@
import { Errors } from "../types/discordeno/errors.ts";
import type { ApplicationCommandOption } from "../types/interactions/commands/applicationCommandOption.ts";
import type { ApplicationCommandOptionChoice } from "../types/interactions/commands/applicationCommandOptionChoice.ts";
import { ApplicationCommandOptionTypes } from "../types/interactions/commands/applicationCommandOptionTypes.ts";
import type { CreateGlobalApplicationCommand } from "../types/interactions/commands/createGlobalApplicationCommand.ts";
import type { EditGlobalApplicationCommand } from "../types/interactions/commands/editGlobalApplicationCommand.ts";
import { ButtonStyles } from "../types/messages/components/buttonStyles.ts";
import type { MessageComponents } from "../types/messages/components/messageComponents.ts";
import type { ImageFormat } from "../types/misc/imageFormat.ts";
import type { ImageSize } from "../types/misc/imageSize.ts";
import { CONTEXT_MENU_COMMANDS_NAME_REGEX, SLASH_COMMANDS_NAME_REGEX } from "./constants.ts";
import { ApplicationCommandTypes } from "../types/interactions/commands/applicationCommandTypes.ts";
import { Bot } from "../bot.ts";
import { MessageComponentTypes } from "../types/messages/components/messageComponentTypes.ts";
/** Pause the execution for a given amount of milliseconds. */
export function delay(ms: number): Promise<void> {
@@ -27,113 +15,6 @@ export const formatImageURL = (url: string, size: ImageSize = 128, format?: Imag
return `${url}.${format || (url.includes("/a_") ? "gif" : "jpg")}?size=${size}`;
};
export function validateSlashOptionChoices(
bot: Bot,
choices: ApplicationCommandOptionChoice[],
optionType: ApplicationCommandOptionTypes
) {
return choices.every((choice) => {
bot.events.debug(`Running for of loop in validateSlashOptionChoices function.`);
if (!bot.utils.validateLength(choice.name, { min: 1, max: 100 })) {
throw new Error(Errors.INVALID_SLASH_OPTION_CHOICE_NAME);
}
if (
optionType === ApplicationCommandOptionTypes.String &&
(typeof choice.value !== "string" || choice.value.length < 1 || choice.value.length > 100)
) {
throw new Error(Errors.INVALID_SLASH_OPTIONS_CHOICE_VALUE_TYPE);
}
if (optionType === ApplicationCommandOptionTypes.Integer && typeof choice.value !== "number") {
throw new Error(Errors.INVALID_SLASH_OPTIONS_CHOICE_VALUE_TYPE);
}
});
}
// TODO: add checks for autocomplete options when discord provides more info about them.
export function validateSlashOptions(bot: Bot, options: ApplicationCommandOption[]) {
const requiredOptions: ApplicationCommandOption[] = [];
const optionalOptions: ApplicationCommandOption[] = [];
for (const option of options) {
bot.events.debug(`Running for of loop in validateSlashOptions function.`);
option.name = option.name.toLowerCase();
if (option.choices?.length) {
if (option.choices.length > 25) throw new Error(Errors.TOO_MANY_SLASH_OPTION_CHOICES);
if (option.type !== ApplicationCommandOptionTypes.String && option.type !== ApplicationCommandOptionTypes.Integer)
throw new Error(Errors.ONLY_STRING_OR_INTEGER_OPTIONS_CAN_HAVE_CHOICES);
}
if (!bot.utils.validateLength(option.name, { min: 1, max: 32 })) throw new Error(Errors.INVALID_SLASH_OPTION_NAME);
if (!bot.utils.validateLength(option.description, { min: 1, max: 100 }))
throw new Error(Errors.INVALID_SLASH_OPTION_DESCRIPTION);
if (option.choices) {
bot.utils.validateSlashOptionChoices(bot, option.choices, option.type);
}
if (option.required) {
requiredOptions.push(option);
continue;
}
optionalOptions.push(option);
}
return [...requiredOptions, ...optionalOptions];
}
export function validateSlashCommands(
bot: Bot,
commands: (CreateGlobalApplicationCommand | EditGlobalApplicationCommand)[],
create = false
) {
return commands.map((command) => {
bot.events.debug(`Running for of loop in validateSlashCommands function.`);
if (create) {
if (!command.name) throw new Error(Errors.INVALID_SLASH_NAME);
// Slash commands require description
if (!command.description && (!command.type || command.type === ApplicationCommandTypes.ChatInput))
throw new Error(Errors.INVALID_CONTEXT_MENU_COMMAND_DESCRIPTION);
if (command.description && (!command.type || command.type !== ApplicationCommandTypes.ChatInput))
throw new Error(Errors.INVALID_SLASH_DESCRIPTION);
}
if (command.name) {
if (!command.type || command.type === ApplicationCommandTypes.ChatInput) {
if (!SLASH_COMMANDS_NAME_REGEX.test(command.name)) {
throw new Error(Errors.INVALID_SLASH_NAME);
}
// Only slash need to be lowercase
command.name = command.name.toLowerCase();
} else {
if (!CONTEXT_MENU_COMMANDS_NAME_REGEX.test(command.name)) {
throw new Error(Errors.INVALID_CONTEXT_MENU_COMMAND_NAME);
}
}
}
if (command.description && !bot.utils.validateLength(command.description, { min: 1, max: 100 })) {
throw new Error(Errors.INVALID_SLASH_DESCRIPTION);
}
if (command.options?.length) {
if (command.options.length > 25) {
throw new Error(Errors.TOO_MANY_SLASH_OPTIONS);
}
command.options = bot.utils.validateSlashOptions(bot, command.options);
}
return command;
});
}
// Typescript is not so good as we developers so we need this little utility function to help it out
// Taken from https://fettblog.eu/typescript-hasownproperty/
/** TS save way to check if a property exists in an object */
@@ -145,138 +26,3 @@ export function hasProperty<T extends {}, Y extends PropertyKey = string>(
// deno-lint-ignore no-prototype-builtins
return obj.hasOwnProperty(prop);
}
export function validateComponents(bot: Bot, components: MessageComponents) {
if (!components?.length) return;
let actionRowCounter = 0;
for (const component of components) {
actionRowCounter++;
// Max of 5 ActionRows per message
if (actionRowCounter > 5) throw new Error(Errors.TOO_MANY_ACTION_ROWS);
// Max of 5 Buttons (or any component type) within an ActionRow
if (component.components?.length > 5) {
throw new Error(Errors.TOO_MANY_COMPONENTS);
} else if (
component.components?.length > 1 &&
component.components.some((subcomponent) => subcomponent.type === MessageComponentTypes.SelectMenu)
) {
throw new Error(Errors.COMPONENT_SELECT_MUST_BE_ALONE);
}
for (const subcomponent of component.components) {
if (subcomponent.customId && !bot.utils.validateLength(subcomponent.customId, { max: 100 })) {
throw new Error(Errors.COMPONENT_CUSTOM_ID_TOO_BIG);
}
// 5 Link buttons can not have a customId
if (subcomponent.type === MessageComponentTypes.Button) {
if (subcomponent.style === ButtonStyles.Link && subcomponent.customId) {
throw new Error(Errors.LINK_BUTTON_CANNOT_HAVE_CUSTOM_ID);
}
// Other buttons must have a customId
if (!subcomponent.customId && subcomponent.style !== ButtonStyles.Link) {
throw new Error(Errors.BUTTON_REQUIRES_CUSTOM_ID);
}
if (!bot.utils.validateLength(subcomponent.label, { max: 80 })) {
throw new Error(Errors.COMPONENT_LABEL_TOO_BIG);
}
subcomponent.emoji = makeEmojiFromString(subcomponent.emoji);
}
if (subcomponent.type === MessageComponentTypes.SelectMenu) {
if (subcomponent.placeholder && !bot.utils.validateLength(subcomponent.placeholder, { max: 100 })) {
throw new Error(Errors.COMPONENT_PLACEHOLDER_TOO_BIG);
}
if (subcomponent.minValues) {
if (subcomponent.minValues < 1) {
throw new Error(Errors.COMPONENT_SELECT_MINVALUE_TOO_LOW);
}
if (subcomponent.minValues > 25) {
throw new Error(Errors.COMPONENT_SELECT_MINVALUE_TOO_MANY);
}
if (!subcomponent.maxValues) subcomponent.maxValues = subcomponent.minValues;
if (subcomponent.minValues > subcomponent.maxValues) {
throw new Error(Errors.COMPONENT_SELECT_MIN_HIGHER_THAN_MAX);
}
}
if (subcomponent.maxValues) {
if (subcomponent.maxValues < 1) {
throw new Error(Errors.COMPONENT_SELECT_MAXVALUE_TOO_LOW);
}
if (subcomponent.maxValues > 25) {
throw new Error(Errors.COMPONENT_SELECT_MAXVALUE_TOO_MANY);
}
}
if (subcomponent.options.length < 1) {
throw new Error(Errors.COMPONENT_SELECT_OPTIONS_TOO_LOW);
}
if (subcomponent.options.length > 25) {
throw new Error(Errors.COMPONENT_SELECT_OPTIONS_TOO_MANY);
}
let defaults = 0;
for (const option of subcomponent.options) {
if (option.default) {
defaults++;
if (defaults > (subcomponent.maxValues || 25)) {
throw new Error(Errors.SELECT_OPTION_TOO_MANY_DEFAULTS);
}
}
if (!bot.utils.validateLength(option.label, { max: 25 })) {
throw new Error(Errors.SELECT_OPTION_LABEL_TOO_BIG);
}
if (!bot.utils.validateLength(option.value, { max: 100 })) {
throw new Error(Errors.SELECT_OPTION_VALUE_TOO_BIG);
}
if (option.description && !bot.utils.validateLength(option.description, { max: 50 })) {
throw new Error(Errors.SELECT_OPTION_VALUE_TOO_BIG);
}
option.emoji = makeEmojiFromString(option.emoji);
}
}
}
}
}
function makeEmojiFromString(
emoji?:
| string
| {
id?: string | undefined;
name?: string | undefined;
animated?: boolean | undefined;
}
) {
if (typeof emoji !== "string") return emoji;
// A snowflake id was provided
if (/^[0-9]+$/.test(emoji)) {
emoji = {
id: emoji,
};
} else {
// A unicode emoji was provided
emoji = {
name: emoji,
};
}
return emoji;
}