diff --git a/packages/discord.js/src/client/Client.js b/packages/discord.js/src/client/Client.js index 82c3c8320125..f73a70d1cebc 100644 --- a/packages/discord.js/src/client/Client.js +++ b/packages/discord.js/src/client/Client.js @@ -638,6 +638,11 @@ module.exports = Client; * @see {@link https://discord.js.org/docs/packages/rest/stable/ImageURLOptions:Interface} */ +/** + * @external EmojiURLOptions + * @see {@link https://discord.js.org/docs/packages/rest/stable/EmojiURLOptions:TypeAlias} + */ + /** * @external BaseImageURLOptions * @see {@link https://discord.js.org/docs/packages/rest/stable/BaseImageURLOptions:Interface} diff --git a/packages/discord.js/src/structures/BaseGuildEmoji.js b/packages/discord.js/src/structures/BaseGuildEmoji.js index a5c2d5da1bf8..544a2dc55b9b 100644 --- a/packages/discord.js/src/structures/BaseGuildEmoji.js +++ b/packages/discord.js/src/structures/BaseGuildEmoji.js @@ -58,7 +58,7 @@ class BaseGuildEmoji extends Emoji { * @method imageURL * @memberof BaseGuildEmoji * @instance - * @param {BaseImageURLOptions} [options] Options for the image URL + * @param {EmojiURLOptions} [options] Options for the emoji URL * @returns {string} */ diff --git a/packages/discord.js/src/structures/Emoji.js b/packages/discord.js/src/structures/Emoji.js index 9451fb043b0b..29a93dbb9951 100644 --- a/packages/discord.js/src/structures/Emoji.js +++ b/packages/discord.js/src/structures/Emoji.js @@ -45,7 +45,7 @@ class Emoji extends Base { /** * Returns a URL for the emoji or `null` if this is not a custom emoji. - * @param {BaseImageURLOptions} [options] Options for the image URL + * @param {EmojiURLOptions} [options] Options for the emoji URL * @returns {?string} */ imageURL(options) { diff --git a/packages/discord.js/typings/index.d.ts b/packages/discord.js/typings/index.d.ts index c6b3b3e8c597..1b3254c8bdf5 100644 --- a/packages/discord.js/typings/index.d.ts +++ b/packages/discord.js/typings/index.d.ts @@ -37,7 +37,7 @@ import { } from '@discordjs/formatters'; import { Awaitable, JSONEncodable } from '@discordjs/util'; import { Collection, ReadonlyCollection } from '@discordjs/collection'; -import { BaseImageURLOptions, ImageURLOptions, RawFile, REST, RESTOptions } from '@discordjs/rest'; +import { BaseImageURLOptions, ImageURLOptions, RawFile, REST, RESTOptions, EmojiURLOptions } from '@discordjs/rest'; import { WebSocketManager as WSWebSocketManager, IShardingStrategy, @@ -697,7 +697,7 @@ export abstract class BaseGuild extends Base { export class BaseGuildEmoji extends Emoji { protected constructor(client: Client, data: RawGuildEmojiData, guild: Guild | GuildPreview); - public imageURL(options?: BaseImageURLOptions): string; + public imageURL(options?: EmojiURLOptions): string; public get url(): string; public available: boolean | null; public get createdAt(): Date; @@ -1492,7 +1492,7 @@ export class Emoji extends Base { public id: Snowflake | null; public name: string | null; public get identifier(): string; - public imageURL(options?: BaseImageURLOptions): string | null; + public imageURL(options?: EmojiURLOptions): string | null; public get url(): string | null; public toJSON(): unknown; public toString(): string; diff --git a/packages/rest/__tests__/CDN.test.ts b/packages/rest/__tests__/CDN.test.ts index c5551c3adbf9..786158efe8e7 100644 --- a/packages/rest/__tests__/CDN.test.ts +++ b/packages/rest/__tests__/CDN.test.ts @@ -54,7 +54,7 @@ test('discoverySplash default', () => { expect(cdn.discoverySplash(id, hash)).toEqual(`${baseCDN}/discovery-splashes/${id}/${hash}.webp`); }); -test('emoji default', () => { +test('emoji', () => { expect(cdn.emoji(id)).toEqual(`${baseCDN}/emojis/${id}.webp`); }); @@ -62,6 +62,14 @@ test('emoji gif', () => { expect(cdn.emoji(id, 'gif')).toEqual(`${baseCDN}/emojis/${id}.gif`); }); +test('emoji animated', () => { + expect(cdn.emoji(id, { animated: true })).toEqual(`${baseCDN}/emojis/${id}.webp?animated=true`); +}); + +test('emoji with GIF format', () => { + expect(cdn.emoji(id, { extension: 'gif' })).toEqual(`${baseCDN}/emojis/${id}.gif`); +}); + test('guildMemberAvatar default', () => { expect(cdn.guildMemberAvatar(id, id, hash)).toEqual(`${baseCDN}/guilds/${id}/users/${id}/avatars/${hash}.webp`); }); diff --git a/packages/rest/src/lib/CDN.ts b/packages/rest/src/lib/CDN.ts index eefc5ceade0e..95ceb8a5ae23 100644 --- a/packages/rest/src/lib/CDN.ts +++ b/packages/rest/src/lib/CDN.ts @@ -14,27 +14,44 @@ import { deprecationWarning } from './utils/utils.js'; let deprecationEmittedForEmoji = false; /** - * The options used for image URLs + * The options used for image URLs. */ export interface BaseImageURLOptions { /** - * The extension to use for the image URL + * The extension to use for the image URL. * * @defaultValue `'webp'` */ extension?: ImageExtension; /** - * The size specified in the image URL + * The size specified in the image URL. */ size?: ImageSize; } +export interface EmojiURLOptionsWebp extends BaseImageURLOptions { + /** + * Whether to use the `animated` query parameter. + */ + animated?: boolean; + extension?: 'webp'; +} + +export interface EmojiURLOptionsNotWebp extends BaseImageURLOptions { + extension: Exclude; +} + /** - * The options used for image URLs with animated content + * The options used for emoji URLs. + */ +export type EmojiURLOptions = EmojiURLOptionsNotWebp | EmojiURLOptionsWebp; + +/** + * The options used for image URLs that may be animated. */ export interface ImageURLOptions extends BaseImageURLOptions { /** - * Whether or not to prefer the static version of an image asset. + * Whether to prefer the static asset. */ forceStatic?: boolean; } @@ -47,6 +64,10 @@ export interface MakeURLOptions { * The allowed extensions that can be used */ allowedExtensions?: readonly string[]; + /** + * Whether to use the `animated` query parameter + */ + animated?: boolean; /** * The base URL. * @@ -192,7 +213,7 @@ export class CDN { * @param emojiId - The emoji id * @param options - Optional options for the emoji */ - public emoji(emojiId: string, options?: Readonly): string; + public emoji(emojiId: string, options?: Readonly): string; /** * Generates an emoji's URL for an emoji. @@ -204,7 +225,7 @@ export class CDN { // eslint-disable-next-line @typescript-eslint/unified-signatures public emoji(emojiId: string, extension?: ImageExtension): string; - public emoji(emojiId: string, options?: ImageExtension | Readonly): string { + public emoji(emojiId: string, options?: ImageExtension | Readonly): string { let resolvedOptions; if (typeof options === 'string') { @@ -381,6 +402,7 @@ export class CDN { base = this.cdn, extension = 'webp', size, + animated, }: Readonly = {}, ): string { // eslint-disable-next-line no-param-reassign @@ -396,6 +418,10 @@ export class CDN { const url = new URL(`${base}${route}.${extension}`); + if (animated !== undefined) { + url.searchParams.set('animated', String(animated)); + } + if (size) { url.searchParams.set('size', String(size)); }