mirror of
https://github.com/discordjs/discord.js.git
synced 2026-05-23 20:10:08 +00:00
Compare commits
80 Commits
@discordjs
...
@discordjs
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8702978057 | ||
|
|
c2b18d6d8b | ||
|
|
519aa3abe8 | ||
|
|
89c076c89e | ||
|
|
f224a07381 | ||
|
|
8e1e1be0c2 | ||
|
|
193a5e9e20 | ||
|
|
73c6bc2c36 | ||
|
|
b7f1ebc334 | ||
|
|
92aea94411 | ||
|
|
41dee5177d | ||
|
|
bbde371324 | ||
|
|
66b971899a | ||
|
|
43235d43fe | ||
|
|
31df3d21cd | ||
|
|
2663d76709 | ||
|
|
44a1e85847 | ||
|
|
d2e1924fa6 | ||
|
|
68dd260dee | ||
|
|
5e66f85f55 | ||
|
|
46060419a9 | ||
|
|
7c1b73cc69 | ||
|
|
95db597fc8 | ||
|
|
0047a49b73 | ||
|
|
32dff01f29 | ||
|
|
efa50fc3fa | ||
|
|
aa61c20ffd | ||
|
|
d48136bee1 | ||
|
|
46bf8f0146 | ||
|
|
7280d4e82e | ||
|
|
bd2914cc98 | ||
|
|
77804cfd55 | ||
|
|
8fea3ed978 | ||
|
|
05c63cd9a1 | ||
|
|
8d69b24b5c | ||
|
|
9baee4b2ce | ||
|
|
c986a99104 | ||
|
|
2b9e4cf9d0 | ||
|
|
1af2f4ed0e | ||
|
|
3fbfe9f1ae | ||
|
|
b901ff7c4c | ||
|
|
5f8915f6d1 | ||
|
|
ff42d7af72 | ||
|
|
0fdbabea98 | ||
|
|
e9944b3d2d | ||
|
|
2b9833cd36 | ||
|
|
7b2a2e3a15 | ||
|
|
6087088579 | ||
|
|
622acbcbf0 | ||
|
|
b2754d4a0e | ||
|
|
53cbb0e36d | ||
|
|
7ce6f2fc8a | ||
|
|
76042f0538 | ||
|
|
dedaa5d657 | ||
|
|
ed00a10e1f | ||
|
|
ae1deac2bf | ||
|
|
a367e2c8c9 | ||
|
|
7678f1176a | ||
|
|
4cca33d9b0 | ||
|
|
388783d7dd | ||
|
|
bda31284bf | ||
|
|
76968b4bc1 | ||
|
|
34343c6afa | ||
|
|
56c9396b71 | ||
|
|
21c283f964 | ||
|
|
13471fa1b7 | ||
|
|
b1ded63e42 | ||
|
|
565fc0192a | ||
|
|
33533b7284 | ||
|
|
be38f57926 | ||
|
|
f79ba52c7a | ||
|
|
72e0c99454 | ||
|
|
3d06c9d872 | ||
|
|
831aafa733 | ||
|
|
5faf074c14 | ||
|
|
297e959f48 | ||
|
|
1fc87a9698 | ||
|
|
366f7174d0 | ||
|
|
97c3237a70 | ||
|
|
c12217829b |
@@ -9,7 +9,9 @@
|
||||
<a href="https://www.npmjs.com/package/discord.js"><img src="https://img.shields.io/npm/v/discord.js.svg?maxAge=3600" alt="npm version" /></a>
|
||||
<a href="https://www.npmjs.com/package/discord.js"><img src="https://img.shields.io/npm/dt/discord.js.svg?maxAge=3600" alt="npm downloads" /></a>
|
||||
<a href="https://github.com/discordjs/discord.js/actions"><img src="https://github.com/discordjs/discord.js/actions/workflows/test.yml/badge.svg" alt="Tests status" /></a>
|
||||
<a href="https://codecov.io/gh/discordjs/discord.js" ><img src="https://codecov.io/gh/discordjs/discord.js/branch/main/graph/badge.svg?precision=2" alt="Code coverage" /></a>
|
||||
<a href="https://github.com/discordjs/discord.js/commits/main"><img src="https://img.shields.io/github/last-commit/discordjs/discord.js.svg?logo=github&logoColor=ffffff" alt="Last commit." /></a>
|
||||
<a href="https://github.com/discordjs/discord.js/graphs/contributors"><img src="https://img.shields.io/github/contributors/discordjs/discord.js.svg?maxAge=3600&logo=github&logoColor=fff&color=00c7be" alt="contributors" /></a>
|
||||
<a href="https://codecov.io/gh/discordjs/discord.js"><img src="https://codecov.io/gh/discordjs/discord.js/branch/main/graph/badge.svg?precision=2" alt="Code coverage" /></a>
|
||||
</p>
|
||||
<p>
|
||||
<a href="https://vercel.com/?utm_source=discordjs&utm_campaign=oss"><img src="https://raw.githubusercontent.com/discordjs/discord.js/main/.github/powered-by-vercel.svg" alt="Vercel" /></a>
|
||||
|
||||
@@ -18,8 +18,9 @@ export async function Badges({ node }: { readonly node: any }) {
|
||||
const isAbstract = node.isAbstract;
|
||||
const isReadonly = node.isReadonly;
|
||||
const isOptional = node.isOptional;
|
||||
const isExternal = node.isExternal;
|
||||
|
||||
const isAny = isDeprecated || isProtected || isStatic || isAbstract || isReadonly || isOptional;
|
||||
const isAny = isDeprecated || isProtected || isStatic || isAbstract || isReadonly || isOptional || isExternal;
|
||||
|
||||
return isAny ? (
|
||||
<div className="mb-1 flex gap-3">
|
||||
@@ -33,6 +34,7 @@ export async function Badges({ node }: { readonly node: any }) {
|
||||
{isAbstract ? <Badge className="bg-cyan-500/20 text-cyan-500">abstract</Badge> : null}
|
||||
{isReadonly ? <Badge className="bg-purple-500/20 text-purple-500">readonly</Badge> : null}
|
||||
{isOptional ? <Badge className="bg-cyan-500/20 text-cyan-500">optional</Badge> : null}
|
||||
{isExternal ? <Badge className="bg-purple-500/20 text-purple-500">external</Badge> : null}
|
||||
</div>
|
||||
) : null;
|
||||
}
|
||||
|
||||
@@ -29,6 +29,7 @@ export async function ParameterNode({
|
||||
{description ? <Badges node={parameter} /> : null}
|
||||
{parameter.name}
|
||||
{parameter.isOptional ? '?' : ''}: <ExcerptNode node={parameter.typeExcerpt} version={version} />
|
||||
{parameter.defaultValue ? ` = ${parameter.defaultValue}` : ''}
|
||||
</span>
|
||||
{description && parameter.description?.length ? (
|
||||
<div className="mt-4 pl-4">
|
||||
|
||||
@@ -51,7 +51,13 @@ export async function PropertyNode({
|
||||
<LinkIcon aria-hidden size={16} />
|
||||
</Link>
|
||||
{property.displayName}
|
||||
{property.isOptional ? '?' : ''} : <ExcerptNode node={property.typeExcerpt} version={version} />
|
||||
{property.isOptional ? '?' : ''} : <ExcerptNode node={property.typeExcerpt} version={version} />{' '}
|
||||
{property.summary?.defaultValueBlock.length
|
||||
? `= ${property.summary.defaultValueBlock.reduce(
|
||||
(acc: string, def: { kind: string; text: string }) => `${acc}${def.text}`,
|
||||
'',
|
||||
)}`
|
||||
: ''}
|
||||
</span>
|
||||
</h3>
|
||||
|
||||
|
||||
14
package.json
14
package.json
@@ -6,19 +6,19 @@
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"build": "turbo run build --concurrency=4",
|
||||
"build:affected": "turbo run build --filter=...[origin/main] --concurrency=4",
|
||||
"build:affected": "turbo run build --filter=...[origin/v14] --concurrency=4",
|
||||
"build:apps": "turbo run build:local --filter=...{apps/*} --concurrency=4",
|
||||
"build:apps:affected": "turbo run build:local --filter=...{apps/*}[origin/main] --concurrency=4",
|
||||
"build:apps:affected": "turbo run build:local --filter=...{apps/*}[origin/v14] --concurrency=4",
|
||||
"test": "turbo run test --concurrency=4",
|
||||
"test:affected": "turbo run test --filter=...[origin/main] --concurrency=4",
|
||||
"test:affected": "turbo run test --filter=...[origin/v14] --concurrency=4",
|
||||
"lint": "turbo run lint --concurrency=4",
|
||||
"lint:affected": "turbo run lint --filter=...[origin/main] --concurrency=4",
|
||||
"lint:affected": "turbo run lint --filter=...[origin/v14] --concurrency=4",
|
||||
"format": "turbo run format --concurrency=4",
|
||||
"format:affected": "turbo run format --filter=...[origin/main] --concurrency=4",
|
||||
"format:affected": "turbo run format --filter=...[origin/v14] --concurrency=4",
|
||||
"fmt": "turbo run format --concurrency=4",
|
||||
"fmt:affected": "turbo run format --filter=...[origin/main] --concurrency=4",
|
||||
"fmt:affected": "turbo run format --filter=...[origin/v14] --concurrency=4",
|
||||
"docs": "turbo run docs --concurrency=4",
|
||||
"docs:affected": "turbo run docs --filter=...[origin/main] --concurrency=4",
|
||||
"docs:affected": "turbo run docs --filter=...[origin/v14] --concurrency=4",
|
||||
"prepare": "is-ci || husky",
|
||||
"update": "pnpm --recursive update --interactive",
|
||||
"update:latest": "pnpm --recursive update --interactive --latest",
|
||||
|
||||
@@ -49,7 +49,7 @@
|
||||
"meilisearch": "^0.38.0",
|
||||
"p-limit": "^6.1.0",
|
||||
"tslib": "^2.6.3",
|
||||
"undici": "6.19.8"
|
||||
"undici": "6.21.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^18.19.45",
|
||||
|
||||
@@ -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<TBaseClass extends IApiItemConstructor>(
|
||||
isOptional: Boolean(parameterOptions.isOptional),
|
||||
isRest: Boolean(parameterOptions.isRest),
|
||||
parent: this,
|
||||
defaultValue: parameterOptions.defaultValue,
|
||||
});
|
||||
|
||||
this[_parameters].push(parameter);
|
||||
@@ -171,6 +173,7 @@ export function ApiParameterListMixin<TBaseClass extends IApiItemConstructor>(
|
||||
parameterTypeTokenRange: parameter.parameterTypeExcerpt.tokenRange,
|
||||
isOptional: parameter.isOptional,
|
||||
isRest: parameter.isRest,
|
||||
defaultValue: parameter.defaultValue,
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -41,6 +41,7 @@ const MinifyJSONMapping = {
|
||||
constraintTokenRange: 'ctr',
|
||||
dependencies: 'dp',
|
||||
defaultTypeTokenRange: 'dtr',
|
||||
defaultValue: 'dv',
|
||||
docComment: 'd',
|
||||
endIndex: 'en',
|
||||
excerptTokens: 'ex',
|
||||
|
||||
@@ -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,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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<ts.ParameterDeclaration>,
|
||||
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(/(?<char>[{}])/g, '\\$<char>');
|
||||
return input.replaceAll(/(?<char>[@{}])/g, '\\$<char>');
|
||||
}
|
||||
|
||||
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] ?? []);
|
||||
|
||||
@@ -9,7 +9,8 @@
|
||||
<a href="https://www.npmjs.com/package/@discordjs/brokers"><img src="https://img.shields.io/npm/v/@discordjs/brokers.svg?maxAge=3600" alt="npm version" /></a>
|
||||
<a href="https://www.npmjs.com/package/@discordjs/brokers"><img src="https://img.shields.io/npm/dt/@discordjs/brokers.svg?maxAge=3600" alt="npm downloads" /></a>
|
||||
<a href="https://github.com/discordjs/discord.js/actions"><img src="https://github.com/discordjs/discord.js/actions/workflows/test.yml/badge.svg" alt="Build status" /></a>
|
||||
<a href="https://codecov.io/gh/discordjs/discord.js" ><img src="https://codecov.io/gh/discordjs/discord.js/branch/main/graph/badge.svg?precision=2&flag=brokers" alt="Code coverage" /></a>
|
||||
<a href="https://github.com/discordjs/discord.js/commits/main/packages/brokers"><img alt="Last commit." src="https://img.shields.io/github/last-commit/discordjs/discord.js?logo=github&logoColor=ffffff&path=packages%2Fbrokers"></a>
|
||||
<a href="https://codecov.io/gh/discordjs/discord.js"><img src="https://codecov.io/gh/discordjs/discord.js/branch/main/graph/badge.svg?precision=2&flag=brokers" alt="Code coverage" /></a>
|
||||
</p>
|
||||
<p>
|
||||
<a href="https://vercel.com/?utm_source=discordjs&utm_campaign=oss"><img src="https://raw.githubusercontent.com/discordjs/discord.js/main/.github/powered-by-vercel.svg" alt="Vercel" /></a>
|
||||
|
||||
@@ -9,7 +9,8 @@
|
||||
<a href="https://www.npmjs.com/package/@discordjs/builders"><img src="https://img.shields.io/npm/v/@discordjs/builders.svg?maxAge=3600" alt="npm version" /></a>
|
||||
<a href="https://www.npmjs.com/package/@discordjs/builders"><img src="https://img.shields.io/npm/dt/@discordjs/builders.svg?maxAge=3600" alt="npm downloads" /></a>
|
||||
<a href="https://github.com/discordjs/discord.js/actions"><img src="https://github.com/discordjs/discord.js/actions/workflows/test.yml/badge.svg" alt="Build status" /></a>
|
||||
<a href="https://codecov.io/gh/discordjs/discord.js" ><img src="https://codecov.io/gh/discordjs/discord.js/branch/main/graph/badge.svg?precision=2&flag=builders" alt="Code coverage" /></a>
|
||||
<a href="https://github.com/discordjs/discord.js/commits/main/packages/builders"><img alt="Last commit." src="https://img.shields.io/github/last-commit/discordjs/discord.js?logo=github&logoColor=ffffff&path=packages%2Fbuilders"></a>
|
||||
<a href="https://codecov.io/gh/discordjs/discord.js"><img src="https://codecov.io/gh/discordjs/discord.js/branch/main/graph/badge.svg?precision=2&flag=builders" alt="Code coverage" /></a>
|
||||
</p>
|
||||
<p>
|
||||
<a href="https://vercel.com/?utm_source=discordjs&utm_campaign=oss"><img src="https://raw.githubusercontent.com/discordjs/discord.js/main/.github/powered-by-vercel.svg" alt="Vercel" /></a>
|
||||
|
||||
@@ -166,7 +166,7 @@ describe('Context Menu Commands', () => {
|
||||
});
|
||||
|
||||
describe('integration types', () => {
|
||||
test('GIVEN a builder with valid integraton types THEN does not throw an error', () => {
|
||||
test('GIVEN a builder with valid integration types THEN does not throw an error', () => {
|
||||
expect(() =>
|
||||
getBuilder().setIntegrationTypes([
|
||||
ApplicationIntegrationType.GuildInstall,
|
||||
|
||||
@@ -68,7 +68,7 @@
|
||||
"@discordjs/formatters": "workspace:^",
|
||||
"@discordjs/util": "workspace:^",
|
||||
"@sapphire/shapeshift": "^4.0.0",
|
||||
"discord-api-types": "0.37.100",
|
||||
"discord-api-types": "^0.37.119",
|
||||
"fast-deep-equal": "^3.1.3",
|
||||
"ts-mixer": "^6.0.4",
|
||||
"tslib": "^2.6.3"
|
||||
|
||||
@@ -9,7 +9,8 @@
|
||||
<a href="https://www.npmjs.com/package/@discordjs/collection"><img src="https://img.shields.io/npm/v/@discordjs/collection.svg?maxAge=3600" alt="npm version" /></a>
|
||||
<a href="https://www.npmjs.com/package/@discordjs/collection"><img src="https://img.shields.io/npm/dt/@discordjs/collection.svg?maxAge=3600" alt="npm downloads" /></a>
|
||||
<a href="https://github.com/discordjs/discord.js/actions"><img src="https://github.com/discordjs/discord.js/actions/workflows/test.yml/badge.svg" alt="Build status" /></a>
|
||||
<a href="https://codecov.io/gh/discordjs/discord.js" ><img src="https://codecov.io/gh/discordjs/discord.js/branch/main/graph/badge.svg?precision=2&flag=collection" alt="Code coverage" /></a>
|
||||
<a href="https://github.com/discordjs/discord.js/commits/main/packages/collection"><img alt="Last commit." src="https://img.shields.io/github/last-commit/discordjs/discord.js?logo=github&logoColor=ffffff&path=packages%2Fcollection"></a>
|
||||
<a href="https://codecov.io/gh/discordjs/discord.js"><img src="https://codecov.io/gh/discordjs/discord.js/branch/main/graph/badge.svg?precision=2&flag=collection" alt="Code coverage" /></a>
|
||||
</p>
|
||||
<p>
|
||||
<a href="https://vercel.com/?utm_source=discordjs&utm_campaign=oss"><img src="https://raw.githubusercontent.com/discordjs/discord.js/main/.github/powered-by-vercel.svg" alt="Vercel" /></a>
|
||||
|
||||
@@ -9,7 +9,8 @@
|
||||
<a href="https://www.npmjs.com/package/@discordjs/core"><img src="https://img.shields.io/npm/v/@discordjs/core.svg?maxAge=3600" alt="npm version" /></a>
|
||||
<a href="https://www.npmjs.com/package/@discordjs/core"><img src="https://img.shields.io/npm/dt/@discordjs/core.svg?maxAge=3600" alt="npm downloads" /></a>
|
||||
<a href="https://github.com/discordjs/discord.js/actions"><img src="https://github.com/discordjs/discord.js/actions/workflows/test.yml/badge.svg" alt="Build status" /></a>
|
||||
<a href="https://codecov.io/gh/discordjs/discord.js" ><img src="https://codecov.io/gh/discordjs/discord.js/branch/main/graph/badge.svg?precision=2&flag=core" alt="Code coverage" /></a>
|
||||
<a href="https://github.com/discordjs/discord.js/commits/main/packages/core"><img alt="Last commit." src="https://img.shields.io/github/last-commit/discordjs/discord.js?logo=github&logoColor=ffffff&path=packages%2Fcore"></a>
|
||||
<a href="https://codecov.io/gh/discordjs/discord.js"><img src="https://codecov.io/gh/discordjs/discord.js/branch/main/graph/badge.svg?precision=2&flag=core" alt="Code coverage" /></a>
|
||||
</p>
|
||||
<p>
|
||||
<a href="https://vercel.com/?utm_source=discordjs&utm_campaign=oss"><img src="https://raw.githubusercontent.com/discordjs/discord.js/main/.github/powered-by-vercel.svg" alt="Vercel" /></a>
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
{
|
||||
"extends": "../../api-extractor.json",
|
||||
"bundledPackages": ["discord-api-types"],
|
||||
"docModel": {
|
||||
"projectFolderUrl": "https://github.com/discordjs/discord.js/tree/main/packages/core"
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"$schema": "https://json.schemastore.org/package.json",
|
||||
"name": "@discordjs/core",
|
||||
"version": "2.0.0",
|
||||
"version": "2.0.1",
|
||||
"description": "A thinly abstracted wrapper around the rest API, and gateway.",
|
||||
"scripts": {
|
||||
"test": "vitest run",
|
||||
@@ -70,7 +70,7 @@
|
||||
"@discordjs/ws": "workspace:^",
|
||||
"@sapphire/snowflake": "^3.5.3",
|
||||
"@vladfrangu/async_event_emitter": "^2.4.6",
|
||||
"discord-api-types": "0.37.100"
|
||||
"discord-api-types": "^0.37.119"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@discordjs/api-extractor": "workspace:^",
|
||||
|
||||
@@ -258,7 +258,7 @@ export class InteractionsAPI {
|
||||
* @param interactionId - The id of the interaction
|
||||
* @param interactionToken - The token of the interaction
|
||||
* @param options - The options for sending the premium required response
|
||||
* @deprecated Sending a premium-style button is the new Discord behaviour.
|
||||
* @deprecated Sending a premium-style button is the new Discord behavior.
|
||||
*/
|
||||
public async sendPremiumRequired(
|
||||
interactionId: Snowflake,
|
||||
|
||||
@@ -196,7 +196,6 @@ export class Client extends AsyncEventEmitter<MappedEvents> {
|
||||
this.api = new API(rest);
|
||||
|
||||
this.gateway.on(WebSocketShardEvents.Dispatch, (dispatch, shardId) => {
|
||||
// @ts-expect-error event props can't be resolved properly, but they are correct
|
||||
this.emit(dispatch.t, this.toEventProps(dispatch.d, shardId));
|
||||
});
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
<p>
|
||||
<a href="https://discord.gg/djs"><img src="https://img.shields.io/discord/222078108977594368?color=5865F2&logo=discord&logoColor=white" alt="Discord server" /></a>
|
||||
<a href="https://github.com/discordjs/discord.js/actions"><img src="https://github.com/discordjs/discord.js/actions/workflows/test.yml/badge.svg" alt="Build status" /></a>
|
||||
<a href="https://github.com/discordjs/discord.js/commits/main/packages/create-discord-bot"><img alt="Last commit." src="https://img.shields.io/github/last-commit/discordjs/discord.js?logo=github&logoColor=ffffff&path=packages%2Fcreate-discord-bot"></a>
|
||||
</p>
|
||||
<p>
|
||||
<a href="https://vercel.com/?utm_source=discordjs&utm_campaign=oss"><img src="https://raw.githubusercontent.com/discordjs/discord.js/main/.github/powered-by-vercel.svg" alt="Vercel" /></a>
|
||||
|
||||
@@ -83,7 +83,7 @@
|
||||
"no-void": "error",
|
||||
"no-warning-comments": "warn",
|
||||
"prefer-promise-reject-errors": "error",
|
||||
"require-await": "warn",
|
||||
"require-await": "off",
|
||||
"wrap-iife": "error",
|
||||
"yoda": "error",
|
||||
|
||||
|
||||
@@ -2,6 +2,72 @@
|
||||
|
||||
All notable changes to this project will be documented in this file.
|
||||
|
||||
# [14.17.3](https://github.com/discordjs/discord.js/compare/14.17.2...14.17.3) - (2025-01-08)
|
||||
|
||||
## Bug Fixes
|
||||
|
||||
- **Message:** Ensure channel is defined for clean content (#10681) ([46bf8f0](https://github.com/discordjs/discord.js/commit/46bf8f0146b67d7c480a3512ade1edbfb16e7a26))
|
||||
- Use `resolve()` for `PermissionOverwrites` (#10686) ([7280d4e](https://github.com/discordjs/discord.js/commit/7280d4e82eb47ce7cb3964057d7d56a62179cf18))
|
||||
|
||||
# [14.17.2](https://github.com/discordjs/discord.js/compare/14.17.1...14.17.2) - (2025-01-02)
|
||||
|
||||
## Bug Fixes
|
||||
|
||||
- **InteractionResponses:** Check correct property for deprecation ([77804cf](https://github.com/discordjs/discord.js/commit/77804cfd559691d9b8c85aec8c494cd6c14c4ea7))
|
||||
|
||||
# [14.17.0](https://github.com/discordjs/discord.js/compare/14.16.3...14.17.0) - (2025-01-01)
|
||||
|
||||
## Bug Fixes
|
||||
|
||||
- **InteractionResponses:** Do not use `in` if a string is passed ([ff42d7a](https://github.com/discordjs/discord.js/commit/ff42d7af72e940ae72c61d2c5164ae68f2708b96))
|
||||
- Use Message#interactionMetadata (#10654) ([6087088](https://github.com/discordjs/discord.js/commit/60870885790eb1857ed4c2969c9c404e356a1299))
|
||||
- **InteractionResponses:** Properly resolve message flags (#10661) ([b2754d4](https://github.com/discordjs/discord.js/commit/b2754d4a0ec250ae84057d0f07c078376f54829c))
|
||||
- **ThreadChannel:** Make `ownerId` always present (#10618) ([7678f11](https://github.com/discordjs/discord.js/commit/7678f1176a645878261361faef0429f9cf7f4810))
|
||||
- **MessageReaction:** Address `undefined` burst properties (#10597) ([76968b4](https://github.com/discordjs/discord.js/commit/76968b4bc14b8a66825f9140d130b1e04c11855a))
|
||||
- **ThreadChannel:** Address parameter type on fetchOwner() (#10592) ([56c9396](https://github.com/discordjs/discord.js/commit/56c9396b717d4dec2410ca13938ce238ec21215d))
|
||||
- **InteractionResponses:** Throw error on deleting response of unacknowledged interaction (#10587) ([21c283f](https://github.com/discordjs/discord.js/commit/21c283f964ab9e331db53cc0c21ca64980372488))
|
||||
- **GuildScheduledEvent:** Handle null recurrence_rule (#10543) ([831aafa](https://github.com/discordjs/discord.js/commit/831aafa733e8eea55534c4c39b87775d2e2f56c4))
|
||||
|
||||
## Documentation
|
||||
|
||||
- Correct discord-api-types URLs (#10622) ([76042f0](https://github.com/discordjs/discord.js/commit/76042f05386edcbadc5ad4ded22e8b15c7b6f8ec))
|
||||
- Typos (#10628) ([388783d](https://github.com/discordjs/discord.js/commit/388783d7dd718aae519801b90aa781d07b7fb64e))
|
||||
- Add note about idempotence to role add/remove routes (#10586) ([565fc01](https://github.com/discordjs/discord.js/commit/565fc0192a5ed2642ff1bd615c59678b5c3cd24b))
|
||||
- **Client:** Fix incorrect managers descriptions ([f79ba52](https://github.com/discordjs/discord.js/commit/f79ba52c7a1334d987e9873a8a411e92d5140116))
|
||||
- **discord.js:** Remove `utf-8-validate` (#10531) ([297e959](https://github.com/discordjs/discord.js/commit/297e959f48abbfd3af58cc29cdcef139d3579821))
|
||||
|
||||
## Features
|
||||
|
||||
- **ClientApplication:** Add webhook events (#10588) ([7b2a2e3](https://github.com/discordjs/discord.js/commit/7b2a2e3a154afd69ff892da615ea75c46730f226))
|
||||
- **InteractionResponses:** Support `with_response` query parameter (#10636) ([622acbc](https://github.com/discordjs/discord.js/commit/622acbcbf02c3b8e0eae4296964c3e745e19378d))
|
||||
- **ClientApplication:** Add webhook events (#10588) ([ae1deac](https://github.com/discordjs/discord.js/commit/ae1deac2bf37aecda4c044bf5c28d03930bd763b))
|
||||
- **EntitlementManager:** Support get entitlement (#10606) ([a367e2c](https://github.com/discordjs/discord.js/commit/a367e2c8c99ab3bfb83cdbfb65e7a5020b50b7f7))
|
||||
- Add subscriptions (#10541) ([4cca33d](https://github.com/discordjs/discord.js/commit/4cca33d9b0759294c9a2dfec39d80a24a2cc1595))
|
||||
- Emit reaction type on gateway events (#10598) ([bda3128](https://github.com/discordjs/discord.js/commit/bda31284bf46515747e002e86ea35d0b6910e269))
|
||||
- Voice Channel Effect Send (#10318) ([34343c6](https://github.com/discordjs/discord.js/commit/34343c6afae65205d3b17b60fdd202d0937d6a46))
|
||||
- **GuildMember:** Banners (#10384) ([b1ded63](https://github.com/discordjs/discord.js/commit/b1ded63e42e7349f535df4680509b9393dd8f288))
|
||||
- Add ApplicationEmoji to EmojiResolvable and MessageReaction#emoji (#10477) ([1fc87a9](https://github.com/discordjs/discord.js/commit/1fc87a96987fe69722502d7574500926a4e0bfde))
|
||||
- Recurring scheduled events (#10447) ([97c3237](https://github.com/discordjs/discord.js/commit/97c3237a70027f71bb3f046357a55bb730daca14))
|
||||
- Message forwarding (#10464) ([c122178](https://github.com/discordjs/discord.js/commit/c12217829b46f7a60266f65af4af19cdbfcd7906))
|
||||
|
||||
## Refactor
|
||||
|
||||
- **FetchApplicationCommandOptions:** Use `Locale` over `LocaleString` (#10625) ([7ce6f2f](https://github.com/discordjs/discord.js/commit/7ce6f2fc8a8756532d71a542186d10a0aa951471))
|
||||
- Use `cache.get()` for snowflakes, `resolve()` otherwise (#10626) ([dedaa5d](https://github.com/discordjs/discord.js/commit/dedaa5d657f15491910ec05102ce72affc822b97))
|
||||
- Remove extra traversing (#10580) ([33533b7](https://github.com/discordjs/discord.js/commit/33533b72849d9741dae8c979734b45abbf3657a7))
|
||||
- **InteractionResponses:** Deprecate ephemeral response option (#10574) ([be38f57](https://github.com/discordjs/discord.js/commit/be38f5792602ed1a79a9638aa8e629e7ad6bdd0d))
|
||||
- Deprecate `reason` parameter on adding and removing thread members (#10551) ([72e0c99](https://github.com/discordjs/discord.js/commit/72e0c994547f2a9c99b320870e14d7f1643f3851))
|
||||
- Deprecate fetching user flags (#10550) ([3d06c9d](https://github.com/discordjs/discord.js/commit/3d06c9d872b2e79356f1239f7d0eb0577a4bcedf))
|
||||
|
||||
## Testing
|
||||
|
||||
- Remove unused test (#10638) ([53cbb0e](https://github.com/discordjs/discord.js/commit/53cbb0e36d4ab191cbc15a022d752da14c2e0ace))
|
||||
|
||||
## Typings
|
||||
|
||||
- Add missing `Caches` managers (#10540) ([13471fa](https://github.com/discordjs/discord.js/commit/13471fa1b7c44b236db9fe9b1a64dacd41b14b76))
|
||||
- Remove newMessage partial on messageUpdate event typing (#10526) ([5faf074](https://github.com/discordjs/discord.js/commit/5faf074c145044f0edefafab97fd07a8dfb8bc30))
|
||||
|
||||
# [14.16.3](https://github.com/discordjs/discord.js/compare/14.16.2...14.16.3) - (2024-09-29)
|
||||
|
||||
## Bug Fixes
|
||||
|
||||
@@ -9,7 +9,8 @@
|
||||
<a href="https://www.npmjs.com/package/discord.js"><img src="https://img.shields.io/npm/v/discord.js.svg?maxAge=3600" alt="npm version" /></a>
|
||||
<a href="https://www.npmjs.com/package/discord.js"><img src="https://img.shields.io/npm/dt/discord.js.svg?maxAge=3600" alt="npm downloads" /></a>
|
||||
<a href="https://github.com/discordjs/discord.js/actions"><img src="https://github.com/discordjs/discord.js/actions/workflows/test.yml/badge.svg" alt="Tests status" /></a>
|
||||
<a href="https://codecov.io/gh/discordjs/discord.js" ><img src="https://codecov.io/gh/discordjs/discord.js/branch/main/graph/badge.svg?precision=2" alt="Code coverage" /></a>
|
||||
<a href="https://github.com/discordjs/discord.js/commits/main/packages/discord.js"><img alt="Last commit." src="https://img.shields.io/github/last-commit/discordjs/discord.js?logo=github&logoColor=ffffff&path=packages%2Fdiscord.js"></a>
|
||||
<a href="https://codecov.io/gh/discordjs/discord.js"><img src="https://codecov.io/gh/discordjs/discord.js/branch/main/graph/badge.svg?precision=2" alt="Code coverage" /></a>
|
||||
</p>
|
||||
<p>
|
||||
<a href="https://vercel.com/?utm_source=discordjs&utm_campaign=oss"><img src="https://raw.githubusercontent.com/discordjs/discord.js/main/.github/powered-by-vercel.svg" alt="Vercel" /></a>
|
||||
@@ -42,7 +43,6 @@ bun add discord.js
|
||||
|
||||
- [zlib-sync](https://www.npmjs.com/package/zlib-sync) for WebSocket data compression and inflation (`npm install zlib-sync`)
|
||||
- [bufferutil](https://www.npmjs.com/package/bufferutil) for a much faster WebSocket connection (`npm install bufferutil`)
|
||||
- [utf-8-validate](https://www.npmjs.com/package/utf-8-validate) in combination with `bufferutil` for much faster WebSocket processing (`npm install utf-8-validate`)
|
||||
- [@discordjs/voice](https://www.npmjs.com/package/@discordjs/voice) for interacting with the Discord Voice API (`npm install @discordjs/voice`)
|
||||
|
||||
## Example usage
|
||||
|
||||
@@ -1,6 +1,14 @@
|
||||
{
|
||||
"extends": "../../api-extractor.json",
|
||||
"mainEntryPointFilePath": "<projectFolder>/typings/index.d.ts",
|
||||
"bundledPackages": [
|
||||
"discord-api-types",
|
||||
"@discordjs/builders",
|
||||
"@discordjs/formatters",
|
||||
"@discordjs/rest",
|
||||
"@discordjs/util",
|
||||
"@discordjs/ws"
|
||||
],
|
||||
"docModel": {
|
||||
"projectFolderUrl": "https://github.com/discordjs/discord.js/tree/main/packages/discord.js"
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"$schema": "https://json.schemastore.org/package.json",
|
||||
"name": "discord.js",
|
||||
"version": "14.16.3",
|
||||
"version": "14.17.3",
|
||||
"description": "A powerful library for interacting with the Discord API",
|
||||
"scripts": {
|
||||
"test": "pnpm run docs:test && pnpm run test:typescript",
|
||||
@@ -65,18 +65,18 @@
|
||||
"homepage": "https://discord.js.org",
|
||||
"funding": "https://github.com/discordjs/discord.js?sponsor",
|
||||
"dependencies": {
|
||||
"@discordjs/builders": "^1.9.0",
|
||||
"@discordjs/builders": "^1.10.0",
|
||||
"@discordjs/collection": "1.5.3",
|
||||
"@discordjs/formatters": "workspace:^",
|
||||
"@discordjs/formatters": "^0.6.0",
|
||||
"@discordjs/rest": "workspace:^",
|
||||
"@discordjs/util": "workspace:^",
|
||||
"@discordjs/ws": "1.1.1",
|
||||
"@discordjs/ws": "^1.2.0",
|
||||
"@sapphire/snowflake": "3.5.3",
|
||||
"discord-api-types": "0.37.100",
|
||||
"discord-api-types": "^0.37.119",
|
||||
"fast-deep-equal": "3.1.3",
|
||||
"lodash.snakecase": "4.1.1",
|
||||
"tslib": "^2.6.3",
|
||||
"undici": "6.19.8"
|
||||
"undici": "6.21.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@discordjs/api-extractor": "workspace:^",
|
||||
|
||||
@@ -107,20 +107,20 @@ class Client extends BaseClient {
|
||||
: null;
|
||||
|
||||
/**
|
||||
* All of the {@link User} objects that have been cached at any point, mapped by their ids
|
||||
* The user manager of this client
|
||||
* @type {UserManager}
|
||||
*/
|
||||
this.users = new UserManager(this);
|
||||
|
||||
/**
|
||||
* All of the guilds the client is currently handling, mapped by their ids -
|
||||
* A manager of all the guilds the client is currently handling -
|
||||
* as long as sharding isn't being used, this will be *every* guild the bot is a member of
|
||||
* @type {GuildManager}
|
||||
*/
|
||||
this.guilds = new GuildManager(this);
|
||||
|
||||
/**
|
||||
* All of the {@link BaseChannel}s that the client is currently handling, mapped by their ids -
|
||||
* All of the {@link BaseChannel}s that the client is currently handling -
|
||||
* as long as sharding isn't being used, this will be *every* channel in *every* guild the bot
|
||||
* is a member of. Note that DM channels will not be initially cached, and thus not be present
|
||||
* in the Manager without their explicit fetching or use.
|
||||
@@ -174,7 +174,7 @@ class Client extends BaseClient {
|
||||
}
|
||||
|
||||
/**
|
||||
* All custom emojis that the client has access to, mapped by their ids
|
||||
* A manager of all the custom emojis that the client has access to
|
||||
* @type {BaseGuildEmojiManager}
|
||||
* @readonly
|
||||
*/
|
||||
|
||||
@@ -51,6 +51,7 @@ class MessageReactionAdd extends Action {
|
||||
/**
|
||||
* Provides additional information about altered reaction
|
||||
* @typedef {Object} MessageReactionEventDetails
|
||||
* @property {ReactionType} type The type of the reaction
|
||||
* @property {boolean} burst Determines whether a super reaction was used
|
||||
*/
|
||||
/**
|
||||
@@ -60,7 +61,7 @@ class MessageReactionAdd extends Action {
|
||||
* @param {User} user The user that applied the guild or reaction emoji
|
||||
* @param {MessageReactionEventDetails} details Details of adding the reaction
|
||||
*/
|
||||
this.client.emit(Events.MessageReactionAdd, reaction, user, { burst: data.burst });
|
||||
this.client.emit(Events.MessageReactionAdd, reaction, user, { type: data.type, burst: data.burst });
|
||||
|
||||
return { message, reaction, user };
|
||||
}
|
||||
|
||||
@@ -41,7 +41,7 @@ class MessageReactionRemove extends Action {
|
||||
* @param {User} user The user whose emoji or reaction emoji was removed
|
||||
* @param {MessageReactionEventDetails} details Details of removing the reaction
|
||||
*/
|
||||
this.client.emit(Events.MessageReactionRemove, reaction, user, { burst: data.burst });
|
||||
this.client.emit(Events.MessageReactionRemove, reaction, user, { type: data.type, burst: data.burst });
|
||||
|
||||
return { message, reaction, user };
|
||||
}
|
||||
|
||||
@@ -2,11 +2,14 @@
|
||||
|
||||
const Action = require('./Action');
|
||||
const Events = require('../../util/Events');
|
||||
const Partials = require('../../util/Partials');
|
||||
|
||||
class PresenceUpdateAction extends Action {
|
||||
handle(data) {
|
||||
let user = this.client.users.cache.get(data.user.id);
|
||||
if (!user && data.user.username) user = this.client.users._add(data.user);
|
||||
if (!user && ('username' in data.user || this.client.options.partials.includes(Partials.User))) {
|
||||
user = this.client.users._add(data.user);
|
||||
}
|
||||
if (!user) return;
|
||||
|
||||
if (data.user.username) {
|
||||
|
||||
@@ -13,7 +13,7 @@ class ThreadListSyncAction extends Action {
|
||||
|
||||
if (data.channel_ids) {
|
||||
for (const id of data.channel_ids) {
|
||||
const channel = client.channels.resolve(id);
|
||||
const channel = client.channels.cache.get(id);
|
||||
if (channel) this.removeStale(channel);
|
||||
}
|
||||
} else {
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
'use strict';
|
||||
|
||||
const Events = require('../../../util/Events');
|
||||
|
||||
module.exports = (client, { d: data }) => {
|
||||
const subscription = client.application.subscriptions._add(data);
|
||||
|
||||
/**
|
||||
* Emitted whenever a subscription is created.
|
||||
* @event Client#subscriptionCreate
|
||||
* @param {Subscription} subscription The subscription that was created
|
||||
*/
|
||||
client.emit(Events.SubscriptionCreate, subscription);
|
||||
};
|
||||
@@ -0,0 +1,16 @@
|
||||
'use strict';
|
||||
|
||||
const Events = require('../../../util/Events');
|
||||
|
||||
module.exports = (client, { d: data }) => {
|
||||
const subscription = client.application.subscriptions._add(data, false);
|
||||
|
||||
client.application.subscriptions.cache.delete(subscription.id);
|
||||
|
||||
/**
|
||||
* Emitted whenever a subscription is deleted.
|
||||
* @event Client#subscriptionDelete
|
||||
* @param {Subscription} subscription The subscription that was deleted
|
||||
*/
|
||||
client.emit(Events.SubscriptionDelete, subscription);
|
||||
};
|
||||
@@ -0,0 +1,16 @@
|
||||
'use strict';
|
||||
|
||||
const Events = require('../../../util/Events');
|
||||
|
||||
module.exports = (client, { d: data }) => {
|
||||
const oldSubscription = client.application.subscriptions.cache.get(data.id)?._clone() ?? null;
|
||||
const newSubscription = client.application.subscriptions._add(data);
|
||||
|
||||
/**
|
||||
* Emitted whenever a subscription is updated - i.e. when a user's subscription renews.
|
||||
* @event Client#subscriptionUpdate
|
||||
* @param {?Subscription} oldSubscription The subscription before the update
|
||||
* @param {Subscription} newSubscription The subscription after the update
|
||||
*/
|
||||
client.emit(Events.SubscriptionUpdate, oldSubscription, newSubscription);
|
||||
};
|
||||
@@ -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;
|
||||
|
||||
/**
|
||||
* Emitted 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));
|
||||
};
|
||||
@@ -53,6 +53,9 @@ const handlers = Object.fromEntries([
|
||||
['STAGE_INSTANCE_CREATE', require('./STAGE_INSTANCE_CREATE')],
|
||||
['STAGE_INSTANCE_DELETE', require('./STAGE_INSTANCE_DELETE')],
|
||||
['STAGE_INSTANCE_UPDATE', require('./STAGE_INSTANCE_UPDATE')],
|
||||
['SUBSCRIPTION_CREATE', require('./SUBSCRIPTION_CREATE')],
|
||||
['SUBSCRIPTION_DELETE', require('./SUBSCRIPTION_DELETE')],
|
||||
['SUBSCRIPTION_UPDATE', require('./SUBSCRIPTION_UPDATE')],
|
||||
['THREAD_CREATE', require('./THREAD_CREATE')],
|
||||
['THREAD_DELETE', require('./THREAD_DELETE')],
|
||||
['THREAD_LIST_SYNC', require('./THREAD_LIST_SYNC')],
|
||||
@@ -61,6 +64,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')],
|
||||
|
||||
@@ -95,7 +95,8 @@ const Messages = {
|
||||
[DjsErrorCodes.ChannelNotCached]: 'Could not find the channel where this message came from in the cache!',
|
||||
[DjsErrorCodes.StageChannelResolve]: 'Could not resolve channel to a stage channel.',
|
||||
[DjsErrorCodes.GuildScheduledEventResolve]: 'Could not resolve the guild scheduled event.',
|
||||
[DjsErrorCodes.FetchOwnerId]: type => `Couldn't resolve the ${type} ownerId to fetch the ${type} member.`,
|
||||
[DjsErrorCodes.FetchOwnerId]: type =>
|
||||
`Couldn't resolve the ${type} ownerId to fetch the ${type} ${type === 'group DM' ? 'owner' : 'member'}.`,
|
||||
|
||||
[DjsErrorCodes.InvalidType]: (name, expected, an = false) => `Supplied ${name} is not a${an ? 'n' : ''} ${expected}.`,
|
||||
[DjsErrorCodes.InvalidElement]: (type, name, elem) => `Supplied ${type} ${name} includes an invalid element: ${elem}`,
|
||||
|
||||
@@ -29,7 +29,6 @@ exports.ChannelFlagsBitField = require('./util/ChannelFlagsBitField');
|
||||
exports.Collection = require('@discordjs/collection').Collection;
|
||||
exports.Constants = require('./util/Constants');
|
||||
exports.Colors = require('./util/Colors');
|
||||
__exportStar(require('./util/DataResolver.js'), exports);
|
||||
exports.Events = require('./util/Events');
|
||||
exports.Formatters = require('./util/Formatters');
|
||||
exports.GuildMemberFlagsBitField = require('./util/GuildMemberFlagsBitField').GuildMemberFlagsBitField;
|
||||
@@ -85,6 +84,7 @@ exports.ReactionManager = require('./managers/ReactionManager');
|
||||
exports.ReactionUserManager = require('./managers/ReactionUserManager');
|
||||
exports.RoleManager = require('./managers/RoleManager');
|
||||
exports.StageInstanceManager = require('./managers/StageInstanceManager');
|
||||
exports.SubscriptionManager = require('./managers/SubscriptionManager').SubscriptionManager;
|
||||
exports.ThreadManager = require('./managers/ThreadManager');
|
||||
exports.ThreadMemberManager = require('./managers/ThreadMemberManager');
|
||||
exports.UserManager = require('./managers/UserManager');
|
||||
@@ -146,6 +146,9 @@ exports.GuildScheduledEvent = require('./structures/GuildScheduledEvent').GuildS
|
||||
exports.GuildTemplate = require('./structures/GuildTemplate');
|
||||
exports.Integration = require('./structures/Integration');
|
||||
exports.IntegrationApplication = require('./structures/IntegrationApplication');
|
||||
exports.InteractionCallback = require('./structures/InteractionCallback');
|
||||
exports.InteractionCallbackResource = require('./structures/InteractionCallbackResource');
|
||||
exports.InteractionCallbackResponse = require('./structures/InteractionCallbackResponse');
|
||||
exports.BaseInteraction = require('./structures/BaseInteraction');
|
||||
exports.InteractionCollector = require('./structures/InteractionCollector');
|
||||
exports.InteractionResponse = require('./structures/InteractionResponse');
|
||||
@@ -202,6 +205,7 @@ exports.SKU = require('./structures/SKU').SKU;
|
||||
exports.StringSelectMenuOptionBuilder = require('./structures/StringSelectMenuOptionBuilder');
|
||||
exports.StageChannel = require('./structures/StageChannel');
|
||||
exports.StageInstance = require('./structures/StageInstance').StageInstance;
|
||||
exports.Subscription = require('./structures/Subscription').Subscription;
|
||||
exports.Sticker = require('./structures/Sticker').Sticker;
|
||||
exports.StickerPack = require('./structures/StickerPack');
|
||||
exports.Team = require('./structures/Team');
|
||||
@@ -215,6 +219,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');
|
||||
|
||||
@@ -82,7 +82,7 @@ class ApplicationCommandManager extends CachedManager {
|
||||
* Options used to fetch Application Commands from Discord
|
||||
* @typedef {BaseFetchOptions} FetchApplicationCommandOptions
|
||||
* @property {Snowflake} [guildId] The guild's id to fetch commands for, for when the guild is not cached
|
||||
* @property {LocaleString} [locale] The locale to use when fetching this command
|
||||
* @property {Locale} [locale] The locale to use when fetching this command
|
||||
* @property {boolean} [withLocalizations] Whether to fetch all localization data
|
||||
*/
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
'use strict';
|
||||
|
||||
const CachedManager = require('./CachedManager');
|
||||
const ApplicationEmoji = require('../structures/ApplicationEmoji');
|
||||
const GuildEmoji = require('../structures/GuildEmoji');
|
||||
const ReactionEmoji = require('../structures/ReactionEmoji');
|
||||
const { parseEmoji } = require('../util/Util');
|
||||
@@ -25,7 +26,8 @@ class BaseGuildEmojiManager extends CachedManager {
|
||||
* * A Snowflake
|
||||
* * A GuildEmoji object
|
||||
* * A ReactionEmoji object
|
||||
* @typedef {Snowflake|GuildEmoji|ReactionEmoji} EmojiResolvable
|
||||
* * An ApplicationEmoji object
|
||||
* @typedef {Snowflake|GuildEmoji|ReactionEmoji|ApplicationEmoji} EmojiResolvable
|
||||
*/
|
||||
|
||||
/**
|
||||
@@ -34,7 +36,8 @@ class BaseGuildEmojiManager extends CachedManager {
|
||||
* @returns {?GuildEmoji}
|
||||
*/
|
||||
resolve(emoji) {
|
||||
if (emoji instanceof ReactionEmoji) return super.resolve(emoji.id);
|
||||
if (emoji instanceof ReactionEmoji) return this.cache.get(emoji.id) ?? null;
|
||||
if (emoji instanceof ApplicationEmoji) return this.cache.get(emoji.id) ?? null;
|
||||
return super.resolve(emoji);
|
||||
}
|
||||
|
||||
@@ -45,6 +48,7 @@ class BaseGuildEmojiManager extends CachedManager {
|
||||
*/
|
||||
resolveId(emoji) {
|
||||
if (emoji instanceof ReactionEmoji) return emoji.id;
|
||||
if (emoji instanceof ApplicationEmoji) return emoji.id;
|
||||
return super.resolveId(emoji);
|
||||
}
|
||||
|
||||
@@ -65,6 +69,7 @@ class BaseGuildEmojiManager extends CachedManager {
|
||||
const emojiResolvable = this.resolve(emoji);
|
||||
if (emojiResolvable) return emojiResolvable.identifier;
|
||||
if (emoji instanceof ReactionEmoji) return emoji.identifier;
|
||||
if (emoji instanceof ApplicationEmoji) return emoji.identifier;
|
||||
if (typeof emoji === 'string') {
|
||||
const res = parseEmoji(emoji);
|
||||
if (res?.name.length) {
|
||||
|
||||
@@ -37,6 +37,12 @@ class EntitlementManager extends CachedManager {
|
||||
* @typedef {SKU|Snowflake} SKUResolvable
|
||||
*/
|
||||
|
||||
/**
|
||||
* Options used to fetch an entitlement
|
||||
* @typedef {BaseFetchOptions} FetchEntitlementOptions
|
||||
* @property {EntitlementResolvable} entitlement The entitlement to fetch
|
||||
*/
|
||||
|
||||
/**
|
||||
* Options used to fetch entitlements
|
||||
* @typedef {Object} FetchEntitlementsOptions
|
||||
@@ -45,6 +51,7 @@ class EntitlementManager extends CachedManager {
|
||||
* @property {UserResolvable} [user] The user to fetch entitlements for
|
||||
* @property {SKUResolvable[]} [skus] The SKUs to fetch entitlements for
|
||||
* @property {boolean} [excludeEnded] Whether to exclude ended entitlements
|
||||
* @property {boolean} [excludeDeleted] Whether to exclude deleted entitlements
|
||||
* @property {boolean} [cache=true] Whether to cache the fetched entitlements
|
||||
* @property {Snowflake} [before] Consider only entitlements before this entitlement id
|
||||
* @property {Snowflake} [after] Consider only entitlements after this entitlement id
|
||||
@@ -53,21 +60,49 @@ class EntitlementManager extends CachedManager {
|
||||
|
||||
/**
|
||||
* Fetches entitlements for this application
|
||||
* @param {FetchEntitlementsOptions} [options={}] Options for fetching the entitlements
|
||||
* @returns {Promise<Collection<Snowflake, Entitlement>>}
|
||||
* @param {EntitlementResolvable|FetchEntitlementOptions|FetchEntitlementsOptions} [options]
|
||||
* Options for fetching the entitlements
|
||||
* @returns {Promise<Entitlement|Collection<Snowflake, Entitlement>>}
|
||||
*/
|
||||
async fetch({ limit, guild, user, skus, excludeEnded, cache = true, before, after } = {}) {
|
||||
async fetch(options) {
|
||||
if (!options) return this._fetchMany(options);
|
||||
const { entitlement, cache, force } = options;
|
||||
const resolvedEntitlement = this.resolveId(entitlement ?? options);
|
||||
|
||||
if (resolvedEntitlement) {
|
||||
return this._fetchSingle({ entitlement: resolvedEntitlement, cache, force });
|
||||
}
|
||||
|
||||
return this._fetchMany(options);
|
||||
}
|
||||
|
||||
async _fetchSingle({ entitlement, cache, force = false }) {
|
||||
if (!force) {
|
||||
const existing = this.cache.get(entitlement);
|
||||
|
||||
if (existing) {
|
||||
return existing;
|
||||
}
|
||||
}
|
||||
|
||||
const data = await this.client.rest.get(Routes.entitlement(this.client.application.id, entitlement));
|
||||
return this._add(data, cache);
|
||||
}
|
||||
|
||||
async _fetchMany({ limit, guild, user, skus, excludeEnded, excludeDeleted, cache, before, after } = {}) {
|
||||
const query = makeURLSearchParams({
|
||||
limit,
|
||||
guild_id: guild && this.client.guilds.resolveId(guild),
|
||||
user_id: user && this.client.users.resolveId(user),
|
||||
sku_ids: skus?.map(sku => resolveSKUId(sku)).join(','),
|
||||
exclude_ended: excludeEnded,
|
||||
exclude_deleted: excludeDeleted,
|
||||
before,
|
||||
after,
|
||||
});
|
||||
|
||||
const entitlements = await this.client.rest.get(Routes.entitlements(this.client.application.id), { query });
|
||||
|
||||
return entitlements.reduce(
|
||||
(coll, entitlement) => coll.set(entitlement.id, this._add(entitlement, cache)),
|
||||
new Collection(),
|
||||
|
||||
@@ -97,14 +97,14 @@ class GuildBanManager extends CachedManager {
|
||||
* .then(console.log)
|
||||
* .catch(console.error);
|
||||
*/
|
||||
fetch(options) {
|
||||
async fetch(options) {
|
||||
if (!options) return this._fetchMany();
|
||||
const { user, cache, force, limit, before, after } = options;
|
||||
const resolvedUser = this.client.users.resolveId(user ?? options);
|
||||
if (resolvedUser) return this._fetchSingle({ user: resolvedUser, cache, force });
|
||||
|
||||
if (!before && !after && !limit && cache === undefined) {
|
||||
return Promise.reject(new DiscordjsError(ErrorCodes.FetchBanResolveId));
|
||||
throw new DiscordjsError(ErrorCodes.FetchBanResolveId);
|
||||
}
|
||||
|
||||
return this._fetchMany(options);
|
||||
@@ -175,7 +175,7 @@ class GuildBanManager extends CachedManager {
|
||||
reason: options.reason,
|
||||
});
|
||||
if (user instanceof GuildMember) return user;
|
||||
const _user = this.client.users.resolve(id);
|
||||
const _user = this.client.users.cache.get(id);
|
||||
if (_user) {
|
||||
return this.guild.members.resolve(_user) ?? _user;
|
||||
}
|
||||
|
||||
@@ -84,7 +84,7 @@ class GuildChannelManager extends CachedManager {
|
||||
* @returns {?(GuildChannel|ThreadChannel)}
|
||||
*/
|
||||
resolve(channel) {
|
||||
if (channel instanceof ThreadChannel) return super.resolve(channel.id);
|
||||
if (channel instanceof ThreadChannel) return this.cache.get(channel.id) ?? null;
|
||||
return super.resolve(channel);
|
||||
}
|
||||
|
||||
@@ -287,7 +287,7 @@ class GuildChannelManager extends CachedManager {
|
||||
const resolvedChannel = this.resolve(channel);
|
||||
if (!resolvedChannel) throw new DiscordjsTypeError(ErrorCodes.InvalidType, 'channel', 'GuildChannelResolvable');
|
||||
|
||||
const parent = options.parent && this.client.channels.resolveId(options.parent);
|
||||
const parentId = options.parent && this.client.channels.resolveId(options.parent);
|
||||
|
||||
if (options.position !== undefined) {
|
||||
await this.setPosition(resolvedChannel, options.position, { position: options.position, reason: options.reason });
|
||||
@@ -298,8 +298,8 @@ class GuildChannelManager extends CachedManager {
|
||||
);
|
||||
|
||||
if (options.lockPermissions) {
|
||||
if (parent) {
|
||||
const newParent = this.guild.channels.resolve(parent);
|
||||
if (parentId) {
|
||||
const newParent = this.cache.get(parentId);
|
||||
if (newParent?.type === ChannelType.GuildCategory) {
|
||||
permission_overwrites = newParent.permissionOverwrites.cache.map(overwrite =>
|
||||
PermissionOverwrites.resolve(overwrite, this.guild),
|
||||
@@ -322,7 +322,7 @@ class GuildChannelManager extends CachedManager {
|
||||
user_limit: options.userLimit,
|
||||
rtc_region: options.rtcRegion,
|
||||
video_quality_mode: options.videoQualityMode,
|
||||
parent_id: parent,
|
||||
parent_id: parentId,
|
||||
lock_permissions: options.lockPermissions,
|
||||
rate_limit_per_user: options.rateLimitPerUser,
|
||||
default_auto_archive_duration: options.defaultAutoArchiveDuration,
|
||||
|
||||
@@ -39,14 +39,14 @@ class GuildEmojiRoleManager extends DataManager {
|
||||
* @param {RoleResolvable|RoleResolvable[]|Collection<Snowflake, Role>} roleOrRoles The role or roles to add
|
||||
* @returns {Promise<GuildEmoji>}
|
||||
*/
|
||||
add(roleOrRoles) {
|
||||
async add(roleOrRoles) {
|
||||
if (!Array.isArray(roleOrRoles) && !(roleOrRoles instanceof Collection)) roleOrRoles = [roleOrRoles];
|
||||
|
||||
const resolvedRoles = [];
|
||||
for (const role of roleOrRoles.values()) {
|
||||
const resolvedRole = this.guild.roles.resolveId(role);
|
||||
if (!resolvedRole) {
|
||||
return Promise.reject(new DiscordjsTypeError(ErrorCodes.InvalidElement, 'Array or Collection', 'roles', role));
|
||||
throw new DiscordjsTypeError(ErrorCodes.InvalidElement, 'Array or Collection', 'roles', role);
|
||||
}
|
||||
resolvedRoles.push(resolvedRole);
|
||||
}
|
||||
@@ -60,14 +60,14 @@ class GuildEmojiRoleManager extends DataManager {
|
||||
* @param {RoleResolvable|RoleResolvable[]|Collection<Snowflake, Role>} roleOrRoles The role or roles to remove
|
||||
* @returns {Promise<GuildEmoji>}
|
||||
*/
|
||||
remove(roleOrRoles) {
|
||||
async remove(roleOrRoles) {
|
||||
if (!Array.isArray(roleOrRoles) && !(roleOrRoles instanceof Collection)) roleOrRoles = [roleOrRoles];
|
||||
|
||||
const resolvedRoleIds = [];
|
||||
for (const role of roleOrRoles.values()) {
|
||||
const roleId = this.guild.roles.resolveId(role);
|
||||
if (!roleId) {
|
||||
return Promise.reject(new DiscordjsTypeError(ErrorCodes.InvalidElement, 'Array or Collection', 'roles', role));
|
||||
throw new DiscordjsTypeError(ErrorCodes.InvalidElement, 'Array or Collection', 'roles', role);
|
||||
}
|
||||
resolvedRoleIds.push(roleId);
|
||||
}
|
||||
|
||||
@@ -121,22 +121,22 @@ class GuildInviteManager extends CachedManager {
|
||||
* .then(console.log)
|
||||
* .catch(console.error);
|
||||
*/
|
||||
fetch(options) {
|
||||
async fetch(options) {
|
||||
if (!options) return this._fetchMany();
|
||||
if (typeof options === 'string') {
|
||||
const code = resolveInviteCode(options);
|
||||
if (!code) return Promise.reject(new DiscordjsError(ErrorCodes.InviteResolveCode));
|
||||
if (!code) throw new DiscordjsError(ErrorCodes.InviteResolveCode);
|
||||
return this._fetchSingle({ code, cache: true });
|
||||
}
|
||||
if (!options.code) {
|
||||
if (options.channelId) {
|
||||
const id = this.guild.channels.resolveId(options.channelId);
|
||||
if (!id) return Promise.reject(new DiscordjsError(ErrorCodes.GuildChannelResolve));
|
||||
if (!id) throw new DiscordjsError(ErrorCodes.GuildChannelResolve);
|
||||
return this._fetchChannelMany(id, options.cache);
|
||||
}
|
||||
|
||||
if ('cache' in options) return this._fetchMany(options.cache);
|
||||
return Promise.reject(new DiscordjsError(ErrorCodes.InviteResolveCode));
|
||||
throw new DiscordjsError(ErrorCodes.InviteResolveCode);
|
||||
}
|
||||
return this._fetchSingle({
|
||||
...options,
|
||||
|
||||
@@ -18,6 +18,7 @@ const { resolveImage } = require('../util/DataResolver');
|
||||
const Events = require('../util/Events');
|
||||
const PermissionsBitField = require('../util/PermissionsBitField');
|
||||
const SystemChannelFlagsBitField = require('../util/SystemChannelFlagsBitField');
|
||||
const { _transformAPIIncidentsData } = require('../util/Transformers.js');
|
||||
const { resolveColor } = require('../util/Util');
|
||||
|
||||
let cacheWarningEmitted = false;
|
||||
@@ -281,6 +282,39 @@ class GuildManager extends CachedManager {
|
||||
return data.reduce((coll, guild) => coll.set(guild.id, new OAuth2Guild(this.client, guild)), new Collection());
|
||||
}
|
||||
|
||||
/**
|
||||
* Options used to set incident actions. Supplying `null` to any option will disable the action.
|
||||
* @typedef {Object} IncidentActionsEditOptions
|
||||
* @property {?DateResolvable} [invitesDisabledUntil] When invites should be enabled again
|
||||
* @property {?DateResolvable} [dmsDisabledUntil] When direct messages should be enabled again
|
||||
*/
|
||||
|
||||
/**
|
||||
* Sets the incident actions for a guild.
|
||||
* @param {GuildResolvable} guild The guild
|
||||
* @param {IncidentActionsEditOptions} incidentActions The incident actions to set
|
||||
* @returns {Promise<IncidentActions>}
|
||||
*/
|
||||
async setIncidentActions(guild, { invitesDisabledUntil, dmsDisabledUntil }) {
|
||||
const guildId = this.resolveId(guild);
|
||||
|
||||
const data = await this.client.rest.put(Routes.guildIncidentActions(guildId), {
|
||||
body: {
|
||||
invites_disabled_until: invitesDisabledUntil && new Date(invitesDisabledUntil).toISOString(),
|
||||
dms_disabled_until: dmsDisabledUntil && new Date(dmsDisabledUntil).toISOString(),
|
||||
},
|
||||
});
|
||||
|
||||
const parsedData = _transformAPIIncidentsData(data);
|
||||
const resolvedGuild = this.resolve(guild);
|
||||
|
||||
if (resolvedGuild) {
|
||||
resolvedGuild.incidentsData = parsedData;
|
||||
}
|
||||
|
||||
return parsedData;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a URL for the PNG widget of a guild.
|
||||
* @param {GuildResolvable} guild The guild of the widget image
|
||||
|
||||
@@ -54,8 +54,8 @@ class GuildMemberManager extends CachedManager {
|
||||
resolve(member) {
|
||||
const memberResolvable = super.resolve(member);
|
||||
if (memberResolvable) return memberResolvable;
|
||||
const userResolvable = this.client.users.resolveId(member);
|
||||
if (userResolvable) return super.resolve(userResolvable);
|
||||
const userId = this.client.users.resolveId(member);
|
||||
if (userId) return this.cache.get(userId) ?? null;
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -67,8 +67,8 @@ class GuildMemberManager extends CachedManager {
|
||||
resolveId(member) {
|
||||
const memberResolvable = super.resolveId(member);
|
||||
if (memberResolvable) return memberResolvable;
|
||||
const userResolvable = this.client.users.resolveId(member);
|
||||
return this.cache.has(userResolvable) ? userResolvable : null;
|
||||
const userId = this.client.users.resolveId(member);
|
||||
return this.cache.has(userId) ? userId : null;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -144,7 +144,7 @@ class GuildMemberManager extends CachedManager {
|
||||
*/
|
||||
get me() {
|
||||
return (
|
||||
this.resolve(this.client.user.id) ??
|
||||
this.cache.get(this.client.user.id) ??
|
||||
(this.client.options.partials.includes(Partials.GuildMember)
|
||||
? this._add({ user: { id: this.client.user.id } }, true)
|
||||
: null)
|
||||
@@ -223,7 +223,7 @@ class GuildMemberManager extends CachedManager {
|
||||
return this._add(data, cache);
|
||||
}
|
||||
|
||||
_fetchMany({
|
||||
async _fetchMany({
|
||||
limit = 0,
|
||||
withPresences: presences,
|
||||
users,
|
||||
@@ -231,7 +231,7 @@ class GuildMemberManager extends CachedManager {
|
||||
time = 120e3,
|
||||
nonce = DiscordSnowflake.generate().toString(),
|
||||
} = {}) {
|
||||
if (nonce.length > 32) return Promise.reject(new DiscordjsRangeError(ErrorCodes.MemberFetchNonceLength));
|
||||
if (nonce.length > 32) throw new DiscordjsRangeError(ErrorCodes.MemberFetchNonceLength);
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
if (!query && !users) query = '';
|
||||
@@ -461,7 +461,7 @@ class GuildMemberManager extends CachedManager {
|
||||
*/
|
||||
async kick(user, reason) {
|
||||
const id = this.client.users.resolveId(user);
|
||||
if (!id) return Promise.reject(new DiscordjsTypeError(ErrorCodes.InvalidType, 'user', 'UserResolvable'));
|
||||
if (!id) throw new DiscordjsTypeError(ErrorCodes.InvalidType, 'user', 'UserResolvable');
|
||||
|
||||
await this.client.rest.delete(Routes.guildMember(this.guild.id, id), { reason });
|
||||
|
||||
@@ -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 });
|
||||
|
||||
|
||||
@@ -101,6 +101,8 @@ class GuildMemberRoleManager extends DataManager {
|
||||
|
||||
/**
|
||||
* Adds a role (or multiple roles) to the member.
|
||||
*
|
||||
* <info>Uses the idempotent PUT route for singular roles, otherwise PATCHes the underlying guild member</info>
|
||||
* @param {RoleResolvable|RoleResolvable[]|Collection<Snowflake, Role>} roleOrRoles The role or roles to add
|
||||
* @param {string} [reason] Reason for adding the role(s)
|
||||
* @returns {Promise<GuildMember>}
|
||||
@@ -138,6 +140,8 @@ class GuildMemberRoleManager extends DataManager {
|
||||
|
||||
/**
|
||||
* Removes a role (or multiple roles) from the member.
|
||||
*
|
||||
* <info>Uses the idempotent DELETE route for singular roles, otherwise PATCHes the underlying guild member</info>
|
||||
* @param {RoleResolvable|RoleResolvable[]|Collection<Snowflake, Role>} roleOrRoles The role or roles to remove
|
||||
* @param {string} [reason] Reason for removing the role(s)
|
||||
* @returns {Promise<GuildMember>}
|
||||
|
||||
@@ -7,6 +7,7 @@ const CachedManager = require('./CachedManager');
|
||||
const { DiscordjsTypeError, DiscordjsError, ErrorCodes } = require('../errors');
|
||||
const { GuildScheduledEvent } = require('../structures/GuildScheduledEvent');
|
||||
const { resolveImage } = require('../util/DataResolver');
|
||||
const { _transformGuildScheduledEventRecurrenceRule } = require('../util/Transformers');
|
||||
|
||||
/**
|
||||
* Manages API methods for GuildScheduledEvents and stores their cache.
|
||||
@@ -36,6 +37,18 @@ class GuildScheduledEventManager extends CachedManager {
|
||||
* @typedef {Snowflake|GuildScheduledEvent} GuildScheduledEventResolvable
|
||||
*/
|
||||
|
||||
/**
|
||||
* Options for setting a recurrence rule for a guild scheduled event.
|
||||
* @typedef {Object} GuildScheduledEventRecurrenceRuleOptions
|
||||
* @property {DateResolvable} startAt The time the recurrence rule interval starts at
|
||||
* @property {GuildScheduledEventRecurrenceRuleFrequency} frequency How often the event occurs
|
||||
* @property {number} interval The spacing between the events
|
||||
* @property {?GuildScheduledEventRecurrenceRuleWeekday[]} byWeekday The days within a week to recur on
|
||||
* @property {?GuildScheduledEventRecurrenceRuleNWeekday[]} byNWeekday The days within a week to recur on
|
||||
* @property {?GuildScheduledEventRecurrenceRuleMonth[]} byMonth The months to recur on
|
||||
* @property {?number[]} byMonthDay The days within a month to recur on
|
||||
*/
|
||||
|
||||
/**
|
||||
* Options used to create a guild scheduled event.
|
||||
* @typedef {Object} GuildScheduledEventCreateOptions
|
||||
@@ -54,6 +67,8 @@ class GuildScheduledEventManager extends CachedManager {
|
||||
* <warn>This is required if `entityType` is {@link GuildScheduledEventEntityType.External}</warn>
|
||||
* @property {?(BufferResolvable|Base64Resolvable)} [image] The cover image of the guild scheduled event
|
||||
* @property {string} [reason] The reason for creating the guild scheduled event
|
||||
* @property {GuildScheduledEventRecurrenceRuleOptions} [recurrenceRule]
|
||||
* The recurrence rule of the guild scheduled event
|
||||
*/
|
||||
|
||||
/**
|
||||
@@ -81,6 +96,7 @@ class GuildScheduledEventManager extends CachedManager {
|
||||
entityMetadata,
|
||||
reason,
|
||||
image,
|
||||
recurrenceRule,
|
||||
} = options;
|
||||
|
||||
let entity_metadata, channel_id;
|
||||
@@ -104,6 +120,7 @@ class GuildScheduledEventManager extends CachedManager {
|
||||
entity_type: entityType,
|
||||
entity_metadata,
|
||||
image: image && (await resolveImage(image)),
|
||||
recurrence_rule: recurrenceRule && _transformGuildScheduledEventRecurrenceRule(recurrenceRule),
|
||||
},
|
||||
reason,
|
||||
});
|
||||
@@ -153,10 +170,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(),
|
||||
);
|
||||
}
|
||||
@@ -178,6 +192,8 @@ class GuildScheduledEventManager extends CachedManager {
|
||||
* {@link GuildScheduledEventEntityType.External}</warn>
|
||||
* @property {?(BufferResolvable|Base64Resolvable)} [image] The cover image of the guild scheduled event
|
||||
* @property {string} [reason] The reason for editing the guild scheduled event
|
||||
* @property {?GuildScheduledEventRecurrenceRuleOptions} [recurrenceRule]
|
||||
* The recurrence rule of the guild scheduled event
|
||||
*/
|
||||
|
||||
/**
|
||||
@@ -203,6 +219,7 @@ class GuildScheduledEventManager extends CachedManager {
|
||||
entityMetadata,
|
||||
reason,
|
||||
image,
|
||||
recurrenceRule,
|
||||
} = options;
|
||||
|
||||
let entity_metadata;
|
||||
@@ -224,6 +241,7 @@ class GuildScheduledEventManager extends CachedManager {
|
||||
status,
|
||||
image: image && (await resolveImage(image)),
|
||||
entity_metadata,
|
||||
recurrence_rule: recurrenceRule && _transformGuildScheduledEventRecurrenceRule(recurrenceRule),
|
||||
},
|
||||
reason,
|
||||
});
|
||||
|
||||
@@ -62,15 +62,13 @@ class PermissionOverwriteManager extends CachedManager {
|
||||
* },
|
||||
* ], 'Needed to change permissions');
|
||||
*/
|
||||
set(overwrites, reason) {
|
||||
async set(overwrites, reason) {
|
||||
if (!Array.isArray(overwrites) && !(overwrites instanceof Collection)) {
|
||||
return Promise.reject(
|
||||
new DiscordjsTypeError(
|
||||
ErrorCodes.InvalidType,
|
||||
'overwrites',
|
||||
'Array or Collection of Permission Overwrites',
|
||||
true,
|
||||
),
|
||||
throw new DiscordjsTypeError(
|
||||
ErrorCodes.InvalidType,
|
||||
'overwrites',
|
||||
'Array or Collection of Permission Overwrites',
|
||||
true,
|
||||
);
|
||||
}
|
||||
return this.channel.edit({ permissionOverwrites: overwrites, reason });
|
||||
|
||||
@@ -38,8 +38,8 @@ class PresenceManager extends CachedManager {
|
||||
resolve(presence) {
|
||||
const presenceResolvable = super.resolve(presence);
|
||||
if (presenceResolvable) return presenceResolvable;
|
||||
const UserResolvable = this.client.users.resolveId(presence);
|
||||
return super.resolve(UserResolvable);
|
||||
const userId = this.client.users.resolveId(presence);
|
||||
return super.cache.get(userId) ?? null;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -50,8 +50,8 @@ class PresenceManager extends CachedManager {
|
||||
resolveId(presence) {
|
||||
const presenceResolvable = super.resolveId(presence);
|
||||
if (presenceResolvable) return presenceResolvable;
|
||||
const userResolvable = this.client.users.resolveId(presence);
|
||||
return this.cache.has(userResolvable) ? userResolvable : null;
|
||||
const userId = this.client.users.resolveId(presence);
|
||||
return this.cache.has(userId) ? userId : null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
81
packages/discord.js/src/managers/SubscriptionManager.js
Normal file
81
packages/discord.js/src/managers/SubscriptionManager.js
Normal file
@@ -0,0 +1,81 @@
|
||||
'use strict';
|
||||
|
||||
const { Collection } = require('@discordjs/collection');
|
||||
const { makeURLSearchParams } = require('@discordjs/rest');
|
||||
const { Routes } = require('discord-api-types/v10');
|
||||
const CachedManager = require('./CachedManager');
|
||||
const { DiscordjsTypeError, ErrorCodes } = require('../errors/index');
|
||||
const { Subscription } = require('../structures/Subscription');
|
||||
const { resolveSKUId } = require('../util/Util');
|
||||
|
||||
/**
|
||||
* Manages API methods for subscriptions and stores their cache.
|
||||
* @extends {CachedManager}
|
||||
*/
|
||||
class SubscriptionManager extends CachedManager {
|
||||
constructor(client, iterable) {
|
||||
super(client, Subscription, iterable);
|
||||
}
|
||||
|
||||
/**
|
||||
* The cache of this manager
|
||||
* @type {Collection<Snowflake, Subscription>}
|
||||
* @name SubscriptionManager#cache
|
||||
*/
|
||||
|
||||
/**
|
||||
* Options used to fetch a subscription
|
||||
* @typedef {BaseFetchOptions} FetchSubscriptionOptions
|
||||
* @property {SKUResolvable} sku The SKU to fetch the subscription for
|
||||
* @property {Snowflake} subscriptionId The id of the subscription to fetch
|
||||
*/
|
||||
|
||||
/**
|
||||
* Options used to fetch subscriptions
|
||||
* @typedef {Object} FetchSubscriptionsOptions
|
||||
* @property {Snowflake} [after] Consider only subscriptions after this subscription id
|
||||
* @property {Snowflake} [before] Consider only subscriptions before this subscription id
|
||||
* @property {number} [limit] The maximum number of subscriptions to fetch
|
||||
* @property {SKUResolvable} sku The SKU to fetch subscriptions for
|
||||
* @property {UserResolvable} user The user to fetch entitlements for
|
||||
* <warn>If both `before` and `after` are provided, only `before` is respected</warn>
|
||||
*/
|
||||
|
||||
/**
|
||||
* Fetches subscriptions for this application
|
||||
* @param {FetchSubscriptionOptions|FetchSubscriptionsOptions} [options={}] Options for fetching the subscriptions
|
||||
* @returns {Promise<Subscription|Collection<Snowflake, Subscription>>}
|
||||
*/
|
||||
async fetch(options = {}) {
|
||||
if (typeof options !== 'object') throw new DiscordjsTypeError(ErrorCodes.InvalidType, 'options', 'object', true);
|
||||
|
||||
const { after, before, cache, limit, sku, subscriptionId, user } = options;
|
||||
|
||||
const skuId = resolveSKUId(sku);
|
||||
|
||||
if (!skuId) throw new DiscordjsTypeError(ErrorCodes.InvalidType, 'sku', 'SKUResolvable');
|
||||
|
||||
if (subscriptionId) {
|
||||
const subscription = await this.client.rest.get(Routes.skuSubscription(skuId, subscriptionId));
|
||||
|
||||
return this._add(subscription, cache);
|
||||
}
|
||||
|
||||
const query = makeURLSearchParams({
|
||||
limit,
|
||||
user_id: this.client.users.resolveId(user) ?? undefined,
|
||||
sku_id: skuId,
|
||||
before,
|
||||
after,
|
||||
});
|
||||
|
||||
const subscriptions = await this.client.rest.get(Routes.skuSubscriptions(skuId), { query });
|
||||
|
||||
return subscriptions.reduce(
|
||||
(coll, subscription) => coll.set(subscription.id, this._add(subscription, cache)),
|
||||
new Collection(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
exports.SubscriptionManager = SubscriptionManager;
|
||||
@@ -97,7 +97,7 @@ class ThreadManager extends CachedManager {
|
||||
* Data that can be resolved to a Date object. This can be:
|
||||
* * A Date object
|
||||
* * A number representing a timestamp
|
||||
* * An [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601) string
|
||||
* * An {@link https://en.wikipedia.org/wiki/ISO_8601 ISO 8601} string
|
||||
* @typedef {Date|number|string} DateResolvable
|
||||
*/
|
||||
|
||||
|
||||
@@ -1,11 +1,15 @@
|
||||
'use strict';
|
||||
|
||||
const process = require('node:process');
|
||||
const { Collection } = require('@discordjs/collection');
|
||||
const { makeURLSearchParams } = require('@discordjs/rest');
|
||||
const { Routes } = require('discord-api-types/v10');
|
||||
const CachedManager = require('./CachedManager');
|
||||
const { DiscordjsTypeError, ErrorCodes } = require('../errors');
|
||||
const ThreadMember = require('../structures/ThreadMember');
|
||||
const { emitDeprecationWarningForRemoveThreadMember } = require('../util/Util');
|
||||
|
||||
let deprecationEmittedForAdd = false;
|
||||
|
||||
/**
|
||||
* Manages API methods for GuildMembers and stores their cache.
|
||||
@@ -53,7 +57,7 @@ class ThreadMemberManager extends CachedManager {
|
||||
* @readonly
|
||||
*/
|
||||
get me() {
|
||||
return this.resolve(this.client.user.id);
|
||||
return this.cache.get(this.client.user.id) ?? null;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -71,8 +75,8 @@ class ThreadMemberManager extends CachedManager {
|
||||
resolve(member) {
|
||||
const memberResolvable = super.resolve(member);
|
||||
if (memberResolvable) return memberResolvable;
|
||||
const userResolvable = this.client.users.resolveId(member);
|
||||
if (userResolvable) return super.resolve(userResolvable);
|
||||
const userId = this.client.users.resolveId(member);
|
||||
if (userId) return super.cache.get(userId) ?? null;
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -92,9 +96,20 @@ class ThreadMemberManager extends CachedManager {
|
||||
* Adds a member to the thread.
|
||||
* @param {UserResolvable|'@me'} member The member to add
|
||||
* @param {string} [reason] The reason for adding this member
|
||||
* <warn>This parameter is **deprecated**. Reasons cannot be used.</warn>
|
||||
* @returns {Promise<Snowflake>}
|
||||
*/
|
||||
async add(member, reason) {
|
||||
if (reason !== undefined && !deprecationEmittedForAdd) {
|
||||
process.emitWarning(
|
||||
// eslint-disable-next-line max-len
|
||||
'The reason parameter of ThreadMemberManager#add() is deprecated as Discord does not parse them. It will be removed in the next major version.',
|
||||
'DeprecationWarning',
|
||||
);
|
||||
|
||||
deprecationEmittedForAdd = true;
|
||||
}
|
||||
|
||||
const id = member === '@me' ? member : this.client.users.resolveId(member);
|
||||
if (!id) throw new DiscordjsTypeError(ErrorCodes.InvalidType, 'member', 'UserResolvable');
|
||||
await this.client.rest.put(Routes.threadMembers(this.thread.id, id), { reason });
|
||||
@@ -105,9 +120,14 @@ class ThreadMemberManager extends CachedManager {
|
||||
* Remove a user from the thread.
|
||||
* @param {UserResolvable|'@me'} member The member to remove
|
||||
* @param {string} [reason] The reason for removing this member from the thread
|
||||
* <warn>This parameter is **deprecated**. Reasons cannot be used.</warn>
|
||||
* @returns {Promise<Snowflake>}
|
||||
*/
|
||||
async remove(member, reason) {
|
||||
if (reason !== undefined) {
|
||||
emitDeprecationWarningForRemoveThreadMember(this.constructor.name);
|
||||
}
|
||||
|
||||
const id = member === '@me' ? member : this.client.users.resolveId(member);
|
||||
if (!id) throw new DiscordjsTypeError(ErrorCodes.InvalidType, 'member', 'UserResolvable');
|
||||
await this.client.rest.delete(Routes.threadMembers(this.thread.id, id), { reason });
|
||||
|
||||
@@ -7,6 +7,7 @@ const { GuildMember } = require('../structures/GuildMember');
|
||||
const { Message } = require('../structures/Message');
|
||||
const ThreadMember = require('../structures/ThreadMember');
|
||||
const User = require('../structures/User');
|
||||
const { emitDeprecationWarningForUserFetchFlags } = require('../util/Util');
|
||||
|
||||
/**
|
||||
* Manages API methods for users and stores their cache.
|
||||
@@ -100,8 +101,11 @@ class UserManager extends CachedManager {
|
||||
* @param {UserResolvable} user The UserResolvable to identify
|
||||
* @param {BaseFetchOptions} [options] Additional options for this fetch
|
||||
* @returns {Promise<UserFlagsBitField>}
|
||||
* @deprecated <warn>This method is deprecated and will be removed in the next major version.
|
||||
* Flags may still be retrieved via {@link UserManager#fetch}.</warn>
|
||||
*/
|
||||
async fetchFlags(user, options) {
|
||||
emitDeprecationWarningForUserFetchFlags(this.constructor.name);
|
||||
return (await this.fetch(user, options)).flags;
|
||||
}
|
||||
|
||||
|
||||
@@ -120,7 +120,7 @@ class Shard extends EventEmitter {
|
||||
* before resolving (`-1` or `Infinity` for no wait)
|
||||
* @returns {Promise<ChildProcess>}
|
||||
*/
|
||||
spawn(timeout = 30_000) {
|
||||
async spawn(timeout = 30_000) {
|
||||
if (this.process) throw new DiscordjsError(ErrorCodes.ShardingProcessExists, this.id);
|
||||
if (this.worker) throw new DiscordjsError(ErrorCodes.ShardingWorkerExists, this.id);
|
||||
|
||||
@@ -161,7 +161,7 @@ class Shard extends EventEmitter {
|
||||
*/
|
||||
this.emit(ShardEvents.Spawn, child);
|
||||
|
||||
if (timeout === -1 || timeout === Infinity) return Promise.resolve(child);
|
||||
if (timeout === -1 || timeout === Infinity) return child;
|
||||
return new Promise((resolve, reject) => {
|
||||
const cleanup = () => {
|
||||
clearTimeout(spawnTimeoutTimer);
|
||||
@@ -260,10 +260,10 @@ class Shard extends EventEmitter {
|
||||
* .then(count => console.log(`${count} guilds in shard ${shard.id}`))
|
||||
* .catch(console.error);
|
||||
*/
|
||||
fetchClientValue(prop) {
|
||||
async fetchClientValue(prop) {
|
||||
// Shard is dead (maybe respawning), don't cache anything and error immediately
|
||||
if (!this.process && !this.worker) {
|
||||
return Promise.reject(new DiscordjsError(ErrorCodes.ShardingNoChildExists, this.id));
|
||||
throw new DiscordjsError(ErrorCodes.ShardingNoChildExists, this.id);
|
||||
}
|
||||
|
||||
// Cached promise from previous call
|
||||
@@ -302,13 +302,13 @@ class Shard extends EventEmitter {
|
||||
* @param {*} [context] The context for the eval
|
||||
* @returns {Promise<*>} Result of the script execution
|
||||
*/
|
||||
eval(script, context) {
|
||||
async eval(script, context) {
|
||||
// Stringify the script if it's a Function
|
||||
const _eval = typeof script === 'function' ? `(${script})(this, ${JSON.stringify(context)})` : script;
|
||||
|
||||
// Shard is dead (maybe respawning), don't cache anything and error immediately
|
||||
if (!this.process && !this.worker) {
|
||||
return Promise.reject(new DiscordjsError(ErrorCodes.ShardingNoChildExists, this.id));
|
||||
throw new DiscordjsError(ErrorCodes.ShardingNoChildExists, this.id);
|
||||
}
|
||||
|
||||
// Cached promise from previous call
|
||||
|
||||
@@ -8,7 +8,7 @@ const { makeError, makePlainError } = require('../util/Util');
|
||||
|
||||
/**
|
||||
* Helper class for sharded clients spawned as a child process/worker, such as from a {@link ShardingManager}.
|
||||
* Utilises IPC to send and receive data to/from the master process and other shards.
|
||||
* Utilizes IPC to send and receive data to/from the master process and other shards.
|
||||
*/
|
||||
class ShardClientUtil {
|
||||
constructor(client, mode) {
|
||||
@@ -225,7 +225,8 @@ class ShardClientUtil {
|
||||
* Emitted when the client encounters an error.
|
||||
* <warn>Errors thrown within this event do not have a catch handler, it is
|
||||
* recommended to not use async functions as `error` event handlers. See the
|
||||
* [Node.js docs](https://nodejs.org/api/events.html#capture-rejections-of-promises) for details.</warn>
|
||||
* {@link https://nodejs.org/api/events.html#capture-rejections-of-promises Node.js documentation}
|
||||
* for details.)</warn>
|
||||
* @event Client#error
|
||||
* @param {Error} error The error encountered
|
||||
*/
|
||||
|
||||
@@ -14,7 +14,7 @@ const { fetchRecommendedShardCount } = require('../util/Util');
|
||||
* This is a utility class that makes multi-process sharding of a bot an easy and painless experience.
|
||||
* It works by spawning a self-contained {@link ChildProcess} or {@link Worker} for each individual shard, each
|
||||
* containing its own instance of your bot's {@link Client}. They all have a line of communication with the master
|
||||
* process, and there are several useful methods that utilise it in order to simplify tasks that are normally difficult
|
||||
* process, and there are several useful methods that utilize it in order to simplify tasks that are normally difficult
|
||||
* with sharding. It can spawn a specific number of shards or the amount that Discord suggests for the bot, and takes a
|
||||
* path to your main bot script to launch for each one.
|
||||
* @extends {EventEmitter}
|
||||
@@ -256,9 +256,9 @@ class ShardingManager extends EventEmitter {
|
||||
* @param {BroadcastEvalOptions} [options={}] The options for the broadcast
|
||||
* @returns {Promise<*|Array<*>>} Results of the script execution
|
||||
*/
|
||||
broadcastEval(script, options = {}) {
|
||||
async broadcastEval(script, options = {}) {
|
||||
if (typeof script !== 'function') {
|
||||
return Promise.reject(new DiscordjsTypeError(ErrorCodes.ShardingInvalidEvalBroadcast));
|
||||
throw new DiscordjsTypeError(ErrorCodes.ShardingInvalidEvalBroadcast);
|
||||
}
|
||||
return this._performOnShards('eval', [`(${script})(this, ${JSON.stringify(options.context)})`], options.shard);
|
||||
}
|
||||
@@ -285,16 +285,16 @@ class ShardingManager extends EventEmitter {
|
||||
* @returns {Promise<*|Array<*>>} Results of the method execution
|
||||
* @private
|
||||
*/
|
||||
_performOnShards(method, args, shard) {
|
||||
if (this.shards.size === 0) return Promise.reject(new DiscordjsError(ErrorCodes.ShardingNoShards));
|
||||
async _performOnShards(method, args, shard) {
|
||||
if (this.shards.size === 0) throw new DiscordjsError(ErrorCodes.ShardingNoShards);
|
||||
|
||||
if (typeof shard === 'number') {
|
||||
if (this.shards.has(shard)) return this.shards.get(shard)[method](...args);
|
||||
return Promise.reject(new DiscordjsError(ErrorCodes.ShardingShardNotFound, shard));
|
||||
throw new DiscordjsError(ErrorCodes.ShardingShardNotFound, shard);
|
||||
}
|
||||
|
||||
if (this.shards.size !== this.shardList.length) {
|
||||
return Promise.reject(new DiscordjsError(ErrorCodes.ShardingInProcess));
|
||||
throw new DiscordjsError(ErrorCodes.ShardingInProcess);
|
||||
}
|
||||
|
||||
const promises = [];
|
||||
|
||||
@@ -9,6 +9,7 @@ const Application = require('./interfaces/Application');
|
||||
const ApplicationCommandManager = require('../managers/ApplicationCommandManager');
|
||||
const ApplicationEmojiManager = require('../managers/ApplicationEmojiManager');
|
||||
const { EntitlementManager } = require('../managers/EntitlementManager');
|
||||
const { SubscriptionManager } = require('../managers/SubscriptionManager');
|
||||
const ApplicationFlagsBitField = require('../util/ApplicationFlagsBitField');
|
||||
const { resolveImage } = require('../util/DataResolver');
|
||||
const PermissionsBitField = require('../util/PermissionsBitField');
|
||||
@@ -44,6 +45,12 @@ class ClientApplication extends Application {
|
||||
* @type {EntitlementManager}
|
||||
*/
|
||||
this.entitlements = new EntitlementManager(this.client);
|
||||
|
||||
/**
|
||||
* The subscription manager for this application
|
||||
* @type {SubscriptionManager}
|
||||
*/
|
||||
this.subscriptions = new SubscriptionManager(this.client);
|
||||
}
|
||||
|
||||
_patch(data) {
|
||||
@@ -166,26 +173,6 @@ class ClientApplication extends Application {
|
||||
this.guildId ??= null;
|
||||
}
|
||||
|
||||
if ('cover_image' in data) {
|
||||
/**
|
||||
* The hash of the application's cover image
|
||||
* @type {?string}
|
||||
*/
|
||||
this.cover = data.cover_image;
|
||||
} else {
|
||||
this.cover ??= null;
|
||||
}
|
||||
|
||||
if ('rpc_origins' in data) {
|
||||
/**
|
||||
* The application's RPC origins, if enabled
|
||||
* @type {string[]}
|
||||
*/
|
||||
this.rpcOrigins = data.rpc_origins;
|
||||
} else {
|
||||
this.rpcOrigins ??= [];
|
||||
}
|
||||
|
||||
if ('bot_require_code_grant' in data) {
|
||||
/**
|
||||
* If this application's bot requires a code grant when using the OAuth2 flow
|
||||
@@ -236,6 +223,36 @@ class ClientApplication extends Application {
|
||||
this.roleConnectionsVerificationURL ??= null;
|
||||
}
|
||||
|
||||
if ('event_webhooks_url' in data) {
|
||||
/**
|
||||
* This application's URL to receive event webhooks
|
||||
* @type {?string}
|
||||
*/
|
||||
this.eventWebhooksURL = data.event_webhooks_url;
|
||||
} else {
|
||||
this.eventWebhooksURL ??= null;
|
||||
}
|
||||
|
||||
if ('event_webhooks_status' in data) {
|
||||
/**
|
||||
* This application's event webhooks status
|
||||
* @type {?ApplicationWebhookEventStatus}
|
||||
*/
|
||||
this.eventWebhooksStatus = data.event_webhooks_status;
|
||||
} else {
|
||||
this.eventWebhooksStatus ??= null;
|
||||
}
|
||||
|
||||
if ('event_webhooks_types' in data) {
|
||||
/**
|
||||
* List of event webhooks types this application subscribes to
|
||||
* @type {?ApplicationWebhookEventType[]}
|
||||
*/
|
||||
this.eventWebhooksTypes = data.event_webhooks_types;
|
||||
} else {
|
||||
this.eventWebhooksTypes ??= null;
|
||||
}
|
||||
|
||||
/**
|
||||
* The owner of this OAuth application
|
||||
* @type {?(User|Team)}
|
||||
@@ -277,6 +294,10 @@ class ClientApplication extends Application {
|
||||
* @property {?(BufferResolvable|Base64Resolvable)} [icon] The application's icon
|
||||
* @property {?(BufferResolvable|Base64Resolvable)} [coverImage] The application's cover image
|
||||
* @property {string} [interactionsEndpointURL] The application's interaction endpoint URL
|
||||
* @property {string} [eventWebhooksURL] The application's event webhooks URL
|
||||
* @property {ApplicationWebhookEventStatus.Enabled|ApplicationWebhookEventStatus.Disabled} [eventWebhooksStatus]
|
||||
* The application's event webhooks status.
|
||||
* @property {ApplicationWebhookEventType[]} [eventWebhooksTypes] The application's event webhooks types
|
||||
* @property {string[]} [tags] The application's tags
|
||||
*/
|
||||
|
||||
@@ -294,6 +315,9 @@ class ClientApplication extends Application {
|
||||
icon,
|
||||
coverImage,
|
||||
interactionsEndpointURL,
|
||||
eventWebhooksURL,
|
||||
eventWebhooksStatus,
|
||||
eventWebhooksTypes,
|
||||
tags,
|
||||
} = {}) {
|
||||
const data = await this.client.rest.patch(Routes.currentApplication(), {
|
||||
@@ -306,6 +330,9 @@ class ClientApplication extends Application {
|
||||
icon: icon && (await resolveImage(icon)),
|
||||
cover_image: coverImage && (await resolveImage(coverImage)),
|
||||
interactions_endpoint_url: interactionsEndpointURL,
|
||||
event_webhooks_url: eventWebhooksURL,
|
||||
event_webhooks_status: eventWebhooksStatus,
|
||||
event_webhooks_types: eventWebhooksTypes,
|
||||
tags,
|
||||
},
|
||||
});
|
||||
|
||||
@@ -73,10 +73,9 @@ class Entitlement extends Base {
|
||||
if ('starts_at' in data) {
|
||||
/**
|
||||
* The timestamp at which this entitlement is valid
|
||||
* <info>This is only `null` for test entitlements</info>
|
||||
* @type {?number}
|
||||
*/
|
||||
this.startsTimestamp = Date.parse(data.starts_at);
|
||||
this.startsTimestamp = data.starts_at ? Date.parse(data.starts_at) : null;
|
||||
} else {
|
||||
this.startsTimestamp ??= null;
|
||||
}
|
||||
@@ -84,10 +83,9 @@ class Entitlement extends Base {
|
||||
if ('ends_at' in data) {
|
||||
/**
|
||||
* The timestamp at which this entitlement is no longer valid
|
||||
* <info>This is only `null` for test entitlements</info>
|
||||
* @type {?number}
|
||||
*/
|
||||
this.endsTimestamp = Date.parse(data.ends_at);
|
||||
this.endsTimestamp = data.ends_at ? Date.parse(data.ends_at) : null;
|
||||
} else {
|
||||
this.endsTimestamp ??= null;
|
||||
}
|
||||
@@ -114,7 +112,6 @@ class Entitlement extends Base {
|
||||
|
||||
/**
|
||||
* The start date at which this entitlement is valid
|
||||
* <info>This is only `null` for test entitlements</info>
|
||||
* @type {?Date}
|
||||
*/
|
||||
get startsAt() {
|
||||
@@ -123,7 +120,6 @@ class Entitlement extends Base {
|
||||
|
||||
/**
|
||||
* The end date at which this entitlement is no longer valid
|
||||
* <info>This is only `null` for test entitlements</info>
|
||||
* @type {?Date}
|
||||
*/
|
||||
get endsAt() {
|
||||
|
||||
@@ -29,6 +29,7 @@ const VoiceStateManager = require('../managers/VoiceStateManager');
|
||||
const { resolveImage } = require('../util/DataResolver');
|
||||
const Status = require('../util/Status');
|
||||
const SystemChannelFlagsBitField = require('../util/SystemChannelFlagsBitField');
|
||||
const { _transformAPIIncidentsData } = require('../util/Transformers.js');
|
||||
const { discordSort, getSortableGroupTypes, resolvePartialEmoji } = require('../util/Util');
|
||||
|
||||
/**
|
||||
@@ -470,6 +471,27 @@ class Guild extends AnonymousGuild {
|
||||
stickers: data.stickers,
|
||||
});
|
||||
}
|
||||
|
||||
if ('incidents_data' in data) {
|
||||
/**
|
||||
* Incident actions of a guild.
|
||||
* @typedef {Object} IncidentActions
|
||||
* @property {?Date} invitesDisabledUntil When invites would be enabled again
|
||||
* @property {?Date} dmsDisabledUntil When direct messages would be enabled again
|
||||
* @property {?Date} dmSpamDetectedAt When direct message spam was detected
|
||||
* @property {?Date} raidDetectedAt When a raid was detected
|
||||
*/
|
||||
|
||||
/**
|
||||
* The incidents data of this guild.
|
||||
* <info>You will need to fetch the guild using {@link BaseGuild#fetch} if you want to receive
|
||||
* this property.</info>
|
||||
* @type {?IncidentActions}
|
||||
*/
|
||||
this.incidentsData = data.incidents_data && _transformAPIIncidentsData(data.incidents_data);
|
||||
} else {
|
||||
this.incidentsData ??= null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1365,6 +1387,15 @@ class Guild extends AnonymousGuild {
|
||||
return this.edit({ features });
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the incident actions for a guild.
|
||||
* @param {IncidentActionsEditOptions} incidentActions The incident actions to set
|
||||
* @returns {Promise<IncidentActions>}
|
||||
*/
|
||||
async setIncidentActions(incidentActions) {
|
||||
return this.client.guilds.setIncidentActions(this.id, incidentActions);
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether this guild equals another guild. It compares all properties, so for most operations
|
||||
* it is advisable to just compare `guild.id === guild2.id` as it is much faster and is often
|
||||
|
||||
@@ -265,8 +265,8 @@ class GuildChannel extends BaseChannel {
|
||||
* Locks in the permission overwrites from the parent channel.
|
||||
* @returns {Promise<GuildChannel>}
|
||||
*/
|
||||
lockPermissions() {
|
||||
if (!this.parent) return Promise.reject(new DiscordjsError(ErrorCodes.GuildChannelOrphan));
|
||||
async lockPermissions() {
|
||||
if (!this.parent) throw new DiscordjsError(ErrorCodes.GuildChannelOrphan);
|
||||
const permissionOverwrites = this.parent.permissionOverwrites.cache.map(overwrite => overwrite.toJSON());
|
||||
return this.edit({ permissionOverwrites });
|
||||
}
|
||||
|
||||
@@ -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}
|
||||
@@ -198,7 +228,7 @@ class GuildMember extends Base {
|
||||
* @readonly
|
||||
*/
|
||||
get presence() {
|
||||
return this.guild.presences.resolve(this.id);
|
||||
return this.guild.presences.cache.get(this.id) ?? null;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -79,7 +79,7 @@ class GuildOnboardingPromptOption extends Base {
|
||||
*/
|
||||
get emoji() {
|
||||
if (!this._emoji.id && !this._emoji.name) return null;
|
||||
return this.client.emojis.resolve(this._emoji.id) ?? new Emoji(this.client, this._emoji);
|
||||
return this.client.emojis.cache.get(this._emoji.id) ?? new Emoji(this.client, this._emoji);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -189,6 +189,56 @@ class GuildScheduledEvent extends Base {
|
||||
} else {
|
||||
this.image ??= null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents the recurrence rule for a {@link GuildScheduledEvent}.
|
||||
* @typedef {Object} GuildScheduledEventRecurrenceRule
|
||||
* @property {number} startTimestamp The timestamp the recurrence rule interval starts at
|
||||
* @property {Date} startAt The time the recurrence rule interval starts at
|
||||
* @property {?number} endTimestamp The timestamp the recurrence rule interval ends at
|
||||
* @property {?Date} endAt The time the recurrence rule interval ends at
|
||||
* @property {GuildScheduledEventRecurrenceRuleFrequency} frequency How often the event occurs
|
||||
* @property {number} interval The spacing between the events
|
||||
* @property {?GuildScheduledEventRecurrenceRuleWeekday[]} byWeekday The days within a week to recur on
|
||||
* @property {?GuildScheduledEventRecurrenceRuleNWeekday[]} byNWeekday The days within a week to recur on
|
||||
* @property {?GuildScheduledEventRecurrenceRuleMonth[]} byMonth The months to recur on
|
||||
* @property {?number[]} byMonthDay The days within a month to recur on
|
||||
* @property {?number[]} byYearDay The days within a year to recur on
|
||||
* @property {?number} count The total amount of times the event is allowed to recur before stopping
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {Object} GuildScheduledEventRecurrenceRuleNWeekday
|
||||
* @property {number} n The week to recur on
|
||||
* @property {GuildScheduledEventRecurrenceRuleWeekday} day The day within the week to recur on
|
||||
*/
|
||||
|
||||
if ('recurrence_rule' in data) {
|
||||
/**
|
||||
* The recurrence rule for this scheduled event
|
||||
* @type {?GuildScheduledEventRecurrenceRule}
|
||||
*/
|
||||
this.recurrenceRule = data.recurrence_rule && {
|
||||
startTimestamp: Date.parse(data.recurrence_rule.start),
|
||||
get startAt() {
|
||||
return new Date(this.startTimestamp);
|
||||
},
|
||||
endTimestamp: data.recurrence_rule.end && Date.parse(data.recurrence_rule.end),
|
||||
get endAt() {
|
||||
return this.endTimestamp && new Date(this.endTimestamp);
|
||||
},
|
||||
frequency: data.recurrence_rule.frequency,
|
||||
interval: data.recurrence_rule.interval,
|
||||
byWeekday: data.recurrence_rule.by_weekday,
|
||||
byNWeekday: data.recurrence_rule.by_n_weekday,
|
||||
byMonth: data.recurrence_rule.by_month,
|
||||
byMonthDay: data.recurrence_rule.by_month_day,
|
||||
byYearDay: data.recurrence_rule.by_year_day,
|
||||
count: data.recurrence_rule.count,
|
||||
};
|
||||
} else {
|
||||
this.recurrenceRule ??= null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
74
packages/discord.js/src/structures/InteractionCallback.js
Normal file
74
packages/discord.js/src/structures/InteractionCallback.js
Normal file
@@ -0,0 +1,74 @@
|
||||
'use strict';
|
||||
|
||||
const { DiscordSnowflake } = require('@sapphire/snowflake');
|
||||
|
||||
/**
|
||||
* Represents an interaction callback response from Discord
|
||||
*/
|
||||
class InteractionCallback {
|
||||
constructor(client, data) {
|
||||
/**
|
||||
* The client that instantiated this.
|
||||
* @name InteractionCallback#client
|
||||
* @type {Client}
|
||||
* @readonly
|
||||
*/
|
||||
Object.defineProperty(this, 'client', { value: client });
|
||||
|
||||
/**
|
||||
* The id of the original interaction response
|
||||
* @type {Snowflake}
|
||||
*/
|
||||
this.id = data.id;
|
||||
|
||||
/**
|
||||
* The type of the original interaction
|
||||
* @type {InteractionType}
|
||||
*/
|
||||
this.type = data.type;
|
||||
|
||||
/**
|
||||
* The instance id of the Activity if one was launched or joined
|
||||
* @type {?string}
|
||||
*/
|
||||
this.activityInstanceId = data.activity_instance_id ?? null;
|
||||
|
||||
/**
|
||||
* The id of the message that was created by the interaction
|
||||
* @type {?Snowflake}
|
||||
*/
|
||||
this.responseMessageId = data.response_message_id ?? null;
|
||||
|
||||
/**
|
||||
* Whether the message is in a loading state
|
||||
* @type {?boolean}
|
||||
*/
|
||||
this.responseMessageLoading = data.response_message_loading ?? null;
|
||||
|
||||
/**
|
||||
* Whether the response message was ephemeral
|
||||
* @type {?boolean}
|
||||
*/
|
||||
this.responseMessageEphemeral = data.response_message_ephemeral ?? null;
|
||||
}
|
||||
|
||||
/**
|
||||
* The timestamp the original interaction was created at
|
||||
* @type {number}
|
||||
* @readonly
|
||||
*/
|
||||
get createdTimestamp() {
|
||||
return DiscordSnowflake.timestampFrom(this.id);
|
||||
}
|
||||
|
||||
/**
|
||||
* The time the original interaction was created at
|
||||
* @type {Date}
|
||||
* @readonly
|
||||
*/
|
||||
get createdAt() {
|
||||
return new Date(this.createdTimestamp);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = InteractionCallback;
|
||||
@@ -0,0 +1,52 @@
|
||||
'use strict';
|
||||
|
||||
const { lazy } = require('@discordjs/util');
|
||||
|
||||
const getMessage = lazy(() => require('./Message').Message);
|
||||
|
||||
/**
|
||||
* Represents the resource that was created by the interaction response.
|
||||
*/
|
||||
class InteractionCallbackResource {
|
||||
constructor(client, data) {
|
||||
/**
|
||||
* The client that instantiated this
|
||||
* @name InteractionCallbackResource#client
|
||||
* @type {Client}
|
||||
* @readonly
|
||||
*/
|
||||
Object.defineProperty(this, 'client', { value: client });
|
||||
|
||||
/**
|
||||
* The interaction callback type
|
||||
* @type {InteractionResponseType}
|
||||
*/
|
||||
this.type = data.type;
|
||||
|
||||
/**
|
||||
* The Activity launched by an interaction
|
||||
* @typedef {Object} ActivityInstance
|
||||
* @property {string} id The instance id of the Activity
|
||||
*/
|
||||
|
||||
/**
|
||||
* Represents the Activity launched by this interaction
|
||||
* @type {?ActivityInstance}
|
||||
*/
|
||||
this.activityInstance = data.activity_instance ?? null;
|
||||
|
||||
if ('message' in data) {
|
||||
/**
|
||||
* The message created by the interaction
|
||||
* @type {?Message}
|
||||
*/
|
||||
this.message =
|
||||
this.client.channels.cache.get(data.message.channel_id)?.messages._add(data.message) ??
|
||||
new (getMessage())(client, data.message);
|
||||
} else {
|
||||
this.message = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = InteractionCallbackResource;
|
||||
@@ -0,0 +1,33 @@
|
||||
'use strict';
|
||||
|
||||
const InteractionCallback = require('./InteractionCallback');
|
||||
const InteractionCallbackResource = require('./InteractionCallbackResource');
|
||||
|
||||
/**
|
||||
* Represents an interaction's response
|
||||
*/
|
||||
class InteractionCallbackResponse {
|
||||
constructor(client, data) {
|
||||
/**
|
||||
* The client that instantiated this
|
||||
* @name InteractionCallbackResponse#client
|
||||
* @type {Client}
|
||||
* @readonly
|
||||
*/
|
||||
Object.defineProperty(this, 'client', { value: client });
|
||||
|
||||
/**
|
||||
* The interaction object associated with the interaction callback response
|
||||
* @type {InteractionCallback}
|
||||
*/
|
||||
this.interaction = new InteractionCallback(client, data.interaction);
|
||||
|
||||
/**
|
||||
* The resource that was created by the interaction response
|
||||
* @type {?InteractionCallbackResource}
|
||||
*/
|
||||
this.resource = data.resource ? new InteractionCallbackResource(client, data.resource) : null;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = InteractionCallbackResponse;
|
||||
@@ -153,8 +153,8 @@ class InteractionCollector extends Collector {
|
||||
if (this.messageId && interaction.message?.id !== this.messageId) return null;
|
||||
if (
|
||||
this.messageInteractionId &&
|
||||
interaction.message?.interaction?.id &&
|
||||
interaction.message.interaction.id !== this.messageInteractionId
|
||||
interaction.message?.interactionMetadata?.id &&
|
||||
interaction.message.interactionMetadata.id !== this.messageInteractionId
|
||||
) {
|
||||
return null;
|
||||
}
|
||||
@@ -180,8 +180,8 @@ class InteractionCollector extends Collector {
|
||||
if (this.messageId && interaction.message?.id !== this.messageId) return null;
|
||||
if (
|
||||
this.messageInteractionId &&
|
||||
interaction.message?.interaction?.id &&
|
||||
interaction.message.interaction.id !== this.messageInteractionId
|
||||
interaction.message?.interactionMetadata?.id &&
|
||||
interaction.message.interactionMetadata.id !== this.messageInteractionId
|
||||
) {
|
||||
return null;
|
||||
}
|
||||
@@ -224,7 +224,7 @@ class InteractionCollector extends Collector {
|
||||
this.stop('messageDelete');
|
||||
}
|
||||
|
||||
if (message.interaction?.id === this.messageInteractionId) {
|
||||
if (message.interactionMetadata?.id === this.messageInteractionId) {
|
||||
this.stop('messageDelete');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,7 +40,7 @@ class Invite extends Base {
|
||||
*/
|
||||
this.guild ??= null;
|
||||
if (data.guild) {
|
||||
this.guild = this.client.guilds.resolve(data.guild.id) ?? new InviteGuild(this.client, data.guild);
|
||||
this.guild = this.client.guilds.cache.get(data.guild.id) ?? new InviteGuild(this.client, data.guild);
|
||||
}
|
||||
|
||||
if ('code' in data) {
|
||||
|
||||
@@ -9,6 +9,7 @@ const {
|
||||
MessageType,
|
||||
MessageFlags,
|
||||
PermissionFlagsBits,
|
||||
MessageReferenceType,
|
||||
} = require('discord-api-types/v10');
|
||||
const Attachment = require('./Attachment');
|
||||
const Base = require('./Base');
|
||||
@@ -364,6 +365,7 @@ class Message extends Base {
|
||||
* @property {Snowflake} channelId The channel id that was referenced
|
||||
* @property {Snowflake|undefined} guildId The guild id that was referenced
|
||||
* @property {Snowflake|undefined} messageId The message id that was referenced
|
||||
* @property {MessageReferenceType} type The type of message reference
|
||||
*/
|
||||
|
||||
if ('message_reference' in data) {
|
||||
@@ -375,6 +377,7 @@ class Message extends Base {
|
||||
channelId: data.message_reference.channel_id,
|
||||
guildId: data.message_reference.guild_id,
|
||||
messageId: data.message_reference.message_id,
|
||||
type: data.message_reference.type,
|
||||
};
|
||||
} else {
|
||||
this.reference ??= null;
|
||||
@@ -448,6 +451,29 @@ class Message extends Base {
|
||||
this.poll ??= null;
|
||||
}
|
||||
|
||||
if (data.message_snapshots) {
|
||||
/**
|
||||
* The message snapshots associated with the message reference
|
||||
* @type {Collection<Snowflake, Message>}
|
||||
*/
|
||||
this.messageSnapshots = data.message_snapshots.reduce((coll, snapshot) => {
|
||||
const channel = this.client.channels.resolve(this.reference.channelId);
|
||||
const snapshotData = {
|
||||
...snapshot.message,
|
||||
id: this.reference.messageId,
|
||||
channel_id: this.reference.channelId,
|
||||
guild_id: this.reference.guildId,
|
||||
};
|
||||
|
||||
return coll.set(
|
||||
this.reference.messageId,
|
||||
channel ? channel.messages._add(snapshotData) : new this.constructor(this.client, snapshotData),
|
||||
);
|
||||
}, new Collection());
|
||||
} else {
|
||||
this.messageSnapshots ??= new Collection();
|
||||
}
|
||||
|
||||
/**
|
||||
* A call associated with a message
|
||||
* @typedef {Object} MessageCall
|
||||
@@ -545,7 +571,7 @@ class Message extends Base {
|
||||
* @readonly
|
||||
*/
|
||||
get thread() {
|
||||
return this.channel?.threads?.resolve(this.id) ?? null;
|
||||
return this.channel?.threads?.cache.get(this.id) ?? null;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -565,7 +591,7 @@ class Message extends Base {
|
||||
*/
|
||||
get cleanContent() {
|
||||
// eslint-disable-next-line eqeqeq
|
||||
return this.content != null ? cleanContent(this.content, this.channel) : null;
|
||||
return this.content != null && this.channel ? cleanContent(this.content, this.channel) : null;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -679,7 +705,11 @@ class Message extends Base {
|
||||
* @readonly
|
||||
*/
|
||||
get editable() {
|
||||
const precheck = Boolean(this.author.id === this.client.user.id && (!this.guild || this.channel?.viewable));
|
||||
const precheck = Boolean(
|
||||
this.author.id === this.client.user.id &&
|
||||
(!this.guild || this.channel?.viewable) &&
|
||||
this.reference?.type !== MessageReferenceType.Forward,
|
||||
);
|
||||
|
||||
// Regardless of permissions thread messages cannot be edited if
|
||||
// the thread is archived or the thread is locked and the bot does not have permission to manage threads.
|
||||
@@ -799,8 +829,8 @@ class Message extends Base {
|
||||
* .then(msg => console.log(`Updated the content of a message to ${msg.content}`))
|
||||
* .catch(console.error);
|
||||
*/
|
||||
edit(options) {
|
||||
if (!this.channel) return Promise.reject(new DiscordjsError(ErrorCodes.ChannelNotCached));
|
||||
async edit(options) {
|
||||
if (!this.channel) throw new DiscordjsError(ErrorCodes.ChannelNotCached);
|
||||
return this.channel.messages.edit(this, options);
|
||||
}
|
||||
|
||||
@@ -815,8 +845,8 @@ class Message extends Base {
|
||||
* .catch(console.error);
|
||||
* }
|
||||
*/
|
||||
crosspost() {
|
||||
if (!this.channel) return Promise.reject(new DiscordjsError(ErrorCodes.ChannelNotCached));
|
||||
async crosspost() {
|
||||
if (!this.channel) throw new DiscordjsError(ErrorCodes.ChannelNotCached);
|
||||
return this.channel.messages.crosspost(this.id);
|
||||
}
|
||||
|
||||
@@ -914,8 +944,8 @@ class Message extends Base {
|
||||
* .then(() => console.log(`Replied to message "${message.content}"`))
|
||||
* .catch(console.error);
|
||||
*/
|
||||
reply(options) {
|
||||
if (!this.channel) return Promise.reject(new DiscordjsError(ErrorCodes.ChannelNotCached));
|
||||
async reply(options) {
|
||||
if (!this.channel) throw new DiscordjsError(ErrorCodes.ChannelNotCached);
|
||||
let data;
|
||||
|
||||
if (options instanceof MessagePayload) {
|
||||
@@ -931,6 +961,24 @@ class Message extends Base {
|
||||
return this.channel.send(data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Forwards this message
|
||||
*
|
||||
* @param {TextBasedChannelResolvable} channel The channel to forward this message to.
|
||||
* @returns {Promise<Message>}
|
||||
*/
|
||||
forward(channel) {
|
||||
const resolvedChannel = this.client.channels.resolve(channel);
|
||||
if (!resolvedChannel) throw new DiscordjsError(ErrorCodes.InvalidType, 'channel', 'TextBasedChannelResolvable');
|
||||
return resolvedChannel.send({
|
||||
forward: {
|
||||
message: this.id,
|
||||
channel: this.channelId,
|
||||
guild: this.guildId,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Options for starting a thread on a message.
|
||||
* @typedef {Object} StartThreadOptions
|
||||
@@ -947,12 +995,12 @@ class Message extends Base {
|
||||
* @param {StartThreadOptions} [options] Options for starting a thread on this message
|
||||
* @returns {Promise<ThreadChannel>}
|
||||
*/
|
||||
startThread(options = {}) {
|
||||
if (!this.channel) return Promise.reject(new DiscordjsError(ErrorCodes.ChannelNotCached));
|
||||
async startThread(options = {}) {
|
||||
if (!this.channel) throw new DiscordjsError(ErrorCodes.ChannelNotCached);
|
||||
if (![ChannelType.GuildText, ChannelType.GuildAnnouncement].includes(this.channel.type)) {
|
||||
return Promise.reject(new DiscordjsError(ErrorCodes.MessageThreadParent));
|
||||
throw new DiscordjsError(ErrorCodes.MessageThreadParent);
|
||||
}
|
||||
if (this.hasThread) return Promise.reject(new DiscordjsError(ErrorCodes.MessageExistingThread));
|
||||
if (this.hasThread) throw new DiscordjsError(ErrorCodes.MessageExistingThread);
|
||||
return this.channel.threads.create({ ...options, startMessage: this });
|
||||
}
|
||||
|
||||
@@ -961,8 +1009,8 @@ class Message extends Base {
|
||||
* @param {boolean} [force=true] Whether to skip the cache check and request the API
|
||||
* @returns {Promise<Message>}
|
||||
*/
|
||||
fetch(force = true) {
|
||||
if (!this.channel) return Promise.reject(new DiscordjsError(ErrorCodes.ChannelNotCached));
|
||||
async fetch(force = true) {
|
||||
if (!this.channel) throw new DiscordjsError(ErrorCodes.ChannelNotCached);
|
||||
return this.channel.messages.fetch({ message: this.id, force });
|
||||
}
|
||||
|
||||
@@ -970,9 +1018,9 @@ class Message extends Base {
|
||||
* Fetches the webhook used to create this message.
|
||||
* @returns {Promise<?Webhook>}
|
||||
*/
|
||||
fetchWebhook() {
|
||||
if (!this.webhookId) return Promise.reject(new DiscordjsError(ErrorCodes.WebhookMessage));
|
||||
if (this.webhookId === this.applicationId) return Promise.reject(new DiscordjsError(ErrorCodes.WebhookApplication));
|
||||
async fetchWebhook() {
|
||||
if (!this.webhookId) throw new DiscordjsError(ErrorCodes.WebhookMessage);
|
||||
if (this.webhookId === this.applicationId) throw new DiscordjsError(ErrorCodes.WebhookApplication);
|
||||
return this.client.fetchWebhook(this.webhookId);
|
||||
}
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
const { Buffer } = require('node:buffer');
|
||||
const { lazy, isJSONEncodable } = require('@discordjs/util');
|
||||
const { DiscordSnowflake } = require('@sapphire/snowflake');
|
||||
const { MessageFlags } = require('discord-api-types/v10');
|
||||
const { MessageFlags, MessageReferenceType } = require('discord-api-types/v10');
|
||||
const ActionRowBuilder = require('./ActionRowBuilder');
|
||||
const { DiscordjsError, DiscordjsRangeError, ErrorCodes } = require('../errors');
|
||||
const { resolveFile } = require('../util/DataResolver');
|
||||
@@ -92,6 +92,7 @@ class MessagePayload {
|
||||
* Whether or not the target is an {@link BaseInteraction} or an {@link InteractionWebhook}
|
||||
* @type {boolean}
|
||||
* @readonly
|
||||
* @deprecated This will no longer serve a purpose in the next major version.
|
||||
*/
|
||||
get isInteraction() {
|
||||
const BaseInteraction = getBaseInteraction();
|
||||
@@ -164,15 +165,12 @@ class MessagePayload {
|
||||
|
||||
let flags;
|
||||
if (
|
||||
this.options.flags !== undefined ||
|
||||
// eslint-disable-next-line eqeqeq
|
||||
this.options.flags != null ||
|
||||
(this.isMessage && this.options.reply === undefined) ||
|
||||
this.isMessageManager
|
||||
) {
|
||||
flags =
|
||||
// eslint-disable-next-line eqeqeq
|
||||
this.options.flags != null
|
||||
? new MessageFlagsBitField(this.options.flags).bitfield
|
||||
: this.target.flags?.bitfield;
|
||||
flags = new MessageFlagsBitField(this.options.flags).bitfield;
|
||||
}
|
||||
|
||||
if (isInteraction && this.options.ephemeral) {
|
||||
@@ -201,6 +199,22 @@ class MessagePayload {
|
||||
}
|
||||
}
|
||||
|
||||
if (typeof this.options.forward === 'object') {
|
||||
const reference = this.options.forward.message;
|
||||
const channel_id = reference.channelId ?? this.target.client.channels.resolveId(this.options.forward.channel);
|
||||
const guild_id = reference.guildId ?? this.target.client.guilds.resolveId(this.options.forward.guild);
|
||||
const message_id = this.target.messages.resolveId(reference);
|
||||
if (message_id) {
|
||||
if (!channel_id) throw new DiscordjsError(ErrorCodes.InvalidType, 'channelId', 'TextBasedChannelResolvable');
|
||||
message_reference = {
|
||||
type: MessageReferenceType.Forward,
|
||||
message_id,
|
||||
channel_id,
|
||||
guild_id: guild_id ?? undefined,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
const attachments = this.options.files?.map((file, index) => ({
|
||||
id: index.toString(),
|
||||
description: file.description,
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
'use strict';
|
||||
|
||||
const { Routes } = require('discord-api-types/v10');
|
||||
const ApplicationEmoji = require('./ApplicationEmoji');
|
||||
const GuildEmoji = require('./GuildEmoji');
|
||||
const ReactionEmoji = require('./ReactionEmoji');
|
||||
const ReactionUserManager = require('../managers/ReactionUserManager');
|
||||
@@ -35,7 +36,7 @@ class MessageReaction {
|
||||
* Whether the client has super-reacted using this emoji
|
||||
* @type {boolean}
|
||||
*/
|
||||
this.meBurst = data.me_burst;
|
||||
this.meBurst = Boolean(data.me_burst);
|
||||
|
||||
/**
|
||||
* A manager of the users that have given this reaction
|
||||
@@ -51,7 +52,7 @@ class MessageReaction {
|
||||
}
|
||||
|
||||
_patch(data) {
|
||||
if ('burst_colors' in data) {
|
||||
if (data.burst_colors) {
|
||||
/**
|
||||
* Hexadecimal colors used for this super reaction
|
||||
* @type {?string[]}
|
||||
@@ -108,16 +109,24 @@ class MessageReaction {
|
||||
}
|
||||
|
||||
/**
|
||||
* The emoji of this reaction. Either a {@link GuildEmoji} object for known custom emojis, or a {@link ReactionEmoji}
|
||||
* object which has fewer properties. Whatever the prototype of the emoji, it will still have
|
||||
* The emoji of this reaction. Either a {@link GuildEmoji} object for known custom emojis,
|
||||
* {@link ApplicationEmoji} for application emojis, or a {@link ReactionEmoji} object
|
||||
* which has fewer properties. Whatever the prototype of the emoji, it will still have
|
||||
* `name`, `id`, `identifier` and `toString()`
|
||||
* @type {GuildEmoji|ReactionEmoji}
|
||||
* @type {GuildEmoji|ReactionEmoji|ApplicationEmoji}
|
||||
* @readonly
|
||||
*/
|
||||
get emoji() {
|
||||
if (this._emoji instanceof GuildEmoji) return this._emoji;
|
||||
if (this._emoji instanceof ApplicationEmoji) return this._emoji;
|
||||
// Check to see if the emoji has become known to the client
|
||||
if (this._emoji.id) {
|
||||
const applicationEmojis = this.message.client.application.emojis.cache;
|
||||
if (applicationEmojis.has(this._emoji.id)) {
|
||||
const emoji = applicationEmojis.get(this._emoji.id);
|
||||
this._emoji = emoji;
|
||||
return emoji;
|
||||
}
|
||||
const emojis = this.message.client.emojis.cache;
|
||||
if (emojis.has(this._emoji.id)) {
|
||||
const emoji = emojis.get(this._emoji.id);
|
||||
|
||||
@@ -1,12 +1,14 @@
|
||||
'use strict';
|
||||
|
||||
const { BaseChannel } = require('./BaseChannel');
|
||||
const TextBasedChannel = require('./interfaces/TextBasedChannel');
|
||||
const { DiscordjsError, ErrorCodes } = require('../errors');
|
||||
const PartialGroupDMMessageManager = require('../managers/PartialGroupDMMessageManager');
|
||||
|
||||
/**
|
||||
* Represents a Partial Group DM Channel on Discord.
|
||||
* @extends {BaseChannel}
|
||||
* @implements {TextBasedChannel}
|
||||
*/
|
||||
class PartialGroupDMChannel extends BaseChannel {
|
||||
constructor(client, data) {
|
||||
@@ -44,6 +46,36 @@ class PartialGroupDMChannel extends BaseChannel {
|
||||
* @type {PartialGroupDMMessageManager}
|
||||
*/
|
||||
this.messages = new PartialGroupDMMessageManager(this);
|
||||
|
||||
if ('owner_id' in data) {
|
||||
/**
|
||||
* The user id of the owner of this Group DM Channel
|
||||
* @type {?Snowflake}
|
||||
*/
|
||||
this.ownerId = data.owner_id;
|
||||
} else {
|
||||
this.ownerId ??= null;
|
||||
}
|
||||
|
||||
if ('last_message_id' in data) {
|
||||
/**
|
||||
* The channel's last message id, if one was sent
|
||||
* @type {?Snowflake}
|
||||
*/
|
||||
this.lastMessageId = data.last_message_id;
|
||||
} else {
|
||||
this.lastMessageId ??= null;
|
||||
}
|
||||
|
||||
if ('last_pin_timestamp' in data) {
|
||||
/**
|
||||
* The timestamp when the last pinned message was pinned, if there was one
|
||||
* @type {?number}
|
||||
*/
|
||||
this.lastPinTimestamp = data.last_pin_timestamp ? Date.parse(data.last_pin_timestamp) : null;
|
||||
} else {
|
||||
this.lastPinTimestamp ??= null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -55,13 +87,45 @@ class PartialGroupDMChannel extends BaseChannel {
|
||||
return this.icon && this.client.rest.cdn.channelIcon(this.id, this.icon, options);
|
||||
}
|
||||
|
||||
delete() {
|
||||
return Promise.reject(new DiscordjsError(ErrorCodes.DeleteGroupDMChannel));
|
||||
/**
|
||||
* Fetches the owner of this Group DM Channel.
|
||||
* @param {BaseFetchOptions} [options] The options for fetching the user
|
||||
* @returns {Promise<User>}
|
||||
*/
|
||||
async fetchOwner(options) {
|
||||
if (!this.ownerId) {
|
||||
throw new DiscordjsError(ErrorCodes.FetchOwnerId, 'group DM');
|
||||
}
|
||||
|
||||
return this.client.users.fetch(this.ownerId, options);
|
||||
}
|
||||
|
||||
fetch() {
|
||||
return Promise.reject(new DiscordjsError(ErrorCodes.FetchGroupDMChannel));
|
||||
async delete() {
|
||||
throw new DiscordjsError(ErrorCodes.DeleteGroupDMChannel);
|
||||
}
|
||||
|
||||
async fetch() {
|
||||
throw new DiscordjsError(ErrorCodes.FetchGroupDMChannel);
|
||||
}
|
||||
|
||||
// These are here only for documentation purposes - they are implemented by TextBasedChannel
|
||||
/* eslint-disable no-empty-function */
|
||||
get lastMessage() {}
|
||||
get lastPinAt() {}
|
||||
createMessageComponentCollector() {}
|
||||
awaitMessageComponent() {}
|
||||
}
|
||||
|
||||
TextBasedChannel.applyToClass(PartialGroupDMChannel, true, [
|
||||
'bulkDelete',
|
||||
'send',
|
||||
'sendTyping',
|
||||
'createMessageCollector',
|
||||
'awaitMessages',
|
||||
'fetchWebhooks',
|
||||
'createWebhook',
|
||||
'setRateLimitPerUser',
|
||||
'setNSFW',
|
||||
]);
|
||||
|
||||
module.exports = PartialGroupDMChannel;
|
||||
|
||||
@@ -181,7 +181,10 @@ class PermissionOverwrites extends Base {
|
||||
}
|
||||
|
||||
const userOrRole = guild.roles.resolve(overwrite.id) ?? guild.client.users.resolve(overwrite.id);
|
||||
if (!userOrRole) throw new DiscordjsTypeError(ErrorCodes.InvalidType, 'parameter', 'User nor a Role');
|
||||
if (!userOrRole) {
|
||||
throw new DiscordjsTypeError(ErrorCodes.InvalidType, 'parameter', 'cached User or Role');
|
||||
}
|
||||
|
||||
const type = userOrRole instanceof Role ? OverwriteType.Role : OverwriteType.Member;
|
||||
|
||||
return {
|
||||
|
||||
@@ -97,9 +97,9 @@ class Poll extends Base {
|
||||
* Ends this poll.
|
||||
* @returns {Promise<Message>}
|
||||
*/
|
||||
end() {
|
||||
async end() {
|
||||
if (Date.now() > this.expiresTimestamp) {
|
||||
return Promise.reject(new DiscordjsError(ErrorCodes.PollAlreadyExpired));
|
||||
throw new DiscordjsError(ErrorCodes.PollAlreadyExpired);
|
||||
}
|
||||
|
||||
return this.message.channel.messages.endPoll(this.message.id);
|
||||
|
||||
@@ -61,7 +61,7 @@ class PollAnswer extends Base {
|
||||
*/
|
||||
get emoji() {
|
||||
if (!this._emoji || (!this._emoji.id && !this._emoji.name)) return null;
|
||||
return this.client.emojis.resolve(this._emoji.id) ?? new Emoji(this.client, this._emoji);
|
||||
return this.client.emojis.cache.get(this._emoji.id) ?? new Emoji(this.client, this._emoji);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -182,8 +182,8 @@ class Sticker extends Base {
|
||||
* Fetches the pack that contains this sticker.
|
||||
* @returns {Promise<?StickerPack>} The sticker pack or `null` if this sticker does not belong to one.
|
||||
*/
|
||||
fetchPack() {
|
||||
if (!this.packId) return Promise.resolve(null);
|
||||
async fetchPack() {
|
||||
if (!this.packId) return null;
|
||||
return this.client.fetchStickerPacks({ packId: this.packId });
|
||||
}
|
||||
|
||||
|
||||
117
packages/discord.js/src/structures/Subscription.js
Normal file
117
packages/discord.js/src/structures/Subscription.js
Normal file
@@ -0,0 +1,117 @@
|
||||
'use strict';
|
||||
|
||||
const Base = require('./Base');
|
||||
|
||||
/**
|
||||
* Represents a Subscription
|
||||
* @extends {Base}
|
||||
*/
|
||||
class Subscription extends Base {
|
||||
constructor(client, data) {
|
||||
super(client);
|
||||
|
||||
/**
|
||||
* The id of the subscription
|
||||
* @type {Snowflake}
|
||||
*/
|
||||
this.id = data.id;
|
||||
|
||||
/**
|
||||
* The id of the user who subscribed
|
||||
* @type {Snowflake}
|
||||
*/
|
||||
this.userId = data.user_id;
|
||||
|
||||
this._patch(data);
|
||||
}
|
||||
|
||||
_patch(data) {
|
||||
/**
|
||||
* The SKU ids subscribed to
|
||||
* @type {Snowflake[]}
|
||||
*/
|
||||
this.skuIds = data.sku_ids;
|
||||
|
||||
/**
|
||||
* The entitlement ids granted for this subscription
|
||||
* @type {Snowflake[]}
|
||||
*/
|
||||
this.entitlementIds = data.entitlement_ids;
|
||||
|
||||
/**
|
||||
* The timestamp the current subscription period will start at
|
||||
* @type {number}
|
||||
*/
|
||||
this.currentPeriodStartTimestamp = Date.parse(data.current_period_start);
|
||||
|
||||
/**
|
||||
* The timestamp the current subscription period will end at
|
||||
* @type {number}
|
||||
*/
|
||||
this.currentPeriodEndTimestamp = Date.parse(data.current_period_end);
|
||||
|
||||
/**
|
||||
* The current status of the subscription
|
||||
* @type {SubscriptionStatus}
|
||||
*/
|
||||
this.status = data.status;
|
||||
|
||||
if ('renewal_sku_ids' in data) {
|
||||
/**
|
||||
* The SKU ids that this user will be subscribed to at renewal
|
||||
* @type {?Snowflake[]}
|
||||
*/
|
||||
this.renewalSkuIds = data.renewal_sku_ids;
|
||||
}
|
||||
|
||||
if ('canceled_at' in data) {
|
||||
/**
|
||||
* The timestamp of when the subscription was canceled
|
||||
* @type {?number}
|
||||
*/
|
||||
this.canceledTimestamp = data.canceled_at ? Date.parse(data.canceled_at) : null;
|
||||
} else {
|
||||
this.canceledTimestamp ??= null;
|
||||
}
|
||||
|
||||
if ('country' in data) {
|
||||
/**
|
||||
* ISO 3166-1 alpha-2 country code of the payment source used to purchase the subscription.
|
||||
* Missing unless queried with a private OAuth scope.
|
||||
* @type {?string}
|
||||
*/
|
||||
this.country = data.country;
|
||||
} else {
|
||||
this.country ??= null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The time the subscription was canceled
|
||||
* @type {?Date}
|
||||
* @readonly
|
||||
*/
|
||||
get canceledAt() {
|
||||
return this.canceledTimestamp && new Date(this.canceledTimestamp);
|
||||
}
|
||||
|
||||
/**
|
||||
* The time the current subscription period will start at
|
||||
* @type {Date}
|
||||
* @readonly
|
||||
*/
|
||||
get currentPeriodStartAt() {
|
||||
return new Date(this.currentPeriodStartTimestamp);
|
||||
}
|
||||
|
||||
/**
|
||||
* The time the current subscription period will end at
|
||||
* @type {Date}
|
||||
* @readonly
|
||||
*/
|
||||
get currentPeriodEndAt() {
|
||||
return new Date(this.currentPeriodEndTimestamp);
|
||||
}
|
||||
}
|
||||
|
||||
exports.Subscription = Subscription;
|
||||
@@ -6,7 +6,7 @@ const { RESTJSONErrorCodes, ChannelFlags, ChannelType, PermissionFlagsBits, Rout
|
||||
const { BaseChannel } = require('./BaseChannel');
|
||||
const getThreadOnlyChannel = lazy(() => require('./ThreadOnlyChannel'));
|
||||
const TextBasedChannel = require('./interfaces/TextBasedChannel');
|
||||
const { DiscordjsError, DiscordjsRangeError, ErrorCodes } = require('../errors');
|
||||
const { DiscordjsRangeError, ErrorCodes } = require('../errors');
|
||||
const GuildMessageManager = require('../managers/GuildMessageManager');
|
||||
const ThreadMemberManager = require('../managers/ThreadMemberManager');
|
||||
const ChannelFlagsBitField = require('../util/ChannelFlagsBitField');
|
||||
@@ -32,6 +32,12 @@ class ThreadChannel extends BaseChannel {
|
||||
*/
|
||||
this.guildId = guild?.id ?? data.guild_id;
|
||||
|
||||
/**
|
||||
* The id of the member who created this thread
|
||||
* @type {Snowflake}
|
||||
*/
|
||||
this.ownerId = data.owner_id;
|
||||
|
||||
/**
|
||||
* A manager of the messages sent to this thread
|
||||
* @type {GuildMessageManager}
|
||||
@@ -122,16 +128,6 @@ class ThreadChannel extends BaseChannel {
|
||||
|
||||
this._createdTimestamp ??= this.type === ChannelType.PrivateThread ? super.createdTimestamp : null;
|
||||
|
||||
if ('owner_id' in data) {
|
||||
/**
|
||||
* The id of the member who created this thread
|
||||
* @type {?Snowflake}
|
||||
*/
|
||||
this.ownerId = data.owner_id;
|
||||
} else {
|
||||
this.ownerId ??= null;
|
||||
}
|
||||
|
||||
if ('last_message_id' in data) {
|
||||
/**
|
||||
* The last message id sent in this thread, if one was sent
|
||||
@@ -288,17 +284,19 @@ 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
|
||||
* @param {FetchThreadOwnerOptions} [options] Options for fetching the owner
|
||||
* @returns {Promise<?ThreadMember>}
|
||||
*/
|
||||
async fetchOwner(options) {
|
||||
if (!this.ownerId) {
|
||||
throw new DiscordjsError(ErrorCodes.FetchOwnerId, 'thread');
|
||||
}
|
||||
|
||||
// TODO: Remove that catch in the next major version
|
||||
const member = await this.members._fetchSingle({ ...options, member: this.ownerId }).catch(error => {
|
||||
if (error instanceof DiscordAPIError && error.code === RESTJSONErrorCodes.UnknownMember) {
|
||||
@@ -319,7 +317,6 @@ class ThreadChannel extends BaseChannel {
|
||||
* @param {BaseFetchOptions} [options] Additional options for this fetch
|
||||
* @returns {Promise<?Message<true>>}
|
||||
*/
|
||||
// eslint-disable-next-line require-await
|
||||
async fetchStarterMessage(options) {
|
||||
const channel = this.parent instanceof getThreadOnlyChannel() ? this : this.parent;
|
||||
return channel?.messages.fetch({ message: this.id, ...options }) ?? null;
|
||||
@@ -409,9 +406,9 @@ class ThreadChannel extends BaseChannel {
|
||||
* @param {string} [reason] Reason for changing invite
|
||||
* @returns {Promise<ThreadChannel>}
|
||||
*/
|
||||
setInvitable(invitable = true, reason) {
|
||||
async setInvitable(invitable = true, reason) {
|
||||
if (this.type !== ChannelType.PrivateThread) {
|
||||
return Promise.reject(new DiscordjsRangeError(ErrorCodes.ThreadInvitableType, this.type));
|
||||
throw new DiscordjsRangeError(ErrorCodes.ThreadInvitableType, this.type);
|
||||
}
|
||||
return this.edit({ invitable, reason });
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
const Base = require('./Base');
|
||||
const ThreadMemberFlagsBitField = require('../util/ThreadMemberFlagsBitField');
|
||||
const { emitDeprecationWarningForRemoveThreadMember } = require('../util/Util');
|
||||
|
||||
/**
|
||||
* Represents a Member for a Thread.
|
||||
@@ -69,7 +70,7 @@ class ThreadMember extends Base {
|
||||
* @readonly
|
||||
*/
|
||||
get guildMember() {
|
||||
return this.member ?? this.thread.guild.members.resolve(this.id);
|
||||
return this.member ?? this.thread.guild.members.cache.get(this.id) ?? null;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -87,7 +88,7 @@ class ThreadMember extends Base {
|
||||
* @readonly
|
||||
*/
|
||||
get user() {
|
||||
return this.client.users.resolve(this.id);
|
||||
return this.client.users.cache.get(this.id) ?? null;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -102,9 +103,14 @@ class ThreadMember extends Base {
|
||||
/**
|
||||
* Removes this member from the thread.
|
||||
* @param {string} [reason] Reason for removing the member
|
||||
* <warn>This parameter is **deprecated**. Reasons cannot be used.</warn>
|
||||
* @returns {Promise<ThreadMember>}
|
||||
*/
|
||||
async remove(reason) {
|
||||
if (reason !== undefined) {
|
||||
emitDeprecationWarningForRemoveThreadMember(this.constructor.name);
|
||||
}
|
||||
|
||||
await this.thread.members.remove(this.id, reason);
|
||||
return this;
|
||||
}
|
||||
|
||||
@@ -36,7 +36,7 @@ const { transformAPIGuildForumTag, transformAPIGuildDefaultReaction } = require(
|
||||
*/
|
||||
|
||||
/**
|
||||
* Represents symbols utilised by thread-only channels.
|
||||
* Represents symbols utilized by thread-only channels.
|
||||
* @extends {GuildChannel}
|
||||
* @implements {TextBasedChannel}
|
||||
* @abstract
|
||||
|
||||
@@ -6,6 +6,7 @@ const { DiscordSnowflake } = require('@sapphire/snowflake');
|
||||
const Base = require('./Base');
|
||||
const TextBasedChannel = require('./interfaces/TextBasedChannel');
|
||||
const UserFlagsBitField = require('../util/UserFlagsBitField');
|
||||
const { emitDeprecationWarningForUserFetchFlags } = require('../util/Util');
|
||||
|
||||
/**
|
||||
* Represents a user on Discord.
|
||||
@@ -346,8 +347,11 @@ class User extends Base {
|
||||
* Fetches this user's flags.
|
||||
* @param {boolean} [force=false] Whether to skip the cache check and request the API
|
||||
* @returns {Promise<UserFlagsBitField>}
|
||||
* @deprecated <warn>This method is deprecated and will be removed in the next major version.
|
||||
* Flags may still be retrieved via {@link User#fetch}.</warn>
|
||||
*/
|
||||
fetchFlags(force = false) {
|
||||
emitDeprecationWarningForUserFetchFlags(this.constructor.name);
|
||||
return this.client.users.fetchFlags(this.id, { force });
|
||||
}
|
||||
|
||||
|
||||
69
packages/discord.js/src/structures/VoiceChannelEffect.js
Normal file
69
packages/discord.js/src/structures/VoiceChannelEffect.js
Normal file
@@ -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;
|
||||
@@ -108,7 +108,7 @@ class Webhook {
|
||||
* The source guild of the webhook
|
||||
* @type {?(Guild|APIGuild)}
|
||||
*/
|
||||
this.sourceGuild = this.client.guilds?.resolve(data.source_guild.id) ?? data.source_guild;
|
||||
this.sourceGuild = this.client.guilds?.cache.get(data.source_guild.id) ?? data.source_guild;
|
||||
} else {
|
||||
this.sourceGuild ??= null;
|
||||
}
|
||||
@@ -118,7 +118,7 @@ class Webhook {
|
||||
* The source channel of the webhook
|
||||
* @type {?(NewsChannel|APIChannel)}
|
||||
*/
|
||||
this.sourceChannel = this.client.channels?.resolve(data.source_channel?.id) ?? data.source_channel;
|
||||
this.sourceChannel = this.client.channels?.cache.get(data.source_channel?.id) ?? data.source_channel;
|
||||
} else {
|
||||
this.sourceChannel ??= null;
|
||||
}
|
||||
@@ -141,8 +141,7 @@ class Webhook {
|
||||
|
||||
/**
|
||||
* Options that can be passed into editMessage.
|
||||
* @typedef {BaseMessageOptions} WebhookMessageEditOptions
|
||||
* @property {Attachment[]} [attachments] Attachments to send with the message
|
||||
* @typedef {MessageEditOptions} WebhookMessageEditOptions
|
||||
* @property {Snowflake} [threadId] The id of the thread this message belongs to
|
||||
* <info>For interaction webhooks, this property is ignored</info>
|
||||
*/
|
||||
|
||||
@@ -53,7 +53,7 @@ class WelcomeChannel extends Base {
|
||||
* @type {GuildEmoji|Emoji}
|
||||
*/
|
||||
get emoji() {
|
||||
return this.client.emojis.resolve(this._emoji.id) ?? new Emoji(this.client, this._emoji);
|
||||
return this.client.emojis.cache.get(this._emoji.id) ?? new Emoji(this.client, this._emoji);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -50,6 +50,56 @@ class Application extends Base {
|
||||
} else {
|
||||
this.icon ??= null;
|
||||
}
|
||||
|
||||
if ('terms_of_service_url' in data) {
|
||||
/**
|
||||
* The URL of the application's terms of service
|
||||
* @type {?string}
|
||||
*/
|
||||
this.termsOfServiceURL = data.terms_of_service_url;
|
||||
} else {
|
||||
this.termsOfServiceURL ??= null;
|
||||
}
|
||||
|
||||
if ('privacy_policy_url' in data) {
|
||||
/**
|
||||
* The URL of the application's privacy policy
|
||||
* @type {?string}
|
||||
*/
|
||||
this.privacyPolicyURL = data.privacy_policy_url;
|
||||
} else {
|
||||
this.privacyPolicyURL ??= null;
|
||||
}
|
||||
|
||||
if ('rpc_origins' in data) {
|
||||
/**
|
||||
* The application's RPC origins, if enabled
|
||||
* @type {string[]}
|
||||
*/
|
||||
this.rpcOrigins = data.rpc_origins;
|
||||
} else {
|
||||
this.rpcOrigins ??= [];
|
||||
}
|
||||
|
||||
if ('cover_image' in data) {
|
||||
/**
|
||||
* The hash of the application's cover image
|
||||
* @type {?string}
|
||||
*/
|
||||
this.cover = data.cover_image;
|
||||
} else {
|
||||
this.cover ??= null;
|
||||
}
|
||||
|
||||
if ('verify_key' in data) {
|
||||
/**
|
||||
* The hex-encoded key for verification in interactions and the GameSDK's GetTicket
|
||||
* @type {?string}
|
||||
*/
|
||||
this.verifyKey = data.verify_key;
|
||||
} else {
|
||||
this.verifyKey ??= null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,14 +1,20 @@
|
||||
'use strict';
|
||||
|
||||
const process = require('node:process');
|
||||
const { deprecate } = require('node:util');
|
||||
const { makeURLSearchParams } = require('@discordjs/rest');
|
||||
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 InteractionCallbackResponse = require('../InteractionCallbackResponse');
|
||||
const InteractionCollector = require('../InteractionCollector');
|
||||
const InteractionResponse = require('../InteractionResponse');
|
||||
const MessagePayload = require('../MessagePayload');
|
||||
|
||||
let deprecationEmittedForEphemeralOption = false;
|
||||
let deprecationEmittedForFetchReplyOption = false;
|
||||
|
||||
/**
|
||||
* @typedef {Object} ModalComponentData
|
||||
* @property {string} title The title of the modal
|
||||
@@ -24,23 +30,33 @@ class InteractionResponses {
|
||||
/**
|
||||
* Options for deferring the reply to an {@link BaseInteraction}.
|
||||
* @typedef {Object} InteractionDeferReplyOptions
|
||||
* @property {boolean} [ephemeral] Whether the reply should be ephemeral
|
||||
* @property {boolean} [ephemeral] Whether the reply should be ephemeral.
|
||||
* <warn>This option is deprecated. Use `flags` instead.</warn>
|
||||
* @property {MessageFlagsResolvable} [flags] Flags for the reply.
|
||||
* <info>Only `MessageFlags.Ephemeral` can be set.</info>
|
||||
* @property {boolean} [withResponse] Whether to return an {@link InteractionCallbackResponse} as the response
|
||||
* @property {boolean} [fetchReply] Whether to fetch the reply
|
||||
* <warn>This option is deprecated. Use `withResponse` or fetch the response instead.</warn>
|
||||
*/
|
||||
|
||||
/**
|
||||
* Options for deferring and updating the reply to a {@link MessageComponentInteraction}.
|
||||
* @typedef {Object} InteractionDeferUpdateOptions
|
||||
* @property {boolean} [withResponse] Whether to return an {@link InteractionCallbackResponse} as the response
|
||||
* @property {boolean} [fetchReply] Whether to fetch the reply
|
||||
* <warn>This option is deprecated. Use `withResponse` or fetch the response instead.</warn>
|
||||
*/
|
||||
|
||||
/**
|
||||
* Options for a reply to a {@link BaseInteraction}.
|
||||
* @typedef {BaseMessageOptionsWithPoll} InteractionReplyOptions
|
||||
* @property {boolean} [ephemeral] Whether the reply should be ephemeral.
|
||||
* <warn>This option is deprecated. Use `flags` instead.</warn>
|
||||
* @property {boolean} [tts=false] Whether the message should be spoken aloud
|
||||
* @property {boolean} [ephemeral] Whether the reply should be ephemeral
|
||||
* @property {boolean} [withResponse] Whether to return an {@link InteractionCallbackResponse} as the response
|
||||
* @property {boolean} [fetchReply] Whether to fetch the reply
|
||||
* @property {MessageFlags} [flags] Which flags to set for the message.
|
||||
* <warn>This option is deprecated. Use `withResponse` or fetch the response instead.</warn>
|
||||
* @property {MessageFlagsResolvable} [flags] Which flags to set for the message.
|
||||
* <info>Only `MessageFlags.Ephemeral`, `MessageFlags.SuppressEmbeds`, and `MessageFlags.SuppressNotifications`
|
||||
* can be set.</info>
|
||||
*/
|
||||
@@ -48,13 +64,21 @@ class InteractionResponses {
|
||||
/**
|
||||
* Options for updating the message received from a {@link MessageComponentInteraction}.
|
||||
* @typedef {MessageEditOptions} InteractionUpdateOptions
|
||||
* @property {boolean} [withResponse] Whether to return an {@link InteractionCallbackResponse} as the response
|
||||
* @property {boolean} [fetchReply] Whether to fetch the reply
|
||||
* <warn>This option is deprecated. Use `withResponse` or fetch the response instead.</warn>
|
||||
*/
|
||||
|
||||
/**
|
||||
* Options for showing a modal in response to a {@link BaseInteraction}
|
||||
* @typedef {Object} ShowModalOptions
|
||||
* @property {boolean} [withResponse] Whether to return an {@link InteractionCallbackResponse} as the response
|
||||
*/
|
||||
|
||||
/**
|
||||
* Defers the reply to this interaction.
|
||||
* @param {InteractionDeferReplyOptions} [options] Options for deferring the reply to this interaction
|
||||
* @returns {Promise<Message|InteractionResponse>}
|
||||
* @returns {Promise<InteractionCallbackResponse|Message|InteractionResponse>}
|
||||
* @example
|
||||
* // Defer the reply to this interaction
|
||||
* interaction.deferReply()
|
||||
@@ -62,67 +86,129 @@ 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), {
|
||||
|
||||
if ('ephemeral' in options) {
|
||||
if (!deprecationEmittedForEphemeralOption) {
|
||||
process.emitWarning(
|
||||
`Supplying "ephemeral" for interaction response options is deprecated. Utilize flags instead.`,
|
||||
);
|
||||
|
||||
deprecationEmittedForEphemeralOption = true;
|
||||
}
|
||||
}
|
||||
|
||||
if ('fetchReply' in options) {
|
||||
if (!deprecationEmittedForFetchReplyOption) {
|
||||
process.emitWarning(
|
||||
// eslint-disable-next-line max-len
|
||||
`Supplying "fetchReply" for interaction response options is deprecated. Utilize "withResponse" instead or fetch the response after using the method.`,
|
||||
);
|
||||
|
||||
deprecationEmittedForFetchReplyOption = true;
|
||||
}
|
||||
}
|
||||
|
||||
const flags = new MessageFlagsBitField(options.flags);
|
||||
|
||||
if (options.ephemeral) {
|
||||
flags.add(MessageFlags.Ephemeral);
|
||||
}
|
||||
|
||||
const response = await this.client.rest.post(Routes.interactionCallback(this.id, this.token), {
|
||||
body: {
|
||||
type: InteractionResponseType.DeferredChannelMessageWithSource,
|
||||
data: {
|
||||
flags: options.ephemeral ? MessageFlags.Ephemeral : undefined,
|
||||
flags: flags.bitfield,
|
||||
},
|
||||
},
|
||||
auth: false,
|
||||
query: makeURLSearchParams({ with_response: options.withResponse ?? false }),
|
||||
});
|
||||
this.deferred = true;
|
||||
|
||||
return options.fetchReply ? this.fetchReply() : new InteractionResponse(this);
|
||||
this.deferred = true;
|
||||
this.ephemeral = flags.has(MessageFlags.Ephemeral);
|
||||
|
||||
return options.withResponse
|
||||
? new InteractionCallbackResponse(this.client, response)
|
||||
: options.fetchReply
|
||||
? this.fetchReply()
|
||||
: new InteractionResponse(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a reply to this interaction.
|
||||
* <info>Use the `fetchReply` option to get the bot's reply message.</info>
|
||||
* <info>Use the `withResponse` option to get the interaction callback response.</info>
|
||||
* @param {string|MessagePayload|InteractionReplyOptions} options The options for the reply
|
||||
* @returns {Promise<Message|InteractionResponse>}
|
||||
* @returns {Promise<InteractionCallbackResponse|Message|InteractionResponse>}
|
||||
* @example
|
||||
* // Reply to the interaction and fetch the response
|
||||
* interaction.reply({ content: 'Pong!', fetchReply: true })
|
||||
* .then((message) => console.log(`Reply sent with content ${message.content}`))
|
||||
* interaction.reply({ content: 'Pong!', withResponse: true })
|
||||
* .then((response) => console.log(`Reply sent with content ${response.resource.message.content}`))
|
||||
* .catch(console.error);
|
||||
* @example
|
||||
* // 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);
|
||||
*/
|
||||
async reply(options) {
|
||||
if (this.deferred || this.replied) throw new DiscordjsError(ErrorCodes.InteractionAlreadyReplied);
|
||||
|
||||
if (typeof options !== 'string') {
|
||||
if ('ephemeral' in options) {
|
||||
if (!deprecationEmittedForEphemeralOption) {
|
||||
process.emitWarning(
|
||||
`Supplying "ephemeral" for interaction response options is deprecated. Utilize flags instead.`,
|
||||
);
|
||||
|
||||
deprecationEmittedForEphemeralOption = true;
|
||||
}
|
||||
}
|
||||
|
||||
if ('fetchReply' in options) {
|
||||
if (!deprecationEmittedForFetchReplyOption) {
|
||||
process.emitWarning(
|
||||
// eslint-disable-next-line max-len
|
||||
`Supplying "fetchReply" for interaction response options is deprecated. Utilize "withResponse" instead or fetch the response after using the method.`,
|
||||
);
|
||||
|
||||
deprecationEmittedForFetchReplyOption = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let messagePayload;
|
||||
if (options instanceof MessagePayload) messagePayload = options;
|
||||
else messagePayload = MessagePayload.create(this, options);
|
||||
|
||||
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), {
|
||||
const response = await this.client.rest.post(Routes.interactionCallback(this.id, this.token), {
|
||||
body: {
|
||||
type: InteractionResponseType.ChannelMessageWithSource,
|
||||
data,
|
||||
},
|
||||
files,
|
||||
auth: false,
|
||||
query: makeURLSearchParams({ with_response: options.withResponse ?? false }),
|
||||
});
|
||||
|
||||
this.ephemeral = Boolean(data.flags & MessageFlags.Ephemeral);
|
||||
this.replied = true;
|
||||
|
||||
return options.fetchReply ? this.fetchReply() : new InteractionResponse(this);
|
||||
return options.withResponse
|
||||
? new InteractionCallbackResponse(this.client, response)
|
||||
: options.fetchReply
|
||||
? this.fetchReply()
|
||||
: new InteractionResponse(this);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -176,6 +262,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);
|
||||
}
|
||||
|
||||
@@ -184,15 +272,17 @@ class InteractionResponses {
|
||||
* @param {string|MessagePayload|InteractionReplyOptions} options The options for the reply
|
||||
* @returns {Promise<Message>}
|
||||
*/
|
||||
followUp(options) {
|
||||
if (!this.deferred && !this.replied) return Promise.reject(new DiscordjsError(ErrorCodes.InteractionNotReplied));
|
||||
return this.webhook.send(options);
|
||||
async followUp(options) {
|
||||
if (!this.deferred && !this.replied) throw new DiscordjsError(ErrorCodes.InteractionNotReplied);
|
||||
const msg = await this.webhook.send(options);
|
||||
this.replied = true;
|
||||
return msg;
|
||||
}
|
||||
|
||||
/**
|
||||
* Defers an update to the message to which the component was attached.
|
||||
* @param {InteractionDeferUpdateOptions} [options] Options for deferring the update to this interaction
|
||||
* @returns {Promise<Message|InteractionResponse>}
|
||||
* @returns {Promise<InteractionCallbackResponse|Message|InteractionResponse>}
|
||||
* @example
|
||||
* // Defer updating and reset the component's loading state
|
||||
* interaction.deferUpdate()
|
||||
@@ -201,21 +291,38 @@ class InteractionResponses {
|
||||
*/
|
||||
async deferUpdate(options = {}) {
|
||||
if (this.deferred || this.replied) throw new DiscordjsError(ErrorCodes.InteractionAlreadyReplied);
|
||||
await this.client.rest.post(Routes.interactionCallback(this.id, this.token), {
|
||||
|
||||
if ('fetchReply' in options) {
|
||||
if (!deprecationEmittedForFetchReplyOption) {
|
||||
process.emitWarning(
|
||||
// eslint-disable-next-line max-len
|
||||
`Supplying "fetchReply" for interaction response options is deprecated. Utilize "withResponse" instead or fetch the response after using the method.`,
|
||||
);
|
||||
|
||||
deprecationEmittedForFetchReplyOption = true;
|
||||
}
|
||||
}
|
||||
|
||||
const response = await this.client.rest.post(Routes.interactionCallback(this.id, this.token), {
|
||||
body: {
|
||||
type: InteractionResponseType.DeferredMessageUpdate,
|
||||
},
|
||||
auth: false,
|
||||
query: makeURLSearchParams({ with_response: options.withResponse ?? false }),
|
||||
});
|
||||
this.deferred = true;
|
||||
|
||||
return options.fetchReply ? this.fetchReply() : new InteractionResponse(this, this.message?.interaction?.id);
|
||||
return options.withResponse
|
||||
? new InteractionCallbackResponse(this.client, response)
|
||||
: options.fetchReply
|
||||
? this.fetchReply()
|
||||
: new InteractionResponse(this, this.message?.interactionMetadata?.id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the original message of the component on which the interaction was received on.
|
||||
* @param {string|MessagePayload|InteractionUpdateOptions} options The options for the updated message
|
||||
* @returns {Promise<Message|void>}
|
||||
* @returns {Promise<InteractionCallbackResponse|Message|void>}
|
||||
* @example
|
||||
* // Remove the components from the message
|
||||
* interaction.update({
|
||||
@@ -228,40 +335,60 @@ class InteractionResponses {
|
||||
async update(options) {
|
||||
if (this.deferred || this.replied) throw new DiscordjsError(ErrorCodes.InteractionAlreadyReplied);
|
||||
|
||||
if (typeof options !== 'string' && 'fetchReply' in options) {
|
||||
if (!deprecationEmittedForFetchReplyOption) {
|
||||
process.emitWarning(
|
||||
// eslint-disable-next-line max-len
|
||||
`Supplying "fetchReply" for interaction response options is deprecated. Utilize "withResponse" instead or fetch the response after using the method.`,
|
||||
);
|
||||
|
||||
deprecationEmittedForFetchReplyOption = true;
|
||||
}
|
||||
}
|
||||
|
||||
let messagePayload;
|
||||
if (options instanceof MessagePayload) messagePayload = options;
|
||||
else messagePayload = MessagePayload.create(this, options);
|
||||
|
||||
const { body: data, files } = await messagePayload.resolveBody().resolveFiles();
|
||||
|
||||
await this.client.rest.post(Routes.interactionCallback(this.id, this.token), {
|
||||
const response = await this.client.rest.post(Routes.interactionCallback(this.id, this.token), {
|
||||
body: {
|
||||
type: InteractionResponseType.UpdateMessage,
|
||||
data,
|
||||
},
|
||||
files,
|
||||
auth: false,
|
||||
query: makeURLSearchParams({ with_response: options.withResponse ?? false }),
|
||||
});
|
||||
this.replied = true;
|
||||
|
||||
return options.fetchReply ? this.fetchReply() : new InteractionResponse(this, this.message.interaction?.id);
|
||||
return options.withResponse
|
||||
? new InteractionCallbackResponse(this.client, response)
|
||||
: options.fetchReply
|
||||
? this.fetchReply()
|
||||
: new InteractionResponse(this, this.message.interactionMetadata?.id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows a modal component
|
||||
* @param {ModalBuilder|ModalComponentData|APIModalInteractionResponseCallbackData} modal The modal to show
|
||||
* @returns {Promise<void>}
|
||||
* @param {ShowModalOptions} [options={}] The options for sending this interaction response
|
||||
* @returns {Promise<InteractionCallbackResponse|undefined>}
|
||||
*/
|
||||
async showModal(modal) {
|
||||
async showModal(modal, options = {}) {
|
||||
if (this.deferred || this.replied) throw new DiscordjsError(ErrorCodes.InteractionAlreadyReplied);
|
||||
await this.client.rest.post(Routes.interactionCallback(this.id, this.token), {
|
||||
const response = await this.client.rest.post(Routes.interactionCallback(this.id, this.token), {
|
||||
body: {
|
||||
type: InteractionResponseType.Modal,
|
||||
data: isJSONEncodable(modal) ? modal.toJSON() : this.client.options.jsonTransformer(modal),
|
||||
},
|
||||
auth: false,
|
||||
query: makeURLSearchParams({ with_response: options.withResponse ?? false }),
|
||||
});
|
||||
this.replied = true;
|
||||
|
||||
return options.withResponse ? new InteractionCallbackResponse(this.client, response) : undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -300,7 +427,7 @@ class InteractionResponses {
|
||||
* .then(interaction => console.log(`${interaction.customId} was submitted!`))
|
||||
* .catch(console.error);
|
||||
*/
|
||||
awaitModalSubmit(options) {
|
||||
async awaitModalSubmit(options) {
|
||||
if (typeof options.time !== 'number') throw new DiscordjsError(ErrorCodes.InvalidType, 'time', 'number');
|
||||
const _options = { ...options, max: 1, interactionType: InteractionType.ModalSubmit };
|
||||
return new Promise((resolve, reject) => {
|
||||
|
||||
@@ -75,7 +75,7 @@ class TextBasedChannel {
|
||||
* @property {?string} [content=''] The content for the message. This can only be `null` when editing a message.
|
||||
* @property {Array<(EmbedBuilder|Embed|APIEmbed)>} [embeds] The embeds for the message
|
||||
* @property {MessageMentionOptions} [allowedMentions] Which mentions should be parsed from the message content
|
||||
* (see [here](https://discord.com/developers/docs/resources/message#allowed-mentions-object) for more details)
|
||||
* (see {@link https://discord.com/developers/docs/resources/message#allowed-mentions-object here} for more details)
|
||||
* @property {Array<(AttachmentBuilder|Attachment|AttachmentPayload|BufferResolvable)>} [files]
|
||||
* The files to send with the message.
|
||||
* @property {Array<(ActionRowBuilder|ActionRow|APIActionRowComponent)>} [components]
|
||||
@@ -110,10 +110,18 @@ class TextBasedChannel {
|
||||
* <info>Only `MessageFlags.SuppressEmbeds` and `MessageFlags.SuppressNotifications` can be set.</info>
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {Object} ForwardOptions
|
||||
* @property {MessageResolvable} message The originating message
|
||||
* @property {TextBasedChannelResolvable} [channel] The channel of the originating message
|
||||
* @property {GuildResolvable} [guild] The guild of the originating message
|
||||
*/
|
||||
|
||||
/**
|
||||
* The options for sending a message.
|
||||
* @typedef {BaseMessageCreateOptions} MessageCreateOptions
|
||||
* @property {ReplyOptions} [reply] The options for replying to a message
|
||||
* @property {ForwardOptions} [forward] The options for forwarding a message
|
||||
*/
|
||||
|
||||
/**
|
||||
|
||||
@@ -100,6 +100,16 @@
|
||||
* @see {@link https://discord-api-types.dev/api/discord-api-types-v10/interface/APIGuildMember}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @external APIGuildScheduledEventRecurrenceRule
|
||||
* @see {@link https://discord-api-types.dev/api/discord-api-types-v10/interface/APIGuildScheduledEventRecurrenceRule}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @external APIIncidentsData
|
||||
* @see {@link https://discord-api-types.dev/api/discord-api-types-v10/interface/APIIncidentsData}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @external APIInteraction
|
||||
* @see {@link https://discord-api-types.dev/api/discord-api-types-v10#APIInteraction}
|
||||
@@ -250,6 +260,16 @@
|
||||
* @see {@link https://discord-api-types.dev/api/discord-api-types-v10/enum/ApplicationRoleConnectionMetadataType}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @external ApplicationWebhookEventStatus
|
||||
* @see {@link https://discord-api-types.dev/api/discord-api-types-v10/enum/ApplicationWebhookEventStatus}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @external ApplicationWebhookEventType
|
||||
* @see {@link https://discord-api-types.dev/api/discord-api-types-v10/enum/ApplicationWebhookEventType}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @external AttachmentFlags
|
||||
* @see {@link https://discord-api-types.dev/api/discord-api-types-v10/enum/AttachmentFlags}
|
||||
@@ -390,6 +410,21 @@
|
||||
* @see {@link https://discord-api-types.dev/api/discord-api-types-v10/enum/GuildScheduledEventPrivacyLevel}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @external GuildScheduledEventRecurrenceRuleFrequency
|
||||
* @see {@link https://discord-api-types.dev/api/discord-api-types-v10/enum/GuildScheduledEventRecurrenceRuleFrequency}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @external GuildScheduledEventRecurrenceRuleMonth
|
||||
* @see {@link https://discord-api-types.dev/api/discord-api-types-v10/enum/GuildScheduledEventRecurrenceRuleMonth}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @external GuildScheduledEventRecurrenceRuleWeekday
|
||||
* @see {@link https://discord-api-types.dev/api/discord-api-types-v10/enum/GuildScheduledEventRecurrenceRuleWeekday}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @external GuildScheduledEventStatus
|
||||
* @see {@link https://discord-api-types.dev/api/discord-api-types-v10/enum/GuildScheduledEventStatus}
|
||||
@@ -442,12 +477,7 @@
|
||||
|
||||
/**
|
||||
* @external Locale
|
||||
* @see {@link https://discord-api-types.dev/api/discord-api-types-rest/common/enum/Locale}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @external LocaleString
|
||||
* @see {@link https://discord-api-types.dev/api/discord-api-types-rest/common#LocaleString}
|
||||
* @see {@link https://discord-api-types.dev/api/discord-api-types-v10/enum/Locale}
|
||||
*/
|
||||
|
||||
/**
|
||||
@@ -455,6 +485,11 @@
|
||||
* @see {@link https://discord-api-types.dev/api/discord-api-types-v10/enum/MessageActivityType}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @external MessageReferenceType
|
||||
* @see {@link https://discord-api-types.dev/api/discord-api-types-v10/enum/MessageReferenceType}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @external MessageType
|
||||
* @see {@link https://discord-api-types.dev/api/discord-api-types-v10/enum/MessageType}
|
||||
@@ -477,7 +512,7 @@
|
||||
|
||||
/**
|
||||
* @external PermissionFlagsBits
|
||||
* @see {@link https://discord-api-types.dev/api/discord-api-types-payloads/common#PermissionFlagsBits}
|
||||
* @see {@link https://discord-api-types.dev/api/discord-api-types-v10#PermissionFlagsBits}
|
||||
*/
|
||||
|
||||
/**
|
||||
@@ -485,6 +520,11 @@
|
||||
* @see {@link https://discord-api-types.dev/api/discord-api-types-v10/enum/PollLayoutType}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @external ReactionType
|
||||
* @see {@link https://discord-api-types.dev/api/discord-api-types-v10/enum/ReactionType}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @external RoleFlags
|
||||
* @see {@link https://discord-api-types.dev/api/discord-api-types-v10/enum/RoleFlags}
|
||||
@@ -497,7 +537,7 @@
|
||||
|
||||
/**
|
||||
* @external RESTJSONErrorCodes
|
||||
* @see {@link https://discord-api-types.dev/api/discord-api-types-rest/common/enum/RESTJSONErrorCodes}
|
||||
* @see {@link https://discord-api-types.dev/api/discord-api-types-v10/enum/RESTJSONErrorCodes}
|
||||
*/
|
||||
|
||||
/**
|
||||
@@ -560,6 +600,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}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
'use strict';
|
||||
|
||||
// This file contains the typedefs for camel-cased JSON data
|
||||
const { ComponentBuilder } = require('@discordjs/builders');
|
||||
const { ComponentType } = require('discord-api-types/v10');
|
||||
|
||||
/**
|
||||
* @typedef {Object} BaseComponentData
|
||||
* @property {ComponentType} type The type of component
|
||||
@@ -71,6 +71,7 @@ const { ComponentType } = require('discord-api-types/v10');
|
||||
* Transforms API data into a component
|
||||
* @param {APIMessageComponent|Component} data The data to create the component from
|
||||
* @returns {Component}
|
||||
* @ignore
|
||||
*/
|
||||
function createComponent(data) {
|
||||
if (data instanceof Component) {
|
||||
@@ -103,6 +104,7 @@ function createComponent(data) {
|
||||
* Transforms API data into a component builder
|
||||
* @param {APIMessageComponent|ComponentBuilder} data The data to create the component from
|
||||
* @returns {ComponentBuilder}
|
||||
* @ignore
|
||||
*/
|
||||
function createComponentBuilder(data) {
|
||||
if (data instanceof ComponentBuilder) {
|
||||
|
||||
@@ -69,6 +69,9 @@
|
||||
* @property {string} StageInstanceCreate stageInstanceCreate
|
||||
* @property {string} StageInstanceDelete stageInstanceDelete
|
||||
* @property {string} StageInstanceUpdate stageInstanceUpdate
|
||||
* @property {string} SubscriptionCreate subscriptionCreate
|
||||
* @property {string} SubscriptionUpdate subscriptionUpdate
|
||||
* @property {string} SubscriptionDelete subscriptionDelete
|
||||
* @property {string} ThreadCreate threadCreate
|
||||
* @property {string} ThreadDelete threadDelete
|
||||
* @property {string} ThreadListSync threadListSync
|
||||
@@ -77,6 +80,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
|
||||
@@ -157,6 +161,9 @@ module.exports = {
|
||||
StageInstanceCreate: 'stageInstanceCreate',
|
||||
StageInstanceDelete: 'stageInstanceDelete',
|
||||
StageInstanceUpdate: 'stageInstanceUpdate',
|
||||
SubscriptionCreate: 'subscriptionCreate',
|
||||
SubscriptionUpdate: 'subscriptionUpdate',
|
||||
SubscriptionDelete: 'subscriptionDelete',
|
||||
ThreadCreate: 'threadCreate',
|
||||
ThreadDelete: 'threadDelete',
|
||||
ThreadListSync: 'threadListSync',
|
||||
@@ -165,6 +172,7 @@ module.exports = {
|
||||
ThreadUpdate: 'threadUpdate',
|
||||
TypingStart: 'typingStart',
|
||||
UserUpdate: 'userUpdate',
|
||||
VoiceChannelEffectSend: 'voiceChannelEffectSend',
|
||||
VoiceServerUpdate: 'voiceServerUpdate',
|
||||
VoiceStateUpdate: 'voiceStateUpdate',
|
||||
Warn: 'warn',
|
||||
|
||||
@@ -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}
|
||||
|
||||
@@ -30,7 +30,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
|
||||
@@ -41,7 +41,7 @@ const { version } = require('../../package.json');
|
||||
* @property {WebsocketOptions} [ws] Options for the WebSocket
|
||||
* @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}
|
||||
*/
|
||||
|
||||
/**
|
||||
|
||||
@@ -54,4 +54,43 @@ function _transformAPIMessageInteractionMetadata(client, messageInteractionMetad
|
||||
};
|
||||
}
|
||||
|
||||
module.exports = { toSnakeCase, _transformAPIAutoModerationAction, _transformAPIMessageInteractionMetadata };
|
||||
/**
|
||||
* Transforms a guild scheduled event recurrence rule object to a snake-cased variant.
|
||||
* @param {GuildScheduledEventRecurrenceRuleOptions} recurrenceRule The recurrence rule to transform
|
||||
* @returns {APIGuildScheduledEventRecurrenceRule}
|
||||
* @ignore
|
||||
*/
|
||||
function _transformGuildScheduledEventRecurrenceRule(recurrenceRule) {
|
||||
return {
|
||||
start: new Date(recurrenceRule.startAt).toISOString(),
|
||||
frequency: recurrenceRule.frequency,
|
||||
interval: recurrenceRule.interval,
|
||||
by_weekday: recurrenceRule.byWeekday,
|
||||
by_n_weekday: recurrenceRule.byNWeekday,
|
||||
by_month: recurrenceRule.byMonth,
|
||||
by_month_day: recurrenceRule.byMonthDay,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Transforms API incidents data to a camel-cased variant.
|
||||
* @param {APIIncidentsData} data The incidents data to transform
|
||||
* @returns {IncidentActions}
|
||||
* @ignore
|
||||
*/
|
||||
function _transformAPIIncidentsData(data) {
|
||||
return {
|
||||
invitesDisabledUntil: data.invites_disabled_until ? new Date(data.invites_disabled_until) : null,
|
||||
dmsDisabledUntil: data.dms_disabled_until ? new Date(data.dms_disabled_until) : null,
|
||||
dmSpamDetectedAt: data.dm_spam_detected_at ? new Date(data.dm_spam_detected_at) : null,
|
||||
raidDetectedAt: data.raid_detected_at ? new Date(data.raid_detected_at) : null,
|
||||
};
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
toSnakeCase,
|
||||
_transformAPIAutoModerationAction,
|
||||
_transformAPIMessageInteractionMetadata,
|
||||
_transformGuildScheduledEventRecurrenceRule,
|
||||
_transformAPIIncidentsData,
|
||||
};
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
'use strict';
|
||||
|
||||
const { parse } = require('node:path');
|
||||
const process = require('node:process');
|
||||
const { Collection } = require('@discordjs/collection');
|
||||
const { ChannelType, RouteBases, Routes } = require('discord-api-types/v10');
|
||||
const { fetch } = require('undici');
|
||||
@@ -8,6 +9,9 @@ const Colors = require('./Colors');
|
||||
const { DiscordjsError, DiscordjsRangeError, DiscordjsTypeError, ErrorCodes } = require('../errors');
|
||||
const isObject = d => typeof d === 'object' && d !== null;
|
||||
|
||||
let deprecationEmittedForUserFetchFlags = false;
|
||||
let deprecationEmittedForRemoveThreadMember = false;
|
||||
|
||||
/**
|
||||
* Flatten an object. Any properties that are collections will get converted to an array of keys.
|
||||
* @param {Object} obj The object to flatten.
|
||||
@@ -499,6 +503,32 @@ function resolveSKUId(resolvable) {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Deprecation function for fetching user flags.
|
||||
* @param {string} name Name of the class
|
||||
* @private
|
||||
*/
|
||||
function emitDeprecationWarningForUserFetchFlags(name) {
|
||||
if (deprecationEmittedForUserFetchFlags) return;
|
||||
process.emitWarning(`${name}#fetchFlags() is deprecated. Use ${name}#fetch() instead.`);
|
||||
deprecationEmittedForUserFetchFlags = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Deprecation function for the reason parameter of removing thread members.
|
||||
* @param {string} name Name of the class
|
||||
* @private
|
||||
*/
|
||||
function emitDeprecationWarningForRemoveThreadMember(name) {
|
||||
if (deprecationEmittedForRemoveThreadMember) return;
|
||||
|
||||
process.emitWarning(
|
||||
`The reason parameter of ${name}#remove() is deprecated as Discord does not parse them. It will be removed in the next major version.`,
|
||||
);
|
||||
|
||||
deprecationEmittedForRemoveThreadMember = true;
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
flatten,
|
||||
fetchRecommendedShardCount,
|
||||
@@ -518,6 +548,8 @@ module.exports = {
|
||||
parseWebhookURL,
|
||||
transformResolved,
|
||||
resolveSKUId,
|
||||
emitDeprecationWarningForUserFetchFlags,
|
||||
emitDeprecationWarningForRemoveThreadMember,
|
||||
};
|
||||
|
||||
// Fixes Circular
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
'use strict';
|
||||
|
||||
const { token } = require('./auth.js');
|
||||
const { token, owner } = require('./auth.js');
|
||||
const { Client } = require('../src');
|
||||
const { ChannelType, GatewayIntentBits } = require('discord-api-types/v10');
|
||||
|
||||
@@ -14,6 +14,7 @@ const client = new Client({
|
||||
GatewayIntentBits.GuildMessages,
|
||||
GatewayIntentBits.GuildMessageReactions,
|
||||
GatewayIntentBits.GuildMembers,
|
||||
GatewayIntentBits.MessageContent,
|
||||
],
|
||||
});
|
||||
|
||||
@@ -186,7 +187,7 @@ client.on('messageCreate', msg => {
|
||||
msg.channel.send(`\`\`\`${msg.content}\`\`\``);
|
||||
}
|
||||
|
||||
if (msg.content.startsWith('#eval') && msg.author.id === '66564597481480192') {
|
||||
if (msg.content.startsWith('#eval') && msg.author.id === owner) {
|
||||
try {
|
||||
const com = eval(msg.content.split(' ').slice(1).join(' '));
|
||||
msg.channel.send(`\`\`\`\n${com}\`\`\``);
|
||||
|
||||
516
packages/discord.js/typings/index.d.ts
vendored
516
packages/discord.js/typings/index.d.ts
vendored
File diff suppressed because it is too large
Load Diff
@@ -33,6 +33,9 @@ import {
|
||||
APIMentionableSelectComponent,
|
||||
APIModalInteractionResponseCallbackData,
|
||||
WebhookType,
|
||||
GuildScheduledEventRecurrenceRuleFrequency,
|
||||
GuildScheduledEventRecurrenceRuleMonth,
|
||||
GuildScheduledEventRecurrenceRuleWeekday,
|
||||
} from 'discord-api-types/v10';
|
||||
import {
|
||||
ApplicationCommand,
|
||||
@@ -209,10 +212,22 @@ import {
|
||||
ApplicationEmoji,
|
||||
ApplicationEmojiManager,
|
||||
StickerPack,
|
||||
GuildScheduledEventManager,
|
||||
SendableChannels,
|
||||
PollData,
|
||||
UserManager,
|
||||
InteractionCallbackResponse,
|
||||
GuildScheduledEventRecurrenceRuleOptions,
|
||||
ThreadOnlyChannel,
|
||||
} from '.';
|
||||
import { expectAssignable, expectDeprecated, expectNotAssignable, expectNotType, expectType } from 'tsd';
|
||||
import {
|
||||
expectAssignable,
|
||||
expectDeprecated,
|
||||
expectNotAssignable,
|
||||
expectNotDeprecated,
|
||||
expectNotType,
|
||||
expectType,
|
||||
} from 'tsd';
|
||||
import type { ContextMenuCommandBuilder, SlashCommandBuilder } from '@discordjs/builders';
|
||||
import { ReadonlyCollection } from '@discordjs/collection';
|
||||
|
||||
@@ -436,6 +451,7 @@ client.on('messageCreate', async message => {
|
||||
const component = await message.awaitMessageComponent({ componentType: ComponentType.Button });
|
||||
expectType<ButtonInteraction<'cached'>>(component);
|
||||
expectType<Message<true>>(await component.reply({ fetchReply: true }));
|
||||
expectType<InteractionCallbackResponse>(await component.reply({ withResponse: true }));
|
||||
|
||||
const buttonCollector = message.createMessageComponentCollector({ componentType: ComponentType.Button });
|
||||
expectType<InteractionCollector<ButtonInteraction<'cached'>>>(buttonCollector);
|
||||
@@ -1750,6 +1766,19 @@ declare const threadMemberManager: ThreadMemberManager;
|
||||
threadMemberManager.fetch({ cache: true, force: false });
|
||||
// @ts-expect-error `withMember` needs to be `true` to receive paginated results.
|
||||
threadMemberManager.fetch({ withMember: false, limit: 5, after: '12345678901234567' });
|
||||
|
||||
expectNotDeprecated(threadMemberManager.add('1234678'));
|
||||
expectDeprecated(threadMemberManager.add('1234678', 'reason'));
|
||||
expectNotDeprecated(threadMemberManager.remove('1234678'));
|
||||
expectDeprecated(threadMemberManager.remove('1234678', 'reason'));
|
||||
expectNotDeprecated(threadMemberWithGuildMember.remove());
|
||||
expectDeprecated(threadMemberWithGuildMember.remove('reason'));
|
||||
}
|
||||
|
||||
declare const userManager: UserManager;
|
||||
{
|
||||
expectDeprecated(userManager.fetchFlags('1234567890'));
|
||||
expectDeprecated(user.fetchFlags());
|
||||
}
|
||||
|
||||
declare const typing: Typing;
|
||||
@@ -1790,10 +1819,14 @@ client.on('interactionCreate', async interaction => {
|
||||
expectType<Guild>(interaction.guild);
|
||||
expectType<Promise<Message<true>>>(interaction.reply({ content: 'a', fetchReply: true }));
|
||||
expectType<Promise<Message<true>>>(interaction.deferReply({ fetchReply: true }));
|
||||
expectType<Promise<InteractionCallbackResponse>>(interaction.reply({ content: 'a', withResponse: true }));
|
||||
expectType<Promise<InteractionCallbackResponse>>(interaction.deferReply({ withResponse: true }));
|
||||
expectType<Promise<Message<true>>>(interaction.editReply({ content: 'a' }));
|
||||
expectType<Promise<Message<true>>>(interaction.fetchReply());
|
||||
expectType<Promise<Message<true>>>(interaction.update({ content: 'a', fetchReply: true }));
|
||||
expectType<Promise<Message<true>>>(interaction.deferUpdate({ fetchReply: true }));
|
||||
expectType<Promise<InteractionCallbackResponse>>(interaction.update({ content: 'a', withResponse: true }));
|
||||
expectType<Promise<InteractionCallbackResponse>>(interaction.deferUpdate({ withResponse: true }));
|
||||
expectType<Promise<Message<true>>>(interaction.followUp({ content: 'a' }));
|
||||
} else if (interaction.inRawGuild()) {
|
||||
expectAssignable<MessageComponentInteraction>(interaction);
|
||||
@@ -1802,10 +1835,14 @@ client.on('interactionCreate', async interaction => {
|
||||
expectType<null>(interaction.guild);
|
||||
expectType<Promise<Message<false>>>(interaction.reply({ content: 'a', fetchReply: true }));
|
||||
expectType<Promise<Message<false>>>(interaction.deferReply({ fetchReply: true }));
|
||||
expectType<Promise<InteractionCallbackResponse>>(interaction.reply({ content: 'a', withResponse: true }));
|
||||
expectType<Promise<InteractionCallbackResponse>>(interaction.deferReply({ withResponse: true }));
|
||||
expectType<Promise<Message<false>>>(interaction.editReply({ content: 'a' }));
|
||||
expectType<Promise<Message<false>>>(interaction.fetchReply());
|
||||
expectType<Promise<Message<false>>>(interaction.update({ content: 'a', fetchReply: true }));
|
||||
expectType<Promise<Message<false>>>(interaction.deferUpdate({ fetchReply: true }));
|
||||
expectType<Promise<InteractionCallbackResponse>>(interaction.update({ content: 'a', withResponse: true }));
|
||||
expectType<Promise<InteractionCallbackResponse>>(interaction.deferUpdate({ withResponse: true }));
|
||||
expectType<Promise<Message<false>>>(interaction.followUp({ content: 'a' }));
|
||||
} else if (interaction.inGuild()) {
|
||||
expectAssignable<MessageComponentInteraction>(interaction);
|
||||
@@ -1814,10 +1851,14 @@ client.on('interactionCreate', async interaction => {
|
||||
expectType<Guild | null>(interaction.guild);
|
||||
expectType<Promise<Message>>(interaction.reply({ content: 'a', fetchReply: true }));
|
||||
expectType<Promise<Message>>(interaction.deferReply({ fetchReply: true }));
|
||||
expectType<Promise<InteractionCallbackResponse>>(interaction.reply({ content: 'a', withResponse: true }));
|
||||
expectType<Promise<InteractionCallbackResponse>>(interaction.deferReply({ withResponse: true }));
|
||||
expectType<Promise<Message>>(interaction.editReply({ content: 'a' }));
|
||||
expectType<Promise<Message>>(interaction.fetchReply());
|
||||
expectType<Promise<Message>>(interaction.update({ content: 'a', fetchReply: true }));
|
||||
expectType<Promise<Message>>(interaction.deferUpdate({ fetchReply: true }));
|
||||
expectType<Promise<InteractionCallbackResponse>>(interaction.update({ content: 'a', withResponse: true }));
|
||||
expectType<Promise<InteractionCallbackResponse>>(interaction.deferUpdate({ withResponse: true }));
|
||||
expectType<Promise<Message>>(interaction.followUp({ content: 'a' }));
|
||||
}
|
||||
}
|
||||
@@ -1853,6 +1894,8 @@ client.on('interactionCreate', async interaction => {
|
||||
expectAssignable<CommandInteraction<'cached'>>(interaction);
|
||||
expectType<Promise<Message<true>>>(interaction.reply({ content: 'a', fetchReply: true }));
|
||||
expectType<Promise<Message<true>>>(interaction.deferReply({ fetchReply: true }));
|
||||
expectType<Promise<InteractionCallbackResponse>>(interaction.reply({ content: 'a', withResponse: true }));
|
||||
expectType<Promise<InteractionCallbackResponse>>(interaction.deferReply({ withResponse: true }));
|
||||
expectType<Promise<Message<true>>>(interaction.editReply({ content: 'a' }));
|
||||
expectType<Promise<Message<true>>>(interaction.fetchReply());
|
||||
expectType<Promise<Message<true>>>(interaction.followUp({ content: 'a' }));
|
||||
@@ -1861,6 +1904,8 @@ client.on('interactionCreate', async interaction => {
|
||||
expectType<null>(interaction.guild);
|
||||
expectType<Promise<Message<false>>>(interaction.reply({ content: 'a', fetchReply: true }));
|
||||
expectType<Promise<Message<false>>>(interaction.deferReply({ fetchReply: true }));
|
||||
expectType<Promise<InteractionCallbackResponse>>(interaction.reply({ content: 'a', withResponse: true }));
|
||||
expectType<Promise<InteractionCallbackResponse>>(interaction.deferReply({ withResponse: true }));
|
||||
expectType<Promise<Message<false>>>(interaction.editReply({ content: 'a' }));
|
||||
expectType<Promise<Message<false>>>(interaction.fetchReply());
|
||||
expectType<Promise<Message<false>>>(interaction.followUp({ content: 'a' }));
|
||||
@@ -1869,6 +1914,8 @@ client.on('interactionCreate', async interaction => {
|
||||
expectType<Guild | null>(interaction.guild);
|
||||
expectType<Promise<Message>>(interaction.reply({ content: 'a', fetchReply: true }));
|
||||
expectType<Promise<Message>>(interaction.deferReply({ fetchReply: true }));
|
||||
expectType<Promise<InteractionCallbackResponse>>(interaction.reply({ content: 'a', withResponse: true }));
|
||||
expectType<Promise<InteractionCallbackResponse>>(interaction.deferReply({ withResponse: true }));
|
||||
expectType<Promise<Message>>(interaction.editReply({ content: 'a' }));
|
||||
expectType<Promise<Message>>(interaction.fetchReply());
|
||||
expectType<Promise<Message>>(interaction.followUp({ content: 'a' }));
|
||||
@@ -1923,18 +1970,21 @@ client.on('interactionCreate', async interaction => {
|
||||
expectType<Message<true>>(interaction.message);
|
||||
expectType<Guild>(interaction.guild);
|
||||
expectType<Promise<Message<true>>>(interaction.reply({ fetchReply: true }));
|
||||
expectType<Promise<InteractionCallbackResponse>>(interaction.reply({ withResponse: true }));
|
||||
} else if (interaction.inRawGuild()) {
|
||||
expectAssignable<ButtonInteraction>(interaction);
|
||||
expectType<APIButtonComponent>(interaction.component);
|
||||
expectType<Message<false>>(interaction.message);
|
||||
expectType<null>(interaction.guild);
|
||||
expectType<Promise<Message<false>>>(interaction.reply({ fetchReply: true }));
|
||||
expectType<Promise<InteractionCallbackResponse>>(interaction.reply({ withResponse: true }));
|
||||
} else if (interaction.inGuild()) {
|
||||
expectAssignable<ButtonInteraction>(interaction);
|
||||
expectType<ButtonComponent | APIButtonComponent>(interaction.component);
|
||||
expectType<Message>(interaction.message);
|
||||
expectAssignable<Guild | null>(interaction.guild);
|
||||
expectType<Promise<Message>>(interaction.reply({ fetchReply: true }));
|
||||
expectType<Promise<InteractionCallbackResponse>>(interaction.reply({ withResponse: true }));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1951,18 +2001,21 @@ client.on('interactionCreate', async interaction => {
|
||||
expectType<Message<true>>(interaction.message);
|
||||
expectType<Guild>(interaction.guild);
|
||||
expectType<Promise<Message<true>>>(interaction.reply({ fetchReply: true }));
|
||||
expectType<Promise<InteractionCallbackResponse>>(interaction.reply({ withResponse: true }));
|
||||
} else if (interaction.inRawGuild()) {
|
||||
expectAssignable<StringSelectMenuInteraction>(interaction);
|
||||
expectType<APIStringSelectComponent>(interaction.component);
|
||||
expectType<Message<false>>(interaction.message);
|
||||
expectType<null>(interaction.guild);
|
||||
expectType<Promise<Message<false>>>(interaction.reply({ fetchReply: true }));
|
||||
expectType<Promise<InteractionCallbackResponse>>(interaction.reply({ withResponse: true }));
|
||||
} else if (interaction.inGuild()) {
|
||||
expectAssignable<StringSelectMenuInteraction>(interaction);
|
||||
expectType<SelectMenuComponent | APIStringSelectComponent>(interaction.component);
|
||||
expectType<Message>(interaction.message);
|
||||
expectType<Guild | null>(interaction.guild);
|
||||
expectType<Promise<Message>>(interaction.reply({ fetchReply: true }));
|
||||
expectType<Promise<InteractionCallbackResponse>>(interaction.reply({ withResponse: true }));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1975,6 +2028,7 @@ client.on('interactionCreate', async interaction => {
|
||||
expectNotAssignable<Interaction<'cached'>>(interaction);
|
||||
expectAssignable<ChatInputCommandInteraction>(interaction);
|
||||
expectType<Promise<Message<false>>>(interaction.reply({ fetchReply: true }));
|
||||
expectType<Promise<InteractionCallbackResponse>>(interaction.reply({ withResponse: true }));
|
||||
expectType<APIInteractionDataResolvedGuildMember | null>(interaction.options.getMember('test'));
|
||||
|
||||
expectType<APIInteractionDataResolvedChannel>(interaction.options.getChannel('test', true));
|
||||
@@ -1989,6 +2043,7 @@ client.on('interactionCreate', async interaction => {
|
||||
expectType<GuildMember | null>(interaction.options.getMember('test'));
|
||||
expectAssignable<ChatInputCommandInteraction>(interaction);
|
||||
expectType<Promise<Message<true>>>(interaction.reply({ fetchReply: true }));
|
||||
expectType<Promise<InteractionCallbackResponse>>(interaction.reply({ withResponse: true }));
|
||||
|
||||
expectType<GuildBasedChannel>(interaction.options.getChannel('test', true));
|
||||
expectType<Role>(interaction.options.getRole('test', true));
|
||||
@@ -2011,10 +2066,9 @@ client.on('interactionCreate', async interaction => {
|
||||
);
|
||||
expectType<MediaChannel>(interaction.options.getChannel('test', true, [ChannelType.GuildMedia]));
|
||||
} else {
|
||||
// @ts-expect-error
|
||||
consumeCachedCommand(interaction);
|
||||
expectType<ChatInputCommandInteraction>(interaction);
|
||||
expectType<Promise<Message>>(interaction.reply({ fetchReply: true }));
|
||||
expectType<Promise<InteractionCallbackResponse>>(interaction.reply({ withResponse: true }));
|
||||
expectType<APIInteractionDataResolvedGuildMember | GuildMember | null>(interaction.options.getMember('test'));
|
||||
|
||||
expectType<GuildBasedChannel | APIInteractionDataResolvedChannel>(interaction.options.getChannel('test', true));
|
||||
@@ -2070,27 +2124,36 @@ client.on('interactionCreate', async interaction => {
|
||||
expectType<Guild>(interaction.guild);
|
||||
expectType<Promise<Message<true>>>(interaction.reply({ content: 'a', fetchReply: true }));
|
||||
expectType<Promise<Message<true>>>(interaction.deferReply({ fetchReply: true }));
|
||||
expectType<Promise<InteractionCallbackResponse>>(interaction.reply({ content: 'a', withResponse: true }));
|
||||
expectType<Promise<InteractionCallbackResponse>>(interaction.deferReply({ withResponse: true }));
|
||||
expectType<Promise<Message<true>>>(interaction.editReply({ content: 'a' }));
|
||||
expectType<Promise<Message<true>>>(interaction.fetchReply());
|
||||
expectType<Promise<Message<true>>>(interaction.deferUpdate({ fetchReply: true }));
|
||||
expectType<Promise<InteractionCallbackResponse>>(interaction.deferUpdate({ withResponse: true }));
|
||||
expectType<Promise<Message<true>>>(interaction.followUp({ content: 'a' }));
|
||||
} else if (interaction.inRawGuild()) {
|
||||
expectAssignable<ModalSubmitInteraction>(interaction);
|
||||
expectType<null>(interaction.guild);
|
||||
expectType<Promise<Message<false>>>(interaction.reply({ content: 'a', fetchReply: true }));
|
||||
expectType<Promise<Message<false>>>(interaction.deferReply({ fetchReply: true }));
|
||||
expectType<Promise<InteractionCallbackResponse>>(interaction.reply({ content: 'a', withResponse: true }));
|
||||
expectType<Promise<InteractionCallbackResponse>>(interaction.deferReply({ withResponse: true }));
|
||||
expectType<Promise<Message<false>>>(interaction.editReply({ content: 'a' }));
|
||||
expectType<Promise<Message<false>>>(interaction.fetchReply());
|
||||
expectType<Promise<Message<false>>>(interaction.deferUpdate({ fetchReply: true }));
|
||||
expectType<Promise<InteractionCallbackResponse>>(interaction.deferUpdate({ withResponse: true }));
|
||||
expectType<Promise<Message<false>>>(interaction.followUp({ content: 'a' }));
|
||||
} else if (interaction.inGuild()) {
|
||||
expectAssignable<ModalSubmitInteraction>(interaction);
|
||||
expectType<Guild | null>(interaction.guild);
|
||||
expectType<Promise<Message>>(interaction.reply({ content: 'a', fetchReply: true }));
|
||||
expectType<Promise<Message>>(interaction.deferReply({ fetchReply: true }));
|
||||
expectType<Promise<InteractionCallbackResponse>>(interaction.reply({ content: 'a', withResponse: true }));
|
||||
expectType<Promise<InteractionCallbackResponse>>(interaction.deferReply({ withResponse: true }));
|
||||
expectType<Promise<Message>>(interaction.editReply({ content: 'a' }));
|
||||
expectType<Promise<Message>>(interaction.fetchReply());
|
||||
expectType<Promise<Message>>(interaction.deferUpdate({ fetchReply: true }));
|
||||
expectType<Promise<InteractionCallbackResponse>>(interaction.deferUpdate({ withResponse: true }));
|
||||
expectType<Promise<Message>>(interaction.followUp({ content: 'a' }));
|
||||
}
|
||||
}
|
||||
@@ -2399,6 +2462,16 @@ declare const partialGroupDMChannel: PartialGroupDMChannel;
|
||||
declare const categoryChannel: CategoryChannel;
|
||||
declare const stageChannel: StageChannel;
|
||||
declare const forumChannel: ForumChannel;
|
||||
declare const mediaChannel: MediaChannel;
|
||||
declare const threadOnlyChannel: ThreadOnlyChannel;
|
||||
|
||||
// Threads have messages.
|
||||
expectType<GuildMessageManager>(threadChannel.messages);
|
||||
|
||||
// Thread-only channels have threads—not messages.
|
||||
notPropertyOf(threadOnlyChannel, 'messages');
|
||||
notPropertyOf(forumChannel, 'messages');
|
||||
notPropertyOf(mediaChannel, 'messages');
|
||||
|
||||
await forumChannel.edit({
|
||||
availableTags: [...forumChannel.availableTags, { name: 'tag' }],
|
||||
@@ -2618,3 +2691,92 @@ client.on('interactionCreate', interaction => {
|
||||
interaction.channel.send({ embeds: [] });
|
||||
}
|
||||
});
|
||||
|
||||
declare const guildScheduledEventManager: GuildScheduledEventManager;
|
||||
await guildScheduledEventManager.edit(snowflake, { recurrenceRule: null });
|
||||
|
||||
{
|
||||
expectNotAssignable<GuildScheduledEventRecurrenceRuleOptions>({
|
||||
startAt: new Date(),
|
||||
frequency: GuildScheduledEventRecurrenceRuleFrequency.Yearly,
|
||||
interval: 1,
|
||||
byMonth: [GuildScheduledEventRecurrenceRuleMonth.May],
|
||||
byMonthDay: [4],
|
||||
// Invalid property
|
||||
byWeekday: [GuildScheduledEventRecurrenceRuleWeekday.Monday],
|
||||
});
|
||||
|
||||
expectNotAssignable<GuildScheduledEventRecurrenceRuleOptions>({
|
||||
startAt: new Date(),
|
||||
frequency: GuildScheduledEventRecurrenceRuleFrequency.Yearly,
|
||||
interval: 1,
|
||||
byMonth: [GuildScheduledEventRecurrenceRuleMonth.May],
|
||||
byMonthDay: [4],
|
||||
// Invalid property
|
||||
byNWeekday: [{ n: 1, day: GuildScheduledEventRecurrenceRuleWeekday.Monday }],
|
||||
});
|
||||
|
||||
expectAssignable<GuildScheduledEventRecurrenceRuleOptions>({
|
||||
startAt: new Date(),
|
||||
frequency: GuildScheduledEventRecurrenceRuleFrequency.Yearly,
|
||||
interval: 1,
|
||||
byMonth: [GuildScheduledEventRecurrenceRuleMonth.May],
|
||||
byMonthDay: [4],
|
||||
});
|
||||
}
|
||||
|
||||
{
|
||||
expectAssignable<GuildScheduledEventRecurrenceRuleOptions>({
|
||||
startAt: new Date(),
|
||||
frequency: GuildScheduledEventRecurrenceRuleFrequency.Monthly,
|
||||
interval: 1,
|
||||
byNWeekday: [{ n: 1, day: GuildScheduledEventRecurrenceRuleWeekday.Monday }],
|
||||
});
|
||||
|
||||
expectNotAssignable<GuildScheduledEventRecurrenceRuleOptions>({
|
||||
startAt: new Date(),
|
||||
frequency: GuildScheduledEventRecurrenceRuleFrequency.Monthly,
|
||||
interval: 1,
|
||||
byNWeekday: [{ n: 1, day: GuildScheduledEventRecurrenceRuleWeekday.Monday }],
|
||||
// Invalid property
|
||||
byWeekday: [GuildScheduledEventRecurrenceRuleWeekday.Monday],
|
||||
});
|
||||
}
|
||||
|
||||
{
|
||||
expectAssignable<GuildScheduledEventRecurrenceRuleOptions>({
|
||||
startAt: new Date(),
|
||||
frequency: GuildScheduledEventRecurrenceRuleFrequency.Weekly,
|
||||
interval: 1,
|
||||
byWeekday: [GuildScheduledEventRecurrenceRuleWeekday.Monday],
|
||||
});
|
||||
|
||||
expectNotAssignable<GuildScheduledEventRecurrenceRuleOptions>({
|
||||
startAt: new Date(),
|
||||
frequency: GuildScheduledEventRecurrenceRuleFrequency.Weekly,
|
||||
interval: 1,
|
||||
byWeekday: [GuildScheduledEventRecurrenceRuleWeekday.Monday],
|
||||
// Invalid property
|
||||
byNWeekday: [{ n: 1, day: GuildScheduledEventRecurrenceRuleWeekday.Monday }],
|
||||
});
|
||||
}
|
||||
|
||||
{
|
||||
expectNotAssignable<GuildScheduledEventRecurrenceRuleOptions>({
|
||||
startAt: new Date(),
|
||||
frequency: GuildScheduledEventRecurrenceRuleFrequency.Daily,
|
||||
interval: 1,
|
||||
byWeekday: [GuildScheduledEventRecurrenceRuleWeekday.Monday],
|
||||
// Invalid property
|
||||
byNWeekday: [{ n: 1, day: GuildScheduledEventRecurrenceRuleWeekday.Monday }],
|
||||
});
|
||||
|
||||
expectNotAssignable<GuildScheduledEventRecurrenceRuleOptions>({
|
||||
startAt: new Date(),
|
||||
frequency: GuildScheduledEventRecurrenceRuleFrequency.Daily,
|
||||
interval: 1,
|
||||
byWeekday: [GuildScheduledEventRecurrenceRuleWeekday.Monday],
|
||||
// Invalid property
|
||||
byMonth: [GuildScheduledEventRecurrenceRuleMonth.May],
|
||||
});
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user