Skip to content

Commit 6260282

Browse files
committed
Merge branch 'main' into refactor/eslint-neon-mainlib
2 parents 42c5761 + 2c35084 commit 6260282

File tree

6 files changed

+67
-38
lines changed

6 files changed

+67
-38
lines changed

packages/discord.js/src/client/Client.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -848,6 +848,11 @@ exports.Client = Client;
848848
* @see {@link https://discord.js.org/docs/packages/rest/stable/ImageURLOptions:Interface}
849849
*/
850850

851+
/**
852+
* @external EmojiURLOptions
853+
* @see {@link https://discord.js.org/docs/packages/rest/stable/EmojiURLOptions:TypeAlias}
854+
*/
855+
851856
/**
852857
* @external BaseImageURLOptions
853858
* @see {@link https://discord.js.org/docs/packages/rest/stable/BaseImageURLOptions:Interface}

packages/discord.js/src/structures/BaseGuildEmoji.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ class BaseGuildEmoji extends Emoji {
6464
* @method imageURL
6565
* @memberof BaseGuildEmoji
6666
* @instance
67-
* @param {ImageURLOptions} [options={}] Options for the image URL
67+
* @param {EmojiURLOptions} [options={}] Options for the emoji URL
6868
* @returns {string}
6969
*/
7070

packages/discord.js/src/structures/Emoji.js

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,11 +48,20 @@ class Emoji extends Base {
4848
/**
4949
* Returns a URL for the emoji or `null` if this is not a custom emoji.
5050
*
51-
* @param {ImageURLOptions} [options={}] Options for the image URL
51+
* @param {EmojiURLOptions} [options={}] Options for the emoji URL
5252
* @returns {?string}
5353
*/
5454
imageURL(options = {}) {
55-
return this.id && this.client.rest.cdn.emoji(this.id, this.animated, options);
55+
if (!this.id) return null;
56+
57+
// Return a dynamic extension depending on whether the emoji is animated.
58+
const resolvedOptions = { extension: options.extension, size: options.size };
59+
60+
if (!options.extension || options.extension === 'webp') {
61+
resolvedOptions.animated = options.animated ?? (this.animated || undefined);
62+
}
63+
64+
return this.client.rest.cdn.emoji(this.id, resolvedOptions);
5665
}
5766

5867
/**

packages/discord.js/typings/index.d.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import { Stream } from 'node:stream';
44
import { MessagePort, Worker } from 'node:worker_threads';
55
import { ApplicationCommandOptionAllowedChannelTypes, MessageActionRowComponentBuilder } from '@discordjs/builders';
66
import { Collection, ReadonlyCollection } from '@discordjs/collection';
7-
import { BaseImageURLOptions, ImageURLOptions, RawFile, REST, RESTOptions } from '@discordjs/rest';
7+
import { BaseImageURLOptions, ImageURLOptions, RawFile, REST, RESTOptions, EmojiURLOptions } from '@discordjs/rest';
88
import { Awaitable, JSONEncodable } from '@discordjs/util';
99
import { WebSocketManager, WebSocketManagerOptions } from '@discordjs/ws';
1010
import { AsyncEventEmitter } from '@vladfrangu/async_event_emitter';
@@ -591,7 +591,7 @@ export abstract class BaseGuild extends Base {
591591

592592
export class BaseGuildEmoji extends Emoji {
593593
protected constructor(client: Client<true>, data: APIEmoji, guild: Guild | GuildPreview);
594-
public imageURL(options?: ImageURLOptions): string;
594+
public imageURL(options?: EmojiURLOptions): string;
595595
public get url(): string;
596596
public available: boolean | null;
597597
public get createdAt(): Date;
@@ -1265,7 +1265,7 @@ export class Emoji extends Base {
12651265
public id: Snowflake | null;
12661266
public name: string | null;
12671267
public get identifier(): string;
1268-
public imageURL(options?: ImageURLOptions): string | null;
1268+
public imageURL(options?: EmojiURLOptions): string | null;
12691269
public get url(): string | null;
12701270
public toJSON(): unknown;
12711271
public toString(): string;

packages/rest/__tests__/CDN.test.ts

Lines changed: 12 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ test('avatar default', () => {
2323
});
2424

2525
test('avatar dynamic-animated', () => {
26-
expect(cdn.avatar(id, animatedHash)).toEqual(`${baseCDN}/avatars/${id}/${animatedHash}.gif`);
26+
expect(cdn.avatar(id, animatedHash)).toEqual(`${baseCDN}/avatars/${id}/${animatedHash}.webp?animated=true`);
2727
});
2828

2929
test('avatar dynamic-not-animated', () => {
@@ -50,28 +50,16 @@ test('discoverySplash default', () => {
5050
expect(cdn.discoverySplash(id, hash)).toEqual(`${baseCDN}/discovery-splashes/${id}/${hash}.webp`);
5151
});
5252

53-
test('emoji static', () => {
54-
expect(cdn.emoji(id, false)).toEqual(`${baseCDN}/emojis/${id}.webp`);
55-
});
56-
57-
test('emoji static with JPG extension', () => {
58-
expect(cdn.emoji(id, false, { extension: 'jpg' })).toEqual(`${baseCDN}/emojis/${id}.jpg`);
59-
});
60-
61-
test('emoji static with JPG extension with force static', () => {
62-
expect(cdn.emoji(id, false, { extension: 'jpg', forceStatic: true })).toEqual(`${baseCDN}/emojis/${id}.jpg`);
53+
test('emoji', () => {
54+
expect(cdn.emoji(id)).toEqual(`${baseCDN}/emojis/${id}.webp`);
6355
});
6456

6557
test('emoji animated', () => {
66-
expect(cdn.emoji(id, true)).toEqual(`${baseCDN}/emojis/${id}.gif`);
58+
expect(cdn.emoji(id, { animated: true })).toEqual(`${baseCDN}/emojis/${id}.webp?animated=true`);
6759
});
6860

69-
test('emoji animated with JPG extension', () => {
70-
expect(cdn.emoji(id, true, { extension: 'jpg' })).toEqual(`${baseCDN}/emojis/${id}.gif`);
71-
});
72-
73-
test('emoji animated with JPG extension with force static', () => {
74-
expect(cdn.emoji(id, true, { extension: 'jpg', forceStatic: true })).toEqual(`${baseCDN}/emojis/${id}.jpg`);
61+
test('emoji with GIF format', () => {
62+
expect(cdn.emoji(id, { extension: 'gif' })).toEqual(`${baseCDN}/emojis/${id}.gif`);
7563
});
7664

7765
test('guildMemberAvatar default', () => {
@@ -80,7 +68,7 @@ test('guildMemberAvatar default', () => {
8068

8169
test('guildMemberAvatar dynamic-animated', () => {
8270
expect(cdn.guildMemberAvatar(id, id, animatedHash)).toEqual(
83-
`${baseCDN}/guilds/${id}/users/${id}/avatars/${animatedHash}.gif`,
71+
`${baseCDN}/guilds/${id}/users/${id}/avatars/${animatedHash}.webp?animated=true`,
8472
);
8573
});
8674

@@ -94,7 +82,7 @@ test('guildMemberBanner default', () => {
9482

9583
test('guildMemberBanner dynamic-animated', () => {
9684
expect(cdn.guildMemberBanner(id, id, animatedHash)).toEqual(
97-
`${baseCDN}/guilds/${id}/users/${id}/banners/${animatedHash}.gif`,
85+
`${baseCDN}/guilds/${id}/users/${id}/banners/${animatedHash}.webp?animated=true`,
9886
);
9987
});
10088

@@ -111,7 +99,7 @@ test('icon default', () => {
11199
});
112100

113101
test('icon dynamic-animated', () => {
114-
expect(cdn.icon(id, animatedHash)).toEqual(`${baseCDN}/icons/${id}/${animatedHash}.gif`);
102+
expect(cdn.icon(id, animatedHash)).toEqual(`${baseCDN}/icons/${id}/${animatedHash}.webp?animated=true`);
115103
});
116104

117105
test('icon dynamic-not-animated', () => {
@@ -157,5 +145,7 @@ test('makeURL throws on invalid extension', () => {
157145
});
158146

159147
test('makeURL valid size', () => {
160-
expect(cdn.avatar(id, animatedHash, { size: 512 })).toEqual(`${baseCDN}/avatars/${id}/${animatedHash}.gif?size=512`);
148+
expect(cdn.avatar(id, animatedHash, { size: 512 })).toEqual(
149+
`${baseCDN}/avatars/${id}/${animatedHash}.webp?animated=true&size=512`,
150+
);
161151
});

packages/rest/src/lib/CDN.ts

Lines changed: 35 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -11,39 +11,60 @@ import {
1111
} from './utils/constants.js';
1212

1313
/**
14-
* The options used for image URLs
14+
* The options used for image URLs.
1515
*/
1616
export interface BaseImageURLOptions {
1717
/**
18-
* The extension to use for the image URL
18+
* The extension to use for the image URL.
1919
*
2020
* @defaultValue `'webp'`
2121
*/
2222
extension?: ImageExtension;
2323
/**
24-
* The size specified in the image URL
24+
* The size specified in the image URL.
2525
*/
2626
size?: ImageSize;
2727
}
2828

29+
export interface EmojiURLOptionsWebp extends BaseImageURLOptions {
30+
/**
31+
* Whether to use the `animated` query parameter.
32+
*/
33+
animated?: boolean;
34+
extension?: 'webp';
35+
}
36+
37+
export interface EmojiURLOptionsNotWebp extends BaseImageURLOptions {
38+
extension: Exclude<ImageExtension, 'webp'>;
39+
}
40+
2941
/**
30-
* The options used for image URLs with animated content
42+
* The options used for emoji URLs.
43+
*/
44+
export type EmojiURLOptions = EmojiURLOptionsNotWebp | EmojiURLOptionsWebp;
45+
46+
/**
47+
* The options used for image URLs that may be animated.
3148
*/
3249
export interface ImageURLOptions extends BaseImageURLOptions {
3350
/**
34-
* Whether or not to prefer the static version of an image asset.
51+
* Whether to prefer the static asset.
3552
*/
3653
forceStatic?: boolean;
3754
}
3855

3956
/**
4057
* The options to use when making a CDN URL
4158
*/
42-
export interface MakeURLOptions {
59+
interface MakeURLOptions {
4360
/**
4461
* The allowed extensions that can be used
4562
*/
4663
allowedExtensions?: readonly string[];
64+
/**
65+
* Whether to use the `animated` query parameter
66+
*/
67+
animated?: boolean;
4768
/**
4869
* The base URL.
4970
*
@@ -162,11 +183,10 @@ export class CDN {
162183
* Generates an emoji's URL.
163184
*
164185
* @param emojiId - The emoji id
165-
* @param animated - Whether the emoji is animated
166186
* @param options - Optional options for the emoji
167187
*/
168-
public emoji(emojiId: string, animated: boolean, options?: Readonly<ImageURLOptions>): string {
169-
return this.dynamicMakeURL(`/emojis/${emojiId}`, animated ? 'a_' : '', options);
188+
public emoji(emojiId: string, options?: Readonly<EmojiURLOptions>): string {
189+
return this.makeURL(`/emojis/${emojiId}`, options);
170190
}
171191

172192
/**
@@ -310,7 +330,7 @@ export class CDN {
310330
hash: string,
311331
{ forceStatic = false, ...options }: Readonly<ImageURLOptions> = {},
312332
): string {
313-
return this.makeURL(route, !forceStatic && hash.startsWith('a_') ? { ...options, extension: 'gif' } : options);
333+
return this.makeURL(route, !forceStatic && hash.startsWith('a_') ? { ...options, animated: true } : options);
314334
}
315335

316336
/**
@@ -326,6 +346,7 @@ export class CDN {
326346
base = this.cdn,
327347
extension = 'webp',
328348
size,
349+
animated,
329350
}: Readonly<MakeURLOptions> = {},
330351
): string {
331352
// eslint-disable-next-line no-param-reassign
@@ -341,6 +362,10 @@ export class CDN {
341362

342363
const url = new URL(`${base}${route}.${extension}`);
343364

365+
if (animated !== undefined) {
366+
url.searchParams.set('animated', String(animated));
367+
}
368+
344369
if (size) {
345370
url.searchParams.set('size', String(size));
346371
}

0 commit comments

Comments
 (0)