Files
discordeno/plugins/permissions/src/components.ts
2022-01-26 19:02:34 +01:00

179 lines
5.0 KiB
TypeScript

import {
Bot,
ButtonStyles,
MessageComponents,
MessageComponentTypes,
} from "../deps.ts";
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("Too many action rows.");
// Max of 5 Buttons (or any component type) within an ActionRow
if (component.components?.length > 5) {
throw new Error("Too many components.");
} else if (
component.components?.length > 1 &&
component.components.some((subcomponent) =>
subcomponent.type === MessageComponentTypes.SelectMenu
)
) {
throw new Error("Select component must be alone.");
}
for (const subcomponent of component.components) {
if (
subcomponent.customId &&
!bot.utils.validateLength(subcomponent.customId, { max: 100 })
) {
throw new Error("The custom id in the component is 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("Link buttons can not have custom ids.");
}
// Other buttons must have a customId
if (
!subcomponent.customId && subcomponent.style !== ButtonStyles.Link
) {
throw new Error(
"The button requires a custom id if it is not a link button.",
);
}
if (!bot.utils.validateLength(subcomponent.label, { max: 80 })) {
throw new Error("The label can not be longer than 80 characters.");
}
subcomponent.emoji = makeEmojiFromString(subcomponent.emoji);
}
if (subcomponent.type === MessageComponentTypes.SelectMenu) {
if (
subcomponent.placeholder &&
!bot.utils.validateLength(subcomponent.placeholder, { max: 100 })
) {
throw new Error(
"The component placeholder can not be longer than 100 characters.",
);
}
if (subcomponent.minValues) {
if (subcomponent.minValues < 1) {
throw new Error(
"The min values must be more than 1 in a select component.",
);
}
if (subcomponent.minValues > 25) {
throw new Error(
"The min values must be less than 25 in a select component.",
);
}
if (!subcomponent.maxValues) {
subcomponent.maxValues = subcomponent.minValues;
}
if (subcomponent.minValues > subcomponent.maxValues) {
throw new Error(
"The select component can not have a min values higher than a max values.",
);
}
}
if (subcomponent.maxValues) {
if (subcomponent.maxValues < 1) {
throw new Error(
"The max values must be more than 1 in a select component.",
);
}
if (subcomponent.maxValues > 25) {
throw new Error(
"The max values must be less than 25 in a select component.",
);
}
}
if (subcomponent.options.length < 1) {
throw new Error("You need atleast 1 option in the select component.");
}
if (subcomponent.options.length > 25) {
throw new Error(
"You can not have more than 25 options in the select component.",
);
}
let defaults = 0;
for (const option of subcomponent.options) {
if (option.default) {
defaults++;
if (defaults > (subcomponent.maxValues || 25)) {
throw new Error("You chose too many default options.");
}
}
if (!bot.utils.validateLength(option.label, { max: 25 })) {
throw new Error(
"The select component label can not exceed 25 characters.",
);
}
if (!bot.utils.validateLength(option.value, { max: 100 })) {
throw new Error(
"The select component value can not exceed 100 characters.",
);
}
if (
option.description &&
!bot.utils.validateLength(option.description, { max: 50 })
) {
throw new Error(
"The select option description can not exceed 50 characters.",
);
}
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;
}