diff --git a/apps/website/src/components/PropertyNode.tsx b/apps/website/src/components/PropertyNode.tsx
index 2bbc31cae0dd..231eacc541c0 100644
--- a/apps/website/src/components/PropertyNode.tsx
+++ b/apps/website/src/components/PropertyNode.tsx
@@ -51,7 +51,13 @@ export async function PropertyNode({
{property.displayName}
- {property.isOptional ? '?' : ''} :
+ {property.isOptional ? '?' : ''} :
{' '}
+ {property.summary?.defaultValueBlock.length
+ ? `= ${property.summary.defaultValueBlock.reduce(
+ (acc: string, def: { kind: string; text: string }) => `${acc}${def.text}`,
+ '',
+ )}`
+ : ''}
diff --git a/packages/api-extractor-model/src/mixins/ApiParameterListMixin.ts b/packages/api-extractor-model/src/mixins/ApiParameterListMixin.ts
index 5df2f2d4962b..cb4c895eab95 100644
--- a/packages/api-extractor-model/src/mixins/ApiParameterListMixin.ts
+++ b/packages/api-extractor-model/src/mixins/ApiParameterListMixin.ts
@@ -14,6 +14,7 @@ import type { IExcerptTokenRange } from './Excerpt.js';
* @public
*/
export interface IApiParameterOptions {
+ defaultValue: string | undefined;
isOptional: boolean;
isRest: boolean;
parameterName: string;
@@ -124,6 +125,7 @@ export function ApiParameterListMixin
(
isOptional: Boolean(parameterOptions.isOptional),
isRest: Boolean(parameterOptions.isRest),
parent: this,
+ defaultValue: parameterOptions.defaultValue,
});
this[_parameters].push(parameter);
@@ -171,6 +173,7 @@ export function ApiParameterListMixin(
parameterTypeTokenRange: parameter.parameterTypeExcerpt.tokenRange,
isOptional: parameter.isOptional,
isRest: parameter.isRest,
+ defaultValue: parameter.defaultValue,
});
}
diff --git a/packages/api-extractor-model/src/model/ApiPackage.ts b/packages/api-extractor-model/src/model/ApiPackage.ts
index fee2211a6770..89f8b4372ca1 100644
--- a/packages/api-extractor-model/src/model/ApiPackage.ts
+++ b/packages/api-extractor-model/src/model/ApiPackage.ts
@@ -41,6 +41,7 @@ const MinifyJSONMapping = {
constraintTokenRange: 'ctr',
dependencies: 'dp',
defaultTypeTokenRange: 'dtr',
+ defaultValue: 'dv',
docComment: 'd',
endIndex: 'en',
excerptTokens: 'ex',
diff --git a/packages/api-extractor-model/src/model/Deserializer.ts b/packages/api-extractor-model/src/model/Deserializer.ts
index fc60ed1c8920..454912626b39 100644
--- a/packages/api-extractor-model/src/model/Deserializer.ts
+++ b/packages/api-extractor-model/src/model/Deserializer.ts
@@ -262,6 +262,7 @@ function mapParam(
startIndex: 1 + index + paramTokens.slice(0, index).reduce((akk, num) => akk + num, 0),
endIndex: 1 + index + paramTokens.slice(0, index + 1).reduce((akk, num) => akk + num, 0),
},
+ defaultValue: param.default,
};
}
diff --git a/packages/api-extractor-model/src/model/Parameter.ts b/packages/api-extractor-model/src/model/Parameter.ts
index c0d47f0a6432..158ac5222986 100644
--- a/packages/api-extractor-model/src/model/Parameter.ts
+++ b/packages/api-extractor-model/src/model/Parameter.ts
@@ -12,6 +12,7 @@ import type { Excerpt } from '../mixins/Excerpt.js';
* @public
*/
export interface IParameterOptions {
+ defaultValue: string | undefined;
isOptional: boolean;
isRest: boolean;
name: string;
@@ -56,6 +57,11 @@ export class Parameter {
*/
public isRest: boolean;
+ /**
+ * The default value for this parameter if optional
+ */
+ public defaultValue: string | undefined;
+
private readonly _parent: ApiParameterListMixin;
public constructor(options: IParameterOptions) {
@@ -64,6 +70,7 @@ export class Parameter {
this.isOptional = options.isOptional;
this.isRest = options.isRest;
this._parent = options.parent;
+ this.defaultValue = options.defaultValue;
}
/**
diff --git a/packages/api-extractor/src/generators/ApiModelGenerator.ts b/packages/api-extractor/src/generators/ApiModelGenerator.ts
index c55268815004..19c46fa2b44c 100644
--- a/packages/api-extractor/src/generators/ApiModelGenerator.ts
+++ b/packages/api-extractor/src/generators/ApiModelGenerator.ts
@@ -843,6 +843,7 @@ export class ApiModelGenerator {
const parameters: IApiParameterOptions[] = this._captureParameters(
nodesToCapture,
functionDeclaration.parameters,
+ jsDoc?.params,
);
const excerptTokens: IExcerptToken[] = this._buildExcerptTokens(astDeclaration, nodesToCapture);
@@ -1043,6 +1044,7 @@ export class ApiModelGenerator {
const parameters: IApiParameterOptions[] = this._captureParameters(
nodesToCapture,
methodDeclaration.parameters,
+ jsDoc?.params,
);
const excerptTokens: IExcerptToken[] = this._buildExcerptTokens(astDeclaration, nodesToCapture);
@@ -1137,7 +1139,11 @@ export class ApiModelGenerator {
methodSignature.typeParameters,
);
- const parameters: IApiParameterOptions[] = this._captureParameters(nodesToCapture, methodSignature.parameters);
+ const parameters: IApiParameterOptions[] = this._captureParameters(
+ nodesToCapture,
+ methodSignature.parameters,
+ jsDoc?.params,
+ );
const excerptTokens: IExcerptToken[] = this._buildExcerptTokens(astDeclaration, nodesToCapture);
const apiItemMetadata: ApiItemMetadata = this._collector.fetchApiItemMetadata(astDeclaration);
@@ -1342,7 +1348,7 @@ export class ApiModelGenerator {
const apiItemMetadata: ApiItemMetadata = this._collector.fetchApiItemMetadata(astDeclaration);
const docComment: tsdoc.DocComment | undefined = jsDoc
? this._tsDocParser.parseString(
- `/**\n * ${this._fixLinkTags(jsDoc.description) ?? ''}${jsDoc.default ? ` (default: ${this._escapeSpecialChars(jsDoc.default)})` : ''}\n${
+ `/**\n * ${this._fixLinkTags(jsDoc.description) ?? ''}${jsDoc.default ? `\n * @defaultValue ${this._escapeSpecialChars(jsDoc.default)}` : ''}\n${
'see' in jsDoc ? jsDoc.see.map((see) => ` * @see ${see}\n`).join('') : ''
}${'readonly' in jsDoc && jsDoc.readonly ? ' * @readonly\n' : ''}${
'deprecated' in jsDoc && jsDoc.deprecated
@@ -1529,6 +1535,7 @@ export class ApiModelGenerator {
},
isOptional: Boolean(parameter.optional),
isRest: parameter.name.startsWith('...'),
+ defaultValue: parameter.default?.toString(),
});
excerptTokens.push(...newTokens);
excerptTokens.push({
@@ -1548,6 +1555,7 @@ export class ApiModelGenerator {
},
isOptional: Boolean(parameter.optional),
isRest: parameter.name.startsWith('...'),
+ defaultValue: parameter.default?.toString(),
});
excerptTokens.push(...newTokens);
excerptTokens.push({
@@ -1640,6 +1648,7 @@ export class ApiModelGenerator {
private _captureParameters(
nodesToCapture: IExcerptBuilderNodeToCapture[],
parameterNodes: ts.NodeArray,
+ jsDoc?: DocgenParamJson[] | undefined,
): IApiParameterOptions[] {
const parameters: IApiParameterOptions[] = [];
for (const parameter of parameterNodes) {
@@ -1650,6 +1659,9 @@ export class ApiModelGenerator {
parameterTypeTokenRange,
isOptional: this._collector.typeChecker.isOptionalParameter(parameter),
isRest: Boolean(parameter.dotDotDotToken),
+ defaultValue:
+ parameter.initializer?.getText() ??
+ jsDoc?.find((param) => param.name === parameter.name.getText().trim())?.default?.toString(),
});
}
@@ -1753,7 +1765,7 @@ export class ApiModelGenerator {
return input;
}
- return input.replaceAll(/(?[{}])/g, '\\$');
+ return input.replaceAll(/(?[@{}])/g, '\\$');
}
private _fixLinkTags(input?: string): string | undefined {
@@ -1848,7 +1860,7 @@ export class ApiModelGenerator {
isOptional: Boolean(prop.nullable),
isReadonly: Boolean(prop.readonly),
docComment: this._tsDocParser.parseString(
- `/**\n * ${this._fixLinkTags(prop.description) ?? ''}${prop.default ? ` (default: ${this._escapeSpecialChars(prop.default)})` : ''}\n${
+ `/**\n * ${this._fixLinkTags(prop.description) ?? ''}\n${prop.default ? ` * @defaultValue ${this._escapeSpecialChars(prop.default)}\n` : ''}${
prop.see?.map((see) => ` * @see ${see}\n`).join('') ?? ''
}${prop.readonly ? ' * @readonly\n' : ''} */`,
).docComment,
@@ -1860,7 +1872,7 @@ export class ApiModelGenerator {
}${prop.name} :`,
},
...mappedVarType,
- { kind: ExcerptTokenKind.Content, text: ';' },
+ { kind: ExcerptTokenKind.Content, text: `${prop.default ? ` = ${prop.default}` : ''};` },
],
propertyTypeTokenRange: { startIndex: 1, endIndex: 1 + mappedVarType.length },
releaseTag: prop.access === 'private' ? ReleaseTag.Internal : ReleaseTag.Public,
@@ -1883,6 +1895,7 @@ export class ApiModelGenerator {
startIndex: 1 + index + paramTokens.slice(0, index).reduce((akk, num) => akk + num, 0),
endIndex: 1 + index + paramTokens.slice(0, index + 1).reduce((akk, num) => akk + num, 0),
},
+ defaultValue: param.default?.toString(),
};
}
@@ -1907,7 +1920,7 @@ export class ApiModelGenerator {
excerptTokens.push(...newTokens);
excerptTokens.push({
kind: ExcerptTokenKind.Content,
- text: `, ${method.params![index + 1]!.name}${
+ text: `${method.params![index]!.default ? ` = ${method.params![index]!.default}` : ''}, ${method.params![index + 1]!.name}${
method.params![index + 1]!.nullable || method.params![index + 1]!.optional ? '?' : ''
}: `,
});
@@ -1917,7 +1930,10 @@ export class ApiModelGenerator {
const newTokens = this._mapVarType(method.params[method.params.length - 1]!.type);
paramTokens.push(newTokens.length);
excerptTokens.push(...newTokens);
- excerptTokens.push({ kind: ExcerptTokenKind.Content, text: `): ` });
+ excerptTokens.push({
+ kind: ExcerptTokenKind.Content,
+ text: `${method.params![method.params.length - 1]!.default ? ` = ${method.params![method.params.length - 1]!.default}` : ''}): `,
+ });
}
const returnTokens = this._mapVarType(method.returns?.[0] ?? []);
diff --git a/packages/discord.js/src/util/Options.js b/packages/discord.js/src/util/Options.js
index 14af76ea692c..aebc63af4d48 100644
--- a/packages/discord.js/src/util/Options.js
+++ b/packages/discord.js/src/util/Options.js
@@ -26,7 +26,7 @@ const { version } = require('../../package.json');
* @property {MessageMentionOptions} [allowedMentions] The default value for {@link BaseMessageOptions#allowedMentions}
* @property {Partials[]} [partials] Structures allowed to be partial. This means events can be emitted even when
* they're missing all the data for a particular structure. See the "Partial Structures" topic on the
- * [guide](https://discordjs.guide/popular-topics/partials.html) for some
+ * {@link https://discordjs.guide/popular-topics/partials.html guide} for some
* important usage information, as partials require you to put checks in place when handling data.
* @property {boolean} [failIfNotExists=true] The default value for {@link MessageReplyOptions#failIfNotExists}
* @property {PresenceData} [presence] Presence data to use upon login
@@ -37,7 +37,7 @@ const { version } = require('../../package.json');
* @property {WebSocketManagerOptions} [ws] Options for the WebSocketManager
* @property {RESTOptions} [rest] Options for the REST manager
* @property {Function} [jsonTransformer] A function used to transform outgoing json data
- * @property {boolean} [enforceNonce=false] The default value for {@link MessageReplyOptions#enforceNonce}
+ * @property {boolean} [enforceNonce=false] The default value for {@link MessageCreateOptions#enforceNonce}
*/
/**
diff --git a/packages/discord.js/typings/index.d.ts b/packages/discord.js/typings/index.d.ts
index ad512d8ed58b..8a603abefb17 100644
--- a/packages/discord.js/typings/index.d.ts
+++ b/packages/discord.js/typings/index.d.ts
@@ -5731,7 +5731,7 @@ export type GuildAuditLogsResolvable = AuditLogEvent | null;
export type GuildAuditLogsTargetType = GuildAuditLogsTypes[keyof GuildAuditLogsTypes][0] | 'All' | 'Unknown';
export type GuildAuditLogsTargets = {
- [key in GuildAuditLogsTargetType]: GuildAuditLogsTargetType;
+ [Key in GuildAuditLogsTargetType]: GuildAuditLogsTargetType;
};
export type GuildBanResolvable = GuildBan | UserResolvable;
diff --git a/packages/scripts/src/builtinDocumentationLinks.ts b/packages/scripts/src/builtinDocumentationLinks.ts
new file mode 100644
index 000000000000..1cafb2dbfc42
--- /dev/null
+++ b/packages/scripts/src/builtinDocumentationLinks.ts
@@ -0,0 +1,109 @@
+export const BuiltinDocumentationLinks = {
+ // Built-in types
+ bigint: 'https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/BigInt',
+ boolean: 'https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean',
+ null: 'https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/null',
+ number: 'https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number',
+ string: 'https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String',
+ symbol: 'https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Symbol',
+ undefined: 'https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/undefined',
+
+ // Built-in classes
+ AbortSignal: 'https://developer.mozilla.org/docs/Web/API/AbortSignal',
+ Agent: 'https://undici.nodejs.org/#/docs/api/Agent',
+ Array: 'https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array',
+ ArrayBuffer: 'https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/ArrayBuffer',
+ AsyncGenerator: 'https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/AsyncGenerator',
+ AsyncIterable: 'https://developer.mozilla.org/docs/Web/JavaScript/Reference/Iteration_protocols',
+ AsyncIterableIterator: 'https://developer.mozilla.org/docs/Web/JavaScript/Reference/Iteration_protocols',
+ Buffer: 'https://nodejs.org/api/buffer.html#class-buffer',
+ ChildProcess: 'https://nodejs.org/api/child_process.html#class-childprocess',
+ Date: 'https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Date',
+ Dispatcher: 'https://undici.nodejs.org/#/docs/api/Dispatcher',
+ Error: 'https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Error',
+ Function: 'https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Function',
+ Generator: 'https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Generator',
+ IncomingMessage: 'https://nodejs.org/api/http.html#class-httpincomingmessage',
+ Iterable: 'https://developer.mozilla.org/docs/Web/JavaScript/Reference/Iteration_protocols',
+ IterableIterator: 'https://developer.mozilla.org/docs/Web/JavaScript/Reference/Iteration_protocols',
+ Iterator: 'https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Iterator',
+ Map: 'https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Map',
+ MessagePort: 'https://nodejs.org/api/worker_threads.html#class-messageport',
+ Promise: 'https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Promise',
+ RangeError: 'https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/RangeError',
+ Readable: 'https://nodejs.org/api/stream.html#class-streamreadable',
+ ReadableStream: 'https://developer.mozilla.org/docs/Web/API/ReadableStream',
+ RegExp: 'https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/RegExp',
+ Response: 'https://developer.mozilla.org/docs/Web/API/Response',
+ ServerResponse: 'https://nodejs.org/api/http.html#class-httpserverresponse',
+ Set: 'https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Set',
+ Stream: 'https://nodejs.org/api/stream.html#stream',
+ SymbolConstructor: 'https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Symbol',
+ TypeError: 'https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/TypeError',
+ URL: 'https://developer.mozilla.org/docs/Web/API/URL',
+ URLSearchParams: 'https://developer.mozilla.org/docs/Web/API/URLSearchParams',
+ WeakMap: 'https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WeakMap',
+ WeakRef: 'https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WeakRef',
+ WeakSet: 'https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/WeakSet',
+ WebSocket: 'https://developer.mozilla.org/docs/Web/API/WebSocket',
+ Worker: 'https://nodejs.org/api/worker_threads.html#class-worker',
+ 'NodeJS.Timeout': 'https://nodejs.org/api/timers.html#class-timeout',
+
+ // Typed arrays
+ BigInt64Array: 'https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/BigInt64Array',
+ BigUint64Array: 'https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/BigUint64Array',
+ Float32Array: 'https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Float32Array',
+ Float64Array: 'https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Float64Array',
+ Int16Array: 'https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Int16Array',
+ Int32Array: 'https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Int32Array',
+ Int8Array: 'https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Int8Array',
+ Uint16Array: 'https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Uint16Array',
+ Uint32Array: 'https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Uint32Array',
+ Uint8Array: 'https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Uint8Array',
+ Uint8ClampedArray: 'https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Uint8ClampedArray',
+
+ // TypeScript types
+ any: 'https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#any',
+ keyof: 'https://www.typescriptlang.org/docs/handbook/2/keyof-types.html',
+ never: 'https://www.typescriptlang.org/docs/handbook/2/functions.html#never',
+ object: 'https://www.typescriptlang.org/docs/handbook/2/functions.html#object',
+ ReadonlyArray: 'https://www.typescriptlang.org/docs/handbook/2/objects.html#the-readonlyarray-type',
+ ReadonlyMap:
+ 'https://github.com/microsoft/TypeScript/blob/1416053b9e85ca2344a7a6aa10456d633ea1cd65/src/lib/es2015.collection.d.ts#L38-L43',
+ ReadonlySet:
+ 'https://github.com/microsoft/TypeScript/blob/1416053b9e85ca2344a7a6aa10456d633ea1cd65/src/lib/es2015.collection.d.ts#L104-L108',
+ unknown: 'https://www.typescriptlang.org/docs/handbook/2/functions.html#unknown',
+ this: 'https://www.typescriptlang.org/docs/handbook/2/classes.html#this-types',
+ typeof: 'https://www.typescriptlang.org/docs/handbook/2/typeof-types.html',
+ void: 'https://www.typescriptlang.org/docs/handbook/2/functions.html#void',
+
+ // TypeScript utility types
+ Awaited: 'https://www.typescriptlang.org/docs/handbook/utility-types.html#awaitedtype',
+ Partial: 'https://www.typescriptlang.org/docs/handbook/utility-types.html#partialtype',
+ Required: 'https://www.typescriptlang.org/docs/handbook/utility-types.html#requiredtype',
+ Readonly: 'https://www.typescriptlang.org/docs/handbook/utility-types.html#readonlytype',
+ Record: 'https://www.typescriptlang.org/docs/handbook/utility-types.html#recordkeys-type',
+ Pick: 'https://www.typescriptlang.org/docs/handbook/utility-types.html#picktype-keys',
+ Omit: 'https://www.typescriptlang.org/docs/handbook/utility-types.html#omittype-keys',
+ Exclude: 'https://www.typescriptlang.org/docs/handbook/utility-types.html#excludeuniontype-excludedmembers',
+ Extract: 'https://www.typescriptlang.org/docs/handbook/utility-types.html#extracttype-union',
+ NonNullable: 'https://www.typescriptlang.org/docs/handbook/utility-types.html#nonnullabletype',
+ Parameters: 'https://www.typescriptlang.org/docs/handbook/utility-types.html#parameterstype',
+ ConstructorParameters: 'https://www.typescriptlang.org/docs/handbook/utility-types.html#constructorparameterstype',
+ ReturnType: 'https://www.typescriptlang.org/docs/handbook/utility-types.html#returntypetype',
+ InstanceType: 'https://www.typescriptlang.org/docs/handbook/utility-types.html#instancetypetype',
+ ThisParameterType: 'https://www.typescriptlang.org/docs/handbook/utility-types.html#thisparametertypetype',
+ OmitThisParameter: 'https://www.typescriptlang.org/docs/handbook/utility-types.html#omitthisparametertype',
+ ThisType: 'https://www.typescriptlang.org/docs/handbook/utility-types.html#thistypetype',
+ Uppercase: 'https://www.typescriptlang.org/docs/handbook/utility-types.html#uppercasestringtype',
+ Lowercase: 'https://www.typescriptlang.org/docs/handbook/utility-types.html#lowercasestringtype',
+ Capitalize: 'https://www.typescriptlang.org/docs/handbook/utility-types.html#capitalizestringtype',
+ Uncapitalize: 'https://www.typescriptlang.org/docs/handbook/utility-types.html#uncapitalizestringtype',
+
+ // External Libraries
+ AsyncEventEmitter: 'https://github.com/vladfrangu/async_event_emitter',
+ AsyncQueue: 'https://www.sapphirejs.dev/docs/Documentation/api-utilities/classes/sapphire_async_queue.AsyncQueue',
+ Redis: 'https://redis.github.io/ioredis/classes/Redis.html',
+ 'prism.opus.Encoder': 'https://amishshah.github.io/prism-media/opus.Encoder.html',
+ 'prism.VolumeTransformer': 'https://amishshah.github.io/prism-media/core.VolumeTransformer.html',
+} as const;
diff --git a/packages/scripts/src/generateSplitDocumentation.ts b/packages/scripts/src/generateSplitDocumentation.ts
index 6c523a34ef47..ee83a2b6f2b3 100644
--- a/packages/scripts/src/generateSplitDocumentation.ts
+++ b/packages/scripts/src/generateSplitDocumentation.ts
@@ -18,10 +18,10 @@ import type {
ApiProperty,
ApiPropertySignature,
ApiTypeAlias,
- ApiTypeParameterListMixin,
ApiVariable,
} from '@discordjs/api-extractor-model';
import {
+ ApiTypeParameterListMixin,
Excerpt,
Meaning,
ApiAbstractMixin,
@@ -49,6 +49,7 @@ import type {
DocComment,
} from '@microsoft/tsdoc';
import type { DeclarationReference } from '@microsoft/tsdoc/lib-commonjs/beta/DeclarationReference.js';
+import { BuiltinDocumentationLinks } from './builtinDocumentationLinks.js';
import { PACKAGES, fetchVersionDocs, fetchVersions } from './shared.js';
function resolvePackageName(packageName: string) {
@@ -225,7 +226,7 @@ function resolveItemURI(item: ApiItemLike): string {
: `${item.parent.displayName}:${item.parent.kind}#${item.displayName}`;
}
-function itemExcerptText(excerpt: Excerpt, apiPackage: ApiPackage) {
+function itemExcerptText(excerpt: Excerpt, apiPackage: ApiPackage, parent?: ApiTypeParameterListMixin) {
const DISCORD_API_TYPES_VERSION = 'v10';
const DISCORD_API_TYPES_DOCS_URL = `https://discord-api-types.dev/api/discord-api-types-${DISCORD_API_TYPES_VERSION}`;
@@ -286,6 +287,27 @@ function itemExcerptText(excerpt: Excerpt, apiPackage: ApiPackage) {
};
}
+ if (token.text in BuiltinDocumentationLinks) {
+ return {
+ text: token.text,
+ href: BuiltinDocumentationLinks[token.text as keyof typeof BuiltinDocumentationLinks],
+ };
+ }
+
+ if (parent?.typeParameters.some((type) => type.name === token.text)) {
+ const [packageName, parentItem] = parent.canonicalReference.toString().split('!');
+ return {
+ text: token.text,
+ resolvedItem: {
+ kind: 'TypeParameter',
+ displayName: token.text,
+ containerKey: `${parent.containerKey}|${token.text}`,
+ uri: `${parentItem}#${token.text}`,
+ packageName: packageName?.replace('@discordjs/', ''),
+ },
+ };
+ }
+
return {
text: token.text,
};
@@ -346,9 +368,19 @@ function itemTsDoc(item: DocNode, apiItem: ApiItem) {
const resolved = resolveCanonicalReference(codeDestination, apiItem.getAssociatedPackage());
if (!foundItem && !resolved) {
+ const itemName = codeDestination.memberReferences[0]?.memberIdentifier?.identifier;
+
+ if (itemName && itemName in BuiltinDocumentationLinks) {
+ return {
+ kind: DocNodeKind.LinkTag,
+ text: itemName,
+ uri: BuiltinDocumentationLinks[itemName as keyof typeof BuiltinDocumentationLinks],
+ };
+ }
+
return {
kind: DocNodeKind.LinkTag,
- text: codeDestination.memberReferences[0]?.memberIdentifier?.identifier ?? null,
+ text: itemName ?? null,
};
}
@@ -534,6 +566,7 @@ function resolveParameters(item: ApiDocumentedItem & ApiParameterListMixin) {
isOptional: param.isOptional,
isRest: param.isRest,
parameterTypeExcerpt: param.parameterTypeExcerpt,
+ defaultValue: param.defaultValue,
};
});
}
@@ -553,9 +586,9 @@ function itemTypeParameters(item: ApiTypeParameterListMixin) {
return item.typeParameters.map((typeParam) => ({
name: typeParam.name,
- constraintsExcerpt: itemExcerptText(typeParam.constraintExcerpt, item.getAssociatedPackage()!),
+ constraintsExcerpt: itemExcerptText(typeParam.constraintExcerpt, item.getAssociatedPackage()!, item),
isOptional: typeParam.isOptional,
- defaultExcerpt: itemExcerptText(typeParam.defaultTypeExcerpt, item.getAssociatedPackage()!),
+ defaultExcerpt: itemExcerptText(typeParam.defaultTypeExcerpt, item.getAssociatedPackage()!, item),
description: typeParam.tsdocTypeParamBlock ? itemTsDoc(typeParam.tsdocTypeParamBlock.content, item) : null,
}));
}
@@ -572,9 +605,14 @@ function itemParameters(item: ApiDocumentedItem & ApiParameterListMixin) {
return params.map((param) => ({
name: param.isRest ? `...${param.name}` : param.name,
- typeExcerpt: itemExcerptText(param.parameterTypeExcerpt, item.getAssociatedPackage()!),
+ typeExcerpt: itemExcerptText(
+ param.parameterTypeExcerpt,
+ item.getAssociatedPackage()!,
+ item.getHierarchy().find(ApiTypeParameterListMixin.isBaseClassOf),
+ ),
isOptional: param.isOptional,
description: param.description ? itemTsDoc(param.description, item) : null,
+ defaultValue: param.defaultValue,
}));
}
@@ -622,7 +660,11 @@ function itemProperty(item: ApiItemContainerMixin) {
return {
...itemInfo(property.item),
inheritedFrom: property.inherited ? resolveItemURI(property.inherited) : null,
- typeExcerpt: itemExcerptText(property.item.propertyTypeExcerpt, property.item.getAssociatedPackage()!),
+ typeExcerpt: itemExcerptText(
+ property.item.propertyTypeExcerpt,
+ property.item.getAssociatedPackage()!,
+ property.item.getHierarchy().find(ApiTypeParameterListMixin.isBaseClassOf),
+ ),
summary: hasSummary ? itemTsDoc(property.item.tsdocComment!, property.item) : null,
};
});
@@ -658,7 +700,11 @@ function itemMethod(item: ApiItemContainerMixin) {
...itemInfo(method.item),
overloadIndex: method.item.overloadIndex,
parametersString: parametersString(method.item),
- returnTypeExcerpt: itemExcerptText(method.item.returnTypeExcerpt, method.item.getAssociatedPackage()!),
+ returnTypeExcerpt: itemExcerptText(
+ method.item.returnTypeExcerpt,
+ method.item.getAssociatedPackage()!,
+ method.item.getHierarchy().find(ApiTypeParameterListMixin.isBaseClassOf),
+ ),
inheritedFrom: method.inherited ? resolveItemURI(method.inherited) : null,
typeParameters: itemTypeParameters(method.item),
parameters: itemParameters(method.item),
@@ -754,7 +800,11 @@ export function itemHierarchyText({
return excerpts.map((excerpt) => {
return {
type,
- excerpts: itemExcerptText(excerpt, item.getAssociatedPackage()!),
+ excerpts: itemExcerptText(
+ excerpt,
+ item.getAssociatedPackage()!,
+ item.getHierarchy().find(ApiTypeParameterListMixin.isBaseClassOf),
+ ),
};
});
}
@@ -848,7 +898,11 @@ function itemTypeAlias(item: ApiTypeAlias) {
...itemInfo(item),
typeParameters: itemTypeParameters(item),
unionMembers: itemUnion(item).map((member) =>
- itemExcerptText(new Excerpt(member, { startIndex: 0, endIndex: member.length }), item.getAssociatedPackage()!),
+ itemExcerptText(
+ new Excerpt(member, { startIndex: 0, endIndex: member.length }),
+ item.getAssociatedPackage()!,
+ item.getHierarchy().find(ApiTypeParameterListMixin.isBaseClassOf),
+ ),
),
};
}
From 6cbe2487bc91b61e0a65df879a8065ab48f7843b Mon Sep 17 00:00:00 2001
From: Qjuh <76154676+Qjuh@users.noreply.github.com>
Date: Sat, 19 Oct 2024 21:34:51 +0200
Subject: [PATCH 03/22] fix: missing tsdocConfig in api.json preventing index
generation (#10565)
---
packages/api-extractor-model/src/model/ApiPackage.ts | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/packages/api-extractor-model/src/model/ApiPackage.ts b/packages/api-extractor-model/src/model/ApiPackage.ts
index 89f8b4372ca1..e55b843b9b5f 100644
--- a/packages/api-extractor-model/src/model/ApiPackage.ts
+++ b/packages/api-extractor-model/src/model/ApiPackage.ts
@@ -294,7 +294,11 @@ export class ApiPackage extends ApiItemContainerMixin(ApiNameMixin(ApiDocumented
const tsdocConfiguration: TSDocConfiguration = new TSDocConfiguration();
- if (versionToDeserialize >= ApiJsonSchemaVersion.V_1004 && 'tsdocConfig' in jsonObject.metadata) {
+ if (
+ versionToDeserialize >= ApiJsonSchemaVersion.V_1004 &&
+ 'tsdocConfig' in jsonObject.metadata &&
+ '$schema' in jsonObject.metadata.tsdocConfig
+ ) {
const tsdocConfigFile: TSDocConfigFile = TSDocConfigFile.loadFromObject(jsonObject.metadata.tsdocConfig);
if (tsdocConfigFile.hasErrors) {
throw new Error(`Error loading ${apiJsonFilename}:\n` + tsdocConfigFile.getErrorSummary());
From 48a9c665dedf9f5085a7992df3a87de3bca2301a Mon Sep 17 00:00:00 2001
From: Jiralite <33201955+Jiralite@users.noreply.github.com>
Date: Tue, 22 Oct 2024 07:10:30 +0100
Subject: [PATCH 04/22] refactor(InteractionResponses)!: Remove `ephemeral`
response option (#10564)
BREAKING CHANGE: MessagePayload#isInteraction no longer serves a purpose and has been removed.
BREAKING CHANGE: InteractionDeferReplyOptions no longer accepts ephemeral. Use flags instead.
BREAKING CHANGE: InteractionReplyOptions no longer accepts ephemeral. Use flags instead.
---
.../src/structures/MessagePayload.js | 21 +----------------
.../interfaces/InteractionResponses.js | 23 +++++++++----------
.../src/util/MessageFlagsBitField.js | 9 ++++++++
packages/discord.js/typings/index.d.ts | 11 +++++----
4 files changed, 28 insertions(+), 36 deletions(-)
diff --git a/packages/discord.js/src/structures/MessagePayload.js b/packages/discord.js/src/structures/MessagePayload.js
index dad8ffedb026..7dc567924ba3 100644
--- a/packages/discord.js/src/structures/MessagePayload.js
+++ b/packages/discord.js/src/structures/MessagePayload.js
@@ -1,17 +1,14 @@
'use strict';
const { Buffer } = require('node:buffer');
-const { lazy, isJSONEncodable } = require('@discordjs/util');
+const { isJSONEncodable } = require('@discordjs/util');
const { DiscordSnowflake } = require('@sapphire/snowflake');
-const { MessageFlags } = require('discord-api-types/v10');
const ActionRowBuilder = require('./ActionRowBuilder');
const { DiscordjsError, DiscordjsRangeError, ErrorCodes } = require('../errors');
const { resolveFile } = require('../util/DataResolver');
const MessageFlagsBitField = require('../util/MessageFlagsBitField');
const { basename, verifyString, resolvePartialEmoji } = require('../util/Util');
-const getBaseInteraction = lazy(() => require('./BaseInteraction'));
-
/**
* Represents a message to be sent to the API.
*/
@@ -88,17 +85,6 @@ class MessagePayload {
return this.target instanceof MessageManager;
}
- /**
- * Whether or not the target is an {@link BaseInteraction} or an {@link InteractionWebhook}
- * @type {boolean}
- * @readonly
- */
- get isInteraction() {
- const BaseInteraction = getBaseInteraction();
- const InteractionWebhook = require('./InteractionWebhook');
- return this.target instanceof BaseInteraction || this.target instanceof InteractionWebhook;
- }
-
/**
* Makes the content of this message.
* @returns {?string}
@@ -120,7 +106,6 @@ class MessagePayload {
*/
resolveBody() {
if (this.body) return this;
- const isInteraction = this.isInteraction;
const isWebhook = this.isWebhook;
const content = this.makeContent();
@@ -175,10 +160,6 @@ class MessagePayload {
: this.target.flags?.bitfield;
}
- if (isInteraction && this.options.ephemeral) {
- flags |= MessageFlags.Ephemeral;
- }
-
let allowedMentions =
this.options.allowedMentions === undefined
? this.target.client.options.allowedMentions
diff --git a/packages/discord.js/src/structures/interfaces/InteractionResponses.js b/packages/discord.js/src/structures/interfaces/InteractionResponses.js
index 5c8900530f61..7b1cfb1429f0 100644
--- a/packages/discord.js/src/structures/interfaces/InteractionResponses.js
+++ b/packages/discord.js/src/structures/interfaces/InteractionResponses.js
@@ -3,7 +3,6 @@
const { isJSONEncodable } = require('@discordjs/util');
const { InteractionResponseType, MessageFlags, Routes, InteractionType } = require('discord-api-types/v10');
const { DiscordjsError, ErrorCodes } = require('../../errors');
-const MessageFlagsBitField = require('../../util/MessageFlagsBitField');
const InteractionCollector = require('../InteractionCollector');
const InteractionResponse = require('../InteractionResponse');
const MessagePayload = require('../MessagePayload');
@@ -23,7 +22,8 @@ class InteractionResponses {
/**
* Options for deferring the reply to an {@link BaseInteraction}.
* @typedef {Object} InteractionDeferReplyOptions
- * @property {boolean} [ephemeral] Whether the reply should be ephemeral
+ * @property {MessageFlagsResolvable} [flags] Flags for the reply.
+ * Only `MessageFlags.Ephemeral` can be set.
* @property {boolean} [fetchReply] Whether to fetch the reply
*/
@@ -37,9 +37,8 @@ class InteractionResponses {
* Options for a reply to a {@link BaseInteraction}.
* @typedef {BaseMessageOptionsWithPoll} InteractionReplyOptions
* @property {boolean} [tts=false] Whether the message should be spoken aloud
- * @property {boolean} [ephemeral] Whether the reply should be ephemeral
* @property {boolean} [fetchReply] Whether to fetch the reply
- * @property {MessageFlags} [flags] Which flags to set for the message.
+ * @property {MessageFlagsResolvable} [flags] Which flags to set for the message.
* Only `MessageFlags.Ephemeral`, `MessageFlags.SuppressEmbeds`, and `MessageFlags.SuppressNotifications`
* can be set.
*/
@@ -61,24 +60,25 @@ class InteractionResponses {
* .catch(console.error)
* @example
* // Defer to send an ephemeral reply later
- * interaction.deferReply({ ephemeral: true })
+ * interaction.deferReply({ flags: MessageFlags.Ephemeral })
* .then(console.log)
* .catch(console.error);
*/
async deferReply(options = {}) {
if (this.deferred || this.replied) throw new DiscordjsError(ErrorCodes.InteractionAlreadyReplied);
- this.ephemeral = options.ephemeral ?? false;
+
await this.client.rest.post(Routes.interactionCallback(this.id, this.token), {
body: {
type: InteractionResponseType.DeferredChannelMessageWithSource,
data: {
- flags: options.ephemeral ? MessageFlags.Ephemeral : undefined,
+ flags: options.flags,
},
},
auth: false,
});
- this.deferred = true;
+ this.deferred = true;
+ this.ephemeral = Boolean(options.flags & MessageFlags.Ephemeral);
return options.fetchReply ? this.fetchReply() : new InteractionResponse(this);
}
@@ -96,7 +96,7 @@ class InteractionResponses {
* // Create an ephemeral reply with an embed
* const embed = new EmbedBuilder().setDescription('Pong!');
*
- * interaction.reply({ embeds: [embed], ephemeral: true })
+ * interaction.reply({ embeds: [embed], flags: MessageFlags.Ephemeral })
* .then(() => console.log('Reply sent.'))
* .catch(console.error);
*/
@@ -109,8 +109,6 @@ class InteractionResponses {
const { body: data, files } = await messagePayload.resolveBody().resolveFiles();
- this.ephemeral = new MessageFlagsBitField(data.flags).has(MessageFlags.Ephemeral);
-
await this.client.rest.post(Routes.interactionCallback(this.id, this.token), {
body: {
type: InteractionResponseType.ChannelMessageWithSource,
@@ -119,8 +117,9 @@ class InteractionResponses {
files,
auth: false,
});
- this.replied = true;
+ this.ephemeral = Boolean(options.flags & MessageFlags.Ephemeral);
+ this.replied = true;
return options.fetchReply ? this.fetchReply() : new InteractionResponse(this);
}
diff --git a/packages/discord.js/src/util/MessageFlagsBitField.js b/packages/discord.js/src/util/MessageFlagsBitField.js
index 71f1fd6c5c08..e6764b2fd791 100644
--- a/packages/discord.js/src/util/MessageFlagsBitField.js
+++ b/packages/discord.js/src/util/MessageFlagsBitField.js
@@ -23,6 +23,15 @@ class MessageFlagsBitField extends BitField {
* @param {BitFieldResolvable} [bits=0] Bit(s) to read from
*/
+/**
+ * Data that can be resolved to give a message flags bit field. This can be:
+ * * A string (see {@link MessageFlagsBitField.Flags})
+ * * A message flag
+ * * An instance of {@link MessageFlagsBitField}
+ * * An array of `MessageFlagsResolvable`
+ * @typedef {string|number|MessageFlagsBitField|MessageFlagsResolvable[]} MessageFlagsResolvable
+ */
+
/**
* Bitfield of the packed bits
* @type {number}
diff --git a/packages/discord.js/typings/index.d.ts b/packages/discord.js/typings/index.d.ts
index 8a603abefb17..edc0c29965a9 100644
--- a/packages/discord.js/typings/index.d.ts
+++ b/packages/discord.js/typings/index.d.ts
@@ -2398,7 +2398,6 @@ export class MessagePayload {
public get isWebhook(): boolean;
public get isMessage(): boolean;
public get isMessageManager(): boolean;
- public get isInteraction(): boolean;
public files: RawFile[] | null;
public options: MessagePayloadOption;
public target: MessageTarget;
@@ -6066,15 +6065,19 @@ export interface InteractionCollectorOptions<
}
export interface InteractionDeferReplyOptions {
- ephemeral?: boolean;
+ flags?: BitFieldResolvable<
+ Extract,
+ MessageFlags.Ephemeral | MessageFlags.SuppressEmbeds | MessageFlags.SuppressNotifications
+ >;
fetchReply?: boolean;
}
-export interface InteractionDeferUpdateOptions extends Omit {}
+export interface InteractionDeferUpdateOptions {
+ fetchReply?: boolean;
+}
export interface InteractionReplyOptions extends BaseMessageOptionsWithPoll {
tts?: boolean;
- ephemeral?: boolean;
fetchReply?: boolean;
flags?: BitFieldResolvable<
Extract,
From b932b64d94f23a03ee65ed54ff0f2666ced7a773 Mon Sep 17 00:00:00 2001
From: Jiralite <33201955+Jiralite@users.noreply.github.com>
Date: Fri, 25 Oct 2024 10:39:47 +0100
Subject: [PATCH 05/22] refactor: remove extra traversing (#10580)
* refactor: remove extra traversion
* refactor(GuildScheduledEventManager): address fetch
---
packages/discord.js/src/managers/GuildChannelManager.js | 2 +-
packages/discord.js/src/managers/GuildMemberManager.js | 4 ++--
.../discord.js/src/managers/GuildScheduledEventManager.js | 5 +----
3 files changed, 4 insertions(+), 7 deletions(-)
diff --git a/packages/discord.js/src/managers/GuildChannelManager.js b/packages/discord.js/src/managers/GuildChannelManager.js
index b981801b601f..4e3753b7198f 100644
--- a/packages/discord.js/src/managers/GuildChannelManager.js
+++ b/packages/discord.js/src/managers/GuildChannelManager.js
@@ -299,7 +299,7 @@ class GuildChannelManager extends CachedManager {
if (options.lockPermissions) {
if (parent) {
- const newParent = this.guild.channels.resolve(parent);
+ const newParent = this.resolve(parent);
if (newParent?.type === ChannelType.GuildCategory) {
permission_overwrites = newParent.permissionOverwrites.cache.map(overwrite =>
PermissionOverwrites.resolve(overwrite, this.guild),
diff --git a/packages/discord.js/src/managers/GuildMemberManager.js b/packages/discord.js/src/managers/GuildMemberManager.js
index fb471328447f..d65cb1c5dd0c 100644
--- a/packages/discord.js/src/managers/GuildMemberManager.js
+++ b/packages/discord.js/src/managers/GuildMemberManager.js
@@ -535,7 +535,7 @@ class GuildMemberManager extends CachedManager {
*/
async addRole(options) {
const { user, role, reason } = options;
- const userId = this.guild.members.resolveId(user);
+ const userId = this.resolveId(user);
const roleId = this.guild.roles.resolveId(role);
await this.client.rest.put(Routes.guildMemberRole(this.guild.id, userId, roleId), { reason });
@@ -549,7 +549,7 @@ class GuildMemberManager extends CachedManager {
*/
async removeRole(options) {
const { user, role, reason } = options;
- const userId = this.guild.members.resolveId(user);
+ const userId = this.resolveId(user);
const roleId = this.guild.roles.resolveId(role);
await this.client.rest.delete(Routes.guildMemberRole(this.guild.id, userId, roleId), { reason });
diff --git a/packages/discord.js/src/managers/GuildScheduledEventManager.js b/packages/discord.js/src/managers/GuildScheduledEventManager.js
index 383875d70002..02e14c06259b 100644
--- a/packages/discord.js/src/managers/GuildScheduledEventManager.js
+++ b/packages/discord.js/src/managers/GuildScheduledEventManager.js
@@ -173,10 +173,7 @@ class GuildScheduledEventManager extends CachedManager {
return data.reduce(
(coll, rawGuildScheduledEventData) =>
- coll.set(
- rawGuildScheduledEventData.id,
- this.guild.scheduledEvents._add(rawGuildScheduledEventData, options.cache),
- ),
+ coll.set(rawGuildScheduledEventData.id, this._add(rawGuildScheduledEventData, options.cache)),
new Collection(),
);
}
From ed78e45706ba7a6bfa9f868580ab21eb1c23f58c Mon Sep 17 00:00:00 2001
From: Pablo <79182286+Yareaj@users.noreply.github.com>
Date: Sun, 27 Oct 2024 01:15:28 -0500
Subject: [PATCH 06/22] build: bump discord-api-types version (#10575)
* chore: bump discord-api-types version
* fix: delete extra file
---
packages/builders/package.json | 2 +-
packages/core/package.json | 2 +-
packages/discord.js/package.json | 2 +-
packages/formatters/package.json | 2 +-
packages/next/package.json | 2 +-
packages/rest/package.json | 2 +-
packages/voice/package.json | 2 +-
packages/ws/package.json | 2 +-
pnpm-lock.yaml | 242 +++++++++++++++++++------------
9 files changed, 158 insertions(+), 100 deletions(-)
diff --git a/packages/builders/package.json b/packages/builders/package.json
index f678a01e0ab7..0f0548de4eb8 100644
--- a/packages/builders/package.json
+++ b/packages/builders/package.json
@@ -66,7 +66,7 @@
"funding": "https://github.com/discordjs/discord.js?sponsor",
"dependencies": {
"@discordjs/util": "workspace:^",
- "discord-api-types": "^0.37.101",
+ "discord-api-types": "^0.37.103",
"ts-mixer": "^6.0.4",
"tslib": "^2.6.3",
"zod": "^3.23.8",
diff --git a/packages/core/package.json b/packages/core/package.json
index b4e74637898e..e6d7e5eabc88 100644
--- a/packages/core/package.json
+++ b/packages/core/package.json
@@ -70,7 +70,7 @@
"@discordjs/ws": "workspace:^",
"@sapphire/snowflake": "^3.5.3",
"@vladfrangu/async_event_emitter": "^2.4.6",
- "discord-api-types": "^0.37.101"
+ "discord-api-types": "^0.37.103"
},
"devDependencies": {
"@discordjs/api-extractor": "workspace:^",
diff --git a/packages/discord.js/package.json b/packages/discord.js/package.json
index e64d85856d0b..6a3e69fcbccf 100644
--- a/packages/discord.js/package.json
+++ b/packages/discord.js/package.json
@@ -72,7 +72,7 @@
"@discordjs/util": "workspace:^",
"@discordjs/ws": "workspace:^",
"@sapphire/snowflake": "3.5.3",
- "discord-api-types": "^0.37.101",
+ "discord-api-types": "^0.37.103",
"fast-deep-equal": "3.1.3",
"lodash.snakecase": "4.1.1",
"tslib": "^2.6.3",
diff --git a/packages/formatters/package.json b/packages/formatters/package.json
index 5e5f348e5db6..b895f26e618e 100644
--- a/packages/formatters/package.json
+++ b/packages/formatters/package.json
@@ -55,7 +55,7 @@
"homepage": "https://discord.js.org",
"funding": "https://github.com/discordjs/discord.js?sponsor",
"dependencies": {
- "discord-api-types": "^0.37.101"
+ "discord-api-types": "^0.37.103"
},
"devDependencies": {
"@discordjs/api-extractor": "workspace:^",
diff --git a/packages/next/package.json b/packages/next/package.json
index 2ac8450050f9..a8a01bc6ce78 100644
--- a/packages/next/package.json
+++ b/packages/next/package.json
@@ -72,7 +72,7 @@
"@discordjs/rest": "workspace:^",
"@discordjs/util": "workspace:^",
"@discordjs/ws": "workspace:^",
- "discord-api-types": "^0.37.101"
+ "discord-api-types": "^0.37.103"
},
"devDependencies": {
"@discordjs/api-extractor": "workspace:^",
diff --git a/packages/rest/package.json b/packages/rest/package.json
index 4288337d3280..425a3afcb246 100644
--- a/packages/rest/package.json
+++ b/packages/rest/package.json
@@ -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.37.101",
+ "discord-api-types": "^0.37.103",
"magic-bytes.js": "^1.10.0",
"tslib": "^2.6.3",
"undici": "6.19.8"
diff --git a/packages/voice/package.json b/packages/voice/package.json
index f33cee6492be..3a8c22360e26 100644
--- a/packages/voice/package.json
+++ b/packages/voice/package.json
@@ -64,7 +64,7 @@
"funding": "https://github.com/discordjs/discord.js?sponsor",
"dependencies": {
"@types/ws": "^8.5.12",
- "discord-api-types": "^0.37.101",
+ "discord-api-types": "^0.37.103",
"prism-media": "^1.3.5",
"tslib": "^2.6.3",
"ws": "^8.18.0"
diff --git a/packages/ws/package.json b/packages/ws/package.json
index d49a1006d9b2..0612473945c0 100644
--- a/packages/ws/package.json
+++ b/packages/ws/package.json
@@ -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.37.101",
+ "discord-api-types": "^0.37.103",
"tslib": "^2.6.3",
"ws": "^8.18.0"
},
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 1ff2a3ee1619..988f6e6f35df 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -674,8 +674,8 @@ importers:
specifier: workspace:^
version: link:../util
discord-api-types:
- specifier: ^0.37.101
- version: 0.37.101
+ specifier: ^0.37.103
+ version: 0.37.103
ts-mixer:
specifier: ^6.0.4
version: 6.0.4
@@ -801,8 +801,8 @@ importers:
specifier: ^2.4.6
version: 2.4.6
discord-api-types:
- specifier: ^0.37.101
- version: 0.37.101
+ specifier: ^0.37.103
+ version: 0.37.103
devDependencies:
'@discordjs/api-extractor':
specifier: workspace:^
@@ -938,8 +938,8 @@ importers:
specifier: 3.5.3
version: 3.5.3
discord-api-types:
- specifier: ^0.37.101
- version: 0.37.101
+ specifier: ^0.37.103
+ version: 0.37.103
fast-deep-equal:
specifier: 3.1.3
version: 3.1.3
@@ -1057,8 +1057,8 @@ importers:
packages/formatters:
dependencies:
discord-api-types:
- specifier: ^0.37.101
- version: 0.37.101
+ specifier: ^0.37.103
+ version: 0.37.103
devDependencies:
'@discordjs/api-extractor':
specifier: workspace:^
@@ -1130,8 +1130,8 @@ importers:
specifier: workspace:^
version: link:../ws
discord-api-types:
- specifier: ^0.37.101
- version: 0.37.101
+ specifier: ^0.37.103
+ version: 0.37.103
devDependencies:
'@discordjs/api-extractor':
specifier: workspace:^
@@ -1304,8 +1304,8 @@ importers:
specifier: ^2.4.6
version: 2.4.6
discord-api-types:
- specifier: ^0.37.101
- version: 0.37.101
+ specifier: ^0.37.103
+ version: 0.37.103
magic-bytes.js:
specifier: ^1.10.0
version: 1.10.0
@@ -1601,8 +1601,8 @@ importers:
specifier: ^8.5.12
version: 8.5.12
discord-api-types:
- specifier: ^0.37.101
- version: 0.37.101
+ specifier: ^0.37.103
+ version: 0.37.103
prism-media:
specifier: ^1.3.5
version: 1.3.5(@discordjs/opus@0.9.0(encoding@0.1.13))
@@ -1689,8 +1689,8 @@ importers:
specifier: ^2.4.6
version: 2.4.6
discord-api-types:
- specifier: ^0.37.101
- version: 0.37.101
+ specifier: ^0.37.103
+ version: 0.37.103
tslib:
specifier: ^2.6.3
version: 2.6.3
@@ -2589,16 +2589,16 @@ packages:
resolution: {integrity: sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==}
engines: {node: '>=12'}
- '@definitelytyped/header-parser@0.2.12':
- resolution: {integrity: sha512-UYtSXiLMhzRFKh7xHMkgiWsscgHxIndmjetaptZMMS0EOvfhUTuEM68GpjiCtz5shXw22Vacs1vDTAkKGDhNmg==}
+ '@definitelytyped/header-parser@0.2.13':
+ resolution: {integrity: sha512-m7YEtGhwAjmQyJQFQ7q8+hTGTiC/WrdRATvw8fyTwgW+RiWUt8MAeehuFj4txnCYXDcLO0ozuW5gNrLoYR4Ubg==}
engines: {node: '>=18.18.0'}
'@definitelytyped/typescript-versions@0.1.4':
resolution: {integrity: sha512-4Rz5kCpyxofwXCtBQaNfmWYXZcH0sMJxpbIgJzS+PAxgFCAa9W+2Jil7rrkpzsjx9E7+zOPukbXBXjyXohcyuQ==}
engines: {node: '>=18.18.0'}
- '@definitelytyped/utils@0.1.7':
- resolution: {integrity: sha512-t58AeNg6+mvyMnBHyPC6JQqWMW0Iwyb+vlpBz4V0d0iDY9H8gGCnLFg9vtN1nC+JXfTXBlf9efu9unMUeaPCiA==}
+ '@definitelytyped/utils@0.1.8':
+ resolution: {integrity: sha512-4JINx4Rttha29f50PBsJo48xZXx/He5yaIWJRwVarhYAN947+S84YciHl+AIhQNRPAFkg8+5qFngEGtKxQDWXA==}
engines: {node: '>=18.18.0'}
'@discordjs/builders@1.9.0':
@@ -5680,6 +5680,9 @@ packages:
'@types/node@18.19.45':
resolution: {integrity: sha512-VZxPKNNhjKmaC1SUYowuXSRSMGyQGmQjvvA1xE4QZ0xce2kLtEhPDS+kqpCPBZYgqblCLQ2DAjSzmgCM5auvhA==}
+ '@types/node@18.19.59':
+ resolution: {integrity: sha512-vizm2EqwV/7Zay+A6J3tGl9Lhr7CjZe2HmWS988sefiEmsyP9CeXEleho6i4hJk/8UtZAo0bWN4QPZZr83RxvQ==}
+
'@types/node@20.16.1':
resolution: {integrity: sha512-zJDo7wEadFtSyNz5QITDfRcrhqDvQI1xQNQ0VoizPjM/dVAODqqIUWbJPkvsxmTI0MYRGRikcdjMPhOssnPejQ==}
@@ -6577,8 +6580,8 @@ packages:
aws-sign2@0.7.0:
resolution: {integrity: sha512-08kcGqnYf/YmjoRhfxyu+CLxBjUtHLXLXX/vUfx9l2LYzG3c1m61nrpyFUZI6zeS+Li/wWMMidD9KgrqtGq3mA==}
- aws4@1.13.1:
- resolution: {integrity: sha512-u5w79Rd7SU4JaIlA/zFqG+gOiuq25q5VLyZ8E+ijJeILuTxVzZgp2CaGw/UTw6pXYN9XMO9yiqj/nEHmhTG5CA==}
+ aws4@1.13.2:
+ resolution: {integrity: sha512-lHe62zvbTB5eEABUVi/AwVh0ZKY9rMMDhmm+eeyuuUQbQ3+J+fONVQOZyj+DdrvD4BY33uYniyRJ4UJIaSKAfw==}
axe-core@4.10.0:
resolution: {integrity: sha512-Mr2ZakwQ7XUAjp7pAwQWRhhK8mQQ6JAaNWSjmjxil0R8BPioMtQsTLOolGYkji1rcL++3dCqZA3zWqpT+9Ew6g==}
@@ -6590,8 +6593,8 @@ packages:
axobject-query@4.0.0:
resolution: {integrity: sha512-+60uv1hiVFhHZeO+Lz0RYzsVHy5Wr1ayX0mwda9KPDVLNJgZ1T9Ny7VmFbLDzxsH0D87I86vgj3gFrjTJUYznw==}
- b4a@1.6.6:
- resolution: {integrity: sha512-5Tk1HLk6b6ctmjIkAcU/Ujv/1WqiDl0F0JdRCR80VsOcUlHcu7pWeWRlOqQLHfDEsVx9YH/aif5AG4ehoCtTmg==}
+ b4a@1.6.7:
+ resolution: {integrity: sha512-OnAYlL5b7LEkALw87fUVafQw5rVR9RjwGd4KUwNQ6DrrNmaVaUCgLipfVlzrPQ4tWOR9P0IXGNOx50jYCCdSJg==}
babel-code-frame@6.26.0:
resolution: {integrity: sha512-XqYMR2dfdGMW+hd0IUZ2PwK+fGeFkOxZJ0wY+JaQAHzt1Zx8LcvpiZD2NiGkEG8qx0CfkAOr5xt76d1e8vG90g==}
@@ -6650,8 +6653,8 @@ packages:
balanced-match@1.0.2:
resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==}
- bare-events@2.4.2:
- resolution: {integrity: sha512-qMKFd2qG/36aA4GwvKq8MxnPgCQAmBWmSyLWsJcbn8v03wvIPQ/hG1Ms8bPzndZxMDoHpxez5VOS+gC9Yi24/Q==}
+ bare-events@2.5.0:
+ resolution: {integrity: sha512-/E8dDe9dsbLyh2qrZ64PEPadOQ0F4gbl1sUJOrmph7xOiIxfY8vwab/4bFLh4Y88/Hk/ujKcrQKc+ps0mv873A==}
base64-js@0.0.8:
resolution: {integrity: sha512-3XSA2cR/h/73EzlXXdU6YNycmYI7+kicTxks4eJg2g39biHR84slg2+des+p7iHYhbRg/udIS4TD53WabcOUkw==}
@@ -7470,6 +7473,15 @@ packages:
supports-color:
optional: true
+ debug@4.3.7:
+ resolution: {integrity: sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==}
+ engines: {node: '>=6.0'}
+ peerDependencies:
+ supports-color: '*'
+ peerDependenciesMeta:
+ supports-color:
+ optional: true
+
decamelize-keys@1.1.1:
resolution: {integrity: sha512-WiPxgEirIV0/eIOMcnFBA3/IJZAZqKnwAwWyvvdi4lsr1WCN22nhdf/3db3DoZcUjTV2SqfzIwNyp6y2xs3nmg==}
engines: {node: '>=0.10.0'}
@@ -7612,8 +7624,8 @@ packages:
resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==}
engines: {node: '>=8'}
- discord-api-types@0.37.101:
- resolution: {integrity: sha512-2wizd94t7G3A8U5Phr3AiuL4gSvhqistDwWnlk1VLTit8BI1jWUncFqFQNdPbHqS3661+Nx/iEyIwtVjPuBP3w==}
+ discord-api-types@0.37.103:
+ resolution: {integrity: sha512-r+qitxXKe2l6KFw5odPdZSSqdEou+7eNC7BfbZ7mny5Me/K06wCTeKUMVeH/YsI9+4QQudskeQ307kr/7ppQ1A==}
discord-api-types@0.37.97:
resolution: {integrity: sha512-No1BXPcVkyVD4ZVmbNgDKaBoqgeQ+FJpzZ8wqHkfmBnTZig1FcH3iPPersiK1TUIAzgClh2IvOuVUYfcWLQAOA==}
@@ -8020,6 +8032,27 @@ packages:
peerDependencies:
eslint: '>=8.0.0'
+ eslint-module-utils@2.12.0:
+ resolution: {integrity: sha512-wALZ0HFoytlyh/1+4wuZ9FJCD/leWHQzzrxJ8+rebyReSLk7LApMyd3WJaLVoN+D5+WIdJyDK1c6JnE65V4Zyg==}
+ engines: {node: '>=4'}
+ peerDependencies:
+ '@typescript-eslint/parser': '*'
+ eslint: '*'
+ eslint-import-resolver-node: '*'
+ eslint-import-resolver-typescript: '*'
+ eslint-import-resolver-webpack: '*'
+ peerDependenciesMeta:
+ '@typescript-eslint/parser':
+ optional: true
+ eslint:
+ optional: true
+ eslint-import-resolver-node:
+ optional: true
+ eslint-import-resolver-typescript:
+ optional: true
+ eslint-import-resolver-webpack:
+ optional: true
+
eslint-module-utils@2.8.1:
resolution: {integrity: sha512-rXDXR3h7cs7dy9RNpUlQf80nX31XWJEyGq1tRMo+6GsO5VmTe4UTwtmonAD4ZkAsrfMVDA2wlGJ3790Ys+D49Q==}
engines: {node: '>=4'}
@@ -8185,6 +8218,7 @@ packages:
eslint@8.57.0:
resolution: {integrity: sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
+ deprecated: This version is no longer supported. Please see https://eslint.org/version-support for other options.
hasBin: true
espree@10.1.0:
@@ -8610,6 +8644,9 @@ packages:
get-tsconfig@4.7.6:
resolution: {integrity: sha512-ZAqrLlu18NbDdRaHq+AKXzAmqIUPswPWKUchfytdAjiRFnCe5ojG2bstg6mRiZabkKfCoL/e98pbBELIV/YCeA==}
+ get-tsconfig@4.8.1:
+ resolution: {integrity: sha512-k9PN+cFBmaLWtVz29SkUoqU5O0slLuHJXt/2P+tMVFT+phsSGXGkp9t3rQIqdz0e+06EHNGs3oM6ZX1s2zHxRg==}
+
get-uri@6.0.3:
resolution: {integrity: sha512-BzUrJBS9EcUb4cFol8r4W3v1cPsSyajLSthNkz5BxbpDcHN5tIrM10E2eNvfnvBn3DaT3DUgx0OpsBKkaOpanw==}
engines: {node: '>= 14'}
@@ -12263,6 +12300,7 @@ packages:
stream-connect@1.0.2:
resolution: {integrity: sha512-68Kl+79cE0RGKemKkhxTSg8+6AGrqBt+cbZAXevg2iJ6Y3zX4JhA/sZeGzLpxW9cXhmqAcE7KnJCisUmIUfnFQ==}
engines: {node: '>=0.10.0'}
+ deprecated: Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.
stream-to-array@2.3.0:
resolution: {integrity: sha512-UsZtOYEn4tWU2RGLOXr/o/xjRBftZRlG3dEWoaHr8j4GuypJ3isitGbVyjQKAuMu+xbiop8q224TjiZWc4XTZA==}
@@ -12278,8 +12316,8 @@ packages:
resolution: {integrity: sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==}
engines: {node: '>=10.0.0'}
- streamx@2.19.0:
- resolution: {integrity: sha512-5z6CNR4gtkPbwlxyEqoDGDmWIzoNJqCBt4Eac1ICP9YaIT08ct712cFj0u1rx4F8luAuL+3Qc+RFIdI4OX00kg==}
+ streamx@2.20.1:
+ resolution: {integrity: sha512-uTa0mU6WUC65iUvzKH4X9hEdvSW7rbPxPtwfWiLMSj3qTdQbAiUboZTxauKfpFuGIGa1C2BYijZ7wgdUXICJhA==}
string-argv@0.3.2:
resolution: {integrity: sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q==}
@@ -12558,8 +12596,8 @@ packages:
resolution: {integrity: sha512-sVACdAWcZkSU9x7AOmJo5TqE+GyNJknHaHsMrR6ZnhjVlVN9Yx6FjHrsKZ3BjIpPCT68zYesPWkakrNupwfOTQ==}
engines: {node: '>=4.0.0'}
- text-decoder@1.1.1:
- resolution: {integrity: sha512-8zll7REEv4GDD3x4/0pW+ppIxSNs7H1J10IKFZsuOMscumCdM2a+toDGLPA3T+1+fLBql4zbt5z83GEQGGV5VA==}
+ text-decoder@1.2.1:
+ resolution: {integrity: sha512-x9v3H/lTKIJKQQe7RPQkLfKAnc9lUTkWDypIQgTzPJAq+5/GCDHonmshfvlsNSj58yyshbIJJDLmU15qNERrXQ==}
text-extensions@2.4.0:
resolution: {integrity: sha512-te/NtwBwfiNRLf9Ijqx3T0nlqZiQ2XrrtBvu+cLL8ZRrGkO0NHTug8MYFKyoSrv/sHTaSKfilUkizV6XhxMJ3g==}
@@ -13815,7 +13853,7 @@ snapshots:
'@babel/core': 7.25.2
'@babel/helper-compilation-targets': 7.25.2
'@babel/helper-plugin-utils': 7.24.8
- debug: 4.3.6
+ debug: 4.3.7
lodash.debounce: 4.0.8
resolve: 1.22.8
transitivePeerDependencies:
@@ -14803,18 +14841,18 @@ snapshots:
dependencies:
'@jridgewell/trace-mapping': 0.3.9
- '@definitelytyped/header-parser@0.2.12':
+ '@definitelytyped/header-parser@0.2.13':
dependencies:
'@definitelytyped/typescript-versions': 0.1.4
- '@definitelytyped/utils': 0.1.7
- semver: 7.5.4
+ '@definitelytyped/utils': 0.1.8
+ semver: 7.6.3
'@definitelytyped/typescript-versions@0.1.4': {}
- '@definitelytyped/utils@0.1.7':
+ '@definitelytyped/utils@0.1.8':
dependencies:
'@qiwi/npm-registry-client': 8.9.1
- '@types/node': 18.19.45
+ '@types/node': 18.19.59
cachedir: 2.4.0
charm: 1.0.2
minimatch: 9.0.5
@@ -14924,7 +14962,7 @@ snapshots:
'@esbuild-plugins/node-resolve@0.1.4(esbuild@0.18.20)':
dependencies:
'@types/resolve': 1.20.6
- debug: 4.3.6
+ debug: 4.3.7
esbuild: 0.18.20
escape-string-regexp: 4.0.0
resolve: 1.22.8
@@ -15656,7 +15694,7 @@ snapshots:
nopt: 5.0.0
npmlog: 5.0.1
rimraf: 3.0.2
- semver: 7.5.4
+ semver: 7.6.3
tar: 6.2.1
transitivePeerDependencies:
- encoding
@@ -15940,14 +15978,14 @@ snapshots:
ini: 4.1.3
nopt: 7.2.1
proc-log: 4.2.0
- semver: 7.5.4
+ semver: 7.6.3
walk-up-path: 3.0.1
transitivePeerDependencies:
- bluebird
'@npmcli/fs@3.1.1':
dependencies:
- semver: 7.5.4
+ semver: 7.6.3
'@npmcli/git@5.0.8':
dependencies:
@@ -15958,7 +15996,7 @@ snapshots:
proc-log: 4.2.0
promise-inflight: 1.0.1
promise-retry: 2.0.1
- semver: 7.5.4
+ semver: 7.6.3
which: 4.0.0
transitivePeerDependencies:
- bluebird
@@ -15980,7 +16018,7 @@ snapshots:
json-parse-even-better-errors: 3.0.2
normalize-package-data: 6.0.2
proc-log: 4.2.0
- semver: 7.5.4
+ semver: 7.6.3
transitivePeerDependencies:
- bluebird
@@ -16146,7 +16184,7 @@ snapshots:
'@opentelemetry/propagator-b3': 1.25.1(@opentelemetry/api@1.9.0)
'@opentelemetry/propagator-jaeger': 1.25.1(@opentelemetry/api@1.9.0)
'@opentelemetry/sdk-trace-base': 1.25.1(@opentelemetry/api@1.9.0)
- semver: 7.5.4
+ semver: 7.6.3
'@opentelemetry/semantic-conventions@1.15.2': {}
@@ -16192,7 +16230,7 @@ snapshots:
request: 2.88.2
retry: 0.12.0
safe-buffer: 5.2.1
- semver: 7.5.4
+ semver: 7.6.3
slide: 1.1.6
ssri: 8.0.1
optionalDependencies:
@@ -19050,6 +19088,10 @@ snapshots:
dependencies:
undici-types: 5.26.5
+ '@types/node@18.19.59':
+ dependencies:
+ undici-types: 5.26.5
+
'@types/node@20.16.1':
dependencies:
undici-types: 6.19.8
@@ -19283,10 +19325,10 @@ snapshots:
dependencies:
'@typescript-eslint/types': 5.62.0
'@typescript-eslint/visitor-keys': 5.62.0
- debug: 4.3.6
+ debug: 4.3.7
globby: 11.1.0
is-glob: 4.0.3
- semver: 7.5.4
+ semver: 7.6.3
tsutils: 3.21.0(typescript@5.5.4)
optionalDependencies:
typescript: 5.5.4
@@ -19297,7 +19339,7 @@ snapshots:
dependencies:
'@typescript-eslint/types': 7.11.0
'@typescript-eslint/visitor-keys': 7.11.0
- debug: 4.3.6
+ debug: 4.3.7
globby: 11.1.0
is-glob: 4.0.3
minimatch: 9.0.5
@@ -19348,7 +19390,7 @@ snapshots:
'@typescript-eslint/typescript-estree': 5.62.0(typescript@5.5.4)
eslint: 8.57.0
eslint-scope: 5.1.1
- semver: 7.5.4
+ semver: 7.6.3
transitivePeerDependencies:
- supports-color
- typescript
@@ -20042,7 +20084,7 @@ snapshots:
agent-base@6.0.2:
dependencies:
- debug: 4.3.6
+ debug: 4.3.7
transitivePeerDependencies:
- supports-color
@@ -20351,7 +20393,7 @@ snapshots:
aws-sign2@0.7.0: {}
- aws4@1.13.1: {}
+ aws4@1.13.2: {}
axe-core@4.10.0: {}
@@ -20363,7 +20405,7 @@ snapshots:
dependencies:
dequal: 2.0.3
- b4a@1.6.6: {}
+ b4a@1.6.7: {}
babel-code-frame@6.26.0:
dependencies:
@@ -20468,7 +20510,7 @@ snapshots:
balanced-match@1.0.2: {}
- bare-events@2.4.2:
+ bare-events@2.5.0:
optional: true
base64-js@0.0.8: {}
@@ -21083,7 +21125,7 @@ snapshots:
handlebars: 4.7.8
json-stringify-safe: 5.0.1
meow: 12.1.1
- semver: 7.5.4
+ semver: 7.6.3
split2: 4.2.0
conventional-changelog@5.1.0:
@@ -21332,6 +21374,10 @@ snapshots:
dependencies:
ms: 2.1.2
+ debug@4.3.7:
+ dependencies:
+ ms: 2.1.3
+
decamelize-keys@1.1.1:
dependencies:
decamelize: 1.2.0
@@ -21462,7 +21508,7 @@ snapshots:
dependencies:
path-type: 4.0.0
- discord-api-types@0.37.101: {}
+ discord-api-types@0.37.103: {}
discord-api-types@0.37.97: {}
@@ -21515,7 +21561,7 @@ snapshots:
dts-critic@3.3.11(typescript@5.5.4):
dependencies:
- '@definitelytyped/header-parser': 0.2.12
+ '@definitelytyped/header-parser': 0.2.13
command-exists: 1.2.9
rimraf: 3.0.2
semver: 6.3.1
@@ -21525,9 +21571,9 @@ snapshots:
dtslint@4.2.1(typescript@5.5.4):
dependencies:
- '@definitelytyped/header-parser': 0.2.12
+ '@definitelytyped/header-parser': 0.2.13
'@definitelytyped/typescript-versions': 0.1.4
- '@definitelytyped/utils': 0.1.7
+ '@definitelytyped/utils': 0.1.8
dts-critic: 3.3.11(typescript@5.5.4)
fs-extra: 6.0.1
json-stable-stringify: 1.1.1
@@ -21773,14 +21819,14 @@ snapshots:
esbuild-register@3.6.0(esbuild@0.18.20):
dependencies:
- debug: 4.3.6
+ debug: 4.3.7
esbuild: 0.18.20
transitivePeerDependencies:
- supports-color
esbuild-register@3.6.0(esbuild@0.21.5):
dependencies:
- debug: 4.3.6
+ debug: 4.3.7
esbuild: 0.21.5
transitivePeerDependencies:
- supports-color
@@ -22026,7 +22072,7 @@ snapshots:
debug: 4.3.6
enhanced-resolve: 5.17.1
eslint: 8.57.0
- eslint-module-utils: 2.8.1(@typescript-eslint/parser@7.18.0(eslint@8.57.0)(typescript@5.5.4))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@7.18.0(eslint@8.57.0)(typescript@5.5.4))(eslint-plugin-i@2.29.1)(eslint@8.57.0))(eslint@8.57.0)
+ eslint-module-utils: 2.8.1(@typescript-eslint/parser@7.18.0(eslint@8.57.0)(typescript@5.5.4))(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.0)
eslint-plugin-import: eslint-plugin-i@2.29.1(@typescript-eslint/parser@7.18.0(eslint@8.57.0)(typescript@5.5.4))(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.0)
fast-glob: 3.3.2
get-tsconfig: 4.7.6
@@ -22059,7 +22105,7 @@ snapshots:
- bluebird
- supports-color
- eslint-module-utils@2.8.1(@typescript-eslint/parser@7.18.0(eslint@8.57.0)(typescript@5.5.4))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@7.18.0(eslint@8.57.0)(typescript@5.5.4))(eslint-plugin-i@2.29.1)(eslint@8.57.0))(eslint@8.57.0):
+ eslint-module-utils@2.12.0(@typescript-eslint/parser@7.18.0(eslint@8.57.0)(typescript@5.5.4))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.0):
dependencies:
debug: 3.2.7
optionalDependencies:
@@ -22070,6 +22116,16 @@ snapshots:
transitivePeerDependencies:
- supports-color
+ eslint-module-utils@2.8.1(@typescript-eslint/parser@7.18.0(eslint@8.57.0)(typescript@5.5.4))(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.0):
+ dependencies:
+ debug: 3.2.7
+ optionalDependencies:
+ '@typescript-eslint/parser': 7.18.0(eslint@8.57.0)(typescript@5.5.4)
+ eslint: 8.57.0
+ eslint-import-resolver-typescript: 3.6.1(@typescript-eslint/parser@7.18.0(eslint@8.57.0)(typescript@5.5.4))(eslint-plugin-i@2.29.1)(eslint@8.57.0)
+ transitivePeerDependencies:
+ - supports-color
+
eslint-plugin-astro@0.33.1(eslint@8.57.0):
dependencies:
'@eslint-community/eslint-utils': 4.4.0(eslint@8.57.0)
@@ -22098,15 +22154,15 @@ snapshots:
eslint-plugin-i@2.29.1(@typescript-eslint/parser@7.18.0(eslint@8.57.0)(typescript@5.5.4))(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.0):
dependencies:
- debug: 4.3.6
+ debug: 4.3.7
doctrine: 3.0.0
eslint: 8.57.0
eslint-import-resolver-node: 0.3.9
- eslint-module-utils: 2.8.1(@typescript-eslint/parser@7.18.0(eslint@8.57.0)(typescript@5.5.4))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@7.18.0(eslint@8.57.0)(typescript@5.5.4))(eslint-plugin-i@2.29.1)(eslint@8.57.0))(eslint@8.57.0)
- get-tsconfig: 4.7.6
+ eslint-module-utils: 2.12.0(@typescript-eslint/parser@7.18.0(eslint@8.57.0)(typescript@5.5.4))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.0)
+ get-tsconfig: 4.8.1
is-glob: 4.0.3
minimatch: 3.1.2
- semver: 7.5.4
+ semver: 7.6.3
transitivePeerDependencies:
- '@typescript-eslint/parser'
- eslint-import-resolver-typescript
@@ -22903,6 +22959,10 @@ snapshots:
dependencies:
resolve-pkg-maps: 1.0.0
+ get-tsconfig@4.8.1:
+ dependencies:
+ resolve-pkg-maps: 1.0.0
+
get-uri@6.0.3:
dependencies:
basic-ftp: 5.0.5
@@ -22965,7 +23025,7 @@ snapshots:
git-semver-tags@7.0.1:
dependencies:
meow: 12.1.1
- semver: 7.5.4
+ semver: 7.6.3
github-slugger@2.0.0: {}
@@ -23367,7 +23427,7 @@ snapshots:
dependencies:
'@tootallnate/once': 2.0.0
agent-base: 6.0.2
- debug: 4.3.6
+ debug: 4.3.7
transitivePeerDependencies:
- supports-color
@@ -23387,7 +23447,7 @@ snapshots:
https-proxy-agent@5.0.1:
dependencies:
agent-base: 6.0.2
- debug: 4.3.6
+ debug: 4.3.7
transitivePeerDependencies:
- supports-color
@@ -23789,7 +23849,7 @@ snapshots:
'@babel/parser': 7.25.4
'@istanbuljs/schema': 0.1.3
istanbul-lib-coverage: 3.2.2
- semver: 7.5.4
+ semver: 7.6.3
transitivePeerDependencies:
- supports-color
@@ -23801,7 +23861,7 @@ snapshots:
istanbul-lib-source-maps@4.0.1:
dependencies:
- debug: 4.3.6
+ debug: 4.3.7
istanbul-lib-coverage: 3.2.2
source-map: 0.6.1
transitivePeerDependencies:
@@ -24178,7 +24238,7 @@ snapshots:
jest-util: 29.7.0
natural-compare: 1.4.0
pretty-format: 29.7.0
- semver: 7.5.4
+ semver: 7.6.3
transitivePeerDependencies:
- supports-color
@@ -25629,7 +25689,7 @@ snapshots:
micromark@2.11.4:
dependencies:
- debug: 4.3.6
+ debug: 4.3.7
parse-entities: 2.0.0
transitivePeerDependencies:
- supports-color
@@ -25637,7 +25697,7 @@ snapshots:
micromark@3.2.0:
dependencies:
'@types/debug': 4.1.12
- debug: 4.3.6
+ debug: 4.3.7
decode-named-character-reference: 1.0.2
micromark-core-commonmark: 1.1.0
micromark-factory-space: 1.1.0
@@ -25659,7 +25719,7 @@ snapshots:
micromark@4.0.0:
dependencies:
'@types/debug': 4.1.12
- debug: 4.3.6
+ debug: 4.3.7
decode-named-character-reference: 1.0.2
devlop: 1.1.0
micromark-core-commonmark: 2.0.1
@@ -26002,13 +26062,13 @@ snapshots:
dependencies:
hosted-git-info: 4.1.0
is-core-module: 2.15.1
- semver: 7.5.4
+ semver: 7.6.3
validate-npm-package-license: 3.0.4
normalize-package-data@6.0.2:
dependencies:
hosted-git-info: 7.0.2
- semver: 7.5.4
+ semver: 7.6.3
validate-npm-package-license: 3.0.4
normalize-path@3.0.0: {}
@@ -26017,7 +26077,7 @@ snapshots:
npm-install-checks@6.3.0:
dependencies:
- semver: 7.5.4
+ semver: 7.6.3
npm-normalize-package-bin@3.0.1: {}
@@ -26032,13 +26092,13 @@ snapshots:
dependencies:
hosted-git-info: 7.0.2
proc-log: 4.2.0
- semver: 7.5.4
+ semver: 7.6.3
validate-npm-package-name: 5.0.1
npm-package-arg@8.1.5:
dependencies:
hosted-git-info: 4.1.0
- semver: 7.5.4
+ semver: 7.6.3
validate-npm-package-name: 3.0.0
npm-pick-manifest@9.1.0:
@@ -26046,7 +26106,7 @@ snapshots:
npm-install-checks: 6.3.0
npm-normalize-package-bin: 3.0.1
npm-package-arg: 11.0.3
- semver: 7.5.4
+ semver: 7.6.3
npm-registry-fetch@14.0.5:
dependencies:
@@ -27302,7 +27362,7 @@ snapshots:
request@2.88.2:
dependencies:
aws-sign2: 0.7.0
- aws4: 1.13.1
+ aws4: 1.13.2
caseless: 0.12.0
combined-stream: 1.0.8
extend: 3.0.2
@@ -27677,7 +27737,7 @@ snapshots:
socks-proxy-agent@7.0.0:
dependencies:
agent-base: 6.0.2
- debug: 4.3.6
+ debug: 4.3.7
socks: 2.8.3
transitivePeerDependencies:
- supports-color
@@ -27845,13 +27905,13 @@ snapshots:
streamsearch@1.1.0: {}
- streamx@2.19.0:
+ streamx@2.20.1:
dependencies:
fast-fifo: 1.3.2
queue-tick: 1.0.1
- text-decoder: 1.1.1
+ text-decoder: 1.2.1
optionalDependencies:
- bare-events: 2.4.2
+ bare-events: 2.5.0
string-argv@0.3.2: {}
@@ -28117,9 +28177,9 @@ snapshots:
tar-stream@3.1.7:
dependencies:
- b4a: 1.6.6
+ b4a: 1.6.7
fast-fifo: 1.3.2
- streamx: 2.19.0
+ streamx: 2.20.1
tar@4.4.18:
dependencies:
@@ -28197,9 +28257,7 @@ snapshots:
array-back: 2.0.0
typical: 2.6.1
- text-decoder@1.1.1:
- dependencies:
- b4a: 1.6.6
+ text-decoder@1.2.1: {}
text-extensions@2.4.0: {}
From a9f629b0d3e0b876b4ce90779834276523b7b1d8 Mon Sep 17 00:00:00 2001
From: Danial Raza
Date: Mon, 4 Nov 2024 11:03:13 +0100
Subject: [PATCH 07/22] feat: add soundboard (#10536)
* feat: add soundboard
* chore: disable `jsdoc/check-param-names` rule
* fix: export `SoundboardSoundsAPI`
---
packages/core/src/api/channel.ts | 21 +++++
packages/core/src/api/guild.ts | 95 +++++++++++++++++++++++
packages/core/src/api/index.ts | 5 ++
packages/core/src/api/soundboardSounds.ts | 20 +++++
packages/core/src/client.ts | 8 ++
5 files changed, 149 insertions(+)
create mode 100644 packages/core/src/api/soundboardSounds.ts
diff --git a/packages/core/src/api/channel.ts b/packages/core/src/api/channel.ts
index fe8aa20c68b9..a651c4ff430c 100644
--- a/packages/core/src/api/channel.ts
+++ b/packages/core/src/api/channel.ts
@@ -33,6 +33,8 @@ import {
type RESTPostAPIChannelThreadsResult,
type APIThreadChannel,
type RESTPostAPIGuildForumThreadsJSONBody,
+ type RESTPostAPISoundboardSendSoundJSONBody,
+ type RESTPostAPISendSoundboardSoundResult,
} from 'discord-api-types/v10';
export interface StartForumThreadOptions extends RESTPostAPIGuildForumThreadsJSONBody {
@@ -583,4 +585,23 @@ export class ChannelsAPI {
signal,
});
}
+
+ /**
+ * Sends a soundboard sound in a channel
+ *
+ * @see {@link https://discord.com/developers/docs/resources/soundboard#send-soundboard-sound}
+ * @param channelId - The id of the channel to send the soundboard sound in
+ * @param body - The data for sending the soundboard sound
+ * @param options - The options for sending the soundboard sound
+ */
+ public async sendSoundboardSound(
+ channelId: Snowflake,
+ body: RESTPostAPISoundboardSendSoundJSONBody,
+ { signal }: Pick = {},
+ ) {
+ return this.rest.post(Routes.sendSoundboardSound(channelId), {
+ body,
+ signal,
+ }) as Promise;
+ }
}
diff --git a/packages/core/src/api/guild.ts b/packages/core/src/api/guild.ts
index 9cb9f8fdeb03..698b6df36958 100644
--- a/packages/core/src/api/guild.ts
+++ b/packages/core/src/api/guild.ts
@@ -100,6 +100,12 @@ import {
type RESTPutAPIGuildOnboardingJSONBody,
type RESTPutAPIGuildOnboardingResult,
type RESTPutAPIGuildTemplateSyncResult,
+ type RESTGetAPIGuildSoundboardSoundResult,
+ type RESTGetAPIGuildSoundboardSoundsResult,
+ type RESTPatchAPIGuildSoundboardSoundJSONBody,
+ type RESTPatchAPIGuildSoundboardSoundResult,
+ type RESTPostAPIGuildSoundboardSoundJSONBody,
+ type RESTPostAPIGuildSoundboardSoundResult,
type Snowflake,
} from 'discord-api-types/v10';
import { VoiceAPI } from './voice';
@@ -1356,4 +1362,93 @@ export class GuildsAPI {
signal,
}) as Promise;
}
+
+ /**
+ * Fetches all the soundboard sounds for a guild
+ *
+ * @see {@link https://discord.com/developers/docs/resources/soundboard#list-guild-soundboard-sounds}
+ * @param guildId - The id of the guild to fetch the soundboard sounds for
+ * @param options - The options for fetching the soundboard sounds
+ */
+ public async getSoundboardSounds(guildId: Snowflake, { signal }: Pick = {}) {
+ return this.rest.get(Routes.guildSoundboardSounds(guildId), {
+ signal,
+ }) as Promise;
+ }
+
+ /**
+ * Fetches a soundboard sound for a guild
+ *
+ * @see {@link https://discord.com/developers/docs/resources/soundboard#get-guild-soundboard-sound}
+ * @param guildId - The id of the guild to fetch the soundboard sound for
+ * @param soundId - The id of the soundboard sound to fetch
+ * @param options - The options for fetching the soundboard sound
+ */
+ public async getSoundboardSound(
+ guildId: Snowflake,
+ soundId: Snowflake,
+ { signal }: Pick = {},
+ ) {
+ return this.rest.get(Routes.guildSoundboardSound(guildId, soundId), {
+ signal,
+ }) as Promise;
+ }
+
+ /**
+ * Creates a new soundboard sound for a guild
+ *
+ * @see {@link https://discord.com/developers/docs/resources/soundboard#create-guild-soundboard-sound}
+ * @param guildId - The id of the guild to create the soundboard sound for
+ * @param body - The data for creating the soundboard sound
+ * @param options - The options for creating the soundboard sound
+ */
+ public async createSoundboardSound(
+ guildId: Snowflake,
+ body: RESTPostAPIGuildSoundboardSoundJSONBody,
+ { reason, signal }: Pick = {},
+ ) {
+ return this.rest.post(Routes.guildSoundboardSounds(guildId), {
+ body,
+ reason,
+ signal,
+ }) as Promise;
+ }
+
+ /**
+ * Edits a soundboard sound for a guild
+ *
+ * @see {@link https://discord.com/developers/docs/resources/soundboard#modify-guild-soundboard-sound}
+ * @param guildId - The id of the guild to edit the soundboard sound for
+ * @param soundId - The id of the soundboard sound to edit
+ * @param body - The data for editing the soundboard sound
+ * @param options - The options for editing the soundboard sound
+ */
+ public async editSoundboardSound(
+ guildId: Snowflake,
+ soundId: Snowflake,
+ body: RESTPatchAPIGuildSoundboardSoundJSONBody,
+ { reason, signal }: Pick = {},
+ ) {
+ return this.rest.patch(Routes.guildSoundboardSound(guildId, soundId), {
+ body,
+ reason,
+ signal,
+ }) as Promise;
+ }
+
+ /**
+ * Deletes a soundboard sound for a guild
+ *
+ * @see {@link https://discord.com/developers/docs/resources/soundboard#delete-guild-soundboard-sound}
+ * @param guildId - The id of the guild to delete the soundboard sound for
+ * @param soundId - The id of the soundboard sound to delete
+ * @param options - The options for deleting the soundboard sound
+ */
+ public async deleteSoundboardSound(
+ guildId: Snowflake,
+ soundId: Snowflake,
+ { reason, signal }: Pick = {},
+ ) {
+ await this.rest.delete(Routes.guildSoundboardSound(guildId, soundId), { reason, signal });
+ }
}
diff --git a/packages/core/src/api/index.ts b/packages/core/src/api/index.ts
index a44fc53a8d7b..d9fbe6b1e93b 100644
--- a/packages/core/src/api/index.ts
+++ b/packages/core/src/api/index.ts
@@ -9,6 +9,7 @@ import { MonetizationAPI } from './monetization.js';
import { OAuth2API } from './oauth2.js';
import { PollAPI } from './poll.js';
import { RoleConnectionsAPI } from './roleConnections.js';
+import { SoundboardSoundsAPI } from './soundboardSounds.js';
import { StageInstancesAPI } from './stageInstances.js';
import { StickersAPI } from './sticker.js';
import { ThreadsAPI } from './thread.js';
@@ -26,6 +27,7 @@ export * from './monetization.js';
export * from './oauth2.js';
export * from './poll.js';
export * from './roleConnections.js';
+export * from './soundboardSounds.js';
export * from './stageInstances.js';
export * from './sticker.js';
export * from './thread.js';
@@ -54,6 +56,8 @@ export class API {
public readonly roleConnections: RoleConnectionsAPI;
+ public readonly soundboardSounds: SoundboardSoundsAPI;
+
public readonly stageInstances: StageInstancesAPI;
public readonly stickers: StickersAPI;
@@ -76,6 +80,7 @@ export class API {
this.oauth2 = new OAuth2API(rest);
this.poll = new PollAPI(rest);
this.roleConnections = new RoleConnectionsAPI(rest);
+ this.soundboardSounds = new SoundboardSoundsAPI(rest);
this.stageInstances = new StageInstancesAPI(rest);
this.stickers = new StickersAPI(rest);
this.threads = new ThreadsAPI(rest);
diff --git a/packages/core/src/api/soundboardSounds.ts b/packages/core/src/api/soundboardSounds.ts
new file mode 100644
index 000000000000..b474fd1e7a6f
--- /dev/null
+++ b/packages/core/src/api/soundboardSounds.ts
@@ -0,0 +1,20 @@
+/* eslint-disable jsdoc/check-param-names */
+
+import type { RequestData, REST } from '@discordjs/rest';
+import { Routes, type RESTGetAPISoundboardDefaultSoundsResult } from 'discord-api-types/v10';
+
+export class SoundboardSoundsAPI {
+ public constructor(private readonly rest: REST) {}
+
+ /**
+ * Fetches all the soundboard default sounds.
+ *
+ * @see {@link https://discord.com/developers/docs/resources/soundboard#list-default-soundboard-sounds}
+ * @param options - The options for fetching the soundboard default sounds.
+ */
+ public async getSoundboardDefaultSounds({ signal }: Pick = {}) {
+ return this.rest.get(Routes.soundboardDefaultSounds(), {
+ signal,
+ }) as Promise;
+ }
+}
diff --git a/packages/core/src/client.ts b/packages/core/src/client.ts
index 90eea1e2d8e9..23b1110c0ad1 100644
--- a/packages/core/src/client.ts
+++ b/packages/core/src/client.ts
@@ -38,6 +38,10 @@ import {
type GatewayGuildScheduledEventUpdateDispatchData,
type GatewayGuildScheduledEventUserAddDispatchData,
type GatewayGuildScheduledEventUserRemoveDispatchData,
+ type GatewayGuildSoundboardSoundCreateDispatch,
+ type GatewayGuildSoundboardSoundDeleteDispatch,
+ type GatewayGuildSoundboardSoundUpdateDispatch,
+ type GatewayGuildSoundboardSoundsUpdateDispatch,
type GatewayGuildStickersUpdateDispatchData,
type GatewayGuildUpdateDispatchData,
type GatewayIntegrationCreateDispatchData,
@@ -131,6 +135,10 @@ export interface MappedEvents {
[GatewayDispatchEvents.GuildScheduledEventUserRemove]: [
ToEventProps,
];
+ [GatewayDispatchEvents.GuildSoundboardSoundCreate]: [ToEventProps];
+ [GatewayDispatchEvents.GuildSoundboardSoundDelete]: [ToEventProps];
+ [GatewayDispatchEvents.GuildSoundboardSoundUpdate]: [ToEventProps];
+ [GatewayDispatchEvents.GuildSoundboardSoundsUpdate]: [ToEventProps];
[GatewayDispatchEvents.GuildStickersUpdate]: [ToEventProps];
[GatewayDispatchEvents.GuildUpdate]: [ToEventProps];
[GatewayDispatchEvents.IntegrationCreate]: [ToEventProps];
From ef2a6879d3921b895f99332baf7fd4ffa606db45 Mon Sep 17 00:00:00 2001
From: Jiralite <33201955+Jiralite@users.noreply.github.com>
Date: Mon, 4 Nov 2024 10:43:34 +0000
Subject: [PATCH 08/22] feat(GuildMember): Banners (#10384)
* feat: initial support for guild member banners
* feat: serialise in `toJSON()`
* feat: serialise in `toJSON()`
* docs: lowercase i
---------
Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
---
.../discord.js/src/structures/GuildMember.js | 33 +++++++++++++++++++
packages/discord.js/typings/index.d.ts | 3 ++
2 files changed, 36 insertions(+)
diff --git a/packages/discord.js/src/structures/GuildMember.js b/packages/discord.js/src/structures/GuildMember.js
index db71c66b5473..b03a1bc4d6ec 100644
--- a/packages/discord.js/src/structures/GuildMember.js
+++ b/packages/discord.js/src/structures/GuildMember.js
@@ -84,6 +84,17 @@ class GuildMember extends Base {
} else if (typeof this.avatar !== 'string') {
this.avatar = null;
}
+
+ if ('banner' in data) {
+ /**
+ * The guild member's banner hash.
+ * @type {?string}
+ */
+ this.banner = data.banner;
+ } else {
+ this.banner ??= null;
+ }
+
if ('joined_at' in data) this.joinedTimestamp = Date.parse(data.joined_at);
if ('premium_since' in data) {
this.premiumSinceTimestamp = data.premium_since ? Date.parse(data.premium_since) : null;
@@ -155,6 +166,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 banner.
+ * @param {ImageURLOptions} [options={}] Options for the banner URL
+ * @returns {?string}
+ */
+ bannerURL(options = {}) {
+ return this.banner && this.client.rest.cdn.guildMemberBanner(this.guild.id, this.id, this.banner, options);
+ }
+
/**
* A link to the member's guild avatar if they have one.
* Otherwise, a link to their {@link User#displayAvatarURL} will be returned.
@@ -165,6 +185,16 @@ class GuildMember extends Base {
return this.avatarURL(options) ?? this.user.displayAvatarURL(options);
}
+ /**
+ * A link to the member's guild banner if they have one.
+ * Otherwise, a link to their {@link User#bannerURL} will be returned.
+ * @param {ImageURLOptions} [options={}] Options for the image URL
+ * @returns {?string}
+ */
+ displayBannerURL(options) {
+ return this.bannerURL(options) ?? this.user.bannerURL(options);
+ }
+
/**
* The time this member joined the guild
* @type {?Date}
@@ -464,6 +494,7 @@ class GuildMember extends Base {
this.joinedTimestamp === member.joinedTimestamp &&
this.nickname === member.nickname &&
this.avatar === member.avatar &&
+ this.banner === member.banner &&
this.pending === member.pending &&
this.communicationDisabledUntilTimestamp === member.communicationDisabledUntilTimestamp &&
this.flags.bitfield === member.flags.bitfield &&
@@ -491,7 +522,9 @@ class GuildMember extends Base {
roles: true,
});
json.avatarURL = this.avatarURL();
+ json.bannerURL = this.bannerURL();
json.displayAvatarURL = this.displayAvatarURL();
+ json.displayBannerURL = this.displayBannerURL();
return json;
}
}
diff --git a/packages/discord.js/typings/index.d.ts b/packages/discord.js/typings/index.d.ts
index edc0c29965a9..bd3cb855c498 100644
--- a/packages/discord.js/typings/index.d.ts
+++ b/packages/discord.js/typings/index.d.ts
@@ -1634,6 +1634,7 @@ export class GuildMember extends Base {
private constructor(client: Client, data: RawGuildMemberData, guild: Guild);
private _roles: Snowflake[];
public avatar: string | null;
+ public banner: string | null;
public get bannable(): boolean;
public get dmChannel(): DMChannel | null;
public get displayColor(): number;
@@ -1660,6 +1661,7 @@ export class GuildMember extends Base {
public user: User;
public get voice(): VoiceState;
public avatarURL(options?: ImageURLOptions): string | null;
+ public bannerURL(options?: ImageURLOptions): string | null;
public ban(options?: BanOptions): Promise;
public disableCommunicationUntil(timeout: DateResolvable | null, reason?: string): Promise;
public timeout(timeout: number | null, reason?: string): Promise;
@@ -1667,6 +1669,7 @@ export class GuildMember extends Base {
public createDM(force?: boolean): Promise;
public deleteDM(): Promise;
public displayAvatarURL(options?: ImageURLOptions): string;
+ public displayBannerURL(options?: ImageURLOptions): string | null;
public edit(options: GuildMemberEditOptions): Promise;
public isCommunicationDisabled(): this is GuildMember & {
communicationDisabledUntilTimestamp: number;
From 1fd662629d24521426c581cd89025e17820ec3e9 Mon Sep 17 00:00:00 2001
From: Danial Raza
Date: Mon, 4 Nov 2024 11:48:41 +0100
Subject: [PATCH 09/22] feat: add subscriptions (#10486)
* feat: add subscriptions
* docs: requested changes
Co-authored-by: Almeida
---------
Co-authored-by: Almeida
Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
---
packages/core/src/api/monetization.ts | 51 ++++++++++++++++++++++++---
packages/core/src/client.ts | 6 ++++
2 files changed, 52 insertions(+), 5 deletions(-)
diff --git a/packages/core/src/api/monetization.ts b/packages/core/src/api/monetization.ts
index 736b8930a1e5..c4cd8dade6b6 100644
--- a/packages/core/src/api/monetization.ts
+++ b/packages/core/src/api/monetization.ts
@@ -6,6 +6,9 @@ import {
type RESTGetAPIEntitlementsQuery,
type RESTGetAPIEntitlementsResult,
type RESTGetAPISKUsResult,
+ type RESTGetAPISKUSubscriptionResult,
+ type RESTGetAPISKUSubscriptionsQuery,
+ type RESTGetAPISKUSubscriptionsResult,
type RESTPostAPIEntitlementJSONBody,
type RESTPostAPIEntitlementResult,
type Snowflake,
@@ -17,17 +20,55 @@ export class MonetizationAPI {
/**
* Fetches the SKUs for an application.
*
- * @see {@link https://discord.com/developers/docs/monetization/skus#list-skus}
+ * @see {@link https://discord.com/developers/docs/resources/sku#list-skus}
+ * @param applicationId - The application id to fetch SKUs for
* @param options - The options for fetching the SKUs.
*/
public async getSKUs(applicationId: Snowflake, { signal }: Pick = {}) {
return this.rest.get(Routes.skus(applicationId), { signal }) as Promise;
}
+ /**
+ * Fetches subscriptions for an SKU.
+ *
+ * @see {@link https://discord.com/developers/docs/resources/subscription#list-sku-subscriptions}
+ * @param skuId - The SKU id to fetch subscriptions for
+ * @param query - The query options for fetching subscriptions
+ * @param options - The options for fetching subscriptions
+ */
+ public async getSKUSubscriptions(
+ skuId: Snowflake,
+ query: RESTGetAPISKUSubscriptionsQuery,
+ { signal }: Pick = {},
+ ) {
+ return this.rest.get(Routes.skuSubscriptions(skuId), {
+ signal,
+ query: makeURLSearchParams(query),
+ }) as Promise;
+ }
+
+ /**
+ * Fetches a subscription for an SKU.
+ *
+ * @see {@link https://discord.com/developers/docs/resources/subscription#get-sku-subscription}
+ * @param skuId - The SKU id to fetch subscription for
+ * @param subscriptionId - The subscription id to fetch
+ * @param options - The options for fetching the subscription
+ */
+ public async getSKUSubscription(
+ skuId: Snowflake,
+ subscriptionId: Snowflake,
+ { signal }: Pick = {},
+ ) {
+ return this.rest.get(Routes.skuSubscription(skuId, subscriptionId), {
+ signal,
+ }) as Promise;
+ }
+
/**
* Fetches the entitlements for an application.
*
- * @see {@link https://discord.com/developers/docs/monetization/entitlements#list-entitlements}
+ * @see {@link https://discord.com/developers/docs/resources/entitlement#list-entitlements}
* @param applicationId - The application id to fetch entitlements for
* @param query - The query options for fetching entitlements
* @param options - The options for fetching entitlements
@@ -46,7 +87,7 @@ export class MonetizationAPI {
/**
* Creates a test entitlement for an application's SKU.
*
- * @see {@link https://discord.com/developers/docs/monetization/entitlements#create-test-entitlement}
+ * @see {@link https://discord.com/developers/docs/resources/entitlement#create-test-entitlement}
* @param applicationId - The application id to create the entitlement for
* @param body - The data for creating the entitlement
* @param options - The options for creating the entitlement
@@ -65,7 +106,7 @@ export class MonetizationAPI {
/**
* Deletes a test entitlement for an application's SKU.
*
- * @see {@link https://discord.com/developers/docs/monetization/entitlements#delete-test-entitlement}
+ * @see {@link https://discord.com/developers/docs/resources/entitlement#delete-test-entitlement}
* @param applicationId - The application id to delete the entitlement for
* @param entitlementId - The entitlement id to delete
* @param options - The options for deleting the entitlement
@@ -81,7 +122,7 @@ export class MonetizationAPI {
/**
* Marks a given entitlement for the user as consumed. Only available for One-Time Purchase consumable SKUs.
*
- * @see {@link https://discord.com/developers/docs/monetization/entitlements#consume-an-entitlement}
+ * @see {@link https://discord.com/developers/docs/resources/entitlement#consume-an-entitlement}
* @param applicationId - The application id to consume the entitlement for
* @param entitlementId - The entitlement id to consume
* @param options - The options for consuming the entitlement
diff --git a/packages/core/src/client.ts b/packages/core/src/client.ts
index 23b1110c0ad1..5bb1c96b7322 100644
--- a/packages/core/src/client.ts
+++ b/packages/core/src/client.ts
@@ -66,6 +66,9 @@ import {
type GatewayStageInstanceCreateDispatchData,
type GatewayStageInstanceDeleteDispatchData,
type GatewayStageInstanceUpdateDispatchData,
+ type GatewaySubscriptionCreateDispatchData,
+ type GatewaySubscriptionDeleteDispatchData,
+ type GatewaySubscriptionUpdateDispatchData,
type GatewayThreadCreateDispatchData,
type GatewayThreadDeleteDispatchData,
type GatewayThreadListSyncDispatchData,
@@ -163,6 +166,9 @@ export interface MappedEvents {
[GatewayDispatchEvents.StageInstanceCreate]: [ToEventProps];
[GatewayDispatchEvents.StageInstanceDelete]: [ToEventProps];
[GatewayDispatchEvents.StageInstanceUpdate]: [ToEventProps];
+ [GatewayDispatchEvents.SubscriptionCreate]: [ToEventProps];
+ [GatewayDispatchEvents.SubscriptionDelete]: [ToEventProps];
+ [GatewayDispatchEvents.SubscriptionUpdate]: [ToEventProps];
[GatewayDispatchEvents.ThreadCreate]: [ToEventProps];
[GatewayDispatchEvents.ThreadDelete]: [ToEventProps];
[GatewayDispatchEvents.ThreadListSync]: [ToEventProps];
From f02bdc3be37bbcae97991df0693531b93da447d4 Mon Sep 17 00:00:00 2001
From: Souji
Date: Tue, 5 Nov 2024 10:29:29 +0100
Subject: [PATCH 10/22] docs: add note about idempotence to role add/remove
routes (#10586)
* chore(docs): Add note about idempotence to role add/remove routes
* chore: remove trailing spaces
---
packages/discord.js/src/managers/GuildMemberRoleManager.js | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/packages/discord.js/src/managers/GuildMemberRoleManager.js b/packages/discord.js/src/managers/GuildMemberRoleManager.js
index e5302683d0f9..7d19bf778b64 100644
--- a/packages/discord.js/src/managers/GuildMemberRoleManager.js
+++ b/packages/discord.js/src/managers/GuildMemberRoleManager.js
@@ -101,6 +101,8 @@ class GuildMemberRoleManager extends DataManager {
/**
* Adds a role (or multiple roles) to the member.
+ *
+ * Uses the idempotent PUT route for singular roles, otherwise PATCHes the underlying guild member
* @param {RoleResolvable|RoleResolvable[]|Collection} roleOrRoles The role or roles to add
* @param {string} [reason] Reason for adding the role(s)
* @returns {Promise}
@@ -138,6 +140,8 @@ class GuildMemberRoleManager extends DataManager {
/**
* Removes a role (or multiple roles) from the member.
+ *
+ * Uses the idempotent DELETE route for singular roles, otherwise PATCHes the underlying guild member
* @param {RoleResolvable|RoleResolvable[]|Collection} roleOrRoles The role or roles to remove
* @param {string} [reason] Reason for removing the role(s)
* @returns {Promise}
From 939e3644e1e1dabe5d3074682c522cc9bc5c7148 Mon Sep 17 00:00:00 2001
From: Danial Raza
Date: Tue, 5 Nov 2024 10:36:41 +0100
Subject: [PATCH 11/22] types: add missing `Caches` managers (#10540)
Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
---
packages/discord.js/typings/index.d.ts | 14 ++++++++------
1 file changed, 8 insertions(+), 6 deletions(-)
diff --git a/packages/discord.js/typings/index.d.ts b/packages/discord.js/typings/index.d.ts
index bd3cb855c498..0661f25eadad 100644
--- a/packages/discord.js/typings/index.d.ts
+++ b/packages/discord.js/typings/index.d.ts
@@ -4961,18 +4961,20 @@ export type BitFieldResolvable];
- GuildEmojiManager: [manager: typeof GuildEmojiManager, holds: typeof GuildEmoji];
// TODO: ChannelManager: [manager: typeof ChannelManager, holds: typeof Channel];
- // TODO: GuildChannelManager: [manager: typeof GuildChannelManager, holds: typeof GuildChannel];
- // TODO: GuildManager: [manager: typeof GuildManager, holds: typeof Guild];
- GuildMemberManager: [manager: typeof GuildMemberManager, holds: typeof GuildMember];
+ DMMessageManager: [manager: typeof MessageManager, holds: typeof Message];
+ EntitlementManager: [manager: typeof EntitlementManager, holds: typeof Entitlement];
GuildBanManager: [manager: typeof GuildBanManager, holds: typeof GuildBan];
+ // TODO: GuildChannelManager: [manager: typeof GuildChannelManager, holds: typeof GuildChannel];
+ GuildEmojiManager: [manager: typeof GuildEmojiManager, holds: typeof GuildEmoji];
GuildForumThreadManager: [manager: typeof GuildForumThreadManager, holds: typeof ThreadChannel];
GuildInviteManager: [manager: typeof GuildInviteManager, holds: typeof Invite];
+ // TODO: GuildManager: [manager: typeof GuildManager, holds: typeof Guild];
+ GuildMemberManager: [manager: typeof GuildMemberManager, holds: typeof GuildMember];
GuildMessageManager: [manager: typeof GuildMessageManager, holds: typeof Message];
GuildScheduledEventManager: [manager: typeof GuildScheduledEventManager, holds: typeof GuildScheduledEvent];
GuildStickerManager: [manager: typeof GuildStickerManager, holds: typeof Sticker];
From 1184b38d3e43193036e17a3c4d6aed95546ba73c Mon Sep 17 00:00:00 2001
From: Naiyar <137700126+imnaiyar@users.noreply.github.com>
Date: Tue, 5 Nov 2024 16:30:44 +0530
Subject: [PATCH 12/22] refactor(ThreadManager)!: match parent ID when fetching
a single thread (#10557)
BREAKING CHANGE: `ThreadManager#fetch` now throws when the provided thread ID doesn't belong to the current channel
---
packages/discord.js/src/errors/ErrorCodes.js | 2 ++
packages/discord.js/src/errors/Messages.js | 1 +
packages/discord.js/src/managers/ThreadManager.js | 9 +++++++--
3 files changed, 10 insertions(+), 2 deletions(-)
diff --git a/packages/discord.js/src/errors/ErrorCodes.js b/packages/discord.js/src/errors/ErrorCodes.js
index f23b3232b442..b160068e7669 100644
--- a/packages/discord.js/src/errors/ErrorCodes.js
+++ b/packages/discord.js/src/errors/ErrorCodes.js
@@ -73,6 +73,7 @@
* @property {'MessageThreadParent'} MessageThreadParent
* @property {'MessageExistingThread'} MessageExistingThread
* @property {'ThreadInvitableType'} ThreadInvitableType
+ * @property {'NotAThreadOfParent'} NotAThreadOfParent
* @property {'WebhookMessage'} WebhookMessage
* @property {'WebhookTokenUnavailable'} WebhookTokenUnavailable
@@ -201,6 +202,7 @@ const keys = [
'MessageThreadParent',
'MessageExistingThread',
'ThreadInvitableType',
+ 'NotAThreadOfParent',
'WebhookMessage',
'WebhookTokenUnavailable',
diff --git a/packages/discord.js/src/errors/Messages.js b/packages/discord.js/src/errors/Messages.js
index 2ee1ab3405e4..133c4d0cee50 100644
--- a/packages/discord.js/src/errors/Messages.js
+++ b/packages/discord.js/src/errors/Messages.js
@@ -78,6 +78,7 @@ const Messages = {
[DjsErrorCodes.MessageThreadParent]: 'The message was not sent in a guild text or announcement channel',
[DjsErrorCodes.MessageExistingThread]: 'The message already has a thread',
[DjsErrorCodes.ThreadInvitableType]: type => `Invitable cannot be edited on ${type}`,
+ [DjsErrorCodes.NotAThreadOfParent]: 'Provided ThreadChannelResolvable is not a thread of the parent channel.',
[DjsErrorCodes.WebhookMessage]: 'The message was not sent by a webhook.',
[DjsErrorCodes.WebhookTokenUnavailable]: 'This action requires a webhook token, but none is available.',
diff --git a/packages/discord.js/src/managers/ThreadManager.js b/packages/discord.js/src/managers/ThreadManager.js
index a8bf2a67e83c..afb75a1e0b7a 100644
--- a/packages/discord.js/src/managers/ThreadManager.js
+++ b/packages/discord.js/src/managers/ThreadManager.js
@@ -83,10 +83,15 @@ class ThreadManager extends CachedManager {
* .then(channel => console.log(channel.name))
* .catch(console.error);
*/
- fetch(options, { cache, force } = {}) {
+ async fetch(options, { cache, force } = {}) {
if (!options) return this.fetchActive(cache);
const channel = this.client.channels.resolveId(options);
- if (channel) return this.client.channels.fetch(channel, { cache, force });
+ if (channel) {
+ const threadChannel = await this.client.channels.fetch(channel, { cache, force });
+ if (threadChannel.parentId !== this.channel.id) throw new DiscordjsTypeError(ErrorCodes.NotAThreadOfParent);
+ return threadChannel;
+ }
+
if (options.archived) {
return this.fetchArchived(options.archived, cache);
}
From c34a57b79826989634a2109ded3fc2c8372c5698 Mon Sep 17 00:00:00 2001
From: Jiralite <33201955+Jiralite@users.noreply.github.com>
Date: Tue, 5 Nov 2024 22:19:48 +0000
Subject: [PATCH 13/22] fix(ThreadChannel): Address parameter type on
`fetchOwner()` (#10579)
* fix(ThreadChannel): address parameter on owner helper method
* docs: fix description
Co-authored-by: Almeida
---------
Co-authored-by: Almeida
Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
---
packages/discord.js/src/structures/ThreadChannel.js | 10 ++++++++--
packages/discord.js/typings/index.d.ts | 6 +++++-
2 files changed, 13 insertions(+), 3 deletions(-)
diff --git a/packages/discord.js/src/structures/ThreadChannel.js b/packages/discord.js/src/structures/ThreadChannel.js
index 129fa3ae3ed1..d3b92dd80592 100644
--- a/packages/discord.js/src/structures/ThreadChannel.js
+++ b/packages/discord.js/src/structures/ThreadChannel.js
@@ -287,11 +287,17 @@ class ThreadChannel extends BaseChannel {
return this.parent?.permissionsFor(memberOrRole, checkAdmin) ?? null;
}
+ /**
+ * Options used to fetch a thread owner.
+ * @typedef {BaseFetchOptions} FetchThreadOwnerOptions
+ * @property {boolean} [withMember] Whether to also return the guild member associated with this thread member
+ */
+
/**
* Fetches the owner of this thread. If the thread member object isn't needed,
* use {@link ThreadChannel#ownerId} instead.
- * @param {BaseFetchOptions} [options] The options for fetching the member
- * @returns {Promise}
+ * @param {FetchThreadOwnerOptions} [options] Options for fetching the owner
+ * @returns {Promise}
*/
async fetchOwner(options) {
if (!this.ownerId) {
diff --git a/packages/discord.js/typings/index.d.ts b/packages/discord.js/typings/index.d.ts
index 0661f25eadad..afb73b20a91b 100644
--- a/packages/discord.js/typings/index.d.ts
+++ b/packages/discord.js/typings/index.d.ts
@@ -3318,7 +3318,7 @@ export class ThreadChannel extends BaseCha
memberOrRole: GuildMemberResolvable | RoleResolvable,
checkAdmin?: boolean,
): Readonly | null;
- public fetchOwner(options?: BaseFetchOptions): Promise;
+ public fetchOwner(options?: FetchThreadOwnerOptions): Promise;
public fetchStarterMessage(options?: BaseFetchOptions): Promise | null>;
public setArchived(archived?: boolean, reason?: string): Promise;
public setAutoArchiveDuration(autoArchiveDuration: ThreadAutoArchiveDuration, reason?: string): Promise;
@@ -5565,6 +5565,10 @@ export interface FetchThreadMemberOptions extends BaseFetchOptions {
withMember?: boolean;
}
+export interface FetchThreadOwnerOptions extends BaseFetchOptions {
+ withMember?: boolean;
+}
+
export interface FetchThreadMembersWithGuildMemberDataOptions {
withMember: true;
after?: Snowflake;
From ea042458a3f378f1cb83545b3291f3552092bf85 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Ren=C3=A9?= <9092381+Renegade334@users.noreply.github.com>
Date: Thu, 7 Nov 2024 11:03:26 +0000
Subject: [PATCH 14/22] perf(collection): optimisations (#10552)
* perf: `merge()`: deduplicate boolean checks
* perf: `toSorted()`: remove redundant closure
* perf: `last[Key]()`: order of operations
- do not perform iterable-to-array until required
- test ! before <
* perf: `{at,keyAt}()`: manually iterate to target
* perf: `first[Key]()`: avoid `Array.from()`
* perf: `map()`: avoid `Array.from()`
* perf: `random[Key]()`: avoid `Array.from()`
* test: `.{at,keyAt}()` indices
* perf: `last[Key]()`: use `.at()`/`.keyAt()` for single element
* perf: `first[Key]()`: use iterable-to-array if returning all
* perf: `random[Key]()`: use `{at,keyAt}()` for single value
- skip iterable-to-array for returning single value
- short-circuit if amount or collection size is zero
* perf: `random[Key]()`: use Durstenfeld shuffle
* refactor: `{key,keyAt}()`: reorder index check
---------
Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
---
.../collection/__tests__/collection.test.ts | 20 ++-
packages/collection/src/collection.ts | 142 ++++++++++++------
2 files changed, 115 insertions(+), 47 deletions(-)
diff --git a/packages/collection/__tests__/collection.test.ts b/packages/collection/__tests__/collection.test.ts
index 0ea401fd44e2..ea8f918bdce6 100644
--- a/packages/collection/__tests__/collection.test.ts
+++ b/packages/collection/__tests__/collection.test.ts
@@ -70,12 +70,20 @@ describe('at() tests', () => {
expect(coll.at(0)).toStrictEqual(1);
});
+ test('positive non-integer index', () => {
+ expect(coll.at(1.5)).toStrictEqual(2);
+ });
+
test('negative index', () => {
expect(coll.at(-1)).toStrictEqual(3);
});
+ test('negative non-integer index', () => {
+ expect(coll.at(-2.5)).toStrictEqual(2);
+ });
+
test('invalid positive index', () => {
- expect(coll.at(4)).toBeUndefined();
+ expect(coll.at(3)).toBeUndefined();
});
test('invalid negative index', () => {
@@ -432,12 +440,20 @@ describe('keyAt() tests', () => {
expect(coll.keyAt(0)).toStrictEqual('a');
});
+ test('positive non-integer index', () => {
+ expect(coll.keyAt(1.5)).toStrictEqual('b');
+ });
+
test('negative index', () => {
expect(coll.keyAt(-1)).toStrictEqual('c');
});
+ test('negative non-integer index', () => {
+ expect(coll.keyAt(-2.5)).toStrictEqual('b');
+ });
+
test('invalid positive index', () => {
- expect(coll.keyAt(4)).toBeUndefined();
+ expect(coll.keyAt(3)).toBeUndefined();
});
test('invalid negative index', () => {
diff --git a/packages/collection/src/collection.ts b/packages/collection/src/collection.ts
index 19fc01da9b11..5fa11cb1ebb9 100644
--- a/packages/collection/src/collection.ts
+++ b/packages/collection/src/collection.ts
@@ -85,9 +85,16 @@ export class Collection extends Map {
public first(amount?: number): Value | Value[] | undefined {
if (amount === undefined) return this.values().next().value;
if (amount < 0) return this.last(amount * -1);
- amount = Math.min(this.size, amount);
+ if (amount >= this.size) return [...this.values()];
+
const iter = this.values();
- return Array.from({ length: amount }, (): Value => iter.next().value!);
+ // eslint-disable-next-line unicorn/no-new-array
+ const results: Value[] = new Array(amount);
+ for (let index = 0; index < amount; index++) {
+ results[index] = iter.next().value!;
+ }
+
+ return results;
}
/**
@@ -102,9 +109,16 @@ export class Collection extends Map {
public firstKey(amount?: number): Key | Key[] | undefined {
if (amount === undefined) return this.keys().next().value;
if (amount < 0) return this.lastKey(amount * -1);
- amount = Math.min(this.size, amount);
+ if (amount >= this.size) return [...this.keys()];
+
const iter = this.keys();
- return Array.from({ length: amount }, (): Key => iter.next().value!);
+ // eslint-disable-next-line unicorn/no-new-array
+ const results: Key[] = new Array(amount);
+ for (let index = 0; index < amount; index++) {
+ results[index] = iter.next().value!;
+ }
+
+ return results;
}
/**
@@ -117,11 +131,12 @@ export class Collection extends Map {
public last(): Value | undefined;
public last(amount: number): Value[];
public last(amount?: number): Value | Value[] | undefined {
- const arr = [...this.values()];
- if (amount === undefined) return arr[arr.length - 1];
- if (amount < 0) return this.first(amount * -1);
+ if (amount === undefined) return this.at(-1);
if (!amount) return [];
- return arr.slice(-amount);
+ if (amount < 0) return this.first(amount * -1);
+
+ const arr = [...this.values()];
+ return arr.slice(amount * -1);
}
/**
@@ -134,11 +149,12 @@ export class Collection extends Map {
public lastKey(): Key | undefined;
public lastKey(amount: number): Key[];
public lastKey(amount?: number): Key | Key[] | undefined {
- const arr = [...this.keys()];
- if (amount === undefined) return arr[arr.length - 1];
- if (amount < 0) return this.firstKey(amount * -1);
+ if (amount === undefined) return this.keyAt(-1);
if (!amount) return [];
- return arr.slice(-amount);
+ if (amount < 0) return this.firstKey(amount * -1);
+
+ const arr = [...this.keys()];
+ return arr.slice(amount * -1);
}
/**
@@ -148,10 +164,21 @@ export class Collection extends Map {
*
* @param index - The index of the element to obtain
*/
- public at(index: number) {
- index = Math.floor(index);
- const arr = [...this.values()];
- return arr.at(index);
+ public at(index: number): Value | undefined {
+ index = Math.trunc(index);
+ if (index >= 0) {
+ if (index >= this.size) return undefined;
+ } else {
+ index += this.size;
+ if (index < 0) return undefined;
+ }
+
+ const iter = this.values();
+ for (let skip = 0; skip < index; skip++) {
+ iter.next();
+ }
+
+ return iter.next().value!;
}
/**
@@ -161,10 +188,21 @@ export class Collection extends Map {
*
* @param index - The index of the key to obtain
*/
- public keyAt(index: number) {
- index = Math.floor(index);
- const arr = [...this.keys()];
- return arr.at(index);
+ public keyAt(index: number): Key | undefined {
+ index = Math.trunc(index);
+ if (index >= 0) {
+ if (index >= this.size) return undefined;
+ } else {
+ index += this.size;
+ if (index < 0) return undefined;
+ }
+
+ const iter = this.keys();
+ for (let skip = 0; skip < index; skip++) {
+ iter.next();
+ }
+
+ return iter.next().value!;
}
/**
@@ -176,13 +214,17 @@ export class Collection extends Map {
public random(): Value | undefined;
public random(amount: number): Value[];
public random(amount?: number): Value | Value[] | undefined {
- const arr = [...this.values()];
- if (amount === undefined) return arr[Math.floor(Math.random() * arr.length)];
- if (!arr.length || !amount) return [];
- return Array.from(
- { length: Math.min(amount, arr.length) },
- (): Value => arr.splice(Math.floor(Math.random() * arr.length), 1)[0]!,
- );
+ if (amount === undefined) return this.at(Math.floor(Math.random() * this.size));
+ amount = Math.min(this.size, amount);
+ if (!amount) return [];
+
+ const values = [...this.values()];
+ for (let sourceIndex = 0; sourceIndex < amount; sourceIndex++) {
+ const targetIndex = sourceIndex + Math.floor(Math.random() * (values.length - sourceIndex));
+ [values[sourceIndex], values[targetIndex]] = [values[targetIndex]!, values[sourceIndex]!];
+ }
+
+ return values.slice(0, amount);
}
/**
@@ -194,13 +236,17 @@ export class Collection extends Map {
public randomKey(): Key | undefined;
public randomKey(amount: number): Key[];
public randomKey(amount?: number): Key | Key[] | undefined {
- const arr = [...this.keys()];
- if (amount === undefined) return arr[Math.floor(Math.random() * arr.length)];
- if (!arr.length || !amount) return [];
- return Array.from(
- { length: Math.min(amount, arr.length) },
- (): Key => arr.splice(Math.floor(Math.random() * arr.length), 1)[0]!,
- );
+ if (amount === undefined) return this.keyAt(Math.floor(Math.random() * this.size));
+ amount = Math.min(this.size, amount);
+ if (!amount) return [];
+
+ const keys = [...this.keys()];
+ for (let sourceIndex = 0; sourceIndex < amount; sourceIndex++) {
+ const targetIndex = sourceIndex + Math.floor(Math.random() * (keys.length - sourceIndex));
+ [keys[sourceIndex], keys[targetIndex]] = [keys[targetIndex]!, keys[sourceIndex]!];
+ }
+
+ return keys.slice(0, amount);
}
/**
@@ -511,10 +557,14 @@ export class Collection extends Map {
if (typeof fn !== 'function') throw new TypeError(`${fn} is not a function`);
if (thisArg !== undefined) fn = fn.bind(thisArg);
const iter = this.entries();
- return Array.from({ length: this.size }, (): NewValue => {
+ // eslint-disable-next-line unicorn/no-new-array
+ const results: NewValue[] = new Array(this.size);
+ for (let index = 0; index < this.size; index++) {
const [key, value] = iter.next().value!;
- return fn(value, key, this);
- });
+ results[index] = fn(value, key, this);
+ }
+
+ return results;
}
/**
@@ -959,12 +1009,14 @@ export class Collection extends Map {
const hasInSelf = this.has(key);
const hasInOther = other.has(key);
- if (hasInSelf && hasInOther) {
- const result = whenInBoth(this.get(key)!, other.get(key)!, key);
- if (result.keep) coll.set(key, result.value);
- } else if (hasInSelf) {
- const result = whenInSelf(this.get(key)!, key);
- if (result.keep) coll.set(key, result.value);
+ if (hasInSelf) {
+ if (hasInOther) {
+ const result = whenInBoth(this.get(key)!, other.get(key)!, key);
+ if (result.keep) coll.set(key, result.value);
+ } else {
+ const result = whenInSelf(this.get(key)!, key);
+ if (result.keep) coll.set(key, result.value);
+ }
} else if (hasInOther) {
const result = whenInOther(other.get(key)!, key);
if (result.keep) coll.set(key, result.value);
@@ -995,8 +1047,8 @@ export class Collection extends Map {
* collection.sorted((userA, userB) => userA.createdTimestamp - userB.createdTimestamp);
* ```
*/
- public toSorted(compareFunction: Comparator = Collection.defaultSort) {
- return new this.constructor[Symbol.species](this).sort((av, bv, ak, bk) => compareFunction(av, bv, ak, bk));
+ public toSorted(compareFunction: Comparator = Collection.defaultSort): Collection {
+ return new this.constructor[Symbol.species](this).sort(compareFunction);
}
public toJSON() {
From c97310681da0fab68ac17fb100fbfcb249dec402 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Ren=C3=A9?= <9092381+Renegade334@users.noreply.github.com>
Date: Thu, 7 Nov 2024 11:12:53 +0000
Subject: [PATCH 15/22] types(collection): simplify ambient constructor
declaration (#10549)
- deduplicates constructor definition
- removes Collection's "internal" JSDoc description block
- removes unnecessary `extends` clause
Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
---
packages/collection/src/collection.ts | 24 +++++++-----------------
1 file changed, 7 insertions(+), 17 deletions(-)
diff --git a/packages/collection/src/collection.ts b/packages/collection/src/collection.ts
index 5fa11cb1ebb9..8f842ef68ad6 100644
--- a/packages/collection/src/collection.ts
+++ b/packages/collection/src/collection.ts
@@ -1,14 +1,4 @@
/* eslint-disable no-param-reassign */
-/**
- * @internal
- */
-export interface CollectionConstructor {
- new (): Collection;
- new (entries?: readonly (readonly [Key, Value])[] | null): Collection;
- new (iterable: Iterable): Collection;
- readonly prototype: Collection;
- readonly [Symbol.species]: CollectionConstructor;
-}
/**
* Represents an immutable version of a collection
@@ -19,13 +9,13 @@ export type ReadonlyCollection = Omit<
> &
ReadonlyMap;
-/**
- * Separate interface for the constructor so that emitted js does not have a constructor that overwrites itself
- *
- * @internal
- */
-export interface Collection extends Map {
- constructor: CollectionConstructor;
+export interface Collection {
+ /**
+ * Ambient declaration to allow `this.constructor[@@species]` in class methods.
+ *
+ * @internal
+ */
+ constructor: typeof Collection & { readonly [Symbol.species]: typeof Collection };
}
/**
From f2f7f1f65b29149ac04db60e624a600036277810 Mon Sep 17 00:00:00 2001
From: cobalt <61329810+cobaltt7@users.noreply.github.com>
Date: Sun, 10 Nov 2024 18:42:04 -0600
Subject: [PATCH 16/22] refactor(formatters): Change `:_:` emoji name
placeholder (#10567)
* Change `:_:` emoji name placeholder
* Update tests
* Format
---
.../formatters/__tests__/formatters.test.ts | 34 +++++++++++--------
packages/formatters/src/formatters.ts | 8 ++---
2 files changed, 24 insertions(+), 18 deletions(-)
diff --git a/packages/formatters/__tests__/formatters.test.ts b/packages/formatters/__tests__/formatters.test.ts
index 1b745439943d..c91f4c694348 100644
--- a/packages/formatters/__tests__/formatters.test.ts
+++ b/packages/formatters/__tests__/formatters.test.ts
@@ -174,31 +174,37 @@ describe('Message formatters', () => {
});
describe('formatEmoji', () => {
- test('GIVEN static emojiId THEN returns "<:_:${emojiId}>"', () => {
- expect<`<:_:851461487498493952>`>(formatEmoji('851461487498493952')).toEqual('<:_:851461487498493952>');
+ test('GIVEN static emojiId THEN returns "<:emoji:${emojiId}>"', () => {
+ expect<`<:emoji:851461487498493952>`>(formatEmoji('851461487498493952')).toEqual('<:emoji:851461487498493952>');
});
- test('GIVEN static emojiId WITH animated explicitly false THEN returns "<:_:[emojiId]>"', () => {
- expect<`<:_:851461487498493952>`>(formatEmoji('851461487498493952', false)).toEqual('<:_:851461487498493952>');
+ test('GIVEN static emojiId WITH animated explicitly false THEN returns "<:emoji:[emojiId]>"', () => {
+ expect<`<:emoji:851461487498493952>`>(formatEmoji('851461487498493952', false)).toEqual(
+ '<:emoji:851461487498493952>',
+ );
});
- test('GIVEN animated emojiId THEN returns ""', () => {
- expect<``>(formatEmoji('827220205352255549', true)).toEqual('');
+ test('GIVEN animated emojiId THEN returns ""', () => {
+ expect<``>(formatEmoji('827220205352255549', true)).toEqual(
+ '',
+ );
});
- test('GIVEN static id in options object THEN returns "<:_:${id}>"', () => {
- expect<`<:_:851461487498493952>`>(formatEmoji({ id: '851461487498493952' })).toEqual('<:_:851461487498493952>');
+ test('GIVEN static id in options object THEN returns "<:emoji:${id}>"', () => {
+ expect<`<:emoji:851461487498493952>`>(formatEmoji({ id: '851461487498493952' })).toEqual(
+ '<:emoji:851461487498493952>',
+ );
});
- test('GIVEN static id in options object WITH animated explicitly false THEN returns "<:_:${id}>"', () => {
- expect<`<:_:851461487498493952>`>(formatEmoji({ animated: false, id: '851461487498493952' })).toEqual(
- '<:_:851461487498493952>',
+ test('GIVEN static id in options object WITH animated explicitly false THEN returns "<:emoji:${id}>"', () => {
+ expect<`<:emoji:851461487498493952>`>(formatEmoji({ animated: false, id: '851461487498493952' })).toEqual(
+ '<:emoji:851461487498493952>',
);
});
- test('GIVEN animated id in options object THEN returns ""', () => {
- expect<``>(formatEmoji({ animated: true, id: '827220205352255549' })).toEqual(
- '',
+ test('GIVEN animated id in options object THEN returns ""', () => {
+ expect<``>(formatEmoji({ animated: true, id: '827220205352255549' })).toEqual(
+ '',
);
});
diff --git a/packages/formatters/src/formatters.ts b/packages/formatters/src/formatters.ts
index 9c4e11932949..915ec331c816 100644
--- a/packages/formatters/src/formatters.ts
+++ b/packages/formatters/src/formatters.ts
@@ -323,7 +323,7 @@ export function chatInputApplicationCommandMention<
* @typeParam EmojiId - This is inferred by the supplied emoji id
* @param emojiId - The emoji id to format
*/
-export function formatEmoji(emojiId: EmojiId, animated?: false): `<:_:${EmojiId}>`;
+export function formatEmoji(emojiId: EmojiId, animated?: false): `<:emoji:${EmojiId}>`;
/**
* Formats an animated emoji id into a fully qualified emoji identifier.
@@ -332,7 +332,7 @@ export function formatEmoji(emojiId: EmojiId, animate
* @param emojiId - The emoji id to format
* @param animated - Whether the emoji is animated
*/
-export function formatEmoji(emojiId: EmojiId, animated?: true): ``;
+export function formatEmoji(emojiId: EmojiId, animated?: true): ``;
/**
* Formats an emoji id into a fully qualified emoji identifier.
@@ -344,7 +344,7 @@ export function formatEmoji(emojiId: EmojiId, animate
export function formatEmoji(
emojiId: EmojiId,
animated?: boolean,
-): `<:_:${EmojiId}>` | ``;
+): `<:emoji:${EmojiId}>` | ``;
/**
* Formats a non-animated emoji id and name into a fully qualified emoji identifier.
@@ -393,7 +393,7 @@ export function formatEmoji
const { id, animated: isAnimated, name: emojiName } = options;
- return `<${isAnimated ? 'a' : ''}:${emojiName ?? '_'}:${id}>`;
+ return `<${isAnimated ? 'a' : ''}:${emojiName ?? 'emoji'}:${id}>`;
}
/**
From b8f5a68297b9614489ba74fcd59b568ee8f58072 Mon Sep 17 00:00:00 2001
From: Naiyar <137700126+imnaiyar@users.noreply.github.com>
Date: Mon, 11 Nov 2024 21:18:52 +0530
Subject: [PATCH 17/22] fix(InteractionResponses): throw error on deleting
response of unacknowledged interaction (#10587)
fix: error on deleting response of non-acknowledged interaction
Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
---
.../src/structures/interfaces/InteractionResponses.js | 2 ++
1 file changed, 2 insertions(+)
diff --git a/packages/discord.js/src/structures/interfaces/InteractionResponses.js b/packages/discord.js/src/structures/interfaces/InteractionResponses.js
index 7b1cfb1429f0..e448e19fd17e 100644
--- a/packages/discord.js/src/structures/interfaces/InteractionResponses.js
+++ b/packages/discord.js/src/structures/interfaces/InteractionResponses.js
@@ -174,6 +174,8 @@ class InteractionResponses {
* .catch(console.error);
*/
async deleteReply(message = '@original') {
+ if (!this.deferred && !this.replied) throw new DiscordjsError(ErrorCodes.InteractionNotReplied);
+
await this.webhook.deleteMessage(message);
}
From e2df0e0dbc224cf8915e30b4906b832e36a6840a Mon Sep 17 00:00:00 2001
From: Jiralite <33201955+Jiralite@users.noreply.github.com>
Date: Tue, 12 Nov 2024 06:50:35 +0000
Subject: [PATCH 18/22] docs: Remove Node.js 10 notice (#10593)
docs: remove Node.js 10 notice
---
packages/collection/src/collection.ts | 2 --
1 file changed, 2 deletions(-)
diff --git a/packages/collection/src/collection.ts b/packages/collection/src/collection.ts
index 8f842ef68ad6..2b4868a5fb10 100644
--- a/packages/collection/src/collection.ts
+++ b/packages/collection/src/collection.ts
@@ -831,7 +831,6 @@ export class Collection extends Map {
/**
* The sort method sorts the items of a collection in place and returns it.
- * The sort is not necessarily stable in Node 10 or older.
* The default sort order is according to string Unicode code points.
*
* @param compareFunction - Specifies a function that defines the sort order.
@@ -1026,7 +1025,6 @@ export class Collection extends Map {
/**
* The sorted method sorts the items of a collection and returns it.
- * The sort is not necessarily stable in Node 10 or older.
* The default sort order is according to string Unicode code points.
*
* @param compareFunction - Specifies a function that defines the sort order.
From 6775175459338ab1c3299a3dc3f49797cf2b7049 Mon Sep 17 00:00:00 2001
From: Jiralite <33201955+Jiralite@users.noreply.github.com>
Date: Thu, 14 Nov 2024 21:00:04 +0000
Subject: [PATCH 19/22] feat: Voice Channel Effect Send (#10318)
* feat: Voice Channel Send Effects (#9288)
* feat: add soundboard fields
* chore: address TODO
* docs: volume is a closed interval
* types: use `GatewayVoiceChannelEffectSendDispatchData`
* refactor: prefer getting from cache
* fix: correctly access cache
Co-authored-by: Danial Raza
---------
Co-authored-by: Danial Raza
---
.../handlers/VOICE_CHANNEL_EFFECT_SEND.js | 16 +++++
.../src/client/websocket/handlers/index.js | 1 +
packages/discord.js/src/index.js | 1 +
.../src/structures/VoiceChannelEffect.js | 69 +++++++++++++++++++
packages/discord.js/src/util/APITypes.js | 5 ++
packages/discord.js/src/util/Events.js | 2 +
packages/discord.js/typings/index.d.ts | 17 +++++
7 files changed, 111 insertions(+)
create mode 100644 packages/discord.js/src/client/websocket/handlers/VOICE_CHANNEL_EFFECT_SEND.js
create mode 100644 packages/discord.js/src/structures/VoiceChannelEffect.js
diff --git a/packages/discord.js/src/client/websocket/handlers/VOICE_CHANNEL_EFFECT_SEND.js b/packages/discord.js/src/client/websocket/handlers/VOICE_CHANNEL_EFFECT_SEND.js
new file mode 100644
index 000000000000..350fdb90647f
--- /dev/null
+++ b/packages/discord.js/src/client/websocket/handlers/VOICE_CHANNEL_EFFECT_SEND.js
@@ -0,0 +1,16 @@
+'use strict';
+
+const VoiceChannelEffect = require('../../../structures/VoiceChannelEffect');
+const Events = require('../../../util/Events');
+
+module.exports = (client, { d: data }) => {
+ const guild = client.guilds.cache.get(data.guild_id);
+ if (!guild) return;
+
+ /**
+ * Emmited when someone sends an effect, such as an emoji reaction, in a voice channel the client is connected to.
+ * @event Client#voiceChannelEffectSend
+ * @param {VoiceChannelEffect} voiceChannelEffect The sent voice channel effect
+ */
+ client.emit(Events.VoiceChannelEffectSend, new VoiceChannelEffect(data, guild));
+};
diff --git a/packages/discord.js/src/client/websocket/handlers/index.js b/packages/discord.js/src/client/websocket/handlers/index.js
index 4af0714a12bf..24c3f86a4aeb 100644
--- a/packages/discord.js/src/client/websocket/handlers/index.js
+++ b/packages/discord.js/src/client/websocket/handlers/index.js
@@ -60,6 +60,7 @@ const handlers = Object.fromEntries([
['THREAD_UPDATE', require('./THREAD_UPDATE')],
['TYPING_START', require('./TYPING_START')],
['USER_UPDATE', require('./USER_UPDATE')],
+ ['VOICE_CHANNEL_EFFECT_SEND', require('./VOICE_CHANNEL_EFFECT_SEND')],
['VOICE_SERVER_UPDATE', require('./VOICE_SERVER_UPDATE')],
['VOICE_STATE_UPDATE', require('./VOICE_STATE_UPDATE')],
['WEBHOOKS_UPDATE', require('./WEBHOOKS_UPDATE')],
diff --git a/packages/discord.js/src/index.js b/packages/discord.js/src/index.js
index cdedc8aa45c0..7c5c17cd63df 100644
--- a/packages/discord.js/src/index.js
+++ b/packages/discord.js/src/index.js
@@ -206,6 +206,7 @@ exports.ThreadOnlyChannel = require('./structures/ThreadOnlyChannel');
exports.Typing = require('./structures/Typing');
exports.User = require('./structures/User');
exports.UserContextMenuCommandInteraction = require('./structures/UserContextMenuCommandInteraction');
+exports.VoiceChannelEffect = require('./structures/VoiceChannelEffect');
exports.VoiceChannel = require('./structures/VoiceChannel');
exports.VoiceRegion = require('./structures/VoiceRegion');
exports.VoiceState = require('./structures/VoiceState');
diff --git a/packages/discord.js/src/structures/VoiceChannelEffect.js b/packages/discord.js/src/structures/VoiceChannelEffect.js
new file mode 100644
index 000000000000..ee42ea6f72b9
--- /dev/null
+++ b/packages/discord.js/src/structures/VoiceChannelEffect.js
@@ -0,0 +1,69 @@
+'use strict';
+
+const { Emoji } = require('./Emoji');
+
+/**
+ * Represents an effect used in a {@link VoiceChannel}.
+ */
+class VoiceChannelEffect {
+ constructor(data, guild) {
+ /**
+ * The guild where the effect was sent from.
+ * @type {Guild}
+ */
+ this.guild = guild;
+
+ /**
+ * The id of the channel the effect was sent in.
+ * @type {Snowflake}
+ */
+ this.channelId = data.channel_id;
+
+ /**
+ * The id of the user that sent the effect.
+ * @type {Snowflake}
+ */
+ this.userId = data.user_id;
+
+ /**
+ * The emoji of the effect.
+ * @type {?Emoji}
+ */
+ this.emoji = data.emoji ? new Emoji(guild.client, data.emoji) : null;
+
+ /**
+ * The animation type of the effect.
+ * @type {?VoiceChannelEffectSendAnimationType}
+ */
+ this.animationType = data.animation_type ?? null;
+
+ /**
+ * The animation id of the effect.
+ * @type {?number}
+ */
+ this.animationId = data.animation_id ?? null;
+
+ /**
+ * The id of the soundboard sound for soundboard effects.
+ * @type {?(Snowflake|number)}
+ */
+ this.soundId = data.sound_id ?? null;
+
+ /**
+ * The volume of the soundboard sound [0-1] for soundboard effects.
+ * @type {?number}
+ */
+ this.soundVolume = data.sound_volume ?? null;
+ }
+
+ /**
+ * The channel the effect was sent in.
+ * @type {?VoiceChannel}
+ * @readonly
+ */
+ get channel() {
+ return this.guild.channels.cache.get(this.channelId) ?? null;
+ }
+}
+
+module.exports = VoiceChannelEffect;
diff --git a/packages/discord.js/src/util/APITypes.js b/packages/discord.js/src/util/APITypes.js
index 8737623d62e6..0032dd4363a9 100644
--- a/packages/discord.js/src/util/APITypes.js
+++ b/packages/discord.js/src/util/APITypes.js
@@ -589,6 +589,11 @@
* @see {@link https://discord-api-types.dev/api/discord-api-types-v10/enum/VideoQualityMode}
*/
+/**
+ * @external VoiceChannelEffectSendAnimationType
+ * @see {@link https://discord-api-types.dev/api/discord-api-types-v10/enum/VoiceChannelEffectSendAnimationType}
+ */
+
/**
* @external WebhookType
* @see {@link https://discord-api-types.dev/api/discord-api-types-v10/enum/WebhookType}
diff --git a/packages/discord.js/src/util/Events.js b/packages/discord.js/src/util/Events.js
index 1ab65a13d8f5..a4b658e5cfba 100644
--- a/packages/discord.js/src/util/Events.js
+++ b/packages/discord.js/src/util/Events.js
@@ -72,6 +72,7 @@
* @property {string} ThreadUpdate threadUpdate
* @property {string} TypingStart typingStart
* @property {string} UserUpdate userUpdate
+ * @property {string} VoiceChannelEffectSend voiceChannelEffectSend
* @property {string} VoiceServerUpdate voiceServerUpdate
* @property {string} VoiceStateUpdate voiceStateUpdate
* @property {string} Warn warn
@@ -154,6 +155,7 @@ module.exports = {
ThreadUpdate: 'threadUpdate',
TypingStart: 'typingStart',
UserUpdate: 'userUpdate',
+ VoiceChannelEffectSend: 'voiceChannelEffectSend',
VoiceServerUpdate: 'voiceServerUpdate',
VoiceStateUpdate: 'voiceStateUpdate',
Warn: 'warn',
diff --git a/packages/discord.js/typings/index.d.ts b/packages/discord.js/typings/index.d.ts
index afb73b20a91b..dc2aac43f714 100644
--- a/packages/discord.js/typings/index.d.ts
+++ b/packages/discord.js/typings/index.d.ts
@@ -166,6 +166,8 @@ import {
GuildScheduledEventRecurrenceRuleFrequency,
GatewaySendPayload,
GatewayDispatchPayload,
+ VoiceChannelEffectSendAnimationType,
+ GatewayVoiceChannelEffectSendDispatchData,
} from 'discord-api-types/v10';
import { ChildProcess } from 'node:child_process';
import { EventEmitter } from 'node:events';
@@ -3557,6 +3559,19 @@ export class VoiceChannel extends BaseGuildVoiceChannel {
public type: ChannelType.GuildVoice;
}
+export class VoiceChannelEffect {
+ private constructor(data: GatewayVoiceChannelEffectSendDispatchData, guild: Guild);
+ public guild: Guild;
+ public channelId: Snowflake;
+ public userId: Snowflake;
+ public emoji: Emoji | null;
+ public animationType: VoiceChannelEffectSendAnimationType | null;
+ public animationId: number | null;
+ public soundId: Snowflake | number | null;
+ public soundVolume: number | null;
+ public get channel(): VoiceChannel | null;
+}
+
export class VoiceRegion {
private constructor(data: RawVoiceRegionData);
public custom: boolean;
@@ -5163,6 +5178,7 @@ export interface ClientEvents {
threadUpdate: [oldThread: AnyThreadChannel, newThread: AnyThreadChannel];
typingStart: [typing: Typing];
userUpdate: [oldUser: User | PartialUser, newUser: User];
+ voiceChannelEffectSend: [voiceChannelEffect: VoiceChannelEffect];
voiceStateUpdate: [oldState: VoiceState, newState: VoiceState];
webhooksUpdate: [channel: TextChannel | AnnouncementChannel | VoiceChannel | ForumChannel | MediaChannel];
interactionCreate: [interaction: Interaction];
@@ -5357,6 +5373,7 @@ export enum Events {
ThreadMembersUpdate = 'threadMembersUpdate',
UserUpdate = 'userUpdate',
PresenceUpdate = 'presenceUpdate',
+ VoiceChannelEffectSend = 'voiceChannelEffectSend',
VoiceServerUpdate = 'voiceServerUpdate',
VoiceStateUpdate = 'voiceStateUpdate',
TypingStart = 'typingStart',
From 3669d5e1120ed0a6e8d8cb8c48414d7841efd594 Mon Sep 17 00:00:00 2001
From: Jiralite <33201955+Jiralite@users.noreply.github.com>
Date: Fri, 15 Nov 2024 10:04:31 +0000
Subject: [PATCH 20/22] docs(channel): Clarify emoji parameter (#10595)
* docs(channel): clarify emoji parameter
* docs: actually add `@example`
* docs: clarify the kind of encoding
Co-Authored-By: Vlad Frangu
---------
Co-authored-by: Vlad Frangu
Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
---
packages/core/src/api/channel.ts | 50 ++++++++++++++++++++++++++++----
1 file changed, 45 insertions(+), 5 deletions(-)
diff --git a/packages/core/src/api/channel.ts b/packages/core/src/api/channel.ts
index a651c4ff430c..3ed52c0c51fe 100644
--- a/packages/core/src/api/channel.ts
+++ b/packages/core/src/api/channel.ts
@@ -92,9 +92,17 @@ export class ChannelsAPI {
* @see {@link https://discord.com/developers/docs/resources/message#get-reactions}
* @param channelId - The id of the channel the message is in
* @param messageId - The id of the message to get the reactions for
- * @param emoji - The emoji to get the reactions for
+ * @param emoji - The emoji to get the reactions for. URL encoding happens internally
* @param query - The query options for fetching the reactions
* @param options - The options for fetching the message reactions
+ * @example
+ * ```ts
+ * // Unicode.
+ * await api.channels.getMessageReactions('1234567890', '1234567890', '👍');
+ *
+ * // Custom emoji.
+ * await api.channels.getMessageReactions('1234567890', '1234567890', 'emoji_name:1234567890');
+ * ```
*/
public async getMessageReactions(
channelId: Snowflake,
@@ -115,8 +123,16 @@ export class ChannelsAPI {
* @see {@link https://discord.com/developers/docs/resources/message#delete-own-reaction}
* @param channelId - The id of the channel the message is in
* @param messageId - The id of the message to delete the reaction for
- * @param emoji - The emoji to delete the reaction for
+ * @param emoji - The emoji to delete the reaction for. URL encoding happens internally
* @param options - The options for deleting the reaction
+ * @example
+ * ```ts
+ * // Unicode.
+ * await api.channels.deleteOwnMessageReaction('1234567890', '1234567890', '👍');
+ *
+ * // Custom emoji.
+ * await api.channels.deleteOwnMessageReaction('1234567890', '1234567890', 'emoji_name:1234567890');
+ * ```
*/
public async deleteOwnMessageReaction(
channelId: Snowflake,
@@ -135,9 +151,17 @@ export class ChannelsAPI {
* @see {@link https://discord.com/developers/docs/resources/message#delete-user-reaction}
* @param channelId - The id of the channel the message is in
* @param messageId - The id of the message to delete the reaction for
- * @param emoji - The emoji to delete the reaction for
+ * @param emoji - The emoji to delete the reaction for. URL encoding happens internally
* @param userId - The id of the user to delete the reaction for
* @param options - The options for deleting the reaction
+ * @example
+ * ```ts
+ * // Unicode.
+ * await api.channels.deleteUserMessageReaction('1234567890', '1234567890', '👍', '1234567890');
+ *
+ * // Custom emoji.
+ * await api.channels.deleteUserMessageReaction('1234567890', '1234567890', 'emoji_name:1234567890', '1234567890');
+ * ```
*/
public async deleteUserMessageReaction(
channelId: Snowflake,
@@ -173,8 +197,16 @@ export class ChannelsAPI {
* @see {@link https://discord.com/developers/docs/resources/message#delete-all-reactions-for-emoji}
* @param channelId - The id of the channel the message is in
* @param messageId - The id of the message to delete the reactions for
- * @param emoji - The emoji to delete the reactions for
+ * @param emoji - The emoji to delete the reactions for. URL encoding happens internally
* @param options - The options for deleting the reactions
+ * @example
+ * ```ts
+ * // Unicode.
+ * await api.channels.deleteAllMessageReactionsForEmoji('1234567890', '1234567890', '👍');
+ *
+ * // Custom emoji.
+ * await api.channels.deleteAllMessageReactionsForEmoji('1234567890', '1234567890', 'emoji_name:1234567890');
+ * ```
*/
public async deleteAllMessageReactionsForEmoji(
channelId: Snowflake,
@@ -191,8 +223,16 @@ export class ChannelsAPI {
* @see {@link https://discord.com/developers/docs/resources/message#create-reaction}
* @param channelId - The id of the channel the message is in
* @param messageId - The id of the message to add the reaction to
- * @param emoji - The emoji to add the reaction with
+ * @param emoji - The emoji to add the reaction with. URL encoding happens internally
* @param options - The options for adding the reaction
+ * @example
+ * ```ts
+ * // Unicode.
+ * await api.channels.addMessageReaction('1234567890', '1234567890', '👍');
+ *
+ * // Custom emoji.
+ * await api.channels.addMessageReaction('1234567890', '1234567890', 'emoji_name:1234567890');
+ * ```
*/
public async addMessageReaction(
channelId: Snowflake,
From c45d912c98e3373d1f78ce4e10380e704eee1b45 Mon Sep 17 00:00:00 2001
From: Qjuh <76154676+Qjuh@users.noreply.github.com>
Date: Fri, 15 Nov 2024 15:28:06 +0100
Subject: [PATCH 21/22] refactor(GuildAuditLogsEntry)!: add type guard for
narrowing (#10521)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
BREAKING CHANGE: removed `GuildAuditLogsEntry.Targets.All` which wasn’t used anywhere
---------
Co-authored-by: Almeida
---
.../src/structures/GuildAuditLogsEntry.js | 10 ++++-
packages/discord.js/typings/index.d.ts | 38 +++++++++++--------
packages/discord.js/typings/index.test-d.ts | 6 +--
3 files changed, 34 insertions(+), 20 deletions(-)
diff --git a/packages/discord.js/src/structures/GuildAuditLogsEntry.js b/packages/discord.js/src/structures/GuildAuditLogsEntry.js
index 53c5b3d3fcd3..2d6430b42659 100644
--- a/packages/discord.js/src/structures/GuildAuditLogsEntry.js
+++ b/packages/discord.js/src/structures/GuildAuditLogsEntry.js
@@ -14,7 +14,6 @@ const Partials = require('../util/Partials');
const { flatten } = require('../util/Util');
const Targets = {
- All: 'All',
Guild: 'Guild',
GuildScheduledEvent: 'GuildScheduledEvent',
Channel: 'Channel',
@@ -503,6 +502,15 @@ class GuildAuditLogsEntry {
return new Date(this.createdTimestamp);
}
+ /**
+ * Checks whether this GuildAuditLogsEntry is of the specified {@link AuditLogEvent} type.
+ * @param {AuditLogEvent} action The type to check for
+ * @returns {boolean}
+ */
+ isAction(action) {
+ return this.action === action;
+ }
+
toJSON() {
return flatten(this, { createdTimestamp: true });
}
diff --git a/packages/discord.js/typings/index.d.ts b/packages/discord.js/typings/index.d.ts
index dc2aac43f714..8d30577c7262 100644
--- a/packages/discord.js/typings/index.d.ts
+++ b/packages/discord.js/typings/index.d.ts
@@ -1467,9 +1467,9 @@ export class Guild extends AnonymousGuild {
public editOnboarding(options: GuildOnboardingEditOptions): Promise;
public editWelcomeScreen(options: WelcomeScreenEditOptions): Promise;
public equals(guild: Guild): boolean;
- public fetchAuditLogs(
+ public fetchAuditLogs(
options?: GuildAuditLogsFetchOptions,
- ): Promise>;
+ ): Promise>;
public fetchIntegrations(): Promise>;
public fetchOnboarding(): Promise;
public fetchOwner(options?: BaseFetchOptions): Promise;
@@ -1515,7 +1515,7 @@ export class Guild extends AnonymousGuild {
public toJSON(): unknown;
}
-export class GuildAuditLogs {
+export class GuildAuditLogs {
private constructor(guild: Guild, data: RawGuildAuditLogData);
private applicationCommands: Collection;
private webhooks: Collection>;
@@ -1527,36 +1527,40 @@ export class GuildAuditLogs {
private constructor(guild: Guild, data: RawGuildAuditLogEntryData, logs?: GuildAuditLogs);
public static Targets: GuildAuditLogsTargets;
- public action: TResolvedType;
+ public action: TAction;
public actionType: TActionType;
public changes: AuditLogChange[];
public get createdAt(): Date;
public get createdTimestamp(): number;
public executorId: Snowflake | null;
public executor: User | null;
- public extra: TResolvedType extends keyof GuildAuditLogsEntryExtraField
- ? GuildAuditLogsEntryExtraField[TResolvedType]
- : null;
+ public extra: TAction extends keyof GuildAuditLogsEntryExtraField ? GuildAuditLogsEntryExtraField[TAction] : null;
public id: Snowflake;
public reason: string | null;
public targetId: Snowflake | null;
- public target: TTargetType extends keyof GuildAuditLogsEntryTargetField
- ? GuildAuditLogsEntryTargetField[TTargetType]
+ public target: TTargetType extends keyof GuildAuditLogsEntryTargetField
+ ? GuildAuditLogsEntryTargetField[TTargetType]
: Role | GuildEmoji | { id: Snowflake } | null;
public targetType: TTargetType;
public static actionType(action: AuditLogEvent): GuildAuditLogsActionType;
public static targetType(target: AuditLogEvent): GuildAuditLogsTargetType;
+ public isAction(
+ action: TCheckAction,
+ ): this is GuildAuditLogsEntry<
+ TCheckAction,
+ TCheckAction extends keyof GuildAuditLogsTypes ? GuildAuditLogsTypes[TCheckAction][1] : 'All',
+ TCheckAction extends keyof GuildAuditLogsTypes ? GuildAuditLogsTypes[TCheckAction][0] : 'Unknown'
+ >;
public toJSON(): unknown;
}
@@ -5726,12 +5730,14 @@ export interface GuildAuditLogsEntryExtraField {
};
}
-export interface GuildAuditLogsEntryTargetField {
+export interface GuildAuditLogsEntryTargetField {
User: User | null;
Guild: Guild;
Webhook: Webhook;
Invite: Invite;
- Message: TActionType extends AuditLogEvent.MessageBulkDelete ? Guild | { id: Snowflake } : User;
+ Emoji: GuildEmoji;
+ Role: Role;
+ Message: TAction extends AuditLogEvent.MessageBulkDelete ? Guild | { id: Snowflake } : User;
Integration: Integration;
Channel: NonThreadGuildBasedChannel | { id: Snowflake; [x: string]: unknown };
Thread: AnyThreadChannel | { id: Snowflake; [x: string]: unknown };
@@ -5753,7 +5759,7 @@ export interface GuildAuditLogsFetchOptions>>(
guild.fetchAuditLogs({ type: AuditLogEvent.IntegrationUpdate }),
);
-expectType>>(guild.fetchAuditLogs({ type: null }));
+expectType>>(guild.fetchAuditLogs({ type: null }));
expectType>>(guild.fetchAuditLogs());
expectType | undefined>>(
@@ -2144,10 +2144,10 @@ expectAssignable al.entries.first()),
);
-expectType | undefined>>(
+expectType | undefined>>(
guild.fetchAuditLogs({ type: null }).then(al => al.entries.first()),
);
-expectType | undefined>>(
+expectType | undefined>>(
guild.fetchAuditLogs().then(al => al.entries.first()),
);
From 51a017a14e0dfdac2a15990f88dc8182b75be6e8 Mon Sep 17 00:00:00 2001
From: Jiralite <33201955+Jiralite@users.noreply.github.com>
Date: Sun, 17 Nov 2024 12:18:46 +0000
Subject: [PATCH 22/22] test: Fix builder methods in type test (#10599)
* test: fix builder methods in type test
* test: remove unused import
---
packages/builders/__tests__/components/button.test.ts | 1 -
packages/builders/__tests__/types.test.ts | 4 ++--
2 files changed, 2 insertions(+), 3 deletions(-)
diff --git a/packages/builders/__tests__/components/button.test.ts b/packages/builders/__tests__/components/button.test.ts
index 7da9abe0fb42..9302a1e4e6e3 100644
--- a/packages/builders/__tests__/components/button.test.ts
+++ b/packages/builders/__tests__/components/button.test.ts
@@ -5,7 +5,6 @@ import {
type APIButtonComponentWithURL,
} from 'discord-api-types/v10';
import { describe, test, expect } from 'vitest';
-import { ButtonBuilder } from '../../src/components/button/Button.js';
import { PrimaryButtonBuilder, PremiumButtonBuilder, LinkButtonBuilder } from '../../src/index.js';
const longStr =
diff --git a/packages/builders/__tests__/types.test.ts b/packages/builders/__tests__/types.test.ts
index de94dbbda9b0..cac2e595a649 100644
--- a/packages/builders/__tests__/types.test.ts
+++ b/packages/builders/__tests__/types.test.ts
@@ -16,6 +16,6 @@ type BuilderPropsOnly = Pick<
}
>;
-expectTypeOf(getBuilder().addStringOption(getStringOption())).toMatchTypeOf();
+expectTypeOf(getBuilder().addStringOptions(getStringOption())).toMatchTypeOf();
-expectTypeOf(getBuilder().addSubcommand(getSubcommand())).toMatchTypeOf();
+expectTypeOf(getBuilder().addSubcommands(getSubcommand())).toMatchTypeOf();