@sapphire/framework
Version:
Discord bot framework built for advanced and amazing bots.
179 lines (177 loc) • 6.91 kB
JavaScript
import { hasChannelTypesSupport, hasChoicesAndAutocompleteSupport, hasMinMaxLengthSupport, hasMinMaxValueSupport, optionTypeToPrettyName, subcommandTypes } from "./_shared.mjs";
import { checkDescription } from "./description.mjs";
import { checkLocalizations } from "./localizations.mjs";
import { checkName } from "./name.mjs";
import { handleAutocomplete } from "./option/autocomplete.mjs";
import { checkChannelTypes } from "./option/channelTypes.mjs";
import { handleMinMaxLengthOptions } from "./option/minMaxLength.mjs";
import { handleMinMaxValueOptions } from "./option/minMaxValue.mjs";
import { checkOptionRequired } from "./option/required.mjs";
import { checkOptionType } from "./option/type.mjs";
import { ApplicationCommandOptionType } from "discord-api-types/v10";
//#region src/lib/utils/application-commands/compute-differences/options.ts
function* checkOptions(existingOptions, newOptions) {
if (!existingOptions?.length && newOptions?.length) yield {
key: "options",
original: "no options present",
expected: "options present"
};
else if (existingOptions?.length && !newOptions?.length) yield {
key: "options",
original: "options present",
expected: "no options present"
};
else if (newOptions?.length) {
let index = 0;
for (const option of newOptions) {
const currentIndex = index++;
const existingOption = existingOptions[currentIndex];
yield* reportOptionDifferences({
currentIndex,
option,
existingOption
});
}
if (index < existingOptions.length) {
let option;
while ((option = existingOptions[index]) !== void 0) {
const expectedType = optionTypeToPrettyName.get(option.type) ?? `unknown (${option.type}); please contact Sapphire developers about this!`;
yield {
key: `existing command option at index ${index}`,
expected: "no option present",
original: `${expectedType} with name ${option.name}`
};
index++;
}
}
}
}
function* reportOptionDifferences({ option, existingOption, currentIndex, keyPath = (index) => `options[${index}]` }) {
if (!existingOption) {
const expectedType = optionTypeToPrettyName.get(option.type) ?? `unknown (${option.type}); please contact Sapphire developers about this!`;
yield {
key: keyPath(currentIndex),
expected: `${expectedType} with name ${option.name}`,
original: "no option present"
};
return;
}
yield* checkOptionType({
key: `${keyPath(currentIndex)}.type`,
originalType: existingOption.type,
expectedType: option.type
});
yield* checkName({
key: `${keyPath(currentIndex)}.name`,
oldName: existingOption.name,
newName: option.name
});
const originalLocalizedNames = existingOption.name_localizations;
const expectedLocalizedNames = option.name_localizations;
yield* checkLocalizations({
localeMapName: `${keyPath(currentIndex)}.nameLocalizations`,
localePresentMessage: "localized names",
localeMissingMessage: "no localized names",
originalLocalizedDescriptions: originalLocalizedNames,
expectedLocalizedDescriptions: expectedLocalizedNames
});
yield* checkDescription({
key: `${keyPath(currentIndex)}.description`,
oldDescription: existingOption.description,
newDescription: option.description
});
const originalLocalizedDescriptions = existingOption.description_localizations;
const expectedLocalizedDescriptions = option.description_localizations;
yield* checkLocalizations({
localeMapName: `${keyPath(currentIndex)}.descriptionLocalizations`,
localePresentMessage: "localized descriptions",
localeMissingMessage: "no localized descriptions",
originalLocalizedDescriptions,
expectedLocalizedDescriptions
});
yield* checkOptionRequired({
key: `${keyPath(currentIndex)}.required`,
oldRequired: existingOption.required,
newRequired: option.required
});
if (subcommandTypes.includes(existingOption.type) && subcommandTypes.includes(option.type)) {
const castedExisting = existingOption;
const castedExpected = option;
if (castedExisting.type === ApplicationCommandOptionType.SubcommandGroup && castedExpected.type === ApplicationCommandOptionType.SubcommandGroup) for (const [subcommandIndex, subcommandOption] of castedExpected.options.entries()) yield* reportOptionDifferences({
currentIndex: subcommandIndex,
option: subcommandOption,
existingOption: castedExisting.options?.[subcommandIndex],
keyPath: (index) => `${keyPath(currentIndex)}.options[${index}]`
});
else if (castedExisting.type === ApplicationCommandOptionType.Subcommand && castedExpected.type === ApplicationCommandOptionType.Subcommand) yield* handleSubcommandOptions({
expectedOptions: castedExpected.options,
existingOptions: castedExisting.options,
currentIndex,
keyPath
});
}
if (hasMinMaxValueSupport(option)) yield* handleMinMaxValueOptions({
currentIndex,
existingOption,
expectedOption: option,
keyPath
});
if (hasChoicesAndAutocompleteSupport(option)) yield* handleAutocomplete({
expectedOption: option,
existingOption,
currentIndex,
keyPath
});
if (hasMinMaxLengthSupport(option)) yield* handleMinMaxLengthOptions({
currentIndex,
existingOption,
expectedOption: option,
keyPath
});
if (hasChannelTypesSupport(option)) yield* checkChannelTypes({
currentIndex,
existingChannelTypes: existingOption.channel_types,
keyPath,
newChannelTypes: option.channel_types
});
}
function* handleSubcommandOptions({ expectedOptions, existingOptions, currentIndex, keyPath }) {
if (!existingOptions?.length && expectedOptions?.length) yield {
key: `${keyPath(currentIndex)}.options`,
expected: "options present",
original: "no options present"
};
else if (existingOptions?.length && !expectedOptions?.length) yield {
key: `${keyPath(currentIndex)}.options`,
expected: "no options present",
original: "options present"
};
else if (expectedOptions?.length) {
let processedIndex = 0;
for (const subcommandOption of expectedOptions) {
const currentSubCommandOptionIndex = processedIndex++;
const existingSubcommandOption = existingOptions[currentSubCommandOptionIndex];
yield* reportOptionDifferences({
currentIndex: currentSubCommandOptionIndex,
option: subcommandOption,
existingOption: existingSubcommandOption,
keyPath: (index) => `${keyPath(currentIndex)}.options[${index}]`
});
}
if (processedIndex < existingOptions.length) {
let option;
while ((option = existingOptions[processedIndex]) !== void 0) {
const expectedType = optionTypeToPrettyName.get(option.type) ?? `unknown (${option.type}); please contact Sapphire developers about this!`;
yield {
key: `existing command option at path ${keyPath(currentIndex)}.options[${processedIndex}]`,
expected: "no option present",
original: `${expectedType} with name ${option.name}`
};
processedIndex++;
}
}
}
}
//#endregion
export { checkOptions };
//# sourceMappingURL=options.mjs.map