Essential utilities, BitField permission management, constants, formatters, and helper functions for Discord bot development and data manipulation.
Efficient flag and permission management using bitwise operations.
/**
* Base class for bitfield operations
* @template S The string representation type
* @template N The numeric representation type
*/
class BitField<S extends string, N extends number | bigint = number> {
constructor(bits?: BitFieldResolvable<S, N>);
readonly bitfield: N;
// Bit manipulation
add(...bits: BitFieldResolvable<S, N>[]): BitField<S, N>;
remove(...bits: BitFieldResolvable<S, N>[]): BitField<S, N>;
serialize(hasPermission?: (...args: readonly unknown[]) => boolean): Record<S, boolean>;
toArray(): S[];
toString(): string;
valueOf(): N;
// Bit checking
any(permission: BitFieldResolvable<S, N>): boolean;
equals(permission: BitFieldResolvable<S, N>): boolean;
has(permission: BitFieldResolvable<S, N>): boolean;
missing(bits: BitFieldResolvable<S, N>, checkAdmin?: boolean): S[];
// Static methods
static Flags: Record<string, number | bigint>;
static resolve<T extends number | bigint>(bit?: BitFieldResolvable<string, T>): T;
}
type BitFieldResolvable<S extends string, N extends number | bigint> =
| RecursiveReadonlyArray<S | N | `${bigint}` | Readonly<BitField<S, N>>>
| S
| N
| `${bigint}`
| Readonly<BitField<S, N>>;Comprehensive Discord permission system with role-based access control.
/**
* Represents Discord permissions using bitfields
* @extends BitField
*/
class PermissionsBitField extends BitField<PermissionsString, bigint> {
static Flags: typeof PermissionFlagsBits;
static All: bigint;
static Default: bigint;
static StageModerator: bigint;
// Permission checking with admin override
any(permission: PermissionResolvable, checkAdmin?: boolean): boolean;
has(permission: PermissionResolvable, checkAdmin?: boolean): boolean;
missing(permissions: PermissionResolvable, checkAdmin?: boolean): PermissionsString[];
serialize(checkAdmin?: boolean): Record<PermissionsString, boolean>;
static resolve(permission?: PermissionResolvable): bigint;
}
/**
* Discord permission flags
*/
const PermissionFlagsBits: {
/** Allows creation of instant invites */
CreateInstantInvite: 1n << 0n;
/** Allows kicking members */
KickMembers: 1n << 1n;
/** Allows banning members */
BanMembers: 1n << 2n;
/** Allows all permissions and bypasses channel permission overwrites */
Administrator: 1n << 3n;
/** Allows management and editing of channels */
ManageChannels: 1n << 4n;
/** Allows management and editing of the guild */
ManageGuild: 1n << 5n;
/** Allows for the addition of reactions to messages */
AddReactions: 1n << 6n;
/** Allows for viewing of audit logs */
ViewAuditLog: 1n << 7n;
/** Allows for using priority speaker in a voice channel */
PrioritySpeaker: 1n << 8n;
/** Allows the user to go live */
Stream: 1n << 9n;
/** Allows guild members to view a channel, which includes reading messages in text channels */
ViewChannel: 1n << 10n;
/** Allows for sending messages in a channel */
SendMessages: 1n << 11n;
/** Allows for sending of /tts messages */
SendTTSMessages: 1n << 12n;
/** Allows for deletion of other users messages */
ManageMessages: 1n << 13n;
/** Links sent by users with this permission will be auto-embedded */
EmbedLinks: 1n << 14n;
/** Allows for uploading images and files */
AttachFiles: 1n << 15n;
/** Allows for reading of message history */
ReadMessageHistory: 1n << 16n;
/** Allows for using the @everyone tag to notify all users in a channel */
MentionEveryone: 1n << 17n;
/** Allows the usage of custom emojis from other servers */
UseExternalEmojis: 1n << 18n;
/** Allows for viewing guild insights */
ViewGuildInsights: 1n << 19n;
/** Allows for joining of a voice channel */
Connect: 1n << 20n;
/** Allows for speaking in a voice channel */
Speak: 1n << 21n;
/** Allows for muting members in a voice channel */
MuteMembers: 1n << 22n;
/** Allows for deafening of members in a voice channel */
DeafenMembers: 1n << 23n;
/** Allows for moving of members between voice channels */
MoveMembers: 1n << 24n;
/** Allows for using voice-activity-detection in a voice channel */
UseVAD: 1n << 25n;
/** Allows for modification of own nickname */
ChangeNickname: 1n << 26n;
/** Allows for modification of other users nicknames */
ManageNicknames: 1n << 27n;
/** Allows management and editing of roles */
ManageRoles: 1n << 28n;
/** Allows management and editing of webhooks */
ManageWebhooks: 1n << 29n;
/** Allows management and editing of emojis, stickers, and soundboard sounds */
ManageGuildExpressions: 1n << 30n;
/** Allows members to use application commands like slash commands and context menus */
UseApplicationCommands: 1n << 31n;
/** Allows for requesting to speak in stage channels */
RequestToSpeak: 1n << 32n;
/** Allows for editing and deleting scheduled events */
ManageEvents: 1n << 33n;
/** Allows for deleting and archiving threads, and viewing all private threads */
ManageThreads: 1n << 34n;
/** Allows for creating public and announcement threads */
CreatePublicThreads: 1n << 35n;
/** Allows for creating private threads */
CreatePrivateThreads: 1n << 36n;
/** Allows the usage of custom stickers from other servers */
UseExternalStickers: 1n << 37n;
/** Allows for sending messages in threads */
SendMessagesInThreads: 1n << 38n;
/** Allows for using Activities in a voice channel */
UseEmbeddedActivities: 1n << 39n;
/** Allows for timing out users to prevent them from sending or reacting to messages */
ModerateMembers: 1n << 40n;
/** Allows for viewing role subscription insights */
ViewCreatorMonetizationAnalytics: 1n << 41n;
/** Allows for using soundboard in a voice channel */
UseSoundboard: 1n << 42n;
/** Allows for creating emojis, stickers, and soundboard sounds */
CreateGuildExpressions: 1n << 43n;
/** Allows for creating scheduled events */
CreateEvents: 1n << 44n;
/** Allows the usage of custom soundboard sounds from other servers */
UseExternalSounds: 1n << 45n;
/** Allows sending voice messages */
SendVoiceMessages: 1n << 46n;
};
type PermissionsString = keyof typeof PermissionFlagsBits;
type PermissionResolvable = BitFieldResolvable<PermissionsString, bigint>;Usage Examples:
// Check user permissions
const member = await guild.members.fetch(userId);
const permissions = member.permissions;
if (permissions.has(PermissionFlagsBits.Administrator)) {
console.log('User is an administrator');
}
if (permissions.has([PermissionFlagsBits.SendMessages, PermissionFlagsBits.ViewChannel])) {
console.log('User can send messages');
}
// Check missing permissions
const requiredPerms = [PermissionFlagsBits.ManageMessages, PermissionFlagsBits.BanMembers];
const missing = permissions.missing(requiredPerms);
if (missing.length > 0) {
console.log(`Missing permissions: ${missing.join(', ')}`);
}
// Create permission overwrites
const overwrites = [
{
id: guild.roles.everyone.id,
deny: [PermissionFlagsBits.ViewChannel]
},
{
id: member.id,
allow: [PermissionFlagsBits.ViewChannel, PermissionFlagsBits.SendMessages]
}
];
await guild.channels.create({
name: 'private-channel',
type: ChannelType.GuildText,
permissionOverwrites: overwrites
});Various specialized BitField classes for different Discord features.
/**
* Gateway intents bitfield
*/
class IntentsBitField extends BitField<GatewayIntentsString> {
static Flags: typeof GatewayIntentBits;
static resolve(bit?: BitFieldResolvable<GatewayIntentsString, number>): number;
}
/**
* Message flags bitfield
*/
class MessageFlagsBitField extends BitField<MessageFlagsString> {
static Flags: typeof MessageFlags;
static resolve(bit?: BitFieldResolvable<MessageFlagsString, number>): number;
}
/**
* User flags bitfield
*/
class UserFlagsBitField extends BitField<UserFlagsString> {
static Flags: typeof UserFlags;
static resolve(bit?: BitFieldResolvable<UserFlagsString, number>): number;
}
/**
* Activity flags bitfield
*/
class ActivityFlagsBitField extends BitField<ActivityFlagsString> {
static Flags: typeof ActivityFlags;
static resolve(bit?: BitFieldResolvable<ActivityFlagsString, number>): number;
}
/**
* Guild member flags bitfield
*/
class GuildMemberFlagsBitField extends BitField<GuildMemberFlagsString> {
static Flags: typeof GuildMemberFlags;
static resolve(bit?: BitFieldResolvable<GuildMemberFlagsString, number>): number;
}
/**
* System channel flags bitfield
*/
class SystemChannelFlagsBitField extends BitField<SystemChannelFlagsString> {
static Flags: typeof GuildSystemChannelFlags;
static resolve(bit?: BitFieldResolvable<SystemChannelFlagsString, number>): number;
}
/**
* Application flags bitfield
*/
class ApplicationFlagsBitField extends BitField<ApplicationFlagsString> {
static Flags: typeof ApplicationFlags;
static resolve(bit?: BitFieldResolvable<ApplicationFlagsString, number>): number;
}
/**
* Attachment flags bitfield
*/
class AttachmentFlagsBitField extends BitField<AttachmentFlagsString> {
static Flags: typeof AttachmentFlags;
static resolve(bit?: BitFieldResolvable<AttachmentFlagsString, number>): number;
}
/**
* Channel flags bitfield
*/
class ChannelFlagsBitField extends BitField<ChannelFlagsString> {
static Flags: typeof ChannelFlags;
static resolve(bit?: BitFieldResolvable<ChannelFlagsString, number>): number;
}
/**
* Role flags bitfield
*/
class RoleFlagsBitField extends BitField<RoleFlagsString> {
static Flags: typeof RoleFlags;
static resolve(bit?: BitFieldResolvable<RoleFlagsString, number>): number;
}
/**
* SKU flags bitfield
*/
class SKUFlagsBitField extends BitField<SKUFlagsString> {
static Flags: typeof SKUFlags;
static resolve(bit?: BitFieldResolvable<SKUFlagsString, number>): number;
}
/**
* Thread member flags bitfield
*/
class ThreadMemberFlagsBitField extends BitField<ThreadMemberFlagsString> {
static Flags: typeof ThreadMemberFlags;
static resolve(bit?: BitFieldResolvable<ThreadMemberFlagsString, number>): number;
}Enhanced Map-based collections with utility methods for Discord data management.
/**
* Enhanced Map with utility methods from @discordjs/collection
*/
class Collection<K, V> extends Map<K, V> {
// Array-like methods
at(index: number): V | undefined;
find(fn: (value: V, key: K, collection: this) => boolean): V | undefined;
findKey(fn: (value: V, key: K, collection: this) => boolean): K | undefined;
filter(fn: (value: V, key: K, collection: this) => boolean): Collection<K, V>;
partition(fn: (value: V, key: K, collection: this) => boolean): [Collection<K, V>, Collection<K, V>];
map<T>(fn: (value: V, key: K, collection: this) => T): T[];
mapValues<T>(fn: (value: V, key: K, collection: this) => T): Collection<K, T>;
some(fn: (value: V, key: K, collection: this) => boolean): boolean;
every(fn: (value: V, key: K, collection: this) => boolean): boolean;
reduce<T>(fn: (accumulator: T, value: V, key: K, collection: this) => T, initialValue?: T): T;
// Utility methods
first(): V | undefined;
first(amount: number): V[];
last(): V | undefined;
last(amount: number): V[];
random(): V | undefined;
random(amount: number): V[];
reverse(): this;
toJSON(): Record<string, V>;
// Set operations
difference<T>(other: ReadonlyCollection<K, T>): Collection<K, V>;
intersect<T>(other: ReadonlyCollection<K, T>): Collection<K, V>;
subtract<T>(other: ReadonlyCollection<K, T>): Collection<K, V>;
// Static methods
static combineEntries<K, V>(entries: Iterable<[K, V]>, combine: (firstValue: V, secondValue: V, key: K) => V): Collection<K, V>;
}
/**
* Size-limited collection that removes oldest entries when limit is exceeded
*/
class LimitedCollection<K, V> extends Collection<K, V> {
constructor(options?: LimitedCollectionOptions<K, V>, iterable?: Iterable<readonly [K, V]>);
readonly maxSize: number;
readonly keepOverLimit: ((value: V, key: K, collection: this) => boolean) | null;
set(key: K, value: V): this;
}
interface LimitedCollectionOptions<K, V> {
maxSize?: number;
keepOverLimit?: (value: V, key: K, collection: LimitedCollection<K, V>) => boolean;
}
type ReadonlyCollection<K, V> = ReadonlyMap<K, V> & Omit<Collection<K, V>, 'delete' | 'set'>;Essential Discord constants, colors, and enumerated values.
/**
* Discord color constants
*/
const Colors: {
Default: 0x000000;
White: 0xffffff;
Aqua: 0x1abc9c;
Green: 0x57f287;
Blue: 0x3498db;
Yellow: 0xfee75c;
Purple: 0x9b59b6;
LuminousVividPink: 0xe91e63;
Fuchsia: 0xeb459e;
Gold: 0xf1c40f;
Orange: 0xe67e22;
Red: 0xed4245;
Grey: 0x95a5a6;
Navy: 0x34495e;
DarkAqua: 0x11806a;
DarkGreen: 0x1f8b4c;
DarkBlue: 0x206694;
DarkPurple: 0x71368a;
DarkVividPink: 0xad1457;
DarkGold: 0xc27c0e;
DarkOrange: 0xa84300;
DarkRed: 0x992d22;
DarkGrey: 0x979c9f;
DarkerGrey: 0x7f8c8d;
LightGrey: 0xbcc0c0;
DarkNavy: 0x2c3e50;
Blurple: 0x5865f2;
Greyple: 0x99aab5;
DarkButNotBlack: 0x2c2f33;
NotQuiteBlack: 0x23272a;
};
/**
* Client status constants
*/
const Status: {
Ready: 0;
Connecting: 1;
Reconnecting: 2;
Idle: 3;
Nearly: 4;
Disconnected: 5;
WaitingForGuilds: 6;
Identifying: 7;
Resuming: 8;
};
/**
* Partial types for incomplete data
*/
const Partials: {
Channel: 0;
GuildMember: 1;
Message: 2;
Reaction: 3;
GuildScheduledEvent: 4;
User: 5;
ThreadMember: 6;
};
/**
* General constants used throughout Discord.js
*/
const Constants: {
MaxBulkDeletableMessageAge: 1209600000; // 14 days in milliseconds
Package: {
name: string;
version: string;
description: string;
license: string;
main: string;
types: string;
homepage: string;
keywords: string[];
bugs: { url: string };
repository: { type: string; url: string };
};
};Helper functions for common Discord operations and data manipulation.
/**
* Utility functions for Discord operations
*/
interface UtilityFunctions {
/** Flatten an object's properties */
flatten(obj: unknown, ...props: Record<string, boolean | string>[]): unknown;
/** Get recommended shard count for large bots */
fetchRecommendedShardCount(token: string, options?: FetchRecommendedShardCountOptions): Promise<number>;
/** Parse emoji from string */
parseEmoji(text: string): { animated: boolean; name: string; id: Snowflake | null } | null;
/** Resolve partial emoji data */
resolvePartialEmoji(emoji: EmojiIdentifierResolvable): Partial<APIPartialEmoji> | null;
/** Create standardized error objects */
makeError(Base: ErrorConstructor): ErrorConstructor;
/** Create plain error objects */
makePlainError(Base: ErrorConstructor): ErrorConstructor;
/** Verify string input validity */
verifyString(data: string, error?: typeof Error, errorMessage?: string, allowEmpty?: boolean): string;
/** Resolve color values to numbers */
resolveColor(color: ColorResolvable): number;
/** Discord-style sorting function */
discordSort<T>(collection: Collection<Snowflake, T>): Collection<Snowflake, T>;
/** Set position for ordered items */
setPosition<T extends { rawPosition: number; position: number }>(
item: T,
position: number,
relative: boolean,
sorted: Collection<Snowflake, T>,
client: Client,
route: string,
reason?: string
): Promise<{ id: Snowflake; position: number }[]>;
/** Get path basename */
basename(path: string, ext?: string): string;
/** Clean message content of mentions */
cleanContent(str: string, channel: TextBasedChannel): string;
/** Clean code block content */
cleanCodeBlockContent(str: string): string;
/** Parse webhook URL */
parseWebhookURL(url: string): WebhookClientData | null;
/** Transform resolved interaction data */
transformResolved(data: APIApplicationCommandInteractionDataResolved): CommandInteractionResolvedData;
/** Resolve SKU ID from various inputs */
resolveSKUId(sku: SKUResolvable): Snowflake;
}
interface FetchRecommendedShardCountOptions {
guildsPerShard?: number;
multipleOf?: number;
}
type ColorResolvable =
| 'Default' | 'White' | 'Aqua' | 'Green' | 'Blue' | 'Yellow' | 'Purple'
| 'LuminousVividPink' | 'Fuchsia' | 'Gold' | 'Orange' | 'Red' | 'Grey'
| 'Navy' | 'DarkAqua' | 'DarkGreen' | 'DarkBlue' | 'DarkPurple' | 'DarkVividPink'
| 'DarkGold' | 'DarkOrange' | 'DarkRed' | 'DarkGrey' | 'DarkerGrey' | 'LightGrey'
| 'DarkNavy' | 'Blurple' | 'Greyple' | 'DarkButNotBlack' | 'NotQuiteBlack'
| number | [number, number, number] | string;Utilities for formatting text with Discord markdown and mentions.
/**
* Discord text formatting utilities from @discordjs/formatters
*/
const Formatters: {
/** Format text as bold */
bold(text: string): string;
/** Format text as italic */
italic(text: string): string;
/** Format text with underline */
underscore(text: string): string;
/** Format text with strikethrough */
strikethrough(text: string): string;
/** Format text as inline code */
inlineCode(text: string): string;
/** Format text as code block */
codeBlock(language: string, content: string): string;
codeBlock(content: string): string;
/** Format text as spoiler */
spoiler(text: string): string;
/** Format text as quote */
quote(text: string): string;
/** Format text as block quote */
blockQuote(text: string): string;
/** Create user mention */
userMention(userId: Snowflake): string;
/** Create channel mention */
channelMention(channelId: Snowflake): string;
/** Create role mention */
roleMention(roleId: Snowflake): string;
/** Create custom emoji mention */
formatEmoji(emojiId: Snowflake, animated?: boolean): string;
/** Create timestamp */
time(date?: Date, style?: TimestampStylesString): string;
/** Create hyperlink */
hyperlink(content: string, url: string, title?: string): string;
/** Hide link embeds */
hideLinkEmbed(url: string): string;
};
const TimestampStyles: {
/** Short time (16:20) */
ShortTime: 't';
/** Long time (16:20:30) */
LongTime: 'T';
/** Short date (20/04/2021) */
ShortDate: 'd';
/** Long date (20 April 2021) */
LongDate: 'D';
/** Short date/time (20 April 2021 16:20) */
ShortDateTime: 'f';
/** Long date/time (Tuesday, 20 April 2021 16:20) */
LongDateTime: 'F';
/** Relative time (2 months ago) */
RelativeTime: 'R';
};
type TimestampStylesString = keyof typeof TimestampStyles;Discord snowflake (ID) parsing and manipulation utilities.
/**
* Discord snowflake utilities from @sapphire/snowflake
*/
const SnowflakeUtil: {
/** Generate a snowflake ID */
generate(options?: SnowflakeGenerateOptions): Snowflake;
/** Deconstruct a snowflake into its components */
deconstruct(snowflake: Snowflake): DeconstructedSnowflake;
/** Get timestamp from snowflake */
timestampFrom(snowflake: Snowflake): number;
/** Transform snowflake to BigInt */
toBigInt(snowflake: Snowflake): bigint;
/** Check if string is a valid snowflake */
isValid(snowflake: string): snowflake is Snowflake;
};
interface SnowflakeGenerateOptions {
/** Timestamp to use (defaults to current time) */
timestamp?: number | Date;
/** Worker ID (0-31) */
workerId?: number;
/** Process ID (0-31) */
processId?: number;
/** Increment value (0-4095) */
increment?: number;
}
interface DeconstructedSnowflake {
/** The timestamp of the snowflake */
timestamp: number;
/** The creation date of the snowflake */
date: Date;
/** The worker ID of the snowflake */
workerId: number;
/** The process ID of the snowflake */
processId: number;
/** The increment of the snowflake */
increment: number;
/** The binary representation of the snowflake */
binary: string;
}
type Snowflake = `${bigint}`;Automatic cache cleanup utilities for memory management.
/**
* Cache sweeping utilities for memory management
*/
const Sweepers: {
/** Sweep expired bans */
bans(guild: Guild, filter: SweepFilter<GuildBan>): number;
/** Sweep old messages */
messages(channel: TextBasedChannel, filter: SweepFilter<Message>): number;
/** Sweep inactive members */
guildMembers(guild: Guild, filter: SweepFilter<GuildMember>): number;
/** Sweep old threads */
threads(guild: Guild, filter: SweepFilter<ThreadChannel>): number;
/** Sweep expired invites */
invites(guild: Guild, filter: SweepFilter<Invite>): number;
/** Sweep inactive presences */
presences(guild: Guild, filter: SweepFilter<Presence>): number;
/** Sweep voice states */
voiceStates(guild: Guild, filter: SweepFilter<VoiceState>): number;
/** Sweep application commands */
applicationCommands(client: Client, filter: SweepFilter<ApplicationCommand>): number;
/** Filter factory for old items */
filterByLifetime<T>(options?: LifetimeFilterOptions<T>): SweepFilter<T>;
/** Filter factory for outdated items */
filterOutdatedItems<T>(lifetime?: number): SweepFilter<T>;
};
type SweepFilter<T> = (value: T) => boolean;
interface LifetimeFilterOptions<T> {
/** Maximum age in milliseconds */
lifetime?: number;
/** Additional filter function */
getComparisonTimestamp?: (value: T) => number;
/** Exclude items that match this condition */
excludeFromSweep?: (value: T) => boolean;
}
interface SweeperOptions {
/** Interval between sweeps in seconds */
interval: number;
/** Maximum lifetime in seconds */
lifetime?: number;
/** Custom filter function */
filter?: () => (value: any) => boolean;
}Usage Examples:
// Permission checking utilities
const checkPermissions = (member: GuildMember, channel: GuildChannel) => {
const permissions = member.permissionsIn(channel);
const requiredPerms = new PermissionsBitField([
PermissionFlagsBits.ViewChannel,
PermissionFlagsBits.SendMessages
]);
const hasPerms = permissions.has(requiredPerms);
const missingPerms = permissions.missing(requiredPerms);
return { hasPerms, missingPerms };
};
// Color utilities
const embedColor = resolveColor('Red'); // Returns number
const randomColor = resolveColor([Math.floor(Math.random() * 256), Math.floor(Math.random() * 256), Math.floor(Math.random() * 256)]);
// Text formatting
const formattedMessage = [
Formatters.bold('Important:'),
Formatters.italic('Please read the rules'),
Formatters.userMention(userId),
Formatters.time(new Date(), TimestampStyles.RelativeTime)
].join(' ');
// Collection utilities
const activeMembers = guild.members.cache
.filter(member => member.presence?.status !== 'offline')
.sort((a, b) => b.joinedTimestamp! - a.joinedTimestamp!)
.first(10);
// Snowflake utilities
const messageAge = Date.now() - SnowflakeUtil.timestampFrom(message.id);
const isOldMessage = messageAge > 1000 * 60 * 60 * 24; // 1 day
// Cache sweeping
const sweptMessages = channel.messages.cache.sweep(
Sweepers.filterByLifetime({ lifetime: 1000 * 60 * 60 }) // 1 hour
);
console.log(`Swept ${sweptMessages} old messages`);
// BitField operations
const userFlags = new UserFlagsBitField([UserFlags.BugHunterLevel1, UserFlags.PremiumEarlySupporter]);
const hasNitro = userFlags.has(UserFlags.PremiumEarlySupporter);
const flagsArray = userFlags.toArray(); // ['BugHunterLevel1', 'PremiumEarlySupporter']
// Advanced collection operations
const membersByRole = guild.members.cache
.partition(member => member.roles.cache.has(roleId));
const [membersWithRole, membersWithoutRole] = membersByRole;
const memberStats = guild.members.cache
.reduce((acc, member) => {
acc.total++;
if (member.user.bot) acc.bots++;
else acc.humans++;
return acc;
}, { total: 0, bots: 0, humans: 0 });