UNPKG

@discordjs/structures

Version:

Wrapper around Discord's structures

1 lines 113 kB
{"version":3,"sources":["../src/bitfields/BitField.ts","../src/bitfields/ChannelFlagsBitField.ts","../src/bitfields/PermissionsBitField.ts","../src/utils/symbols.ts","../src/channels/mixins/AppliedTagsMixin.ts","../src/channels/mixins/ChannelOwnerMixin.ts","../src/channels/mixins/GuildChannelMixin.ts","../src/channels/mixins/ChannelParentMixin.ts","../src/channels/mixins/ChannelPermissionMixin.ts","../src/channels/mixins/ChannelPinMixin.ts","../src/channels/mixins/TextChannelMixin.ts","../src/channels/mixins/ChannelSlowmodeMixin.ts","../src/channels/mixins/ChannelWebhookMixin.ts","../src/channels/mixins/ChannelTopicMixin.ts","../src/channels/mixins/DMChannelMixin.ts","../src/channels/mixins/GroupDMMixin.ts","../src/channels/mixins/ThreadChannelMixin.ts","../src/channels/mixins/ThreadOnlyChannelMixin.ts","../src/channels/mixins/VoiceChannelMixin.ts","../src/Structure.ts","../src/channels/ForumTag.ts","../src/channels/PermissionOverwrite.ts","../src/channels/ThreadMetadata.ts","../src/channels/Channel.ts","../src/utils/type-guards.ts","../src/Mixin.ts","../src/channels/AnnouncementChannel.ts","../src/channels/AnnouncementThreadChannel.ts","../src/channels/CategoryChannel.ts","../src/channels/DMChannel.ts","../src/channels/ForumChannel.ts","../src/channels/GroupDMChannel.ts","../src/channels/MediaChannel.ts","../src/channels/PrivateThreadChannel.ts","../src/channels/PublicThreadChannel.ts","../src/channels/StageChannel.ts","../src/channels/TextChannel.ts","../src/channels/VoiceChannel.ts","../src/invites/Invite.ts","../src/users/AvatarDecorationData.ts","../src/users/User.ts","../src/users/Connection.ts","../src/utils/optimization.ts"],"sourcesContent":["import type { EnumLike, NonAbstract, RecursiveReadonlyArray } from '../utils/types.js';\n\n// TODO: this currently is mostly copied from mainlib discord.js v14 and definitely needs a refactor in a later iteration\n\n/**\n * Data that can be resolved to give a bit field. This can be:\n * A bit number (this can be a number literal or a value taken from {@link (BitField:class).Flags})\n * A string bit number\n * An instance of BitField\n * An Array of BitFieldResolvable\n */\nexport type BitFieldResolvable<Flags extends string> =\n\t| Flags\n\t| Readonly<BitField<Flags>>\n\t| RecursiveReadonlyArray<Flags | Readonly<BitField<Flags>> | bigint | number | `${bigint}`>\n\t| bigint\n\t| number\n\t| `${bigint}`;\n\n/**\n * Data structure that makes it easy to interact with a bit field.\n */\nexport abstract class BitField<Flags extends string> {\n\t/**\n\t * Numeric bit field flags.\n\t *\n\t * @remarks Defined in extension classes\n\t */\n\tpublic static readonly Flags: EnumLike<unknown, bigint | number> = {};\n\n\tpublic static readonly DefaultBit: bigint = 0n;\n\n\t/**\n\t * Bitfield of the packed bits\n\t */\n\tpublic bitField: bigint;\n\n\tdeclare public ['constructor']: NonAbstract<typeof BitField<Flags>>;\n\n\t/**\n\t * @param bits - Bit(s) to read from\n\t */\n\tpublic constructor(bits: BitFieldResolvable<Flags> = this.constructor.DefaultBit) {\n\t\tthis.bitField = this.constructor.resolve(bits);\n\t}\n\n\t/**\n\t * Checks whether the bit field has a bit, or any of multiple bits.\n\t *\n\t * @param bit - Bit(s) to check for\n\t * @returns Whether the bit field has the bit(s)\n\t */\n\tpublic any(bit: BitFieldResolvable<Flags>) {\n\t\treturn (this.bitField & this.constructor.resolve(bit)) !== this.constructor.DefaultBit;\n\t}\n\n\t/**\n\t * Checks if this bit field equals another\n\t *\n\t * @param bit - Bit(s) to check for\n\t * @returns Whether this bit field equals the other\n\t */\n\tpublic equals(bit: BitFieldResolvable<Flags>) {\n\t\treturn this.bitField === this.constructor.resolve(bit);\n\t}\n\n\t/**\n\t * Checks whether the bit field has a bit, or multiple bits.\n\t *\n\t * @param bit - Bit(s) to check for\n\t * @returns Whether the bit field has the bit(s)\n\t */\n\tpublic has(bit: BitFieldResolvable<Flags>, ..._hasParams: unknown[]) {\n\t\tconst resolvedBit = this.constructor.resolve(bit);\n\t\treturn (this.bitField & resolvedBit) === resolvedBit;\n\t}\n\n\t/**\n\t * Gets all given bits that are missing from the bit field.\n\t *\n\t * @param bits - Bit(s) to check for\n\t * @param hasParams - Additional parameters for the has method, if any\n\t * @returns A bit field containing the missing bits\n\t */\n\tpublic missing(bits: BitFieldResolvable<Flags>, ...hasParams: readonly unknown[]) {\n\t\treturn new this.constructor(bits).remove(this).toArray(...hasParams);\n\t}\n\n\t/**\n\t * Freezes these bits, making them immutable.\n\t *\n\t * @returns This bit field but frozen\n\t */\n\tpublic freeze() {\n\t\treturn Object.freeze(this);\n\t}\n\n\t/**\n\t * Adds bits to these ones.\n\t *\n\t * @param bits - Bits to add\n\t * @returns These bits or new BitField if the instance is frozen.\n\t */\n\tpublic add(...bits: BitFieldResolvable<Flags>[]) {\n\t\tlet total = this.constructor.DefaultBit;\n\t\tfor (const bit of bits) {\n\t\t\ttotal |= this.constructor.resolve(bit);\n\t\t}\n\n\t\tif (Object.isFrozen(this)) return new this.constructor(this.bitField | total);\n\t\tthis.bitField |= total;\n\t\treturn this;\n\t}\n\n\t/**\n\t * Removes bits from these.\n\t *\n\t * @param bits - Bits to remove\n\t * @returns These bits or new BitField if the instance is frozen.\n\t */\n\tpublic remove(...bits: BitFieldResolvable<Flags>[]) {\n\t\tlet total = this.constructor.DefaultBit;\n\t\tfor (const bit of bits) {\n\t\t\ttotal |= this.constructor.resolve(bit);\n\t\t}\n\n\t\tif (Object.isFrozen(this)) return new this.constructor(this.bitField & ~total);\n\t\tthis.bitField &= ~total;\n\t\treturn this;\n\t}\n\n\t/**\n\t * Gets an object mapping field names to a boolean indicating whether the bit is available.\n\t *\n\t * @param hasParams - Additional parameters for the has method, if any\n\t * @returns An object mapping field names to a boolean indicating whether the bit is available\n\t */\n\tpublic serialize(...hasParams: readonly unknown[]) {\n\t\tconst serialized: Partial<Record<keyof Flags, boolean>> = {};\n\t\tfor (const [flag, bit] of Object.entries(this.constructor.Flags)) {\n\t\t\tif (Number.isNaN(Number(flag))) serialized[flag as keyof Flags] = this.has(bit as bigint | number, ...hasParams);\n\t\t}\n\n\t\treturn serialized;\n\t}\n\n\t/**\n\t * Gets an Array of bit field names based on the bits available.\n\t *\n\t * @param hasParams - Additional parameters for the has method, if any\n\t * @returns An Array of bit field names\n\t */\n\tpublic toArray(...hasParams: readonly unknown[]) {\n\t\treturn [...this[Symbol.iterator](...hasParams)];\n\t}\n\n\tpublic toJSON(asNumber?: boolean) {\n\t\tif (asNumber) {\n\t\t\tif (this.bitField > Number.MAX_SAFE_INTEGER) {\n\t\t\t\tthrow new RangeError(\n\t\t\t\t\t`Cannot convert bitfield value ${this.bitField} to number, as it is bigger than ${Number.MAX_SAFE_INTEGER} (the maximum safe integer)`,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\treturn Number(this.bitField);\n\t\t}\n\n\t\treturn this.bitField.toString();\n\t}\n\n\tpublic valueOf() {\n\t\treturn this.bitField;\n\t}\n\n\tpublic *[Symbol.iterator](...hasParams: unknown[]) {\n\t\tfor (const bitName of Object.keys(this.constructor.Flags)) {\n\t\t\tif (Number.isNaN(Number(bitName)) && this.has(bitName as Flags, ...hasParams)) yield bitName as Flags;\n\t\t}\n\t}\n\n\t/**\n\t * Resolves bit fields to their numeric form.\n\t *\n\t * @param bit - bit(s) to resolve\n\t * @returns the numeric value of the bit fields\n\t */\n\tpublic static resolve<Flags extends string = string>(bit: BitFieldResolvable<Flags>): bigint {\n\t\tconst DefaultBit = this.DefaultBit;\n\t\tif (typeof bit === 'bigint' && bit >= DefaultBit) return bit;\n\t\tif (typeof bit === 'number' && BigInt(bit) >= DefaultBit) return BigInt(bit);\n\t\tif (bit instanceof BitField) return bit.bitField;\n\t\tif (Array.isArray(bit)) {\n\t\t\treturn bit.map((bit_) => this.resolve(bit_)).reduce((prev, bit_) => prev | bit_, DefaultBit);\n\t\t}\n\n\t\tif (typeof bit === 'string') {\n\t\t\tif (!Number.isNaN(Number(bit))) return BigInt(bit);\n\t\t\tif (bit in this.Flags) return this.Flags[bit as keyof typeof this.Flags];\n\t\t}\n\n\t\tthrow new Error(`BitFieldInvalid: ${JSON.stringify(bit)}`);\n\t}\n}\n","import { ChannelFlags } from 'discord-api-types/v10';\nimport { BitField } from './BitField.js';\n\n/**\n * Data structure that makes it easy to interact with a {@link (Channel:class).flags} bitfield.\n */\nexport class ChannelFlagsBitField extends BitField<keyof ChannelFlags> {\n\t/**\n\t * Numeric guild channel flags.\n\t */\n\tpublic static override readonly Flags = ChannelFlags;\n\n\tpublic override toJSON() {\n\t\treturn super.toJSON(true);\n\t}\n}\n","/* eslint-disable unicorn/consistent-function-scoping */\nimport { PermissionFlagsBits } from 'discord-api-types/v10';\nimport type { BitFieldResolvable } from './BitField.js';\nimport { BitField } from './BitField.js';\n\n/**\n * Data structure that makes it easy to interact with a permission bit field. All {@link GuildMember}s have a set of\n * permissions in their guild, and each channel in the guild may also have {@link PermissionOverwrite}s for the member\n * that override their default permissions.\n */\nexport class PermissionsBitField extends BitField<keyof typeof PermissionFlagsBits> {\n\t/**\n\t * Numeric permission flags.\n\t *\n\t * @see {@link https://discord.com/developers/docs/topics/permissions#permissions-bitwise-permission-flags}\n\t */\n\tpublic static override Flags = PermissionFlagsBits;\n\n\t/**\n\t * Bit field representing every permission combined\n\t */\n\tpublic static readonly All = Object.values(PermissionFlagsBits).reduce((all, perm) => all | perm, 0n);\n\n\t/**\n\t * Bit field representing the default permissions for users\n\t */\n\tpublic static readonly Default = 104_324_673n;\n\n\t/**\n\t * Bit field representing the permissions required for moderators of stage channels\n\t */\n\tpublic static readonly StageModerator =\n\t\tPermissionFlagsBits.ManageChannels | PermissionFlagsBits.MuteMembers | PermissionFlagsBits.MoveMembers;\n\n\t/**\n\t * Gets all given bits that are missing from the bit field.\n\t *\n\t * @param bits - Bit(s) to check for\n\t * @param checkAdmin - Whether to allow the administrator permission to override\n\t * @returns A bit field containing the missing permissions\n\t */\n\tpublic override missing(bits: BitFieldResolvable<keyof typeof PermissionFlagsBits>, checkAdmin = true) {\n\t\treturn checkAdmin && this.has(PermissionFlagsBits.Administrator) ? [] : super.missing(bits);\n\t}\n\n\t/**\n\t * Checks whether the bit field has a permission, or any of multiple permissions.\n\t *\n\t * @param permission - Permission(s) to check for\n\t * @param checkAdmin - Whether to allow the administrator permission to override\n\t * @returns Whether the bit field has the permission(s)\n\t */\n\tpublic override any(permission: BitFieldResolvable<keyof typeof PermissionFlagsBits>, checkAdmin = true) {\n\t\treturn (checkAdmin && super.has(PermissionFlagsBits.Administrator)) || super.any(permission);\n\t}\n\n\t/**\n\t * Checks whether the bit field has a permission, or multiple permissions.\n\t *\n\t * @param permission - Permission(s) to check for\n\t * @param checkAdmin - Whether to allow the administrator permission to override\n\t * @returns Whether the bit field has the permission(s)\n\t */\n\tpublic override has(permission: BitFieldResolvable<keyof typeof PermissionFlagsBits>, checkAdmin = true) {\n\t\treturn (checkAdmin && super.has(PermissionFlagsBits.Administrator)) || super.has(permission);\n\t}\n\n\t/**\n\t * Gets an Array of bitfield names based on the permissions available.\n\t *\n\t * @returns An Array of permission names\n\t */\n\tpublic override toArray() {\n\t\treturn super.toArray(false);\n\t}\n}\n","export const kData = Symbol.for('djs.structures.data');\nexport const kClone = Symbol.for('djs.structures.clone');\nexport const kPatch = Symbol.for('djs.structures.patch');\nexport const kExpiresTimestamp = Symbol.for('djs.structures.expiresTimestamp');\nexport const kCreatedTimestamp = Symbol.for('djs.structures.createdTimestamp');\nexport const kEditedTimestamp = Symbol.for('djs.structures.editedTimestamp');\nexport const kArchiveTimestamp = Symbol.for('djs.structures.archiveTimestamp');\n\nexport const kAllow = Symbol.for('djs.structures.allow');\nexport const kDeny = Symbol.for('djs.structures.deny');\n\nexport const kLastPinTimestamp = Symbol.for('djs.structures.lastPinTimestamp');\n\nexport const kMixinConstruct = Symbol.for('djs.structures.mixin.construct');\nexport const kMixinToJSON = Symbol.for('djs.structures.mixin.toJSON');\n","import type { ChannelType } from 'discord-api-types/v10';\nimport { kData } from '../../utils/symbols.js';\nimport type { Channel } from '../Channel.js';\n\nexport interface AppliedTagsMixin extends Channel<ChannelType.PublicThread> {}\n\nexport class AppliedTagsMixin {\n\t/**\n\t * The ids of the set of tags that have been applied to a thread in a {@link (ForumChannel:class)} or a {@link (MediaChannel:class)}.\n\t */\n\tpublic get appliedTags(): readonly string[] | null {\n\t\treturn Array.isArray(this[kData].applied_tags) ? this[kData].applied_tags : null;\n\t}\n}\n","import type { ChannelType, ThreadChannelType } from 'discord-api-types/v10';\nimport { kData } from '../../utils/symbols.js';\nimport type { Channel } from '../Channel.js';\n\nexport interface ChannelOwnerMixin<Type extends ChannelType.GroupDM | ThreadChannelType> extends Channel<Type> {}\n\nexport class ChannelOwnerMixin<Type extends ChannelType.GroupDM | ThreadChannelType> {\n\t/**\n\t * The id of the creator of the group DM or thread\n\t */\n\tpublic get ownerId() {\n\t\treturn this[kData].owner_id;\n\t}\n}\n","import { channelLink } from '@discordjs/formatters';\nimport type { GuildChannelType } from 'discord-api-types/v10';\nimport { ChannelFlagsBitField } from '../../bitfields/ChannelFlagsBitField.js';\nimport { kData } from '../../utils/symbols.js';\nimport type { Channel } from '../Channel.js';\n\nexport interface GuildChannelMixin<Type extends GuildChannelType = GuildChannelType> extends Channel<Type> {}\n\nexport class GuildChannelMixin<Type extends GuildChannelType = GuildChannelType> {\n\t/**\n\t * The flags that are applied to the channel.\n\t *\n\t * @privateRemarks The type of `flags` can be narrowed in Guild Channels and DMChannel to ChannelFlags, and in GroupDM channel\n\t * to null, respecting Omit behaviors\n\t */\n\tpublic get flags() {\n\t\treturn this[kData].flags ? new ChannelFlagsBitField(this[kData].flags) : null;\n\t}\n\n\t/**\n\t * THe id of the guild this channel is in.\n\t */\n\tpublic get guildId() {\n\t\treturn this[kData].guild_id!;\n\t}\n\n\t/**\n\t * The URL to this channel.\n\t */\n\tpublic get url() {\n\t\treturn channelLink(this.id, this.guildId);\n\t}\n\n\t/**\n\t * Indicates whether this channel is in a guild\n\t */\n\tpublic isGuildBased(): this is GuildChannelMixin & this {\n\t\treturn true;\n\t}\n}\n","import type { ChannelType, GuildChannelType } from 'discord-api-types/v10';\nimport { kData } from '../../utils/symbols.js';\nimport { GuildChannelMixin } from './GuildChannelMixin.js';\n\nexport class ChannelParentMixin<\n\tType extends Exclude<GuildChannelType, ChannelType.GuildCategory | ChannelType.GuildDirectory>,\n> extends GuildChannelMixin<Type> {\n\t/**\n\t * The id of the parent category for a channel (each parent category can contain up to 50 channels) or id of the parent channel for a thread\n\t */\n\tpublic get parentId() {\n\t\treturn this[kData].parent_id;\n\t}\n\n\t/**\n\t * Whether the channel is nsfw\n\t */\n\tpublic get nsfw() {\n\t\treturn this[kData].nsfw;\n\t}\n}\n","import type { ChannelType, GuildChannelType, ThreadChannelType } from 'discord-api-types/v10';\nimport { kData } from '../../utils/symbols.js';\nimport type { Channel } from '../Channel.js';\n\nexport interface ChannelPermissionMixin<\n\tType extends Exclude<GuildChannelType, ChannelType.GuildDirectory | ThreadChannelType> = Exclude<\n\t\tGuildChannelType,\n\t\tChannelType.GuildDirectory | ThreadChannelType\n\t>,\n> extends Channel<Type> {}\n\n/**\n * @remarks has an array of sub-structures {@link PermissionOverwrite} that extending mixins should add to their DataTemplate and _optimizeData\n */\nexport class ChannelPermissionMixin<\n\tType extends Exclude<GuildChannelType, ChannelType.GuildDirectory | ThreadChannelType> = Exclude<\n\t\tGuildChannelType,\n\t\tChannelType.GuildDirectory | ThreadChannelType\n\t>,\n> {\n\t/**\n\t * The sorting position of the channel\n\t */\n\tpublic get position() {\n\t\treturn this[kData].position;\n\t}\n\n\t/**\n\t * Indicates whether this channel can have permission overwrites\n\t */\n\tpublic isPermissionCapable(): this is ChannelPermissionMixin & this {\n\t\treturn true;\n\t}\n}\n","import type { ChannelType, ThreadChannelType } from 'discord-api-types/v10';\nimport { kLastPinTimestamp, kMixinConstruct, kMixinToJSON } from '../../utils/symbols.js';\nimport type { Channel, ChannelDataType } from '../Channel.js';\n\nexport interface ChannelPinMixin<\n\tType extends ChannelType.DM | ChannelType.GuildAnnouncement | ChannelType.GuildText | ThreadChannelType,\n> extends Channel<Type> {}\n\nexport class ChannelPinMixin<\n\tType extends ChannelType.DM | ChannelType.GuildAnnouncement | ChannelType.GuildText | ThreadChannelType,\n> {\n\t/**\n\t * The timestamp of when the last pin in the channel happened\n\t */\n\tdeclare protected [kLastPinTimestamp]: number | null;\n\n\t/**\n\t * The template used for removing data from the raw data stored for each Channel.\n\t */\n\tpublic static readonly DataTemplate: Partial<\n\t\tChannelDataType<ChannelType.DM | ChannelType.GuildAnnouncement | ChannelType.GuildText | ThreadChannelType>\n\t> = {\n\t\tset last_pin_timestamp(_: string) {},\n\t};\n\n\tpublic [kMixinConstruct]() {\n\t\tthis[kLastPinTimestamp] ??= null;\n\t}\n\n\t/**\n\t * {@inheritDoc Structure.optimizeData}\n\t */\n\tprotected optimizeData(data: Partial<ChannelDataType<Type>>) {\n\t\tif (data.last_pin_timestamp) {\n\t\t\tthis[kLastPinTimestamp] = Date.parse(data.last_pin_timestamp);\n\t\t}\n\t}\n\n\t/**\n\t * The timestamp of when the last pin in the channel happened.\n\t */\n\tpublic get lastPinTimestamp() {\n\t\treturn this[kLastPinTimestamp];\n\t}\n\n\t/**\n\t * The Date of when the last pin in the channel happened\n\t */\n\tpublic get lastPinAt() {\n\t\tconst lastPinTimestamp = this.lastPinTimestamp;\n\t\treturn lastPinTimestamp ? new Date(lastPinTimestamp) : null;\n\t}\n\n\t/**\n\t * Adds data from optimized properties omitted from [kData].\n\t *\n\t * @param data - the result of {@link (Structure:class).toJSON}\n\t */\n\tprotected [kMixinToJSON](data: Partial<ChannelDataType<Type>>) {\n\t\tdata.last_pin_timestamp = this[kLastPinTimestamp] ? new Date(this[kLastPinTimestamp]).toISOString() : null;\n\t}\n}\n","import type { TextChannelType } from 'discord-api-types/v10';\nimport { kData } from '../../utils/symbols.js';\nimport type { Channel } from '../Channel.js';\n\nexport interface TextChannelMixin<Type extends TextChannelType = TextChannelType> extends Channel<Type> {}\n\nexport class TextChannelMixin<Type extends TextChannelType = TextChannelType> {\n\t/**\n\t * The id of the last message sent in this channel.\n\t */\n\tpublic get lastMessageId() {\n\t\treturn this[kData].last_message_id;\n\t}\n\n\t/**\n\t * Indicates whether this channel can contain messages\n\t */\n\tpublic isTextBased(): this is TextChannelMixin & this {\n\t\treturn true;\n\t}\n}\n","import type { GuildTextChannelType } from 'discord-api-types/v10';\nimport { kData } from '../../utils/symbols.js';\nimport { TextChannelMixin } from './TextChannelMixin.js';\n\nexport class ChannelSlowmodeMixin<Type extends GuildTextChannelType> extends TextChannelMixin<Type> {\n\t/**\n\t * The rate limit per user (slowmode) of this channel.\n\t */\n\tpublic get rateLimitPerUser() {\n\t\treturn this[kData].rate_limit_per_user;\n\t}\n}\n","import type { ChannelType, GuildTextChannelType, ThreadChannelType } from 'discord-api-types/v10';\nimport type { Channel } from '../Channel.js';\n\nexport interface ChannelWebhookMixin<\n\tType extends ChannelType.GuildForum | ChannelType.GuildMedia | Exclude<GuildTextChannelType, ThreadChannelType> =\n\t\t| ChannelType.GuildForum\n\t\t| ChannelType.GuildMedia\n\t\t| Exclude<GuildTextChannelType, ThreadChannelType>,\n> extends Channel<Type> {}\n\nexport class ChannelWebhookMixin<\n\tType extends ChannelType.GuildForum | ChannelType.GuildMedia | Exclude<GuildTextChannelType, ThreadChannelType> =\n\t\t| ChannelType.GuildForum\n\t\t| ChannelType.GuildMedia\n\t\t| Exclude<GuildTextChannelType, ThreadChannelType>,\n> {\n\t/**\n\t * Indicates whether this channel can have webhooks\n\t */\n\tpublic isWebhookCapable(): this is ChannelWebhookMixin & this {\n\t\treturn true;\n\t}\n}\n","import type { ChannelType } from 'discord-api-types/v10';\nimport { kData } from '../../utils/symbols.js';\nimport type { Channel } from '../Channel.js';\nimport { ChannelWebhookMixin } from './ChannelWebhookMixin.js';\n\nexport interface ChannelTopicMixin<\n\tType extends ChannelType.GuildAnnouncement | ChannelType.GuildForum | ChannelType.GuildMedia | ChannelType.GuildText,\n> extends Channel<Type> {}\n\nexport class ChannelTopicMixin<\n\tType extends ChannelType.GuildAnnouncement | ChannelType.GuildForum | ChannelType.GuildMedia | ChannelType.GuildText,\n> extends ChannelWebhookMixin<Type> {\n\t/**\n\t * The topic of this channel.\n\t */\n\tpublic get topic() {\n\t\treturn this[kData].topic;\n\t}\n\n\t/**\n\t * The duration after which new threads get archived by default on this channel.\n\t */\n\tpublic get defaultAutoArchiveDuration() {\n\t\treturn this[kData].default_auto_archive_duration;\n\t}\n\n\t/**\n\t * The default value for rate limit per user (slowmode) on new threads in this channel.\n\t */\n\tpublic get defaultThreadRateLimitPerUser() {\n\t\treturn this[kData].default_thread_rate_limit_per_user;\n\t}\n}\n","import { channelLink } from '@discordjs/formatters';\nimport type { ChannelType } from 'discord-api-types/v10';\nimport type { User } from '../../users/User.js';\nimport type { Channel } from '../Channel.js';\n\nexport interface DMChannelMixin<\n\tType extends ChannelType.DM | ChannelType.GroupDM = ChannelType.DM | ChannelType.GroupDM,\n> extends Channel<Type> {}\n\n/**\n * @remarks has recipients, an array of sub-structures {@link User} that extending mixins should add to their DataTemplate and _optimizeData\n */\nexport class DMChannelMixin<Type extends ChannelType.DM | ChannelType.GroupDM = ChannelType.DM | ChannelType.GroupDM> {\n\t/**\n\t * The URL to this channel.\n\t */\n\tpublic get url() {\n\t\treturn channelLink(this.id);\n\t}\n\n\t/**\n\t * Indicates whether this channel is a DM or DM Group\n\t */\n\tpublic isDMBased(): this is DMChannelMixin & this {\n\t\treturn true;\n\t}\n}\n","import type { ChannelType } from 'discord-api-types/v10';\nimport { kData } from '../../utils/symbols.js';\nimport type { Channel } from '../Channel.js';\n\nexport interface GroupDMMixin extends Channel<ChannelType.GroupDM> {}\n\nexport class GroupDMMixin {\n\t/**\n\t * The icon hash of the group DM.\n\t */\n\tpublic get icon() {\n\t\treturn this[kData].icon;\n\t}\n\n\t/**\n\t * Whether the channel is managed by an application via the `gdm.join` OAuth2 scope.\n\t */\n\tpublic get managed() {\n\t\treturn this[kData].managed;\n\t}\n\n\t/**\n\t * The application id of the group DM creator if it is bot-created.\n\t */\n\tpublic get applicationId() {\n\t\treturn this[kData].application_id;\n\t}\n}\n","import type { ThreadChannelType } from 'discord-api-types/v10';\nimport { kData } from '../../utils/symbols.js';\nimport type { Channel } from '../Channel.js';\n\nexport interface ThreadChannelMixin<Type extends ThreadChannelType = ThreadChannelType> extends Channel<Type> {}\n\n/**\n * @remarks has a sub-structure {@link ThreadMetadata} that extending mixins should add to their DataTemplate and _optimizeData\n */\nexport class ThreadChannelMixin<Type extends ThreadChannelType = ThreadChannelType> {\n\t/**\n\t * The approximate count of users in a thread, stops counting at 50\n\t */\n\tpublic get memberCount() {\n\t\treturn this[kData].member_count;\n\t}\n\n\t/**\n\t * The number of messages (not including the initial message or deleted messages) in a thread.\n\t */\n\tpublic get messageCount() {\n\t\treturn this[kData].message_count;\n\t}\n\n\t/**\n\t * The number of messages ever sent in a thread, it's similar to message_count on message creation,\n\t * but will not decrement the number when a message is deleted.\n\t */\n\tpublic get totalMessageSent() {\n\t\treturn this[kData].total_message_sent;\n\t}\n\n\t/**\n\t * Indicates whether this channel is a thread channel\n\t */\n\tpublic isThread(): this is ThreadChannelMixin & this {\n\t\treturn true;\n\t}\n}\n","import type { ChannelType } from 'discord-api-types/v10';\nimport { kData } from '../../utils/symbols.js';\nimport type { Channel } from '../Channel.js';\n\nexport interface ThreadOnlyChannelMixin<\n\tType extends ChannelType.GuildForum | ChannelType.GuildMedia = ChannelType.GuildForum | ChannelType.GuildMedia,\n> extends Channel<Type> {}\n\n/**\n * @remarks has an array of sub-structures {@link ForumTag} that extending mixins should add to their DataTemplate and _optimizeData\n */\nexport class ThreadOnlyChannelMixin<\n\tType extends ChannelType.GuildForum | ChannelType.GuildMedia = ChannelType.GuildForum | ChannelType.GuildMedia,\n> {\n\t/**\n\t * The emoji to show in the add reaction button on a thread in this channel.\n\t */\n\tpublic get defaultReactionEmoji() {\n\t\treturn this[kData].default_reaction_emoji;\n\t}\n\n\t/**\n\t * The default sort order type used to order posts in this channel.\n\t *\n\t * @defaultValue `null` – indicates a preferred sort order hasn't been set.\n\t */\n\tpublic get defaultSortOrder() {\n\t\treturn this[kData].default_sort_order!;\n\t}\n\n\t/**\n\t * Indicates whether this channel only allows thread creation\n\t */\n\tpublic isThreadOnly(): this is ThreadOnlyChannelMixin & this {\n\t\treturn true;\n\t}\n}\n","import type { ChannelType } from 'discord-api-types/v10';\nimport { kData } from '../../utils/symbols.js';\nimport type { Channel } from '../Channel.js';\nimport { TextChannelMixin } from './TextChannelMixin.js';\n\nexport interface VoiceChannelMixin<\n\tType extends ChannelType.GuildStageVoice | ChannelType.GuildVoice =\n\t\t| ChannelType.GuildStageVoice\n\t\t| ChannelType.GuildVoice,\n> extends Channel<Type> {}\n\nexport class VoiceChannelMixin<\n\tType extends ChannelType.GuildStageVoice | ChannelType.GuildVoice =\n\t\t| ChannelType.GuildStageVoice\n\t\t| ChannelType.GuildVoice,\n> extends TextChannelMixin<Type> {\n\t/**\n\t * The bitrate (in bits) of the voice channel.\n\t */\n\tpublic get bitrate() {\n\t\treturn this[kData].bitrate!;\n\t}\n\n\t/**\n\t * The voice region id for this channel, automatic when set to null.\n\t */\n\tpublic get rtcRegion() {\n\t\treturn this[kData].rtc_region!;\n\t}\n\n\t/**\n\t * The camera video quality mode of the voice channel, {@link discord-api-types/v10#(VideoQualityMode:enum) | Auto} when not present.\n\t */\n\tpublic get videoQualityMode() {\n\t\treturn this[kData].video_quality_mode!;\n\t}\n\n\t/**\n\t * The user limit of the voice channel.\n\t */\n\tpublic get userLimit() {\n\t\treturn this[kData].user_limit!;\n\t}\n\n\t/**\n\t * Indicates whether this channel has voice connection capabilities\n\t */\n\tpublic override isVoiceBased(): this is VoiceChannelMixin & this {\n\t\treturn true;\n\t}\n}\n","import { kClone, kData, kMixinConstruct, kMixinToJSON, kPatch } from './utils/symbols.js';\nimport type { ReplaceOmittedWithUnknown } from './utils/types.js';\n\nexport const DataTemplatePropertyName = 'DataTemplate';\nexport const OptimizeDataPropertyName = 'optimizeData';\n\n/**\n * Represents a data model from the Discord API\n *\n * @privateRemarks\n * Explanation of the type complexity surround Structure:\n *\n * There are two layers of Omitted generics, one here, which allows omitting things at the library level so we do not accidentally\n * access them, in addition to whatever the user does at the layer above.\n *\n * The second layer, in the exported structure is effectively a type cast that allows the getters types to match whatever data template is used\n *\n * In order to safely set and access this data, the constructor and patch take data as \"partial\" and forcibly assigns it to kData. To accommodate this,\n * kData stores properties as `unknown` when it is omitted, which allows accessing the property in getters even when it may not actually be present.\n * This is the most technically correct way of representing the value, especially since there is no way to guarantee runtime matches the \"type cast.\"\n */\nexport abstract class Structure<DataType extends {}, Omitted extends keyof DataType | '' = ''> {\n\t/**\n\t * A construct function used when mixing to allow mixins to set optimized property defaults\n\t *\n\t * @internal\n\t * @remarks This should only be used to set defaults, setting optimized values should be done\n\t * in the mixins `optimizeData` method, which will be called automatically.\n\t * @param data - The full API data received by the Structure\n\t */\n\tprotected [kMixinConstruct]?(data: Partial<DataType>): void;\n\n\t/**\n\t * A function used when mixing to allow mixins to add properties to the result of toJSON\n\t *\n\t * @internal\n\t * @remarks This should only be used to add properties that the mixin optimizes, if the raw\n\t * JSON data is unchanged the property will already be returned.\n\t * @param data - The result of the base class toJSON Structure before it gets returned\n\t */\n\tprotected [kMixinToJSON]?(data: Partial<DataType>): void;\n\n\t/**\n\t * The template used for removing data from the raw data stored for each Structure.\n\t *\n\t * @remarks This template should be overridden in all subclasses to provide more accurate type information.\n\t * The template in the base {@link Structure} class will have no effect on most subclasses for this reason.\n\t */\n\tprotected static readonly DataTemplate: Record<string, unknown> = {};\n\n\t/**\n\t * @returns A cloned version of the data template, ready to create a new data object.\n\t */\n\tprivate getDataTemplate() {\n\t\treturn Object.create((this.constructor as typeof Structure).DataTemplate);\n\t}\n\n\t/**\n\t * The raw data from the API for this structure\n\t *\n\t * @internal\n\t */\n\tprotected [kData]: Readonly<ReplaceOmittedWithUnknown<Omitted, DataType>>;\n\n\t/**\n\t * Creates a new structure to represent API data\n\t *\n\t * @param data - the data from the API that this structure will represent\n\t * @remarks To be made public in subclasses\n\t * @internal\n\t */\n\tpublic constructor(data: Readonly<Partial<DataType>>, ..._rest: unknown[]) {\n\t\tthis[kData] = Object.assign(this.getDataTemplate(), data);\n\t\tthis[kMixinConstruct]?.(data);\n\t}\n\n\t/**\n\t * Patches the raw data of this object in place\n\t *\n\t * @param data - the updated data from the API to patch with\n\t * @remarks To be made public in subclasses\n\t * @returns this\n\t * @internal\n\t */\n\tprotected [kPatch](data: Readonly<Partial<DataType>>): this {\n\t\tthis[kData] = Object.assign(this.getDataTemplate(), this[kData], data);\n\t\tthis.optimizeData(data);\n\t\treturn this;\n\t}\n\n\t/**\n\t * Creates a clone of this structure\n\t *\n\t * @returns a clone of this\n\t * @internal\n\t */\n\tprotected [kClone](patchPayload?: Readonly<Partial<DataType>>): typeof this {\n\t\tconst clone = this.toJSON();\n\t\t// @ts-expect-error constructor is of abstract class is unknown\n\t\treturn new this.constructor(\n\t\t\t// Ensure the ts-expect-error only applies to the constructor call\n\t\t\tpatchPayload ? Object.assign(clone, patchPayload) : clone,\n\t\t);\n\t}\n\n\t/**\n\t * Function called to ensure stored raw data is in optimized formats, used in tandem with a data template\n\t *\n\t * @example created_timestamp is an ISO string, this can be stored in optimized form as a number\n\t * @param _data - the raw data received from the API to optimize\n\t * @remarks Implementation to be done in subclasses and mixins where needed.\n\t * For typescript users, mixins must use the closest ancestors access modifier.\n\t * @remarks Automatically called in Structure[kPatch] but must be called manually in the constructor\n\t * of any class implementing this method.\n\t * @remarks Additionally, when implementing, ensure to call `super._optimizeData` if any class in the super chain aside\n\t * from Structure contains an implementation.\n\t * Note: mixins do not need to call super ever as the process of mixing walks the prototype chain.\n\t * @virtual\n\t * @internal\n\t */\n\tprotected optimizeData(_data: Partial<DataType>) {}\n\n\t/**\n\t * Transforms this object to its JSON format with raw API data (or close to it),\n\t * automatically called by `JSON.stringify()` when this structure is stringified\n\t *\n\t * @remarks\n\t * The type of this data is determined by omissions at runtime and is only guaranteed for default omissions\n\t * @privateRemarks\n\t * When omitting properties at the library level, this must be overridden to re-add those properties\n\t */\n\tpublic toJSON(): DataType {\n\t\t// This will be DataType provided nothing is omitted, when omits occur, subclass needs to overwrite this.\n\t\tconst data =\n\t\t\t// Spread is way faster than structuredClone, but is shallow. So use it only if there is no nested objects\n\t\t\t(\n\t\t\t\tObject.values(this[kData]).some((value) => typeof value === 'object' && value !== null)\n\t\t\t\t\t? structuredClone(this[kData])\n\t\t\t\t\t: { ...this[kData] }\n\t\t\t) as DataType;\n\t\tthis[kMixinToJSON]?.(data);\n\t\treturn data;\n\t}\n}\n","import type { APIGuildForumTag } from 'discord-api-types/v10';\nimport { Structure } from '../Structure.js';\nimport { kData } from '../utils/symbols.js';\nimport type { Partialize } from '../utils/types.js';\n\n/**\n * Represents metadata of a thread channel on Discord.\n *\n * @typeParam Omitted - Specify the properties that will not be stored in the raw data field as a union, implement via `DataTemplate`\n */\nexport class ForumTag<Omitted extends keyof APIGuildForumTag | '' = ''> extends Structure<APIGuildForumTag, Omitted> {\n\tpublic constructor(data: Partialize<APIGuildForumTag, Omitted>) {\n\t\tsuper(data);\n\t}\n\n\t/**\n\t * The id of the tag.\n\t */\n\tpublic get id() {\n\t\treturn this[kData].id;\n\t}\n\n\t/**\n\t * The name of the tag.\n\t */\n\tpublic get name() {\n\t\treturn this[kData].name;\n\t}\n\n\t/**\n\t * Whether this tag can only be added to or removed from threads by a member with the {@link discord-api-types/v10#(PermissionFlagsBits:variable) | ManageThreads} permission.\n\t */\n\tpublic get moderated() {\n\t\treturn this[kData].moderated;\n\t}\n\n\t/**\n\t * The id of a guild's custom emoji.\n\t */\n\tpublic get emojiId() {\n\t\treturn this[kData].emoji_id;\n\t}\n\n\t/**\n\t * The unicode character of the emoji.\n\t */\n\tpublic get emojiName() {\n\t\treturn this[kData].emoji_name;\n\t}\n\n\t/**\n\t * The textual representation of this tag's emoji. Either a unicode character or a guild emoji mention.\n\t */\n\tpublic get emoji() {\n\t\treturn this.emojiName ?? `<:_:${this.emojiId}>`;\n\t}\n}\n","import type { APIOverwrite } from 'discord-api-types/v10';\nimport { Structure } from '../Structure.js';\nimport { PermissionsBitField } from '../bitfields/PermissionsBitField.js';\nimport { kAllow, kData, kDeny } from '../utils/symbols.js';\nimport type { Partialize } from '../utils/types.js';\n\n/**\n * Represents metadata of a thread channel on Discord.\n *\n * @typeParam Omitted - Specify the properties that will not be stored in the raw data field as a union, implement via `DataTemplate`\n */\nexport class PermissionOverwrite<Omitted extends keyof APIOverwrite | '' = 'allow' | 'deny'> extends Structure<\n\tAPIOverwrite,\n\tOmitted\n> {\n\tprotected [kAllow]: bigint | null = null;\n\n\tprotected [kDeny]: bigint | null = null;\n\n\tpublic constructor(data: Partialize<APIOverwrite, Omitted>) {\n\t\tsuper(data);\n\t\tthis.optimizeData(data);\n\t}\n\n\t/**\n\t * The template used for removing data from the raw data stored for each ThreadMetadata\n\t *\n\t * @remarks This template has defaults, if you want to remove additional data and keep the defaults,\n\t * use `Object.defineProperties`. To override the defaults, set this value directly.\n\t */\n\tpublic static override readonly DataTemplate: Partial<APIOverwrite> = {\n\t\tset allow(_: string) {},\n\t\tset deny(_: string) {},\n\t};\n\n\t/**\n\t * {@inheritDoc Structure.optimizeData}\n\t */\n\tprotected override optimizeData(data: Partial<APIOverwrite>) {\n\t\tif (data.allow) {\n\t\t\tthis[kAllow] = BigInt(data.allow);\n\t\t}\n\n\t\tif (data.deny) {\n\t\t\tthis[kDeny] = BigInt(data.deny);\n\t\t}\n\t}\n\n\t/**\n\t * The permission bit set allowed by this overwrite.\n\t */\n\tpublic get allow() {\n\t\tconst allow = this[kAllow];\n\t\treturn typeof allow === 'bigint' ? new PermissionsBitField(allow) : null;\n\t}\n\n\t/**\n\t * The permission bit set denied by this overwrite.\n\t */\n\tpublic get deny() {\n\t\tconst deny = this[kDeny];\n\t\treturn typeof deny === 'bigint' ? new PermissionsBitField(deny) : null;\n\t}\n\n\t/**\n\t * The role or user id for this overwrite.\n\t */\n\tpublic get id() {\n\t\treturn this[kData].id;\n\t}\n\n\t/**\n\t * The type of this overwrite.\n\t */\n\tpublic get type() {\n\t\treturn this[kData].type;\n\t}\n\n\t/**\n\t * {@inheritDoc Structure.toJSON}\n\t */\n\tpublic override toJSON() {\n\t\tconst clone = super.toJSON();\n\t\tif (this[kAllow]) {\n\t\t\tclone.allow = this[kAllow].toString();\n\t\t}\n\n\t\tif (this[kDeny]) {\n\t\t\tclone.deny = this[kDeny].toString();\n\t\t}\n\n\t\treturn clone;\n\t}\n}\n","import type { APIThreadMetadata } from 'discord-api-types/v10';\nimport { Structure } from '../Structure.js';\nimport { kArchiveTimestamp, kCreatedTimestamp, kData } from '../utils/symbols.js';\nimport type { Partialize } from '../utils/types.js';\n\n/**\n * Represents metadata of a thread channel on Discord.\n *\n * @typeParam Omitted - Specify the properties that will not be stored in the raw data field as a union, implement via `DataTemplate`\n */\nexport class ThreadMetadata<\n\tOmitted extends keyof APIThreadMetadata | '' = 'archive_timestamp' | 'create_timestamp',\n> extends Structure<APIThreadMetadata, Omitted> {\n\tprotected [kArchiveTimestamp]: number | null = null;\n\n\tprotected [kCreatedTimestamp]: number | null = null;\n\n\tpublic constructor(data: Partialize<APIThreadMetadata, Omitted>) {\n\t\tsuper(data);\n\t\tthis.optimizeData(data);\n\t}\n\n\t/**\n\t * The template used for removing data from the raw data stored for each ThreadMetadata\n\t *\n\t * @remarks This template has defaults, if you want to remove additional data and keep the defaults,\n\t * use `Object.defineProperties`. To override the defaults, set this value directly.\n\t */\n\tpublic static override readonly DataTemplate: Partial<APIThreadMetadata> = {\n\t\tset create_timestamp(_: string) {},\n\t\tset archive_timestamp(_: string) {},\n\t};\n\n\t/**\n\t * {@inheritDoc Structure.optimizeData}\n\t */\n\tprotected override optimizeData(data: Partial<APIThreadMetadata>) {\n\t\tif (data.create_timestamp) {\n\t\t\tthis[kCreatedTimestamp] = Date.parse(data.create_timestamp);\n\t\t}\n\n\t\tif (data.archive_timestamp) {\n\t\t\tthis[kArchiveTimestamp] = Date.parse(data.archive_timestamp);\n\t\t}\n\t}\n\n\t/**\n\t * Whether the thread is archived.\n\t */\n\tpublic get archived() {\n\t\treturn this[kData].archived;\n\t}\n\n\t/**\n\t * The timestamp when the thread's archive status was last changed, used for calculating recent activity.\n\t */\n\tpublic get archivedTimestamp() {\n\t\treturn this[kArchiveTimestamp];\n\t}\n\n\t/**\n\t * The timestamp when the thread was created; only populated for threads created after 2022-01-09.\n\t */\n\tpublic get createdTimestamp() {\n\t\treturn this[kCreatedTimestamp];\n\t}\n\n\t/**\n\t * The thread will stop showing in the channel list after auto_archive_duration minutes of inactivity,\n\t */\n\tpublic get autoArchiveDuration() {\n\t\treturn this[kData].auto_archive_duration;\n\t}\n\n\t/**\n\t * Whether non-moderators can add other non-moderators to a thread; only available on private threads.\n\t */\n\tpublic get invitable() {\n\t\treturn this[kData].invitable;\n\t}\n\n\t/**\n\t * Whether the thread is locked; when a thread is locked, only users with {@link discord-api-types/v10#(PermissionFlagsBits:variable) | ManageThreads} can unarchive it.\n\t */\n\tpublic get locked() {\n\t\treturn this[kData].locked;\n\t}\n\n\t/**\n\t * The time the thread was archived at\n\t */\n\tpublic get archivedAt() {\n\t\tconst archivedTimestamp = this.archivedTimestamp;\n\t\treturn archivedTimestamp ? new Date(archivedTimestamp) : null;\n\t}\n\n\t/**\n\t * The time the thread was created at\n\t */\n\tpublic get createdAt() {\n\t\tconst createdTimestamp = this.createdTimestamp;\n\t\treturn createdTimestamp ? new Date(createdTimestamp) : null;\n\t}\n\n\t/**\n\t * {@inheritDoc Structure.toJSON}\n\t */\n\tpublic override toJSON() {\n\t\tconst data = super.toJSON();\n\t\tif (this[kArchiveTimestamp]) {\n\t\t\tdata.archive_timestamp = new Date(this[kArchiveTimestamp]).toISOString();\n\t\t}\n\n\t\tif (this[kCreatedTimestamp]) {\n\t\t\tdata.create_timestamp = new Date(this[kCreatedTimestamp]).toISOString();\n\t\t}\n\n\t\treturn data;\n\t}\n}\n","import { DiscordSnowflake } from '@sapphire/snowflake';\nimport type { APIChannel, APIPartialChannel, ChannelType, ChannelFlags } from 'discord-api-types/v10';\nimport { Structure } from '../Structure.js';\nimport { ChannelFlagsBitField } from '../bitfields/ChannelFlagsBitField.js';\nimport { kData, kPatch } from '../utils/symbols.js';\nimport { isIdSet } from '../utils/type-guards.js';\nimport type { Partialize } from '../utils/types.js';\nimport type { ChannelPermissionMixin } from './mixins/ChannelPermissionMixin.js';\nimport type { ChannelWebhookMixin } from './mixins/ChannelWebhookMixin.js';\nimport type { DMChannelMixin } from './mixins/DMChannelMixin.js';\nimport type { GuildChannelMixin } from './mixins/GuildChannelMixin.js';\nimport type { TextChannelMixin } from './mixins/TextChannelMixin.js';\nimport type { ThreadChannelMixin } from './mixins/ThreadChannelMixin.js';\nimport type { ThreadOnlyChannelMixin } from './mixins/ThreadOnlyChannelMixin.js';\nimport type { VoiceChannelMixin } from './mixins/VoiceChannelMixin.js';\n\nexport type PartialChannel = Channel<ChannelType, Exclude<keyof APIChannel, keyof APIPartialChannel>>;\n\n/**\n * The data stored by a {@link Channel} structure based on its {@link (Channel:class).\"type\"} property.\n */\nexport type ChannelDataType<Type extends ChannelType | 'unknown'> = Type extends ChannelType\n\t? Extract<APIChannel, { type: Type }>\n\t: APIPartialChannel;\n\n/**\n * Represents any channel on Discord.\n *\n * @typeParam Type - Specify the type of the channel being constructed for more accurate data types\n * @typeParam Omitted - Specify the properties that will not be stored in the raw data field as a union, implement via `DataTemplate`\n * @remarks Although this class _can_ be instantiated directly for any channel type,\n * it's intended to be subclassed with the appropriate mixins for each channel type.\n */\nexport class Channel<\n\tType extends ChannelType | 'unknown' = ChannelType,\n\tOmitted extends keyof ChannelDataType<Type> | '' = '',\n> extends Structure<ChannelDataType<Type>, Omitted> {\n\t/**\n\t * The template used for removing data from the raw data stored for each Channel.\n\t *\n\t * @remarks This template is only guaranteed to apply to channels constructed directly via `new Channel()`.\n\t * Use the appropriate subclass template to remove data from that channel type.\n\t */\n\tpublic static override readonly DataTemplate: Partial<APIChannel> = {};\n\n\t/**\n\t * @param data - The raw data received from the API for the channel\n\t */\n\tpublic constructor(data: Partialize<ChannelDataType<Type>, Omitted>) {\n\t\tsuper(data as ChannelDataType<Type>);\n\t}\n\n\t/**\n\t * {@inheritDoc Structure.[kPatch]}\n\t *\n\t * @internal\n\t */\n\tpublic override [kPatch](data: Partial<ChannelDataType<Type>>) {\n\t\treturn super[kPatch](data);\n\t}\n\n\t/**\n\t * The id of the channel\n\t */\n\tpublic get id() {\n\t\treturn this[kData].id;\n\t}\n\n\t/**\n\t * The type of the channel\n\t */\n\tpublic get type() {\n\t\t// This cast can be incorrect when type is omitted and if the wrong type of channel was constructed\n\t\treturn this[kData].type as Type extends 'unknown' ? number : Type;\n\t}\n\n\t/**\n\t * The name of the channel, null for DMs\n\t *\n\t * @privateRemarks The type of `name` can be narrowed in Guild Channels and DM channels to string and null respectively,\n\t * respecting Omit behaviors\n\t */\n\tpublic get name() {\n\t\treturn this[kData].name;\n\t}\n\n\t/**\n\t * The flags that are applied to the channel.\n\t *\n\t * @privateRemarks The type of `flags` can be narrowed in Guild Channels and DMChannel to ChannelFlags, and in GroupDM channel\n\t * to null, respecting Omit behaviors\n\t */\n\tpublic get flags() {\n\t\tconst flags =\n\t\t\t'flags' in this[kData] && typeof this[kData].flags === 'number' ? (this[kData].flags as ChannelFlags) : null;\n\t\treturn flags ? new ChannelFlagsBitField(flags) : null;\n\t}\n\n\t/**\n\t * The timestamp the channel was created at\n\t */\n\tpublic get createdTimestamp() {\n\t\treturn isIdSet(this.id) ? DiscordSnowflake.timestampFrom(this.id) : null;\n\t}\n\n\t/**\n\t * The time the channel was created at\n\t */\n\tpublic get createdAt() {\n\t\tconst createdTimestamp = this.createdTimestamp;\n\t\treturn createdTimestamp ? new Date(createdTimestamp) : null;\n\t}\n\n\t/**\n\t * Indicates whether this channel is a thread channel\n\t *\n\t * @privateRemarks Overridden to `true` on `ThreadChannelMixin`\n\t */\n\tpublic isThread(): this is ThreadChannelMixin & this {\n\t\treturn false;\n\t}\n\n\t/**\n\t * Indicates whether this channel can contain messages\n\t *\n\t * @privateRemarks Overridden to `true` on `TextChannelMixin`\n\t */\n\tpublic isTextBased(): this is TextChannelMixin & this {\n\t\treturn false;\n\t}\n\n\t/**\n\t * Indicates whether this channel is in a guild\n\t *\n\t * @privateRemarks Overridden to `true` on `GuildChannelMixin`\n\t */\n\tpublic isGuildBased(): this is GuildChannelMixin & this {\n\t\treturn false;\n\t}\n\n\t/**\n\t * Indicates whether this channel is a DM or DM Group\n\t *\n\t * @privateRemarks Overridden to `true` on `DMChannelMixin`\n\t */\n\tpublic isDMBased(): this is DMChannelMixin & this {\n\t\treturn false;\n\t}\n\n\t/**\n\t * Indicates whether this channel has voice connection capabilities\n\t *\n\t * @privateRemarks Overridden to `true` on `VoiceChannelMixin`\n\t */\n\tpublic isVoiceBased(): this is VoiceChannelMixin & this {\n\t\treturn false;\n\t}\n\n\t/**\n\t * Indicates whether this channel only allows thread creation\n\t *\n\t * @privateRemarks Overridden to `true` on `ThreadOnlyChannelMixin`\n\t */\n\tpublic isThreadOnly(): this is ThreadOnlyChannelMixin & this {\n\t\treturn false;\n\t}\n\n\t/**\n\t * Indicates whether this channel can have permission overwrites\n\t *\n\t * @privateRemarks Overridden to `true` on `ChannelPermissionsMixin`\n\t */\n\tpublic isPermissionCapable(): this is ChannelPermissionMixin & this {\n\t\treturn false;\n\t}\n\n\t/**\n\t * Indicates whether this channel can have webhooks\n\t *\n\t * @privateRemarks Overridden to `true` on `ChannelWebhooksMixin`\n\t */\n\tpublic isWebhookCapable(): this is ChannelWebhookMixin & this {\n\t\treturn false;\n\t}\n}\n","export function isIdSet(id: unknown): id is bigint | string {\n\treturn typeof id === 'string' || typeof id === 'bigint';\n}\n","import { DataTemplatePropertyName, OptimizeDataPropertyName, type Structure } from './Structure.js';\nimport { kMixinConstruct, kMixinToJSON } from './utils/symbols.js';\n\nexport type Mixinable<ClassType> = new (...args: unknown[]) => ClassType;\n\nexport type MixinBase<BaseClass extends Structure<{}>> =\n\tBaseClass extends Structure<infer DataType, infer Omitted> ? Structure<DataType, Omitted> : never;\n\n/**\n * Copies the prototype (getters, setters, and methods) of all mixins to the destination class.\n * For type information see {@link MixinTypes}\n *\n * @param destination - The class to apply the mixins to, must extend the base that the mixins expect it to.\n * @param mixins - Classes that contain \"pure\" prototypes to be copied on top of the destination class prototype\n * @remarks All mixins should be \"pure\" in that they only contain getters, setters, and methods.\n * The runtime code will only copy these, and adding properties to the class only results\n * in the types of the mixed class being wrong.\n * @example\n * ```\n * // Interface merging on the mixin to give type access to props on the base and kData that are available once copied\n * interface TextMixin extends Channel {}\n * class TextMixin {\n * \t// Methods / getters\n * }\n *\n * // Interface merging on the mixed class to give it accurate type information within the declaration and when instantiated\n * interface TextChannel extends MixinTypes<Channel, [TextMixin]> {}\n * class TextChannel extends Channel {}\n *\n * // Apply for runtime\n * Mixin(TextChannel, [TextMixin])\n * ```\n * @typeParam DestinationClass - The class to be mixed, ensures that the mixins provided can be used with this destination\n */\nexport function Mixin<DestinationClass extends typeof Structure<{}>>(\n\tdestination: DestinationClass,\n\tmixins: Mixinable<MixinBase<DestinationClass['prototype']>>[],\n) {\n\tconst dataTemplates: Record<string, unknown>[] = [];\n\tconst dataOptimizatio