Compare commits

..

34 Commits

Author SHA1 Message Date
Vlad Frangu
dceac0089d chore(core): release @discordjs/core@2.2.1 2025-08-21 00:48:29 +03:00
Vlad Frangu
a2f7d3ad54 chore(rest): release @discordjs/rest@2.6.0 2025-08-21 00:43:53 +03:00
Jiralite
b532df61ed fix: Remove trailing color references (#11007)
fix: role colour fixes
2025-07-20 18:01:45 +01:00
Jiralite
d60e0bf30b types(Invite): Approximate fields should be nullable (#10997)
types: nullable fields
2025-07-16 23:41:57 +01:00
Danial Raza
baa08b8fbb feat: support user guilds (#10995) 2025-07-16 22:27:54 +02:00
Jiralite
f469f74aca feat(MessageManager): New pinned messages routes (#10993)
feat(MessageManager)!: New pinned messages routes (#10989)

BREAKING CHANGE: `fetchPinned()` has been renamed to `fetchPins()`, which is a paginated endpoint to fetch pinned messages.
2025-07-16 11:33:16 +01:00
Jiralite
90d3b28268 fix(Emoji): remove incorrect nullables, add ApplicationEmoji#available (#10990)
fix: remove incorrect nullables, add `ApplicationEmoji#available`

Co-authored-by: Amgelo563 <61554601+Amgelo563@users.noreply.github.com>
2025-07-15 19:52:47 +01:00
Jiralite
a271e9b51e build: Upgrade discord-api-types (#10991)
build: Upgrade dependencies
2025-07-15 01:30:58 +01:00
Danial Raza
8ac0e1e5d6 feat(User): add collectibles (#10939)
* feat(User): add `collectibles`

* docs: nullable collectibles and nameplate data

Co-authored-by: Jiralite <33201955+Jiralite@users.noreply.github.com>

---------

Co-Authored-By: Jiralite <33201955+Jiralite@users.noreply.github.com>
2025-07-15 00:41:57 +01:00
Jiralite
9d6fdf8979 feat: Role gradient colours (#10986)
* feat: backport role gradient colours

* chore: add deprecations
2025-07-14 18:34:52 +01:00
Jiralite
cafe58b3bd feat: Support animated WebP (#10987)
* feat: Support animated WebP (#10911)

* feat: support animated WebP

* refactor: change the rest

* fix: remove redundant code

* fix(CDN): Export `MakeURLOptions`
2025-07-14 18:34:27 +01:00
Jiralite
7eca844f6d chore: remove unused directive 2025-07-14 10:58:55 +01:00
Naiyar
63f5261f4c fix(GuildChannelManager): properly resolve avatar for createWebhook (#10772)
fix(GuildChannelManager): properly resolve avatr for createWebhook
2025-07-14 02:26:55 +01:00
Almeida
5be774db64 docs: remove hardcoded locale from links (#10794)
Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
2025-07-14 02:24:17 +01:00
Almeida
b36b751bde fix(Message): forwarded messages are not crosspostable (#10821)
Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
2025-07-14 02:19:03 +01:00
Danial Raza
500712d5ea types(ModalSubmitFields): fix fields type (#10816)
Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
2025-07-14 02:17:36 +01:00
Danial Raza
040c66ae15 docs(ApplicationCommand): incorrect method in example (#10837) 2025-07-14 02:10:20 +01:00
Jiralite
82378fc2e8 refactor: Deprecate ready event in favor of clientReady (#10969)
* refactor: deprecate ready event

* refactor: tweak message

Co-Authored-By: Vlad Frangu <me@vladfrangu.dev>

* Update packages/discord.js/src/client/websocket/WebSocketManager.js

Co-authored-by: Qjuh <76154676+Qjuh@users.noreply.github.com>

* chore: disable max-len

---------

Co-authored-by: Vlad Frangu <me@vladfrangu.dev>
Co-authored-by: Qjuh <76154676+Qjuh@users.noreply.github.com>
2025-07-13 21:32:22 +01:00
Jiralite
d4f742e99e refactor(ThreadChannel): Remove trimming of name (#10984)
refactor(ThreadChannel): no need to trim name

Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
2025-07-13 21:16:44 +01:00
Jiralite
51ceb203fa fix(DirectoryChannel): Export class (#10985)
fix: export directory channels
2025-07-13 21:07:09 +01:00
Qjuh
1404e32849 fix(Events): WebhooksUpdate enum value (#10970)
fix: change Events.WebhooksUpdate value
2025-07-11 19:39:12 +01:00
Jiralite
9fc3e5ea72 fix: Adjust reason in methods options (#10977)
fix: Adjust `reason` in methods options (#10976)

* fix(channel): allow reason in editing

* fix(channel): allow reason in `delete()`

* fix(channel): allow reason in creating threads

* chore: run format

* fix(guild): remove incorrect `reason` option

---------

Co-authored-by: Danial Raza <danialrazafb@gmail.com>
2025-07-11 10:00:58 +01:00
TÆMBØ
19e74b1533 types(InteractionCallbackResponse): add missing InGuild generic (#10963) 2025-07-03 00:21:13 +02:00
Vlad Frangu
de22a10038 chore(discord.js): release discord.js@14.21.0 2025-06-26 01:33:02 +03:00
Vlad Frangu
8ab30cdefa chore(core): release @discordjs/core@2.2.0 2025-06-26 01:26:48 +03:00
Danial Raza
c2a43b685e types(ClientEventTypes): add missing guildSoundboardSoundsUpdate (#10928) 2025-06-25 16:22:07 +01:00
Jiralite
507b696792 fix(ClientUser): Remove token assignment (#10953)
fix(ClientUser): remove token assignment
2025-06-25 16:15:35 +01:00
Jiralite
15f7571243 feat(GuildMember): add avatarDecorationData (#10942)
Co-Authored-By: Danial Raza <danialrazafb@gmail.com>
2025-06-25 12:31:43 +01:00
Almeida
3fa429c7df feat(ClientApplication): add approximateUserAuthorizationCount (#10933)
Co-authored-by: Danial Raza <danialrazafb@gmail.com>
Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
2025-06-25 12:22:36 +01:00
Jiralite
7713627fd1 feat(webhook): Support with_components (#10945)
feat: support `with_components`
2025-06-22 10:48:47 +01:00
Vlad Frangu
6a5c0fb32d chore(discord.js): release discord.js@14.20.0 2025-06-16 15:41:03 +03:00
Vlad Frangu
eb5acd1e30 chore(discord.js): bump ws 2025-06-16 15:39:20 +03:00
Vlad Frangu
127021d5ab chore(core): release @discordjs/core@2.1.1 2025-06-16 15:30:25 +03:00
Vlad Frangu
0943bc2efb chore(ws): release @discordjs/ws@2.0.3 2025-06-16 15:29:02 +03:00
47 changed files with 960 additions and 218 deletions

2
.github/CODEOWNERS vendored
View File

@@ -1,5 +1,5 @@
# Learn how to add code owners here:
# https://help.github.com/en/articles/about-code-owners
# https://help.github.com/articles/about-code-owners
* @iCrawl

View File

@@ -83,7 +83,7 @@ export class StringSelectMenuBuilder extends BaseSelectMenuBuilder<APIStringSele
*
* @remarks
* This method behaves similarly
* to {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/slice | Array.prototype.splice()}.
* to {@link https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array/slice | Array.prototype.splice()}.
* It's useful for modifying and adjusting the order of existing options.
* @example
* Remove the first option:

View File

@@ -125,7 +125,7 @@ export class EmbedBuilder {
*
* @remarks
* This method behaves similarly
* to {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/splice | Array.prototype.splice()}.
* to {@link https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array/splice | Array.prototype.splice()}.
* The maximum amount of fields that can be added is 25.
*
* It's useful for modifying and adjusting order of the already-existing fields of an embed.

View File

@@ -2,6 +2,24 @@
All notable changes to this project will be documented in this file.
# [@discordjs/core@2.2.1](https://github.com/discordjs/discord.js/compare/@discordjs/core@2.2.0...@discordjs/core@2.2.1) - (2025-08-20)
## Bug Fixes
- Adjust `reason` in methods options (#10977) ([9fc3e5e](https://github.com/discordjs/discord.js/commit/9fc3e5ea72a2714d81cc57cbac4f378a49934446))
# [@discordjs/core@2.2.0](https://github.com/discordjs/discord.js/compare/@discordjs/core@2.1.1...@discordjs/core@2.2.0) - (2025-06-25)
## Features
- **webhook:** Support `with_components` (#10945) ([7713627](https://github.com/discordjs/discord.js/commit/7713627fd18599a6187b325e1e4bc9a17cf23e21))
# [@discordjs/core@2.1.1](https://github.com/discordjs/discord.js/compare/@discordjs/core@2.1.0...@discordjs/core@2.1.1) - (2025-06-16)
## Bug Fixes
- **guild:** Fix incorrectly-detected deprecated overload ([d0a535e](https://github.com/discordjs/discord.js/commit/d0a535ea6a66861276691a51547adfb2bcef0384))
# [@discordjs/core@2.1.0](https://github.com/discordjs/discord.js/compare/@discordjs/core@2.0.1...@discordjs/core@2.1.0) - (2025-04-25)
## Features

View File

@@ -1,7 +1,7 @@
{
"$schema": "https://json.schemastore.org/package.json",
"name": "@discordjs/core",
"version": "2.1.0",
"version": "2.2.1",
"description": "A thinly abstracted wrapper around the rest API, and gateway.",
"scripts": {
"test": "vitest run",
@@ -70,7 +70,7 @@
"@discordjs/ws": "workspace:^",
"@sapphire/snowflake": "^3.5.3",
"@vladfrangu/async_event_emitter": "^2.4.6",
"discord-api-types": "^0.38.1"
"discord-api-types": "^0.38.16"
},
"devDependencies": {
"@discordjs/api-extractor": "workspace:^",

View File

@@ -223,9 +223,13 @@ export class ChannelsAPI {
public async edit(
channelId: Snowflake,
body: RESTPatchAPIChannelJSONBody,
{ signal }: Pick<RequestData, 'signal'> = {},
{ signal, reason }: Pick<RequestData, 'reason' | 'signal'> = {},
) {
return this.rest.patch(Routes.channel(channelId), { body, signal }) as Promise<RESTPatchAPIChannelResult>;
return this.rest.patch(Routes.channel(channelId), {
reason,
body,
signal,
}) as Promise<RESTPatchAPIChannelResult>;
}
/**
@@ -235,8 +239,8 @@ export class ChannelsAPI {
* @param channelId - The id of the channel to delete
* @param options - The options for deleting the channel
*/
public async delete(channelId: Snowflake, { signal }: Pick<RequestData, 'signal'> = {}) {
return this.rest.delete(Routes.channel(channelId), { signal }) as Promise<RESTDeleteAPIChannelResult>;
public async delete(channelId: Snowflake, { signal, reason }: Pick<RequestData, 'reason' | 'signal'> = {}) {
return this.rest.delete(Routes.channel(channelId), { signal, reason }) as Promise<RESTDeleteAPIChannelResult>;
}
/**
@@ -441,11 +445,12 @@ export class ChannelsAPI {
channelId: Snowflake,
body: RESTPostAPIChannelThreadsJSONBody,
messageId?: Snowflake,
{ signal }: Pick<RequestData, 'signal'> = {},
{ signal, reason }: Pick<RequestData, 'reason' | 'signal'> = {},
) {
return this.rest.post(Routes.threads(channelId, messageId), {
body,
signal,
reason,
}) as Promise<RESTPostAPIChannelThreadsResult>;
}
@@ -460,7 +465,7 @@ export class ChannelsAPI {
public async createForumThread(
channelId: Snowflake,
{ message, ...optionsBody }: StartForumThreadOptions,
{ signal }: Pick<RequestData, 'signal'> = {},
{ signal, reason }: Pick<RequestData, 'reason' | 'signal'> = {},
) {
const { files, ...messageBody } = message;
@@ -469,7 +474,12 @@ export class ChannelsAPI {
message: messageBody,
};
return this.rest.post(Routes.threads(channelId), { files, body, signal }) as Promise<APIThreadChannel>;
return this.rest.post(Routes.threads(channelId), {
files,
body,
reason,
signal,
}) as Promise<APIThreadChannel>;
}
/**

View File

@@ -198,8 +198,8 @@ export class GuildsAPI {
* @param guildId - The id of the guild to delete
* @param options - The options for deleting this guild
*/
public async delete(guildId: Snowflake, { signal, reason }: Pick<RequestData, 'reason' | 'signal'> = {}) {
await this.rest.delete(Routes.guild(guildId), { reason, signal });
public async delete(guildId: Snowflake, { signal }: Pick<RequestData, 'signal'> = {}) {
await this.rest.delete(Routes.guild(guildId), { signal });
}
/**

View File

@@ -44,7 +44,7 @@ export class OAuth2API {
{ signal }: Pick<RequestData, 'signal'> = {},
) {
return this.rest.post(Routes.oauth2TokenExchange(), {
body: makeURLSearchParams(body),
body: makeURLSearchParams<RESTPostOAuth2AccessTokenURLEncodedData>(body),
passThroughBody: true,
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
@@ -66,7 +66,7 @@ export class OAuth2API {
{ signal }: Pick<RequestData, 'signal'> = {},
) {
return this.rest.post(Routes.oauth2TokenExchange(), {
body: makeURLSearchParams(body),
body: makeURLSearchParams<RESTPostOAuth2RefreshTokenURLEncodedData>(body),
passThroughBody: true,
headers: {
'Content-Type': 'application/x-www-form-urlencoded',

View File

@@ -9,6 +9,7 @@ import {
type RESTPatchAPIWebhookJSONBody,
type RESTPatchAPIWebhookResult,
type RESTPatchAPIWebhookWithTokenMessageJSONBody,
type RESTPatchAPIWebhookWithTokenMessageQuery,
type RESTPatchAPIWebhookWithTokenMessageResult,
type RESTPostAPIWebhookWithTokenGitHubQuery,
type RESTPostAPIWebhookWithTokenJSONBody,
@@ -127,13 +128,14 @@ export class WebhooksAPI {
{
wait,
thread_id,
with_components,
files,
...body
}: RESTPostAPIWebhookWithTokenJSONBody & RESTPostAPIWebhookWithTokenQuery & { files?: RawFile[] },
{ signal }: Pick<RequestData, 'signal'> = {},
) {
return this.rest.post(Routes.webhook(id, token), {
query: makeURLSearchParams({ wait, thread_id }),
query: makeURLSearchParams({ wait, thread_id, with_components }),
files,
body,
auth: false,
@@ -232,13 +234,14 @@ export class WebhooksAPI {
messageId: Snowflake,
{
thread_id,
with_components,
files,
...body
}: RESTPatchAPIWebhookWithTokenMessageJSONBody & { files?: RawFile[]; thread_id?: string },
}: RESTPatchAPIWebhookWithTokenMessageJSONBody & RESTPatchAPIWebhookWithTokenMessageQuery & { files?: RawFile[] },
{ signal }: Pick<RequestData, 'signal'> = {},
) {
return this.rest.patch(Routes.webhookMessage(id, token, messageId), {
query: makeURLSearchParams({ thread_id }),
query: makeURLSearchParams({ thread_id, with_components }),
auth: false,
body,
signal,

View File

@@ -2,6 +2,42 @@
All notable changes to this project will be documented in this file.
# [14.21.0](https://github.com/discordjs/discord.js/compare/14.20.0...14.21.0) - (2025-06-25)
## Bug Fixes
- **ClientUser:** Remove token assignment (#10953) ([507b696](https://github.com/discordjs/discord.js/commit/507b696792d61ae49565b4613439aceb08dcf38a))
## Features
- **GuildMember:** Add `avatarDecorationData` (#10942) ([15f7571](https://github.com/discordjs/discord.js/commit/15f7571243d5b206141290478fd5164d299c0850))
- **ClientApplication:** Add `approximateUserAuthorizationCount` (#10933) ([3fa429c](https://github.com/discordjs/discord.js/commit/3fa429c7dfa3bb3e6f099cd2f068c474a01677b1))
## Typings
- **ClientEventTypes:** Add missing `guildSoundboardSoundsUpdate` (#10928) ([c2a43b6](https://github.com/discordjs/discord.js/commit/c2a43b685e01eff878a399e8c00df8e473c185ad))
# [14.20.0](https://github.com/discordjs/discord.js/compare/14.19.3...14.20.0) - (2025-06-16)
## Bug Fixes
- Use resolvePartialEmoji on MessagePayload#options#components (#10910) ([f2f757c](https://github.com/discordjs/discord.js/commit/f2f757ce52b76d5e571f47f9bf1c5188627b80d5))
- **ChannelManager:** Remove threads from cache upon deletion (#10883) ([ee2eb73](https://github.com/discordjs/discord.js/commit/ee2eb7349f2467451880baaea54e02074916015f))
- **PartialGroupDMChannel:** Prevent `undefined` values (#10889) ([9bca4af](https://github.com/discordjs/discord.js/commit/9bca4af5fdb78fae7b970498db7f93df31f55ef9))
## Features
- Backport entrypoint command (#10908) ([c0eae34](https://github.com/discordjs/discord.js/commit/c0eae344c2ed43fa67be9fda8e3d3e479693d2d1))
- **BaseInteraction:** Add `attachmentSizeLimit` (#10830) ([7e21a94](https://github.com/discordjs/discord.js/commit/7e21a9474e532c5b22c6e0600c446fca47352617))
## Performance
- **Components:** Hash table (#10893) ([2d19163](https://github.com/discordjs/discord.js/commit/2d19163d764705667691430e438499fd330ffb65))
## Refactor
- **Client:** Remove `with_expiration` query parameter (#10800) ([c8f6066](https://github.com/discordjs/discord.js/commit/c8f6066d6a0a1fc6ac23a49d66604d95b588af3e))
# [14.19.3](https://github.com/discordjs/discord.js/compare/14.19.2...14.19.3) - (2025-05-02)
## Bug Fixes

View File

@@ -1,7 +1,7 @@
{
"$schema": "https://json.schemastore.org/package.json",
"name": "discord.js",
"version": "14.19.3",
"version": "14.21.0",
"description": "A powerful library for interacting with the Discord API",
"scripts": {
"test": "pnpm run docs:test && pnpm run test:typescript",
@@ -71,9 +71,9 @@
"@discordjs/formatters": "^0.6.1",
"@discordjs/rest": "workspace:^",
"@discordjs/util": "workspace:^",
"@discordjs/ws": "^1.2.2",
"@discordjs/ws": "^1.2.3",
"@sapphire/snowflake": "3.5.3",
"discord-api-types": "^0.38.1",
"discord-api-types": "^0.38.16",
"fast-deep-equal": "3.1.3",
"lodash.snakecase": "4.1.1",
"magic-bytes.js": "^1.10.0",

View File

@@ -522,7 +522,7 @@ class Client extends BaseClient {
}
/**
* Calls {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/eval} on a script
* Calls {@link https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/eval} on a script
* with the client as `this`.
* @param {string} script Script to eval
* @returns {*}
@@ -604,7 +604,7 @@ module.exports = Client;
*/
/**
* A {@link https://developer.twitter.com/en/docs/twitter-ids Twitter snowflake},
* A {@link https://docs.x.com/resources/fundamentals/x-ids Twitter snowflake},
* except the epoch is 2015-01-01T00:00:00.000Z.
*
* If we have a snowflake '266241948824764416' we can represent it as binary:
@@ -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}

View File

@@ -19,6 +19,7 @@ const Status = require('../../util/Status');
const WebSocketShardEvents = require('../../util/WebSocketShardEvents');
let zlib;
let deprecationEmitted = false;
try {
zlib = require('zlib-sync');
@@ -379,6 +380,22 @@ class WebSocketManager extends EventEmitter {
/**
* Emitted when the client becomes ready to start working.
* @event Client#ready
* @deprecated Use {@link Client#event:clientReady} instead.
* @param {Client} client The client
*/
if (this.client.emit('ready', this.client) && !deprecationEmitted) {
deprecationEmitted = true;
process.emitWarning(
// eslint-disable-next-line max-len
'The ready event has been renamed to clientReady to distinguish it from the gateway READY event and will only emit under that name in v15. Please use clientReady instead.',
'DeprecationWarning',
);
}
/**
* Emitted when the client becomes ready to start working.
* @event Client#clientReady
* @param {Client} client The client
*/
this.client.emit(Events.ClientReady, this.client);

View File

@@ -126,6 +126,7 @@ exports.CommandInteractionOptionResolver = require('./structures/CommandInteract
exports.Component = require('./structures/Component');
exports.ContainerComponent = require('./structures/ContainerComponent');
exports.ContextMenuCommandInteraction = require('./structures/ContextMenuCommandInteraction');
exports.DirectoryChannel = require('./structures/DirectoryChannel');
exports.DMChannel = require('./structures/DMChannel');
exports.Embed = require('./structures/Embed');
exports.EmbedBuilder = require('./structures/EmbedBuilder');

View File

@@ -230,13 +230,13 @@ class GuildChannelManager extends CachedManager {
async createWebhook({ channel, name, avatar, reason }) {
const id = this.resolveId(channel);
if (!id) throw new DiscordjsTypeError(ErrorCodes.InvalidType, 'channel', 'GuildChannelResolvable');
if (typeof avatar === 'string' && !avatar.startsWith('data:')) {
avatar = await resolveImage(avatar);
}
const resolvedImage = await resolveImage(avatar);
const data = await this.client.rest.post(Routes.channelWebhooks(id), {
body: {
name,
avatar,
avatar: resolvedImage,
},
reason,
});

View File

@@ -65,7 +65,7 @@ class GuildMemberRoleManager extends DataManager {
* @readonly
*/
get color() {
const coloredRoles = this.cache.filter(role => role.color);
const coloredRoles = this.cache.filter(role => role.colors.primaryColor);
if (!coloredRoles.size) return null;
return coloredRoles.reduce((prev, role) => (role.comparePositionTo(prev) > 0 ? role : prev));
}

View File

@@ -1,5 +1,6 @@
'use strict';
const process = require('node:process');
const { Collection } = require('@discordjs/collection');
const { makeURLSearchParams } = require('@discordjs/rest');
const { Routes } = require('discord-api-types/v10');
@@ -10,6 +11,8 @@ const MessagePayload = require('../structures/MessagePayload');
const { MakeCacheOverrideSymbol } = require('../util/Symbols');
const { resolvePartialEmoji } = require('../util/Util');
let deprecationEmittedForFetchPinned = false;
/**
* Manages API methods for Messages and holds their cache.
* @extends {CachedManager}
@@ -116,19 +119,83 @@ class MessageManager extends CachedManager {
return data.reduce((_data, message) => _data.set(message.id, this._add(message, options.cache)), new Collection());
}
/**
* Options used to fetch pinned messages.
*
* @typedef {Object} FetchPinnedMessagesOptions
* @property {DateResolvable} [before] Consider only pinned messages before this time
* @property {number} [limit] The maximum number of pinned messages to return
* @property {boolean} [cache] Whether to cache the pinned messages
*/
/**
* Data returned from fetching pinned messages.
*
* @typedef {Object} FetchPinnedMessagesResponse
* @property {MessagePin[]} items The pinned messages
* @property {boolean} hasMore Whether there are additional pinned messages that require a subsequent call
*/
/**
* Pinned message data returned from fetching pinned messages.
*
* @typedef {Object} MessagePin
* @property {Date} pinnedAt The time the message was pinned at
* @property {number} pinnedTimestamp The timestamp the message was pinned at
* @property {Message} message The pinned message
*/
/**
* Fetches the pinned messages of this channel and returns a collection of them.
* <info>The returned Collection does not contain any reaction data of the messages.
* Those need to be fetched separately.</info>
*
* @param {FetchPinnedMessagesOptions} [options={}] Options for fetching pinned messages
* @returns {Promise<FetchPinnedMessagesResponse>}
* @example
* // Get pinned messages
* channel.messages.fetchPins()
* .then(messages => console.log(`Received ${messages.items.length} messages`))
* .catch(console.error);
*/
async fetchPins(options = {}) {
const data = await this.client.rest.get(Routes.channelMessagesPins(this.channel.id), {
query: makeURLSearchParams({
...options,
before: options.before && new Date(options.before).toISOString(),
}),
});
return {
items: data.items.map(item => ({
pinnedTimestamp: Date.parse(item.pinned_at),
get pinnedAt() {
return new Date(this.pinnedTimestamp);
},
message: this._add(item.message, options.cache),
})),
hasMore: data.has_more,
};
}
/**
* Fetches the pinned messages of this channel and returns a collection of them.
* <info>The returned Collection does not contain any reaction data of the messages.
* Those need to be fetched separately.</info>
* @param {boolean} [cache=true] Whether to cache the message(s)
* @deprecated Use {@link MessageManager#fetchPins} instead.
* @returns {Promise<Collection<Snowflake, Message>>}
* @example
* // Get pinned messages
* channel.messages.fetchPinned()
* .then(messages => console.log(`Received ${messages.size} messages`))
* .catch(console.error);
*/
async fetchPinned(cache = true) {
if (!deprecationEmittedForFetchPinned) {
process.emitWarning(
'The MessageManager#fetchPinned() method is deprecated. Use MessageManager#fetchPins() instead.',
'DeprecationWarning',
);
deprecationEmittedForFetchPinned = true;
}
const data = await this.client.rest.get(Routes.channelPins(this.channel.id));
const messages = new Collection();
for (const message of data) messages.set(message.id, this._add(message, cache));
@@ -219,7 +286,7 @@ class MessageManager extends CachedManager {
message = this.resolveId(message);
if (!message) throw new DiscordjsTypeError(ErrorCodes.InvalidType, 'message', 'MessageResolvable');
await this.client.rest.put(Routes.channelPin(this.channel.id, message), { reason });
await this.client.rest.put(Routes.channelMessagesPin(this.channel.id, message), { reason });
}
/**
@@ -232,7 +299,7 @@ class MessageManager extends CachedManager {
message = this.resolveId(message);
if (!message) throw new DiscordjsTypeError(ErrorCodes.InvalidType, 'message', 'MessageResolvable');
await this.client.rest.delete(Routes.channelPin(this.channel.id, message), { reason });
await this.client.rest.delete(Routes.channelMessagesPin(this.channel.id, message), { reason });
}
/**

View File

@@ -12,6 +12,8 @@ const PermissionsBitField = require('../util/PermissionsBitField');
const { setPosition, resolveColor } = require('../util/Util');
let cacheWarningEmitted = false;
let deprecationEmittedForCreate = false;
let deprecationEmittedForEdit = false;
/**
* Manages API methods for roles and stores their cache.
@@ -58,7 +60,7 @@ class RoleManager extends CachedManager {
* @example
* // Fetch a single role
* message.guild.roles.fetch('222078108977594368')
* .then(role => console.log(`The role color is: ${role.color}`))
* .then(role => console.log(`The role color is: ${role.colors.primaryColor}`))
* .catch(console.error);
*/
async fetch(id, { cache = true, force = false } = {}) {
@@ -112,11 +114,24 @@ class RoleManager extends CachedManager {
* @returns {?Snowflake}
*/
/**
* @typedef {Object} RoleColorsResolvable
* @property {ColorResolvable} primaryColor The primary color of the role
* @property {ColorResolvable} [secondaryColor] The secondary color of the role.
* This will make the role a gradient between the other provided colors
* @property {ColorResolvable} [tertiaryColor] The tertiary color of the role.
* When sending `tertiaryColor` the API enforces the role color to be a holographic style
* with values of `primaryColor = 11127295`, `secondaryColor = 16759788`, and `tertiaryColor = 16761760`.
* These values are available as a constant: `Constants.HolographicStyle`
*/
/**
* Options used to create a new role.
* @typedef {Object} RoleCreateOptions
* @property {string} [name] The name of the new role
* @property {ColorResolvable} [color] The data to create the role with
* <warn>This property is deprecated. Use `colors` instead.</warn>
* @property {RoleColorsResolvable} [colors] The colors to create the role with
* @property {boolean} [hoist] Whether or not the new role should be hoisted
* @property {PermissionResolvable} [permissions] The permissions for the new role
* @property {number} [position] The position of the new role
@@ -142,15 +157,30 @@ class RoleManager extends CachedManager {
* // Create a new role with data and a reason
* guild.roles.create({
* name: 'Super Cool Blue People',
* color: Colors.Blue,
* reason: 'we needed a role for Super Cool People',
* colors: {
* primaryColor: Colors.Blue,
* },
* })
* .then(console.log)
* .catch(console.error);
* @example
* // Create a role with holographic colors
* guild.roles.create({
* name: 'Holographic Role',
* reason: 'Creating a role with holographic effect',
* colors: {
* primaryColor: Constants.HolographicStyle.Primary,
* secondaryColor: Constants.HolographicStyle.Secondary,
* tertiaryColor: Constants.HolographicStyle.Tertiary,
* },
* })
* .then(console.log)
* .catch(console.error);
*/
async create(options = {}) {
let { name, color, hoist, permissions, position, mentionable, reason, icon, unicodeEmoji } = options;
color &&= resolveColor(color);
let { permissions, icon } = options;
const { name, color, hoist, position, mentionable, reason, unicodeEmoji } = options;
if (permissions !== undefined) permissions = new PermissionsBitField(permissions);
if (icon) {
const guildEmojiURL = this.guild.emojis.resolve(icon)?.imageURL();
@@ -158,10 +188,30 @@ class RoleManager extends CachedManager {
if (typeof icon !== 'string') icon = undefined;
}
let colors = options.colors && {
primary_color: resolveColor(options.colors.primaryColor),
secondary_color: options.colors.secondaryColor && resolveColor(options.colors.secondaryColor),
tertiary_color: options.colors.tertiaryColor && resolveColor(options.colors.tertiaryColor),
};
if (color !== undefined) {
if (!deprecationEmittedForCreate) {
process.emitWarning(`Passing "color" to RoleManager#create() is deprecated. Use "colors" instead.`);
}
deprecationEmittedForCreate = true;
colors = {
primary_color: resolveColor(color),
secondary_color: null,
tertiary_color: null,
};
}
const data = await this.client.rest.post(Routes.guildRoles(this.guild.id), {
body: {
name,
color,
colors,
hoist,
permissions,
mentionable,
@@ -210,9 +260,29 @@ class RoleManager extends CachedManager {
if (typeof icon !== 'string') icon = undefined;
}
let colors = options.colors && {
primary_color: resolveColor(options.colors.primaryColor),
secondary_color: options.colors.secondaryColor && resolveColor(options.colors.secondaryColor),
tertiary_color: options.colors.tertiaryColor && resolveColor(options.colors.tertiaryColor),
};
if (options.color !== undefined) {
if (!deprecationEmittedForEdit) {
process.emitWarning(`Passing "color" to RoleManager#edit() is deprecated. Use "colors" instead.`);
}
deprecationEmittedForEdit = true;
colors = {
primary_color: resolveColor(options.color),
secondary_color: null,
tertiary_color: null,
};
}
const body = {
name: options.name,
color: options.color === undefined ? undefined : resolveColor(options.color),
colors,
hoist: options.hoist,
permissions: options.permissions === undefined ? undefined : new PermissionsBitField(options.permissions),
mentionable: options.mentionable,

View File

@@ -312,7 +312,7 @@ class ApplicationCommand extends Base {
* @returns {Promise<ApplicationCommand>}
* @example
* // Edit the name localizations of this command
* command.setLocalizedNames({
* command.setNameLocalizations({
* 'en-GB': 'test',
* 'pt-BR': 'teste',
* })

View File

@@ -16,37 +16,42 @@ class ApplicationEmoji extends Emoji {
*/
this.application = application;
/**
* The user who created this emoji
* @type {?User}
*/
this.author = null;
this.managed = null;
this.requiresColons = null;
this._patch(data);
}
_patch(data) {
if ('name' in data) this.name = data.name;
if (data.user) this.author = this.client.users._add(data.user);
if (data.user) {
/**
* The user who created this emoji
* @type {User}
*/
this.author = this.client.users._add(data.user);
}
if ('managed' in data) {
/**
* Whether this emoji is managed by an external service
* @type {?boolean}
* Whether this emoji is managed by an external service. Always `false` for application emojis
* @type {false}
*/
this.managed = data.managed;
}
if ('require_colons' in data) {
/**
* Whether or not this emoji requires colons surrounding it
* @type {?boolean}
* Whether this emoji requires colons surrounding it. Always `true` for application emojis
* @type {true}
*/
this.requiresColons = data.require_colons;
}
if ('available' in data) {
/**
* Whether this emoji is available. Always `true` for application emojis
* @type {true}
*/
this.available = data.available;
}
}
/**
@@ -107,7 +112,8 @@ class ApplicationEmoji extends Emoji {
other.id === this.id &&
other.name === this.name &&
other.managed === this.managed &&
other.requiresColons === this.requiresColons
other.requiresColons === this.requiresColons &&
other.available === this.available
);
}
@@ -115,4 +121,49 @@ class ApplicationEmoji extends Emoji {
}
}
/**
* The emoji's name
* @name name
* @memberof ApplicationEmoji
* @instance
* @type {string}
* @readonly
*/
/**
* Whether the emoji is animated
* @name animated
* @memberof ApplicationEmoji
* @instance
* @type {boolean}
* @readonly
*/
/**
* Returns a URL for the emoji.
* @method imageURL
* @memberof ApplicationEmoji
* @instance
* @param {EmojiURLOptions} [options] Options for the image URL
* @returns {string}
*/
/**
* The time the emoji was created at
* @name createdAt
* @memberof ApplicationEmoji
* @instance
* @type {Date}
* @readonly
*/
/**
* The timestamp the emoji was created at
* @name createdTimestamp
* @memberof ApplicationEmoji
* @instance
* @type {number}
* @readonly
*/
module.exports = ApplicationEmoji;

View File

@@ -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}
*/
@@ -72,4 +72,40 @@ class BaseGuildEmoji extends Emoji {
* @deprecated Use {@link BaseGuildEmoji#imageURL} instead.
*/
/**
* The emoji's name
* @name name
* @memberof BaseGuildEmoji
* @instance
* @type {string}
* @readonly
*/
/**
* Whether or not the emoji is animated
* @name animated
* @memberof BaseGuildEmoji
* @instance
* @type {boolean}
* @readonly
*/
/**
* The time the emoji was created at.
* @name createdAt
* @memberof BaseGuildEmoji
* @instance
* @type {Date}
* @readonly
*/
/**
* The timestamp the emoji was created at.
* @name createdTimestamp
* @memberof BaseGuildEmoji
* @instance
* @type {number}
* @readonly
*/
module.exports = BaseGuildEmoji;

View File

@@ -163,6 +163,17 @@ class ClientApplication extends Application {
this.approximateUserInstallCount ??= null;
}
if ('approximate_user_authorization_count' in data) {
/**
* An approximate amount of users that have OAuth2 authorizations for this application.
*
* @type {?number}
*/
this.approximateUserAuthorizationCount = data.approximate_user_authorization_count;
} else {
this.approximateUserAuthorizationCount ??= null;
}
if ('guild_id' in data) {
/**
* The id of the guild associated with this application.

View File

@@ -64,8 +64,6 @@ class ClientUser extends User {
},
});
this.client.token = data.token;
this.client.rest.setToken(data.token);
const { updated } = this.client.actions.UserUpdate.handle(data);
return updated ?? this;
}

View File

@@ -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) {

View File

@@ -122,6 +122,20 @@ class GuildMember extends Base {
} else {
this.flags ??= new GuildMemberFlagsBitField().freeze();
}
if (data.avatar_decoration_data) {
/**
* The member avatar decoration's data
*
* @type {?AvatarDecorationData}
*/
this.avatarDecorationData = {
asset: data.avatar_decoration_data.asset,
skuId: data.avatar_decoration_data.sku_id,
};
} else {
this.avatarDecorationData = null;
}
}
_clone() {
@@ -166,6 +180,15 @@ class GuildMember extends Base {
return this.avatar && this.client.rest.cdn.guildMemberAvatar(this.guild.id, this.id, this.avatar, options);
}
/**
* A link to the member's avatar decoration.
*
* @returns {?string}
*/
avatarDecorationURL() {
return this.avatarDecorationData ? this.client.rest.cdn.avatarDecoration(this.avatarDecorationData.asset) : null;
}
/**
* A link to the member's banner.
* @param {ImageURLOptions} [options={}] Options for the banner URL
@@ -195,6 +218,16 @@ class GuildMember extends Base {
return this.bannerURL(options) ?? this.user.bannerURL(options);
}
/**
* A link to the member's guild avatar decoration if they have one.
* Otherwise, a link to their {@link User#avatarDecorationURL} will be returned.
*
* @returns {?string}
*/
displayAvatarDecorationURL() {
return this.avatarDecorationURL() ?? this.user.avatarDecorationURL();
}
/**
* The time this member joined the guild
* @type {?Date}
@@ -237,7 +270,7 @@ class GuildMember extends Base {
* @readonly
*/
get displayColor() {
return this.roles.color?.color ?? 0;
return this.roles.color?.colors.primaryColor ?? 0;
}
/**
@@ -499,7 +532,10 @@ class GuildMember extends Base {
this.communicationDisabledUntilTimestamp === member.communicationDisabledUntilTimestamp &&
this.flags.bitfield === member.flags.bitfield &&
(this._roles === member._roles ||
(this._roles.length === member._roles.length && this._roles.every((role, i) => role === member._roles[i])))
(this._roles.length === member._roles.length &&
this._roles.every((role, index) => role === member._roles[index]))) &&
this.avatarDecorationData?.asset === member.avatarDecorationData?.asset &&
this.avatarDecorationData?.skuId === member.avatarDecorationData?.skuId
);
}
@@ -525,6 +561,7 @@ class GuildMember extends Base {
json.bannerURL = this.bannerURL();
json.displayAvatarURL = this.displayAvatarURL();
json.displayBannerURL = this.displayBannerURL();
json.avatarDecorationURL = this.avatarDecorationURL();
return json;
}
}

View File

@@ -812,6 +812,7 @@ class Message extends Base {
return Boolean(
channel?.type === ChannelType.GuildAnnouncement &&
!this.flags.has(MessageFlags.Crossposted) &&
this.reference?.type !== MessageReferenceType.Forward &&
this.type === MessageType.Default &&
!this.poll &&
channel.viewable &&

View File

@@ -54,11 +54,37 @@ class Role extends Base {
if ('color' in data) {
/**
* The base 10 color of the role
*
* @type {number}
* @deprecated Use {@link Role#colors} instead.
*/
this.color = data.color;
}
/**
* @typedef {Object} RoleColors
* @property {number} primaryColor The primary color of the role
* @property {?number} secondaryColor The secondary color of the role.
* This will make the role a gradient between the other provided colors
* @property {?number} tertiaryColor The tertiary color of the role.
* When sending `tertiaryColor` the API enforces the role color to be a holographic style
* with values of `primaryColor = 11127295`, `secondaryColor = 16759788`, and `tertiaryColor = 16761760`.
* These values are available as a constant: `Constants.HolographicStyle`
*/
if ('colors' in data) {
/**
* The colors of the role
*
* @type {RoleColors}
*/
this.colors = {
primaryColor: data.colors.primary_color,
secondaryColor: data.colors.secondary_color,
tertiaryColor: data.colors.tertiary_color,
};
}
if ('hoist' in data) {
/**
* If true, users that are part of this role will appear in a separate category in the users list
@@ -170,7 +196,7 @@ class Role extends Base {
* @readonly
*/
get hexColor() {
return `#${this.color.toString(16).padStart(6, '0')}`;
return `#${this.colors.primaryColor.toString(16).padStart(6, '0')}`;
}
/**
@@ -231,6 +257,8 @@ class Role extends Base {
* @typedef {Object} RoleData
* @property {string} [name] The name of the role
* @property {ColorResolvable} [color] The color of the role, either a hex string or a base 10 number
* <warn>This property is deprecated. Use `colors` instead.</warn>
* @property {RoleColorsResolvable} [colors] The colors of the role
* @property {boolean} [hoist] Whether or not the role should be hoisted
* @property {number} [position] The position of the role
* @property {PermissionResolvable} [permissions] The permissions of the role
@@ -286,17 +314,39 @@ class Role extends Base {
/**
* Sets a new color for the role.
*
* @param {ColorResolvable} color The color of the role
* @param {string} [reason] Reason for changing the role's color
* @returns {Promise<Role>}
* @deprecated Use {@link Role#setColors} instead.
*/
async setColor(color, reason) {
return this.edit({ color, reason });
}
/**
* Sets new colors for the role.
*
* @param {RoleColorsResolvable} colors The colors of the role
* @param {string} [reason] Reason for changing the role's colors
* @returns {Promise<Role>}
* @example
* // Set the color of a role
* role.setColor('#FF0000')
* .then(updated => console.log(`Set color of role to ${updated.color}`))
* // Set the colors of a role
* role.setColors({ primaryColor: '#FF0000', secondaryColor: '#00FF00', tertiaryColor: '#0000FF' })
* .then(updated => console.log(`Set colors of role to ${updated.colors}`))
* .catch(console.error);
* @example
* // Set holographic colors using constants
* role.setColors({
* primaryColor: Constants.HolographicStyle.Primary,
* secondaryColor: Constants.HolographicStyle.Secondary,
* tertiaryColor: Constants.HolographicStyle.Tertiary,
* })
* .then(updated => console.log(`Set holographic colors for role ${updated.name}`))
* .catch(console.error);
*/
setColor(color, reason) {
return this.edit({ color, reason });
async setColors(colors, reason) {
return this.edit({ colors, reason });
}
/**
@@ -434,7 +484,9 @@ class Role extends Base {
role &&
this.id === role.id &&
this.name === role.name &&
this.color === role.color &&
this.colors.primaryColor === role.colors.primaryColor &&
this.colors.secondaryColor === role.colors.secondaryColor &&
this.colors.tertiaryColor === role.colors.tertiaryColor &&
this.hoist === role.hoist &&
this.position === role.position &&
this.permissions.bitfield === role.permissions.bitfield &&

View File

@@ -351,7 +351,7 @@ class ThreadChannel extends BaseChannel {
async edit(options) {
const newData = await this.client.rest.patch(Routes.channel(this.id), {
body: {
name: (options.name ?? this.name).trim(),
name: options.name,
archived: options.archived,
auto_archive_duration: options.autoArchiveDuration,
rate_limit_per_user: options.rateLimitPerUser,

View File

@@ -5,6 +5,7 @@ const { calculateUserDefaultAvatarIndex } = require('@discordjs/rest');
const { DiscordSnowflake } = require('@sapphire/snowflake');
const Base = require('./Base');
const TextBasedChannel = require('./interfaces/TextBasedChannel');
const { _transformCollectibles } = require('../util/Transformers.js');
const UserFlagsBitField = require('../util/UserFlagsBitField');
const { emitDeprecationWarningForUserFetchFlags } = require('../util/Util');
@@ -140,18 +141,74 @@ class User extends Base {
* @property {string} asset The avatar decoration hash
* @property {Snowflake} skuId The id of the avatar decoration's SKU
*/
if (data.avatar_decoration_data) {
/**
* The user avatar decoration's data
* @type {?AvatarDecorationData}
*/
this.avatarDecorationData = {
asset: data.avatar_decoration_data.asset,
skuId: data.avatar_decoration_data.sku_id,
};
if ('avatar_decoration_data' in data) {
if (data.avatar_decoration_data) {
/**
* The user avatar decoration's data
*
* @type {?AvatarDecorationData}
*/
this.avatarDecorationData = {
asset: data.avatar_decoration_data.asset,
skuId: data.avatar_decoration_data.sku_id,
};
} else {
this.avatarDecorationData = null;
}
} else {
this.avatarDecorationData = null;
this.avatarDecorationData ??= null;
}
/**
* @typedef {Object} NameplateData
* @property {Snowflake} skuId The id of the nameplate's SKU
* @property {string} asset The nameplate's asset path
* @property {string} label The nameplate's label
* @property {NameplatePalette} palette Background color of the nameplate
*/
/**
* @typedef {Object} Collectibles
* @property {?NameplateData} nameplate The user's nameplate data
*/
if (data.collectibles) {
/**
* The user's collectibles
*
* @type {?Collectibles}
*/
this.collectibles = _transformCollectibles(data.collectibles);
} else {
this.collectibles = null;
}
/**
* @typedef {Object} UserPrimaryGuild
* @property {?Snowflake} identityGuildId The id of the user's primary guild
* @property {?boolean} identityEnabled Whether the user is displaying the primary guild's tag
* @property {?string} tag The user's guild tag. Limited to 4 characters
* @property {?string} badge The guild tag badge hash
*/
if ('primary_guild' in data) {
if (data.primary_guild) {
/**
* The primary guild of the user
*
* @type {?UserPrimaryGuild}
*/
this.primaryGuild = {
identityGuildId: data.primary_guild.identity_guild_id,
identityEnabled: data.primary_guild.identity_enabled,
tag: data.primary_guild.tag,
badge: data.primary_guild.badge,
};
} else {
this.primaryGuild = null;
}
} else {
this.primaryGuild ??= null;
}
}
@@ -244,6 +301,18 @@ class User extends Base {
return this.banner && this.client.rest.cdn.banner(this.id, this.banner, options);
}
/**
* A link to the user's guild tag badge.
*
* @param {ImageURLOptions} [options={}] Options for the image URL
* @returns {?string}
*/
guildTagBadgeURL(options = {}) {
return this.primaryGuild?.badge
? this.client.rest.cdn.guildTagBadge(this.primaryGuild.identityGuildId, this.primaryGuild.badge, options)
: null;
}
/**
* The tag of this user
* <info>This user's username, or their legacy tag (e.g. `hydrabolt#0001`)
@@ -314,7 +383,15 @@ class User extends Base {
this.accentColor === user.accentColor &&
this.avatarDecoration === user.avatarDecoration &&
this.avatarDecorationData?.asset === user.avatarDecorationData?.asset &&
this.avatarDecorationData?.skuId === user.avatarDecorationData?.skuId
this.avatarDecorationData?.skuId === user.avatarDecorationData?.skuId &&
this.collectibles?.nameplate?.skuId === user.collectibles?.nameplate?.skuId &&
this.collectibles?.nameplate?.asset === user.collectibles?.nameplate?.asset &&
this.collectibles?.nameplate?.label === user.collectibles?.nameplate?.label &&
this.collectibles?.nameplate?.palette === user.collectibles?.nameplate?.palette &&
this.primaryGuild?.identityGuildId === user.primaryGuild?.identityGuildId &&
this.primaryGuild?.identityEnabled === user.primaryGuild?.identityEnabled &&
this.primaryGuild?.tag === user.primaryGuild?.tag &&
this.primaryGuild?.badge === user.primaryGuild?.badge
);
}
@@ -339,6 +416,18 @@ class User extends Base {
('avatar_decoration_data' in user
? this.avatarDecorationData?.asset === user.avatar_decoration_data?.asset &&
this.avatarDecorationData?.skuId === user.avatar_decoration_data?.sku_id
: true) &&
('collectibles' in user
? this.collectibles?.nameplate?.skuId === user.collectibles?.nameplate?.sku_id &&
this.collectibles?.nameplate?.asset === user.collectibles?.nameplate?.asset &&
this.collectibles?.nameplate?.label === user.collectibles?.nameplate?.label &&
this.collectibles?.nameplate?.palette === user.collectibles?.nameplate?.palette
: true) &&
('primary_guild' in user
? this.primaryGuild?.identityGuildId === user.primary_guild?.identity_guild_id &&
this.primaryGuild?.identityEnabled === user.primary_guild?.identity_enabled &&
this.primaryGuild?.tag === user.primary_guild?.tag &&
this.primaryGuild?.badge === user.primary_guild?.badge
: true)
);
}
@@ -388,6 +477,7 @@ class User extends Base {
json.avatarURL = this.avatarURL();
json.displayAvatarURL = this.displayAvatarURL();
json.bannerURL = this.banner ? this.bannerURL() : this.banner;
json.guildTagBadgeURL = this.guildTagBadgeURL();
return json;
}
}

View File

@@ -267,7 +267,7 @@ class Collector extends EventEmitter {
/**
* Allows collectors to be consumed with for-await-of loops
* @see {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for-await...of}
* @see {@link https://developer.mozilla.org/docs/Web/JavaScript/Reference/Statements/for-await...of}
*/
async *[Symbol.asyncIterator]() {
const queue = [];

View File

@@ -550,6 +550,11 @@
* @see {@link https://discord-api-types.dev/api/discord-api-types-v10/enum/MessageFlags}
*/
/**
* @external NameplatePalette
* @see {@link https://discord-api-types.dev/api/discord-api-types-v10/enum/NameplatePalette}
*/
/**
* @external OAuth2Scopes
* @see {@link https://discord-api-types.dev/api/discord-api-types-v10/enum/OAuth2Scopes}

View File

@@ -254,6 +254,21 @@ exports.StickerFormatExtensionMap = {
[StickerFormatType.GIF]: ImageFormat.GIF,
};
/**
* Holographic color values for role styling.
* When using `tertiaryColor`, the API enforces these specific values for holographic effect.
*
* @typedef {Object} HolographicStyle
* @property {number} Primary 11127295 (0xA9FFFF)
* @property {number} Secondary 16759788 (0xFFCCCC)
* @property {number} Tertiary 16761760 (0xFFE0A0)
*/
exports.HolographicStyle = {
Primary: 11_127_295,
Secondary: 16_759_788,
Tertiary: 16_761_760,
};
/**
* @typedef {Object} Constants Constants that can be used in an enum or object-like way.
* @property {number} MaxBulkDeletableMessageAge Max bulk deletable message age
@@ -264,4 +279,5 @@ exports.StickerFormatExtensionMap = {
* @property {VoiceBasedChannelTypes} VoiceBasedChannelTypes The types of channels that are voice-based
* @property {SelectMenuTypes} SelectMenuTypes The types of components that are select menus.
* @property {Object} StickerFormatExtensionMap A mapping between sticker formats and their respective image formats.
* @property {HolographicStyle} HolographicStyle Holographic color values for role styling.
*/

View File

@@ -12,7 +12,7 @@
* @property {string} ChannelDelete channelDelete
* @property {string} ChannelPinsUpdate channelPinsUpdate
* @property {string} ChannelUpdate channelUpdate
* @property {string} ClientReady ready
* @property {string} ClientReady clientReady
* @property {string} Debug debug
* @property {string} EntitlementCreate entitlementCreate
* @property {string} EntitlementUpdate entitlementUpdate
@@ -89,7 +89,7 @@
* @property {string} VoiceServerUpdate voiceServerUpdate
* @property {string} VoiceStateUpdate voiceStateUpdate
* @property {string} Warn warn
* @property {string} WebhooksUpdate webhookUpdate
* @property {string} WebhooksUpdate webhooksUpdate
*/
// JSDoc for IntelliSense purposes
@@ -108,7 +108,7 @@ module.exports = {
ChannelDelete: 'channelDelete',
ChannelPinsUpdate: 'channelPinsUpdate',
ChannelUpdate: 'channelUpdate',
ClientReady: 'ready',
ClientReady: 'clientReady',
Debug: 'debug',
EntitlementCreate: 'entitlementCreate',
EntitlementUpdate: 'entitlementUpdate',
@@ -186,5 +186,5 @@ module.exports = {
VoiceServerUpdate: 'voiceServerUpdate',
VoiceStateUpdate: 'voiceStateUpdate',
Warn: 'warn',
WebhooksUpdate: 'webhookUpdate',
WebhooksUpdate: 'webhooksUpdate',
};

View File

@@ -95,10 +95,31 @@ function _transformAPIIncidentsData(data) {
};
}
/**
* Transforms a collectibles object to a camel-cased variant.
*
* @param {APICollectibles} collectibles The collectibles to transform
* @returns {Collectibles}
* @ignore
*/
function _transformCollectibles(collectibles) {
if (!collectibles.nameplate) return { nameplate: null };
return {
nameplate: {
skuId: collectibles.nameplate.sku_id,
asset: collectibles.nameplate.asset,
label: collectibles.nameplate.label,
palette: collectibles.nameplate.palette,
},
};
}
module.exports = {
toSnakeCase,
_transformAPIAutoModerationAction,
_transformAPIMessageInteractionMetadata,
_transformGuildScheduledEventRecurrenceRule,
_transformAPIIncidentsData,
_transformCollectibles,
};

View File

@@ -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, EmojiURLOptions, ImageURLOptions, RawFile, REST, RESTOptions } from '@discordjs/rest';
import {
WebSocketManager as WSWebSocketManager,
IShardingStrategy,
@@ -80,6 +80,7 @@ import {
InteractionType,
InviteTargetType,
MessageType,
NameplatePalette,
OAuth2Scopes,
RESTPostAPIApplicationCommandsJSONBody,
Snowflake,
@@ -599,7 +600,7 @@ export abstract class CommandInteraction<Cached extends CacheType = CacheType> e
public inRawGuild(): this is CommandInteraction<'raw'>;
public deferReply(
options: InteractionDeferReplyOptions & { withResponse: true },
): Promise<InteractionCallbackResponse>;
): Promise<InteractionCallbackResponse<BooleanCache<Cached>>>;
/** @deprecated `fetchReply` is deprecated. Use `withResponse` instead or fetch the response after using the method. */
public deferReply(
options: InteractionDeferReplyOptions & { fetchReply: true },
@@ -611,29 +612,35 @@ export abstract class CommandInteraction<Cached extends CacheType = CacheType> e
): Promise<Message<BooleanCache<Cached>>>;
public fetchReply(message?: Snowflake | '@original'): Promise<Message<BooleanCache<Cached>>>;
public followUp(options: string | MessagePayload | InteractionReplyOptions): Promise<Message<BooleanCache<Cached>>>;
public reply(options: InteractionReplyOptions & { withResponse: true }): Promise<InteractionCallbackResponse>;
public reply(
options: InteractionReplyOptions & { withResponse: true },
): Promise<InteractionCallbackResponse<BooleanCache<Cached>>>;
/** @deprecated `fetchReply` is deprecated. Use `withResponse` instead or fetch the response after using the method. */
public reply(options: InteractionReplyOptions & { fetchReply: true }): Promise<Message<BooleanCache<Cached>>>;
public reply(
options: string | MessagePayload | InteractionReplyOptions,
): Promise<InteractionResponse<BooleanCache<Cached>>>;
public launchActivity(options: LaunchActivityOptions & { withResponse: true }): Promise<InteractionCallbackResponse>;
public launchActivity(
options: LaunchActivityOptions & { withResponse: true },
): Promise<InteractionCallbackResponse<BooleanCache<Cached>>>;
public launchActivity(options?: LaunchActivityOptions & { withResponse?: false }): Promise<undefined>;
public launchActivity(options?: LaunchActivityOptions): Promise<InteractionCallbackResponse | undefined>;
public launchActivity(
options?: LaunchActivityOptions,
): Promise<InteractionCallbackResponse<BooleanCache<Cached>> | undefined>;
public showModal(
modal:
| JSONEncodable<APIModalInteractionResponseCallbackData>
| ModalComponentData
| APIModalInteractionResponseCallbackData,
options: ShowModalOptions & { withResponse: true },
): Promise<InteractionCallbackResponse>;
): Promise<InteractionCallbackResponse<BooleanCache<Cached>>>;
public showModal(
modal:
| JSONEncodable<APIModalInteractionResponseCallbackData>
| ModalComponentData
| APIModalInteractionResponseCallbackData,
options?: ShowModalOptions & { withResponse: true },
): Promise<InteractionCallbackResponse>;
): Promise<InteractionCallbackResponse<BooleanCache<Cached>>>;
public showModal(
modal:
| JSONEncodable<APIModalInteractionResponseCallbackData>
@@ -691,14 +698,16 @@ export abstract class BaseGuild extends Base {
export class BaseGuildEmoji extends Emoji {
protected constructor(client: Client<true>, 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;
public get createdTimestamp(): number;
public guild: Guild | GuildPreview;
public id: Snowflake;
public managed: boolean | null;
public name: string;
public animated: boolean;
public managed: boolean;
public requiresColons: boolean | null;
}
@@ -1159,6 +1168,7 @@ export class ClientApplication extends Application {
public flags: Readonly<ApplicationFlagsBitField>;
public approximateGuildCount: number | null;
public approximateUserInstallCount: number | null;
public approximateUserAuthorizationCount: number | null;
public tags: string[];
public installParams: ClientApplicationInstallParams | null;
public integrationTypesConfig: IntegrationTypesConfiguration | null;
@@ -1485,7 +1495,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;
@@ -1504,10 +1514,16 @@ export class ApplicationEmoji extends Emoji {
private constructor(client: Client<true>, data: RawApplicationEmojiData, application: ClientApplication);
public application: ClientApplication;
public author: User | null;
public author: User;
public id: Snowflake;
public managed: boolean | null;
public requiresColons: boolean | null;
public managed: false;
public requiresColons: true;
public name: string;
public animated: boolean;
public available: true;
public get createdAt(): Date;
public get createdTimestamp(): number;
public imageURL(options?: EmojiURLOptions): string;
public delete(): Promise<ApplicationEmoji>;
public edit(options: ApplicationEmojiEditOptions): Promise<ApplicationEmoji>;
public equals(other: ApplicationEmoji | unknown): boolean;
@@ -1798,6 +1814,7 @@ export class GuildMember extends Base {
private constructor(client: Client<true>, data: RawGuildMemberData, guild: Guild);
private _roles: Snowflake[];
public avatar: string | null;
public avatarDecorationData: AvatarDecorationData | null;
public banner: string | null;
public get bannable(): boolean;
public get dmChannel(): DMChannel | null;
@@ -1825,6 +1842,7 @@ export class GuildMember extends Base {
public user: User;
public get voice(): VoiceState;
public avatarURL(options?: ImageURLOptions): string | null;
public avatarDecorationURL(): string | null;
public bannerURL(options?: ImageURLOptions): string | null;
public ban(options?: BanOptions): Promise<GuildMember>;
public disableCommunicationUntil(timeout: DateResolvable | null, reason?: string): Promise<GuildMember>;
@@ -1834,6 +1852,7 @@ export class GuildMember extends Base {
public deleteDM(): Promise<DMChannel>;
public displayAvatarURL(options?: ImageURLOptions): string;
public displayBannerURL(options?: ImageURLOptions): string | null;
public displayAvatarDecorationURL(): string | null;
public edit(options: GuildMemberEditOptions): Promise<GuildMember>;
public isCommunicationDisabled(): this is GuildMember & {
communicationDisabledUntilTimestamp: number;
@@ -2155,17 +2174,17 @@ export class InteractionCallback {
public type: InteractionType;
}
export class InteractionCallbackResponse {
export class InteractionCallbackResponse<InGuild extends boolean = boolean> {
private constructor(client: Client<true>, data: RESTPostAPIInteractionCallbackWithResponseResult);
public readonly client: Client<true>;
public interaction: InteractionCallback;
public resource: InteractionCallbackResource | null;
public resource: InteractionCallbackResource<InGuild> | null;
}
export class InteractionCallbackResource {
export class InteractionCallbackResource<InGuild extends boolean = boolean> {
private constructor(client: Client<true>, data: RESTAPIInteractionCallbackResourceObject);
public activityInstance: RESTAPIInteractionCallbackActivityInstanceResource | null;
public message: Message | null;
public message: Message<InGuild> | null;
public type: InteractionResponseType;
}
@@ -2236,8 +2255,8 @@ export class Invite extends Base {
public inviterId: Snowflake | null;
public maxAge: number | null;
public maxUses: number | null;
public memberCount: number;
public presenceCount: number;
public memberCount: number | null;
public presenceCount: number | null;
public targetApplication: IntegrationApplication | null;
public targetUser: User | null;
public targetType: InviteTargetType | null;
@@ -2522,7 +2541,7 @@ export class MessageComponentInteraction<Cached extends CacheType = CacheType> e
public inRawGuild(): this is MessageComponentInteraction<'raw'>;
public deferReply(
options: InteractionDeferReplyOptions & { withResponse: true },
): Promise<InteractionCallbackResponse>;
): Promise<InteractionCallbackResponse<BooleanCache<Cached>>>;
/** @deprecated `fetchReply` is deprecated. Use `withResponse` instead or fetch the response after using the method. */
public deferReply(
options: InteractionDeferReplyOptions & { fetchReply: true },
@@ -2530,7 +2549,7 @@ export class MessageComponentInteraction<Cached extends CacheType = CacheType> e
public deferReply(options?: InteractionDeferReplyOptions): Promise<InteractionResponse<BooleanCache<Cached>>>;
public deferUpdate(
options: InteractionDeferUpdateOptions & { withResponse: true },
): Promise<InteractionCallbackResponse>;
): Promise<InteractionCallbackResponse<BooleanCache<Cached>>>;
/** @deprecated `fetchReply` is deprecated. Use `withResponse` instead or fetch the response after using the method. */
public deferUpdate(
options: InteractionDeferUpdateOptions & { fetchReply: true },
@@ -2542,28 +2561,36 @@ export class MessageComponentInteraction<Cached extends CacheType = CacheType> e
): Promise<Message<BooleanCache<Cached>>>;
public fetchReply(message?: Snowflake | '@original'): Promise<Message<BooleanCache<Cached>>>;
public followUp(options: string | MessagePayload | InteractionReplyOptions): Promise<Message<BooleanCache<Cached>>>;
public reply(options: InteractionReplyOptions & { withResponse: true }): Promise<InteractionCallbackResponse>;
public reply(
options: InteractionReplyOptions & { withResponse: true },
): Promise<InteractionCallbackResponse<BooleanCache<Cached>>>;
/** @deprecated `fetchReply` is deprecated. Use `withResponse` instead or fetch the response after using the method. */
public reply(options: InteractionReplyOptions & { fetchReply: true }): Promise<Message<BooleanCache<Cached>>>;
public reply(
options: string | MessagePayload | InteractionReplyOptions,
): Promise<InteractionResponse<BooleanCache<Cached>>>;
public update(options: InteractionUpdateOptions & { withResponse: true }): Promise<InteractionCallbackResponse>;
public update(
options: InteractionUpdateOptions & { withResponse: true },
): Promise<InteractionCallbackResponse<BooleanCache<Cached>>>;
/** @deprecated `fetchReply` is deprecated. Use `withResponse` instead or fetch the response after using the method. */
public update(options: InteractionUpdateOptions & { fetchReply: true }): Promise<Message<BooleanCache<Cached>>>;
public update(
options: string | MessagePayload | InteractionUpdateOptions,
): Promise<InteractionResponse<BooleanCache<Cached>>>;
public launchActivity(options: LaunchActivityOptions & { withResponse: true }): Promise<InteractionCallbackResponse>;
public launchActivity(
options: LaunchActivityOptions & { withResponse: true },
): Promise<InteractionCallbackResponse<BooleanCache<Cached>>>;
public launchActivity(options?: LaunchActivityOptions & { withResponse?: false }): Promise<undefined>;
public launchActivity(options?: LaunchActivityOptions): Promise<InteractionCallbackResponse | undefined>;
public launchActivity(
options?: LaunchActivityOptions,
): Promise<InteractionCallbackResponse<BooleanCache<Cached>> | undefined>;
public showModal(
modal:
| JSONEncodable<APIModalInteractionResponseCallbackData>
| ModalComponentData
| APIModalInteractionResponseCallbackData,
options: ShowModalOptions & { withResponse: true },
): Promise<InteractionCallbackResponse>;
): Promise<InteractionCallbackResponse<BooleanCache<Cached>>>;
public showModal(
modal:
| JSONEncodable<APIModalInteractionResponseCallbackData>
@@ -2741,7 +2768,7 @@ export interface ActionRowModalData {
export class ModalSubmitFields {
private constructor(components: readonly (readonly ModalActionRowComponent[])[]);
public components: ActionRowModalData[];
public fields: Collection<string, ModalActionRowComponent>;
public fields: Collection<string, TextInputModalData>;
public getField<Type extends ComponentType>(customId: string, type: Type): { type: Type } & TextInputModalData;
public getField(customId: string, type?: ComponentType): TextInputModalData;
public getTextInputValue(customId: string): string;
@@ -2751,7 +2778,9 @@ export interface ModalMessageModalSubmitInteraction<Cached extends CacheType = C
extends ModalSubmitInteraction<Cached> {
message: Message<BooleanCache<Cached>>;
channelId: Snowflake;
update(options: InteractionUpdateOptions & { withResponse: true }): Promise<InteractionCallbackResponse>;
update(
options: InteractionUpdateOptions & { withResponse: true },
): Promise<InteractionCallbackResponse<BooleanCache<Cached>>>;
/** @deprecated `fetchReply` is deprecated. Use `withResponse` instead or fetch the response after using the method. */
update(options: InteractionUpdateOptions & { fetchReply: true }): Promise<Message>;
update(
@@ -2773,7 +2802,9 @@ export class ModalSubmitInteraction<Cached extends CacheType = CacheType> extend
public message: Message<BooleanCache<Cached>> | null;
public replied: boolean;
public readonly webhook: InteractionWebhook;
public reply(options: InteractionReplyOptions & { withResponse: true }): Promise<InteractionCallbackResponse>;
public reply(
options: InteractionReplyOptions & { withResponse: true },
): Promise<InteractionCallbackResponse<BooleanCache<Cached>>>;
/** @deprecated `fetchReply` is deprecated. Use `withResponse` instead or fetch the response after using the method. */
public reply(options: InteractionReplyOptions & { fetchReply: true }): Promise<Message<BooleanCache<Cached>>>;
public reply(
@@ -2785,7 +2816,7 @@ export class ModalSubmitInteraction<Cached extends CacheType = CacheType> extend
): Promise<Message<BooleanCache<Cached>>>;
public deferReply(
options: InteractionDeferReplyOptions & { withResponse: true },
): Promise<InteractionCallbackResponse>;
): Promise<InteractionCallbackResponse<BooleanCache<Cached>>>;
/** @deprecated `fetchReply` is deprecated. Use `withResponse` instead or fetch the response after using the method. */
public deferReply(
options: InteractionDeferReplyOptions & { fetchReply: true },
@@ -2795,7 +2826,7 @@ export class ModalSubmitInteraction<Cached extends CacheType = CacheType> extend
public followUp(options: string | MessagePayload | InteractionReplyOptions): Promise<Message<BooleanCache<Cached>>>;
public deferUpdate(
options: InteractionDeferUpdateOptions & { withResponse: true },
): Promise<InteractionCallbackResponse>;
): Promise<InteractionCallbackResponse<BooleanCache<Cached>>>;
/** @deprecated `fetchReply` is deprecated. Use `withResponse` instead or fetch the response after using the method. */
public deferUpdate(
options: InteractionDeferUpdateOptions & { fetchReply: true },
@@ -2803,9 +2834,13 @@ export class ModalSubmitInteraction<Cached extends CacheType = CacheType> extend
public deferUpdate(options?: InteractionDeferUpdateOptions): Promise<InteractionResponse<BooleanCache<Cached>>>;
/** @deprecated Sending a premium-style button is the new Discord behaviour. */
public sendPremiumRequired(): Promise<void>;
public launchActivity(options: LaunchActivityOptions & { withResponse: true }): Promise<InteractionCallbackResponse>;
public launchActivity(
options: LaunchActivityOptions & { withResponse: true },
): Promise<InteractionCallbackResponse<BooleanCache<Cached>>>;
public launchActivity(options?: LaunchActivityOptions & { withResponse?: false }): Promise<undefined>;
public launchActivity(options?: LaunchActivityOptions): Promise<InteractionCallbackResponse | undefined>;
public launchActivity(
options?: LaunchActivityOptions,
): Promise<InteractionCallbackResponse<BooleanCache<Cached>> | undefined>;
public inGuild(): this is ModalSubmitInteraction<'raw' | 'cached'>;
public inCachedGuild(): this is ModalSubmitInteraction<'cached'>;
public inRawGuild(): this is ModalSubmitInteraction<'raw'>;
@@ -3054,9 +3089,23 @@ export class RichPresenceAssets {
public smallImageURL(options?: ImageURLOptions): string | null;
}
export interface RoleColors {
primaryColor: number;
secondaryColor: number | null;
tertiaryColor: number | null;
}
export interface RoleColorsResolvable {
primaryColor: ColorResolvable;
secondaryColor?: ColorResolvable;
tertiaryColor?: ColorResolvable;
}
export class Role extends Base {
private constructor(client: Client<true>, data: RawRoleData, guild: Guild);
/** @deprecated Use {@link Role.colors} instead. */
public color: number;
public colors: RoleColors;
public get createdAt(): Date;
public get createdTimestamp(): number;
public get editable(): boolean;
@@ -3084,7 +3133,9 @@ export class Role extends Base {
channel: NonThreadGuildBasedChannel | Snowflake,
checkAdmin?: boolean,
): Readonly<PermissionsBitField>;
/** @deprecated Use {@link Role.setColors} instead. */
public setColor(color: ColorResolvable, reason?: string): Promise<Role>;
public setColors(colors: RoleColorsResolvable, reason?: string): Promise<Role>;
public setHoist(hoist?: boolean, reason?: string): Promise<Role>;
public setMentionable(mentionable?: boolean, reason?: string): Promise<Role>;
public setName(name: string, reason?: string): Promise<Role>;
@@ -3752,6 +3803,24 @@ export interface AvatarDecorationData {
skuId: Snowflake;
}
export interface Collectibles {
nameplate: NameplateData | null;
}
export interface UserPrimaryGuild {
badge: string | null;
identityEnabled: boolean | null;
identityGuildId: Snowflake | null;
tag: string | null;
}
export interface NameplateData {
asset: string;
label: string;
palette: NameplatePalette;
skuId: Snowflake;
}
export interface UnfurledMediaItemData {
url: string;
}
@@ -3777,6 +3846,7 @@ export class User extends Base {
public bot: boolean;
public get createdAt(): Date;
public get createdTimestamp(): number;
public collectibles: Collectibles | null;
public discriminator: string;
public get displayName(): string;
public get defaultAvatarURL(): string;
@@ -3786,12 +3856,14 @@ export class User extends Base {
public get hexAccentColor(): HexColorString | null | undefined;
public id: Snowflake;
public get partial(): false;
public primaryGuild: UserPrimaryGuild | null;
public system: boolean;
public get tag(): string;
public username: string;
public avatarURL(options?: ImageURLOptions): string | null;
public avatarDecorationURL(options?: BaseImageURLOptions): string | null;
public bannerURL(options?: ImageURLOptions): string | null | undefined;
public guildTagBadgeURL(options?: ImageURLOptions): string | null;
public createDM(force?: boolean): Promise<DMChannel>;
public deleteDM(): Promise<DMChannel>;
public displayAvatarURL(options?: ImageURLOptions): string;
@@ -4236,6 +4308,11 @@ export type DeletableMessageType =
| MessageType.UserJoin;
export const Constants: {
HolographicStyle: {
Primary: 11_127_295;
Secondary: 16_759_788;
Tertiary: 16_761_760;
};
MaxBulkDeletableMessageAge: 1_209_600_000;
SweeperKeys: SweeperKey[];
NonSystemMessageTypes: NonSystemMessageType[];
@@ -4957,7 +5034,9 @@ export abstract class MessageManager<InGuild extends boolean = boolean> extends
): Promise<Message<InGuild>>;
public fetch(options: MessageResolvable | FetchMessageOptions): Promise<Message<InGuild>>;
public fetch(options?: FetchMessagesOptions): Promise<Collection<Snowflake, Message<InGuild>>>;
/** @deprecated Use {@link MessageManager.fetchPins} instead. */
public fetchPinned(cache?: boolean): Promise<Collection<Snowflake, Message<InGuild>>>;
public fetchPins(options?: FetchPinnedMessagesOptions): Promise<FetchPinnedMessagesResponse<InGuild>>;
public react(message: MessageResolvable, emoji: EmojiIdentifierResolvable): Promise<void>;
public pin(message: MessageResolvable, reason?: string): Promise<void>;
public unpin(message: MessageResolvable, reason?: string): Promise<void>;
@@ -5764,6 +5843,7 @@ export interface ClientEvents {
oldChannel: DMChannel | NonThreadGuildBasedChannel,
newChannel: DMChannel | NonThreadGuildBasedChannel,
];
clientReady: [client: Client<true>];
debug: [message: string];
warn: [message: string];
emojiCreate: [emoji: GuildEmoji];
@@ -5787,9 +5867,13 @@ export interface ClientEvents {
guildMembersChunk: [members: ReadonlyCollection<Snowflake, GuildMember>, guild: Guild, data: GuildMembersChunk];
guildMemberUpdate: [oldMember: GuildMember | PartialGuildMember, newMember: GuildMember];
guildUpdate: [oldGuild: Guild, newGuild: Guild];
guildSoundboardSoundCreate: [soundboardSound: SoundboardSound];
guildSoundboardSoundDelete: [soundboardSound: SoundboardSound | PartialSoundboardSound];
guildSoundboardSoundUpdate: [oldSoundboardSound: SoundboardSound | null, newSoundboardSound: SoundboardSound];
guildSoundboardSoundCreate: [soundboardSound: GuildSoundboardSound];
guildSoundboardSoundDelete: [soundboardSound: GuildSoundboardSound | PartialSoundboardSound];
guildSoundboardSoundUpdate: [
oldSoundboardSound: GuildSoundboardSound | null,
newSoundboardSound: GuildSoundboardSound,
];
guildSoundboardSoundsUpdate: [soundboardSounds: ReadonlyCollection<Snowflake, GuildSoundboardSound>, guild: Guild];
inviteCreate: [invite: Invite];
inviteDelete: [invite: Invite];
messageCreate: [message: OmitPartialGroupDMChannel<Message>];
@@ -5820,6 +5904,7 @@ export interface ClientEvents {
newMessage: OmitPartialGroupDMChannel<Message>,
];
presenceUpdate: [oldPresence: Presence | null, newPresence: Presence];
/** @deprecated Use {@link ClientEvents.ClientReady} instead. */
ready: [client: Client<true>];
invalidated: [];
roleCreate: [role: Role];
@@ -5865,7 +5950,7 @@ export interface ClientEvents {
guildScheduledEventDelete: [guildScheduledEvent: GuildScheduledEvent | PartialGuildScheduledEvent];
guildScheduledEventUserAdd: [guildScheduledEvent: GuildScheduledEvent | PartialGuildScheduledEvent, user: User];
guildScheduledEventUserRemove: [guildScheduledEvent: GuildScheduledEvent | PartialGuildScheduledEvent, user: User];
soundboardSounds: [soundboardSounds: ReadonlyCollection<Snowflake, SoundboardSound>, guild: Guild];
soundboardSounds: [soundboardSounds: ReadonlyCollection<Snowflake, GuildSoundboardSound>, guild: Guild];
}
export interface ClientFetchInviteOptions {
@@ -6005,7 +6090,7 @@ export enum Events {
AutoModerationRuleCreate = 'autoModerationRuleCreate',
AutoModerationRuleDelete = 'autoModerationRuleDelete',
AutoModerationRuleUpdate = 'autoModerationRuleUpdate',
ClientReady = 'ready',
ClientReady = 'clientReady',
EntitlementCreate = 'entitlementCreate',
EntitlementDelete = 'entitlementDelete',
EntitlementUpdate = 'entitlementUpdate',
@@ -6057,7 +6142,7 @@ export enum Events {
VoiceServerUpdate = 'voiceServerUpdate',
VoiceStateUpdate = 'voiceStateUpdate',
TypingStart = 'typingStart',
WebhooksUpdate = 'webhookUpdate',
WebhooksUpdate = 'webhooksUpdate',
InteractionCreate = 'interactionCreate',
Error = 'error',
Warn = 'warn',
@@ -6275,6 +6360,23 @@ export interface FetchMessagesOptions {
cache?: boolean;
}
export interface FetchPinnedMessagesOptions {
before?: DateResolvable;
cache?: boolean;
limit?: number;
}
export interface FetchPinnedMessagesResponse<InGuild extends boolean = boolean> {
hasMore: boolean;
items: readonly MessagePin<InGuild>[];
}
export interface MessagePin<InGuild extends boolean = boolean> {
message: Message<InGuild>;
get pinnedAt(): Date;
pinnedTimestamp: number;
}
export interface FetchReactionUsersOptions {
type?: ReactionType;
limit?: number;
@@ -7340,7 +7442,9 @@ export interface ResolvedOverwriteOptions {
export interface RoleData {
name?: string;
/** @deprecated Use {@link RoleData.colors} instead. */
color?: ColorResolvable;
colors?: RoleColorsResolvable;
hoist?: boolean;
position?: number;
permissions?: PermissionResolvable;

View File

@@ -231,6 +231,7 @@ import {
FileComponentData,
ContainerComponentData,
InteractionResponse,
FetchPinnedMessagesResponse,
} from '.';
import {
expectAssignable,
@@ -463,7 +464,7 @@ client.on('messageCreate', async message => {
const component = await message.awaitMessageComponent({ componentType: ComponentType.Button });
expectType<ButtonInteraction<'cached'>>(component);
expectType<Message<true>>(await component.reply({ fetchReply: true }));
expectType<InteractionCallbackResponse>(await component.reply({ withResponse: true }));
expectType<InteractionCallbackResponse<true>>(await component.reply({ withResponse: true }));
const buttonCollector = message.createMessageComponentCollector({ componentType: ComponentType.Button });
expectType<InteractionCollector<ButtonInteraction<'cached'>>>(buttonCollector);
@@ -1690,6 +1691,7 @@ declare const guildChannelManager: GuildChannelManager;
expectType<Promise<Message<true>>>(messages.edit('1234567890', 'text'));
expectType<Promise<Message<true>>>(messages.fetch('1234567890'));
expectType<Promise<Collection<Snowflake, Message<true>>>>(messages.fetchPinned());
expectType<Promise<FetchPinnedMessagesResponse<true>>>(messages.fetchPins());
expectType<Guild>(message.guild);
expectType<Snowflake>(message.guildId);
expectType<GuildTextBasedChannel>(message.channel.messages.channel);
@@ -1703,6 +1705,7 @@ declare const guildChannelManager: GuildChannelManager;
expectType<Promise<Message>>(messages.edit('1234567890', 'text'));
expectType<Promise<Message>>(messages.fetch('1234567890'));
expectType<Promise<Collection<Snowflake, Message>>>(messages.fetchPinned());
expectType<Promise<FetchPinnedMessagesResponse>>(messages.fetchPins());
expectType<Guild | null>(message.guild);
expectType<Snowflake | null>(message.guildId);
expectType<DMChannel | PartialGroupDMChannel | GuildTextBasedChannel>(message.channel.messages.channel);
@@ -1882,18 +1885,18 @@ client.on('interactionCreate', async interaction => {
expectType<Guild>(interaction.guild);
expectType<Promise<Message<true>>>(interaction.reply({ content: 'a', fetchReply: true }));
expectType<Promise<Message<true>>>(interaction.deferReply({ fetchReply: true }));
expectType<Promise<InteractionCallbackResponse>>(interaction.reply({ content: 'a', withResponse: true }));
expectType<Promise<InteractionCallbackResponse>>(interaction.deferReply({ withResponse: true }));
expectType<Promise<InteractionCallbackResponse<true>>>(interaction.reply({ content: 'a', withResponse: true }));
expectType<Promise<InteractionCallbackResponse<true>>>(interaction.deferReply({ withResponse: true }));
expectType<Promise<Message<true>>>(interaction.editReply({ content: 'a' }));
expectType<Promise<Message<true>>>(interaction.fetchReply());
expectType<Promise<Message<true>>>(interaction.update({ content: 'a', fetchReply: true }));
expectType<Promise<Message<true>>>(interaction.deferUpdate({ fetchReply: true }));
expectType<Promise<InteractionCallbackResponse>>(interaction.update({ content: 'a', withResponse: true }));
expectType<Promise<InteractionCallbackResponse>>(interaction.deferUpdate({ withResponse: true }));
expectType<Promise<InteractionCallbackResponse<true>>>(interaction.update({ content: 'a', withResponse: true }));
expectType<Promise<InteractionCallbackResponse<true>>>(interaction.deferUpdate({ withResponse: true }));
expectType<Promise<Message<true>>>(interaction.followUp({ content: 'a' }));
expectType<Promise<InteractionCallbackResponse>>(interaction.launchActivity({ withResponse: true }));
expectType<Promise<InteractionCallbackResponse<true>>>(interaction.launchActivity({ withResponse: true }));
expectType<Promise<undefined>>(interaction.launchActivity({ withResponse: false }));
expectType<Promise<InteractionCallbackResponse | undefined>>(
expectType<Promise<InteractionCallbackResponse<true> | undefined>>(
interaction.launchActivity({ withResponse: booleanValue }),
);
} else if (interaction.inRawGuild()) {
@@ -1903,18 +1906,18 @@ client.on('interactionCreate', async interaction => {
expectType<null>(interaction.guild);
expectType<Promise<Message<false>>>(interaction.reply({ content: 'a', fetchReply: true }));
expectType<Promise<Message<false>>>(interaction.deferReply({ fetchReply: true }));
expectType<Promise<InteractionCallbackResponse>>(interaction.reply({ content: 'a', withResponse: true }));
expectType<Promise<InteractionCallbackResponse>>(interaction.deferReply({ withResponse: true }));
expectType<Promise<InteractionCallbackResponse<false>>>(interaction.reply({ content: 'a', withResponse: true }));
expectType<Promise<InteractionCallbackResponse<false>>>(interaction.deferReply({ withResponse: true }));
expectType<Promise<Message<false>>>(interaction.editReply({ content: 'a' }));
expectType<Promise<Message<false>>>(interaction.fetchReply());
expectType<Promise<Message<false>>>(interaction.update({ content: 'a', fetchReply: true }));
expectType<Promise<Message<false>>>(interaction.deferUpdate({ fetchReply: true }));
expectType<Promise<InteractionCallbackResponse>>(interaction.update({ content: 'a', withResponse: true }));
expectType<Promise<InteractionCallbackResponse>>(interaction.deferUpdate({ withResponse: true }));
expectType<Promise<InteractionCallbackResponse<false>>>(interaction.update({ content: 'a', withResponse: true }));
expectType<Promise<InteractionCallbackResponse<false>>>(interaction.deferUpdate({ withResponse: true }));
expectType<Promise<Message<false>>>(interaction.followUp({ content: 'a' }));
expectType<Promise<InteractionCallbackResponse>>(interaction.launchActivity({ withResponse: true }));
expectType<Promise<InteractionCallbackResponse<false>>>(interaction.launchActivity({ withResponse: true }));
expectType<Promise<undefined>>(interaction.launchActivity({ withResponse: false }));
expectType<Promise<InteractionCallbackResponse | undefined>>(
expectType<Promise<InteractionCallbackResponse<false> | undefined>>(
interaction.launchActivity({ withResponse: booleanValue }),
);
} else if (interaction.inGuild()) {
@@ -1972,14 +1975,14 @@ client.on('interactionCreate', async interaction => {
expectAssignable<CommandInteraction<'cached'>>(interaction);
expectType<Promise<Message<true>>>(interaction.reply({ content: 'a', fetchReply: true }));
expectType<Promise<Message<true>>>(interaction.deferReply({ fetchReply: true }));
expectType<Promise<InteractionCallbackResponse>>(interaction.reply({ content: 'a', withResponse: true }));
expectType<Promise<InteractionCallbackResponse>>(interaction.deferReply({ withResponse: true }));
expectType<Promise<InteractionCallbackResponse<true>>>(interaction.reply({ content: 'a', withResponse: true }));
expectType<Promise<InteractionCallbackResponse<true>>>(interaction.deferReply({ withResponse: true }));
expectType<Promise<Message<true>>>(interaction.editReply({ content: 'a' }));
expectType<Promise<Message<true>>>(interaction.fetchReply());
expectType<Promise<Message<true>>>(interaction.followUp({ content: 'a' }));
expectType<Promise<InteractionCallbackResponse>>(interaction.launchActivity({ withResponse: true }));
expectType<Promise<InteractionCallbackResponse<true>>>(interaction.launchActivity({ withResponse: true }));
expectType<Promise<undefined>>(interaction.launchActivity({ withResponse: false }));
expectType<Promise<InteractionCallbackResponse | undefined>>(
expectType<Promise<InteractionCallbackResponse<true> | undefined>>(
interaction.launchActivity({ withResponse: booleanValue }),
);
} else if (interaction.inRawGuild()) {
@@ -1987,14 +1990,14 @@ client.on('interactionCreate', async interaction => {
expectType<null>(interaction.guild);
expectType<Promise<Message<false>>>(interaction.reply({ content: 'a', fetchReply: true }));
expectType<Promise<Message<false>>>(interaction.deferReply({ fetchReply: true }));
expectType<Promise<InteractionCallbackResponse>>(interaction.reply({ content: 'a', withResponse: true }));
expectType<Promise<InteractionCallbackResponse>>(interaction.deferReply({ withResponse: true }));
expectType<Promise<InteractionCallbackResponse<false>>>(interaction.reply({ content: 'a', withResponse: true }));
expectType<Promise<InteractionCallbackResponse<false>>>(interaction.deferReply({ withResponse: true }));
expectType<Promise<Message<false>>>(interaction.editReply({ content: 'a' }));
expectType<Promise<Message<false>>>(interaction.fetchReply());
expectType<Promise<Message<false>>>(interaction.followUp({ content: 'a' }));
expectType<Promise<InteractionCallbackResponse>>(interaction.launchActivity({ withResponse: true }));
expectType<Promise<InteractionCallbackResponse<false>>>(interaction.launchActivity({ withResponse: true }));
expectType<Promise<undefined>>(interaction.launchActivity({ withResponse: false }));
expectType<Promise<InteractionCallbackResponse | undefined>>(
expectType<Promise<InteractionCallbackResponse<false> | undefined>>(
interaction.launchActivity({ withResponse: booleanValue }),
);
} else if (interaction.inGuild()) {
@@ -2063,14 +2066,14 @@ client.on('interactionCreate', async interaction => {
expectType<Message<true>>(interaction.message);
expectType<Guild>(interaction.guild);
expectType<Promise<Message<true>>>(interaction.reply({ fetchReply: true }));
expectType<Promise<InteractionCallbackResponse>>(interaction.reply({ withResponse: true }));
expectType<Promise<InteractionCallbackResponse<true>>>(interaction.reply({ withResponse: true }));
} else if (interaction.inRawGuild()) {
expectAssignable<ButtonInteraction>(interaction);
expectType<APIButtonComponent>(interaction.component);
expectType<Message<false>>(interaction.message);
expectType<null>(interaction.guild);
expectType<Promise<Message<false>>>(interaction.reply({ fetchReply: true }));
expectType<Promise<InteractionCallbackResponse>>(interaction.reply({ withResponse: true }));
expectType<Promise<InteractionCallbackResponse<false>>>(interaction.reply({ withResponse: true }));
} else if (interaction.inGuild()) {
expectAssignable<ButtonInteraction>(interaction);
expectType<ButtonComponent | APIButtonComponent>(interaction.component);
@@ -2094,14 +2097,14 @@ client.on('interactionCreate', async interaction => {
expectType<Message<true>>(interaction.message);
expectType<Guild>(interaction.guild);
expectType<Promise<Message<true>>>(interaction.reply({ fetchReply: true }));
expectType<Promise<InteractionCallbackResponse>>(interaction.reply({ withResponse: true }));
expectType<Promise<InteractionCallbackResponse<true>>>(interaction.reply({ withResponse: true }));
} else if (interaction.inRawGuild()) {
expectAssignable<StringSelectMenuInteraction>(interaction);
expectType<APIStringSelectComponent>(interaction.component);
expectType<Message<false>>(interaction.message);
expectType<null>(interaction.guild);
expectType<Promise<Message<false>>>(interaction.reply({ fetchReply: true }));
expectType<Promise<InteractionCallbackResponse>>(interaction.reply({ withResponse: true }));
expectType<Promise<InteractionCallbackResponse<false>>>(interaction.reply({ withResponse: true }));
} else if (interaction.inGuild()) {
expectAssignable<StringSelectMenuInteraction>(interaction);
expectType<SelectMenuComponent | APIStringSelectComponent>(interaction.component);
@@ -2121,7 +2124,7 @@ client.on('interactionCreate', async interaction => {
expectNotAssignable<Interaction<'cached'>>(interaction);
expectAssignable<ChatInputCommandInteraction>(interaction);
expectType<Promise<Message<false>>>(interaction.reply({ fetchReply: true }));
expectType<Promise<InteractionCallbackResponse>>(interaction.reply({ withResponse: true }));
expectType<Promise<InteractionCallbackResponse<false>>>(interaction.reply({ withResponse: true }));
expectType<APIInteractionDataResolvedGuildMember | null>(interaction.options.getMember('test'));
expectType<APIInteractionDataResolvedChannel>(interaction.options.getChannel('test', true));
@@ -2136,7 +2139,7 @@ client.on('interactionCreate', async interaction => {
expectType<GuildMember | null>(interaction.options.getMember('test'));
expectAssignable<ChatInputCommandInteraction>(interaction);
expectType<Promise<Message<true>>>(interaction.reply({ fetchReply: true }));
expectType<Promise<InteractionCallbackResponse>>(interaction.reply({ withResponse: true }));
expectType<Promise<InteractionCallbackResponse<true>>>(interaction.reply({ withResponse: true }));
expectType<GuildBasedChannel>(interaction.options.getChannel('test', true));
expectType<Role>(interaction.options.getRole('test', true));
@@ -2208,28 +2211,28 @@ client.on('interactionCreate', async interaction => {
expectAssignable<PrimaryEntryPointCommandInteraction>(interaction);
expectAssignable<Guild>(interaction.guild);
expectAssignable<CommandInteraction<'cached'>>(interaction);
expectType<Promise<InteractionCallbackResponse>>(interaction.reply({ content: 'a', withResponse: true }));
expectType<Promise<InteractionCallbackResponse>>(interaction.deferReply({ withResponse: true }));
expectType<Promise<InteractionCallbackResponse<true>>>(interaction.reply({ content: 'a', withResponse: true }));
expectType<Promise<InteractionCallbackResponse<true>>>(interaction.deferReply({ withResponse: true }));
expectType<Promise<InteractionResponse<true>>>(interaction.deferReply());
expectType<Promise<InteractionResponse<true>>>(interaction.reply({ content: 'a', withResponse: false }));
expectType<Promise<InteractionResponse<true>>>(interaction.deferReply({ withResponse: false }));
expectType<Promise<Message<true>>>(interaction.editReply({ content: 'a' }));
expectType<Promise<Message<true>>>(interaction.fetchReply());
expectType<Promise<Message<true>>>(interaction.followUp({ content: 'a' }));
expectType<Promise<InteractionCallbackResponse>>(interaction.launchActivity({ withResponse: true }));
expectType<Promise<InteractionCallbackResponse<true>>>(interaction.launchActivity({ withResponse: true }));
expectType<Promise<undefined>>(interaction.launchActivity({ withResponse: false }));
} else if (interaction.inRawGuild()) {
expectAssignable<PrimaryEntryPointCommandInteraction>(interaction);
expectType<null>(interaction.guild);
expectType<Promise<InteractionCallbackResponse>>(interaction.reply({ content: 'a', withResponse: true }));
expectType<Promise<InteractionCallbackResponse>>(interaction.deferReply({ withResponse: true }));
expectType<Promise<InteractionCallbackResponse<false>>>(interaction.reply({ content: 'a', withResponse: true }));
expectType<Promise<InteractionCallbackResponse<false>>>(interaction.deferReply({ withResponse: true }));
expectType<Promise<InteractionResponse<false>>>(interaction.deferReply());
expectType<Promise<InteractionResponse<false>>>(interaction.reply({ content: 'a', withResponse: false }));
expectType<Promise<InteractionResponse<false>>>(interaction.deferReply({ withResponse: false }));
expectType<Promise<Message<false>>>(interaction.editReply({ content: 'a' }));
expectType<Promise<Message<false>>>(interaction.fetchReply());
expectType<Promise<Message<false>>>(interaction.followUp({ content: 'a' }));
expectType<Promise<InteractionCallbackResponse>>(interaction.launchActivity({ withResponse: true }));
expectType<Promise<InteractionCallbackResponse<false>>>(interaction.launchActivity({ withResponse: true }));
expectType<Promise<undefined>>(interaction.launchActivity({ withResponse: false }));
} else if (interaction.inGuild()) {
expectAssignable<PrimaryEntryPointCommandInteraction>(interaction);
@@ -2268,27 +2271,27 @@ client.on('interactionCreate', async interaction => {
expectType<Guild>(interaction.guild);
expectType<Promise<Message<true>>>(interaction.reply({ content: 'a', fetchReply: true }));
expectType<Promise<Message<true>>>(interaction.deferReply({ fetchReply: true }));
expectType<Promise<InteractionCallbackResponse>>(interaction.reply({ content: 'a', withResponse: true }));
expectType<Promise<InteractionCallbackResponse>>(interaction.deferReply({ withResponse: true }));
expectType<Promise<InteractionCallbackResponse<true>>>(interaction.reply({ content: 'a', withResponse: true }));
expectType<Promise<InteractionCallbackResponse<true>>>(interaction.deferReply({ withResponse: true }));
expectType<Promise<Message<true>>>(interaction.editReply({ content: 'a' }));
expectType<Promise<Message<true>>>(interaction.fetchReply());
expectType<Promise<Message<true>>>(interaction.deferUpdate({ fetchReply: true }));
expectType<Promise<InteractionCallbackResponse>>(interaction.deferUpdate({ withResponse: true }));
expectType<Promise<InteractionCallbackResponse<true>>>(interaction.deferUpdate({ withResponse: true }));
expectType<Promise<Message<true>>>(interaction.followUp({ content: 'a' }));
expectType<Promise<InteractionCallbackResponse>>(interaction.launchActivity({ withResponse: true }));
expectType<Promise<InteractionCallbackResponse<true>>>(interaction.launchActivity({ withResponse: true }));
} else if (interaction.inRawGuild()) {
expectAssignable<ModalSubmitInteraction>(interaction);
expectType<null>(interaction.guild);
expectType<Promise<Message<false>>>(interaction.reply({ content: 'a', fetchReply: true }));
expectType<Promise<Message<false>>>(interaction.deferReply({ fetchReply: true }));
expectType<Promise<InteractionCallbackResponse>>(interaction.reply({ content: 'a', withResponse: true }));
expectType<Promise<InteractionCallbackResponse>>(interaction.deferReply({ withResponse: true }));
expectType<Promise<InteractionCallbackResponse<false>>>(interaction.reply({ content: 'a', withResponse: true }));
expectType<Promise<InteractionCallbackResponse<false>>>(interaction.deferReply({ withResponse: true }));
expectType<Promise<Message<false>>>(interaction.editReply({ content: 'a' }));
expectType<Promise<Message<false>>>(interaction.fetchReply());
expectType<Promise<Message<false>>>(interaction.deferUpdate({ fetchReply: true }));
expectType<Promise<InteractionCallbackResponse>>(interaction.deferUpdate({ withResponse: true }));
expectType<Promise<InteractionCallbackResponse<false>>>(interaction.deferUpdate({ withResponse: true }));
expectType<Promise<Message<false>>>(interaction.followUp({ content: 'a' }));
expectType<Promise<InteractionCallbackResponse>>(interaction.launchActivity({ withResponse: true }));
expectType<Promise<InteractionCallbackResponse<false>>>(interaction.launchActivity({ withResponse: true }));
} else if (interaction.inGuild()) {
expectAssignable<ModalSubmitInteraction>(interaction);
expectType<Guild | null>(interaction.guild);

View File

@@ -55,7 +55,7 @@
"homepage": "https://discord.js.org",
"funding": "https://github.com/discordjs/discord.js?sponsor",
"dependencies": {
"discord-api-types": "^0.37.119"
"discord-api-types": "^0.38.16"
},
"devDependencies": {
"@discordjs/api-extractor": "workspace:^",

View File

@@ -72,7 +72,7 @@
"@discordjs/rest": "workspace:^",
"@discordjs/util": "workspace:^",
"@discordjs/ws": "workspace:^",
"discord-api-types": "^0.37.119"
"discord-api-types": "^0.38.16"
},
"devDependencies": {
"@discordjs/api-extractor": "workspace:^",

View File

@@ -2,6 +2,17 @@
All notable changes to this project will be documented in this file.
# [@discordjs/rest@2.6.0](https://github.com/discordjs/discord.js/compare/@discordjs/rest@2.5.1...@discordjs/rest@2.6.0) - (2025-08-20)
## Documentation
- Remove hardcoded locale from links (#10794) ([5be774d](https://github.com/discordjs/discord.js/commit/5be774db641b60669505645861d721200d335a7b))
## Features
- Support user guilds (#10995) ([baa08b8](https://github.com/discordjs/discord.js/commit/baa08b8fbb64abd8265890413c95f81e2c61303f))
- Support animated WebP (#10987) ([cafe58b](https://github.com/discordjs/discord.js/commit/cafe58b3bd9defb5050a7a90bd07568f3b509c89))
# [@discordjs/rest@2.5.0](https://github.com/discordjs/discord.js/compare/@discordjs/rest@2.4.3...@discordjs/rest@2.5.0) - (2025-04-25)
## Features

View File

@@ -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`);
});
@@ -134,8 +142,11 @@ test('soundboardSound', () => {
expect(cdn.soundboardSound(id)).toEqual(`${baseCDN}/soundboard-sounds/${id}`);
});
test('guildTagBadge', () => {
expect(cdn.guildTagBadge(id, hash)).toEqual(`${baseCDN}/guild-tag-badges/${id}/${hash}.webp`);
});
test('makeURL throws on invalid size', () => {
// @ts-expect-error: Invalid size
expect(() => cdn.avatar(id, animatedHash, { size: 5 })).toThrow(RangeError);
});

View File

@@ -1,7 +1,7 @@
{
"$schema": "https://json.schemastore.org/package.json",
"name": "@discordjs/rest",
"version": "2.5.1",
"version": "2.6.0",
"description": "The REST API for discord.js",
"scripts": {
"test": "vitest run",
@@ -88,7 +88,7 @@
"@sapphire/async-queue": "^1.5.3",
"@sapphire/snowflake": "^3.5.3",
"@vladfrangu/async_event_emitter": "^2.4.6",
"discord-api-types": "^0.38.1",
"discord-api-types": "^0.38.16",
"magic-bytes.js": "^1.10.0",
"tslib": "^2.6.3",
"undici": "6.21.3"

View File

@@ -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<ImageExtension, 'webp'>;
}
/**
* 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<BaseImageURLOptions>): string;
public emoji(emojiId: string, options?: Readonly<EmojiURLOptions>): 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<BaseImageURLOptions>): string {
public emoji(emojiId: string, options?: ImageExtension | Readonly<EmojiURLOptions>): string {
let resolvedOptions;
if (typeof options === 'string') {
@@ -353,6 +374,17 @@ export class CDN {
return `${this.cdn}${CDNRoutes.soundboardSound(soundId)}`;
}
/**
* Generates a URL for a guild tag badge.
*
* @param guildId - The guild id
* @param badgeHash - The hash of the badge
* @param options - Optional options for the badge
*/
public guildTagBadge(guildId: string, badgeHash: string, options?: Readonly<BaseImageURLOptions>): string {
return this.makeURL(`/guild-tag-badges/${guildId}/${badgeHash}`, options);
}
/**
* Constructs the URL for the resource, checking whether or not `hash` starts with `a_` if `dynamic` is set to `true`.
*
@@ -381,6 +413,7 @@ export class CDN {
base = this.cdn,
extension = 'webp',
size,
animated,
}: Readonly<MakeURLOptions> = {},
): string {
// eslint-disable-next-line no-param-reassign
@@ -396,6 +429,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));
}

View File

@@ -336,9 +336,9 @@ export class REST extends AsyncEventEmitter<RestEvents> {
for (const [index, file] of request.files.entries()) {
const fileKey = file.key ?? `files[${index}]`;
// https://developer.mozilla.org/en-US/docs/Web/API/FormData/append#parameters
// https://developer.mozilla.org/docs/Web/API/FormData/append#parameters
// FormData.append only accepts a string or Blob.
// https://developer.mozilla.org/en-US/docs/Web/API/Blob/Blob#parameters
// https://developer.mozilla.org/docs/Web/API/Blob/Blob#parameters
// The Blob constructor accepts TypedArray/ArrayBuffer, strings, and Blobs.
if (isBufferLike(file.data)) {
// Try to infer the content type from the buffer if one isn't passed

View File

@@ -64,7 +64,7 @@
"funding": "https://github.com/discordjs/discord.js?sponsor",
"dependencies": {
"@types/ws": "^8.5.12",
"discord-api-types": "^0.37.119",
"discord-api-types": "^0.38.16",
"prism-media": "^1.3.5",
"tslib": "^2.6.3",
"ws": "^8.18.0"

View File

@@ -2,6 +2,37 @@
All notable changes to this project will be documented in this file.
# [@discordjs/ws@2.0.3](https://github.com/discordjs/discord.js/compare/@discordjs/ws@2.0.2...@discordjs/ws@2.0.3) - (2025-06-16)
## Bug Fixes
- Regression in allowedMentions when replying (#10866) ([2ebb5cb](https://github.com/discordjs/discord.js/commit/2ebb5cbd53d869a52cba4549e7acc417963741cd))
# [@discordjs/ws@2.0.0](https://github.com/discordjs/discord.js/compare/@discordjs/ws@1.1.1...@discordjs/ws@2.0.0) - (2024-09-02)
## Bug Fixes
- **WebSocketShard:** Buffer native zlib decompression payload (#10416) ([defb083](https://github.com/discordjs/discord.js/commit/defb083528ef31383778187a04ced8b00d886242)) by @didinele
- **WebSocketManager:** Heartbeat event had outdated types (#10417) ([5eabec1](https://github.com/discordjs/discord.js/commit/5eabec14d45ef7bdd7f610e84234eb63e726eacd)) by @didinele
- Retry for EAI_AGAIN I/O error (#10383) ([be04acd](https://github.com/discordjs/discord.js/commit/be04acd534d7d0c3fb7f6bd174e4a6482aae0d73)) by @didinele
- Consistent debug log spacing (#10349) ([38c699b](https://github.com/discordjs/discord.js/commit/38c699bc8a2ca40f37f70c93e08067e00f12ee81)) by @Jiralite
## Features
- **WebsocketManager:** Retroactive token setting (#10418) ([de94eaf](https://github.com/discordjs/discord.js/commit/de94eaf351a69fab57ec766bd9e90e8c05e8c3d1)) by @didinele
- **WebSocketShard:** Explicit time out network error handling (#10375) ([093ac92](https://github.com/discordjs/discord.js/commit/093ac924aef1bf328feadb49876bfbe26052fe1a)) by @didinele
## Refactor
- **WebSocketShard:** Error event handling (#10436) ([a6de270](https://github.com/discordjs/discord.js/commit/a6de2707fc1107262b12491f73b5b6887df91c67)) by @didinele
- **ws:** Event layout (#10376) ([bf6761a](https://github.com/discordjs/discord.js/commit/bf6761a44adec1fe5017f6bf5d8bc0734916961f)) by @didinele
- **BREAKING CHANGE:** All events now emit shard id as its own param
* fix: worker event forwarding
---------
- Native zlib support (#10316) ([94cc02a](https://github.com/discordjs/discord.js/commit/94cc02a2580496774d75673abc0caabc765d9ee0)) by @sdanialraza
# [@discordjs/ws@2.0.0](https://github.com/discordjs/discord.js/compare/@discordjs/ws@1.1.1...@discordjs/ws@2.0.0) - (2024-09-02)
## Bug Fixes

View File

@@ -1,7 +1,7 @@
{
"$schema": "https://json.schemastore.org/package.json",
"name": "@discordjs/ws",
"version": "2.0.2",
"version": "2.0.3",
"description": "Wrapper around Discord's gateway",
"scripts": {
"test": "vitest run",
@@ -79,7 +79,7 @@
"@sapphire/async-queue": "^1.5.3",
"@types/ws": "^8.5.12",
"@vladfrangu/async_event_emitter": "^2.4.6",
"discord-api-types": "^0.38.1",
"discord-api-types": "^0.38.16",
"tslib": "^2.6.3",
"ws": "^8.18.0"
},

62
pnpm-lock.yaml generated
View File

@@ -816,8 +816,8 @@ importers:
specifier: ^2.4.6
version: 2.4.6
discord-api-types:
specifier: ^0.38.1
version: 0.38.1
specifier: ^0.38.16
version: 0.38.16
devDependencies:
'@discordjs/api-extractor':
specifier: workspace:^
@@ -947,14 +947,14 @@ importers:
specifier: workspace:^
version: link:../util
'@discordjs/ws':
specifier: ^1.2.2
version: 1.2.2(bufferutil@4.0.8)(utf-8-validate@6.0.4)
specifier: ^1.2.3
version: 1.2.3(bufferutil@4.0.8)(utf-8-validate@6.0.4)
'@sapphire/snowflake':
specifier: 3.5.3
version: 3.5.3
discord-api-types:
specifier: ^0.38.1
version: 0.38.1
specifier: ^0.38.16
version: 0.38.16
fast-deep-equal:
specifier: 3.1.3
version: 3.1.3
@@ -1075,8 +1075,8 @@ importers:
packages/formatters:
dependencies:
discord-api-types:
specifier: ^0.37.119
version: 0.37.119
specifier: ^0.38.16
version: 0.38.16
devDependencies:
'@discordjs/api-extractor':
specifier: workspace:^
@@ -1148,8 +1148,8 @@ importers:
specifier: workspace:^
version: link:../ws
discord-api-types:
specifier: ^0.37.119
version: 0.37.119
specifier: ^0.38.16
version: 0.38.16
devDependencies:
'@discordjs/api-extractor':
specifier: workspace:^
@@ -1322,8 +1322,8 @@ importers:
specifier: ^2.4.6
version: 2.4.6
discord-api-types:
specifier: ^0.38.1
version: 0.38.1
specifier: ^0.38.16
version: 0.38.16
magic-bytes.js:
specifier: ^1.10.0
version: 1.10.0
@@ -1619,8 +1619,8 @@ importers:
specifier: ^8.5.12
version: 8.5.12
discord-api-types:
specifier: ^0.37.119
version: 0.37.119
specifier: ^0.38.16
version: 0.38.16
prism-media:
specifier: ^1.3.5
version: 1.3.5
@@ -1716,8 +1716,8 @@ importers:
specifier: ^2.4.6
version: 2.4.6
discord-api-types:
specifier: ^0.38.1
version: 0.38.1
specifier: ^0.38.16
version: 0.38.16
tslib:
specifier: ^2.6.3
version: 2.6.3
@@ -2805,16 +2805,16 @@ packages:
resolution: {integrity: sha512-5cnX+tASiPCqCWtFcFslxBVUaCetB0thvM/JyavhbXInP1HJIEU+Qv/zMrnuwSsX3yWH2lVXNJZeDK3EiP4HHg==}
engines: {node: '>=16.11.0'}
'@discordjs/rest@2.5.0':
resolution: {integrity: sha512-PWhchxTzpn9EV3vvPRpwS0EE2rNYB9pvzDU/eLLW3mByJl0ZHZjHI2/wA8EbH2gRMQV7nu+0FoDF84oiPl8VAQ==}
'@discordjs/rest@2.5.1':
resolution: {integrity: sha512-Tg9840IneBcbrAjcGaQzHUJWFNq1MMWZjTdjJ0WS/89IffaNKc++iOvffucPxQTF/gviO9+9r8kEPea1X5J2Dw==}
engines: {node: '>=18'}
'@discordjs/util@1.1.1':
resolution: {integrity: sha512-eddz6UnOBEB1oITPinyrB2Pttej49M9FZQY8NxgEvc3tq6ZICZ19m70RsmzRdDHk80O9NoYN/25AqJl8vPVf/g==}
engines: {node: '>=18'}
'@discordjs/ws@1.2.2':
resolution: {integrity: sha512-dyfq7yn0wO0IYeYOs3z79I6/HumhmKISzFL0Z+007zQJMtAFGtt3AEoq1nuLXtcunUE5YYYQqgKvybXukAK8/w==}
'@discordjs/ws@1.2.3':
resolution: {integrity: sha512-wPlQDxEmlDg5IxhJPuxXr3Vy9AjYq5xCvFWGJyD7w7Np8ZGu+Mc+97LCoEc/+AYCo2IDpKioiH0/c/mj5ZR9Uw==}
engines: {node: '>=16.11.0'}
'@edge-runtime/format@2.2.1':
@@ -8357,8 +8357,8 @@ packages:
discord-api-types@0.37.119:
resolution: {integrity: sha512-WasbGFXEB+VQWXlo6IpW3oUv73Yuau1Ig4AZF/m13tXcTKnMpc/mHjpztIlz4+BM9FG9BHQkEXiPto3bKduQUg==}
discord-api-types@0.38.1:
resolution: {integrity: sha512-vsjsqjAuxsPhiwbPjTBeGQaDPlizFmSkU0mTzFGMgRxqCDIRBR7iTY74HacpzrDV0QtERHRKQEk1tq7drZUtHg==}
discord-api-types@0.38.16:
resolution: {integrity: sha512-Cz42dC5WqJD17Yk0bRy7YLTJmh3NKo4FGpxZuA8MHqT0RPxKSrll5YhlODZ2z5DiEV/gpHMeTSrTFTWpSXjT1Q==}
dlv@1.1.3:
resolution: {integrity: sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==}
@@ -16323,7 +16323,7 @@ snapshots:
'@discordjs/formatters': 0.6.1
'@discordjs/util': 1.1.1
'@sapphire/shapeshift': 4.0.0
discord-api-types: 0.38.1
discord-api-types: 0.38.16
fast-deep-equal: 3.1.3
ts-mixer: 6.0.4
tslib: 2.8.1
@@ -16334,31 +16334,31 @@ snapshots:
'@discordjs/formatters@0.6.1':
dependencies:
discord-api-types: 0.38.1
discord-api-types: 0.38.16
'@discordjs/rest@2.5.0':
'@discordjs/rest@2.5.1':
dependencies:
'@discordjs/collection': 2.1.1
'@discordjs/util': 1.1.1
'@sapphire/async-queue': 1.5.3
'@sapphire/snowflake': 3.5.3
'@vladfrangu/async_event_emitter': 2.4.6
discord-api-types: 0.38.1
discord-api-types: 0.38.16
magic-bytes.js: 1.10.0
tslib: 2.8.1
undici: 6.21.1
undici: 6.21.3
'@discordjs/util@1.1.1': {}
'@discordjs/ws@1.2.2(bufferutil@4.0.8)(utf-8-validate@6.0.4)':
'@discordjs/ws@1.2.3(bufferutil@4.0.8)(utf-8-validate@6.0.4)':
dependencies:
'@discordjs/collection': 2.1.1
'@discordjs/rest': 2.5.0
'@discordjs/rest': 2.5.1
'@discordjs/util': 1.1.1
'@sapphire/async-queue': 1.5.3
'@types/ws': 8.5.12
'@vladfrangu/async_event_emitter': 2.4.6
discord-api-types: 0.38.1
discord-api-types: 0.38.16
tslib: 2.8.1
ws: 8.18.0(bufferutil@4.0.8)(utf-8-validate@6.0.4)
transitivePeerDependencies:
@@ -23711,7 +23711,7 @@ snapshots:
discord-api-types@0.37.119: {}
discord-api-types@0.38.1: {}
discord-api-types@0.38.16: {}
dlv@1.1.3: {}