mirror of
https://github.com/discordjs/discord.js.git
synced 2026-05-23 20:10:08 +00:00
Compare commits
39 Commits
@discordjs
...
@discordjs
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8ab30cdefa | ||
|
|
c2a43b685e | ||
|
|
507b696792 | ||
|
|
15f7571243 | ||
|
|
3fa429c7df | ||
|
|
7713627fd1 | ||
|
|
6a5c0fb32d | ||
|
|
eb5acd1e30 | ||
|
|
127021d5ab | ||
|
|
0943bc2efb | ||
|
|
a1c83c17d6 | ||
|
|
c0eae344c2 | ||
|
|
f2f757ce52 | ||
|
|
65cfa3ffd3 | ||
|
|
ee2eb7349f | ||
|
|
2d19163d76 | ||
|
|
9bca4af5fd | ||
|
|
fe5e344adc | ||
|
|
c8f6066d6a | ||
|
|
7e21a9474e | ||
|
|
d0a535ea6a | ||
|
|
8124fc68be | ||
|
|
dbd5354056 | ||
|
|
2ebb5cbd53 | ||
|
|
096cd92b87 | ||
|
|
37ef57b880 | ||
|
|
e3c247e423 | ||
|
|
5f3fc170fb | ||
|
|
20fade2a87 | ||
|
|
e827644b5a | ||
|
|
62815928ab | ||
|
|
7fb6630c02 | ||
|
|
737b80b5f2 | ||
|
|
481ccd228b | ||
|
|
a3fff7b8be | ||
|
|
8cdbe23766 | ||
|
|
d920933dc5 | ||
|
|
2d817df3b5 | ||
|
|
1605a2c289 |
2
.github/workflows/cleanup-cache.yml
vendored
2
.github/workflows/cleanup-cache.yml
vendored
@@ -1,4 +1,4 @@
|
||||
# https://docs.github.com/en/actions/using-workflows/caching-dependencies-to-speed-up-workflows#force-deleting-cache-entries
|
||||
# https://docs.github.com/actions/using-workflows/caching-dependencies-to-speed-up-workflows#force-deleting-cache-entries
|
||||
name: Cleanup caches
|
||||
on:
|
||||
pull_request:
|
||||
|
||||
48
.github/workflows/documentation.yml
vendored
48
.github/workflows/documentation.yml
vendored
@@ -103,7 +103,15 @@ jobs:
|
||||
if: ${{ env.REF_TYPE == 'tag' && (!inputs.ref || inputs.ref == 'main') }}
|
||||
env:
|
||||
DATABASE_URL: ${{ secrets.DATABASE_URL }}
|
||||
CF_D1_DOCS_API_KEY: ${{ secrets.CF_D1_DOCS_API_KEY }}
|
||||
CF_D1_DOCS_ID: ${{ secrets.CF_D1_DOCS_ID }}
|
||||
CF_ACCOUNT_ID: ${{ secrets.CF_ACCOUNT_ID }}
|
||||
BLOB_READ_WRITE_TOKEN: ${{ secrets.BLOB_READ_WRITE_TOKEN }}
|
||||
CF_R2_DOCS_URL: ${{ secrets.CF_R2_DOCS_URL }}
|
||||
CF_R2_DOCS_ACCESS_KEY_ID: ${{ secrets.CF_R2_DOCS_ACCESS_KEY_ID }}
|
||||
CF_R2_DOCS_SECRET_ACCESS_KEY: ${{ secrets.CF_R2_DOCS_SECRET_ACCESS_KEY }}
|
||||
CF_R2_DOCS_BUCKET: ${{ secrets.CF_R2_DOCS_BUCKET }}
|
||||
CF_R2_DOCS_BUCKET_URL: ${{ secrets.CF_R2_DOCS_BUCKET_URL }}
|
||||
uses: ./packages/actions/src/uploadDocumentation
|
||||
with:
|
||||
package: ${{ steps.extract-tag.outputs.package }}
|
||||
@@ -113,7 +121,15 @@ jobs:
|
||||
if: ${{ env.REF_TYPE == 'tag' && inputs.ref && inputs.ref != 'main' }}
|
||||
env:
|
||||
DATABASE_URL: ${{ secrets.DATABASE_URL }}
|
||||
CF_D1_DOCS_API_KEY: ${{ secrets.CF_D1_DOCS_API_KEY }}
|
||||
CF_D1_DOCS_ID: ${{ secrets.CF_D1_DOCS_ID }}
|
||||
CF_ACCOUNT_ID: ${{ secrets.CF_ACCOUNT_ID }}
|
||||
BLOB_READ_WRITE_TOKEN: ${{ secrets.BLOB_READ_WRITE_TOKEN }}
|
||||
CF_R2_DOCS_URL: ${{ secrets.CF_R2_DOCS_URL }}
|
||||
CF_R2_DOCS_ACCESS_KEY_ID: ${{ secrets.CF_R2_DOCS_ACCESS_KEY_ID }}
|
||||
CF_R2_DOCS_SECRET_ACCESS_KEY: ${{ secrets.CF_R2_DOCS_SECRET_ACCESS_KEY }}
|
||||
CF_R2_DOCS_BUCKET: ${{ secrets.CF_R2_DOCS_BUCKET }}
|
||||
CF_R2_DOCS_BUCKET_URL: ${{ secrets.CF_R2_DOCS_BUCKET_URL }}
|
||||
uses: ./main/packages/actions/src/uploadDocumentation
|
||||
with:
|
||||
package: ${{ steps.extract-tag.outputs.package }}
|
||||
@@ -123,6 +139,10 @@ jobs:
|
||||
if: ${{ env.REF_TYPE == 'tag' && (!inputs.ref || inputs.ref == 'main') }}
|
||||
env:
|
||||
BLOB_READ_WRITE_TOKEN: ${{ secrets.BLOB_READ_WRITE_TOKEN }}
|
||||
CF_R2_DOCS_URL: ${{ secrets.CF_R2_DOCS_URL }}
|
||||
CF_R2_DOCS_ACCESS_KEY_ID: ${{ secrets.CF_R2_DOCS_ACCESS_KEY_ID }}
|
||||
CF_R2_DOCS_SECRET_ACCESS_KEY: ${{ secrets.CF_R2_DOCS_SECRET_ACCESS_KEY }}
|
||||
CF_R2_DOCS_BUCKET: ${{ secrets.CF_R2_DOCS_BUCKET }}
|
||||
uses: ./packages/actions/src/uploadSplitDocumentation
|
||||
with:
|
||||
package: ${{ steps.extract-tag.outputs.package }}
|
||||
@@ -132,6 +152,10 @@ jobs:
|
||||
if: ${{ env.REF_TYPE == 'tag' && inputs.ref && inputs.ref != 'main' }}
|
||||
env:
|
||||
BLOB_READ_WRITE_TOKEN: ${{ secrets.BLOB_READ_WRITE_TOKEN }}
|
||||
CF_R2_DOCS_URL: ${{ secrets.CF_R2_DOCS_URL }}
|
||||
CF_R2_DOCS_ACCESS_KEY_ID: ${{ secrets.CF_R2_DOCS_ACCESS_KEY_ID }}
|
||||
CF_R2_DOCS_SECRET_ACCESS_KEY: ${{ secrets.CF_R2_DOCS_SECRET_ACCESS_KEY }}
|
||||
CF_R2_DOCS_BUCKET: ${{ secrets.CF_R2_DOCS_BUCKET }}
|
||||
uses: ./main/packages/actions/src/uploadSplitDocumentation
|
||||
with:
|
||||
package: ${{ steps.extract-tag.outputs.package }}
|
||||
@@ -155,26 +179,50 @@ jobs:
|
||||
if: ${{ env.REF_TYPE == 'branch' && (!inputs.ref || inputs.ref == 'main') }}
|
||||
env:
|
||||
DATABASE_URL: ${{ secrets.DATABASE_URL }}
|
||||
CF_D1_DOCS_API_KEY: ${{ secrets.CF_D1_DOCS_API_KEY }}
|
||||
CF_D1_DOCS_ID: ${{ secrets.CF_D1_DOCS_ID }}
|
||||
CF_ACCOUNT_ID: ${{ secrets.CF_ACCOUNT_ID }}
|
||||
BLOB_READ_WRITE_TOKEN: ${{ secrets.BLOB_READ_WRITE_TOKEN }}
|
||||
CF_R2_DOCS_URL: ${{ secrets.CF_R2_DOCS_URL }}
|
||||
CF_R2_DOCS_ACCESS_KEY_ID: ${{ secrets.CF_R2_DOCS_ACCESS_KEY_ID }}
|
||||
CF_R2_DOCS_SECRET_ACCESS_KEY: ${{ secrets.CF_R2_DOCS_SECRET_ACCESS_KEY }}
|
||||
CF_R2_DOCS_BUCKET: ${{ secrets.CF_R2_DOCS_BUCKET }}
|
||||
CF_R2_DOCS_BUCKET_URL: ${{ secrets.CF_R2_DOCS_BUCKET_URL }}
|
||||
uses: ./packages/actions/src/uploadDocumentation
|
||||
|
||||
- name: Upload documentation to database
|
||||
if: ${{ env.REF_TYPE == 'branch' && inputs.ref && inputs.ref != 'main' }}
|
||||
env:
|
||||
DATABASE_URL: ${{ secrets.DATABASE_URL }}
|
||||
CF_D1_DOCS_API_KEY: ${{ secrets.CF_D1_DOCS_API_KEY }}
|
||||
CF_D1_DOCS_ID: ${{ secrets.CF_D1_DOCS_ID }}
|
||||
CF_ACCOUNT_ID: ${{ secrets.CF_ACCOUNT_ID }}
|
||||
BLOB_READ_WRITE_TOKEN: ${{ secrets.BLOB_READ_WRITE_TOKEN }}
|
||||
CF_R2_DOCS_URL: ${{ secrets.CF_R2_DOCS_URL }}
|
||||
CF_R2_DOCS_ACCESS_KEY_ID: ${{ secrets.CF_R2_DOCS_ACCESS_KEY_ID }}
|
||||
CF_R2_DOCS_SECRET_ACCESS_KEY: ${{ secrets.CF_R2_DOCS_SECRET_ACCESS_KEY }}
|
||||
CF_R2_DOCS_BUCKET: ${{ secrets.CF_R2_DOCS_BUCKET }}
|
||||
CF_R2_DOCS_BUCKET_URL: ${{ secrets.CF_R2_DOCS_BUCKET_URL }}
|
||||
uses: ./main/packages/actions/src/uploadDocumentation
|
||||
|
||||
- name: Upload split documentation to blob storage
|
||||
if: ${{ env.REF_TYPE == 'branch' && (!inputs.ref || inputs.ref == 'main') }}
|
||||
env:
|
||||
BLOB_READ_WRITE_TOKEN: ${{ secrets.BLOB_READ_WRITE_TOKEN }}
|
||||
CF_R2_DOCS_URL: ${{ secrets.CF_R2_DOCS_URL }}
|
||||
CF_R2_DOCS_ACCESS_KEY_ID: ${{ secrets.CF_R2_DOCS_ACCESS_KEY_ID }}
|
||||
CF_R2_DOCS_SECRET_ACCESS_KEY: ${{ secrets.CF_R2_DOCS_SECRET_ACCESS_KEY }}
|
||||
CF_R2_DOCS_BUCKET: ${{ secrets.CF_R2_DOCS_BUCKET }}
|
||||
uses: ./packages/actions/src/uploadSplitDocumentation
|
||||
|
||||
- name: Upload split documentation to blob storage
|
||||
if: ${{ env.REF_TYPE == 'branch' && inputs.ref && inputs.ref != 'main' }}
|
||||
env:
|
||||
BLOB_READ_WRITE_TOKEN: ${{ secrets.BLOB_READ_WRITE_TOKEN }}
|
||||
CF_R2_DOCS_URL: ${{ secrets.CF_R2_DOCS_URL }}
|
||||
CF_R2_DOCS_ACCESS_KEY_ID: ${{ secrets.CF_R2_DOCS_ACCESS_KEY_ID }}
|
||||
CF_R2_DOCS_SECRET_ACCESS_KEY: ${{ secrets.CF_R2_DOCS_SECRET_ACCESS_KEY }}
|
||||
CF_R2_DOCS_BUCKET: ${{ secrets.CF_R2_DOCS_BUCKET }}
|
||||
uses: ./main/packages/actions/src/uploadSplitDocumentation
|
||||
|
||||
- name: Move docs to correct directory
|
||||
|
||||
@@ -41,28 +41,32 @@
|
||||
"homepage": "https://discord.js.org",
|
||||
"funding": "https://github.com/discordjs/discord.js?sponsor",
|
||||
"dependencies": {
|
||||
"@actions/core": "^1.10.1",
|
||||
"@actions/core": "^1.11.1",
|
||||
"@actions/glob": "^0.5.0",
|
||||
"@aws-sdk/client-s3": "^3.787.0",
|
||||
"@discordjs/scripts": "workspace:^",
|
||||
"@vercel/blob": "^0.23.4",
|
||||
"@vercel/blob": "^0.27.3",
|
||||
"@vercel/postgres": "^0.9.0",
|
||||
"cloudflare": "^4.2.0",
|
||||
"meilisearch": "^0.38.0",
|
||||
"p-limit": "^6.1.0",
|
||||
"tslib": "^2.6.3",
|
||||
"undici": "6.21.1"
|
||||
"p-limit": "^6.2.0",
|
||||
"p-queue": "^8.1.0",
|
||||
"tslib": "^2.8.1",
|
||||
"undici": "7.8.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^18.19.45",
|
||||
"@vitest/coverage-v8": "^2.0.5",
|
||||
"@types/node": "^22.14.0",
|
||||
"@vitest/coverage-v8": "^3.1.1",
|
||||
"cross-env": "^7.0.3",
|
||||
"eslint": "^8.57.0",
|
||||
"eslint-config-neon": "^0.1.62",
|
||||
"eslint-formatter-pretty": "^6.0.1",
|
||||
"prettier": "^3.3.3",
|
||||
"tsup": "^8.2.4",
|
||||
"turbo": "^2.0.14",
|
||||
"typescript": "~5.5.4",
|
||||
"vitest": "^2.0.5"
|
||||
"prettier": "^3.5.3",
|
||||
"terser": "^5.37.0",
|
||||
"tsup": "^8.4.0",
|
||||
"turbo": "^2.5.0",
|
||||
"typescript": "~5.8.3",
|
||||
"vitest": "^3.1.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
|
||||
@@ -9,7 +9,7 @@ runs:
|
||||
with:
|
||||
swap-size-gb: 10
|
||||
|
||||
- uses: pnpm/action-setup@v4.0.0
|
||||
- uses: pnpm/action-setup@v4.1.0
|
||||
name: Install pnpm
|
||||
with:
|
||||
run_install: false
|
||||
|
||||
@@ -1,13 +1,26 @@
|
||||
/* eslint-disable @typescript-eslint/no-loop-func */
|
||||
import { readFile } from 'node:fs/promises';
|
||||
import process from 'node:process';
|
||||
import { getInput, setFailed } from '@actions/core';
|
||||
import { create } from '@actions/glob';
|
||||
import { PutObjectCommand, S3Client } from '@aws-sdk/client-s3';
|
||||
import { put } from '@vercel/blob';
|
||||
import { createPool } from '@vercel/postgres';
|
||||
import Cloudflare from 'cloudflare';
|
||||
import pLimit from 'p-limit';
|
||||
|
||||
if (!process.env.DATABASE_URL) {
|
||||
setFailed('DATABASE_URL is not set');
|
||||
if (
|
||||
!process.env.DATABASE_URL ||
|
||||
!process.env.CF_R2_DOCS_URL ||
|
||||
!process.env.CF_R2_DOCS_ACCESS_KEY_ID ||
|
||||
!process.env.CF_R2_DOCS_SECRET_ACCESS_KEY ||
|
||||
!process.env.CF_R2_DOCS_BUCKET ||
|
||||
!process.env.CF_R2_DOCS_BUCKET_URL ||
|
||||
!process.env.CF_D1_DOCS_API_KEY ||
|
||||
!process.env.CF_D1_DOCS_ID ||
|
||||
!process.env.CF_ACCOUNT_ID
|
||||
) {
|
||||
setFailed('Missing environment variables');
|
||||
}
|
||||
|
||||
const pkg = getInput('package') || '*';
|
||||
@@ -17,6 +30,21 @@ const pool = createPool({
|
||||
connectionString: process.env.DATABASE_URL,
|
||||
});
|
||||
|
||||
const S3 = new S3Client({
|
||||
region: 'auto',
|
||||
endpoint: process.env.CF_R2_DOCS_URL!,
|
||||
credentials: {
|
||||
accessKeyId: process.env.CF_R2_DOCS_ACCESS_KEY_ID!,
|
||||
secretAccessKey: process.env.CF_R2_DOCS_SECRET_ACCESS_KEY!,
|
||||
},
|
||||
requestChecksumCalculation: 'WHEN_REQUIRED',
|
||||
responseChecksumValidation: 'WHEN_REQUIRED',
|
||||
});
|
||||
|
||||
const client = new Cloudflare({
|
||||
apiToken: process.env.CF_D1_DOCS_API_KEY,
|
||||
});
|
||||
|
||||
const limit = pLimit(10);
|
||||
const promises = [];
|
||||
|
||||
@@ -26,12 +54,14 @@ for await (const file of globber.globGenerator()) {
|
||||
const data = await readFile(file, 'utf8');
|
||||
try {
|
||||
promises.push(
|
||||
// eslint-disable-next-line @typescript-eslint/no-loop-func
|
||||
limit(async () => {
|
||||
console.log(`Uploading ${file} with ${version}...`);
|
||||
const json = JSON.parse(data);
|
||||
const name = json.name ?? json.n;
|
||||
const { url } = await put(`${name.replace('@discordjs/', '')}/${version}.json`, data, {
|
||||
|
||||
const key = `${name.replace('@discordjs/', '')}/${version}.json`;
|
||||
|
||||
const { url } = await put(key, data, {
|
||||
access: 'public',
|
||||
addRandomSuffix: false,
|
||||
});
|
||||
@@ -39,6 +69,19 @@ for await (const file of globber.globGenerator()) {
|
||||
'@discordjs/',
|
||||
'',
|
||||
)}, ${version}, ${url}) on conflict (name, version) do update set url = EXCLUDED.url`;
|
||||
|
||||
await S3.send(
|
||||
new PutObjectCommand({
|
||||
Bucket: process.env.CF_R2_DOCS_BUCKET,
|
||||
Key: key,
|
||||
Body: data,
|
||||
}),
|
||||
);
|
||||
await client.d1.database.raw(process.env.CF_D1_DOCS_ID!, {
|
||||
account_id: process.env.CF_ACCOUNT_ID!,
|
||||
sql: `insert into documentation (name, version, url) values (?, ?, ?) on conflict (name, version) do update set url = excluded.url;`,
|
||||
params: [name.replace('@discordjs/', ''), version, process.env.CF_R2_DOCS_BUCKET_URL + '/' + key],
|
||||
});
|
||||
}),
|
||||
);
|
||||
} catch (error) {
|
||||
|
||||
@@ -1,32 +1,82 @@
|
||||
/* eslint-disable @typescript-eslint/no-loop-func */
|
||||
import { readFile } from 'node:fs/promises';
|
||||
import { basename, dirname, relative, sep } from 'node:path';
|
||||
import { cwd } from 'node:process';
|
||||
import { getInput } from '@actions/core';
|
||||
import process from 'node:process';
|
||||
import { setTimeout as sleep } from 'node:timers/promises';
|
||||
import { setFailed, getInput } from '@actions/core';
|
||||
import { create } from '@actions/glob';
|
||||
import { S3Client, PutObjectCommand } from '@aws-sdk/client-s3';
|
||||
import { put } from '@vercel/blob';
|
||||
import pLimit from 'p-limit';
|
||||
import PQueue from 'p-queue';
|
||||
|
||||
if (
|
||||
!process.env.CF_R2_DOCS_URL ||
|
||||
!process.env.CF_R2_DOCS_ACCESS_KEY_ID ||
|
||||
!process.env.CF_R2_DOCS_SECRET_ACCESS_KEY ||
|
||||
!process.env.CF_R2_DOCS_BUCKET
|
||||
) {
|
||||
setFailed('Missing environment variables');
|
||||
}
|
||||
|
||||
const pkg = getInput('package') || '*';
|
||||
const version = getInput('version') || 'main';
|
||||
|
||||
const limit = pLimit(10);
|
||||
const queue = new PQueue({ concurrency: 10, interval: 60_000, intervalCap: 1_000 });
|
||||
const promises = [];
|
||||
const failedUploads: string[] = [];
|
||||
|
||||
const S3 = new S3Client({
|
||||
region: 'auto',
|
||||
endpoint: process.env.CF_R2_DOCS_URL!,
|
||||
credentials: {
|
||||
accessKeyId: process.env.CF_R2_DOCS_ACCESS_KEY_ID!,
|
||||
secretAccessKey: process.env.CF_R2_DOCS_SECRET_ACCESS_KEY!,
|
||||
},
|
||||
requestChecksumCalculation: 'WHEN_REQUIRED',
|
||||
responseChecksumValidation: 'WHEN_REQUIRED',
|
||||
});
|
||||
|
||||
const globber = await create(`packages/${pkg}/docs/${pkg}/split/*.api.json`);
|
||||
console.log('Glob: ', await globber.glob());
|
||||
for await (const file of globber.globGenerator()) {
|
||||
const data = await readFile(file, 'utf8');
|
||||
const pkgName = dirname(relative(cwd(), file)).split(sep)[1];
|
||||
const pkgName = dirname(relative(process.cwd(), file)).split(sep)[1];
|
||||
try {
|
||||
promises.push(
|
||||
// eslint-disable-next-line @typescript-eslint/no-loop-func
|
||||
limit(async () => {
|
||||
queue.add(async () => {
|
||||
console.log(`Uploading ${file} with ${version} from ${pkgName}...`);
|
||||
const name = basename(file).replace('main.', '');
|
||||
await put(`rewrite/${pkgName}/${version}.${name}`, data, {
|
||||
access: 'public',
|
||||
addRandomSuffix: false,
|
||||
});
|
||||
async function upload(retries = 0) {
|
||||
try {
|
||||
await put(`rewrite/${pkgName}/${version}.${name}`, data, {
|
||||
access: 'public',
|
||||
addRandomSuffix: false,
|
||||
});
|
||||
await S3.send(
|
||||
new PutObjectCommand({
|
||||
Bucket: process.env.CF_R2_DOCS_BUCKET,
|
||||
Key: `${pkgName}/${version}.${name}`,
|
||||
Body: data,
|
||||
}),
|
||||
);
|
||||
} catch (error) {
|
||||
if (retries > 3) {
|
||||
console.error(`Could not upload ${file} after 3 retries`, error);
|
||||
failedUploads.push(name);
|
||||
return;
|
||||
}
|
||||
|
||||
if (typeof error === 'object' && error && 'retryAfter' in error && typeof error.retryAfter === 'number') {
|
||||
await sleep(error.retryAfter * 1_000);
|
||||
return upload(retries + 1);
|
||||
} else {
|
||||
console.error(`Could not upload ${file}`, error);
|
||||
failedUploads.push(name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
await upload();
|
||||
}),
|
||||
);
|
||||
} catch (error) {
|
||||
@@ -36,6 +86,9 @@ for await (const file of globber.globGenerator()) {
|
||||
|
||||
try {
|
||||
await Promise.all(promises);
|
||||
if (failedUploads.length) {
|
||||
setFailed(`Failed to upload ${failedUploads.length} files: ${failedUploads.join(', ')}`);
|
||||
}
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
}
|
||||
|
||||
10
packages/actions/tsconfig.test.json
Normal file
10
packages/actions/tsconfig.test.json
Normal file
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"$schema": "https://json.schemastore.org/tsconfig.json",
|
||||
"extends": "./tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"noEmit": true,
|
||||
"skipLibCheck": true
|
||||
},
|
||||
"include": ["__tests__/**/*.ts"],
|
||||
"exclude": ["node_modules"]
|
||||
}
|
||||
@@ -2,6 +2,18 @@
|
||||
|
||||
All notable changes to this project will be documented in this file.
|
||||
|
||||
# [@discordjs/core@2.2.0](https://github.com/discordjs/discord.js/compare/@discordjs/core@2.1.1...@discordjs/core@2.2.0) - (2025-06-25)
|
||||
|
||||
## Features
|
||||
|
||||
- **webhook:** Support `with_components` (#10945) ([7713627](https://github.com/discordjs/discord.js/commit/7713627fd18599a6187b325e1e4bc9a17cf23e21))
|
||||
|
||||
# [@discordjs/core@2.1.1](https://github.com/discordjs/discord.js/compare/@discordjs/core@2.1.0...@discordjs/core@2.1.1) - (2025-06-16)
|
||||
|
||||
## Bug Fixes
|
||||
|
||||
- **guild:** Fix incorrectly-detected deprecated overload ([d0a535e](https://github.com/discordjs/discord.js/commit/d0a535ea6a66861276691a51547adfb2bcef0384))
|
||||
|
||||
# [@discordjs/core@2.1.0](https://github.com/discordjs/discord.js/compare/@discordjs/core@2.0.1...@discordjs/core@2.1.0) - (2025-04-25)
|
||||
|
||||
## Features
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"$schema": "https://json.schemastore.org/package.json",
|
||||
"name": "@discordjs/core",
|
||||
"version": "2.1.0",
|
||||
"version": "2.2.0",
|
||||
"description": "A thinly abstracted wrapper around the rest API, and gateway.",
|
||||
"scripts": {
|
||||
"test": "vitest run",
|
||||
|
||||
@@ -115,7 +115,7 @@ export class GuildsAPI {
|
||||
* @param options - The options for fetching the guild
|
||||
* @deprecated Use the overload with a query instead.
|
||||
*/
|
||||
public async get(guildId: Snowflake, { signal }?: Pick<RequestData, 'signal'>): Promise<RESTGetAPIGuildResult>;
|
||||
public async get(guildId: Snowflake, { signal }: Pick<RequestData, 'signal'>): Promise<RESTGetAPIGuildResult>;
|
||||
|
||||
/**
|
||||
* Fetches a guild
|
||||
|
||||
@@ -9,6 +9,7 @@ import {
|
||||
type RESTPatchAPIWebhookJSONBody,
|
||||
type RESTPatchAPIWebhookResult,
|
||||
type RESTPatchAPIWebhookWithTokenMessageJSONBody,
|
||||
type RESTPatchAPIWebhookWithTokenMessageQuery,
|
||||
type RESTPatchAPIWebhookWithTokenMessageResult,
|
||||
type RESTPostAPIWebhookWithTokenGitHubQuery,
|
||||
type RESTPostAPIWebhookWithTokenJSONBody,
|
||||
@@ -127,13 +128,14 @@ export class WebhooksAPI {
|
||||
{
|
||||
wait,
|
||||
thread_id,
|
||||
with_components,
|
||||
files,
|
||||
...body
|
||||
}: RESTPostAPIWebhookWithTokenJSONBody & RESTPostAPIWebhookWithTokenQuery & { files?: RawFile[] },
|
||||
{ signal }: Pick<RequestData, 'signal'> = {},
|
||||
) {
|
||||
return this.rest.post(Routes.webhook(id, token), {
|
||||
query: makeURLSearchParams({ wait, thread_id }),
|
||||
query: makeURLSearchParams({ wait, thread_id, with_components }),
|
||||
files,
|
||||
body,
|
||||
auth: false,
|
||||
@@ -232,13 +234,14 @@ export class WebhooksAPI {
|
||||
messageId: Snowflake,
|
||||
{
|
||||
thread_id,
|
||||
with_components,
|
||||
files,
|
||||
...body
|
||||
}: RESTPatchAPIWebhookWithTokenMessageJSONBody & { files?: RawFile[]; thread_id?: string },
|
||||
}: RESTPatchAPIWebhookWithTokenMessageJSONBody & RESTPatchAPIWebhookWithTokenMessageQuery & { files?: RawFile[] },
|
||||
{ signal }: Pick<RequestData, 'signal'> = {},
|
||||
) {
|
||||
return this.rest.patch(Routes.webhookMessage(id, token, messageId), {
|
||||
query: makeURLSearchParams({ thread_id }),
|
||||
query: makeURLSearchParams({ thread_id, with_components }),
|
||||
auth: false,
|
||||
body,
|
||||
signal,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"$schema": "https://json.schemastore.org/lintstagedrc.schema.json",
|
||||
"*": "prettier --ignore-unknown --write",
|
||||
"{src/**,test/**,typings/**,scripts/**}.{mjs,js,ts}": "cross-env ESLINT_USE_FLAT_CONFIG=false eslint --ext mjs,js,ts --fix"
|
||||
"{src/**,typings/**,scripts/**}.{mjs,js,ts}": "cross-env ESLINT_USE_FLAT_CONFIG=false eslint --ext mjs,js,ts --fix"
|
||||
}
|
||||
|
||||
@@ -2,6 +2,73 @@
|
||||
|
||||
All notable changes to this project will be documented in this file.
|
||||
|
||||
# [14.20.0](https://github.com/discordjs/discord.js/compare/14.19.3...14.20.0) - (2025-06-16)
|
||||
|
||||
## Bug Fixes
|
||||
|
||||
- Use resolvePartialEmoji on MessagePayload#options#components (#10910) ([f2f757c](https://github.com/discordjs/discord.js/commit/f2f757ce52b76d5e571f47f9bf1c5188627b80d5))
|
||||
- **ChannelManager:** Remove threads from cache upon deletion (#10883) ([ee2eb73](https://github.com/discordjs/discord.js/commit/ee2eb7349f2467451880baaea54e02074916015f))
|
||||
- **PartialGroupDMChannel:** Prevent `undefined` values (#10889) ([9bca4af](https://github.com/discordjs/discord.js/commit/9bca4af5fdb78fae7b970498db7f93df31f55ef9))
|
||||
|
||||
## Features
|
||||
|
||||
- Backport entrypoint command (#10908) ([c0eae34](https://github.com/discordjs/discord.js/commit/c0eae344c2ed43fa67be9fda8e3d3e479693d2d1))
|
||||
- **BaseInteraction:** Add `attachmentSizeLimit` (#10830) ([7e21a94](https://github.com/discordjs/discord.js/commit/7e21a9474e532c5b22c6e0600c446fca47352617))
|
||||
|
||||
## Performance
|
||||
|
||||
- **Components:** Hash table (#10893) ([2d19163](https://github.com/discordjs/discord.js/commit/2d19163d764705667691430e438499fd330ffb65))
|
||||
|
||||
## Refactor
|
||||
|
||||
- **Client:** Remove `with_expiration` query parameter (#10800) ([c8f6066](https://github.com/discordjs/discord.js/commit/c8f6066d6a0a1fc6ac23a49d66604d95b588af3e))
|
||||
|
||||
# [14.19.3](https://github.com/discordjs/discord.js/compare/14.19.2...14.19.3) - (2025-05-02)
|
||||
|
||||
## Bug Fixes
|
||||
|
||||
- Regression in allowedMentions when replying (#10866) ([2ebb5cb](https://github.com/discordjs/discord.js/commit/2ebb5cbd53d869a52cba4549e7acc417963741cd))
|
||||
|
||||
# [14.19.2](https://github.com/discordjs/discord.js/compare/14.19.1...14.19.2) - (2025-04-28)
|
||||
|
||||
## Bug Fixes
|
||||
|
||||
- **WebSocketManager:** Always emit shardDisconnect on unresumable close (#10826) ([37ef57b](https://github.com/discordjs/discord.js/commit/37ef57b88079db2f87036dfd9d57af9a2e5d1b9f))
|
||||
- **SoundboardSound:** Wrong emoji comparison in `equals` (#10861) ([5f3fc17](https://github.com/discordjs/discord.js/commit/5f3fc170fbfd49fa4f117901578c309f00f65d0b))
|
||||
- AllowedMentions, container, media item `toJSON()` for components v2 (#10852) ([20fade2](https://github.com/discordjs/discord.js/commit/20fade2a875695aa677e32b983320e746fd4d69c))
|
||||
- **Guild:** Cache soundboard sounds when patching (#10857) ([e827644](https://github.com/discordjs/discord.js/commit/e827644b5aecf05f7551e4e31a620894cc7aa71f))
|
||||
- **GuildSoundboardSoundManager:** Value "undefined" is not snowflake (#10854) ([6281592](https://github.com/discordjs/discord.js/commit/62815928aba0baa96b3422a4a7f1c4321c123dc7))
|
||||
|
||||
## Typings
|
||||
|
||||
- **GuildSoundboardSoundEditOptions:** Add missing `reason` (#10863) ([e3c247e](https://github.com/discordjs/discord.js/commit/e3c247e423c91b9d9e1d40d0521b6eddf0bc53c9))
|
||||
|
||||
# [14.19.1](https://github.com/discordjs/discord.js/compare/14.19.0...14.19.1) - (2025-04-26)
|
||||
|
||||
## Bug Fixes
|
||||
|
||||
- Add in `withComponents` to Webhook ([481ccd2](https://github.com/discordjs/discord.js/commit/481ccd228bc240e32ac552475f8427a8042e1add))
|
||||
|
||||
# [14.19.0](https://github.com/discordjs/discord.js/compare/14.18.0...14.19.0) - (2025-04-26)
|
||||
|
||||
## Bug Fixes
|
||||
|
||||
- Set `with_components` when sending components through webhooks ([8cdbe23](https://github.com/discordjs/discord.js/commit/8cdbe23766c6e5fe1e0acc040120e839511fea2c))
|
||||
- **GuildAuditLogEntry:** Fix some incorrect types and runtime logic (#10849) ([d920933](https://github.com/discordjs/discord.js/commit/d920933dc5b3c518754f526a9864582fc2c92a43))
|
||||
- Spread out section components next to accessory ([1605a2c](https://github.com/discordjs/discord.js/commit/1605a2c2894c4bb834c604f13a5a91cdbffac3a8))
|
||||
- Correctly extend CachedManager in GuildSoundboardSoundManager ([532c384](https://github.com/discordjs/discord.js/commit/532c3842bc293c965dd9fee846257c9e0bbb450a))
|
||||
- **MessagePayload:** Preserve existing flags when editing (#10766) ([ebfd526](https://github.com/discordjs/discord.js/commit/ebfd52695e205bccda3ae6f4ec39d4e5e8891ab0))
|
||||
|
||||
## Features
|
||||
|
||||
- Soundboard missing things (#10850) ([2d817df](https://github.com/discordjs/discord.js/commit/2d817df3b5894da84a1990cb4e0cfded8a925e75))
|
||||
- Components v2 in v14 (#10781) ([edace17](https://github.com/discordjs/discord.js/commit/edace17a131f857547163a3acf4bb6fec0c1e415))
|
||||
- Add soundboard in v14 (#10843) ([d3154cf](https://github.com/discordjs/discord.js/commit/d3154cf8f1eb027b5b4921d4048a32f464a3cd85))
|
||||
|
||||
## Typings
|
||||
|
||||
- Make `Client.on()` compatible with esnext.disposable in TS5.6+ (#10773) ([45552fa](https://github.com/discordjs/discord.js/commit/45552faf02c67b5079f34567c0214203cd927d2e))
|
||||
|
||||
# [14.18.0](https://github.com/discordjs/discord.js/compare/14.17.3...14.18.0) - (2025-02-10)
|
||||
|
||||
## Bug Fixes
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"$schema": "https://json.schemastore.org/package.json",
|
||||
"name": "discord.js",
|
||||
"version": "14.18.0",
|
||||
"version": "14.20.0",
|
||||
"description": "A powerful library for interacting with the Discord API",
|
||||
"scripts": {
|
||||
"test": "pnpm run docs:test && pnpm run test:typescript",
|
||||
@@ -36,7 +36,8 @@
|
||||
},
|
||||
"files": [
|
||||
"src",
|
||||
"typings"
|
||||
"typings/*.d.ts",
|
||||
"typings/*.d.mts"
|
||||
],
|
||||
"contributors": [
|
||||
"Crawl <icrawltogo@gmail.com>",
|
||||
@@ -65,19 +66,19 @@
|
||||
"homepage": "https://discord.js.org",
|
||||
"funding": "https://github.com/discordjs/discord.js?sponsor",
|
||||
"dependencies": {
|
||||
"@discordjs/builders": "^1.11.1",
|
||||
"@discordjs/builders": "^1.11.2",
|
||||
"@discordjs/collection": "1.5.3",
|
||||
"@discordjs/formatters": "^0.6.1",
|
||||
"@discordjs/rest": "workspace:^",
|
||||
"@discordjs/util": "workspace:^",
|
||||
"@discordjs/ws": "^1.2.2",
|
||||
"@discordjs/ws": "^1.2.3",
|
||||
"@sapphire/snowflake": "3.5.3",
|
||||
"discord-api-types": "^0.38.1",
|
||||
"fast-deep-equal": "3.1.3",
|
||||
"lodash.snakecase": "4.1.1",
|
||||
"magic-bytes.js": "^1.10.0",
|
||||
"tslib": "^2.6.3",
|
||||
"undici": "6.21.1"
|
||||
"undici": "6.21.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@discordjs/api-extractor": "workspace:^",
|
||||
|
||||
@@ -277,7 +277,6 @@ class Client extends BaseClient {
|
||||
const code = resolveInviteCode(invite);
|
||||
const query = makeURLSearchParams({
|
||||
with_counts: true,
|
||||
with_expiration: true,
|
||||
guild_scheduled_event_id: options?.guildScheduledEventId,
|
||||
});
|
||||
const data = await this.rest.get(Routes.invite(code), { query });
|
||||
|
||||
@@ -9,6 +9,7 @@ const ChatInputCommandInteraction = require('../../structures/ChatInputCommandIn
|
||||
const MentionableSelectMenuInteraction = require('../../structures/MentionableSelectMenuInteraction');
|
||||
const MessageContextMenuCommandInteraction = require('../../structures/MessageContextMenuCommandInteraction');
|
||||
const ModalSubmitInteraction = require('../../structures/ModalSubmitInteraction');
|
||||
const PrimaryEntryPointCommandInteraction = require('../../structures/PrimaryEntryPointCommandInteraction');
|
||||
const RoleSelectMenuInteraction = require('../../structures/RoleSelectMenuInteraction');
|
||||
const StringSelectMenuInteraction = require('../../structures/StringSelectMenuInteraction');
|
||||
const UserContextMenuCommandInteraction = require('../../structures/UserContextMenuCommandInteraction');
|
||||
@@ -38,6 +39,9 @@ class InteractionCreateAction extends Action {
|
||||
if (channel && !channel.isTextBased()) return;
|
||||
InteractionClass = MessageContextMenuCommandInteraction;
|
||||
break;
|
||||
case ApplicationCommandType.PrimaryEntryPoint:
|
||||
InteractionClass = PrimaryEntryPointCommandInteraction;
|
||||
break;
|
||||
default:
|
||||
client.emit(
|
||||
Events.Debug,
|
||||
|
||||
@@ -36,10 +36,13 @@ const BeforeReadyWhitelist = [
|
||||
|
||||
const WaitingForGuildEvents = [GatewayDispatchEvents.GuildCreate, GatewayDispatchEvents.GuildDelete];
|
||||
|
||||
const UNRESUMABLE_CLOSE_CODES = [
|
||||
CloseCodes.Normal,
|
||||
GatewayCloseCodes.AlreadyAuthenticated,
|
||||
GatewayCloseCodes.InvalidSeq,
|
||||
const UNRECOVERABLE_CLOSE_CODES = [
|
||||
GatewayCloseCodes.AuthenticationFailed,
|
||||
GatewayCloseCodes.InvalidShard,
|
||||
GatewayCloseCodes.ShardingRequired,
|
||||
GatewayCloseCodes.InvalidAPIVersion,
|
||||
GatewayCloseCodes.InvalidIntents,
|
||||
GatewayCloseCodes.DisallowedIntents,
|
||||
];
|
||||
|
||||
const reasonIsDeprecated = 'the reason property is deprecated, use the code property to determine the reason';
|
||||
@@ -242,7 +245,7 @@ class WebSocketManager extends EventEmitter {
|
||||
this._ws.on(WSWebSocketShardEvents.Closed, ({ code, shardId }) => {
|
||||
const shard = this.shards.get(shardId);
|
||||
shard.emit(WebSocketShardEvents.Close, { code, reason: reasonIsDeprecated, wasClean: true });
|
||||
if (UNRESUMABLE_CLOSE_CODES.includes(code) && this.destroyed) {
|
||||
if (UNRECOVERABLE_CLOSE_CODES.includes(code)) {
|
||||
shard.status = Status.Disconnected;
|
||||
/**
|
||||
* Emitted when a shard's WebSocket disconnects and will no longer reconnect.
|
||||
@@ -251,7 +254,7 @@ class WebSocketManager extends EventEmitter {
|
||||
* @param {number} id The shard id that disconnected
|
||||
*/
|
||||
this.client.emit(Events.ShardDisconnect, { code, reason: reasonIsDeprecated, wasClean: true }, shardId);
|
||||
this.debug([`Shard not resumable: ${code} (${GatewayCloseCodes[code] ?? CloseCodes[code]})`], shardId);
|
||||
this.debug([`Shard not recoverable: ${code} (${GatewayCloseCodes[code] ?? CloseCodes[code]})`], shardId);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -180,6 +180,7 @@ exports.PartialGroupDMChannel = require('./structures/PartialGroupDMChannel');
|
||||
exports.PermissionOverwrites = require('./structures/PermissionOverwrites');
|
||||
exports.Poll = require('./structures/Poll').Poll;
|
||||
exports.PollAnswer = require('./structures/PollAnswer').PollAnswer;
|
||||
exports.PrimaryEntryPointCommandInteraction = require('./structures/PrimaryEntryPointCommandInteraction');
|
||||
exports.Presence = require('./structures/Presence').Presence;
|
||||
exports.ReactionCollector = require('./structures/ReactionCollector');
|
||||
exports.ReactionEmoji = require('./structures/ReactionEmoji');
|
||||
|
||||
@@ -261,6 +261,7 @@ class ApplicationCommandManager extends CachedManager {
|
||||
dm_permission: command.dmPermission ?? command.dm_permission,
|
||||
integration_types: command.integrationTypes ?? command.integration_types,
|
||||
contexts: command.contexts,
|
||||
handler: command.handler,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -69,6 +69,13 @@ class ChannelManager extends CachedManager {
|
||||
|
||||
channel?.parent?.threads?.cache.delete(id);
|
||||
this.cache.delete(id);
|
||||
|
||||
if (channel?.threads) {
|
||||
for (const threadId of channel.threads.cache.keys()) {
|
||||
this.cache.delete(threadId);
|
||||
channel.guild?.channels.cache.delete(threadId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -105,7 +105,7 @@ class GuildSoundboardSoundManager extends CachedManager {
|
||||
* Data for editing a soundboard sound.
|
||||
* @typedef {Object} GuildSoundboardSoundEditOptions
|
||||
* @property {string} [name] The name of the soundboard sound
|
||||
* @property {?number} [volume] The volume of the soundboard sound, from 0 to 1
|
||||
* @property {?number} [volume] The volume (a double) of the soundboard sound, from 0 (inclusive) to 1
|
||||
* @property {?Snowflake} [emojiId] The emoji id of the soundboard sound
|
||||
* @property {?string} [emojiName] The emoji name of the soundboard sound
|
||||
* @property {string} [reason] The reason for editing the soundboard sound
|
||||
@@ -157,35 +157,57 @@ class GuildSoundboardSoundManager extends CachedManager {
|
||||
await this.client.rest.delete(Routes.guildSoundboardSound(this.guild.id, soundId), { reason });
|
||||
}
|
||||
|
||||
/**
|
||||
* Options used to fetch a soundboard sound.
|
||||
* @typedef {BaseFetchOptions} FetchSoundboardSoundOptions
|
||||
* @property {SoundboardSoundResolvable} soundboardSound The soundboard sound to fetch
|
||||
*/
|
||||
|
||||
/**
|
||||
* Options used to fetch soundboard sounds from Discord
|
||||
* @typedef {Object} FetchGuildSoundboardSoundsOptions
|
||||
* @property {boolean} [cache] Whether to cache the fetched soundboard sounds
|
||||
*/
|
||||
|
||||
/* eslint-disable max-len */
|
||||
/**
|
||||
* Obtains one or more soundboard sounds from Discord, or the soundboard sound cache if they're already available.
|
||||
* @param {Snowflake} [id] The soundboard sound's id
|
||||
* @param {BaseFetchOptions} [options] Additional options for this fetch
|
||||
* @param {SoundboardSoundResolvable|FetchSoundboardSoundOptions|FetchGuildSoundboardSoundsOptions} [options] Options for fetching soundboard sound(s)
|
||||
* @returns {Promise<SoundboardSound|Collection<Snowflake, SoundboardSound>>}
|
||||
* @example
|
||||
* // Fetch all soundboard sounds from the guild
|
||||
* guild.soundboardSounds.fetch()
|
||||
* .then(sounds => console.log(`There are ${sounds.size} soundboard sounds.`))
|
||||
* .catch(console.error);
|
||||
* @example
|
||||
* // Fetch a single soundboard sound
|
||||
* guild.soundboardSounds.fetch('222078108977594368')
|
||||
* .then(sound => console.log(`The soundboard sound name is: ${sound.name}`))
|
||||
* .catch(console.error);
|
||||
* @example
|
||||
* // Fetch all soundboard sounds from the guild
|
||||
* guild.soundboardSounds.fetch()
|
||||
* .then(sounds => console.log(`There are ${sounds.size} soundboard sounds.`))
|
||||
* .catch(console.error);
|
||||
*/
|
||||
async fetch(id, { cache = true, force = false } = {}) {
|
||||
if (id) {
|
||||
if (!force) {
|
||||
const existing = this.cache.get(id);
|
||||
if (existing) return existing;
|
||||
}
|
||||
/* eslint-enable max-len */
|
||||
async fetch(options) {
|
||||
if (!options) return this._fetchMany();
|
||||
const { cache, force, soundboardSound } = options;
|
||||
const resolvedSoundboardSound = this.resolveId(soundboardSound ?? options);
|
||||
if (resolvedSoundboardSound) return this._fetchSingle({ cache, force, soundboardSound: resolvedSoundboardSound });
|
||||
return this._fetchMany({ cache });
|
||||
}
|
||||
|
||||
const sound = await this.client.rest.get(Routes.guildSoundboardSound(this.guild.id, id));
|
||||
return this._add(sound, cache);
|
||||
async _fetchSingle({ cache, force, soundboardSound } = {}) {
|
||||
if (!force) {
|
||||
const existing = this.cache.get(soundboardSound);
|
||||
if (existing) return existing;
|
||||
}
|
||||
|
||||
const data = await this.client.rest.get(Routes.guildSoundboardSound(this.guild.id, soundboardSound));
|
||||
return this._add(data, cache);
|
||||
}
|
||||
|
||||
async _fetchMany({ cache } = {}) {
|
||||
const data = await this.client.rest.get(Routes.guildSoundboardSounds(this.guild.id));
|
||||
return new Collection(data.map(sound => [sound.sound_id, this._add(sound, cache)]));
|
||||
|
||||
return data.items.reduce((coll, sound) => coll.set(sound.sound_id, this._add(sound, cache)), new Collection());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -174,6 +174,18 @@ class ApplicationCommand extends Base {
|
||||
this.contexts ??= null;
|
||||
}
|
||||
|
||||
if ('handler' in data) {
|
||||
/**
|
||||
* Determines whether the interaction is handled by the app's interactions handler or by Discord.
|
||||
* <info>Only available for {@link ApplicationCommandType.PrimaryEntryPoint} commands on
|
||||
* applications with the {@link ApplicationFlags.Embedded} flag (i.e, those that have an Activity)</info>
|
||||
* @type {?EntryPointCommandHandlerType}
|
||||
*/
|
||||
this.handler = data.handler;
|
||||
} else {
|
||||
this.handler ??= null;
|
||||
}
|
||||
|
||||
if ('version' in data) {
|
||||
/**
|
||||
* Autoincrementing version identifier updated during substantial record changes
|
||||
@@ -216,15 +228,20 @@ class ApplicationCommand extends Base {
|
||||
* @property {string} name The name of the command, must be in all lowercase if type is
|
||||
* {@link ApplicationCommandType.ChatInput}
|
||||
* @property {Object<Locale, string>} [nameLocalizations] The localizations for the command name
|
||||
* @property {string} description The description of the command, if type is {@link ApplicationCommandType.ChatInput}
|
||||
* @property {string} description The description of the command,
|
||||
* if type is {@link ApplicationCommandType.ChatInput} or {@link ApplicationCommandType.PrimaryEntryPoint}
|
||||
* @property {boolean} [nsfw] Whether the command is age-restricted
|
||||
* @property {Object<Locale, string>} [descriptionLocalizations] The localizations for the command description,
|
||||
* if type is {@link ApplicationCommandType.ChatInput}
|
||||
* if type is {@link ApplicationCommandType.ChatInput} or {@link ApplicationCommandType.PrimaryEntryPoint}
|
||||
* @property {ApplicationCommandType} [type=ApplicationCommandType.ChatInput] The type of the command
|
||||
* @property {ApplicationCommandOptionData[]} [options] Options for the command
|
||||
* @property {?PermissionResolvable} [defaultMemberPermissions] The bitfield used to determine the default permissions
|
||||
* a member needs in order to run the command
|
||||
* @property {boolean} [dmPermission] Whether the command is enabled in DMs
|
||||
* @property {ApplicationIntegrationType[]} [integrationTypes] Installation contexts where the command is available
|
||||
* @property {InteractionContextType[]} [contexts] Interaction contexts where the command can be used
|
||||
* @property {EntryPointCommandHandlerType} [handler] Whether the interaction is handled by the app's
|
||||
* interactions handler or by Discord.
|
||||
*/
|
||||
|
||||
/**
|
||||
@@ -419,7 +436,8 @@ class ApplicationCommand extends Base {
|
||||
this.descriptionLocalizations ?? {},
|
||||
) ||
|
||||
!isEqual(command.integrationTypes ?? command.integration_types ?? [], this.integrationTypes ?? []) ||
|
||||
!isEqual(command.contexts ?? [], this.contexts ?? [])
|
||||
!isEqual(command.contexts ?? [], this.contexts ?? []) ||
|
||||
('handler' in command && command.handler !== this.handler)
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -122,6 +122,12 @@ class BaseInteraction extends Base {
|
||||
* @type {?InteractionContextType}
|
||||
*/
|
||||
this.context = data.context ?? null;
|
||||
|
||||
/**
|
||||
* Attachment size limit in bytes
|
||||
* @type {number}
|
||||
*/
|
||||
this.attachmentSizeLimit = data.attachment_size_limit;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -219,6 +225,16 @@ class BaseInteraction extends Base {
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates whether this interaction is a {@link PrimaryEntryPointCommandInteraction}
|
||||
* @returns {boolean}
|
||||
*/
|
||||
isPrimaryEntryPointCommand() {
|
||||
return (
|
||||
this.type === InteractionType.ApplicationCommand && this.commandType === ApplicationCommandType.PrimaryEntryPoint
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates whether this interaction is a {@link MessageComponentInteraction}
|
||||
* @returns {boolean}
|
||||
|
||||
@@ -163,6 +163,17 @@ class ClientApplication extends Application {
|
||||
this.approximateUserInstallCount ??= null;
|
||||
}
|
||||
|
||||
if ('approximate_user_authorization_count' in data) {
|
||||
/**
|
||||
* An approximate amount of users that have OAuth2 authorizations for this application.
|
||||
*
|
||||
* @type {?number}
|
||||
*/
|
||||
this.approximateUserAuthorizationCount = data.approximate_user_authorization_count;
|
||||
} else {
|
||||
this.approximateUserAuthorizationCount ??= null;
|
||||
}
|
||||
|
||||
if ('guild_id' in data) {
|
||||
/**
|
||||
* The id of the guild associated with this application.
|
||||
|
||||
@@ -64,8 +64,6 @@ class ClientUser extends User {
|
||||
},
|
||||
});
|
||||
|
||||
this.client.token = data.token;
|
||||
this.client.rest.setToken(data.token);
|
||||
const { updated } = this.client.actions.UserUpdate.handle(data);
|
||||
return updated ?? this;
|
||||
}
|
||||
|
||||
@@ -152,6 +152,7 @@ class CommandInteraction extends BaseInteraction {
|
||||
editReply() {}
|
||||
deleteReply() {}
|
||||
followUp() {}
|
||||
launchActivity() {}
|
||||
showModal() {}
|
||||
sendPremiumRequired() {}
|
||||
awaitModalSubmit() {}
|
||||
|
||||
@@ -499,6 +499,13 @@ class Guild extends AnonymousGuild {
|
||||
} else {
|
||||
this.incidentsData ??= null;
|
||||
}
|
||||
|
||||
if (data.soundboard_sounds) {
|
||||
this.soundboardSounds.cache.clear();
|
||||
for (const soundboardSound of data.soundboard_sounds) {
|
||||
this.soundboardSounds._add(soundboardSound);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -32,6 +32,7 @@ const Targets = {
|
||||
AutoModeration: 'AutoModeration',
|
||||
GuildOnboarding: 'GuildOnboarding',
|
||||
GuildOnboardingPrompt: 'GuildOnboardingPrompt',
|
||||
SoundboardSound: 'SoundboardSound',
|
||||
Unknown: 'Unknown',
|
||||
};
|
||||
|
||||
@@ -87,6 +88,8 @@ const Targets = {
|
||||
* * ApplicationCommandPermission
|
||||
* * GuildOnboarding
|
||||
* * GuildOnboardingPrompt
|
||||
* * SoundboardSound
|
||||
* * AutoModeration
|
||||
* * Unknown
|
||||
* @typedef {string} AuditLogTargetType
|
||||
*/
|
||||
@@ -200,7 +203,6 @@ class GuildAuditLogsEntry {
|
||||
|
||||
case AuditLogEvent.MemberMove:
|
||||
case AuditLogEvent.MessageDelete:
|
||||
case AuditLogEvent.MessageBulkDelete:
|
||||
this.extra = {
|
||||
channel: guild.channels.cache.get(data.options.channel_id) ?? { id: data.options.channel_id },
|
||||
count: Number(data.options.count),
|
||||
@@ -215,6 +217,7 @@ class GuildAuditLogsEntry {
|
||||
};
|
||||
break;
|
||||
|
||||
case AuditLogEvent.MessageBulkDelete:
|
||||
case AuditLogEvent.MemberDisconnect:
|
||||
this.extra = {
|
||||
count: Number(data.options.count),
|
||||
@@ -366,12 +369,14 @@ class GuildAuditLogsEntry {
|
||||
data.action_type === AuditLogEvent.OnboardingPromptCreate
|
||||
? new GuildOnboardingPrompt(guild.client, changesReduce(this.changes, { id: data.target_id }), guild.id)
|
||||
: changesReduce(this.changes, { id: data.target_id });
|
||||
} else if (targetType === Targets.GuildOnboarding) {
|
||||
this.target = changesReduce(this.changes, { id: data.target_id });
|
||||
} else if (targetType === Targets.Role) {
|
||||
this.target = guild.roles.cache.get(data.target_id) ?? { id: data.target_id };
|
||||
} else if (targetType === Targets.Emoji) {
|
||||
this.target = guild.emojis.cache.get(data.target_id) ?? { id: data.target_id };
|
||||
} else if (targetType === Targets.SoundboardSound) {
|
||||
this.target = guild.soundboardSounds.cache.get(data.target_id) ?? { id: data.target_id };
|
||||
} else if (data.target_id) {
|
||||
this.target = guild[`${targetType.toLowerCase()}s`]?.cache.get(data.target_id) ?? { id: data.target_id };
|
||||
this.target = { id: data.target_id };
|
||||
}
|
||||
}
|
||||
|
||||
@@ -395,7 +400,9 @@ class GuildAuditLogsEntry {
|
||||
if (target < 110) return Targets.GuildScheduledEvent;
|
||||
if (target < 120) return Targets.Thread;
|
||||
if (target < 130) return Targets.ApplicationCommand;
|
||||
if (target >= 140 && target < 150) return Targets.AutoModeration;
|
||||
if (target < 140) return Targets.SoundboardSound;
|
||||
if (target < 143) return Targets.AutoModeration;
|
||||
if (target < 146) return Targets.User;
|
||||
if (target >= 163 && target <= 165) return Targets.GuildOnboardingPrompt;
|
||||
if (target >= 160 && target < 170) return Targets.GuildOnboarding;
|
||||
return Targets.Unknown;
|
||||
@@ -423,6 +430,7 @@ class GuildAuditLogsEntry {
|
||||
AuditLogEvent.StickerCreate,
|
||||
AuditLogEvent.GuildScheduledEventCreate,
|
||||
AuditLogEvent.ThreadCreate,
|
||||
AuditLogEvent.SoundboardSoundCreate,
|
||||
AuditLogEvent.AutoModerationRuleCreate,
|
||||
AuditLogEvent.AutoModerationBlockMessage,
|
||||
AuditLogEvent.OnboardingPromptCreate,
|
||||
@@ -452,6 +460,7 @@ class GuildAuditLogsEntry {
|
||||
AuditLogEvent.StickerDelete,
|
||||
AuditLogEvent.GuildScheduledEventDelete,
|
||||
AuditLogEvent.ThreadDelete,
|
||||
AuditLogEvent.SoundboardSoundDelete,
|
||||
AuditLogEvent.AutoModerationRuleDelete,
|
||||
AuditLogEvent.OnboardingPromptDelete,
|
||||
].includes(action)
|
||||
@@ -476,8 +485,12 @@ class GuildAuditLogsEntry {
|
||||
AuditLogEvent.StickerUpdate,
|
||||
AuditLogEvent.GuildScheduledEventUpdate,
|
||||
AuditLogEvent.ThreadUpdate,
|
||||
AuditLogEvent.SoundboardSoundUpdate,
|
||||
AuditLogEvent.ApplicationCommandPermissionUpdate,
|
||||
AuditLogEvent.AutoModerationRuleUpdate,
|
||||
AuditLogEvent.AutoModerationBlockMessage,
|
||||
AuditLogEvent.AutoModerationFlagToChannel,
|
||||
AuditLogEvent.AutoModerationUserCommunicationDisabled,
|
||||
AuditLogEvent.OnboardingPromptUpdate,
|
||||
AuditLogEvent.OnboardingUpdate,
|
||||
].includes(action)
|
||||
|
||||
@@ -122,6 +122,20 @@ class GuildMember extends Base {
|
||||
} else {
|
||||
this.flags ??= new GuildMemberFlagsBitField().freeze();
|
||||
}
|
||||
|
||||
if (data.avatar_decoration_data) {
|
||||
/**
|
||||
* The member avatar decoration's data
|
||||
*
|
||||
* @type {?AvatarDecorationData}
|
||||
*/
|
||||
this.avatarDecorationData = {
|
||||
asset: data.avatar_decoration_data.asset,
|
||||
skuId: data.avatar_decoration_data.sku_id,
|
||||
};
|
||||
} else {
|
||||
this.avatarDecorationData = null;
|
||||
}
|
||||
}
|
||||
|
||||
_clone() {
|
||||
@@ -166,6 +180,15 @@ class GuildMember extends Base {
|
||||
return this.avatar && this.client.rest.cdn.guildMemberAvatar(this.guild.id, this.id, this.avatar, options);
|
||||
}
|
||||
|
||||
/**
|
||||
* A link to the member's avatar decoration.
|
||||
*
|
||||
* @returns {?string}
|
||||
*/
|
||||
avatarDecorationURL() {
|
||||
return this.avatarDecorationData ? this.client.rest.cdn.avatarDecoration(this.avatarDecorationData.asset) : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* A link to the member's banner.
|
||||
* @param {ImageURLOptions} [options={}] Options for the banner URL
|
||||
@@ -195,6 +218,16 @@ class GuildMember extends Base {
|
||||
return this.bannerURL(options) ?? this.user.bannerURL(options);
|
||||
}
|
||||
|
||||
/**
|
||||
* A link to the member's guild avatar decoration if they have one.
|
||||
* Otherwise, a link to their {@link User#avatarDecorationURL} will be returned.
|
||||
*
|
||||
* @returns {?string}
|
||||
*/
|
||||
displayAvatarDecorationURL() {
|
||||
return this.avatarDecorationURL() ?? this.user.avatarDecorationURL();
|
||||
}
|
||||
|
||||
/**
|
||||
* The time this member joined the guild
|
||||
* @type {?Date}
|
||||
@@ -499,7 +532,10 @@ class GuildMember extends Base {
|
||||
this.communicationDisabledUntilTimestamp === member.communicationDisabledUntilTimestamp &&
|
||||
this.flags.bitfield === member.flags.bitfield &&
|
||||
(this._roles === member._roles ||
|
||||
(this._roles.length === member._roles.length && this._roles.every((role, i) => role === member._roles[i])))
|
||||
(this._roles.length === member._roles.length &&
|
||||
this._roles.every((role, index) => role === member._roles[index]))) &&
|
||||
this.avatarDecorationData?.asset === member.avatarDecorationData?.asset &&
|
||||
this.avatarDecorationData?.skuId === member.avatarDecorationData?.skuId
|
||||
);
|
||||
}
|
||||
|
||||
@@ -525,6 +561,7 @@ class GuildMember extends Base {
|
||||
json.bannerURL = this.bannerURL();
|
||||
json.displayAvatarURL = this.displayAvatarURL();
|
||||
json.displayBannerURL = this.displayBannerURL();
|
||||
json.avatarDecorationURL = this.avatarDecorationURL();
|
||||
return json;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -97,6 +97,7 @@ class MessageComponentInteraction extends BaseInteraction {
|
||||
followUp() {}
|
||||
deferUpdate() {}
|
||||
update() {}
|
||||
launchActivity() {}
|
||||
showModal() {}
|
||||
sendPremiumRequired() {}
|
||||
awaitModalSubmit() {}
|
||||
|
||||
@@ -248,7 +248,10 @@ class MessagePayload {
|
||||
components,
|
||||
username,
|
||||
avatar_url: avatarURL,
|
||||
allowed_mentions: content === undefined && message_reference === undefined ? undefined : allowedMentions,
|
||||
allowed_mentions:
|
||||
this.isMessage && message_reference === undefined && this.target.author.id !== this.target.client.user.id
|
||||
? undefined
|
||||
: allowedMentions,
|
||||
flags,
|
||||
message_reference,
|
||||
attachments: this.options.attachments,
|
||||
|
||||
@@ -119,6 +119,7 @@ class ModalSubmitInteraction extends BaseInteraction {
|
||||
deferUpdate() {}
|
||||
update() {}
|
||||
sendPremiumRequired() {}
|
||||
launchActivity() {}
|
||||
}
|
||||
|
||||
InteractionResponses.applyToClass(ModalSubmitInteraction, 'showModal');
|
||||
|
||||
@@ -27,7 +27,7 @@ class PartialGroupDMChannel extends BaseChannel {
|
||||
* The hash of the channel icon
|
||||
* @type {?string}
|
||||
*/
|
||||
this.icon = data.icon;
|
||||
this.icon = data.icon ?? null;
|
||||
|
||||
/**
|
||||
* Recipient data received in a {@link PartialGroupDMChannel}.
|
||||
@@ -39,7 +39,7 @@ class PartialGroupDMChannel extends BaseChannel {
|
||||
* The recipients of this Group DM Channel.
|
||||
* @type {PartialRecipient[]}
|
||||
*/
|
||||
this.recipients = data.recipients;
|
||||
this.recipients = data.recipients ?? [];
|
||||
|
||||
/**
|
||||
* A manager of the messages belonging to this channel
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
'use strict';
|
||||
|
||||
const CommandInteraction = require('./CommandInteraction.js');
|
||||
|
||||
/**
|
||||
* Represents a primary entry point command interaction.
|
||||
* @extends {CommandInteraction}
|
||||
*/
|
||||
class PrimaryEntryPointCommandInteraction extends CommandInteraction {}
|
||||
|
||||
module.exports = PrimaryEntryPointCommandInteraction;
|
||||
@@ -181,8 +181,8 @@ class SoundboardSound extends Base {
|
||||
this.available === other.available &&
|
||||
this.name === other.name &&
|
||||
this.volume === other.volume &&
|
||||
this.emojiId === other.emojiId &&
|
||||
this.emojiName === other.emojiName &&
|
||||
this._emoji?.id === other._emoji?.id &&
|
||||
this._emoji?.name === other._emoji?.name &&
|
||||
this.guildId === other.guildId &&
|
||||
this.user?.id === other.user?.id
|
||||
);
|
||||
@@ -193,8 +193,8 @@ class SoundboardSound extends Base {
|
||||
this.available === other.available &&
|
||||
this.name === other.name &&
|
||||
this.volume === other.volume &&
|
||||
this.emojiId === other.emoji_id &&
|
||||
this.emojiName === other.emoji_name &&
|
||||
(this._emoji?.id ?? null) === other.emoji_id &&
|
||||
(this._emoji?.name ?? null) === other.emoji_name &&
|
||||
this.guildId === other.guild_id &&
|
||||
this.user?.id === other.user?.id
|
||||
);
|
||||
|
||||
@@ -20,6 +20,14 @@ class UnfurledMediaItem {
|
||||
get url() {
|
||||
return this.data.url;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the API-compatible JSON for this media item
|
||||
* @returns {APIUnfurledMediaItem}
|
||||
*/
|
||||
toJSON() {
|
||||
return { ...this.data };
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = UnfurledMediaItem;
|
||||
|
||||
@@ -137,6 +137,8 @@ class Webhook {
|
||||
* @property {string} [threadName] Name of the thread to create (only available if the webhook is in a forum channel)
|
||||
* @property {Snowflake[]} [appliedTags]
|
||||
* The tags to apply to the created thread (only available if the webhook is in a forum channel)
|
||||
* @property {boolean} [withComponents] Whether to allow sending non-interactive components in the message.
|
||||
* <info>For application-owned webhooks, this property is ignored</info>
|
||||
*/
|
||||
|
||||
/**
|
||||
@@ -214,12 +216,14 @@ class Webhook {
|
||||
messagePayload = MessagePayload.create(this, options).resolveBody();
|
||||
}
|
||||
|
||||
const { body, files } = await messagePayload.resolveFiles();
|
||||
|
||||
const query = makeURLSearchParams({
|
||||
wait: true,
|
||||
thread_id: messagePayload.options.threadId,
|
||||
with_components: messagePayload.options.withComponents,
|
||||
});
|
||||
|
||||
const { body, files } = await messagePayload.resolveFiles();
|
||||
const d = await this.client.rest.post(Routes.webhook(this.id, this.token), {
|
||||
body,
|
||||
files,
|
||||
@@ -298,6 +302,8 @@ class Webhook {
|
||||
* @property {boolean} [cache=true] Whether to cache the message.
|
||||
* @property {Snowflake} [threadId] The id of the thread this message belongs to.
|
||||
* <info>For interaction webhooks, this property is ignored</info>
|
||||
* @property {boolean} [withComponents] Whether to allow sending non-interactive components in the message.
|
||||
* <info>For application-owned webhooks, this property is ignored</info>
|
||||
*/
|
||||
|
||||
/**
|
||||
@@ -337,14 +343,17 @@ class Webhook {
|
||||
|
||||
const { body, files } = await messagePayload.resolveBody().resolveFiles();
|
||||
|
||||
const query = makeURLSearchParams({
|
||||
thread_id: messagePayload.options.threadId,
|
||||
with_components: messagePayload.options.withComponents,
|
||||
});
|
||||
|
||||
const d = await this.client.rest.patch(
|
||||
Routes.webhookMessage(this.id, this.token, typeof message === 'string' ? message : message.id),
|
||||
{
|
||||
body,
|
||||
files,
|
||||
query: messagePayload.options.threadId
|
||||
? makeURLSearchParams({ thread_id: messagePayload.options.threadId })
|
||||
: undefined,
|
||||
query,
|
||||
auth: false,
|
||||
},
|
||||
);
|
||||
|
||||
@@ -69,6 +69,12 @@ class InteractionResponses {
|
||||
* <warn>This option is deprecated. Use `withResponse` or fetch the response instead.</warn>
|
||||
*/
|
||||
|
||||
/**
|
||||
* Options for launching activity in response to a {@link BaseInteraction}
|
||||
* @typedef {Object} LaunchActivityOptions
|
||||
* @property {boolean} [withResponse] Whether to return an {@link InteractionCallbackResponse} as the response
|
||||
*/
|
||||
|
||||
/**
|
||||
* Options for showing a modal in response to a {@link BaseInteraction}
|
||||
* @typedef {Object} ShowModalOptions
|
||||
@@ -370,6 +376,25 @@ class InteractionResponses {
|
||||
: new InteractionResponse(this, this.message.interactionMetadata?.id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Launches this application's activity, if enabled
|
||||
* @param {LaunchActivityOptions} [options={}] Options for launching the activity
|
||||
* @returns {Promise<InteractionCallbackResponse|undefined>}
|
||||
*/
|
||||
async launchActivity({ withResponse } = {}) {
|
||||
if (this.deferred || this.replied) throw new DiscordjsError(ErrorCodes.InteractionAlreadyReplied);
|
||||
const response = await this.client.rest.post(Routes.interactionCallback(this.id, this.token), {
|
||||
query: makeURLSearchParams({ with_response: withResponse ?? false }),
|
||||
body: {
|
||||
type: InteractionResponseType.LaunchActivity,
|
||||
},
|
||||
auth: false,
|
||||
});
|
||||
this.replied = true;
|
||||
|
||||
return withResponse ? new InteractionCallbackResponse(this.client, response) : undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows a modal component
|
||||
* @param {ModalBuilder|ModalComponentData|APIModalInteractionResponseCallbackData} modal The modal to show
|
||||
@@ -450,6 +475,7 @@ class InteractionResponses {
|
||||
'followUp',
|
||||
'deferUpdate',
|
||||
'update',
|
||||
'launchActivity',
|
||||
'showModal',
|
||||
'sendPremiumRequired',
|
||||
'awaitModalSubmit',
|
||||
|
||||
@@ -152,7 +152,7 @@
|
||||
|
||||
/**
|
||||
* @external APIMediaGalleryItem
|
||||
* @se {@link https://discord-api-types.dev/api/discord-api-types-v10/interface/APIMediaGalleryItem}
|
||||
* @see {@link https://discord-api-types.dev/api/discord-api-types-v10/interface/APIMediaGalleryItem}
|
||||
*/
|
||||
|
||||
/**
|
||||
@@ -370,6 +370,11 @@
|
||||
* @see {@link https://discord-api-types.dev/api/discord-api-types-v10/enum/EntitlementType}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @external EntryPointCommandHandlerType
|
||||
* @see {@link https://discord-api-types.dev/api/discord-api-types-v10/enum/EntryPointCommandHandlerType}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @external ForumLayoutType
|
||||
* @see {@link https://discord-api-types.dev/api/discord-api-types-v10/enum/ForumLayoutType}
|
||||
|
||||
@@ -141,44 +141,7 @@ const { ComponentType } = require('discord-api-types/v10');
|
||||
* @ignore
|
||||
*/
|
||||
function createComponent(data) {
|
||||
if (data instanceof Component) {
|
||||
return data;
|
||||
}
|
||||
|
||||
switch (data.type) {
|
||||
case ComponentType.ActionRow:
|
||||
return new ActionRow(data);
|
||||
case ComponentType.Button:
|
||||
return new ButtonComponent(data);
|
||||
case ComponentType.StringSelect:
|
||||
return new StringSelectMenuComponent(data);
|
||||
case ComponentType.TextInput:
|
||||
return new TextInputComponent(data);
|
||||
case ComponentType.UserSelect:
|
||||
return new UserSelectMenuComponent(data);
|
||||
case ComponentType.RoleSelect:
|
||||
return new RoleSelectMenuComponent(data);
|
||||
case ComponentType.MentionableSelect:
|
||||
return new MentionableSelectMenuComponent(data);
|
||||
case ComponentType.ChannelSelect:
|
||||
return new ChannelSelectMenuComponent(data);
|
||||
case ComponentType.Container:
|
||||
return new ContainerComponent(data);
|
||||
case ComponentType.TextDisplay:
|
||||
return new TextDisplayComponent(data);
|
||||
case ComponentType.File:
|
||||
return new FileComponent(data);
|
||||
case ComponentType.MediaGallery:
|
||||
return new MediaGalleryComponent(data);
|
||||
case ComponentType.Section:
|
||||
return new SectionComponent(data);
|
||||
case ComponentType.Separator:
|
||||
return new SeparatorComponent(data);
|
||||
case ComponentType.Thumbnail:
|
||||
return new ThumbnailComponent(data);
|
||||
default:
|
||||
return new Component(data);
|
||||
}
|
||||
return data instanceof Component ? data : new (ComponentTypeToComponent[data.type] ?? Component)(data);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -188,29 +151,25 @@ function createComponent(data) {
|
||||
* @ignore
|
||||
*/
|
||||
function createComponentBuilder(data) {
|
||||
if (data instanceof ComponentBuilder) {
|
||||
return data;
|
||||
}
|
||||
return data instanceof ComponentBuilder ? data : new (ComponentTypeToBuilder[data.type] ?? ComponentBuilder)(data);
|
||||
}
|
||||
|
||||
switch (data.type) {
|
||||
/**
|
||||
* Extracts all interactive components from the component tree
|
||||
* @param {Component|APIMessageComponent} component The component to find all interactive components in
|
||||
* @returns {Array<Component|APIMessageComponent>}
|
||||
* @ignore
|
||||
*/
|
||||
function extractInteractiveComponents(component) {
|
||||
switch (component.type) {
|
||||
case ComponentType.ActionRow:
|
||||
return new ActionRowBuilder(data);
|
||||
case ComponentType.Button:
|
||||
return new ButtonBuilder(data);
|
||||
case ComponentType.StringSelect:
|
||||
return new StringSelectMenuBuilder(data);
|
||||
case ComponentType.TextInput:
|
||||
return new TextInputBuilder(data);
|
||||
case ComponentType.UserSelect:
|
||||
return new UserSelectMenuBuilder(data);
|
||||
case ComponentType.RoleSelect:
|
||||
return new RoleSelectMenuBuilder(data);
|
||||
case ComponentType.MentionableSelect:
|
||||
return new MentionableSelectMenuBuilder(data);
|
||||
case ComponentType.ChannelSelect:
|
||||
return new ChannelSelectMenuBuilder(data);
|
||||
return component.components;
|
||||
case ComponentType.Section:
|
||||
return [...component.components, component.accessory];
|
||||
case ComponentType.Container:
|
||||
return component.components.flatMap(extractInteractiveComponents);
|
||||
default:
|
||||
return new ComponentBuilder(data);
|
||||
return [component];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -219,20 +178,12 @@ function createComponentBuilder(data) {
|
||||
* @param {Array<Component|APIMessageComponent>} components The components to search in
|
||||
* @param {string} customId The customId to search for
|
||||
* @returns {Component|APIMessageComponent}
|
||||
* @ignore
|
||||
*/
|
||||
function findComponentByCustomId(components, customId) {
|
||||
return (
|
||||
components
|
||||
.flatMap(component => {
|
||||
switch (component.type) {
|
||||
case ComponentType.ActionRow:
|
||||
return component.components;
|
||||
case ComponentType.Section:
|
||||
return [component.accessory];
|
||||
default:
|
||||
return [component];
|
||||
}
|
||||
})
|
||||
.flatMap(extractInteractiveComponents)
|
||||
.find(component => (component.customId ?? component.custom_id) === customId) ?? null
|
||||
);
|
||||
}
|
||||
@@ -263,3 +214,32 @@ const TextInputComponent = require('../structures/TextInputComponent');
|
||||
const ThumbnailComponent = require('../structures/ThumbnailComponent');
|
||||
const UserSelectMenuBuilder = require('../structures/UserSelectMenuBuilder');
|
||||
const UserSelectMenuComponent = require('../structures/UserSelectMenuComponent');
|
||||
|
||||
const ComponentTypeToComponent = {
|
||||
[ComponentType.ActionRow]: ActionRow,
|
||||
[ComponentType.Button]: ButtonComponent,
|
||||
[ComponentType.StringSelect]: StringSelectMenuComponent,
|
||||
[ComponentType.TextInput]: TextInputComponent,
|
||||
[ComponentType.UserSelect]: UserSelectMenuComponent,
|
||||
[ComponentType.RoleSelect]: RoleSelectMenuComponent,
|
||||
[ComponentType.MentionableSelect]: MentionableSelectMenuComponent,
|
||||
[ComponentType.ChannelSelect]: ChannelSelectMenuComponent,
|
||||
[ComponentType.Container]: ContainerComponent,
|
||||
[ComponentType.TextDisplay]: TextDisplayComponent,
|
||||
[ComponentType.File]: FileComponent,
|
||||
[ComponentType.MediaGallery]: MediaGalleryComponent,
|
||||
[ComponentType.Section]: SectionComponent,
|
||||
[ComponentType.Separator]: SeparatorComponent,
|
||||
[ComponentType.Thumbnail]: ThumbnailComponent,
|
||||
};
|
||||
|
||||
const ComponentTypeToBuilder = {
|
||||
[ComponentType.ActionRow]: ActionRowBuilder,
|
||||
[ComponentType.Button]: ButtonBuilder,
|
||||
[ComponentType.StringSelect]: StringSelectMenuBuilder,
|
||||
[ComponentType.TextInput]: TextInputBuilder,
|
||||
[ComponentType.UserSelect]: UserSelectMenuBuilder,
|
||||
[ComponentType.RoleSelect]: RoleSelectMenuBuilder,
|
||||
[ComponentType.MentionableSelect]: MentionableSelectMenuBuilder,
|
||||
[ComponentType.ChannelSelect]: ChannelSelectMenuBuilder,
|
||||
};
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
const { isJSONEncodable } = require('@discordjs/util');
|
||||
const snakeCase = require('lodash.snakecase');
|
||||
const { resolvePartialEmoji } = require('./Util');
|
||||
|
||||
/**
|
||||
* Transforms camel-cased keys into snake cased keys
|
||||
@@ -13,7 +14,14 @@ function toSnakeCase(obj) {
|
||||
if (obj instanceof Date) return obj;
|
||||
if (isJSONEncodable(obj)) return toSnakeCase(obj.toJSON());
|
||||
if (Array.isArray(obj)) return obj.map(toSnakeCase);
|
||||
return Object.fromEntries(Object.entries(obj).map(([key, value]) => [snakeCase(key), toSnakeCase(value)]));
|
||||
return Object.fromEntries(
|
||||
Object.entries(obj).map(([key, value]) => [
|
||||
snakeCase(key),
|
||||
// TODO: The special handling of 'emoji' is just a temporary fix for v14, will be dropped in v15.
|
||||
// See https://github.com/discordjs/discord.js/issues/10909
|
||||
key === 'emoji' && typeof value === 'string' ? resolvePartialEmoji(value) : toSnakeCase(value),
|
||||
]),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
148
packages/discord.js/test/messages.js
Normal file
148
packages/discord.js/test/messages.js
Normal file
@@ -0,0 +1,148 @@
|
||||
'use strict';
|
||||
|
||||
const { readFile } = require('node:fs/promises');
|
||||
const { createReadStream } = require('node:fs');
|
||||
const path = require('node:path');
|
||||
const { setTimeout: sleep } = require('node:timers/promises');
|
||||
const util = require('node:util');
|
||||
const { fetch } = require('undici');
|
||||
const { Client, GatewayIntentBits, AttachmentBuilder, EmbedBuilder, MessageFlags, ComponentType } = require('../src');
|
||||
|
||||
const client = new Client({
|
||||
intents: [GatewayIntentBits.Guilds, GatewayIntentBits.GuildMessages, GatewayIntentBits.MessageContent],
|
||||
});
|
||||
|
||||
const buffer = l =>
|
||||
fetch(l)
|
||||
.then(res => res.arrayBuffer())
|
||||
.then(Buffer.from);
|
||||
|
||||
const linkA = 'https://discord.js.org/static/logo.svg';
|
||||
const fileA = path.join(__dirname, 'blobReach.png');
|
||||
|
||||
const embed = () => new EmbedBuilder();
|
||||
const attach = (attachment, name) => new AttachmentBuilder(attachment, { name });
|
||||
|
||||
const tests = [
|
||||
m => m.channel.send('x'),
|
||||
|
||||
m => m.channel.send({ content: 'x', embeds: [{ description: 'a' }] }),
|
||||
m => m.channel.send({ embeds: [{ description: 'a' }] }),
|
||||
m => m.channel.send({ files: [{ attachment: fileA }] }),
|
||||
m =>
|
||||
m.channel.send({
|
||||
embeds: [{ description: 'a' }],
|
||||
files: [{ attachment: fileA, name: 'xyz.png' }],
|
||||
}),
|
||||
|
||||
m => m.channel.send({ content: 'x', embeds: [embed().setDescription('a')] }),
|
||||
m => m.channel.send({ embeds: [embed().setDescription('a')] }),
|
||||
m => m.channel.send({ embeds: [embed().setDescription('a'), embed().setDescription('b')] }),
|
||||
|
||||
m => m.channel.send({ content: 'x', files: [attach(fileA)] }),
|
||||
m => m.channel.send({ files: [fileA] }),
|
||||
m => m.channel.send({ files: [attach(fileA)] }),
|
||||
async m => m.channel.send({ files: [await buffer(linkA)] }),
|
||||
async m => m.channel.send({ files: [{ attachment: await buffer(linkA) }] }),
|
||||
m => m.channel.send({ files: [attach(fileA), attach(fileA)] }),
|
||||
|
||||
m => m.channel.send({ embeds: [{ description: 'a' }] }).then(m2 => m2.edit('x')),
|
||||
m => m.channel.send({ embeds: [embed().setDescription('a')] }).then(m2 => m2.edit('x')),
|
||||
|
||||
m => m.channel.send('x').then(m2 => m2.edit({ embeds: [{ description: 'a' }] })),
|
||||
m => m.channel.send('x').then(m2 => m2.edit({ embeds: [embed().setDescription('a')] })),
|
||||
|
||||
m => m.channel.send({ embeds: [{ description: 'a' }] }).then(m2 => m2.edit({ content: 'x', embeds: [] })),
|
||||
m => m.channel.send({ embeds: [embed().setDescription('a')] }).then(m2 => m2.edit({ content: 'x', embeds: [] })),
|
||||
|
||||
m => m.channel.send({ content: 'x', embeds: [embed().setDescription('a')], files: [attach(fileA)] }),
|
||||
m => m.channel.send({ content: 'x', files: [attach(fileA), attach(fileA)] }),
|
||||
|
||||
m => m.channel.send({ embeds: [embed().setDescription('a')], files: [attach(fileA)] }),
|
||||
m =>
|
||||
m.channel.send({
|
||||
embeds: [embed().setImage('attachment://two.png')],
|
||||
files: [attach(fileA, 'two.png')],
|
||||
}),
|
||||
m => m.channel.send({ content: 'x', files: [attach(fileA)] }),
|
||||
m => m.channel.send({ files: [fileA] }),
|
||||
m => m.channel.send({ files: [attach(fileA)] }),
|
||||
async m => m.channel.send({ files: [await readFile(fileA)] }),
|
||||
|
||||
m => m.channel.send({ content: 'x', files: [attach(createReadStream(fileA))] }),
|
||||
m => m.channel.send({ files: [createReadStream(fileA)] }),
|
||||
m => m.channel.send({ files: [{ attachment: createReadStream(fileA) }] }),
|
||||
|
||||
m => m.reply({ content: 'x', allowedMentions: { repliedUser: false } }),
|
||||
m => m.reply({ content: 'x', allowedMentions: { repliedUser: true } }),
|
||||
m => m.reply({ content: 'x' }),
|
||||
m => m.reply({ content: `${m.author}`, allowedMentions: { repliedUser: false } }),
|
||||
m => m.reply({ content: `${m.author}`, allowedMentions: { parse: ['users'], repliedUser: false } }),
|
||||
m => m.reply({ content: `${m.author}`, allowedMentions: { parse: ['users'], repliedUser: true } }),
|
||||
m => m.reply({ content: `${m.author}` }),
|
||||
|
||||
m => m.edit({ flags: MessageFlags.SuppressEmbeds }),
|
||||
m => m.edit({ flags: MessageFlags.SuppressEmbeds, allowedMentions: { repliedUser: false } }),
|
||||
|
||||
m =>
|
||||
m
|
||||
.reply({ content: 'x', allowedMentions: { repliedUser: false } })
|
||||
.then(msg => msg.edit({ content: 'a', allowedMentions: { repliedUser: true } })),
|
||||
|
||||
m =>
|
||||
m.channel.send({
|
||||
components: [{ type: ComponentType.TextDisplay, content: `${m.author}` }],
|
||||
flags: MessageFlags.IsComponentsV2,
|
||||
}),
|
||||
m =>
|
||||
m.channel.send({
|
||||
components: [{ type: ComponentType.TextDisplay, content: `${m.author}` }],
|
||||
flags: MessageFlags.IsComponentsV2,
|
||||
allowedMentions: { parse: ['users'] },
|
||||
}),
|
||||
m =>
|
||||
m.channel.send({
|
||||
components: [{ type: ComponentType.TextDisplay, content: `${m.author}` }],
|
||||
flags: MessageFlags.IsComponentsV2,
|
||||
allowedMentions: { parse: [] },
|
||||
}),
|
||||
m =>
|
||||
m.reply({
|
||||
components: [{ type: ComponentType.TextDisplay, content: `${m.author}` }],
|
||||
flags: MessageFlags.IsComponentsV2,
|
||||
allowedMentions: { parse: [], repliedUser: true },
|
||||
}),
|
||||
m =>
|
||||
m.reply({
|
||||
components: [{ type: ComponentType.TextDisplay, content: `${m.author}` }],
|
||||
flags: MessageFlags.IsComponentsV2,
|
||||
allowedMentions: { parse: [], repliedUser: false },
|
||||
}),
|
||||
|
||||
m => m.channel.send('Done!'),
|
||||
];
|
||||
|
||||
client.on('messageCreate', async message => {
|
||||
if (message.author.id !== process.env.OWNER) return;
|
||||
const match = message.content.match(/^do (.+)$/);
|
||||
if (match?.[1] === 'it') {
|
||||
/* eslint-disable no-await-in-loop */
|
||||
for (const [i, test] of tests.entries()) {
|
||||
await message.channel.send(`**#${i}**\n\`\`\`js\n${test.toString()}\`\`\``);
|
||||
await test(message).catch(e => message.channel.send(`Error!\n\`\`\`\n${e}\`\`\``));
|
||||
await sleep(1_000);
|
||||
}
|
||||
/* eslint-enable no-await-in-loop */
|
||||
} else if (match) {
|
||||
const n = parseInt(match[1]) || 0;
|
||||
const test = tests.slice(n)[0];
|
||||
const i = tests.indexOf(test);
|
||||
await message.channel.send(`**#${i}**\n\`\`\`js\n${test.toString()}\`\`\``);
|
||||
await test(message).catch(e => message.channel.send(`Error!\n\`\`\`\n${e}\`\`\``));
|
||||
}
|
||||
});
|
||||
|
||||
client.login();
|
||||
|
||||
// eslint-disable-next-line no-console
|
||||
process.on('unhandledRejection', console.error);
|
||||
162
packages/discord.js/typings/index.d.ts
vendored
162
packages/discord.js/typings/index.d.ts
vendored
@@ -213,6 +213,7 @@ import {
|
||||
SeparatorSpacingSize,
|
||||
APIFileComponent,
|
||||
APIMessageTopLevelComponent,
|
||||
EntryPointCommandHandlerType,
|
||||
} from 'discord-api-types/v10';
|
||||
import { ChildProcess } from 'node:child_process';
|
||||
import { EventEmitter } from 'node:events';
|
||||
@@ -480,6 +481,7 @@ export class ApplicationCommand<PermissionsFetchType = {}> extends Base {
|
||||
public get manager(): ApplicationCommandManager;
|
||||
public id: Snowflake;
|
||||
public integrationTypes: ApplicationIntegrationType[] | null;
|
||||
public handler: EntryPointCommandHandlerType | null;
|
||||
public name: string;
|
||||
public nameLocalizations: LocalizationMap | null;
|
||||
public nameLocalized: string | null;
|
||||
@@ -583,23 +585,6 @@ export type BooleanCache<Cached extends CacheType> = Cached extends 'cached' ? t
|
||||
export abstract class CommandInteraction<Cached extends CacheType = CacheType> extends BaseInteraction<Cached> {
|
||||
public type: InteractionType.ApplicationCommand;
|
||||
public get command(): ApplicationCommand | ApplicationCommand<{ guild: GuildResolvable }> | null;
|
||||
public options: Omit<
|
||||
CommandInteractionOptionResolver<Cached>,
|
||||
| 'getMessage'
|
||||
| 'getFocused'
|
||||
| 'getMentionable'
|
||||
| 'getRole'
|
||||
| 'getUser'
|
||||
| 'getMember'
|
||||
| 'getAttachment'
|
||||
| 'getNumber'
|
||||
| 'getInteger'
|
||||
| 'getString'
|
||||
| 'getChannel'
|
||||
| 'getBoolean'
|
||||
| 'getSubcommandGroup'
|
||||
| 'getSubcommand'
|
||||
>;
|
||||
public channelId: Snowflake;
|
||||
public commandId: Snowflake;
|
||||
public commandName: string;
|
||||
@@ -632,6 +617,9 @@ export abstract class CommandInteraction<Cached extends CacheType = CacheType> e
|
||||
public reply(
|
||||
options: string | MessagePayload | InteractionReplyOptions,
|
||||
): Promise<InteractionResponse<BooleanCache<Cached>>>;
|
||||
public launchActivity(options: LaunchActivityOptions & { withResponse: true }): Promise<InteractionCallbackResponse>;
|
||||
public launchActivity(options?: LaunchActivityOptions & { withResponse?: false }): Promise<undefined>;
|
||||
public launchActivity(options?: LaunchActivityOptions): Promise<InteractionCallbackResponse | undefined>;
|
||||
public showModal(
|
||||
modal:
|
||||
| JSONEncodable<APIModalInteractionResponseCallbackData>
|
||||
@@ -1171,6 +1159,7 @@ export class ClientApplication extends Application {
|
||||
public flags: Readonly<ApplicationFlagsBitField>;
|
||||
public approximateGuildCount: number | null;
|
||||
public approximateUserInstallCount: number | null;
|
||||
public approximateUserAuthorizationCount: number | null;
|
||||
public tags: string[];
|
||||
public installParams: ClientApplicationInstallParams | null;
|
||||
public integrationTypesConfig: IntegrationTypesConfiguration | null;
|
||||
@@ -1439,6 +1428,23 @@ export class CommandInteractionOptionResolver<Cached extends CacheType = CacheTy
|
||||
}
|
||||
|
||||
export class ContextMenuCommandInteraction<Cached extends CacheType = CacheType> extends CommandInteraction<Cached> {
|
||||
public options: Omit<
|
||||
CommandInteractionOptionResolver<Cached>,
|
||||
| 'getMessage'
|
||||
| 'getFocused'
|
||||
| 'getMentionable'
|
||||
| 'getRole'
|
||||
| 'getUser'
|
||||
| 'getMember'
|
||||
| 'getAttachment'
|
||||
| 'getNumber'
|
||||
| 'getInteger'
|
||||
| 'getString'
|
||||
| 'getChannel'
|
||||
| 'getBoolean'
|
||||
| 'getSubcommandGroup'
|
||||
| 'getSubcommand'
|
||||
>;
|
||||
public commandType: ApplicationCommandType.Message | ApplicationCommandType.User;
|
||||
public targetId: Snowflake;
|
||||
public inGuild(): this is ContextMenuCommandInteraction<'raw' | 'cached'>;
|
||||
@@ -1447,6 +1453,15 @@ export class ContextMenuCommandInteraction<Cached extends CacheType = CacheType>
|
||||
private resolveContextMenuOptions(data: APIApplicationCommandInteractionData): CommandInteractionOption<Cached>[];
|
||||
}
|
||||
|
||||
export class PrimaryEntryPointCommandInteraction<
|
||||
Cached extends CacheType = CacheType,
|
||||
> extends CommandInteraction<Cached> {
|
||||
public commandType: ApplicationCommandType.PrimaryEntryPoint;
|
||||
public inGuild(): this is PrimaryEntryPointCommandInteraction<'raw' | 'cached'>;
|
||||
public inCachedGuild(): this is PrimaryEntryPointCommandInteraction<'cached'>;
|
||||
public inRawGuild(): this is PrimaryEntryPointCommandInteraction<'raw'>;
|
||||
}
|
||||
|
||||
// tslint:disable-next-line no-empty-interface
|
||||
export interface DMChannel
|
||||
extends Omit<
|
||||
@@ -1607,9 +1622,9 @@ export class Guild extends AnonymousGuild {
|
||||
public editOnboarding(options: GuildOnboardingEditOptions): Promise<GuildOnboarding>;
|
||||
public editWelcomeScreen(options: WelcomeScreenEditOptions): Promise<WelcomeScreen>;
|
||||
public equals(guild: Guild): boolean;
|
||||
public fetchAuditLogs<Event extends GuildAuditLogsResolvable = null>(
|
||||
public fetchAuditLogs<Event extends GuildAuditLogsResolvable = AuditLogEvent>(
|
||||
options?: GuildAuditLogsFetchOptions<Event>,
|
||||
): Promise<GuildAuditLogs<Event>>;
|
||||
): Promise<GuildAuditLogs<Event extends null ? AuditLogEvent : Event>>;
|
||||
public fetchIntegrations(): Promise<Collection<Snowflake | string, Integration>>;
|
||||
public fetchOnboarding(): Promise<GuildOnboarding>;
|
||||
public fetchOwner(options?: BaseFetchOptions): Promise<GuildMember>;
|
||||
@@ -1666,7 +1681,7 @@ export class FileComponent extends Component<APIFileComponent> {
|
||||
public get spoiler(): boolean;
|
||||
}
|
||||
|
||||
export class GuildAuditLogs<Event extends GuildAuditLogsResolvable = AuditLogEvent> {
|
||||
export class GuildAuditLogs<Event extends AuditLogEvent = AuditLogEvent> {
|
||||
private constructor(guild: Guild, data: RawGuildAuditLogData);
|
||||
private applicationCommands: Collection<Snowflake, ApplicationCommand>;
|
||||
private webhooks: Collection<Snowflake, Webhook<WebhookType.ChannelFollower | WebhookType.Incoming>>;
|
||||
@@ -1678,33 +1693,30 @@ export class GuildAuditLogs<Event extends GuildAuditLogsResolvable = AuditLogEve
|
||||
}
|
||||
|
||||
export class GuildAuditLogsEntry<
|
||||
TAction extends GuildAuditLogsResolvable = AuditLogEvent,
|
||||
TAction extends AuditLogEvent = AuditLogEvent,
|
||||
TActionType extends GuildAuditLogsActionType = TAction extends keyof GuildAuditLogsTypes
|
||||
? GuildAuditLogsTypes[TAction][1]
|
||||
: GuildAuditLogsActionType,
|
||||
: 'All',
|
||||
TTargetType extends GuildAuditLogsTargetType = TAction extends keyof GuildAuditLogsTypes
|
||||
? GuildAuditLogsTypes[TAction][0]
|
||||
: GuildAuditLogsTargetType,
|
||||
TResolvedType = TAction extends null ? AuditLogEvent : TAction,
|
||||
: 'Unknown',
|
||||
> {
|
||||
private constructor(guild: Guild, data: RawGuildAuditLogEntryData, logs?: GuildAuditLogs);
|
||||
public static Targets: GuildAuditLogsTargets;
|
||||
public action: TResolvedType;
|
||||
public action: TAction;
|
||||
public actionType: TActionType;
|
||||
public changes: AuditLogChange[];
|
||||
public get createdAt(): Date;
|
||||
public get createdTimestamp(): number;
|
||||
public executorId: Snowflake | null;
|
||||
public executor: User | null;
|
||||
public extra: TResolvedType extends keyof GuildAuditLogsEntryExtraField
|
||||
? GuildAuditLogsEntryExtraField[TResolvedType]
|
||||
: null;
|
||||
public executor: User | PartialUser | null;
|
||||
public extra: TAction extends keyof GuildAuditLogsEntryExtraField ? GuildAuditLogsEntryExtraField[TAction] : null;
|
||||
public id: Snowflake;
|
||||
public reason: string | null;
|
||||
public targetId: Snowflake | null;
|
||||
public target: TTargetType extends keyof GuildAuditLogsEntryTargetField<TActionType>
|
||||
? GuildAuditLogsEntryTargetField<TActionType>[TTargetType]
|
||||
: Role | GuildEmoji | { id: Snowflake } | null;
|
||||
public target: TTargetType extends keyof GuildAuditLogsEntryTargetField<TAction>
|
||||
? GuildAuditLogsEntryTargetField<TAction>[TTargetType]
|
||||
: { id: Snowflake | undefined; [x: string]: unknown } | null;
|
||||
public targetType: TTargetType;
|
||||
public static actionType(action: AuditLogEvent): GuildAuditLogsActionType;
|
||||
public static targetType(target: AuditLogEvent): GuildAuditLogsTargetType;
|
||||
@@ -1787,6 +1799,7 @@ export class GuildMember extends Base {
|
||||
private constructor(client: Client<true>, data: RawGuildMemberData, guild: Guild);
|
||||
private _roles: Snowflake[];
|
||||
public avatar: string | null;
|
||||
public avatarDecorationData: AvatarDecorationData | null;
|
||||
public banner: string | null;
|
||||
public get bannable(): boolean;
|
||||
public get dmChannel(): DMChannel | null;
|
||||
@@ -1814,6 +1827,7 @@ export class GuildMember extends Base {
|
||||
public user: User;
|
||||
public get voice(): VoiceState;
|
||||
public avatarURL(options?: ImageURLOptions): string | null;
|
||||
public avatarDecorationURL(): string | null;
|
||||
public bannerURL(options?: ImageURLOptions): string | null;
|
||||
public ban(options?: BanOptions): Promise<GuildMember>;
|
||||
public disableCommunicationUntil(timeout: DateResolvable | null, reason?: string): Promise<GuildMember>;
|
||||
@@ -1823,6 +1837,7 @@ export class GuildMember extends Base {
|
||||
public deleteDM(): Promise<DMChannel>;
|
||||
public displayAvatarURL(options?: ImageURLOptions): string;
|
||||
public displayBannerURL(options?: ImageURLOptions): string | null;
|
||||
public displayAvatarDecorationURL(): string | null;
|
||||
public edit(options: GuildMemberEditOptions): Promise<GuildMember>;
|
||||
public isCommunicationDisabled(): this is GuildMember & {
|
||||
communicationDisabledUntilTimestamp: number;
|
||||
@@ -2065,6 +2080,7 @@ export type Interaction<Cached extends CacheType = CacheType> =
|
||||
| ChatInputCommandInteraction<Cached>
|
||||
| MessageContextMenuCommandInteraction<Cached>
|
||||
| UserContextMenuCommandInteraction<Cached>
|
||||
| PrimaryEntryPointCommandInteraction<Cached>
|
||||
| AnySelectMenuInteraction<Cached>
|
||||
| ButtonInteraction<Cached>
|
||||
| AutocompleteInteraction<Cached>
|
||||
@@ -2105,6 +2121,7 @@ export class BaseInteraction<Cached extends CacheType = CacheType> extends Base
|
||||
public locale: Locale;
|
||||
public guildLocale: CacheTypeReducer<Cached, Locale>;
|
||||
public entitlements: Collection<Snowflake, Entitlement>;
|
||||
public attachmentSizeLimit: number;
|
||||
public inGuild(): this is BaseInteraction<'raw' | 'cached'>;
|
||||
public inCachedGuild(): this is BaseInteraction<'cached'>;
|
||||
public inRawGuild(): this is BaseInteraction<'raw'>;
|
||||
@@ -2113,6 +2130,7 @@ export class BaseInteraction<Cached extends CacheType = CacheType> extends Base
|
||||
public isChatInputCommand(): this is ChatInputCommandInteraction<Cached>;
|
||||
public isCommand(): this is CommandInteraction<Cached>;
|
||||
public isContextMenuCommand(): this is ContextMenuCommandInteraction<Cached>;
|
||||
public isPrimaryEntryPointCommand(): this is PrimaryEntryPointCommandInteraction<Cached>;
|
||||
public isMessageComponent(): this is MessageComponentInteraction<Cached>;
|
||||
public isMessageContextMenuCommand(): this is MessageContextMenuCommandInteraction<Cached>;
|
||||
public isModalSubmit(): this is ModalSubmitInteraction<Cached>;
|
||||
@@ -2540,6 +2558,9 @@ export class MessageComponentInteraction<Cached extends CacheType = CacheType> e
|
||||
public update(
|
||||
options: string | MessagePayload | InteractionUpdateOptions,
|
||||
): Promise<InteractionResponse<BooleanCache<Cached>>>;
|
||||
public launchActivity(options: LaunchActivityOptions & { withResponse: true }): Promise<InteractionCallbackResponse>;
|
||||
public launchActivity(options?: LaunchActivityOptions & { withResponse?: false }): Promise<undefined>;
|
||||
public launchActivity(options?: LaunchActivityOptions): Promise<InteractionCallbackResponse | undefined>;
|
||||
public showModal(
|
||||
modal:
|
||||
| JSONEncodable<APIModalInteractionResponseCallbackData>
|
||||
@@ -2786,6 +2807,9 @@ export class ModalSubmitInteraction<Cached extends CacheType = CacheType> extend
|
||||
public deferUpdate(options?: InteractionDeferUpdateOptions): Promise<InteractionResponse<BooleanCache<Cached>>>;
|
||||
/** @deprecated Sending a premium-style button is the new Discord behaviour. */
|
||||
public sendPremiumRequired(): Promise<void>;
|
||||
public launchActivity(options: LaunchActivityOptions & { withResponse: true }): Promise<InteractionCallbackResponse>;
|
||||
public launchActivity(options?: LaunchActivityOptions & { withResponse?: false }): Promise<undefined>;
|
||||
public launchActivity(options?: LaunchActivityOptions): Promise<InteractionCallbackResponse | undefined>;
|
||||
public inGuild(): this is ModalSubmitInteraction<'raw' | 'cached'>;
|
||||
public inCachedGuild(): this is ModalSubmitInteraction<'cached'>;
|
||||
public inRawGuild(): this is ModalSubmitInteraction<'raw'>;
|
||||
@@ -3222,7 +3246,7 @@ export type SelectMenuType = APISelectMenuComponent['type'];
|
||||
|
||||
export interface SeparatorComponentData extends BaseComponentData {
|
||||
spacing?: SeparatorSpacingSize;
|
||||
dividier?: boolean;
|
||||
divider?: boolean;
|
||||
}
|
||||
export class SeparatorComponent extends Component<APISeparatorComponent> {
|
||||
private constructor(data: APISeparatorComponent);
|
||||
@@ -4860,8 +4884,15 @@ export interface GuildSoundboardSoundEditOptions {
|
||||
volume?: number | null;
|
||||
emojiId?: Snowflake | null;
|
||||
emojiName?: string | null;
|
||||
reason?: string;
|
||||
}
|
||||
|
||||
export interface FetchGuildSoundboardSoundOptions extends BaseFetchOptions {
|
||||
soundboardSound: SoundboardSoundResolvable;
|
||||
}
|
||||
|
||||
export interface FetchGuildSoundboardSoundsOptions extends Pick<BaseFetchOptions, 'cache'> {}
|
||||
|
||||
export class GuildSoundboardSoundManager extends CachedManager<Snowflake, SoundboardSound, SoundboardSoundResolvable> {
|
||||
private constructor(guild: Guild, iterable?: Iterable<APISoundboardSound>);
|
||||
public guild: Guild;
|
||||
@@ -4871,8 +4902,8 @@ export class GuildSoundboardSoundManager extends CachedManager<Snowflake, Soundb
|
||||
options: GuildSoundboardSoundEditOptions,
|
||||
): Promise<GuildSoundboardSound>;
|
||||
public delete(soundboardSound: SoundboardSoundResolvable): Promise<void>;
|
||||
public fetch(id: Snowflake, options?: BaseFetchOptions): Promise<GuildSoundboardSound>;
|
||||
public fetch(options?: BaseFetchOptions): Promise<Collection<Snowflake, GuildSoundboardSound>>;
|
||||
public fetch(options: SoundboardSoundResolvable | FetchGuildSoundboardSoundOptions): Promise<GuildSoundboardSound>;
|
||||
public fetch(options?: FetchGuildSoundboardSoundsOptions): Promise<Collection<Snowflake, GuildSoundboardSound>>;
|
||||
}
|
||||
|
||||
export class GuildStickerManager extends CachedManager<Snowflake, Sticker, StickerResolvable> {
|
||||
@@ -5266,10 +5297,18 @@ export interface ChatInputApplicationCommandData extends BaseApplicationCommandD
|
||||
options?: readonly ApplicationCommandOptionData[];
|
||||
}
|
||||
|
||||
export interface PrimaryEntryPointCommandData extends BaseApplicationCommandData {
|
||||
description?: string;
|
||||
descriptionLocalizations?: LocalizationMap;
|
||||
type: ApplicationCommandType.PrimaryEntryPoint;
|
||||
handler?: EntryPointCommandHandlerType;
|
||||
}
|
||||
|
||||
export type ApplicationCommandData =
|
||||
| UserApplicationCommandData
|
||||
| MessageApplicationCommandData
|
||||
| ChatInputApplicationCommandData;
|
||||
| ChatInputApplicationCommandData
|
||||
| PrimaryEntryPointCommandData;
|
||||
|
||||
export interface ApplicationCommandChannelOptionData extends BaseApplicationCommandOptionsData {
|
||||
type: CommandOptionChannelResolvableType;
|
||||
@@ -5752,9 +5791,13 @@ export interface ClientEvents {
|
||||
guildMembersChunk: [members: ReadonlyCollection<Snowflake, GuildMember>, guild: Guild, data: GuildMembersChunk];
|
||||
guildMemberUpdate: [oldMember: GuildMember | PartialGuildMember, newMember: GuildMember];
|
||||
guildUpdate: [oldGuild: Guild, newGuild: Guild];
|
||||
guildSoundboardSoundCreate: [soundboardSound: SoundboardSound];
|
||||
guildSoundboardSoundDelete: [soundboardSound: SoundboardSound | PartialSoundboardSound];
|
||||
guildSoundboardSoundUpdate: [oldSoundboardSound: SoundboardSound | null, newSoundboardSound: SoundboardSound];
|
||||
guildSoundboardSoundCreate: [soundboardSound: GuildSoundboardSound];
|
||||
guildSoundboardSoundDelete: [soundboardSound: GuildSoundboardSound | PartialSoundboardSound];
|
||||
guildSoundboardSoundUpdate: [
|
||||
oldSoundboardSound: GuildSoundboardSound | null,
|
||||
newSoundboardSound: GuildSoundboardSound,
|
||||
];
|
||||
guildSoundboardSoundsUpdate: [soundboardSounds: ReadonlyCollection<Snowflake, GuildSoundboardSound>, guild: Guild];
|
||||
inviteCreate: [invite: Invite];
|
||||
inviteDelete: [invite: Invite];
|
||||
messageCreate: [message: OmitPartialGroupDMChannel<Message>];
|
||||
@@ -5830,7 +5873,7 @@ export interface ClientEvents {
|
||||
guildScheduledEventDelete: [guildScheduledEvent: GuildScheduledEvent | PartialGuildScheduledEvent];
|
||||
guildScheduledEventUserAdd: [guildScheduledEvent: GuildScheduledEvent | PartialGuildScheduledEvent, user: User];
|
||||
guildScheduledEventUserRemove: [guildScheduledEvent: GuildScheduledEvent | PartialGuildScheduledEvent, user: User];
|
||||
soundboardSounds: [soundboardSounds: ReadonlyCollection<Snowflake, SoundboardSound>, guild: Guild];
|
||||
soundboardSounds: [soundboardSounds: ReadonlyCollection<Snowflake, GuildSoundboardSound>, guild: Guild];
|
||||
}
|
||||
|
||||
export interface ClientFetchInviteOptions {
|
||||
@@ -6334,12 +6377,15 @@ interface GuildAuditLogsTypes {
|
||||
[AuditLogEvent.ThreadUpdate]: ['Thread', 'Update'];
|
||||
[AuditLogEvent.ThreadDelete]: ['Thread', 'Delete'];
|
||||
[AuditLogEvent.ApplicationCommandPermissionUpdate]: ['ApplicationCommand', 'Update'];
|
||||
[AuditLogEvent.SoundboardSoundCreate]: ['SoundboardSound', 'Create'];
|
||||
[AuditLogEvent.SoundboardSoundUpdate]: ['SoundboardSound', 'Update'];
|
||||
[AuditLogEvent.SoundboardSoundDelete]: ['SoundboardSound', 'Delete'];
|
||||
[AuditLogEvent.AutoModerationRuleCreate]: ['AutoModeration', 'Create'];
|
||||
[AuditLogEvent.AutoModerationRuleUpdate]: ['AutoModeration', 'Update'];
|
||||
[AuditLogEvent.AutoModerationRuleDelete]: ['AutoModeration', 'Delete'];
|
||||
[AuditLogEvent.AutoModerationBlockMessage]: ['AutoModeration', 'Create'];
|
||||
[AuditLogEvent.AutoModerationFlagToChannel]: ['AutoModeration', 'Create'];
|
||||
[AuditLogEvent.AutoModerationUserCommunicationDisabled]: ['AutoModeration', 'Create'];
|
||||
[AuditLogEvent.AutoModerationBlockMessage]: ['User', 'Update'];
|
||||
[AuditLogEvent.AutoModerationFlagToChannel]: ['User', 'Update'];
|
||||
[AuditLogEvent.AutoModerationUserCommunicationDisabled]: ['User', 'Update'];
|
||||
[AuditLogEvent.OnboardingPromptCreate]: ['GuildOnboardingPrompt', 'Create'];
|
||||
[AuditLogEvent.OnboardingPromptUpdate]: ['GuildOnboardingPrompt', 'Update'];
|
||||
[AuditLogEvent.OnboardingPromptDelete]: ['GuildOnboardingPrompt', 'Delete'];
|
||||
@@ -6355,7 +6401,7 @@ export interface GuildAuditLogsEntryExtraField {
|
||||
[AuditLogEvent.MemberPrune]: { removed: number; days: number };
|
||||
[AuditLogEvent.MemberMove]: { channel: VoiceBasedChannel | { id: Snowflake }; count: number };
|
||||
[AuditLogEvent.MessageDelete]: { channel: GuildTextBasedChannel | { id: Snowflake }; count: number };
|
||||
[AuditLogEvent.MessageBulkDelete]: { channel: GuildTextBasedChannel | { id: Snowflake }; count: number };
|
||||
[AuditLogEvent.MessageBulkDelete]: { count: number };
|
||||
[AuditLogEvent.MessagePin]: { channel: GuildTextBasedChannel | { id: Snowflake }; messageId: Snowflake };
|
||||
[AuditLogEvent.MessageUnpin]: { channel: GuildTextBasedChannel | { id: Snowflake }; messageId: Snowflake };
|
||||
[AuditLogEvent.MemberDisconnect]: { count: number };
|
||||
@@ -6395,12 +6441,14 @@ export interface GuildAuditLogsEntryExtraField {
|
||||
};
|
||||
}
|
||||
|
||||
export interface GuildAuditLogsEntryTargetField<TActionType extends GuildAuditLogsActionType> {
|
||||
User: User | null;
|
||||
export interface GuildAuditLogsEntryTargetField<TAction extends AuditLogEvent> {
|
||||
User: User | PartialUser | null;
|
||||
Guild: Guild;
|
||||
Webhook: Webhook<WebhookType.ChannelFollower | WebhookType.Incoming>;
|
||||
Invite: Invite;
|
||||
Message: TActionType extends AuditLogEvent.MessageBulkDelete ? Guild | { id: Snowflake } : User;
|
||||
Emoji: GuildEmoji | { id: Snowflake };
|
||||
Role: Role | { id: Snowflake };
|
||||
Message: TAction extends AuditLogEvent.MessageBulkDelete ? GuildTextBasedChannel | { id: Snowflake } : User | null;
|
||||
Integration: Integration;
|
||||
Channel: NonThreadGuildBasedChannel | { id: Snowflake; [x: string]: unknown };
|
||||
Thread: AnyThreadChannel | { id: Snowflake; [x: string]: unknown };
|
||||
@@ -6409,7 +6457,8 @@ export interface GuildAuditLogsEntryTargetField<TActionType extends GuildAuditLo
|
||||
GuildScheduledEvent: GuildScheduledEvent;
|
||||
ApplicationCommand: ApplicationCommand | { id: Snowflake };
|
||||
AutoModerationRule: AutoModerationRule;
|
||||
GuildOnboardingPrompt: GuildOnboardingPrompt;
|
||||
GuildOnboardingPrompt: GuildOnboardingPrompt | { id: Snowflake; [x: string]: unknown };
|
||||
SoundboardSound: SoundboardSound | { id: Snowflake };
|
||||
}
|
||||
|
||||
export interface GuildAuditLogsFetchOptions<Event extends GuildAuditLogsResolvable> {
|
||||
@@ -6422,10 +6471,10 @@ export interface GuildAuditLogsFetchOptions<Event extends GuildAuditLogsResolvab
|
||||
|
||||
export type GuildAuditLogsResolvable = AuditLogEvent | null;
|
||||
|
||||
export type GuildAuditLogsTargetType = GuildAuditLogsTypes[keyof GuildAuditLogsTypes][0] | 'All' | 'Unknown';
|
||||
export type GuildAuditLogsTargetType = GuildAuditLogsTypes[keyof GuildAuditLogsTypes][0] | 'Unknown';
|
||||
|
||||
export type GuildAuditLogsTargets = {
|
||||
[Key in GuildAuditLogsTargetType]: GuildAuditLogsTargetType;
|
||||
[Key in GuildAuditLogsTargetType]: Key;
|
||||
};
|
||||
|
||||
export type GuildBanResolvable = GuildBan | UserResolvable;
|
||||
@@ -7034,7 +7083,12 @@ export interface MessageEditAttachmentData {
|
||||
export interface MessageEditOptions extends Omit<BaseMessageOptions, 'content'> {
|
||||
content?: string | null;
|
||||
attachments?: readonly (Attachment | MessageEditAttachmentData)[];
|
||||
flags?: BitFieldResolvable<Extract<MessageFlagsString, 'SuppressEmbeds'>, MessageFlags.SuppressEmbeds> | undefined;
|
||||
flags?:
|
||||
| BitFieldResolvable<
|
||||
Extract<MessageFlagsString, 'SuppressEmbeds' | 'IsComponentsV2'>,
|
||||
MessageFlags.SuppressEmbeds | MessageFlags.IsComponentsV2
|
||||
>
|
||||
| undefined;
|
||||
}
|
||||
|
||||
export type MessageReactionResolvable = MessageReaction | Snowflake | string;
|
||||
@@ -7360,6 +7414,10 @@ export interface ShowModalOptions {
|
||||
withResponse?: boolean;
|
||||
}
|
||||
|
||||
export interface LaunchActivityOptions {
|
||||
withResponse?: boolean;
|
||||
}
|
||||
|
||||
export { Snowflake };
|
||||
|
||||
export type StageInstanceResolvable = StageInstance | Snowflake;
|
||||
@@ -7550,6 +7608,7 @@ export interface WebhookEditOptions {
|
||||
|
||||
export interface WebhookMessageEditOptions extends MessageEditOptions {
|
||||
threadId?: Snowflake;
|
||||
withComponents?: boolean;
|
||||
}
|
||||
|
||||
export interface InteractionEditReplyOptions
|
||||
@@ -7569,6 +7628,7 @@ export interface WebhookMessageCreateOptions
|
||||
threadId?: Snowflake;
|
||||
threadName?: string;
|
||||
appliedTags?: readonly Snowflake[];
|
||||
withComponents?: boolean;
|
||||
}
|
||||
|
||||
export interface WebSocketOptions {
|
||||
|
||||
@@ -218,6 +218,7 @@ import {
|
||||
PollData,
|
||||
UserManager,
|
||||
InteractionCallbackResponse,
|
||||
PrimaryEntryPointCommandInteraction,
|
||||
GuildScheduledEventRecurrenceRuleOptions,
|
||||
ThreadOnlyChannel,
|
||||
SectionComponentData,
|
||||
@@ -229,6 +230,7 @@ import {
|
||||
SeparatorComponentData,
|
||||
FileComponentData,
|
||||
ContainerComponentData,
|
||||
InteractionResponse,
|
||||
} from '.';
|
||||
import {
|
||||
expectAssignable,
|
||||
@@ -687,7 +689,7 @@ client.on('messageCreate', async message => {
|
||||
const rawSeparator: SeparatorComponentData = {
|
||||
type: ComponentType.Separator,
|
||||
spacing: 1,
|
||||
dividier: false,
|
||||
divider: false,
|
||||
};
|
||||
|
||||
const rawFile: FileComponentData = {
|
||||
@@ -1889,6 +1891,11 @@ client.on('interactionCreate', async interaction => {
|
||||
expectType<Promise<InteractionCallbackResponse>>(interaction.update({ content: 'a', withResponse: true }));
|
||||
expectType<Promise<InteractionCallbackResponse>>(interaction.deferUpdate({ withResponse: true }));
|
||||
expectType<Promise<Message<true>>>(interaction.followUp({ content: 'a' }));
|
||||
expectType<Promise<InteractionCallbackResponse>>(interaction.launchActivity({ withResponse: true }));
|
||||
expectType<Promise<undefined>>(interaction.launchActivity({ withResponse: false }));
|
||||
expectType<Promise<InteractionCallbackResponse | undefined>>(
|
||||
interaction.launchActivity({ withResponse: booleanValue }),
|
||||
);
|
||||
} else if (interaction.inRawGuild()) {
|
||||
expectAssignable<MessageComponentInteraction>(interaction);
|
||||
expectType<APIButtonComponent | APISelectMenuComponent>(interaction.component);
|
||||
@@ -1905,6 +1912,11 @@ client.on('interactionCreate', async interaction => {
|
||||
expectType<Promise<InteractionCallbackResponse>>(interaction.update({ content: 'a', withResponse: true }));
|
||||
expectType<Promise<InteractionCallbackResponse>>(interaction.deferUpdate({ withResponse: true }));
|
||||
expectType<Promise<Message<false>>>(interaction.followUp({ content: 'a' }));
|
||||
expectType<Promise<InteractionCallbackResponse>>(interaction.launchActivity({ withResponse: true }));
|
||||
expectType<Promise<undefined>>(interaction.launchActivity({ withResponse: false }));
|
||||
expectType<Promise<InteractionCallbackResponse | undefined>>(
|
||||
interaction.launchActivity({ withResponse: booleanValue }),
|
||||
);
|
||||
} else if (interaction.inGuild()) {
|
||||
expectAssignable<MessageComponentInteraction>(interaction);
|
||||
expectType<MessageActionRowComponent | APIButtonComponent | APISelectMenuComponent>(interaction.component);
|
||||
@@ -1921,6 +1933,11 @@ client.on('interactionCreate', async interaction => {
|
||||
expectType<Promise<InteractionCallbackResponse>>(interaction.update({ content: 'a', withResponse: true }));
|
||||
expectType<Promise<InteractionCallbackResponse>>(interaction.deferUpdate({ withResponse: true }));
|
||||
expectType<Promise<Message>>(interaction.followUp({ content: 'a' }));
|
||||
expectType<Promise<InteractionCallbackResponse>>(interaction.launchActivity({ withResponse: true }));
|
||||
expectType<Promise<undefined>>(interaction.launchActivity({ withResponse: false }));
|
||||
expectType<Promise<InteractionCallbackResponse | undefined>>(
|
||||
interaction.launchActivity({ withResponse: booleanValue }),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1960,6 +1977,11 @@ client.on('interactionCreate', async interaction => {
|
||||
expectType<Promise<Message<true>>>(interaction.editReply({ content: 'a' }));
|
||||
expectType<Promise<Message<true>>>(interaction.fetchReply());
|
||||
expectType<Promise<Message<true>>>(interaction.followUp({ content: 'a' }));
|
||||
expectType<Promise<InteractionCallbackResponse>>(interaction.launchActivity({ withResponse: true }));
|
||||
expectType<Promise<undefined>>(interaction.launchActivity({ withResponse: false }));
|
||||
expectType<Promise<InteractionCallbackResponse | undefined>>(
|
||||
interaction.launchActivity({ withResponse: booleanValue }),
|
||||
);
|
||||
} else if (interaction.inRawGuild()) {
|
||||
expectAssignable<ContextMenuCommandInteraction>(interaction);
|
||||
expectType<null>(interaction.guild);
|
||||
@@ -1970,6 +1992,11 @@ client.on('interactionCreate', async interaction => {
|
||||
expectType<Promise<Message<false>>>(interaction.editReply({ content: 'a' }));
|
||||
expectType<Promise<Message<false>>>(interaction.fetchReply());
|
||||
expectType<Promise<Message<false>>>(interaction.followUp({ content: 'a' }));
|
||||
expectType<Promise<InteractionCallbackResponse>>(interaction.launchActivity({ withResponse: true }));
|
||||
expectType<Promise<undefined>>(interaction.launchActivity({ withResponse: false }));
|
||||
expectType<Promise<InteractionCallbackResponse | undefined>>(
|
||||
interaction.launchActivity({ withResponse: booleanValue }),
|
||||
);
|
||||
} else if (interaction.inGuild()) {
|
||||
expectAssignable<ContextMenuCommandInteraction>(interaction);
|
||||
expectType<Guild | null>(interaction.guild);
|
||||
@@ -1980,6 +2007,11 @@ client.on('interactionCreate', async interaction => {
|
||||
expectType<Promise<Message>>(interaction.editReply({ content: 'a' }));
|
||||
expectType<Promise<Message>>(interaction.fetchReply());
|
||||
expectType<Promise<Message>>(interaction.followUp({ content: 'a' }));
|
||||
expectType<Promise<InteractionCallbackResponse>>(interaction.launchActivity({ withResponse: true }));
|
||||
expectType<Promise<undefined>>(interaction.launchActivity({ withResponse: false }));
|
||||
expectType<Promise<InteractionCallbackResponse | undefined>>(
|
||||
interaction.launchActivity({ withResponse: booleanValue }),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2164,6 +2196,57 @@ client.on('interactionCreate', async interaction => {
|
||||
interaction.options.getMessage('name');
|
||||
}
|
||||
|
||||
if (
|
||||
interaction.type === InteractionType.ApplicationCommand &&
|
||||
interaction.commandType === ApplicationCommandType.PrimaryEntryPoint
|
||||
) {
|
||||
expectType<PrimaryEntryPointCommandInteraction>(interaction);
|
||||
|
||||
// @ts-expect-error No options on primary entry point commands
|
||||
interaction.options;
|
||||
if (interaction.inCachedGuild()) {
|
||||
expectAssignable<PrimaryEntryPointCommandInteraction>(interaction);
|
||||
expectAssignable<Guild>(interaction.guild);
|
||||
expectAssignable<CommandInteraction<'cached'>>(interaction);
|
||||
expectType<Promise<InteractionCallbackResponse>>(interaction.reply({ content: 'a', withResponse: true }));
|
||||
expectType<Promise<InteractionCallbackResponse>>(interaction.deferReply({ withResponse: true }));
|
||||
expectType<Promise<InteractionResponse<true>>>(interaction.deferReply());
|
||||
expectType<Promise<InteractionResponse<true>>>(interaction.reply({ content: 'a', withResponse: false }));
|
||||
expectType<Promise<InteractionResponse<true>>>(interaction.deferReply({ withResponse: false }));
|
||||
expectType<Promise<Message<true>>>(interaction.editReply({ content: 'a' }));
|
||||
expectType<Promise<Message<true>>>(interaction.fetchReply());
|
||||
expectType<Promise<Message<true>>>(interaction.followUp({ content: 'a' }));
|
||||
expectType<Promise<InteractionCallbackResponse>>(interaction.launchActivity({ withResponse: true }));
|
||||
expectType<Promise<undefined>>(interaction.launchActivity({ withResponse: false }));
|
||||
} else if (interaction.inRawGuild()) {
|
||||
expectAssignable<PrimaryEntryPointCommandInteraction>(interaction);
|
||||
expectType<null>(interaction.guild);
|
||||
expectType<Promise<InteractionCallbackResponse>>(interaction.reply({ content: 'a', withResponse: true }));
|
||||
expectType<Promise<InteractionCallbackResponse>>(interaction.deferReply({ withResponse: true }));
|
||||
expectType<Promise<InteractionResponse<false>>>(interaction.deferReply());
|
||||
expectType<Promise<InteractionResponse<false>>>(interaction.reply({ content: 'a', withResponse: false }));
|
||||
expectType<Promise<InteractionResponse<false>>>(interaction.deferReply({ withResponse: false }));
|
||||
expectType<Promise<Message<false>>>(interaction.editReply({ content: 'a' }));
|
||||
expectType<Promise<Message<false>>>(interaction.fetchReply());
|
||||
expectType<Promise<Message<false>>>(interaction.followUp({ content: 'a' }));
|
||||
expectType<Promise<InteractionCallbackResponse>>(interaction.launchActivity({ withResponse: true }));
|
||||
expectType<Promise<undefined>>(interaction.launchActivity({ withResponse: false }));
|
||||
} else if (interaction.inGuild()) {
|
||||
expectAssignable<PrimaryEntryPointCommandInteraction>(interaction);
|
||||
expectType<Guild | null>(interaction.guild);
|
||||
expectType<Promise<InteractionCallbackResponse>>(interaction.reply({ content: 'a', withResponse: true }));
|
||||
expectType<Promise<InteractionCallbackResponse>>(interaction.deferReply({ withResponse: true }));
|
||||
expectType<Promise<InteractionResponse>>(interaction.deferReply());
|
||||
expectType<Promise<InteractionResponse>>(interaction.reply({ content: 'a', withResponse: false }));
|
||||
expectType<Promise<InteractionResponse>>(interaction.deferReply({ withResponse: false }));
|
||||
expectType<Promise<Message>>(interaction.editReply({ content: 'a' }));
|
||||
expectType<Promise<Message>>(interaction.fetchReply());
|
||||
expectType<Promise<Message>>(interaction.followUp({ content: 'a' }));
|
||||
expectType<Promise<InteractionCallbackResponse>>(interaction.launchActivity({ withResponse: true }));
|
||||
expectType<Promise<undefined>>(interaction.launchActivity({ withResponse: false }));
|
||||
}
|
||||
}
|
||||
|
||||
if (interaction.isRepliable()) {
|
||||
expectAssignable<RepliableInteraction>(interaction);
|
||||
interaction.reply('test');
|
||||
@@ -2192,6 +2275,7 @@ client.on('interactionCreate', async interaction => {
|
||||
expectType<Promise<Message<true>>>(interaction.deferUpdate({ fetchReply: true }));
|
||||
expectType<Promise<InteractionCallbackResponse>>(interaction.deferUpdate({ withResponse: true }));
|
||||
expectType<Promise<Message<true>>>(interaction.followUp({ content: 'a' }));
|
||||
expectType<Promise<InteractionCallbackResponse>>(interaction.launchActivity({ withResponse: true }));
|
||||
} else if (interaction.inRawGuild()) {
|
||||
expectAssignable<ModalSubmitInteraction>(interaction);
|
||||
expectType<null>(interaction.guild);
|
||||
@@ -2204,6 +2288,7 @@ client.on('interactionCreate', async interaction => {
|
||||
expectType<Promise<Message<false>>>(interaction.deferUpdate({ fetchReply: true }));
|
||||
expectType<Promise<InteractionCallbackResponse>>(interaction.deferUpdate({ withResponse: true }));
|
||||
expectType<Promise<Message<false>>>(interaction.followUp({ content: 'a' }));
|
||||
expectType<Promise<InteractionCallbackResponse>>(interaction.launchActivity({ withResponse: true }));
|
||||
} else if (interaction.inGuild()) {
|
||||
expectAssignable<ModalSubmitInteraction>(interaction);
|
||||
expectType<Guild | null>(interaction.guild);
|
||||
@@ -2216,6 +2301,7 @@ client.on('interactionCreate', async interaction => {
|
||||
expectType<Promise<Message>>(interaction.deferUpdate({ fetchReply: true }));
|
||||
expectType<Promise<InteractionCallbackResponse>>(interaction.deferUpdate({ withResponse: true }));
|
||||
expectType<Promise<Message>>(interaction.followUp({ content: 'a' }));
|
||||
expectType<Promise<InteractionCallbackResponse>>(interaction.launchActivity({ withResponse: true }));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2272,7 +2358,7 @@ expectType<Promise<GuildAuditLogs<AuditLogEvent.IntegrationUpdate>>>(
|
||||
guild.fetchAuditLogs({ type: AuditLogEvent.IntegrationUpdate }),
|
||||
);
|
||||
|
||||
expectType<Promise<GuildAuditLogs<null>>>(guild.fetchAuditLogs({ type: null }));
|
||||
expectType<Promise<GuildAuditLogs<AuditLogEvent>>>(guild.fetchAuditLogs({ type: null }));
|
||||
expectType<Promise<GuildAuditLogs<AuditLogEvent>>>(guild.fetchAuditLogs());
|
||||
|
||||
expectType<Promise<GuildAuditLogsEntry<AuditLogEvent.MemberKick, 'Delete', 'User'> | undefined>>(
|
||||
@@ -2282,10 +2368,10 @@ expectAssignable<Promise<GuildAuditLogsEntry<AuditLogEvent.MemberKick, 'Delete',
|
||||
guild.fetchAuditLogs({ type: AuditLogEvent.MemberKick }).then(al => al.entries.first()),
|
||||
);
|
||||
|
||||
expectType<Promise<GuildAuditLogsEntry<null, GuildAuditLogsActionType, GuildAuditLogsTargetType> | undefined>>(
|
||||
expectType<Promise<GuildAuditLogsEntry<AuditLogEvent, GuildAuditLogsActionType, GuildAuditLogsTargetType> | undefined>>(
|
||||
guild.fetchAuditLogs({ type: null }).then(al => al.entries.first()),
|
||||
);
|
||||
expectType<Promise<GuildAuditLogsEntry<null, GuildAuditLogsActionType, GuildAuditLogsTargetType> | undefined>>(
|
||||
expectType<Promise<GuildAuditLogsEntry<AuditLogEvent, GuildAuditLogsActionType, GuildAuditLogsTargetType> | undefined>>(
|
||||
guild.fetchAuditLogs().then(al => al.entries.first()),
|
||||
);
|
||||
|
||||
@@ -2304,15 +2390,18 @@ expectType<Promise<{ channel: GuildTextBasedChannel | { id: Snowflake }; count:
|
||||
guild.fetchAuditLogs({ type: AuditLogEvent.MessageDelete }).then(al => al.entries.first()?.extra),
|
||||
);
|
||||
|
||||
expectType<Promise<User | null | undefined>>(
|
||||
expectType<Promise<User | PartialUser | null | undefined>>(
|
||||
guild.fetchAuditLogs({ type: AuditLogEvent.MemberKick }).then(al => al.entries.first()?.target),
|
||||
);
|
||||
expectType<Promise<StageInstance | undefined>>(
|
||||
guild.fetchAuditLogs({ type: AuditLogEvent.StageInstanceCreate }).then(al => al.entries.first()?.target),
|
||||
);
|
||||
expectType<Promise<User | undefined>>(
|
||||
expectType<Promise<User | null | undefined>>(
|
||||
guild.fetchAuditLogs({ type: AuditLogEvent.MessageDelete }).then(al => al.entries.first()?.target),
|
||||
);
|
||||
expectType<Promise<GuildTextBasedChannel | { id: string } | undefined>>(
|
||||
guild.fetchAuditLogs({ type: AuditLogEvent.MessageBulkDelete }).then(al => al.entries.first()?.target),
|
||||
);
|
||||
|
||||
declare const AuditLogChange: AuditLogChange;
|
||||
// @ts-expect-error
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"$schema": "https://json.schemastore.org/package.json",
|
||||
"name": "@discordjs/rest",
|
||||
"version": "2.5.0",
|
||||
"version": "2.5.1",
|
||||
"description": "The REST API for discord.js",
|
||||
"scripts": {
|
||||
"test": "vitest run",
|
||||
@@ -91,7 +91,7 @@
|
||||
"discord-api-types": "^0.38.1",
|
||||
"magic-bytes.js": "^1.10.0",
|
||||
"tslib": "^2.6.3",
|
||||
"undici": "6.21.1"
|
||||
"undici": "6.21.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@discordjs/api-extractor": "workspace:^",
|
||||
|
||||
@@ -2,6 +2,37 @@
|
||||
|
||||
All notable changes to this project will be documented in this file.
|
||||
|
||||
# [@discordjs/ws@2.0.3](https://github.com/discordjs/discord.js/compare/@discordjs/ws@2.0.2...@discordjs/ws@2.0.3) - (2025-06-16)
|
||||
|
||||
## Bug Fixes
|
||||
|
||||
- Regression in allowedMentions when replying (#10866) ([2ebb5cb](https://github.com/discordjs/discord.js/commit/2ebb5cbd53d869a52cba4549e7acc417963741cd))
|
||||
|
||||
# [@discordjs/ws@2.0.0](https://github.com/discordjs/discord.js/compare/@discordjs/ws@1.1.1...@discordjs/ws@2.0.0) - (2024-09-02)
|
||||
|
||||
## Bug Fixes
|
||||
|
||||
- **WebSocketShard:** Buffer native zlib decompression payload (#10416) ([defb083](https://github.com/discordjs/discord.js/commit/defb083528ef31383778187a04ced8b00d886242)) by @didinele
|
||||
- **WebSocketManager:** Heartbeat event had outdated types (#10417) ([5eabec1](https://github.com/discordjs/discord.js/commit/5eabec14d45ef7bdd7f610e84234eb63e726eacd)) by @didinele
|
||||
- Retry for EAI_AGAIN I/O error (#10383) ([be04acd](https://github.com/discordjs/discord.js/commit/be04acd534d7d0c3fb7f6bd174e4a6482aae0d73)) by @didinele
|
||||
- Consistent debug log spacing (#10349) ([38c699b](https://github.com/discordjs/discord.js/commit/38c699bc8a2ca40f37f70c93e08067e00f12ee81)) by @Jiralite
|
||||
|
||||
## Features
|
||||
|
||||
- **WebsocketManager:** Retroactive token setting (#10418) ([de94eaf](https://github.com/discordjs/discord.js/commit/de94eaf351a69fab57ec766bd9e90e8c05e8c3d1)) by @didinele
|
||||
- **WebSocketShard:** Explicit time out network error handling (#10375) ([093ac92](https://github.com/discordjs/discord.js/commit/093ac924aef1bf328feadb49876bfbe26052fe1a)) by @didinele
|
||||
|
||||
## Refactor
|
||||
|
||||
- **WebSocketShard:** Error event handling (#10436) ([a6de270](https://github.com/discordjs/discord.js/commit/a6de2707fc1107262b12491f73b5b6887df91c67)) by @didinele
|
||||
- **ws:** Event layout (#10376) ([bf6761a](https://github.com/discordjs/discord.js/commit/bf6761a44adec1fe5017f6bf5d8bc0734916961f)) by @didinele
|
||||
- **BREAKING CHANGE:** All events now emit shard id as its own param
|
||||
|
||||
* fix: worker event forwarding
|
||||
|
||||
---------
|
||||
- Native zlib support (#10316) ([94cc02a](https://github.com/discordjs/discord.js/commit/94cc02a2580496774d75673abc0caabc765d9ee0)) by @sdanialraza
|
||||
|
||||
# [@discordjs/ws@2.0.0](https://github.com/discordjs/discord.js/compare/@discordjs/ws@1.1.1...@discordjs/ws@2.0.0) - (2024-09-02)
|
||||
|
||||
## Bug Fixes
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"$schema": "https://json.schemastore.org/package.json",
|
||||
"name": "@discordjs/ws",
|
||||
"version": "2.0.2",
|
||||
"version": "2.0.3",
|
||||
"description": "Wrapper around Discord's gateway",
|
||||
"scripts": {
|
||||
"test": "vitest run",
|
||||
@@ -100,9 +100,9 @@
|
||||
"tsup": "^8.2.4",
|
||||
"turbo": "^2.0.14",
|
||||
"typescript": "~5.5.4",
|
||||
"undici": "6.21.1",
|
||||
"undici": "6.21.3",
|
||||
"vitest": "^2.0.5",
|
||||
"zlib-sync": "^0.1.9"
|
||||
"zlib-sync": "^0.1.10"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=20"
|
||||
|
||||
3328
pnpm-lock.yaml
generated
3328
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user