mirror of
https://github.com/discordeno/discordeno.git
synced 2026-09-17 08:47:22 +00:00
feat(user)!: add more getters for user transformer (#4661)
* feat: enhance user tag getter * feat(user): add `0000` condition and better jsdoc for tag * chore(user): use this keyword instead of destructuring assignment * fix(user): correct isLegacy logic * feat(images): add ImageOptions * refactor(images)!: split avatarUrl into more specific functions and add displayAvatarUrl * feat(user)!: add more useful getters for user * fix: update tests for images * chore: using n suffix for bigint instead of converting to bigint Co-authored-by: Fleny <Fleny113@outlook.com> * fix: update dependencies for avatarUrl Co-authored-by: Fleny <Fleny113@outlook.com> * fix(user): correct the avatarUrl second parameter to avatar hash Co-authored-by: Fleny <Fleny113@outlook.com> * chore: undo unnecessary // from auto comment hotkey Co-authored-by: Fleny <Fleny113@outlook.com> --------- Co-authored-by: Fleny <Fleny113@outlook.com>
This commit is contained in:
+56
-147
@@ -1,6 +1,11 @@
|
||||
import { type BigString, type GetGuildWidgetImageQuery, type ImageFormat, type ImageSize, StickerFormatTypes } from '@discordeno/types'
|
||||
import { iconBigintToHash } from './hash.js'
|
||||
|
||||
export interface ImageOptions {
|
||||
size?: ImageSize
|
||||
format?: ImageFormat
|
||||
}
|
||||
|
||||
/** Help format an image url. */
|
||||
export function formatImageUrl(url: string, size: ImageSize = 128, format?: ImageFormat): string {
|
||||
return `${url}.${format ?? (url.includes('/a_') ? 'gif' : 'webp')}?size=${size}`
|
||||
@@ -25,26 +30,43 @@ export function emojiUrl(emojiId: BigString, animated = false, format: ImageForm
|
||||
* Builds a URL to a user's avatar stored in the Discord CDN.
|
||||
*
|
||||
* @param userId - The ID of the user to get the avatar of.
|
||||
* @param discriminator - The user's discriminator. (4-digit tag after the hashtag.)
|
||||
* @param avatar - The user's avatar hash.
|
||||
* @param options - The parameters for the building of the URL.
|
||||
* @returns The link to the resource.
|
||||
* @returns The user avatar as a URL.
|
||||
*/
|
||||
export function avatarUrl(
|
||||
userId: BigString,
|
||||
discriminator: string,
|
||||
options?: {
|
||||
avatar: BigString | undefined
|
||||
size?: ImageSize
|
||||
format?: ImageFormat
|
||||
},
|
||||
): string {
|
||||
return options?.avatar
|
||||
? formatImageUrl(
|
||||
`https://cdn.discordapp.com/avatars/${userId}/${typeof options.avatar === 'string' ? options.avatar : iconBigintToHash(options.avatar)}`,
|
||||
options?.size ?? 128,
|
||||
options?.format,
|
||||
)
|
||||
: `https://cdn.discordapp.com/embed/avatars/${discriminator === '0' ? (BigInt(userId) >> BigInt(22)) % BigInt(6) : Number(discriminator) % 5}.png`
|
||||
export function avatarUrl(userId: BigString, avatar: BigString, options?: ImageOptions): string {
|
||||
return formatImageUrl(
|
||||
`https://cdn.discordapp.com/avatars/${userId}/${typeof avatar === 'string' ? avatar : iconBigintToHash(avatar)}`,
|
||||
options?.size ?? 128,
|
||||
options?.format,
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds a URL to a user's default avatar stored in the Discord CDN.
|
||||
*
|
||||
* @param userId - The ID of the user to get the avatar of.
|
||||
* @param discriminator - The user's discriminator. (4-digit tag after the hashtag.)
|
||||
* @returns The user default avatar as an URL.
|
||||
*/
|
||||
export function defaultAvatarUrl(userId: BigString, discriminator: string) {
|
||||
const isLegacy = discriminator === '0' || discriminator === '0000'
|
||||
const index = isLegacy ? (BigInt(userId) >> 22n) % 6n : Number(discriminator) % 5
|
||||
|
||||
return `https://cdn.discordapp.com/embed/avatars/${index}.png`
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds a URL to a user's display avatar stored in the Discord CDN.
|
||||
*
|
||||
* @param userId - The ID of the user to get the avatar of.
|
||||
* @param discriminator - The user's discriminator. (4-digit tag after the hashtag.)
|
||||
* @param avatar - The user's avatar hash.
|
||||
* @param options - The parameters for the building of the URL.
|
||||
* @returns The user display avatar as an URL.
|
||||
*/
|
||||
export function displayAvatarUrl(userId: BigString, discriminator: string, avatar: BigString | undefined, options?: ImageOptions): string {
|
||||
return avatar ? avatarUrl(userId, avatar, options) : defaultAvatarUrl(userId, discriminator)
|
||||
}
|
||||
|
||||
export function avatarDecorationUrl(avatarDecoration: BigString): string {
|
||||
@@ -60,14 +82,7 @@ export function avatarDecorationUrl(avatarDecoration: BigString): string {
|
||||
* @param options - The parameters for the building of the URL.
|
||||
* @returns The link to the resource or `undefined` if no banner has not been set.
|
||||
*/
|
||||
export function bannerUrl(
|
||||
userId: BigString,
|
||||
options?: {
|
||||
banner?: BigString
|
||||
size?: ImageSize
|
||||
format?: ImageFormat
|
||||
},
|
||||
): string | undefined {
|
||||
export function bannerUrl(userId: BigString, options?: ImageOptions & { banner?: BigString }): string | undefined {
|
||||
return options?.banner
|
||||
? formatImageUrl(
|
||||
`https://cdn.discordapp.com/banners/${userId}/${typeof options.banner === 'string' ? options.banner : iconBigintToHash(options.banner)}`,
|
||||
@@ -84,14 +99,7 @@ export function bannerUrl(
|
||||
* @param options - The parameters for the building of the URL.
|
||||
* @returns The link to the resource or `undefined` if no banner has been set.
|
||||
*/
|
||||
export function guildBannerUrl(
|
||||
guildId: BigString,
|
||||
options: {
|
||||
banner?: BigString
|
||||
size?: ImageSize
|
||||
format?: ImageFormat
|
||||
},
|
||||
): string | undefined {
|
||||
export function guildBannerUrl(guildId: BigString, options: ImageOptions & { banner?: BigString }): string | undefined {
|
||||
return options.banner
|
||||
? formatImageUrl(
|
||||
`https://cdn.discordapp.com/banners/${guildId}/${typeof options.banner === 'string' ? options.banner : iconBigintToHash(options.banner)}`,
|
||||
@@ -109,14 +117,7 @@ export function guildBannerUrl(
|
||||
* @param options - The parameters for the building of the URL.
|
||||
* @returns The link to the resource or `undefined` if no banner has been set.
|
||||
*/
|
||||
export function guildIconUrl(
|
||||
guildId: BigString,
|
||||
imageHash: BigString | undefined,
|
||||
options?: {
|
||||
size?: ImageSize
|
||||
format?: ImageFormat
|
||||
},
|
||||
): string | undefined {
|
||||
export function guildIconUrl(guildId: BigString, imageHash: BigString | undefined, options?: ImageOptions): string | undefined {
|
||||
return imageHash
|
||||
? formatImageUrl(
|
||||
`https://cdn.discordapp.com/icons/${guildId}/${typeof imageHash === 'string' ? imageHash : iconBigintToHash(imageHash)}`,
|
||||
@@ -134,14 +135,7 @@ export function guildIconUrl(
|
||||
* @param options - The parameters for the building of the URL.
|
||||
* @returns The link to the resource or `undefined` if the guild does not have a splash image set.
|
||||
*/
|
||||
export function guildSplashUrl(
|
||||
guildId: BigString,
|
||||
imageHash: BigString | undefined,
|
||||
options?: {
|
||||
size?: ImageSize
|
||||
format?: ImageFormat
|
||||
},
|
||||
): string | undefined {
|
||||
export function guildSplashUrl(guildId: BigString, imageHash: BigString | undefined, options?: ImageOptions): string | undefined {
|
||||
return imageHash
|
||||
? formatImageUrl(
|
||||
`https://cdn.discordapp.com/splashes/${guildId}/${typeof imageHash === 'string' ? imageHash : iconBigintToHash(imageHash)}`,
|
||||
@@ -159,14 +153,7 @@ export function guildSplashUrl(
|
||||
* @param options - The parameters for the building of the URL.
|
||||
* @returns The link to the resource or `undefined` if the guild does not have a splash image set.
|
||||
*/
|
||||
export function guildDiscoverySplashUrl(
|
||||
guildId: BigString,
|
||||
imageHash: BigString | undefined,
|
||||
options?: {
|
||||
size?: ImageSize
|
||||
format?: ImageFormat
|
||||
},
|
||||
): string | undefined {
|
||||
export function guildDiscoverySplashUrl(guildId: BigString, imageHash: BigString | undefined, options?: ImageOptions): string | undefined {
|
||||
return imageHash
|
||||
? formatImageUrl(
|
||||
`https://cdn.discordapp.com/discovery-splashes/${guildId}/${typeof imageHash === 'string' ? imageHash : iconBigintToHash(imageHash)}`,
|
||||
@@ -183,14 +170,7 @@ export function guildDiscoverySplashUrl(
|
||||
* @param options - The parameters for the building of the URL.
|
||||
* @returns The link to the resource or `undefined`.
|
||||
*/
|
||||
export function guildScheduledEventCoverUrl(
|
||||
eventId: BigString,
|
||||
options: {
|
||||
cover?: BigString
|
||||
size?: ImageSize
|
||||
format?: ImageFormat
|
||||
},
|
||||
): string | undefined {
|
||||
export function guildScheduledEventCoverUrl(eventId: BigString, options: ImageOptions & { cover?: BigString }): string | undefined {
|
||||
return options.cover
|
||||
? formatImageUrl(
|
||||
`https://cdn.discordapp.com/guild-events/${eventId}/${typeof options.cover === 'string' ? options.cover : iconBigintToHash(options.cover)}`,
|
||||
@@ -225,15 +205,7 @@ export function getWidgetImageUrl(guildId: BigString, options?: GetGuildWidgetIm
|
||||
* @param options - The parameters for the building of the URL.
|
||||
* @returns The link to the resource or `undefined` if no banner has been set.
|
||||
*/
|
||||
export function memberAvatarUrl(
|
||||
guildId: BigString,
|
||||
userId: BigString,
|
||||
options?: {
|
||||
avatar?: BigString
|
||||
size?: ImageSize
|
||||
format?: ImageFormat
|
||||
},
|
||||
): string | undefined {
|
||||
export function memberAvatarUrl(guildId: BigString, userId: BigString, options?: ImageOptions & { avatar?: BigString }): string | undefined {
|
||||
return options?.avatar
|
||||
? formatImageUrl(
|
||||
`https://cdn.discordapp.com/guilds/${guildId}/users/${userId}/avatars/${
|
||||
@@ -253,15 +225,7 @@ export function memberAvatarUrl(
|
||||
* @param options - The parameters for the building of the URL.
|
||||
* @returns The link to the resource or `undefined` if no banner has been set.
|
||||
*/
|
||||
export function memberBannerUrl(
|
||||
guildId: BigString,
|
||||
userId: BigString,
|
||||
options?: {
|
||||
banner?: BigString
|
||||
size?: ImageSize
|
||||
format?: ImageFormat
|
||||
},
|
||||
): string | undefined {
|
||||
export function memberBannerUrl(guildId: BigString, userId: BigString, options?: ImageOptions & { banner?: BigString }): string | undefined {
|
||||
return options?.banner
|
||||
? formatImageUrl(
|
||||
`https://cdn.discordapp.com/guilds/${guildId}/users/${userId}/banners/${
|
||||
@@ -281,14 +245,7 @@ export function memberBannerUrl(
|
||||
* @param options - The parameters for the building of the URL.
|
||||
* @returns The link to the resource or `undefined`
|
||||
*/
|
||||
export function applicationIconUrl(
|
||||
applicationId: BigString,
|
||||
iconHash: BigString | undefined,
|
||||
options?: {
|
||||
size?: ImageSize
|
||||
format?: ImageFormat
|
||||
},
|
||||
): string | undefined {
|
||||
export function applicationIconUrl(applicationId: BigString, iconHash: BigString | undefined, options?: ImageOptions): string | undefined {
|
||||
return iconHash
|
||||
? formatImageUrl(
|
||||
`https://cdn.discordapp.com/app-icons/${applicationId}/${typeof iconHash === 'string' ? iconHash : iconBigintToHash(iconHash)}`,
|
||||
@@ -306,14 +263,7 @@ export function applicationIconUrl(
|
||||
* @param options - The parameters for the building of the URL.
|
||||
* @returns The link to the resource or `undefined`.
|
||||
*/
|
||||
export function applicationCoverUrl(
|
||||
applicationId: BigString,
|
||||
coverHash: BigString | undefined,
|
||||
options?: {
|
||||
size?: ImageSize
|
||||
format?: ImageFormat
|
||||
},
|
||||
): string | undefined {
|
||||
export function applicationCoverUrl(applicationId: BigString, coverHash: BigString | undefined, options?: ImageOptions): string | undefined {
|
||||
return coverHash
|
||||
? formatImageUrl(
|
||||
`https://cdn.discordapp.com/app-icons/${applicationId}/${typeof coverHash === 'string' ? coverHash : iconBigintToHash(coverHash)}`,
|
||||
@@ -331,14 +281,7 @@ export function applicationCoverUrl(
|
||||
* @param options - The parameters for the building of the URL.
|
||||
* @returns The link to the resource or `undefined`.
|
||||
*/
|
||||
export function applicationAssetUrl(
|
||||
applicationId: BigString,
|
||||
assetId: BigString | undefined,
|
||||
options?: {
|
||||
size?: ImageSize
|
||||
format?: ImageFormat
|
||||
},
|
||||
): string | undefined {
|
||||
export function applicationAssetUrl(applicationId: BigString, assetId: BigString | undefined, options?: ImageOptions): string | undefined {
|
||||
return assetId
|
||||
? formatImageUrl(
|
||||
`https://cdn.discordapp.com/app-icons/${applicationId}/${typeof assetId === 'string' ? assetId : iconBigintToHash(assetId)}`,
|
||||
@@ -355,13 +298,7 @@ export function applicationAssetUrl(
|
||||
* @param options - The parameters for the building of the URL.
|
||||
* @returns The link to the resource or `undefined`.
|
||||
*/
|
||||
export function stickerPackBannerUrl(
|
||||
bannerAssetId: BigString | undefined,
|
||||
options?: {
|
||||
size?: ImageSize
|
||||
format?: ImageFormat
|
||||
},
|
||||
): string | undefined {
|
||||
export function stickerPackBannerUrl(bannerAssetId: BigString | undefined, options?: ImageOptions): string | undefined {
|
||||
return bannerAssetId
|
||||
? formatImageUrl(
|
||||
`https://cdn.discordapp.com/app-assets/710982414301790216/store/${
|
||||
@@ -380,14 +317,7 @@ export function stickerPackBannerUrl(
|
||||
* @param options - The parameters for the building of the URL.
|
||||
* @returns The link to the resource or `undefined`.
|
||||
*/
|
||||
export function stickerUrl(
|
||||
stickerId: BigString | number,
|
||||
options?: {
|
||||
size?: ImageSize
|
||||
format?: ImageFormat
|
||||
type?: StickerFormatTypes
|
||||
},
|
||||
): string | undefined {
|
||||
export function stickerUrl(stickerId: BigString | number, options?: ImageOptions & { type?: StickerFormatTypes }): string | undefined {
|
||||
if (!stickerId) return
|
||||
|
||||
const url =
|
||||
@@ -406,14 +336,7 @@ export function stickerUrl(
|
||||
* @param options - The parameters for the building of the URL.
|
||||
* @returns The link to the resource or `undefined`.
|
||||
*/
|
||||
export function teamIconUrl(
|
||||
teamId: BigString,
|
||||
iconHash: BigString | undefined,
|
||||
options?: {
|
||||
size?: ImageSize
|
||||
format?: ImageFormat
|
||||
},
|
||||
): string | undefined {
|
||||
export function teamIconUrl(teamId: BigString, iconHash: BigString | undefined, options?: ImageOptions): string | undefined {
|
||||
return iconHash
|
||||
? formatImageUrl(
|
||||
`https://cdn.discordapp.com/team-icons/${teamId}/store/${typeof iconHash === 'string' ? iconHash : iconBigintToHash(iconHash)}`,
|
||||
@@ -431,14 +354,7 @@ export function teamIconUrl(
|
||||
* @param options - The parameters for the building of the URL.
|
||||
* @returns The link to the resource or `undefined`.
|
||||
*/
|
||||
export function roleIconUrl(
|
||||
roleId: BigString,
|
||||
iconHash: BigString | undefined,
|
||||
options?: {
|
||||
size?: ImageSize
|
||||
format?: ImageFormat
|
||||
},
|
||||
): string | undefined {
|
||||
export function roleIconUrl(roleId: BigString, iconHash: BigString | undefined, options?: ImageOptions): string | undefined {
|
||||
return iconHash
|
||||
? formatImageUrl(
|
||||
`https://cdn.discordapp.com/role-icons/${roleId}/${typeof iconHash === 'string' ? iconHash : iconBigintToHash(iconHash)}`,
|
||||
@@ -456,14 +372,7 @@ export function roleIconUrl(
|
||||
* @param options - The parameters for the building of the URL.
|
||||
* @returns The link to the resource or `undefined` if no badge has been set.
|
||||
*/
|
||||
export function guildTagBadgeUrl(
|
||||
guildId: BigString,
|
||||
badgeHash: BigString | undefined,
|
||||
options?: {
|
||||
size?: ImageSize
|
||||
format?: ImageFormat
|
||||
},
|
||||
): string | undefined {
|
||||
export function guildTagBadgeUrl(guildId: BigString, badgeHash: BigString | undefined, options?: ImageOptions): string | undefined {
|
||||
if (badgeHash === undefined) return undefined
|
||||
|
||||
return formatImageUrl(`https://cdn.discordapp.com/guild-tag-badges/${guildId}/${badgeHash}`, options?.size ?? 128, options?.format)
|
||||
|
||||
@@ -1,6 +1,16 @@
|
||||
import { expect } from 'chai'
|
||||
import { describe, it } from 'mocha'
|
||||
import { avatarUrl, emojiUrl, formatImageUrl, getWidgetImageUrl, guildBannerUrl, guildIconUrl, guildSplashUrl } from '../src/images.js'
|
||||
import {
|
||||
avatarUrl,
|
||||
defaultAvatarUrl,
|
||||
displayAvatarUrl,
|
||||
emojiUrl,
|
||||
formatImageUrl,
|
||||
getWidgetImageUrl,
|
||||
guildBannerUrl,
|
||||
guildIconUrl,
|
||||
guildSplashUrl,
|
||||
} from '../src/images.js'
|
||||
|
||||
describe('images.ts', () => {
|
||||
describe('formatImageUrl function', () => {
|
||||
@@ -55,27 +65,39 @@ describe('images.ts', () => {
|
||||
|
||||
describe('avatarUrl function', () => {
|
||||
it('will return the url for given avatar icon hash', () => {
|
||||
expect(
|
||||
avatarUrl('207324334904049664', '9130', {
|
||||
avatar: 'db26a6fb924c985f66b79364cf5797b7',
|
||||
}),
|
||||
).to.equal('https://cdn.discordapp.com/avatars/207324334904049664/db26a6fb924c985f66b79364cf5797b7.webp?size=128')
|
||||
expect(avatarUrl('207324334904049664', 'db26a6fb924c985f66b79364cf5797b7')).to.equal(
|
||||
'https://cdn.discordapp.com/avatars/207324334904049664/db26a6fb924c985f66b79364cf5797b7.webp?size=128',
|
||||
)
|
||||
})
|
||||
|
||||
it('will return the url for given avatar icon bigint', () => {
|
||||
expect(
|
||||
avatarUrl('207324334904049664', '9130', {
|
||||
avatar: 4034407661299384404326332419647968090039n,
|
||||
}),
|
||||
).to.equal('https://cdn.discordapp.com/avatars/207324334904049664/db26a6fb924c985f66b79364cf5797b7.webp?size=128')
|
||||
expect(avatarUrl('207324334904049664', 4034407661299384404326332419647968090039n)).to.equal(
|
||||
'https://cdn.discordapp.com/avatars/207324334904049664/db26a6fb924c985f66b79364cf5797b7.webp?size=128',
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
describe('defaultAvatarUrl function', () => {
|
||||
it('will return the url for default avatar', () => {
|
||||
expect(defaultAvatarUrl('207324334904049664', '9130')).to.equal('https://cdn.discordapp.com/embed/avatars/0.png')
|
||||
})
|
||||
})
|
||||
|
||||
describe('displayAvatarUrl function', () => {
|
||||
it('will return the url for given avatar icon hash', () => {
|
||||
expect(displayAvatarUrl('207324334904049664', '9130', 'db26a6fb924c985f66b79364cf5797b7')).to.equal(
|
||||
'https://cdn.discordapp.com/avatars/207324334904049664/db26a6fb924c985f66b79364cf5797b7.webp?size=128',
|
||||
)
|
||||
})
|
||||
|
||||
it('will return the url for given avatar icon bigint', () => {
|
||||
expect(displayAvatarUrl('207324334904049664', '9130', 4034407661299384404326332419647968090039n)).to.equal(
|
||||
'https://cdn.discordapp.com/avatars/207324334904049664/db26a6fb924c985f66b79364cf5797b7.webp?size=128',
|
||||
)
|
||||
})
|
||||
|
||||
it('will return the url for default avatar', () => {
|
||||
expect(
|
||||
avatarUrl('207324334904049664', '9130', {
|
||||
avatar: undefined,
|
||||
}),
|
||||
).to.equal('https://cdn.discordapp.com/embed/avatars/0.png')
|
||||
expect(displayAvatarUrl('207324334904049664', '9130', undefined)).to.equal('https://cdn.discordapp.com/embed/avatars/0.png')
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
Reference in New Issue
Block a user