diff --git a/packages/bot/src/transformers.ts b/packages/bot/src/transformers.ts index 7390aaf1b..ea42425f2 100644 --- a/packages/bot/src/transformers.ts +++ b/packages/bot/src/transformers.ts @@ -75,7 +75,7 @@ import { import { transformIntegration, type Integration } from './transformers/integration.js' import { transformInteraction, transformInteractionDataOption, type Interaction, type InteractionDataOption } from './transformers/interaction.js' import { transformInvite, type Invite } from './transformers/invite.js' -import { transformMember, transformUser, type Member, type User } from './transformers/member.js' +import { transformMember, type Member } from './transformers/member.js' import { transformMessage, type Message } from './transformers/message.js' import { transformPresence, type PresenceUpdate } from './transformers/presence.js' import { transformAllowedMentionsToDiscordAllowedMentions } from './transformers/reverse/allowedMentions.js' @@ -88,6 +88,7 @@ import { transformSticker, transformStickerPack, type Sticker, type StickerPack import { transformTeam, type Team } from './transformers/team.js' import { transformTemplate, type Template } from './transformers/template.js' import { transformThreadMember, type ThreadMember } from './transformers/threadMember.js' +import { transformUser, type User } from './transformers/user.js' import { transformVoiceRegion, type VoiceRegions } from './transformers/voiceRegion.js' import { transformVoiceState, type VoiceState } from './transformers/voiceState.js' import { transformWebhook, type Webhook } from './transformers/webhook.js' @@ -98,7 +99,7 @@ import type { BotInteractionResponse, DiscordComponent, DiscordInteractionRespon export interface Transformers { customizers: { - interaction: (bot: Bot, payload: DiscordInteraction, interaction: Interaction) => any; + interaction: (bot: Bot, payload: DiscordInteraction, interaction: Interaction) => any message: (bot: Bot, payload: DiscordMessage, message: Message) => any } desiredProperties: { @@ -271,20 +272,20 @@ export interface Transformers { webhookId: boolean } role: { - name: boolean; - guildId: boolean; - position: boolean; - color: boolean; - id: boolean; - botId: boolean; - integrationId: boolean; - permissions: boolean; - icon: boolean; - unicodeEmoji: boolean; + name: boolean + guildId: boolean + position: boolean + color: boolean + id: boolean + botId: boolean + integrationId: boolean + permissions: boolean + icon: boolean + unicodeEmoji: boolean } scheduledEvent: { - id: boolean; - guildId: boolean; + id: boolean + guildId: boolean channelId: boolean creatorId: boolean scheduledStartTime: boolean @@ -320,8 +321,25 @@ export interface Transformers { user: boolean sortValue: boolean } + user: { + username: boolean + locale: boolean + flags: boolean + premiumType: boolean + publicFlags: boolean + accentColor: boolean + id: boolean + discriminator: boolean + avatar: boolean + bot: boolean + system: boolean + mfaEnabled: boolean + verified: boolean + email: boolean + banner: boolean + } webhook: { - id: boolean; + id: boolean type: boolean guildId: boolean channelId: boolean @@ -622,6 +640,23 @@ export function createTransformers(options: Partial): Transformers user: false, sortValue: false, }, + user: { + username: false, + locale: false, + flags: false, + premiumType: false, + publicFlags: false, + accentColor: false, + id: false, + discriminator: false, + avatar: false, + bot: false, + system: false, + mfaEnabled: false, + verified: false, + email: false, + banner: false, + }, webhook: { id: false, type: false, @@ -635,7 +670,7 @@ export function createTransformers(options: Partial): Transformers sourceGuild: false, sourceChannel: false, url: false, - } + }, }, reverse: { allowedMentions: options.reverse?.allowedMentions ?? transformAllowedMentionsToDiscordAllowedMentions, diff --git a/packages/bot/src/transformers/interaction.ts b/packages/bot/src/transformers/interaction.ts index ac0ccfe41..b7b0afbc9 100644 --- a/packages/bot/src/transformers/interaction.ts +++ b/packages/bot/src/transformers/interaction.ts @@ -10,9 +10,10 @@ import { Collection } from '@discordeno/utils' import type { Bot, Component } from '../index.js' import type { DiscordInteractionDataResolved } from '../typings.js' import type { Attachment } from './attachment.js' -import type { Member, User } from './member.js' +import type { Member } from './member.js' import type { Message } from './message.js' import type { Role } from './role.js' +import type { User } from './user.js' export interface Interaction { /** Id of the interaction */ diff --git a/packages/bot/src/transformers/member.ts b/packages/bot/src/transformers/member.ts index 16a51de73..f85f87a8d 100644 --- a/packages/bot/src/transformers/member.ts +++ b/packages/bot/src/transformers/member.ts @@ -1,27 +1,8 @@ -import type { DiscordMember, DiscordUser } from '@discordeno/types' +import type { DiscordMember } from '@discordeno/types' import { iconHashToBigInt } from '@discordeno/utils' import type { Bot } from '../bot.js' import type { Optionalize } from '../optionalize.js' import { MemberToggles } from './toggles/member.js' -import { UserToggles } from './toggles/user.js' - -// eslint-disable-next-line @typescript-eslint/explicit-function-return-type -export function transformUser(bot: Bot, payload: DiscordUser) { - const user = { - id: bot.transformers.snowflake(payload.id || ''), - username: payload.username, - discriminator: payload.discriminator, - avatar: payload.avatar ? iconHashToBigInt(payload.avatar) : undefined, - locale: payload.locale, - email: payload.email ?? undefined, - flags: payload.flags, - premiumType: payload.premium_type, - publicFlags: payload.public_flags, - toggles: new UserToggles(payload), - } - - return user as Optionalize -} // eslint-disable-next-line @typescript-eslint/explicit-function-return-type export function transformMember(bot: Bot, payload: DiscordMember, guildId: bigint, userId: bigint) { @@ -43,4 +24,3 @@ export function transformMember(bot: Bot, payload: DiscordMember, guildId: bigin } export interface Member extends ReturnType {} -export interface User extends ReturnType {} diff --git a/packages/bot/src/transformers/message.ts b/packages/bot/src/transformers/message.ts index f73f95314..4ed44189a 100644 --- a/packages/bot/src/transformers/message.ts +++ b/packages/bot/src/transformers/message.ts @@ -7,8 +7,9 @@ import type { Channel } from './channel.js' import type { Component } from './component.js' import type { Embed } from './embed.js' import type { Emoji } from './emoji.js' -import type { Member, User } from './member.js' +import type { Member } from './member.js' import { ToggleBitfield } from './toggles/ToggleBitfield.js' +import type { User } from './user.js' const baseMessage: Partial & MessageBase = { get crossposted() { diff --git a/packages/bot/src/transformers/user.ts b/packages/bot/src/transformers/user.ts new file mode 100644 index 000000000..ffe79dbc3 --- /dev/null +++ b/packages/bot/src/transformers/user.ts @@ -0,0 +1,84 @@ +import type { DiscordUser, PremiumTypes } from '@discordeno/types' +import { iconHashToBigInt } from '@discordeno/utils' +import { ToggleBitfield, UserToggles, type Bot } from '../index.js' + +const baseUser: Partial & BaseUser = { + get tag() { + // eslint-disable-next-line @typescript-eslint/restrict-template-expressions + return `${this.username}#${this.discriminator}` + }, + get bot() { + return !!this.toggles?.has('bot') + }, + get system() { + return !!this.toggles?.has('system') + }, + get mfaEnabled() { + return !!this.toggles?.has('mfaEnabled') + }, + get verified() { + return !!this.toggles?.has('verified') + }, +} + +export function transformUser(bot: Bot, payload: DiscordUser): User { + const user: User = Object.create(baseUser) + const props = bot.transformers.desiredProperties.user + + if (props.bot || props.system || props.mfaEnabled || props.verified) { + user.toggles = new UserToggles(payload) + } + if (props.flags) user.flags = new ToggleBitfield(payload.flags) + if (props.publicFlags) user.publicFlags = new ToggleBitfield(payload.public_flags) + if (payload.id && props.id) user.id = bot.transformers.snowflake(payload.id) + if (payload.username && props.username) user.username = payload.username + if (payload.discriminator && props.discriminator) user.discriminator = payload.discriminator + if (payload.locale && props.locale) user.locale = payload.locale + if (payload.email && props.email) user.email = payload.email + if (payload.premium_type && props.premiumType) user.premiumType = payload.premium_type + if (payload.avatar && props.avatar) user.avatar = iconHashToBigInt(payload.avatar) + if (payload.banner && props.banner) user.banner = iconHashToBigInt(payload.banner) + if (payload.accent_color && props.accentColor) user.accentColor = payload.accent_color + + return user +} + +export interface BaseUser { + /** The user tag in the form of username#discriminator */ + tag: string + /** Whether the user belongs to an OAuth2 application */ + bot: boolean + /** Whether the user is an Official Discord System user (part of the urgent message system) */ + system: boolean + /** Whether the user has two factor enabled on their account */ + mfaEnabled: boolean + /** Whether the email on this account has been verified */ + verified: boolean +} + +export interface User extends BaseUser { + /** Compressed version of all the booleans on a user. */ + toggles?: UserToggles + /** The user's username, not unique across the platform */ + username: string + /** The user's chosen language option */ + locale?: string + /** The flags on a user's account */ + flags?: ToggleBitfield + /** The type of Nitro subscription on a user's account */ + premiumType?: PremiumTypes + /** The public flags on a user's account */ + publicFlags?: ToggleBitfield + /** the user's banner color encoded as an integer representation of hexadecimal color code */ + accentColor?: number + /** The user's id */ + id: bigint + /** The user's 4-digit discord-tag */ + discriminator: string + /** The user's avatar hash */ + avatar?: bigint + /** The user's email */ + email?: string + /** the user's banner, or null if unset */ + banner?: bigint +} diff --git a/packages/types/src/discord.ts b/packages/types/src/discord.ts index 5cd128bfa..f8c74a24d 100644 --- a/packages/types/src/discord.ts +++ b/packages/types/src/discord.ts @@ -37,7 +37,6 @@ import type { TargetTypes, TeamMembershipStates, TextStyles, - UserFlags, VerificationLevels, VideoQualityModes, WebhookTypes, @@ -50,11 +49,11 @@ export interface DiscordUser { /** The user's chosen language option */ locale?: string /** The flags on a user's account */ - flags?: UserFlags + flags?: number /** The type of Nitro subscription on a user's account */ premium_type?: PremiumTypes /** The public flags on a user's account */ - public_flags?: UserFlags + public_flags?: number /** the user's banner color encoded as an integer representation of hexadecimal color code */ accent_color?: number /** The user's id */