UNPKG

discord-starboard-plus

Version:

Discord Starboard Plus: A clean, maintainable starboard system for Discord.js bots. Features per-guild configuration, TypeScript support. Highlight your community's favorite messages with customizable starboards.

143 lines 5.62 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.ConfigValidator = void 0; /** * Default configuration values */ const DEFAULT_OPTIONS = { starEmoji: '\u2b50', requiredReactions: 1, ignoreBots: true, ignoreSelf: false, ignoredChannels: [], ignoreGuilds: [], updateOnReaction: true, logActions: true, embedColor: 0xFFAC33, maxAttachments: 4, allowNSFW: false, jumpToMessage: true, showMessageDate: true, maxSearchDepth: 500, useComponentsV2: false }; /** * Configuration validation and normalization. * Centralizes all configuration logic following SRP. */ class ConfigValidator { /** * Validate configuration options. * Throws an error if validation fails. */ static validate(options) { const errors = []; // Required fields if (!options.starboardChannelID) { errors.push('starboardChannelID is required'); } else if (!ConfigValidator.isValidSnowflake(options.starboardChannelID)) { errors.push('starboardChannelID must be a valid Discord Snowflake'); } // Numeric validations if (options.requiredReactions !== undefined) { if (!Number.isInteger(options.requiredReactions) || options.requiredReactions < 1) { errors.push('requiredReactions must be a positive integer'); } } if (options.maxAttachments !== undefined) { if (!Number.isInteger(options.maxAttachments) || options.maxAttachments < 0) { errors.push('maxAttachments must be a non-negative integer'); } } if (options.maxSearchDepth !== undefined) { if (!Number.isInteger(options.maxSearchDepth) || options.maxSearchDepth < 100) { errors.push('maxSearchDepth must be an integer >= 100'); } } // Array validations if (options.ignoredChannels !== undefined) { if (!Array.isArray(options.ignoredChannels)) { errors.push('ignoredChannels must be an array'); } else if (!options.ignoredChannels.every(ConfigValidator.isValidSnowflake)) { errors.push('ignoredChannels must contain valid Discord Snowflakes'); } } if (options.ignoreGuilds !== undefined) { if (!Array.isArray(options.ignoreGuilds)) { errors.push('ignoreGuilds must be an array'); } else if (!options.ignoreGuilds.every(ConfigValidator.isValidSnowflake)) { errors.push('ignoreGuilds must contain valid Discord Snowflakes'); } } // Emoji validation if (options.starEmoji !== undefined) { if (typeof options.starEmoji !== 'string' || options.starEmoji.length === 0) { errors.push('starEmoji must be a non-empty string'); } } if (errors.length > 0) { throw new Error(`Configuration validation failed:\n- ${errors.join('\n- ')}`); } } /** * Normalize configuration options by applying defaults. * Returns a complete StarboardOptions object. */ static normalize(options) { return { starEmoji: options.starEmoji ?? DEFAULT_OPTIONS.starEmoji, starboardChannelID: options.starboardChannelID, requiredReactions: Math.max(1, options.requiredReactions ?? DEFAULT_OPTIONS.requiredReactions), ignoreBots: options.ignoreBots ?? DEFAULT_OPTIONS.ignoreBots, ignoreSelf: options.ignoreSelf ?? DEFAULT_OPTIONS.ignoreSelf, ignoredChannels: [...(options.ignoredChannels ?? DEFAULT_OPTIONS.ignoredChannels)], ignoreGuilds: [...(options.ignoreGuilds ?? DEFAULT_OPTIONS.ignoreGuilds)], updateOnReaction: options.updateOnReaction ?? DEFAULT_OPTIONS.updateOnReaction, logActions: options.logActions ?? DEFAULT_OPTIONS.logActions, embedColor: options.embedColor ?? DEFAULT_OPTIONS.embedColor, maxAttachments: Math.max(0, options.maxAttachments ?? DEFAULT_OPTIONS.maxAttachments), allowNSFW: options.allowNSFW ?? DEFAULT_OPTIONS.allowNSFW, jumpToMessage: options.jumpToMessage ?? DEFAULT_OPTIONS.jumpToMessage, showMessageDate: options.showMessageDate ?? DEFAULT_OPTIONS.showMessageDate, maxSearchDepth: Math.max(100, options.maxSearchDepth ?? DEFAULT_OPTIONS.maxSearchDepth), useComponentsV2: options.useComponentsV2 ?? DEFAULT_OPTIONS.useComponentsV2 }; } /** * Validate and normalize in one step. */ static validateAndNormalize(options) { ConfigValidator.validate(options); return ConfigValidator.normalize(options); } /** * Merge partial options with existing options. */ static merge(existing, partial) { const merged = { ...existing, ...partial }; return ConfigValidator.validateAndNormalize(merged); } /** * Check if a string is a valid Discord Snowflake. */ static isValidSnowflake(value) { if (typeof value !== 'string') return false; // Snowflakes are numeric strings between 17-20 digits return /^\d{17,20}$/.test(value); } /** * Get default options (without starboardChannelID) */ static getDefaults() { return { ...DEFAULT_OPTIONS }; } } exports.ConfigValidator = ConfigValidator; //# sourceMappingURL=ConfigValidator.js.map