Compare commits

..

4 Commits

Author SHA1 Message Date
Vlad Frangu
d6c7b8fe05 chore(builders): release @discordjs/builders@1.10.0 2025-01-01 23:24:11 +02:00
Vlad Frangu
e9d6046047 chore(formatters): release @discordjs/formatters@0.6.0 2025-01-01 23:23:37 +02:00
Jiralite
24e20d27a9 build: bump discord-api-types to 0.37.114 2024-12-24 12:07:58 +00:00
Jiralite
8760fde9ff build: bump discord-api-types to 0.37.113 2024-12-22 21:58:29 +00:00
211 changed files with 1290 additions and 9325 deletions

2
.github/CODEOWNERS vendored
View File

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

View File

@@ -1,4 +1,4 @@
# https://docs.github.com/actions/using-workflows/caching-dependencies-to-speed-up-workflows#force-deleting-cache-entries # https://docs.github.com/en/actions/using-workflows/caching-dependencies-to-speed-up-workflows#force-deleting-cache-entries
name: Cleanup caches name: Cleanup caches
on: on:
pull_request: pull_request:

View File

@@ -103,15 +103,7 @@ jobs:
if: ${{ env.REF_TYPE == 'tag' && (!inputs.ref || inputs.ref == 'main') }} if: ${{ env.REF_TYPE == 'tag' && (!inputs.ref || inputs.ref == 'main') }}
env: env:
DATABASE_URL: ${{ secrets.DATABASE_URL }} 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 }} 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 uses: ./packages/actions/src/uploadDocumentation
with: with:
package: ${{ steps.extract-tag.outputs.package }} package: ${{ steps.extract-tag.outputs.package }}
@@ -121,15 +113,7 @@ jobs:
if: ${{ env.REF_TYPE == 'tag' && inputs.ref && inputs.ref != 'main' }} if: ${{ env.REF_TYPE == 'tag' && inputs.ref && inputs.ref != 'main' }}
env: env:
DATABASE_URL: ${{ secrets.DATABASE_URL }} 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 }} 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 uses: ./main/packages/actions/src/uploadDocumentation
with: with:
package: ${{ steps.extract-tag.outputs.package }} package: ${{ steps.extract-tag.outputs.package }}
@@ -139,10 +123,6 @@ jobs:
if: ${{ env.REF_TYPE == 'tag' && (!inputs.ref || inputs.ref == 'main') }} if: ${{ env.REF_TYPE == 'tag' && (!inputs.ref || inputs.ref == 'main') }}
env: env:
BLOB_READ_WRITE_TOKEN: ${{ secrets.BLOB_READ_WRITE_TOKEN }} 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 uses: ./packages/actions/src/uploadSplitDocumentation
with: with:
package: ${{ steps.extract-tag.outputs.package }} package: ${{ steps.extract-tag.outputs.package }}
@@ -152,10 +132,6 @@ jobs:
if: ${{ env.REF_TYPE == 'tag' && inputs.ref && inputs.ref != 'main' }} if: ${{ env.REF_TYPE == 'tag' && inputs.ref && inputs.ref != 'main' }}
env: env:
BLOB_READ_WRITE_TOKEN: ${{ secrets.BLOB_READ_WRITE_TOKEN }} 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 uses: ./main/packages/actions/src/uploadSplitDocumentation
with: with:
package: ${{ steps.extract-tag.outputs.package }} package: ${{ steps.extract-tag.outputs.package }}
@@ -179,50 +155,26 @@ jobs:
if: ${{ env.REF_TYPE == 'branch' && (!inputs.ref || inputs.ref == 'main') }} if: ${{ env.REF_TYPE == 'branch' && (!inputs.ref || inputs.ref == 'main') }}
env: env:
DATABASE_URL: ${{ secrets.DATABASE_URL }} 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 }} 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 uses: ./packages/actions/src/uploadDocumentation
- name: Upload documentation to database - name: Upload documentation to database
if: ${{ env.REF_TYPE == 'branch' && inputs.ref && inputs.ref != 'main' }} if: ${{ env.REF_TYPE == 'branch' && inputs.ref && inputs.ref != 'main' }}
env: env:
DATABASE_URL: ${{ secrets.DATABASE_URL }} 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 }} 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 uses: ./main/packages/actions/src/uploadDocumentation
- name: Upload split documentation to blob storage - name: Upload split documentation to blob storage
if: ${{ env.REF_TYPE == 'branch' && (!inputs.ref || inputs.ref == 'main') }} if: ${{ env.REF_TYPE == 'branch' && (!inputs.ref || inputs.ref == 'main') }}
env: env:
BLOB_READ_WRITE_TOKEN: ${{ secrets.BLOB_READ_WRITE_TOKEN }} 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 uses: ./packages/actions/src/uploadSplitDocumentation
- name: Upload split documentation to blob storage - name: Upload split documentation to blob storage
if: ${{ env.REF_TYPE == 'branch' && inputs.ref && inputs.ref != 'main' }} if: ${{ env.REF_TYPE == 'branch' && inputs.ref && inputs.ref != 'main' }}
env: env:
BLOB_READ_WRITE_TOKEN: ${{ secrets.BLOB_READ_WRITE_TOKEN }} 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 uses: ./main/packages/actions/src/uploadSplitDocumentation
- name: Move docs to correct directory - name: Move docs to correct directory

View File

@@ -9,9 +9,7 @@
<a href="https://www.npmjs.com/package/discord.js"><img src="https://img.shields.io/npm/v/discord.js.svg?maxAge=3600" alt="npm version" /></a> <a href="https://www.npmjs.com/package/discord.js"><img src="https://img.shields.io/npm/v/discord.js.svg?maxAge=3600" alt="npm version" /></a>
<a href="https://www.npmjs.com/package/discord.js"><img src="https://img.shields.io/npm/dt/discord.js.svg?maxAge=3600" alt="npm downloads" /></a> <a href="https://www.npmjs.com/package/discord.js"><img src="https://img.shields.io/npm/dt/discord.js.svg?maxAge=3600" alt="npm downloads" /></a>
<a href="https://github.com/discordjs/discord.js/actions"><img src="https://github.com/discordjs/discord.js/actions/workflows/test.yml/badge.svg" alt="Tests status" /></a> <a href="https://github.com/discordjs/discord.js/actions"><img src="https://github.com/discordjs/discord.js/actions/workflows/test.yml/badge.svg" alt="Tests status" /></a>
<a href="https://github.com/discordjs/discord.js/commits/main"><img src="https://img.shields.io/github/last-commit/discordjs/discord.js.svg?logo=github&logoColor=ffffff" alt="Last commit." /></a> <a href="https://codecov.io/gh/discordjs/discord.js" ><img src="https://codecov.io/gh/discordjs/discord.js/branch/main/graph/badge.svg?precision=2" alt="Code coverage" /></a>
<a href="https://github.com/discordjs/discord.js/graphs/contributors"><img src="https://img.shields.io/github/contributors/discordjs/discord.js.svg?maxAge=3600&logo=github&logoColor=fff&color=00c7be" alt="contributors" /></a>
<a href="https://codecov.io/gh/discordjs/discord.js"><img src="https://codecov.io/gh/discordjs/discord.js/branch/main/graph/badge.svg?precision=2" alt="Code coverage" /></a>
</p> </p>
<p> <p>
<a href="https://vercel.com/?utm_source=discordjs&utm_campaign=oss"><img src="https://raw.githubusercontent.com/discordjs/discord.js/main/.github/powered-by-vercel.svg" alt="Vercel" /></a> <a href="https://vercel.com/?utm_source=discordjs&utm_campaign=oss"><img src="https://raw.githubusercontent.com/discordjs/discord.js/main/.github/powered-by-vercel.svg" alt="Vercel" /></a>

View File

@@ -18,9 +18,8 @@ export async function Badges({ node }: { readonly node: any }) {
const isAbstract = node.isAbstract; const isAbstract = node.isAbstract;
const isReadonly = node.isReadonly; const isReadonly = node.isReadonly;
const isOptional = node.isOptional; const isOptional = node.isOptional;
const isExternal = node.isExternal;
const isAny = isDeprecated || isProtected || isStatic || isAbstract || isReadonly || isOptional || isExternal; const isAny = isDeprecated || isProtected || isStatic || isAbstract || isReadonly || isOptional;
return isAny ? ( return isAny ? (
<div className="mb-1 flex gap-3"> <div className="mb-1 flex gap-3">
@@ -34,7 +33,6 @@ export async function Badges({ node }: { readonly node: any }) {
{isAbstract ? <Badge className="bg-cyan-500/20 text-cyan-500">abstract</Badge> : null} {isAbstract ? <Badge className="bg-cyan-500/20 text-cyan-500">abstract</Badge> : null}
{isReadonly ? <Badge className="bg-purple-500/20 text-purple-500">readonly</Badge> : null} {isReadonly ? <Badge className="bg-purple-500/20 text-purple-500">readonly</Badge> : null}
{isOptional ? <Badge className="bg-cyan-500/20 text-cyan-500">optional</Badge> : null} {isOptional ? <Badge className="bg-cyan-500/20 text-cyan-500">optional</Badge> : null}
{isExternal ? <Badge className="bg-purple-500/20 text-purple-500">external</Badge> : null}
</div> </div>
) : null; ) : null;
} }

View File

@@ -29,7 +29,6 @@ export async function ParameterNode({
{description ? <Badges node={parameter} /> : null} {description ? <Badges node={parameter} /> : null}
{parameter.name} {parameter.name}
{parameter.isOptional ? '?' : ''}: <ExcerptNode node={parameter.typeExcerpt} version={version} /> {parameter.isOptional ? '?' : ''}: <ExcerptNode node={parameter.typeExcerpt} version={version} />
{parameter.defaultValue ? ` = ${parameter.defaultValue}` : ''}
</span> </span>
{description && parameter.description?.length ? ( {description && parameter.description?.length ? (
<div className="mt-4 pl-4"> <div className="mt-4 pl-4">

View File

@@ -51,13 +51,7 @@ export async function PropertyNode({
<LinkIcon aria-hidden size={16} /> <LinkIcon aria-hidden size={16} />
</Link> </Link>
{property.displayName} {property.displayName}
{property.isOptional ? '?' : ''} : <ExcerptNode node={property.typeExcerpt} version={version} />{' '} {property.isOptional ? '?' : ''} : <ExcerptNode node={property.typeExcerpt} version={version} />
{property.summary?.defaultValueBlock.length
? `= ${property.summary.defaultValueBlock.reduce(
(acc: string, def: { kind: string; text: string }) => `${acc}${def.text}`,
'',
)}`
: ''}
</span> </span>
</h3> </h3>

View File

@@ -20,7 +20,7 @@ export async function fetchDependencies({
return Object.entries<string>(parsedDependencies) return Object.entries<string>(parsedDependencies)
.filter(([key]) => key.startsWith('@discordjs/') && !key.includes('api-extractor')) .filter(([key]) => key.startsWith('@discordjs/') && !key.includes('api-extractor'))
.map(([key, value]) => `${key.replace('@discordjs/', '').replaceAll('.', '-')}-${sanitizeVersion(value)}`); .map(([key, value]) => `${key.replace('@discordjs/', '').replaceAll('.', '-')}-${value.replaceAll('.', '-')}`);
} catch { } catch {
return []; return [];
} }
@@ -36,12 +36,8 @@ export async function fetchDependencies({
return Object.entries<string>(parsedDependencies) return Object.entries<string>(parsedDependencies)
.filter(([key]) => key.startsWith('@discordjs/') && !key.includes('api-extractor')) .filter(([key]) => key.startsWith('@discordjs/') && !key.includes('api-extractor'))
.map(([key, value]) => `${key.replace('@discordjs/', '').replaceAll('.', '-')}-${sanitizeVersion(value)}`); .map(([key, value]) => `${key.replace('@discordjs/', '').replaceAll('.', '-')}-${value.replaceAll('.', '-')}`);
} catch { } catch {
return []; return [];
} }
} }
function sanitizeVersion(version: string) {
return version.replaceAll('.', '-').replace(/^[\^~]/, '');
}

View File

@@ -6,19 +6,19 @@
"private": true, "private": true,
"scripts": { "scripts": {
"build": "turbo run build --concurrency=4", "build": "turbo run build --concurrency=4",
"build:affected": "turbo run build --filter=...[origin/v14] --concurrency=4", "build:affected": "turbo run build --filter=...[origin/main] --concurrency=4",
"build:apps": "turbo run build:local --filter=...{apps/*} --concurrency=4", "build:apps": "turbo run build:local --filter=...{apps/*} --concurrency=4",
"build:apps:affected": "turbo run build:local --filter=...{apps/*}[origin/v14] --concurrency=4", "build:apps:affected": "turbo run build:local --filter=...{apps/*}[origin/main] --concurrency=4",
"test": "turbo run test --concurrency=4", "test": "turbo run test --concurrency=4",
"test:affected": "turbo run test --filter=...[origin/v14] --concurrency=4", "test:affected": "turbo run test --filter=...[origin/main] --concurrency=4",
"lint": "turbo run lint --concurrency=4", "lint": "turbo run lint --concurrency=4",
"lint:affected": "turbo run lint --filter=...[origin/v14] --concurrency=4", "lint:affected": "turbo run lint --filter=...[origin/main] --concurrency=4",
"format": "turbo run format --concurrency=4", "format": "turbo run format --concurrency=4",
"format:affected": "turbo run format --filter=...[origin/v14] --concurrency=4", "format:affected": "turbo run format --filter=...[origin/main] --concurrency=4",
"fmt": "turbo run format --concurrency=4", "fmt": "turbo run format --concurrency=4",
"fmt:affected": "turbo run format --filter=...[origin/v14] --concurrency=4", "fmt:affected": "turbo run format --filter=...[origin/main] --concurrency=4",
"docs": "turbo run docs --concurrency=4", "docs": "turbo run docs --concurrency=4",
"docs:affected": "turbo run docs --filter=...[origin/v14] --concurrency=4", "docs:affected": "turbo run docs --filter=...[origin/main] --concurrency=4",
"prepare": "is-ci || husky", "prepare": "is-ci || husky",
"update": "pnpm --recursive update --interactive", "update": "pnpm --recursive update --interactive",
"update:latest": "pnpm --recursive update --interactive --latest", "update:latest": "pnpm --recursive update --interactive --latest",

View File

@@ -41,32 +41,28 @@
"homepage": "https://discord.js.org", "homepage": "https://discord.js.org",
"funding": "https://github.com/discordjs/discord.js?sponsor", "funding": "https://github.com/discordjs/discord.js?sponsor",
"dependencies": { "dependencies": {
"@actions/core": "^1.11.1", "@actions/core": "^1.10.1",
"@actions/glob": "^0.5.0", "@actions/glob": "^0.5.0",
"@aws-sdk/client-s3": "^3.787.0",
"@discordjs/scripts": "workspace:^", "@discordjs/scripts": "workspace:^",
"@vercel/blob": "^0.27.3", "@vercel/blob": "^0.23.4",
"@vercel/postgres": "^0.9.0", "@vercel/postgres": "^0.9.0",
"cloudflare": "^4.2.0",
"meilisearch": "^0.38.0", "meilisearch": "^0.38.0",
"p-limit": "^6.2.0", "p-limit": "^6.1.0",
"p-queue": "^8.1.0", "tslib": "^2.6.3",
"tslib": "^2.8.1", "undici": "6.19.8"
"undici": "7.8.0"
}, },
"devDependencies": { "devDependencies": {
"@types/node": "^22.14.0", "@types/node": "^18.19.45",
"@vitest/coverage-v8": "^3.1.1", "@vitest/coverage-v8": "^2.0.5",
"cross-env": "^7.0.3", "cross-env": "^7.0.3",
"eslint": "^8.57.0", "eslint": "^8.57.0",
"eslint-config-neon": "^0.1.62", "eslint-config-neon": "^0.1.62",
"eslint-formatter-pretty": "^6.0.1", "eslint-formatter-pretty": "^6.0.1",
"prettier": "^3.5.3", "prettier": "^3.3.3",
"terser": "^5.37.0", "tsup": "^8.2.4",
"tsup": "^8.4.0", "turbo": "^2.0.14",
"turbo": "^2.5.0", "typescript": "~5.5.4",
"typescript": "~5.8.3", "vitest": "^2.0.5"
"vitest": "^3.1.1"
}, },
"engines": { "engines": {
"node": ">=18" "node": ">=18"

View File

@@ -9,7 +9,7 @@ runs:
with: with:
swap-size-gb: 10 swap-size-gb: 10
- uses: pnpm/action-setup@v4.1.0 - uses: pnpm/action-setup@v4.0.0
name: Install pnpm name: Install pnpm
with: with:
run_install: false run_install: false

View File

@@ -1,26 +1,13 @@
/* eslint-disable @typescript-eslint/no-loop-func */
import { readFile } from 'node:fs/promises'; import { readFile } from 'node:fs/promises';
import process from 'node:process'; import process from 'node:process';
import { getInput, setFailed } from '@actions/core'; import { getInput, setFailed } from '@actions/core';
import { create } from '@actions/glob'; import { create } from '@actions/glob';
import { PutObjectCommand, S3Client } from '@aws-sdk/client-s3';
import { put } from '@vercel/blob'; import { put } from '@vercel/blob';
import { createPool } from '@vercel/postgres'; import { createPool } from '@vercel/postgres';
import Cloudflare from 'cloudflare';
import pLimit from 'p-limit'; import pLimit from 'p-limit';
if ( if (!process.env.DATABASE_URL) {
!process.env.DATABASE_URL || setFailed('DATABASE_URL is not set');
!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') || '*'; const pkg = getInput('package') || '*';
@@ -30,21 +17,6 @@ const pool = createPool({
connectionString: process.env.DATABASE_URL, 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 limit = pLimit(10);
const promises = []; const promises = [];
@@ -54,14 +26,12 @@ for await (const file of globber.globGenerator()) {
const data = await readFile(file, 'utf8'); const data = await readFile(file, 'utf8');
try { try {
promises.push( promises.push(
// eslint-disable-next-line @typescript-eslint/no-loop-func
limit(async () => { limit(async () => {
console.log(`Uploading ${file} with ${version}...`); console.log(`Uploading ${file} with ${version}...`);
const json = JSON.parse(data); const json = JSON.parse(data);
const name = json.name ?? json.n; 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', access: 'public',
addRandomSuffix: false, addRandomSuffix: false,
}); });
@@ -69,19 +39,6 @@ for await (const file of globber.globGenerator()) {
'@discordjs/', '@discordjs/',
'', '',
)}, ${version}, ${url}) on conflict (name, version) do update set url = EXCLUDED.url`; )}, ${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) { } catch (error) {

View File

@@ -1,82 +1,32 @@
/* eslint-disable @typescript-eslint/no-loop-func */
import { readFile } from 'node:fs/promises'; import { readFile } from 'node:fs/promises';
import { basename, dirname, relative, sep } from 'node:path'; import { basename, dirname, relative, sep } from 'node:path';
import process from 'node:process'; import { cwd } from 'node:process';
import { setTimeout as sleep } from 'node:timers/promises'; import { getInput } from '@actions/core';
import { setFailed, getInput } from '@actions/core';
import { create } from '@actions/glob'; import { create } from '@actions/glob';
import { S3Client, PutObjectCommand } from '@aws-sdk/client-s3';
import { put } from '@vercel/blob'; import { put } from '@vercel/blob';
import PQueue from 'p-queue'; import pLimit from 'p-limit';
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 pkg = getInput('package') || '*';
const version = getInput('version') || 'main'; const version = getInput('version') || 'main';
const queue = new PQueue({ concurrency: 10, interval: 60_000, intervalCap: 1_000 }); const limit = pLimit(10);
const promises = []; 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`); const globber = await create(`packages/${pkg}/docs/${pkg}/split/*.api.json`);
console.log('Glob: ', await globber.glob()); console.log('Glob: ', await globber.glob());
for await (const file of globber.globGenerator()) { for await (const file of globber.globGenerator()) {
const data = await readFile(file, 'utf8'); const data = await readFile(file, 'utf8');
const pkgName = dirname(relative(process.cwd(), file)).split(sep)[1]; const pkgName = dirname(relative(cwd(), file)).split(sep)[1];
try { try {
promises.push( promises.push(
queue.add(async () => { // eslint-disable-next-line @typescript-eslint/no-loop-func
limit(async () => {
console.log(`Uploading ${file} with ${version} from ${pkgName}...`); console.log(`Uploading ${file} with ${version} from ${pkgName}...`);
const name = basename(file).replace('main.', ''); const name = basename(file).replace('main.', '');
async function upload(retries = 0) { await put(`rewrite/${pkgName}/${version}.${name}`, data, {
try { access: 'public',
await put(`rewrite/${pkgName}/${version}.${name}`, data, { addRandomSuffix: false,
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) { } catch (error) {
@@ -86,9 +36,6 @@ for await (const file of globber.globGenerator()) {
try { try {
await Promise.all(promises); await Promise.all(promises);
if (failedUploads.length) {
setFailed(`Failed to upload ${failedUploads.length} files: ${failedUploads.join(', ')}`);
}
} catch (error) { } catch (error) {
console.log(error); console.log(error);
} }

View File

@@ -1,10 +0,0 @@
{
"$schema": "https://json.schemastore.org/tsconfig.json",
"extends": "./tsconfig.json",
"compilerOptions": {
"noEmit": true,
"skipLibCheck": true
},
"include": ["__tests__/**/*.ts"],
"exclude": ["node_modules"]
}

View File

@@ -14,7 +14,6 @@ import type { IExcerptTokenRange } from './Excerpt.js';
* @public * @public
*/ */
export interface IApiParameterOptions { export interface IApiParameterOptions {
defaultValue: string | undefined;
isOptional: boolean; isOptional: boolean;
isRest: boolean; isRest: boolean;
parameterName: string; parameterName: string;
@@ -125,7 +124,6 @@ export function ApiParameterListMixin<TBaseClass extends IApiItemConstructor>(
isOptional: Boolean(parameterOptions.isOptional), isOptional: Boolean(parameterOptions.isOptional),
isRest: Boolean(parameterOptions.isRest), isRest: Boolean(parameterOptions.isRest),
parent: this, parent: this,
defaultValue: parameterOptions.defaultValue,
}); });
this[_parameters].push(parameter); this[_parameters].push(parameter);
@@ -173,7 +171,6 @@ export function ApiParameterListMixin<TBaseClass extends IApiItemConstructor>(
parameterTypeTokenRange: parameter.parameterTypeExcerpt.tokenRange, parameterTypeTokenRange: parameter.parameterTypeExcerpt.tokenRange,
isOptional: parameter.isOptional, isOptional: parameter.isOptional,
isRest: parameter.isRest, isRest: parameter.isRest,
defaultValue: parameter.defaultValue,
}); });
} }

View File

@@ -41,7 +41,6 @@ const MinifyJSONMapping = {
constraintTokenRange: 'ctr', constraintTokenRange: 'ctr',
dependencies: 'dp', dependencies: 'dp',
defaultTypeTokenRange: 'dtr', defaultTypeTokenRange: 'dtr',
defaultValue: 'dv',
docComment: 'd', docComment: 'd',
endIndex: 'en', endIndex: 'en',
excerptTokens: 'ex', excerptTokens: 'ex',

View File

@@ -262,7 +262,6 @@ function mapParam(
startIndex: 1 + index + paramTokens.slice(0, index).reduce((akk, num) => akk + num, 0), startIndex: 1 + index + paramTokens.slice(0, index).reduce((akk, num) => akk + num, 0),
endIndex: 1 + index + paramTokens.slice(0, index + 1).reduce((akk, num) => akk + num, 0), endIndex: 1 + index + paramTokens.slice(0, index + 1).reduce((akk, num) => akk + num, 0),
}, },
defaultValue: param.default,
}; };
} }

View File

@@ -12,7 +12,6 @@ import type { Excerpt } from '../mixins/Excerpt.js';
* @public * @public
*/ */
export interface IParameterOptions { export interface IParameterOptions {
defaultValue: string | undefined;
isOptional: boolean; isOptional: boolean;
isRest: boolean; isRest: boolean;
name: string; name: string;
@@ -57,11 +56,6 @@ export class Parameter {
*/ */
public isRest: boolean; public isRest: boolean;
/**
* The default value for this parameter if optional
*/
public defaultValue: string | undefined;
private readonly _parent: ApiParameterListMixin; private readonly _parent: ApiParameterListMixin;
public constructor(options: IParameterOptions) { public constructor(options: IParameterOptions) {
@@ -70,7 +64,6 @@ export class Parameter {
this.isOptional = options.isOptional; this.isOptional = options.isOptional;
this.isRest = options.isRest; this.isRest = options.isRest;
this._parent = options.parent; this._parent = options.parent;
this.defaultValue = options.defaultValue;
} }
/** /**

View File

@@ -114,7 +114,7 @@ interface DocgenEventJson {
} }
interface DocgenParamJson { interface DocgenParamJson {
default?: boolean | number | string; default?: string;
description: string; description: string;
name: string; name: string;
nullable?: boolean; nullable?: boolean;
@@ -155,7 +155,7 @@ interface DocgenMethodJson {
interface DocgenPropertyJson { interface DocgenPropertyJson {
abstract?: boolean; abstract?: boolean;
access?: DocgenAccess; access?: DocgenAccess;
default?: boolean | number | string; default?: string;
deprecated?: DocgenDeprecated; deprecated?: DocgenDeprecated;
description: string; description: string;
meta: DocgenMetaJson; meta: DocgenMetaJson;
@@ -843,7 +843,6 @@ export class ApiModelGenerator {
const parameters: IApiParameterOptions[] = this._captureParameters( const parameters: IApiParameterOptions[] = this._captureParameters(
nodesToCapture, nodesToCapture,
functionDeclaration.parameters, functionDeclaration.parameters,
jsDoc?.params,
); );
const excerptTokens: IExcerptToken[] = this._buildExcerptTokens(astDeclaration, nodesToCapture); const excerptTokens: IExcerptToken[] = this._buildExcerptTokens(astDeclaration, nodesToCapture);
@@ -1044,7 +1043,6 @@ export class ApiModelGenerator {
const parameters: IApiParameterOptions[] = this._captureParameters( const parameters: IApiParameterOptions[] = this._captureParameters(
nodesToCapture, nodesToCapture,
methodDeclaration.parameters, methodDeclaration.parameters,
jsDoc?.params,
); );
const excerptTokens: IExcerptToken[] = this._buildExcerptTokens(astDeclaration, nodesToCapture); const excerptTokens: IExcerptToken[] = this._buildExcerptTokens(astDeclaration, nodesToCapture);
@@ -1139,11 +1137,7 @@ export class ApiModelGenerator {
methodSignature.typeParameters, methodSignature.typeParameters,
); );
const parameters: IApiParameterOptions[] = this._captureParameters( const parameters: IApiParameterOptions[] = this._captureParameters(nodesToCapture, methodSignature.parameters);
nodesToCapture,
methodSignature.parameters,
jsDoc?.params,
);
const excerptTokens: IExcerptToken[] = this._buildExcerptTokens(astDeclaration, nodesToCapture); const excerptTokens: IExcerptToken[] = this._buildExcerptTokens(astDeclaration, nodesToCapture);
const apiItemMetadata: ApiItemMetadata = this._collector.fetchApiItemMetadata(astDeclaration); const apiItemMetadata: ApiItemMetadata = this._collector.fetchApiItemMetadata(astDeclaration);
@@ -1270,7 +1264,7 @@ export class ApiModelGenerator {
const apiItemMetadata: ApiItemMetadata = this._collector.fetchApiItemMetadata(astDeclaration); const apiItemMetadata: ApiItemMetadata = this._collector.fetchApiItemMetadata(astDeclaration);
const docComment: tsdoc.DocComment | undefined = jsDoc const docComment: tsdoc.DocComment | undefined = jsDoc
? this._tsDocParser.parseString( ? this._tsDocParser.parseString(
`/**\n * ${this._fixLinkTags(jsDoc.description) ?? ''}${jsDoc.default ? ` (default: ${this._escapeSpecialChars(jsDoc.default)})` : ''}\n${ `/**\n * ${this._fixLinkTags(jsDoc.description) ?? ''}\n${
'see' in jsDoc ? jsDoc.see.map((see) => ` * @see ${see}\n`).join('') : '' 'see' in jsDoc ? jsDoc.see.map((see) => ` * @see ${see}\n`).join('') : ''
}${'readonly' in jsDoc && jsDoc.readonly ? ' * @readonly\n' : ''}${ }${'readonly' in jsDoc && jsDoc.readonly ? ' * @readonly\n' : ''}${
'deprecated' in jsDoc && jsDoc.deprecated 'deprecated' in jsDoc && jsDoc.deprecated
@@ -1348,7 +1342,7 @@ export class ApiModelGenerator {
const apiItemMetadata: ApiItemMetadata = this._collector.fetchApiItemMetadata(astDeclaration); const apiItemMetadata: ApiItemMetadata = this._collector.fetchApiItemMetadata(astDeclaration);
const docComment: tsdoc.DocComment | undefined = jsDoc const docComment: tsdoc.DocComment | undefined = jsDoc
? this._tsDocParser.parseString( ? this._tsDocParser.parseString(
`/**\n * ${this._fixLinkTags(jsDoc.description) ?? ''}${jsDoc.default ? `\n * @defaultValue ${this._escapeSpecialChars(jsDoc.default)}` : ''}\n${ `/**\n * ${this._fixLinkTags(jsDoc.description) ?? ''}\n${
'see' in jsDoc ? jsDoc.see.map((see) => ` * @see ${see}\n`).join('') : '' 'see' in jsDoc ? jsDoc.see.map((see) => ` * @see ${see}\n`).join('') : ''
}${'readonly' in jsDoc && jsDoc.readonly ? ' * @readonly\n' : ''}${ }${'readonly' in jsDoc && jsDoc.readonly ? ' * @readonly\n' : ''}${
'deprecated' in jsDoc && jsDoc.deprecated 'deprecated' in jsDoc && jsDoc.deprecated
@@ -1516,17 +1510,15 @@ export class ApiModelGenerator {
const excerptTokens: IExcerptToken[] = [ const excerptTokens: IExcerptToken[] = [
{ {
kind: ExcerptTokenKind.Content, kind: ExcerptTokenKind.Content,
text: `public on(eventName: '${name}', listener: (${ text: `on('${name}', (${
jsDoc.params?.length jsDoc.params?.length ? `${jsDoc.params[0]?.name}${jsDoc.params[0]?.nullable ? '?' : ''}: ` : ') => {})'
? `${jsDoc.params[0]?.name}${jsDoc.params[0]?.optional ? '?' : ''}: `
: ') => void): this;'
}`, }`,
}, },
]; ];
const parameters: IApiParameterOptions[] = []; const parameters: IApiParameterOptions[] = [];
for (let index = 0; index < (jsDoc.params?.length ?? 0) - 1; index++) { for (let index = 0; index < (jsDoc.params?.length ?? 0) - 1; index++) {
const parameter = jsDoc.params![index]!; const parameter = jsDoc.params![index]!;
const newTokens = this._mapVarType(parameter.type, parameter.nullable); const newTokens = this._mapVarType(parameter.type);
parameters.push({ parameters.push({
parameterName: parameter.name, parameterName: parameter.name,
parameterTypeTokenRange: { parameterTypeTokenRange: {
@@ -1535,7 +1527,6 @@ export class ApiModelGenerator {
}, },
isOptional: Boolean(parameter.optional), isOptional: Boolean(parameter.optional),
isRest: parameter.name.startsWith('...'), isRest: parameter.name.startsWith('...'),
defaultValue: parameter.default?.toString(),
}); });
excerptTokens.push(...newTokens); excerptTokens.push(...newTokens);
excerptTokens.push({ excerptTokens.push({
@@ -1546,7 +1537,7 @@ export class ApiModelGenerator {
if (jsDoc.params?.length) { if (jsDoc.params?.length) {
const parameter = jsDoc.params![jsDoc.params.length - 1]!; const parameter = jsDoc.params![jsDoc.params.length - 1]!;
const newTokens = this._mapVarType(parameter.type, parameter.nullable); const newTokens = this._mapVarType(parameter.type);
parameters.push({ parameters.push({
parameterName: parameter.name, parameterName: parameter.name,
parameterTypeTokenRange: { parameterTypeTokenRange: {
@@ -1555,12 +1546,11 @@ export class ApiModelGenerator {
}, },
isOptional: Boolean(parameter.optional), isOptional: Boolean(parameter.optional),
isRest: parameter.name.startsWith('...'), isRest: parameter.name.startsWith('...'),
defaultValue: parameter.default?.toString(),
}); });
excerptTokens.push(...newTokens); excerptTokens.push(...newTokens);
excerptTokens.push({ excerptTokens.push({
kind: ExcerptTokenKind.Content, kind: ExcerptTokenKind.Content,
text: `) => void): this;`, text: `) => {})`,
}); });
} }
@@ -1648,7 +1638,6 @@ export class ApiModelGenerator {
private _captureParameters( private _captureParameters(
nodesToCapture: IExcerptBuilderNodeToCapture[], nodesToCapture: IExcerptBuilderNodeToCapture[],
parameterNodes: ts.NodeArray<ts.ParameterDeclaration>, parameterNodes: ts.NodeArray<ts.ParameterDeclaration>,
jsDoc?: DocgenParamJson[] | undefined,
): IApiParameterOptions[] { ): IApiParameterOptions[] {
const parameters: IApiParameterOptions[] = []; const parameters: IApiParameterOptions[] = [];
for (const parameter of parameterNodes) { for (const parameter of parameterNodes) {
@@ -1659,9 +1648,6 @@ export class ApiModelGenerator {
parameterTypeTokenRange, parameterTypeTokenRange,
isOptional: this._collector.typeChecker.isOptionalParameter(parameter), isOptional: this._collector.typeChecker.isOptionalParameter(parameter),
isRest: Boolean(parameter.dotDotDotToken), isRest: Boolean(parameter.dotDotDotToken),
defaultValue:
parameter.initializer?.getText() ??
jsDoc?.find((param) => param.name === parameter.name.getText().trim())?.default?.toString(),
}); });
} }
@@ -1760,14 +1746,6 @@ export class ApiModelGenerator {
return sourceLocation; return sourceLocation;
} }
private _escapeSpecialChars(input: boolean | number | string) {
if (typeof input !== 'string') {
return input;
}
return input.replaceAll(/(?<char>[@{}])/g, '\\$<char>');
}
private _fixLinkTags(input?: string): string | undefined { private _fixLinkTags(input?: string): string | undefined {
return input return input
?.replaceAll(linkRegEx, (_match, _p1, _p2, _p3, _p4, _p5, _offset, _string, groups) => { ?.replaceAll(linkRegEx, (_match, _p1, _p2, _p3, _p4, _p5, _offset, _string, groups) => {
@@ -1787,7 +1765,7 @@ export class ApiModelGenerator {
.replaceAll('* ', '\n * * '); .replaceAll('* ', '\n * * ');
} }
private _mapVarType(typey: DocgenVarTypeJson, nullable?: boolean): IExcerptToken[] { private _mapVarType(typey: DocgenVarTypeJson): IExcerptToken[] {
const mapper = Array.isArray(typey) ? typey : (typey.types ?? []); const mapper = Array.isArray(typey) ? typey : (typey.types ?? []);
const lookup: { [K in ts.SyntaxKind]?: string } = { const lookup: { [K in ts.SyntaxKind]?: string } = {
[ts.SyntaxKind.ClassDeclaration]: 'class', [ts.SyntaxKind.ClassDeclaration]: 'class',
@@ -1830,22 +1808,7 @@ export class ApiModelGenerator {
{ kind: ExcerptTokenKind.Content, text: symbol ?? '' }, { kind: ExcerptTokenKind.Content, text: symbol ?? '' },
]; ];
}, []); }, []);
return index === 0 return index === 0 ? result : [{ kind: ExcerptTokenKind.Content, text: ' | ' }, ...result];
? mapper.length === 1 && (nullable || ('nullable' in typey && typey.nullable))
? [
...result,
{ kind: ExcerptTokenKind.Content, text: ' | ' },
{ kind: ExcerptTokenKind.Reference, text: 'null' },
]
: result
: index === mapper.length - 1 && (nullable || ('nullable' in typey && typey.nullable))
? [
{ kind: ExcerptTokenKind.Content, text: ' | ' },
...result,
{ kind: ExcerptTokenKind.Content, text: ' | ' },
{ kind: ExcerptTokenKind.Reference, text: 'null' },
]
: [{ kind: ExcerptTokenKind.Content, text: ' | ' }, ...result];
}) })
.filter((excerpt) => excerpt.text.length); .filter((excerpt) => excerpt.text.length);
} }
@@ -1860,7 +1823,7 @@ export class ApiModelGenerator {
isOptional: Boolean(prop.nullable), isOptional: Boolean(prop.nullable),
isReadonly: Boolean(prop.readonly), isReadonly: Boolean(prop.readonly),
docComment: this._tsDocParser.parseString( docComment: this._tsDocParser.parseString(
`/**\n * ${this._fixLinkTags(prop.description) ?? ''}\n${prop.default ? ` * @defaultValue ${this._escapeSpecialChars(prop.default)}\n` : ''}${ `/**\n * ${this._fixLinkTags(prop.description) ?? ''}\n${
prop.see?.map((see) => ` * @see ${see}\n`).join('') ?? '' prop.see?.map((see) => ` * @see ${see}\n`).join('') ?? ''
}${prop.readonly ? ' * @readonly\n' : ''} */`, }${prop.readonly ? ' * @readonly\n' : ''} */`,
).docComment, ).docComment,
@@ -1872,7 +1835,7 @@ export class ApiModelGenerator {
}${prop.name} :`, }${prop.name} :`,
}, },
...mappedVarType, ...mappedVarType,
{ kind: ExcerptTokenKind.Content, text: `${prop.default ? ` = ${prop.default}` : ''};` }, { kind: ExcerptTokenKind.Content, text: ';' },
], ],
propertyTypeTokenRange: { startIndex: 1, endIndex: 1 + mappedVarType.length }, propertyTypeTokenRange: { startIndex: 1, endIndex: 1 + mappedVarType.length },
releaseTag: prop.access === 'private' ? ReleaseTag.Internal : ReleaseTag.Public, releaseTag: prop.access === 'private' ? ReleaseTag.Internal : ReleaseTag.Public,
@@ -1895,7 +1858,6 @@ export class ApiModelGenerator {
startIndex: 1 + index + paramTokens.slice(0, index).reduce((akk, num) => akk + num, 0), startIndex: 1 + index + paramTokens.slice(0, index).reduce((akk, num) => akk + num, 0),
endIndex: 1 + index + paramTokens.slice(0, index + 1).reduce((akk, num) => akk + num, 0), endIndex: 1 + index + paramTokens.slice(0, index + 1).reduce((akk, num) => akk + num, 0),
}, },
defaultValue: param.default?.toString(),
}; };
} }
@@ -1920,7 +1882,7 @@ export class ApiModelGenerator {
excerptTokens.push(...newTokens); excerptTokens.push(...newTokens);
excerptTokens.push({ excerptTokens.push({
kind: ExcerptTokenKind.Content, kind: ExcerptTokenKind.Content,
text: `${method.params![index]!.default ? ` = ${method.params![index]!.default}` : ''}, ${method.params![index + 1]!.name}${ text: `, ${method.params![index + 1]!.name}${
method.params![index + 1]!.nullable || method.params![index + 1]!.optional ? '?' : '' method.params![index + 1]!.nullable || method.params![index + 1]!.optional ? '?' : ''
}: `, }: `,
}); });
@@ -1930,10 +1892,7 @@ export class ApiModelGenerator {
const newTokens = this._mapVarType(method.params[method.params.length - 1]!.type); const newTokens = this._mapVarType(method.params[method.params.length - 1]!.type);
paramTokens.push(newTokens.length); paramTokens.push(newTokens.length);
excerptTokens.push(...newTokens); excerptTokens.push(...newTokens);
excerptTokens.push({ excerptTokens.push({ kind: ExcerptTokenKind.Content, text: `): ` });
kind: ExcerptTokenKind.Content,
text: `${method.params![method.params.length - 1]!.default ? ` = ${method.params![method.params.length - 1]!.default}` : ''}): `,
});
} }
const returnTokens = this._mapVarType(method.returns?.[0] ?? []); const returnTokens = this._mapVarType(method.returns?.[0] ?? []);

View File

@@ -9,8 +9,7 @@
<a href="https://www.npmjs.com/package/@discordjs/brokers"><img src="https://img.shields.io/npm/v/@discordjs/brokers.svg?maxAge=3600" alt="npm version" /></a> <a href="https://www.npmjs.com/package/@discordjs/brokers"><img src="https://img.shields.io/npm/v/@discordjs/brokers.svg?maxAge=3600" alt="npm version" /></a>
<a href="https://www.npmjs.com/package/@discordjs/brokers"><img src="https://img.shields.io/npm/dt/@discordjs/brokers.svg?maxAge=3600" alt="npm downloads" /></a> <a href="https://www.npmjs.com/package/@discordjs/brokers"><img src="https://img.shields.io/npm/dt/@discordjs/brokers.svg?maxAge=3600" alt="npm downloads" /></a>
<a href="https://github.com/discordjs/discord.js/actions"><img src="https://github.com/discordjs/discord.js/actions/workflows/test.yml/badge.svg" alt="Build status" /></a> <a href="https://github.com/discordjs/discord.js/actions"><img src="https://github.com/discordjs/discord.js/actions/workflows/test.yml/badge.svg" alt="Build status" /></a>
<a href="https://github.com/discordjs/discord.js/commits/main/packages/brokers"><img alt="Last commit." src="https://img.shields.io/github/last-commit/discordjs/discord.js?logo=github&logoColor=ffffff&path=packages%2Fbrokers"></a> <a href="https://codecov.io/gh/discordjs/discord.js" ><img src="https://codecov.io/gh/discordjs/discord.js/branch/main/graph/badge.svg?precision=2&flag=brokers" alt="Code coverage" /></a>
<a href="https://codecov.io/gh/discordjs/discord.js"><img src="https://codecov.io/gh/discordjs/discord.js/branch/main/graph/badge.svg?precision=2&flag=brokers" alt="Code coverage" /></a>
</p> </p>
<p> <p>
<a href="https://vercel.com/?utm_source=discordjs&utm_campaign=oss"><img src="https://raw.githubusercontent.com/discordjs/discord.js/main/.github/powered-by-vercel.svg" alt="Vercel" /></a> <a href="https://vercel.com/?utm_source=discordjs&utm_campaign=oss"><img src="https://raw.githubusercontent.com/discordjs/discord.js/main/.github/powered-by-vercel.svg" alt="Vercel" /></a>
@@ -24,7 +23,7 @@
## Installation ## Installation
**Node.js 20 or newer is required.** **Node.js 18 or newer is required.**
```sh ```sh
npm install @discordjs/brokers npm install @discordjs/brokers

View File

@@ -30,10 +30,8 @@ body = """
{{ commit.message | upper_first }} ([{{ commit.id | truncate(length=7, end="") }}]({{ self::remote_url() }}/commit/{{ commit.id }}))\ {{ commit.message | upper_first }} ([{{ commit.id | truncate(length=7, end="") }}]({{ self::remote_url() }}/commit/{{ commit.id }}))\
{% if commit.github.username %} by @{{ commit.github.username }}{%- endif %}\ {% if commit.github.username %} by @{{ commit.github.username }}{%- endif %}\
{% if commit.breaking %}\ {% if commit.breaking %}\
{% for footer in commit.footers %}\ {% for breakingChange in commit.footers %}\
{% if footer.breaking %}\ \n{% raw %} {% endraw %}- **{{ breakingChange.token }}{{ breakingChange.separator }}** {{ breakingChange.value }}\
\n{% raw %} {% endraw %}- **{{ footer.token }}{{ footer.separator }}** {{ footer.value }}\
{% endif %}\
{% endfor %}\ {% endfor %}\
{% endif %}\ {% endif %}\
{% endfor %} {% endfor %}

View File

@@ -89,7 +89,7 @@
"vitest": "^2.0.5" "vitest": "^2.0.5"
}, },
"engines": { "engines": {
"node": ">=20" "node": ">=18"
}, },
"publishConfig": { "publishConfig": {
"access": "public", "access": "public",

View File

@@ -9,8 +9,7 @@
<a href="https://www.npmjs.com/package/@discordjs/builders"><img src="https://img.shields.io/npm/v/@discordjs/builders.svg?maxAge=3600" alt="npm version" /></a> <a href="https://www.npmjs.com/package/@discordjs/builders"><img src="https://img.shields.io/npm/v/@discordjs/builders.svg?maxAge=3600" alt="npm version" /></a>
<a href="https://www.npmjs.com/package/@discordjs/builders"><img src="https://img.shields.io/npm/dt/@discordjs/builders.svg?maxAge=3600" alt="npm downloads" /></a> <a href="https://www.npmjs.com/package/@discordjs/builders"><img src="https://img.shields.io/npm/dt/@discordjs/builders.svg?maxAge=3600" alt="npm downloads" /></a>
<a href="https://github.com/discordjs/discord.js/actions"><img src="https://github.com/discordjs/discord.js/actions/workflows/test.yml/badge.svg" alt="Build status" /></a> <a href="https://github.com/discordjs/discord.js/actions"><img src="https://github.com/discordjs/discord.js/actions/workflows/test.yml/badge.svg" alt="Build status" /></a>
<a href="https://github.com/discordjs/discord.js/commits/main/packages/builders"><img alt="Last commit." src="https://img.shields.io/github/last-commit/discordjs/discord.js?logo=github&logoColor=ffffff&path=packages%2Fbuilders"></a> <a href="https://codecov.io/gh/discordjs/discord.js" ><img src="https://codecov.io/gh/discordjs/discord.js/branch/main/graph/badge.svg?precision=2&flag=builders" alt="Code coverage" /></a>
<a href="https://codecov.io/gh/discordjs/discord.js"><img src="https://codecov.io/gh/discordjs/discord.js/branch/main/graph/badge.svg?precision=2&flag=builders" alt="Code coverage" /></a>
</p> </p>
<p> <p>
<a href="https://vercel.com/?utm_source=discordjs&utm_campaign=oss"><img src="https://raw.githubusercontent.com/discordjs/discord.js/main/.github/powered-by-vercel.svg" alt="Vercel" /></a> <a href="https://vercel.com/?utm_source=discordjs&utm_campaign=oss"><img src="https://raw.githubusercontent.com/discordjs/discord.js/main/.github/powered-by-vercel.svg" alt="Vercel" /></a>
@@ -24,7 +23,7 @@
## Installation ## Installation
**Node.js 18 or newer is required.** **Node.js 16.11.0 or newer is required.**
```sh ```sh
npm install @discordjs/builders npm install @discordjs/builders

View File

@@ -166,7 +166,7 @@ describe('Context Menu Commands', () => {
}); });
describe('integration types', () => { describe('integration types', () => {
test('GIVEN a builder with valid integration types THEN does not throw an error', () => { test('GIVEN a builder with valid integraton types THEN does not throw an error', () => {
expect(() => expect(() =>
getBuilder().setIntegrationTypes([ getBuilder().setIntegrationTypes([
ApplicationIntegrationType.GuildInstall, ApplicationIntegrationType.GuildInstall,

View File

@@ -565,7 +565,7 @@ describe('Slash Commands', () => {
}); });
describe('integration types', () => { describe('integration types', () => {
test('GIVEN a builder with valid integration types THEN does not throw an error', () => { test('GIVEN a builder with valid integraton types THEN does not throw an error', () => {
expect(() => expect(() =>
getBuilder().setIntegrationTypes([ getBuilder().setIntegrationTypes([
ApplicationIntegrationType.GuildInstall, ApplicationIntegrationType.GuildInstall,

View File

@@ -30,10 +30,8 @@ body = """
{{ commit.message | upper_first }} ([{{ commit.id | truncate(length=7, end="") }}]({{ self::remote_url() }}/commit/{{ commit.id }}))\ {{ commit.message | upper_first }} ([{{ commit.id | truncate(length=7, end="") }}]({{ self::remote_url() }}/commit/{{ commit.id }}))\
{% if commit.github.username %} by @{{ commit.github.username }}{%- endif %}\ {% if commit.github.username %} by @{{ commit.github.username }}{%- endif %}\
{% if commit.breaking %}\ {% if commit.breaking %}\
{% for footer in commit.footers %}\ {% for breakingChange in commit.footers %}\
{% if footer.breaking %}\ \n{% raw %} {% endraw %}- **{{ breakingChange.token }}{{ breakingChange.separator }}** {{ breakingChange.value }}\
\n{% raw %} {% endraw %}- **{{ footer.token }}{{ footer.separator }}** {{ footer.value }}\
{% endif %}\
{% endfor %}\ {% endfor %}\
{% endif %}\ {% endif %}\
{% endfor %} {% endfor %}

View File

@@ -1,7 +1,7 @@
{ {
"$schema": "https://json.schemastore.org/package.json", "$schema": "https://json.schemastore.org/package.json",
"name": "@discordjs/builders", "name": "@discordjs/builders",
"version": "1.9.0", "version": "1.10.0",
"description": "A set of builders that you can use when creating your bot", "description": "A set of builders that you can use when creating your bot",
"scripts": { "scripts": {
"test": "vitest run", "test": "vitest run",
@@ -68,7 +68,7 @@
"@discordjs/formatters": "workspace:^", "@discordjs/formatters": "workspace:^",
"@discordjs/util": "workspace:^", "@discordjs/util": "workspace:^",
"@sapphire/shapeshift": "^4.0.0", "@sapphire/shapeshift": "^4.0.0",
"discord-api-types": "^0.37.119", "discord-api-types": "^0.37.114",
"fast-deep-equal": "^3.1.3", "fast-deep-equal": "^3.1.3",
"ts-mixer": "^6.0.4", "ts-mixer": "^6.0.4",
"tslib": "^2.6.3" "tslib": "^2.6.3"
@@ -91,7 +91,7 @@
"vitest": "^2.0.5" "vitest": "^2.0.5"
}, },
"engines": { "engines": {
"node": ">=18" "node": ">=16.11.0"
}, },
"publishConfig": { "publishConfig": {
"access": "public", "access": "public",

View File

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

View File

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

View File

@@ -9,8 +9,7 @@
<a href="https://www.npmjs.com/package/@discordjs/collection"><img src="https://img.shields.io/npm/v/@discordjs/collection.svg?maxAge=3600" alt="npm version" /></a> <a href="https://www.npmjs.com/package/@discordjs/collection"><img src="https://img.shields.io/npm/v/@discordjs/collection.svg?maxAge=3600" alt="npm version" /></a>
<a href="https://www.npmjs.com/package/@discordjs/collection"><img src="https://img.shields.io/npm/dt/@discordjs/collection.svg?maxAge=3600" alt="npm downloads" /></a> <a href="https://www.npmjs.com/package/@discordjs/collection"><img src="https://img.shields.io/npm/dt/@discordjs/collection.svg?maxAge=3600" alt="npm downloads" /></a>
<a href="https://github.com/discordjs/discord.js/actions"><img src="https://github.com/discordjs/discord.js/actions/workflows/test.yml/badge.svg" alt="Build status" /></a> <a href="https://github.com/discordjs/discord.js/actions"><img src="https://github.com/discordjs/discord.js/actions/workflows/test.yml/badge.svg" alt="Build status" /></a>
<a href="https://github.com/discordjs/discord.js/commits/main/packages/collection"><img alt="Last commit." src="https://img.shields.io/github/last-commit/discordjs/discord.js?logo=github&logoColor=ffffff&path=packages%2Fcollection"></a> <a href="https://codecov.io/gh/discordjs/discord.js" ><img src="https://codecov.io/gh/discordjs/discord.js/branch/main/graph/badge.svg?precision=2&flag=collection" alt="Code coverage" /></a>
<a href="https://codecov.io/gh/discordjs/discord.js"><img src="https://codecov.io/gh/discordjs/discord.js/branch/main/graph/badge.svg?precision=2&flag=collection" alt="Code coverage" /></a>
</p> </p>
<p> <p>
<a href="https://vercel.com/?utm_source=discordjs&utm_campaign=oss"><img src="https://raw.githubusercontent.com/discordjs/discord.js/main/.github/powered-by-vercel.svg" alt="Vercel" /></a> <a href="https://vercel.com/?utm_source=discordjs&utm_campaign=oss"><img src="https://raw.githubusercontent.com/discordjs/discord.js/main/.github/powered-by-vercel.svg" alt="Vercel" /></a>

View File

@@ -30,10 +30,8 @@ body = """
{{ commit.message | upper_first }} ([{{ commit.id | truncate(length=7, end="") }}]({{ self::remote_url() }}/commit/{{ commit.id }}))\ {{ commit.message | upper_first }} ([{{ commit.id | truncate(length=7, end="") }}]({{ self::remote_url() }}/commit/{{ commit.id }}))\
{% if commit.github.username %} by @{{ commit.github.username }}{%- endif %}\ {% if commit.github.username %} by @{{ commit.github.username }}{%- endif %}\
{% if commit.breaking %}\ {% if commit.breaking %}\
{% for footer in commit.footers %}\ {% for breakingChange in commit.footers %}\
{% if footer.breaking %}\ \n{% raw %} {% endraw %}- **{{ breakingChange.token }}{{ breakingChange.separator }}** {{ breakingChange.value }}\
\n{% raw %} {% endraw %}- **{{ footer.token }}{{ footer.separator }}** {{ footer.value }}\
{% endif %}\
{% endfor %}\ {% endfor %}\
{% endif %}\ {% endif %}\
{% endfor %} {% endfor %}

View File

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

View File

@@ -9,8 +9,7 @@
<a href="https://www.npmjs.com/package/@discordjs/core"><img src="https://img.shields.io/npm/v/@discordjs/core.svg?maxAge=3600" alt="npm version" /></a> <a href="https://www.npmjs.com/package/@discordjs/core"><img src="https://img.shields.io/npm/v/@discordjs/core.svg?maxAge=3600" alt="npm version" /></a>
<a href="https://www.npmjs.com/package/@discordjs/core"><img src="https://img.shields.io/npm/dt/@discordjs/core.svg?maxAge=3600" alt="npm downloads" /></a> <a href="https://www.npmjs.com/package/@discordjs/core"><img src="https://img.shields.io/npm/dt/@discordjs/core.svg?maxAge=3600" alt="npm downloads" /></a>
<a href="https://github.com/discordjs/discord.js/actions"><img src="https://github.com/discordjs/discord.js/actions/workflows/test.yml/badge.svg" alt="Build status" /></a> <a href="https://github.com/discordjs/discord.js/actions"><img src="https://github.com/discordjs/discord.js/actions/workflows/test.yml/badge.svg" alt="Build status" /></a>
<a href="https://github.com/discordjs/discord.js/commits/main/packages/core"><img alt="Last commit." src="https://img.shields.io/github/last-commit/discordjs/discord.js?logo=github&logoColor=ffffff&path=packages%2Fcore"></a> <a href="https://codecov.io/gh/discordjs/discord.js" ><img src="https://codecov.io/gh/discordjs/discord.js/branch/main/graph/badge.svg?precision=2&flag=core" alt="Code coverage" /></a>
<a href="https://codecov.io/gh/discordjs/discord.js"><img src="https://codecov.io/gh/discordjs/discord.js/branch/main/graph/badge.svg?precision=2&flag=core" alt="Code coverage" /></a>
</p> </p>
<p> <p>
<a href="https://vercel.com/?utm_source=discordjs&utm_campaign=oss"><img src="https://raw.githubusercontent.com/discordjs/discord.js/main/.github/powered-by-vercel.svg" alt="Vercel" /></a> <a href="https://vercel.com/?utm_source=discordjs&utm_campaign=oss"><img src="https://raw.githubusercontent.com/discordjs/discord.js/main/.github/powered-by-vercel.svg" alt="Vercel" /></a>
@@ -24,7 +23,7 @@
## Installation ## Installation
**Node.js 20 or newer is required.** **Node.js 18 or newer is required.**
```sh ```sh
npm install @discordjs/core npm install @discordjs/core

View File

@@ -1,6 +1,5 @@
{ {
"extends": "../../api-extractor.json", "extends": "../../api-extractor.json",
"bundledPackages": ["discord-api-types"],
"docModel": { "docModel": {
"projectFolderUrl": "https://github.com/discordjs/discord.js/tree/main/packages/core" "projectFolderUrl": "https://github.com/discordjs/discord.js/tree/main/packages/core"
} }

View File

@@ -30,10 +30,8 @@ body = """
{{ commit.message | upper_first }} ([{{ commit.id | truncate(length=7, end="") }}]({{ self::remote_url() }}/commit/{{ commit.id }}))\ {{ commit.message | upper_first }} ([{{ commit.id | truncate(length=7, end="") }}]({{ self::remote_url() }}/commit/{{ commit.id }}))\
{% if commit.github.username %} by @{{ commit.github.username }}{%- endif %}\ {% if commit.github.username %} by @{{ commit.github.username }}{%- endif %}\
{% if commit.breaking %}\ {% if commit.breaking %}\
{% for footer in commit.footers %}\ {% for breakingChange in commit.footers %}\
{% if footer.breaking %}\ \n{% raw %} {% endraw %}- **{{ breakingChange.token }}{{ breakingChange.separator }}** {{ breakingChange.value }}\
\n{% raw %} {% endraw %}- **{{ footer.token }}{{ footer.separator }}** {{ footer.value }}\
{% endif %}\
{% endfor %}\ {% endfor %}\
{% endif %}\ {% endif %}\
{% endfor %} {% endfor %}

View File

@@ -1,7 +1,7 @@
{ {
"$schema": "https://json.schemastore.org/package.json", "$schema": "https://json.schemastore.org/package.json",
"name": "@discordjs/core", "name": "@discordjs/core",
"version": "2.2.1", "version": "2.0.0",
"description": "A thinly abstracted wrapper around the rest API, and gateway.", "description": "A thinly abstracted wrapper around the rest API, and gateway.",
"scripts": { "scripts": {
"test": "vitest run", "test": "vitest run",
@@ -70,7 +70,7 @@
"@discordjs/ws": "workspace:^", "@discordjs/ws": "workspace:^",
"@sapphire/snowflake": "^3.5.3", "@sapphire/snowflake": "^3.5.3",
"@vladfrangu/async_event_emitter": "^2.4.6", "@vladfrangu/async_event_emitter": "^2.4.6",
"discord-api-types": "^0.38.16" "discord-api-types": "^0.37.114"
}, },
"devDependencies": { "devDependencies": {
"@discordjs/api-extractor": "workspace:^", "@discordjs/api-extractor": "workspace:^",
@@ -90,7 +90,7 @@
"vitest": "^2.0.5" "vitest": "^2.0.5"
}, },
"engines": { "engines": {
"node": ">=20" "node": ">=18"
}, },
"publishConfig": { "publishConfig": {
"access": "public", "access": "public",

View File

@@ -45,7 +45,7 @@ export class ChannelsAPI {
/** /**
* Sends a message in a channel * Sends a message in a channel
* *
* @see {@link https://discord.com/developers/docs/resources/message#create-message} * @see {@link https://discord.com/developers/docs/resources/channel#create-message}
* @param channelId - The id of the channel to send the message in * @param channelId - The id of the channel to send the message in
* @param body - The data for sending the message * @param body - The data for sending the message
* @param options - The options for sending the message * @param options - The options for sending the message
@@ -65,7 +65,7 @@ export class ChannelsAPI {
/** /**
* Edits a message * Edits a message
* *
* @see {@link https://discord.com/developers/docs/resources/message#edit-message} * @see {@link https://discord.com/developers/docs/resources/channel#edit-message}
* @param channelId - The id of the channel the message is in * @param channelId - The id of the channel the message is in
* @param messageId - The id of the message to edit * @param messageId - The id of the message to edit
* @param body - The data for editing the message * @param body - The data for editing the message
@@ -87,7 +87,7 @@ export class ChannelsAPI {
/** /**
* Fetches the reactions for a message * Fetches the reactions for a message
* *
* @see {@link https://discord.com/developers/docs/resources/message#get-reactions} * @see {@link https://discord.com/developers/docs/resources/channel#get-reactions}
* @param channelId - The id of the channel the message is in * @param channelId - The id of the channel the message is in
* @param messageId - The id of the message to get the reactions for * @param messageId - The id of the message to get the reactions for
* @param emoji - The emoji to get the reactions for * @param emoji - The emoji to get the reactions for
@@ -110,7 +110,7 @@ export class ChannelsAPI {
/** /**
* Deletes a reaction for the current user * Deletes a reaction for the current user
* *
* @see {@link https://discord.com/developers/docs/resources/message#delete-own-reaction} * @see {@link https://discord.com/developers/docs/resources/channel#delete-own-reaction}
* @param channelId - The id of the channel the message is in * @param channelId - The id of the channel the message is in
* @param messageId - The id of the message to delete the reaction for * @param messageId - The id of the message to delete the reaction for
* @param emoji - The emoji to delete the reaction for * @param emoji - The emoji to delete the reaction for
@@ -130,7 +130,7 @@ export class ChannelsAPI {
/** /**
* Deletes a reaction for a user * Deletes a reaction for a user
* *
* @see {@link https://discord.com/developers/docs/resources/message#delete-user-reaction} * @see {@link https://discord.com/developers/docs/resources/channel#delete-user-reaction}
* @param channelId - The id of the channel the message is in * @param channelId - The id of the channel the message is in
* @param messageId - The id of the message to delete the reaction for * @param messageId - The id of the message to delete the reaction for
* @param emoji - The emoji to delete the reaction for * @param emoji - The emoji to delete the reaction for
@@ -152,7 +152,7 @@ export class ChannelsAPI {
/** /**
* Deletes all reactions for a message * Deletes all reactions for a message
* *
* @see {@link https://discord.com/developers/docs/resources/message#delete-all-reactions} * @see {@link https://discord.com/developers/docs/resources/channel#delete-all-reactions}
* @param channelId - The id of the channel the message is in * @param channelId - The id of the channel the message is in
* @param messageId - The id of the message to delete the reactions for * @param messageId - The id of the message to delete the reactions for
* @param options - The options for deleting the reactions * @param options - The options for deleting the reactions
@@ -168,7 +168,7 @@ export class ChannelsAPI {
/** /**
* Deletes all reactions of an emoji for a message * Deletes all reactions of an emoji for a message
* *
* @see {@link https://discord.com/developers/docs/resources/message#delete-all-reactions-for-emoji} * @see {@link https://discord.com/developers/docs/resources/channel#delete-all-reactions-for-emoji}
* @param channelId - The id of the channel the message is in * @param channelId - The id of the channel the message is in
* @param messageId - The id of the message to delete the reactions for * @param messageId - The id of the message to delete the reactions for
* @param emoji - The emoji to delete the reactions for * @param emoji - The emoji to delete the reactions for
@@ -186,7 +186,7 @@ export class ChannelsAPI {
/** /**
* Adds a reaction to a message * Adds a reaction to a message
* *
* @see {@link https://discord.com/developers/docs/resources/message#create-reaction} * @see {@link https://discord.com/developers/docs/resources/channel#create-reaction}
* @param channelId - The id of the channel the message is in * @param channelId - The id of the channel the message is in
* @param messageId - The id of the message to add the reaction to * @param messageId - The id of the message to add the reaction to
* @param emoji - The emoji to add the reaction with * @param emoji - The emoji to add the reaction with
@@ -223,13 +223,9 @@ export class ChannelsAPI {
public async edit( public async edit(
channelId: Snowflake, channelId: Snowflake,
body: RESTPatchAPIChannelJSONBody, body: RESTPatchAPIChannelJSONBody,
{ signal, reason }: Pick<RequestData, 'reason' | 'signal'> = {}, { signal }: Pick<RequestData, 'signal'> = {},
) { ) {
return this.rest.patch(Routes.channel(channelId), { return this.rest.patch(Routes.channel(channelId), { body, signal }) as Promise<RESTPatchAPIChannelResult>;
reason,
body,
signal,
}) as Promise<RESTPatchAPIChannelResult>;
} }
/** /**
@@ -239,14 +235,14 @@ export class ChannelsAPI {
* @param channelId - The id of the channel to delete * @param channelId - The id of the channel to delete
* @param options - The options for deleting the channel * @param options - The options for deleting the channel
*/ */
public async delete(channelId: Snowflake, { signal, reason }: Pick<RequestData, 'reason' | 'signal'> = {}) { public async delete(channelId: Snowflake, { signal }: Pick<RequestData, 'signal'> = {}) {
return this.rest.delete(Routes.channel(channelId), { signal, reason }) as Promise<RESTDeleteAPIChannelResult>; return this.rest.delete(Routes.channel(channelId), { signal }) as Promise<RESTDeleteAPIChannelResult>;
} }
/** /**
* Fetches the messages of a channel * Fetches the messages of a channel
* *
* @see {@link https://discord.com/developers/docs/resources/message#get-channel-messages} * @see {@link https://discord.com/developers/docs/resources/channel#get-channel-messages}
* @param channelId - The id of the channel to fetch messages from * @param channelId - The id of the channel to fetch messages from
* @param query - The query options for fetching messages * @param query - The query options for fetching messages
* @param options - The options for fetching the messages * @param options - The options for fetching the messages
@@ -303,7 +299,7 @@ export class ChannelsAPI {
/** /**
* Deletes a message * Deletes a message
* *
* @see {@link https://discord.com/developers/docs/resources/message#delete-message} * @see {@link https://discord.com/developers/docs/resources/channel#delete-message}
* @param channelId - The id of the channel the message is in * @param channelId - The id of the channel the message is in
* @param messageId - The id of the message to delete * @param messageId - The id of the message to delete
* @param options - The options for deleting the message * @param options - The options for deleting the message
@@ -319,7 +315,7 @@ export class ChannelsAPI {
/** /**
* Bulk deletes messages * Bulk deletes messages
* *
* @see {@link https://discord.com/developers/docs/resources/message#bulk-delete-messages} * @see {@link https://discord.com/developers/docs/resources/channel#bulk-delete-messages}
* @param channelId - The id of the channel the messages are in * @param channelId - The id of the channel the messages are in
* @param messageIds - The ids of the messages to delete * @param messageIds - The ids of the messages to delete
* @param options - The options for deleting the messages * @param options - The options for deleting the messages
@@ -335,7 +331,7 @@ export class ChannelsAPI {
/** /**
* Fetches a message * Fetches a message
* *
* @see {@link https://discord.com/developers/docs/resources/message#get-channel-message} * @see {@link https://discord.com/developers/docs/resources/channel#get-channel-message}
* @param channelId - The id of the channel the message is in * @param channelId - The id of the channel the message is in
* @param messageId - The id of the message to fetch * @param messageId - The id of the message to fetch
* @param options - The options for fetching the message * @param options - The options for fetching the message
@@ -349,7 +345,7 @@ export class ChannelsAPI {
/** /**
* Crossposts a message * Crossposts a message
* *
* @see {@link https://discord.com/developers/docs/resources/message#crosspost-message} * @see {@link https://discord.com/developers/docs/resources/channel#crosspost-message}
* @param channelId - The id of the channel the message is in * @param channelId - The id of the channel the message is in
* @param messageId - The id of the message to crosspost * @param messageId - The id of the message to crosspost
* @param options - The options for crossposting the message * @param options - The options for crossposting the message
@@ -445,19 +441,18 @@ export class ChannelsAPI {
channelId: Snowflake, channelId: Snowflake,
body: RESTPostAPIChannelThreadsJSONBody, body: RESTPostAPIChannelThreadsJSONBody,
messageId?: Snowflake, messageId?: Snowflake,
{ signal, reason }: Pick<RequestData, 'reason' | 'signal'> = {}, { signal }: Pick<RequestData, 'signal'> = {},
) { ) {
return this.rest.post(Routes.threads(channelId, messageId), { return this.rest.post(Routes.threads(channelId, messageId), {
body, body,
signal, signal,
reason,
}) as Promise<RESTPostAPIChannelThreadsResult>; }) as Promise<RESTPostAPIChannelThreadsResult>;
} }
/** /**
* Creates a new forum post * Creates a new forum post
* *
* @see {@link https://discord.com/developers/docs/resources/channel#start-thread-in-forum-or-media-channel} * @see {@link https://discord.com/developers/docs/resources/channel#start-thread-in-forum-channel}
* @param channelId - The id of the forum channel to start the thread in * @param channelId - The id of the forum channel to start the thread in
* @param body - The data for starting the thread * @param body - The data for starting the thread
* @param options - The options for starting the thread * @param options - The options for starting the thread
@@ -465,7 +460,7 @@ export class ChannelsAPI {
public async createForumThread( public async createForumThread(
channelId: Snowflake, channelId: Snowflake,
{ message, ...optionsBody }: StartForumThreadOptions, { message, ...optionsBody }: StartForumThreadOptions,
{ signal, reason }: Pick<RequestData, 'reason' | 'signal'> = {}, { signal }: Pick<RequestData, 'signal'> = {},
) { ) {
const { files, ...messageBody } = message; const { files, ...messageBody } = message;
@@ -474,12 +469,7 @@ export class ChannelsAPI {
message: messageBody, message: messageBody,
}; };
return this.rest.post(Routes.threads(channelId), { return this.rest.post(Routes.threads(channelId), { files, body, signal }) as Promise<APIThreadChannel>;
files,
body,
reason,
signal,
}) as Promise<APIThreadChannel>;
} }
/** /**

View File

@@ -115,7 +115,7 @@ export class GuildsAPI {
* @param options - The options for fetching the guild * @param options - The options for fetching the guild
* @deprecated Use the overload with a query instead. * @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 * Fetches a guild
@@ -198,8 +198,8 @@ export class GuildsAPI {
* @param guildId - The id of the guild to delete * @param guildId - The id of the guild to delete
* @param options - The options for deleting this guild * @param options - The options for deleting this guild
*/ */
public async delete(guildId: Snowflake, { signal }: Pick<RequestData, 'signal'> = {}) { public async delete(guildId: Snowflake, { signal, reason }: Pick<RequestData, 'reason' | 'signal'> = {}) {
await this.rest.delete(Routes.guild(guildId), { signal }); await this.rest.delete(Routes.guild(guildId), { reason, signal });
} }
/** /**

View File

@@ -258,7 +258,7 @@ export class InteractionsAPI {
* @param interactionId - The id of the interaction * @param interactionId - The id of the interaction
* @param interactionToken - The token of the interaction * @param interactionToken - The token of the interaction
* @param options - The options for sending the premium required response * @param options - The options for sending the premium required response
* @deprecated Sending a premium-style button is the new Discord behavior. * @deprecated Sending a premium-style button is the new Discord behaviour.
*/ */
public async sendPremiumRequired( public async sendPremiumRequired(
interactionId: Snowflake, interactionId: Snowflake,

View File

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

View File

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

View File

@@ -7,7 +7,6 @@
<p> <p>
<a href="https://discord.gg/djs"><img src="https://img.shields.io/discord/222078108977594368?color=5865F2&logo=discord&logoColor=white" alt="Discord server" /></a> <a href="https://discord.gg/djs"><img src="https://img.shields.io/discord/222078108977594368?color=5865F2&logo=discord&logoColor=white" alt="Discord server" /></a>
<a href="https://github.com/discordjs/discord.js/actions"><img src="https://github.com/discordjs/discord.js/actions/workflows/test.yml/badge.svg" alt="Build status" /></a> <a href="https://github.com/discordjs/discord.js/actions"><img src="https://github.com/discordjs/discord.js/actions/workflows/test.yml/badge.svg" alt="Build status" /></a>
<a href="https://github.com/discordjs/discord.js/commits/main/packages/create-discord-bot"><img alt="Last commit." src="https://img.shields.io/github/last-commit/discordjs/discord.js?logo=github&logoColor=ffffff&path=packages%2Fcreate-discord-bot"></a>
</p> </p>
<p> <p>
<a href="https://vercel.com/?utm_source=discordjs&utm_campaign=oss"><img src="https://raw.githubusercontent.com/discordjs/discord.js/main/.github/powered-by-vercel.svg" alt="Vercel" /></a> <a href="https://vercel.com/?utm_source=discordjs&utm_campaign=oss"><img src="https://raw.githubusercontent.com/discordjs/discord.js/main/.github/powered-by-vercel.svg" alt="Vercel" /></a>

View File

@@ -30,10 +30,8 @@ body = """
{{ commit.message | upper_first }} ([{{ commit.id | truncate(length=7, end="") }}]({{ self::remote_url() }}/commit/{{ commit.id }}))\ {{ commit.message | upper_first }} ([{{ commit.id | truncate(length=7, end="") }}]({{ self::remote_url() }}/commit/{{ commit.id }}))\
{% if commit.github.username %} by @{{ commit.github.username }}{%- endif %}\ {% if commit.github.username %} by @{{ commit.github.username }}{%- endif %}\
{% if commit.breaking %}\ {% if commit.breaking %}\
{% for footer in commit.footers %}\ {% for breakingChange in commit.footers %}\
{% if footer.breaking %}\ \n{% raw %} {% endraw %}- **{{ breakingChange.token }}{{ breakingChange.separator }}** {{ breakingChange.value }}\
\n{% raw %} {% endraw %}- **{{ footer.token }}{{ footer.separator }}** {{ footer.value }}\
{% endif %}\
{% endfor %}\ {% endfor %}\
{% endif %}\ {% endif %}\
{% endfor %} {% endfor %}

View File

@@ -83,7 +83,7 @@
"no-void": "error", "no-void": "error",
"no-warning-comments": "warn", "no-warning-comments": "warn",
"prefer-promise-reject-errors": "error", "prefer-promise-reject-errors": "error",
"require-await": "off", "require-await": "warn",
"wrap-iife": "error", "wrap-iife": "error",
"yoda": "error", "yoda": "error",

View File

@@ -1,5 +1,5 @@
{ {
"$schema": "https://json.schemastore.org/lintstagedrc.schema.json", "$schema": "https://json.schemastore.org/lintstagedrc.schema.json",
"*": "prettier --ignore-unknown --write", "*": "prettier --ignore-unknown --write",
"{src/**,typings/**,scripts/**}.{mjs,js,ts}": "cross-env ESLINT_USE_FLAT_CONFIG=false eslint --ext mjs,js,ts --fix" "{src/**,test/**,typings/**,scripts/**}.{mjs,js,ts}": "cross-env ESLINT_USE_FLAT_CONFIG=false eslint --ext mjs,js,ts --fix"
} }

View File

@@ -2,272 +2,6 @@
All notable changes to this project will be documented in this file. All notable changes to this project will be documented in this file.
# [14.22.1](https://github.com/discordjs/discord.js/compare/14.22.0...14.22.1) - (2025-08-22)
## Bug Fixes
- **GuildChannel:** Account for everyone base permissions (#11053) ([ecef7bd](https://github.com/discordjs/discord.js/commit/ecef7bdf22cc3e7c1fc47d828a55f6139672b2a8))
# [14.22.0](https://github.com/discordjs/discord.js/compare/14.21.0...14.22.0) - (2025-08-20)
## Bug Fixes
- Remove trailing `color` references (#11007) ([b532df6](https://github.com/discordjs/discord.js/commit/b532df61ed346e2289831f2905984583a53d3fa5))
- **Emoji:** Remove incorrect nullables, add `ApplicationEmoji#available` (#10990) ([90d3b28](https://github.com/discordjs/discord.js/commit/90d3b282684f5a4bbf9ce2672fa5efd5ec802e95))
- **GuildChannelManager:** Properly resolve avatar for createWebhook (#10772) ([63f5261](https://github.com/discordjs/discord.js/commit/63f5261f4c351cd1b6befca1163254300f7424f4))
- **Message:** Forwarded messages are not `crosspostable` (#10821) ([b36b751](https://github.com/discordjs/discord.js/commit/b36b751bde5f5de286d748465619147619959d4f))
- **DirectoryChannel:** Export class (#10985) ([51ceb20](https://github.com/discordjs/discord.js/commit/51ceb203fa218accab47f604f91f74b49af7e51f))
- **Events:** `WebhooksUpdate` enum value (#10970) ([1404e32](https://github.com/discordjs/discord.js/commit/1404e328492549f4a17ab997eb648f3263e8ec25))
## Documentation
- Remove hardcoded locale from links (#10794) ([5be774d](https://github.com/discordjs/discord.js/commit/5be774db641b60669505645861d721200d335a7b))
- **ApplicationCommand:** Incorrect method in example (#10837) ([040c66a](https://github.com/discordjs/discord.js/commit/040c66ae15fd3cc7cb40bdbb5384ede445c40973))
## Features
- Support user guilds (#10995) ([baa08b8](https://github.com/discordjs/discord.js/commit/baa08b8fbb64abd8265890413c95f81e2c61303f))
- **MessageManager:** New pinned messages routes (#10993) ([f469f74](https://github.com/discordjs/discord.js/commit/f469f74acaa14f126fd02af4a032ca8e56dbb534))
- `fetchPinned()` has been renamed to `fetchPins()`, which is a paginated endpoint to fetch pinned messages.
- **User:** Add `collectibles` (#10939) ([8ac0e1e](https://github.com/discordjs/discord.js/commit/8ac0e1e5d6df9c51fd3a41d9f8c9dbe8f786229a))
- Role gradient colours (#10986) ([9d6fdf8](https://github.com/discordjs/discord.js/commit/9d6fdf8979d29787a13912cfa55f1ff3961c6b68))
- Support animated WebP (#10987) ([cafe58b](https://github.com/discordjs/discord.js/commit/cafe58b3bd9defb5050a7a90bd07568f3b509c89))
## Refactor
- Deprecate `ready` event in favor of `clientReady` (#10969) ([82378fc](https://github.com/discordjs/discord.js/commit/82378fc2e8f4fd7e56b5a80eb6a6d3a8315e388e))
- **ThreadChannel:** Remove trimming of name (#10984) ([d4f742e](https://github.com/discordjs/discord.js/commit/d4f742e99e31b4eb9e84afce3bab48ed549f8ae3))
## Typings
- **Invite:** Approximate fields should be nullable (#10997) ([d60e0bf](https://github.com/discordjs/discord.js/commit/d60e0bf30bac05921063d010fab253ca829ae3bb))
- **ModalSubmitFields:** Fix `fields` type (#10816) ([500712d](https://github.com/discordjs/discord.js/commit/500712d5eaef1a75133e088e0f260842d12f3419))
- **InteractionCallbackResponse:** Add missing InGuild generic (#10963) ([19e74b1](https://github.com/discordjs/discord.js/commit/19e74b153317cf8b910317c56beb95a698acc00c))
# [14.21.0](https://github.com/discordjs/discord.js/compare/14.20.0...14.21.0) - (2025-06-25)
## Bug Fixes
- **ClientUser:** Remove token assignment (#10953) ([507b696](https://github.com/discordjs/discord.js/commit/507b696792d61ae49565b4613439aceb08dcf38a))
## Features
- **GuildMember:** Add `avatarDecorationData` (#10942) ([15f7571](https://github.com/discordjs/discord.js/commit/15f7571243d5b206141290478fd5164d299c0850))
- **ClientApplication:** Add `approximateUserAuthorizationCount` (#10933) ([3fa429c](https://github.com/discordjs/discord.js/commit/3fa429c7dfa3bb3e6f099cd2f068c474a01677b1))
## Typings
- **ClientEventTypes:** Add missing `guildSoundboardSoundsUpdate` (#10928) ([c2a43b6](https://github.com/discordjs/discord.js/commit/c2a43b685e01eff878a399e8c00df8e473c185ad))
# [14.20.0](https://github.com/discordjs/discord.js/compare/14.19.3...14.20.0) - (2025-06-16)
## Bug Fixes
- Use resolvePartialEmoji on MessagePayload#options#components (#10910) ([f2f757c](https://github.com/discordjs/discord.js/commit/f2f757ce52b76d5e571f47f9bf1c5188627b80d5))
- **ChannelManager:** Remove threads from cache upon deletion (#10883) ([ee2eb73](https://github.com/discordjs/discord.js/commit/ee2eb7349f2467451880baaea54e02074916015f))
- **PartialGroupDMChannel:** Prevent `undefined` values (#10889) ([9bca4af](https://github.com/discordjs/discord.js/commit/9bca4af5fdb78fae7b970498db7f93df31f55ef9))
## Features
- Backport entrypoint command (#10908) ([c0eae34](https://github.com/discordjs/discord.js/commit/c0eae344c2ed43fa67be9fda8e3d3e479693d2d1))
- **BaseInteraction:** Add `attachmentSizeLimit` (#10830) ([7e21a94](https://github.com/discordjs/discord.js/commit/7e21a9474e532c5b22c6e0600c446fca47352617))
## Performance
- **Components:** Hash table (#10893) ([2d19163](https://github.com/discordjs/discord.js/commit/2d19163d764705667691430e438499fd330ffb65))
## Refactor
- **Client:** Remove `with_expiration` query parameter (#10800) ([c8f6066](https://github.com/discordjs/discord.js/commit/c8f6066d6a0a1fc6ac23a49d66604d95b588af3e))
# [14.19.3](https://github.com/discordjs/discord.js/compare/14.19.2...14.19.3) - (2025-05-02)
## Bug Fixes
- 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
- **Guild:** Type error with permissionOverwrites (#10527) ([8e1e1be](https://github.com/discordjs/discord.js/commit/8e1e1be0c23a0a063a6b530ac8cee30cf7629644))
- Incorrect relative path (#10734) ([b7f1ebc](https://github.com/discordjs/discord.js/commit/b7f1ebc334e110be3208c476b61b82a69386fd84))
- **PresenceUpdate:** Correctly add user regardless of their properties (#10672) ([7c1b73c](https://github.com/discordjs/discord.js/commit/7c1b73cc697fd3b85011bdb2c098ca3a3f863b1f))
- **InteractionResponses:** Mark replied true for followUps (#10688) ([32dff01](https://github.com/discordjs/discord.js/commit/32dff01f291271bde3cfb354964ed140a6fa82d7))
## Documentation
- Use link tags to render links on the documentation (#10731) ([66b9718](https://github.com/discordjs/discord.js/commit/66b971899ab702240642e3ae2d189fd9e7efc701))
- **Message:** Improve message snapshots description (#10709) ([31df3d2](https://github.com/discordjs/discord.js/commit/31df3d21cdc53400672924bc7c5dc7fd3053630b))
## Features
- Message forwards (#10733) ([89c076c](https://github.com/discordjs/discord.js/commit/89c076c89e90e8f5912786e8899ced9e8eea6003))
- Incident Actions (#10727) ([41dee51](https://github.com/discordjs/discord.js/commit/41dee5177d9cb15f667e60a34619882222bf249c))
- **website:** Type parameters links, builtin doc links, default values (#10515) ([43235d4](https://github.com/discordjs/discord.js/commit/43235d43fe76e26805c52dcff13519652bcb6a4a))
- **PartialGroupDMChannel:** Add missing properties (#10502) ([5e66f85](https://github.com/discordjs/discord.js/commit/5e66f85f55724a583921252b035eb2097345fec8))
- **Subscription:** Add `renewalSkuIds` (#10662) ([efa50fc](https://github.com/discordjs/discord.js/commit/efa50fc3fa463b09bde11c1640daa2abb8c22686))
- **website:** Include reexported members in docs (#10518) ([aa61c20](https://github.com/discordjs/discord.js/commit/aa61c20ffdac3f3a0dca224f9e48e614309ecb2e))
## Refactor
- Use throw instead of Promise.reject (#10712) ([2663d76](https://github.com/discordjs/discord.js/commit/2663d767099f2e14a23f9cbfb868f279ffb253d1))
- Remove data resolver exports (#10701) ([4606041](https://github.com/discordjs/discord.js/commit/46060419a9593dc5132ba6f13b58d0c18613679b))
- **IntegrationApplication:** Move common properties to Application (#10627) ([95db597](https://github.com/discordjs/discord.js/commit/95db597fc844e7951b07cfb5741e27086ac7451a))
## Styling
- Prettier ([92aea94](https://github.com/discordjs/discord.js/commit/92aea944119638b12c03be0f627f20fe5fe5145e))
## Typings
- Fix recurrence rule types (#10694) ([193a5e9](https://github.com/discordjs/discord.js/commit/193a5e9e20fc4832592b2a3b6f142752121f43d5))
- **ThreadOnlyChannel:** Remove incorrect `messages` property (#10708) ([44a1e85](https://github.com/discordjs/discord.js/commit/44a1e858473a51809cb1e6114d6a659fe28587f0))
- Add `undefined` to `flags` for `exactOptionalPropertyTypes` (#10707) ([d2e1924](https://github.com/discordjs/discord.js/commit/d2e1924fa6a06120879a1158d501a899db3d6d96))
- Allow only ephemeral for defer reply (#10696) ([68dd260](https://github.com/discordjs/discord.js/commit/68dd260dee1a7b0bbd4fcdff1b39283ea8dcedec))
- Remove createComponent and createComponentBuilder (#10687) ([0047a49](https://github.com/discordjs/discord.js/commit/0047a49b7395acf0936702f233e7fb89e9f352fe))
# [14.17.3](https://github.com/discordjs/discord.js/compare/14.17.2...14.17.3) - (2025-01-08)
## Bug Fixes
- **Message:** Ensure channel is defined for clean content (#10681) ([46bf8f0](https://github.com/discordjs/discord.js/commit/46bf8f0146b67d7c480a3512ade1edbfb16e7a26))
- Use `resolve()` for `PermissionOverwrites` (#10686) ([7280d4e](https://github.com/discordjs/discord.js/commit/7280d4e82eb47ce7cb3964057d7d56a62179cf18))
# [14.17.2](https://github.com/discordjs/discord.js/compare/14.17.1...14.17.2) - (2025-01-02)
## Bug Fixes
- **InteractionResponses:** Check correct property for deprecation ([77804cf](https://github.com/discordjs/discord.js/commit/77804cfd559691d9b8c85aec8c494cd6c14c4ea7))
# [14.17.0](https://github.com/discordjs/discord.js/compare/14.16.3...14.17.0) - (2025-01-01)
## Bug Fixes
- **InteractionResponses:** Do not use `in` if a string is passed ([ff42d7a](https://github.com/discordjs/discord.js/commit/ff42d7af72e940ae72c61d2c5164ae68f2708b96))
- Use Message#interactionMetadata (#10654) ([6087088](https://github.com/discordjs/discord.js/commit/60870885790eb1857ed4c2969c9c404e356a1299))
- **InteractionResponses:** Properly resolve message flags (#10661) ([b2754d4](https://github.com/discordjs/discord.js/commit/b2754d4a0ec250ae84057d0f07c078376f54829c))
- **ThreadChannel:** Make `ownerId` always present (#10618) ([7678f11](https://github.com/discordjs/discord.js/commit/7678f1176a645878261361faef0429f9cf7f4810))
- **MessageReaction:** Address `undefined` burst properties (#10597) ([76968b4](https://github.com/discordjs/discord.js/commit/76968b4bc14b8a66825f9140d130b1e04c11855a))
- **ThreadChannel:** Address parameter type on fetchOwner() (#10592) ([56c9396](https://github.com/discordjs/discord.js/commit/56c9396b717d4dec2410ca13938ce238ec21215d))
- **InteractionResponses:** Throw error on deleting response of unacknowledged interaction (#10587) ([21c283f](https://github.com/discordjs/discord.js/commit/21c283f964ab9e331db53cc0c21ca64980372488))
- **GuildScheduledEvent:** Handle null recurrence_rule (#10543) ([831aafa](https://github.com/discordjs/discord.js/commit/831aafa733e8eea55534c4c39b87775d2e2f56c4))
## Documentation
- Correct discord-api-types URLs (#10622) ([76042f0](https://github.com/discordjs/discord.js/commit/76042f05386edcbadc5ad4ded22e8b15c7b6f8ec))
- Typos (#10628) ([388783d](https://github.com/discordjs/discord.js/commit/388783d7dd718aae519801b90aa781d07b7fb64e))
- Add note about idempotence to role add/remove routes (#10586) ([565fc01](https://github.com/discordjs/discord.js/commit/565fc0192a5ed2642ff1bd615c59678b5c3cd24b))
- **Client:** Fix incorrect managers descriptions ([f79ba52](https://github.com/discordjs/discord.js/commit/f79ba52c7a1334d987e9873a8a411e92d5140116))
- **discord.js:** Remove `utf-8-validate` (#10531) ([297e959](https://github.com/discordjs/discord.js/commit/297e959f48abbfd3af58cc29cdcef139d3579821))
## Features
- **ClientApplication:** Add webhook events (#10588) ([7b2a2e3](https://github.com/discordjs/discord.js/commit/7b2a2e3a154afd69ff892da615ea75c46730f226))
- **InteractionResponses:** Support `with_response` query parameter (#10636) ([622acbc](https://github.com/discordjs/discord.js/commit/622acbcbf02c3b8e0eae4296964c3e745e19378d))
- **ClientApplication:** Add webhook events (#10588) ([ae1deac](https://github.com/discordjs/discord.js/commit/ae1deac2bf37aecda4c044bf5c28d03930bd763b))
- **EntitlementManager:** Support get entitlement (#10606) ([a367e2c](https://github.com/discordjs/discord.js/commit/a367e2c8c99ab3bfb83cdbfb65e7a5020b50b7f7))
- Add subscriptions (#10541) ([4cca33d](https://github.com/discordjs/discord.js/commit/4cca33d9b0759294c9a2dfec39d80a24a2cc1595))
- Emit reaction type on gateway events (#10598) ([bda3128](https://github.com/discordjs/discord.js/commit/bda31284bf46515747e002e86ea35d0b6910e269))
- Voice Channel Effect Send (#10318) ([34343c6](https://github.com/discordjs/discord.js/commit/34343c6afae65205d3b17b60fdd202d0937d6a46))
- **GuildMember:** Banners (#10384) ([b1ded63](https://github.com/discordjs/discord.js/commit/b1ded63e42e7349f535df4680509b9393dd8f288))
- Add ApplicationEmoji to EmojiResolvable and MessageReaction#emoji (#10477) ([1fc87a9](https://github.com/discordjs/discord.js/commit/1fc87a96987fe69722502d7574500926a4e0bfde))
- Recurring scheduled events (#10447) ([97c3237](https://github.com/discordjs/discord.js/commit/97c3237a70027f71bb3f046357a55bb730daca14))
- Message forwarding (#10464) ([c122178](https://github.com/discordjs/discord.js/commit/c12217829b46f7a60266f65af4af19cdbfcd7906))
## Refactor
- **FetchApplicationCommandOptions:** Use `Locale` over `LocaleString` (#10625) ([7ce6f2f](https://github.com/discordjs/discord.js/commit/7ce6f2fc8a8756532d71a542186d10a0aa951471))
- Use `cache.get()` for snowflakes, `resolve()` otherwise (#10626) ([dedaa5d](https://github.com/discordjs/discord.js/commit/dedaa5d657f15491910ec05102ce72affc822b97))
- Remove extra traversing (#10580) ([33533b7](https://github.com/discordjs/discord.js/commit/33533b72849d9741dae8c979734b45abbf3657a7))
- **InteractionResponses:** Deprecate ephemeral response option (#10574) ([be38f57](https://github.com/discordjs/discord.js/commit/be38f5792602ed1a79a9638aa8e629e7ad6bdd0d))
- Deprecate `reason` parameter on adding and removing thread members (#10551) ([72e0c99](https://github.com/discordjs/discord.js/commit/72e0c994547f2a9c99b320870e14d7f1643f3851))
- Deprecate fetching user flags (#10550) ([3d06c9d](https://github.com/discordjs/discord.js/commit/3d06c9d872b2e79356f1239f7d0eb0577a4bcedf))
## Testing
- Remove unused test (#10638) ([53cbb0e](https://github.com/discordjs/discord.js/commit/53cbb0e36d4ab191cbc15a022d752da14c2e0ace))
## Typings
- Add missing `Caches` managers (#10540) ([13471fa](https://github.com/discordjs/discord.js/commit/13471fa1b7c44b236db9fe9b1a64dacd41b14b76))
- Remove newMessage partial on messageUpdate event typing (#10526) ([5faf074](https://github.com/discordjs/discord.js/commit/5faf074c145044f0edefafab97fd07a8dfb8bc30))
# [14.16.3](https://github.com/discordjs/discord.js/compare/14.16.2...14.16.3) - (2024-09-29)
## Bug Fixes
- **BaseInteraction:** Add missing props (#10517) ([6c77fee](https://github.com/discordjs/discord.js/commit/6c77fee41b1aabc243bff623debd157a4c7fad6a)) by @monbrey
- `GuildChannel#guildId` not being patched to `undefined` (#10505) ([2adee06](https://github.com/discordjs/discord.js/commit/2adee06b6e92b7854ebb1c2bfd04940aab68dd10)) by @Qjuh
## Typings
- **MessageEditOptions:** Omit `poll` (#10509) ([665bf14](https://github.com/discordjs/discord.js/commit/665bf1486aec62e9528f5f7b5a6910ae6b5a6c9c)) by @TAEMBO
# [14.16.2](https://github.com/discordjs/discord.js/compare/14.16.1...14.16.2) - (2024-09-12)
## Bug Fixes
- **ApplicationCommand:** Incorrect comparison in equals method (#10497) ([3c74aa2](https://github.com/discordjs/discord.js/commit/3c74aa204909323ff6d05991438bee2c583e838b)) by @monbrey
- Type guard for sendable text-based channels (#10482) ([dea6840](https://github.com/discordjs/discord.js/commit/dea68400a38edb90b8b4242d64be14968943130d)) by @vladfrangu
## Documentation
- Update discord documentation links (#10484) ([799fa54](https://github.com/discordjs/discord.js/commit/799fa54fa4434144855be2f7a0bbac6ff8ce9d0b)) by @sdanialraza
- **Message:** Mark `interaction` as deprecated (#10481) ([c13f18e](https://github.com/discordjs/discord.js/commit/c13f18e90eb6eb315397c095e948993856428757)) by @sdanialraza
- **ApplicationEmojiManager:** Fix fetch example (#10480) ([4594896](https://github.com/discordjs/discord.js/commit/4594896b5404c6a34e07544951c59ff8f3657184)) by @sdanialraza
## Typings
- Export GroupDM helper type (#10478) ([aff772c](https://github.com/discordjs/discord.js/commit/aff772c7aa3b3de58780a94588d1f3576a434f32)) by @Qjuh
# [14.16.1](https://github.com/discordjs/discord.js/compare/14.16.0...14.16.1) - (2024-09-02)
## Bug Fixes
- **Message:** Reacting returning undefined (#10475) ([9257a09](https://github.com/discordjs/discord.js/commit/9257a09abbf80558ed2d5d209a2f6bd2a4b3d799)) by @vladfrangu
- **Transformers:** Pass client to recursive call (#10474) ([4810f7c](https://github.com/discordjs/discord.js/commit/4810f7c8637dacf77d0442bd84e0d579e1f1d3bd)) by @SpaceEEC
# [14.16.0](https://github.com/discordjs/discord.js/compare/14.15.3...14.16.0) - (2024-09-01) # [14.16.0](https://github.com/discordjs/discord.js/compare/14.15.3...14.16.0) - (2024-09-01)
## Bug Fixes ## Bug Fixes

View File

@@ -9,8 +9,7 @@
<a href="https://www.npmjs.com/package/discord.js"><img src="https://img.shields.io/npm/v/discord.js.svg?maxAge=3600" alt="npm version" /></a> <a href="https://www.npmjs.com/package/discord.js"><img src="https://img.shields.io/npm/v/discord.js.svg?maxAge=3600" alt="npm version" /></a>
<a href="https://www.npmjs.com/package/discord.js"><img src="https://img.shields.io/npm/dt/discord.js.svg?maxAge=3600" alt="npm downloads" /></a> <a href="https://www.npmjs.com/package/discord.js"><img src="https://img.shields.io/npm/dt/discord.js.svg?maxAge=3600" alt="npm downloads" /></a>
<a href="https://github.com/discordjs/discord.js/actions"><img src="https://github.com/discordjs/discord.js/actions/workflows/test.yml/badge.svg" alt="Tests status" /></a> <a href="https://github.com/discordjs/discord.js/actions"><img src="https://github.com/discordjs/discord.js/actions/workflows/test.yml/badge.svg" alt="Tests status" /></a>
<a href="https://github.com/discordjs/discord.js/commits/main/packages/discord.js"><img alt="Last commit." src="https://img.shields.io/github/last-commit/discordjs/discord.js?logo=github&logoColor=ffffff&path=packages%2Fdiscord.js"></a> <a href="https://codecov.io/gh/discordjs/discord.js" ><img src="https://codecov.io/gh/discordjs/discord.js/branch/main/graph/badge.svg?precision=2" alt="Code coverage" /></a>
<a href="https://codecov.io/gh/discordjs/discord.js"><img src="https://codecov.io/gh/discordjs/discord.js/branch/main/graph/badge.svg?precision=2" alt="Code coverage" /></a>
</p> </p>
<p> <p>
<a href="https://vercel.com/?utm_source=discordjs&utm_campaign=oss"><img src="https://raw.githubusercontent.com/discordjs/discord.js/main/.github/powered-by-vercel.svg" alt="Vercel" /></a> <a href="https://vercel.com/?utm_source=discordjs&utm_campaign=oss"><img src="https://raw.githubusercontent.com/discordjs/discord.js/main/.github/powered-by-vercel.svg" alt="Vercel" /></a>
@@ -30,7 +29,7 @@ discord.js is a powerful [Node.js](https://nodejs.org) module that allows you to
## Installation ## Installation
**Node.js 18 or newer is required.** **Node.js 16.11.0 or newer is required.**
```sh ```sh
npm install discord.js npm install discord.js
@@ -43,6 +42,7 @@ bun add discord.js
- [zlib-sync](https://www.npmjs.com/package/zlib-sync) for WebSocket data compression and inflation (`npm install zlib-sync`) - [zlib-sync](https://www.npmjs.com/package/zlib-sync) for WebSocket data compression and inflation (`npm install zlib-sync`)
- [bufferutil](https://www.npmjs.com/package/bufferutil) for a much faster WebSocket connection (`npm install bufferutil`) - [bufferutil](https://www.npmjs.com/package/bufferutil) for a much faster WebSocket connection (`npm install bufferutil`)
- [utf-8-validate](https://www.npmjs.com/package/utf-8-validate) in combination with `bufferutil` for much faster WebSocket processing (`npm install utf-8-validate`)
- [@discordjs/voice](https://www.npmjs.com/package/@discordjs/voice) for interacting with the Discord Voice API (`npm install @discordjs/voice`) - [@discordjs/voice](https://www.npmjs.com/package/@discordjs/voice) for interacting with the Discord Voice API (`npm install @discordjs/voice`)
## Example usage ## Example usage

View File

@@ -1,15 +1,6 @@
{ {
"extends": "../../api-extractor.json", "extends": "../../api-extractor.json",
"mainEntryPointFilePath": "<projectFolder>/typings/index.d.ts", "mainEntryPointFilePath": "<projectFolder>/typings/index.d.ts",
"bundledPackages": [
"discord-api-types",
"@discordjs/collection",
"@discordjs/builders",
"@discordjs/formatters",
"@discordjs/rest",
"@discordjs/util",
"@discordjs/ws"
],
"docModel": { "docModel": {
"projectFolderUrl": "https://github.com/discordjs/discord.js/tree/main/packages/discord.js" "projectFolderUrl": "https://github.com/discordjs/discord.js/tree/main/packages/discord.js"
} }

View File

@@ -30,10 +30,8 @@ body = """
{{ commit.message | upper_first }} ([{{ commit.id | truncate(length=7, end="") }}]({{ self::remote_url() }}/commit/{{ commit.id }}))\ {{ commit.message | upper_first }} ([{{ commit.id | truncate(length=7, end="") }}]({{ self::remote_url() }}/commit/{{ commit.id }}))\
{% if commit.github.username %} by @{{ commit.github.username }}{%- endif %}\ {% if commit.github.username %} by @{{ commit.github.username }}{%- endif %}\
{% if commit.breaking %}\ {% if commit.breaking %}\
{% for footer in commit.footers %}\ {% for breakingChange in commit.footers %}\
{% if footer.breaking %}\ \n{% raw %} {% endraw %}- **{{ breakingChange.token }}{{ breakingChange.separator }}** {{ breakingChange.value }}\
\n{% raw %} {% endraw %}- **{{ footer.token }}{{ footer.separator }}** {{ footer.value }}\
{% endif %}\
{% endfor %}\ {% endfor %}\
{% endif %}\ {% endif %}\
{% endfor %} {% endfor %}
@@ -69,7 +67,8 @@ commit_parsers = [
{ body = ".*security", group = "Security"}, { body = ".*security", group = "Security"},
] ]
filter_commits = true filter_commits = true
tag_pattern = "^[0-9]+" tag_pattern = "[0-9]*"
skip_tags = "v[0-9]*|@discordjs*"
ignore_tags = "" ignore_tags = ""
topo_order = false topo_order = false
sort_commits = "newest" sort_commits = "newest"

View File

@@ -1,7 +1,7 @@
{ {
"$schema": "https://json.schemastore.org/package.json", "$schema": "https://json.schemastore.org/package.json",
"name": "discord.js", "name": "discord.js",
"version": "14.22.1", "version": "14.16.0",
"description": "A powerful library for interacting with the Discord API", "description": "A powerful library for interacting with the Discord API",
"scripts": { "scripts": {
"test": "pnpm run docs:test && pnpm run test:typescript", "test": "pnpm run docs:test && pnpm run test:typescript",
@@ -36,8 +36,7 @@
}, },
"files": [ "files": [
"src", "src",
"typings/*.d.ts", "typings"
"typings/*.d.mts"
], ],
"contributors": [ "contributors": [
"Crawl <icrawltogo@gmail.com>", "Crawl <icrawltogo@gmail.com>",
@@ -66,19 +65,18 @@
"homepage": "https://discord.js.org", "homepage": "https://discord.js.org",
"funding": "https://github.com/discordjs/discord.js?sponsor", "funding": "https://github.com/discordjs/discord.js?sponsor",
"dependencies": { "dependencies": {
"@discordjs/builders": "^1.11.2", "@discordjs/builders": "workspace:^",
"@discordjs/collection": "1.5.3", "@discordjs/collection": "1.5.3",
"@discordjs/formatters": "^0.6.1", "@discordjs/formatters": "workspace:^",
"@discordjs/rest": "workspace:^", "@discordjs/rest": "workspace:^",
"@discordjs/util": "workspace:^", "@discordjs/util": "workspace:^",
"@discordjs/ws": "^1.2.3", "@discordjs/ws": "1.1.1",
"@sapphire/snowflake": "3.5.3", "@sapphire/snowflake": "3.5.3",
"discord-api-types": "^0.38.16", "discord-api-types": "^0.37.114",
"fast-deep-equal": "3.1.3", "fast-deep-equal": "3.1.3",
"lodash.snakecase": "4.1.1", "lodash.snakecase": "4.1.1",
"magic-bytes.js": "^1.10.0",
"tslib": "^2.6.3", "tslib": "^2.6.3",
"undici": "6.21.3" "undici": "6.19.8"
}, },
"devDependencies": { "devDependencies": {
"@discordjs/api-extractor": "workspace:^", "@discordjs/api-extractor": "workspace:^",
@@ -100,7 +98,7 @@
"typescript": "~5.5.4" "typescript": "~5.5.4"
}, },
"engines": { "engines": {
"node": ">=18" "node": ">=16.11.0"
}, },
"publishConfig": { "publishConfig": {
"provenance": true "provenance": true

View File

@@ -18,7 +18,6 @@ const ClientPresence = require('../structures/ClientPresence');
const GuildPreview = require('../structures/GuildPreview'); const GuildPreview = require('../structures/GuildPreview');
const GuildTemplate = require('../structures/GuildTemplate'); const GuildTemplate = require('../structures/GuildTemplate');
const Invite = require('../structures/Invite'); const Invite = require('../structures/Invite');
const { SoundboardSound } = require('../structures/SoundboardSound');
const { Sticker } = require('../structures/Sticker'); const { Sticker } = require('../structures/Sticker');
const StickerPack = require('../structures/StickerPack'); const StickerPack = require('../structures/StickerPack');
const VoiceRegion = require('../structures/VoiceRegion'); const VoiceRegion = require('../structures/VoiceRegion');
@@ -108,20 +107,20 @@ class Client extends BaseClient {
: null; : null;
/** /**
* The user manager of this client * All of the {@link User} objects that have been cached at any point, mapped by their ids
* @type {UserManager} * @type {UserManager}
*/ */
this.users = new UserManager(this); this.users = new UserManager(this);
/** /**
* A manager of all the guilds the client is currently handling - * All of the guilds the client is currently handling, mapped by their ids -
* as long as sharding isn't being used, this will be *every* guild the bot is a member of * as long as sharding isn't being used, this will be *every* guild the bot is a member of
* @type {GuildManager} * @type {GuildManager}
*/ */
this.guilds = new GuildManager(this); this.guilds = new GuildManager(this);
/** /**
* All of the {@link BaseChannel}s that the client is currently handling - * All of the {@link BaseChannel}s that the client is currently handling, mapped by their ids -
* as long as sharding isn't being used, this will be *every* channel in *every* guild the bot * as long as sharding isn't being used, this will be *every* channel in *every* guild the bot
* is a member of. Note that DM channels will not be initially cached, and thus not be present * is a member of. Note that DM channels will not be initially cached, and thus not be present
* in the Manager without their explicit fetching or use. * in the Manager without their explicit fetching or use.
@@ -175,7 +174,7 @@ class Client extends BaseClient {
} }
/** /**
* A manager of all the custom emojis that the client has access to * All custom emojis that the client has access to, mapped by their ids
* @type {BaseGuildEmojiManager} * @type {BaseGuildEmojiManager}
* @readonly * @readonly
*/ */
@@ -277,6 +276,7 @@ class Client extends BaseClient {
const code = resolveInviteCode(invite); const code = resolveInviteCode(invite);
const query = makeURLSearchParams({ const query = makeURLSearchParams({
with_counts: true, with_counts: true,
with_expiration: true,
guild_scheduled_event_id: options?.guildScheduledEventId, guild_scheduled_event_id: options?.guildScheduledEventId,
}); });
const data = await this.rest.get(Routes.invite(code), { query }); const data = await this.rest.get(Routes.invite(code), { query });
@@ -390,19 +390,6 @@ class Client extends BaseClient {
return this.fetchStickerPacks(); return this.fetchStickerPacks();
} }
/**
* Obtains the list of default soundboard sounds.
* @returns {Promise<Collection<string, SoundboardSound>>}
* @example
* client.fetchDefaultSoundboardSounds()
* .then(sounds => console.log(`Available soundboard sounds are: ${sounds.map(sound => sound.name).join(', ')}`))
* .catch(console.error);
*/
async fetchDefaultSoundboardSounds() {
const data = await this.rest.get(Routes.soundboardDefaultSounds());
return new Collection(data.map(sound => [sound.sound_id, new SoundboardSound(this, sound)]));
}
/** /**
* Obtains a guild preview from Discord, available for all guilds the bot is in and all Discoverable guilds. * Obtains a guild preview from Discord, available for all guilds the bot is in and all Discoverable guilds.
* @param {GuildResolvable} guild The guild to fetch the preview for * @param {GuildResolvable} guild The guild to fetch the preview for
@@ -522,7 +509,7 @@ class Client extends BaseClient {
} }
/** /**
* Calls {@link https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/eval} on a script * Calls {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/eval} on a script
* with the client as `this`. * with the client as `this`.
* @param {string} script Script to eval * @param {string} script Script to eval
* @returns {*} * @returns {*}
@@ -604,7 +591,7 @@ module.exports = Client;
*/ */
/** /**
* A {@link https://docs.x.com/resources/fundamentals/x-ids Twitter snowflake}, * A {@link https://developer.twitter.com/en/docs/twitter-ids Twitter snowflake},
* except the epoch is 2015-01-01T00:00:00.000Z. * except the epoch is 2015-01-01T00:00:00.000Z.
* *
* If we have a snowflake '266241948824764416' we can represent it as binary: * If we have a snowflake '266241948824764416' we can represent it as binary:
@@ -638,11 +625,6 @@ module.exports = Client;
* @see {@link https://discord.js.org/docs/packages/rest/stable/ImageURLOptions:Interface} * @see {@link https://discord.js.org/docs/packages/rest/stable/ImageURLOptions:Interface}
*/ */
/**
* @external EmojiURLOptions
* @see {@link https://discord.js.org/docs/packages/rest/stable/EmojiURLOptions:TypeAlias}
*/
/** /**
* @external BaseImageURLOptions * @external BaseImageURLOptions
* @see {@link https://discord.js.org/docs/packages/rest/stable/BaseImageURLOptions:Interface} * @see {@link https://discord.js.org/docs/packages/rest/stable/BaseImageURLOptions:Interface}

View File

@@ -111,14 +111,6 @@ class GenericAction {
getThreadMember(id, manager) { getThreadMember(id, manager) {
return this.getPayload({ user_id: id }, manager, id, Partials.ThreadMember, false); return this.getPayload({ user_id: id }, manager, id, Partials.ThreadMember, false);
} }
getSoundboardSound(data, guild) {
return this.getPayload(data, guild.soundboardSounds, data.sound_id, Partials.SoundboardSound);
}
spreadInjectedData(data) {
return Object.fromEntries(Object.getOwnPropertySymbols(data).map(symbol => [symbol, data[symbol]]));
}
} }
module.exports = GenericAction; module.exports = GenericAction;

View File

@@ -43,7 +43,6 @@ class ActionsManager {
this.register(require('./GuildScheduledEventUpdate')); this.register(require('./GuildScheduledEventUpdate'));
this.register(require('./GuildScheduledEventUserAdd')); this.register(require('./GuildScheduledEventUserAdd'));
this.register(require('./GuildScheduledEventUserRemove')); this.register(require('./GuildScheduledEventUserRemove'));
this.register(require('./GuildSoundboardSoundDelete.js'));
this.register(require('./GuildStickerCreate')); this.register(require('./GuildStickerCreate'));
this.register(require('./GuildStickerDelete')); this.register(require('./GuildStickerDelete'));
this.register(require('./GuildStickerUpdate')); this.register(require('./GuildStickerUpdate'));

View File

@@ -1,29 +0,0 @@
'use strict';
const Action = require('./Action.js');
const Events = require('../../util/Events.js');
class GuildSoundboardSoundDeleteAction extends Action {
handle(data) {
const guild = this.client.guilds.cache.get(data.guild_id);
if (!guild) return {};
const soundboardSound = this.getSoundboardSound(data, guild);
if (soundboardSound) {
guild.soundboardSounds.cache.delete(soundboardSound.soundId);
/**
* Emitted whenever a soundboard sound is deleted in a guild.
* @event Client#guildSoundboardSoundDelete
* @param {SoundboardSound} soundboardSound The soundboard sound that was deleted
*/
this.client.emit(Events.GuildSoundboardSoundDelete, soundboardSound);
}
return { soundboardSound };
}
}
module.exports = GuildSoundboardSoundDeleteAction;

View File

@@ -9,7 +9,6 @@ const ChatInputCommandInteraction = require('../../structures/ChatInputCommandIn
const MentionableSelectMenuInteraction = require('../../structures/MentionableSelectMenuInteraction'); const MentionableSelectMenuInteraction = require('../../structures/MentionableSelectMenuInteraction');
const MessageContextMenuCommandInteraction = require('../../structures/MessageContextMenuCommandInteraction'); const MessageContextMenuCommandInteraction = require('../../structures/MessageContextMenuCommandInteraction');
const ModalSubmitInteraction = require('../../structures/ModalSubmitInteraction'); const ModalSubmitInteraction = require('../../structures/ModalSubmitInteraction');
const PrimaryEntryPointCommandInteraction = require('../../structures/PrimaryEntryPointCommandInteraction');
const RoleSelectMenuInteraction = require('../../structures/RoleSelectMenuInteraction'); const RoleSelectMenuInteraction = require('../../structures/RoleSelectMenuInteraction');
const StringSelectMenuInteraction = require('../../structures/StringSelectMenuInteraction'); const StringSelectMenuInteraction = require('../../structures/StringSelectMenuInteraction');
const UserContextMenuCommandInteraction = require('../../structures/UserContextMenuCommandInteraction'); const UserContextMenuCommandInteraction = require('../../structures/UserContextMenuCommandInteraction');
@@ -39,9 +38,6 @@ class InteractionCreateAction extends Action {
if (channel && !channel.isTextBased()) return; if (channel && !channel.isTextBased()) return;
InteractionClass = MessageContextMenuCommandInteraction; InteractionClass = MessageContextMenuCommandInteraction;
break; break;
case ApplicationCommandType.PrimaryEntryPoint:
InteractionClass = PrimaryEntryPointCommandInteraction;
break;
default: default:
client.emit( client.emit(
Events.Debug, Events.Debug,

View File

@@ -6,11 +6,7 @@ const Events = require('../../util/Events');
class MessageCreateAction extends Action { class MessageCreateAction extends Action {
handle(data) { handle(data) {
const client = this.client; const client = this.client;
const channel = this.getChannel({ const channel = this.getChannel({ id: data.channel_id, guild_id: data.guild_id, author: data.author });
id: data.channel_id,
author: data.author,
...('guild_id' in data && { guild_id: data.guild_id }),
});
if (channel) { if (channel) {
if (!channel.isTextBased()) return {}; if (!channel.isTextBased()) return {};

View File

@@ -6,7 +6,7 @@ const Events = require('../../util/Events');
class MessageDeleteAction extends Action { class MessageDeleteAction extends Action {
handle(data) { handle(data) {
const client = this.client; const client = this.client;
const channel = this.getChannel({ id: data.channel_id, ...('guild_id' in data && { guild_id: data.guild_id }) }); const channel = this.getChannel({ id: data.channel_id, guild_id: data.guild_id });
let message; let message;
if (channel) { if (channel) {
if (!channel.isTextBased()) return {}; if (!channel.isTextBased()) return {};

View File

@@ -5,7 +5,7 @@ const Events = require('../../util/Events');
class MessagePollVoteAddAction extends Action { class MessagePollVoteAddAction extends Action {
handle(data) { handle(data) {
const channel = this.getChannel({ id: data.channel_id, ...('guild_id' in data && { guild_id: data.guild_id }) }); const channel = this.getChannel({ id: data.channel_id, guild_id: data.guild_id });
if (!channel?.isTextBased()) return false; if (!channel?.isTextBased()) return false;
const message = this.getMessage(data, channel); const message = this.getMessage(data, channel);

View File

@@ -5,7 +5,7 @@ const Events = require('../../util/Events');
class MessagePollVoteRemoveAction extends Action { class MessagePollVoteRemoveAction extends Action {
handle(data) { handle(data) {
const channel = this.getChannel({ id: data.channel_id, ...('guild_id' in data && { guild_id: data.guild_id }) }); const channel = this.getChannel({ id: data.channel_id, guild_id: data.guild_id });
if (!channel?.isTextBased()) return false; if (!channel?.isTextBased()) return false;
const message = this.getMessage(data, channel); const message = this.getMessage(data, channel);

View File

@@ -23,13 +23,7 @@ class MessageReactionAdd extends Action {
if (!user) return false; if (!user) return false;
// Verify channel // Verify channel
const channel = this.getChannel({ const channel = this.getChannel({ id: data.channel_id, guild_id: data.guild_id, user_id: data.user_id });
id: data.channel_id,
...('guild_id' in data && { guild_id: data.guild_id }),
user_id: data.user_id,
...this.spreadInjectedData(data),
});
if (!channel?.isTextBased()) return false; if (!channel?.isTextBased()) return false;
// Verify message // Verify message
@@ -51,7 +45,6 @@ class MessageReactionAdd extends Action {
/** /**
* Provides additional information about altered reaction * Provides additional information about altered reaction
* @typedef {Object} MessageReactionEventDetails * @typedef {Object} MessageReactionEventDetails
* @property {ReactionType} type The type of the reaction
* @property {boolean} burst Determines whether a super reaction was used * @property {boolean} burst Determines whether a super reaction was used
*/ */
/** /**
@@ -61,7 +54,7 @@ class MessageReactionAdd extends Action {
* @param {User} user The user that applied the guild or reaction emoji * @param {User} user The user that applied the guild or reaction emoji
* @param {MessageReactionEventDetails} details Details of adding the reaction * @param {MessageReactionEventDetails} details Details of adding the reaction
*/ */
this.client.emit(Events.MessageReactionAdd, reaction, user, { type: data.type, burst: data.burst }); this.client.emit(Events.MessageReactionAdd, reaction, user, { burst: data.burst });
return { message, reaction, user }; return { message, reaction, user };
} }

View File

@@ -19,11 +19,7 @@ class MessageReactionRemove extends Action {
if (!user) return false; if (!user) return false;
// Verify channel // Verify channel
const channel = this.getChannel({ const channel = this.getChannel({ id: data.channel_id, guild_id: data.guild_id, user_id: data.user_id });
id: data.channel_id,
...('guild_id' in data && { guild_id: data.guild_id }),
user_id: data.user_id,
});
if (!channel?.isTextBased()) return false; if (!channel?.isTextBased()) return false;
// Verify message // Verify message
@@ -41,7 +37,7 @@ class MessageReactionRemove extends Action {
* @param {User} user The user whose emoji or reaction emoji was removed * @param {User} user The user whose emoji or reaction emoji was removed
* @param {MessageReactionEventDetails} details Details of removing the reaction * @param {MessageReactionEventDetails} details Details of removing the reaction
*/ */
this.client.emit(Events.MessageReactionRemove, reaction, user, { type: data.type, burst: data.burst }); this.client.emit(Events.MessageReactionRemove, reaction, user, { burst: data.burst });
return { message, reaction, user }; return { message, reaction, user };
} }

View File

@@ -6,7 +6,7 @@ const Events = require('../../util/Events');
class MessageReactionRemoveAll extends Action { class MessageReactionRemoveAll extends Action {
handle(data) { handle(data) {
// Verify channel // Verify channel
const channel = this.getChannel({ id: data.channel_id, ...('guild_id' in data && { guild_id: data.guild_id }) }); const channel = this.getChannel({ id: data.channel_id, guild_id: data.guild_id });
if (!channel?.isTextBased()) return false; if (!channel?.isTextBased()) return false;
// Verify message // Verify message

View File

@@ -5,7 +5,7 @@ const Events = require('../../util/Events');
class MessageReactionRemoveEmoji extends Action { class MessageReactionRemoveEmoji extends Action {
handle(data) { handle(data) {
const channel = this.getChannel({ id: data.channel_id, ...('guild_id' in data && { guild_id: data.guild_id }) }); const channel = this.getChannel({ id: data.channel_id, guild_id: data.guild_id });
if (!channel?.isTextBased()) return false; if (!channel?.isTextBased()) return false;
const message = this.getMessage(data, channel); const message = this.getMessage(data, channel);

View File

@@ -4,7 +4,7 @@ const Action = require('./Action');
class MessageUpdateAction extends Action { class MessageUpdateAction extends Action {
handle(data) { handle(data) {
const channel = this.getChannel({ id: data.channel_id, ...('guild_id' in data && { guild_id: data.guild_id }) }); const channel = this.getChannel({ id: data.channel_id, guild_id: data.guild_id });
if (channel) { if (channel) {
if (!channel.isTextBased()) return {}; if (!channel.isTextBased()) return {};

View File

@@ -2,14 +2,11 @@
const Action = require('./Action'); const Action = require('./Action');
const Events = require('../../util/Events'); const Events = require('../../util/Events');
const Partials = require('../../util/Partials');
class PresenceUpdateAction extends Action { class PresenceUpdateAction extends Action {
handle(data) { handle(data) {
let user = this.client.users.cache.get(data.user.id); let user = this.client.users.cache.get(data.user.id);
if (!user && ('username' in data.user || this.client.options.partials.includes(Partials.User))) { if (!user && data.user.username) user = this.client.users._add(data.user);
user = this.client.users._add(data.user);
}
if (!user) return; if (!user) return;
if (data.user.username) { if (data.user.username) {

View File

@@ -13,7 +13,7 @@ class ThreadListSyncAction extends Action {
if (data.channel_ids) { if (data.channel_ids) {
for (const id of data.channel_ids) { for (const id of data.channel_ids) {
const channel = client.channels.cache.get(id); const channel = client.channels.resolve(id);
if (channel) this.removeStale(channel); if (channel) this.removeStale(channel);
} }
} else { } else {

View File

@@ -6,7 +6,7 @@ const Events = require('../../util/Events');
class TypingStart extends Action { class TypingStart extends Action {
handle(data) { handle(data) {
const channel = this.getChannel({ id: data.channel_id, ...('guild_id' in data && { guild_id: data.guild_id }) }); const channel = this.getChannel({ id: data.channel_id, guild_id: data.guild_id });
if (!channel) return; if (!channel) return;
if (!channel.isTextBased()) { if (!channel.isTextBased()) {

View File

@@ -19,7 +19,6 @@ const Status = require('../../util/Status');
const WebSocketShardEvents = require('../../util/WebSocketShardEvents'); const WebSocketShardEvents = require('../../util/WebSocketShardEvents');
let zlib; let zlib;
let deprecationEmitted = false;
try { try {
zlib = require('zlib-sync'); zlib = require('zlib-sync');
@@ -37,13 +36,10 @@ const BeforeReadyWhitelist = [
const WaitingForGuildEvents = [GatewayDispatchEvents.GuildCreate, GatewayDispatchEvents.GuildDelete]; const WaitingForGuildEvents = [GatewayDispatchEvents.GuildCreate, GatewayDispatchEvents.GuildDelete];
const UNRECOVERABLE_CLOSE_CODES = [ const UNRESUMABLE_CLOSE_CODES = [
GatewayCloseCodes.AuthenticationFailed, CloseCodes.Normal,
GatewayCloseCodes.InvalidShard, GatewayCloseCodes.AlreadyAuthenticated,
GatewayCloseCodes.ShardingRequired, GatewayCloseCodes.InvalidSeq,
GatewayCloseCodes.InvalidAPIVersion,
GatewayCloseCodes.InvalidIntents,
GatewayCloseCodes.DisallowedIntents,
]; ];
const reasonIsDeprecated = 'the reason property is deprecated, use the code property to determine the reason'; const reasonIsDeprecated = 'the reason property is deprecated, use the code property to determine the reason';
@@ -246,7 +242,7 @@ class WebSocketManager extends EventEmitter {
this._ws.on(WSWebSocketShardEvents.Closed, ({ code, shardId }) => { this._ws.on(WSWebSocketShardEvents.Closed, ({ code, shardId }) => {
const shard = this.shards.get(shardId); const shard = this.shards.get(shardId);
shard.emit(WebSocketShardEvents.Close, { code, reason: reasonIsDeprecated, wasClean: true }); shard.emit(WebSocketShardEvents.Close, { code, reason: reasonIsDeprecated, wasClean: true });
if (UNRECOVERABLE_CLOSE_CODES.includes(code)) { if (UNRESUMABLE_CLOSE_CODES.includes(code) && this.destroyed) {
shard.status = Status.Disconnected; shard.status = Status.Disconnected;
/** /**
* Emitted when a shard's WebSocket disconnects and will no longer reconnect. * Emitted when a shard's WebSocket disconnects and will no longer reconnect.
@@ -255,7 +251,7 @@ class WebSocketManager extends EventEmitter {
* @param {number} id The shard id that disconnected * @param {number} id The shard id that disconnected
*/ */
this.client.emit(Events.ShardDisconnect, { code, reason: reasonIsDeprecated, wasClean: true }, shardId); this.client.emit(Events.ShardDisconnect, { code, reason: reasonIsDeprecated, wasClean: true }, shardId);
this.debug([`Shard not recoverable: ${code} (${GatewayCloseCodes[code] ?? CloseCodes[code]})`], shardId); this.debug([`Shard not resumable: ${code} (${GatewayCloseCodes[code] ?? CloseCodes[code]})`], shardId);
return; return;
} }
@@ -380,22 +376,6 @@ class WebSocketManager extends EventEmitter {
/** /**
* Emitted when the client becomes ready to start working. * Emitted when the client becomes ready to start working.
* @event Client#ready * @event Client#ready
* @deprecated Use {@link Client#event:clientReady} instead.
* @param {Client} client The client
*/
if (this.client.emit('ready', this.client) && !deprecationEmitted) {
deprecationEmitted = true;
process.emitWarning(
// eslint-disable-next-line max-len
'The ready event has been renamed to clientReady to distinguish it from the gateway READY event and will only emit under that name in v15. Please use clientReady instead.',
'DeprecationWarning',
);
}
/**
* Emitted when the client becomes ready to start working.
* @event Client#clientReady
* @param {Client} client The client * @param {Client} client The client
*/ */
this.client.emit(Events.ClientReady, this.client); this.client.emit(Events.ClientReady, this.client);

View File

@@ -1,24 +0,0 @@
'use strict';
const { Collection } = require('@discordjs/collection');
const Events = require('../../../util/Events.js');
module.exports = (client, { d: data }) => {
const guild = client.guilds.cache.get(data.guild_id);
if (!guild) return;
const soundboardSounds = new Collection();
for (const soundboardSound of data.soundboard_sounds) {
soundboardSounds.set(soundboardSound.sound_id, guild.soundboardSounds._add(soundboardSound));
}
/**
* Emitted whenever multiple guild soundboard sounds are updated.
* @event Client#guildSoundboardSoundsUpdate
* @param {Collection<Snowflake, SoundboardSound>} soundboardSounds The updated soundboard sounds
* @param {Guild} guild The guild that the soundboard sounds are from
*/
client.emit(Events.GuildSoundboardSoundsUpdate, soundboardSounds, guild);
};

View File

@@ -1,18 +0,0 @@
'use strict';
const Events = require('../../../util/Events.js');
module.exports = (client, { d: data }) => {
const guild = client.guilds.cache.get(data.guild_id);
if (!guild) return;
const soundboardSound = guild.soundboardSounds._add(data);
/**
* Emitted whenever a guild soundboard sound is created.
* @event Client#guildSoundboardSoundCreate
* @param {SoundboardSound} soundboardSound The created guild soundboard sound
*/
client.emit(Events.GuildSoundboardSoundCreate, soundboardSound);
};

View File

@@ -1,5 +0,0 @@
'use strict';
module.exports = (client, { d: data }) => {
client.actions.GuildSoundboardSoundDelete.handle(data);
};

View File

@@ -1,20 +0,0 @@
'use strict';
const Events = require('../../../util/Events.js');
module.exports = (client, { d: data }) => {
const guild = client.guilds.cache.get(data.guild_id);
if (!guild) return;
const oldGuildSoundboardSound = guild.soundboardSounds.cache.get(data.sound_id)?._clone() ?? null;
const newGuildSoundboardSound = guild.soundboardSounds._add(data);
/**
* Emitted whenever a guild soundboard sound is updated.
* @event Client#guildSoundboardSoundUpdate
* @param {?SoundboardSound} oldGuildSoundboardSound The guild soundboard sound before the update
* @param {SoundboardSound} newGuildSoundboardSound The guild soundboard sound after the update
*/
client.emit(Events.GuildSoundboardSoundUpdate, oldGuildSoundboardSound, newGuildSoundboardSound);
};

View File

@@ -1,24 +0,0 @@
'use strict';
const { Collection } = require('@discordjs/collection');
const Events = require('../../../util/Events.js');
module.exports = (client, { d: data }) => {
const guild = client.guilds.cache.get(data.guild_id);
if (!guild) return;
const soundboardSounds = new Collection();
for (const soundboardSound of data.soundboard_sounds) {
soundboardSounds.set(soundboardSound.sound_id, guild.soundboardSounds._add(soundboardSound));
}
/**
* Emitted whenever soundboard sounds are received (all soundboard sounds come from the same guild).
* @event Client#soundboardSounds
* @param {Collection<Snowflake, SoundboardSound>} soundboardSounds The sounds received
* @param {Guild} guild The guild that the soundboard sounds are from
*/
client.emit(Events.SoundboardSounds, soundboardSounds, guild);
};

View File

@@ -1,14 +0,0 @@
'use strict';
const Events = require('../../../util/Events');
module.exports = (client, { d: data }) => {
const subscription = client.application.subscriptions._add(data);
/**
* Emitted whenever a subscription is created.
* @event Client#subscriptionCreate
* @param {Subscription} subscription The subscription that was created
*/
client.emit(Events.SubscriptionCreate, subscription);
};

View File

@@ -1,16 +0,0 @@
'use strict';
const Events = require('../../../util/Events');
module.exports = (client, { d: data }) => {
const subscription = client.application.subscriptions._add(data, false);
client.application.subscriptions.cache.delete(subscription.id);
/**
* Emitted whenever a subscription is deleted.
* @event Client#subscriptionDelete
* @param {Subscription} subscription The subscription that was deleted
*/
client.emit(Events.SubscriptionDelete, subscription);
};

View File

@@ -1,16 +0,0 @@
'use strict';
const Events = require('../../../util/Events');
module.exports = (client, { d: data }) => {
const oldSubscription = client.application.subscriptions.cache.get(data.id)?._clone() ?? null;
const newSubscription = client.application.subscriptions._add(data);
/**
* Emitted whenever a subscription is updated - i.e. when a user's subscription renews.
* @event Client#subscriptionUpdate
* @param {?Subscription} oldSubscription The subscription before the update
* @param {Subscription} newSubscription The subscription after the update
*/
client.emit(Events.SubscriptionUpdate, oldSubscription, newSubscription);
};

View File

@@ -1,16 +0,0 @@
'use strict';
const VoiceChannelEffect = require('../../../structures/VoiceChannelEffect');
const Events = require('../../../util/Events');
module.exports = (client, { d: data }) => {
const guild = client.guilds.cache.get(data.guild_id);
if (!guild) return;
/**
* Emitted when someone sends an effect, such as an emoji reaction, in a voice channel the client is connected to.
* @event Client#voiceChannelEffectSend
* @param {VoiceChannelEffect} voiceChannelEffect The sent voice channel effect
*/
client.emit(Events.VoiceChannelEffectSend, new VoiceChannelEffect(data, guild));
};

View File

@@ -32,10 +32,6 @@ const handlers = Object.fromEntries([
['GUILD_SCHEDULED_EVENT_UPDATE', require('./GUILD_SCHEDULED_EVENT_UPDATE')], ['GUILD_SCHEDULED_EVENT_UPDATE', require('./GUILD_SCHEDULED_EVENT_UPDATE')],
['GUILD_SCHEDULED_EVENT_USER_ADD', require('./GUILD_SCHEDULED_EVENT_USER_ADD')], ['GUILD_SCHEDULED_EVENT_USER_ADD', require('./GUILD_SCHEDULED_EVENT_USER_ADD')],
['GUILD_SCHEDULED_EVENT_USER_REMOVE', require('./GUILD_SCHEDULED_EVENT_USER_REMOVE')], ['GUILD_SCHEDULED_EVENT_USER_REMOVE', require('./GUILD_SCHEDULED_EVENT_USER_REMOVE')],
['GUILD_SOUNDBOARD_SOUNDS_UPDATE', require('./GUILD_SOUNDBOARD_SOUNDS_UPDATE.js')],
['GUILD_SOUNDBOARD_SOUND_CREATE', require('./GUILD_SOUNDBOARD_SOUND_CREATE.js')],
['GUILD_SOUNDBOARD_SOUND_DELETE', require('./GUILD_SOUNDBOARD_SOUND_DELETE.js')],
['GUILD_SOUNDBOARD_SOUND_UPDATE', require('./GUILD_SOUNDBOARD_SOUND_UPDATE.js')],
['GUILD_STICKERS_UPDATE', require('./GUILD_STICKERS_UPDATE')], ['GUILD_STICKERS_UPDATE', require('./GUILD_STICKERS_UPDATE')],
['GUILD_UPDATE', require('./GUILD_UPDATE')], ['GUILD_UPDATE', require('./GUILD_UPDATE')],
['INTERACTION_CREATE', require('./INTERACTION_CREATE')], ['INTERACTION_CREATE', require('./INTERACTION_CREATE')],
@@ -54,13 +50,9 @@ const handlers = Object.fromEntries([
['PRESENCE_UPDATE', require('./PRESENCE_UPDATE')], ['PRESENCE_UPDATE', require('./PRESENCE_UPDATE')],
['READY', require('./READY')], ['READY', require('./READY')],
['RESUMED', require('./RESUMED')], ['RESUMED', require('./RESUMED')],
['SOUNDBOARD_SOUNDS', require('./SOUNDBOARD_SOUNDS.js')],
['STAGE_INSTANCE_CREATE', require('./STAGE_INSTANCE_CREATE')], ['STAGE_INSTANCE_CREATE', require('./STAGE_INSTANCE_CREATE')],
['STAGE_INSTANCE_DELETE', require('./STAGE_INSTANCE_DELETE')], ['STAGE_INSTANCE_DELETE', require('./STAGE_INSTANCE_DELETE')],
['STAGE_INSTANCE_UPDATE', require('./STAGE_INSTANCE_UPDATE')], ['STAGE_INSTANCE_UPDATE', require('./STAGE_INSTANCE_UPDATE')],
['SUBSCRIPTION_CREATE', require('./SUBSCRIPTION_CREATE')],
['SUBSCRIPTION_DELETE', require('./SUBSCRIPTION_DELETE')],
['SUBSCRIPTION_UPDATE', require('./SUBSCRIPTION_UPDATE')],
['THREAD_CREATE', require('./THREAD_CREATE')], ['THREAD_CREATE', require('./THREAD_CREATE')],
['THREAD_DELETE', require('./THREAD_DELETE')], ['THREAD_DELETE', require('./THREAD_DELETE')],
['THREAD_LIST_SYNC', require('./THREAD_LIST_SYNC')], ['THREAD_LIST_SYNC', require('./THREAD_LIST_SYNC')],
@@ -69,7 +61,6 @@ const handlers = Object.fromEntries([
['THREAD_UPDATE', require('./THREAD_UPDATE')], ['THREAD_UPDATE', require('./THREAD_UPDATE')],
['TYPING_START', require('./TYPING_START')], ['TYPING_START', require('./TYPING_START')],
['USER_UPDATE', require('./USER_UPDATE')], ['USER_UPDATE', require('./USER_UPDATE')],
['VOICE_CHANNEL_EFFECT_SEND', require('./VOICE_CHANNEL_EFFECT_SEND')],
['VOICE_SERVER_UPDATE', require('./VOICE_SERVER_UPDATE')], ['VOICE_SERVER_UPDATE', require('./VOICE_SERVER_UPDATE')],
['VOICE_STATE_UPDATE', require('./VOICE_STATE_UPDATE')], ['VOICE_STATE_UPDATE', require('./VOICE_STATE_UPDATE')],
['WEBHOOKS_UPDATE', require('./WEBHOOKS_UPDATE')], ['WEBHOOKS_UPDATE', require('./WEBHOOKS_UPDATE')],

View File

@@ -106,7 +106,6 @@
* @property {'GuildChannelUnowned'} GuildChannelUnowned * @property {'GuildChannelUnowned'} GuildChannelUnowned
* @property {'GuildOwned'} GuildOwned * @property {'GuildOwned'} GuildOwned
* @property {'GuildMembersTimeout'} GuildMembersTimeout * @property {'GuildMembersTimeout'} GuildMembersTimeout
* @property {'GuildSoundboardSoundsTimeout'} GuildSoundboardSoundsTimeout
* @property {'GuildUncachedMe'} GuildUncachedMe * @property {'GuildUncachedMe'} GuildUncachedMe
* @property {'ChannelNotCached'} ChannelNotCached * @property {'ChannelNotCached'} ChannelNotCached
* @property {'StageChannelResolve'} StageChannelResolve * @property {'StageChannelResolve'} StageChannelResolve
@@ -132,8 +131,6 @@
* @property {'MissingManageEmojisAndStickersPermission'} MissingManageEmojisAndStickersPermission * @property {'MissingManageEmojisAndStickersPermission'} MissingManageEmojisAndStickersPermission
* <warn>This property is deprecated. Use `MissingManageGuildExpressionsPermission` instead.</warn> * <warn>This property is deprecated. Use `MissingManageGuildExpressionsPermission` instead.</warn>
* *
* @property {'NotGuildSoundboardSound'} NotGuildSoundboardSound
* @property {'NotGuildSticker'} NotGuildSticker * @property {'NotGuildSticker'} NotGuildSticker
* @property {'ReactionResolveUser'} ReactionResolveUser * @property {'ReactionResolveUser'} ReactionResolveUser
@@ -269,7 +266,6 @@ const keys = [
'GuildChannelUnowned', 'GuildChannelUnowned',
'GuildOwned', 'GuildOwned',
'GuildMembersTimeout', 'GuildMembersTimeout',
'GuildSoundboardSoundsTimeout',
'GuildUncachedMe', 'GuildUncachedMe',
'ChannelNotCached', 'ChannelNotCached',
'StageChannelResolve', 'StageChannelResolve',
@@ -294,7 +290,6 @@ const keys = [
'MissingManageGuildExpressionsPermission', 'MissingManageGuildExpressionsPermission',
'MissingManageEmojisAndStickersPermission', 'MissingManageEmojisAndStickersPermission',
'NotGuildSoundboardSound',
'NotGuildSticker', 'NotGuildSticker',
'ReactionResolveUser', 'ReactionResolveUser',

View File

@@ -91,13 +91,11 @@ const Messages = {
[DjsErrorCodes.GuildChannelUnowned]: "The fetched channel does not belong to this manager's guild.", [DjsErrorCodes.GuildChannelUnowned]: "The fetched channel does not belong to this manager's guild.",
[DjsErrorCodes.GuildOwned]: 'Guild is owned by the client.', [DjsErrorCodes.GuildOwned]: 'Guild is owned by the client.',
[DjsErrorCodes.GuildMembersTimeout]: "Members didn't arrive in time.", [DjsErrorCodes.GuildMembersTimeout]: "Members didn't arrive in time.",
[DjsErrorCodes.GuildSoundboardSoundsTimeout]: "Soundboard sounds didn't arrive in time.",
[DjsErrorCodes.GuildUncachedMe]: 'The client user as a member of this guild is uncached.', [DjsErrorCodes.GuildUncachedMe]: 'The client user as a member of this guild is uncached.',
[DjsErrorCodes.ChannelNotCached]: 'Could not find the channel where this message came from in the cache!', [DjsErrorCodes.ChannelNotCached]: 'Could not find the channel where this message came from in the cache!',
[DjsErrorCodes.StageChannelResolve]: 'Could not resolve channel to a stage channel.', [DjsErrorCodes.StageChannelResolve]: 'Could not resolve channel to a stage channel.',
[DjsErrorCodes.GuildScheduledEventResolve]: 'Could not resolve the guild scheduled event.', [DjsErrorCodes.GuildScheduledEventResolve]: 'Could not resolve the guild scheduled event.',
[DjsErrorCodes.FetchOwnerId]: type => [DjsErrorCodes.FetchOwnerId]: type => `Couldn't resolve the ${type} ownerId to fetch the ${type} member.`,
`Couldn't resolve the ${type} ownerId to fetch the ${type} ${type === 'group DM' ? 'owner' : 'member'}.`,
[DjsErrorCodes.InvalidType]: (name, expected, an = false) => `Supplied ${name} is not a${an ? 'n' : ''} ${expected}.`, [DjsErrorCodes.InvalidType]: (name, expected, an = false) => `Supplied ${name} is not a${an ? 'n' : ''} ${expected}.`,
[DjsErrorCodes.InvalidElement]: (type, name, elem) => `Supplied ${type} ${name} includes an invalid element: ${elem}`, [DjsErrorCodes.InvalidElement]: (type, name, elem) => `Supplied ${type} ${name} includes an invalid element: ${elem}`,
@@ -119,8 +117,6 @@ const Messages = {
[DjsErrorCodes.MissingManageEmojisAndStickersPermission]: guild => [DjsErrorCodes.MissingManageEmojisAndStickersPermission]: guild =>
`Client must have Manage Emojis and Stickers permission in guild ${guild} to see emoji authors.`, `Client must have Manage Emojis and Stickers permission in guild ${guild} to see emoji authors.`,
[DjsErrorCodes.NotGuildSoundboardSound]: action =>
`Soundboard sound is a default (non-guild) soundboard sound and can't be ${action}.`,
[DjsErrorCodes.NotGuildSticker]: 'Sticker is a standard (non-guild) sticker and has no author.', [DjsErrorCodes.NotGuildSticker]: 'Sticker is a standard (non-guild) sticker and has no author.',
[DjsErrorCodes.ReactionResolveUser]: "Couldn't resolve the user id to remove from the reaction.", [DjsErrorCodes.ReactionResolveUser]: "Couldn't resolve the user id to remove from the reaction.",

View File

@@ -29,6 +29,7 @@ exports.ChannelFlagsBitField = require('./util/ChannelFlagsBitField');
exports.Collection = require('@discordjs/collection').Collection; exports.Collection = require('@discordjs/collection').Collection;
exports.Constants = require('./util/Constants'); exports.Constants = require('./util/Constants');
exports.Colors = require('./util/Colors'); exports.Colors = require('./util/Colors');
__exportStar(require('./util/DataResolver.js'), exports);
exports.Events = require('./util/Events'); exports.Events = require('./util/Events');
exports.Formatters = require('./util/Formatters'); exports.Formatters = require('./util/Formatters');
exports.GuildMemberFlagsBitField = require('./util/GuildMemberFlagsBitField').GuildMemberFlagsBitField; exports.GuildMemberFlagsBitField = require('./util/GuildMemberFlagsBitField').GuildMemberFlagsBitField;
@@ -75,7 +76,6 @@ exports.GuildMemberManager = require('./managers/GuildMemberManager');
exports.GuildMemberRoleManager = require('./managers/GuildMemberRoleManager'); exports.GuildMemberRoleManager = require('./managers/GuildMemberRoleManager');
exports.GuildMessageManager = require('./managers/GuildMessageManager'); exports.GuildMessageManager = require('./managers/GuildMessageManager');
exports.GuildScheduledEventManager = require('./managers/GuildScheduledEventManager'); exports.GuildScheduledEventManager = require('./managers/GuildScheduledEventManager');
exports.GuildSoundboardSoundManager = require('./managers/GuildSoundboardSoundManager.js').GuildSoundboardSoundManager;
exports.GuildStickerManager = require('./managers/GuildStickerManager'); exports.GuildStickerManager = require('./managers/GuildStickerManager');
exports.GuildTextThreadManager = require('./managers/GuildTextThreadManager'); exports.GuildTextThreadManager = require('./managers/GuildTextThreadManager');
exports.MessageManager = require('./managers/MessageManager'); exports.MessageManager = require('./managers/MessageManager');
@@ -85,7 +85,6 @@ exports.ReactionManager = require('./managers/ReactionManager');
exports.ReactionUserManager = require('./managers/ReactionUserManager'); exports.ReactionUserManager = require('./managers/ReactionUserManager');
exports.RoleManager = require('./managers/RoleManager'); exports.RoleManager = require('./managers/RoleManager');
exports.StageInstanceManager = require('./managers/StageInstanceManager'); exports.StageInstanceManager = require('./managers/StageInstanceManager');
exports.SubscriptionManager = require('./managers/SubscriptionManager').SubscriptionManager;
exports.ThreadManager = require('./managers/ThreadManager'); exports.ThreadManager = require('./managers/ThreadManager');
exports.ThreadMemberManager = require('./managers/ThreadMemberManager'); exports.ThreadMemberManager = require('./managers/ThreadMemberManager');
exports.UserManager = require('./managers/UserManager'); exports.UserManager = require('./managers/UserManager');
@@ -124,15 +123,12 @@ exports.CommandInteraction = require('./structures/CommandInteraction');
exports.Collector = require('./structures/interfaces/Collector'); exports.Collector = require('./structures/interfaces/Collector');
exports.CommandInteractionOptionResolver = require('./structures/CommandInteractionOptionResolver'); exports.CommandInteractionOptionResolver = require('./structures/CommandInteractionOptionResolver');
exports.Component = require('./structures/Component'); exports.Component = require('./structures/Component');
exports.ContainerComponent = require('./structures/ContainerComponent');
exports.ContextMenuCommandInteraction = require('./structures/ContextMenuCommandInteraction'); exports.ContextMenuCommandInteraction = require('./structures/ContextMenuCommandInteraction');
exports.DirectoryChannel = require('./structures/DirectoryChannel');
exports.DMChannel = require('./structures/DMChannel'); exports.DMChannel = require('./structures/DMChannel');
exports.Embed = require('./structures/Embed'); exports.Embed = require('./structures/Embed');
exports.EmbedBuilder = require('./structures/EmbedBuilder'); exports.EmbedBuilder = require('./structures/EmbedBuilder');
exports.Emoji = require('./structures/Emoji').Emoji; exports.Emoji = require('./structures/Emoji').Emoji;
exports.Entitlement = require('./structures/Entitlement').Entitlement; exports.Entitlement = require('./structures/Entitlement').Entitlement;
exports.FileComponent = require('./structures/FileComponent');
exports.ForumChannel = require('./structures/ForumChannel'); exports.ForumChannel = require('./structures/ForumChannel');
exports.Guild = require('./structures/Guild').Guild; exports.Guild = require('./structures/Guild').Guild;
exports.GuildAuditLogs = require('./structures/GuildAuditLogs'); exports.GuildAuditLogs = require('./structures/GuildAuditLogs');
@@ -150,9 +146,6 @@ exports.GuildScheduledEvent = require('./structures/GuildScheduledEvent').GuildS
exports.GuildTemplate = require('./structures/GuildTemplate'); exports.GuildTemplate = require('./structures/GuildTemplate');
exports.Integration = require('./structures/Integration'); exports.Integration = require('./structures/Integration');
exports.IntegrationApplication = require('./structures/IntegrationApplication'); exports.IntegrationApplication = require('./structures/IntegrationApplication');
exports.InteractionCallback = require('./structures/InteractionCallback');
exports.InteractionCallbackResource = require('./structures/InteractionCallbackResource');
exports.InteractionCallbackResponse = require('./structures/InteractionCallbackResponse');
exports.BaseInteraction = require('./structures/BaseInteraction'); exports.BaseInteraction = require('./structures/BaseInteraction');
exports.InteractionCollector = require('./structures/InteractionCollector'); exports.InteractionCollector = require('./structures/InteractionCollector');
exports.InteractionResponse = require('./structures/InteractionResponse'); exports.InteractionResponse = require('./structures/InteractionResponse');
@@ -165,8 +158,6 @@ exports.Attachment = require('./structures/Attachment');
exports.AttachmentBuilder = require('./structures/AttachmentBuilder'); exports.AttachmentBuilder = require('./structures/AttachmentBuilder');
exports.ModalBuilder = require('./structures/ModalBuilder'); exports.ModalBuilder = require('./structures/ModalBuilder');
exports.MediaChannel = require('./structures/MediaChannel'); exports.MediaChannel = require('./structures/MediaChannel');
exports.MediaGalleryComponent = require('./structures/MediaGalleryComponent');
exports.MediaGalleryItem = require('./structures/MediaGalleryItem');
exports.MessageCollector = require('./structures/MessageCollector'); exports.MessageCollector = require('./structures/MessageCollector');
exports.MessageComponentInteraction = require('./structures/MessageComponentInteraction'); exports.MessageComponentInteraction = require('./structures/MessageComponentInteraction');
exports.MessageContextMenuCommandInteraction = require('./structures/MessageContextMenuCommandInteraction'); exports.MessageContextMenuCommandInteraction = require('./structures/MessageContextMenuCommandInteraction');
@@ -181,13 +172,11 @@ exports.PartialGroupDMChannel = require('./structures/PartialGroupDMChannel');
exports.PermissionOverwrites = require('./structures/PermissionOverwrites'); exports.PermissionOverwrites = require('./structures/PermissionOverwrites');
exports.Poll = require('./structures/Poll').Poll; exports.Poll = require('./structures/Poll').Poll;
exports.PollAnswer = require('./structures/PollAnswer').PollAnswer; exports.PollAnswer = require('./structures/PollAnswer').PollAnswer;
exports.PrimaryEntryPointCommandInteraction = require('./structures/PrimaryEntryPointCommandInteraction');
exports.Presence = require('./structures/Presence').Presence; exports.Presence = require('./structures/Presence').Presence;
exports.ReactionCollector = require('./structures/ReactionCollector'); exports.ReactionCollector = require('./structures/ReactionCollector');
exports.ReactionEmoji = require('./structures/ReactionEmoji'); exports.ReactionEmoji = require('./structures/ReactionEmoji');
exports.RichPresenceAssets = require('./structures/Presence').RichPresenceAssets; exports.RichPresenceAssets = require('./structures/Presence').RichPresenceAssets;
exports.Role = require('./structures/Role').Role; exports.Role = require('./structures/Role').Role;
exports.SectionComponent = require('./structures/SectionComponent');
exports.SelectMenuBuilder = require('./structures/SelectMenuBuilder'); exports.SelectMenuBuilder = require('./structures/SelectMenuBuilder');
exports.ChannelSelectMenuBuilder = require('./structures/ChannelSelectMenuBuilder'); exports.ChannelSelectMenuBuilder = require('./structures/ChannelSelectMenuBuilder');
exports.MentionableSelectMenuBuilder = require('./structures/MentionableSelectMenuBuilder'); exports.MentionableSelectMenuBuilder = require('./structures/MentionableSelectMenuBuilder');
@@ -209,30 +198,23 @@ exports.RoleSelectMenuInteraction = require('./structures/RoleSelectMenuInteract
exports.StringSelectMenuInteraction = require('./structures/StringSelectMenuInteraction'); exports.StringSelectMenuInteraction = require('./structures/StringSelectMenuInteraction');
exports.UserSelectMenuInteraction = require('./structures/UserSelectMenuInteraction'); exports.UserSelectMenuInteraction = require('./structures/UserSelectMenuInteraction');
exports.SelectMenuOptionBuilder = require('./structures/SelectMenuOptionBuilder'); exports.SelectMenuOptionBuilder = require('./structures/SelectMenuOptionBuilder');
exports.SeparatorComponent = require('./structures/SeparatorComponent');
exports.SKU = require('./structures/SKU').SKU; exports.SKU = require('./structures/SKU').SKU;
exports.SoundboardSound = require('./structures/SoundboardSound.js').SoundboardSound;
exports.StringSelectMenuOptionBuilder = require('./structures/StringSelectMenuOptionBuilder'); exports.StringSelectMenuOptionBuilder = require('./structures/StringSelectMenuOptionBuilder');
exports.StageChannel = require('./structures/StageChannel'); exports.StageChannel = require('./structures/StageChannel');
exports.StageInstance = require('./structures/StageInstance').StageInstance; exports.StageInstance = require('./structures/StageInstance').StageInstance;
exports.Subscription = require('./structures/Subscription').Subscription;
exports.Sticker = require('./structures/Sticker').Sticker; exports.Sticker = require('./structures/Sticker').Sticker;
exports.StickerPack = require('./structures/StickerPack'); exports.StickerPack = require('./structures/StickerPack');
exports.Team = require('./structures/Team'); exports.Team = require('./structures/Team');
exports.TeamMember = require('./structures/TeamMember'); exports.TeamMember = require('./structures/TeamMember');
exports.TextChannel = require('./structures/TextChannel'); exports.TextChannel = require('./structures/TextChannel');
exports.TextDisplayComponent = require('./structures/TextDisplayComponent');
exports.TextInputBuilder = require('./structures/TextInputBuilder'); exports.TextInputBuilder = require('./structures/TextInputBuilder');
exports.TextInputComponent = require('./structures/TextInputComponent'); exports.TextInputComponent = require('./structures/TextInputComponent');
exports.ThreadChannel = require('./structures/ThreadChannel'); exports.ThreadChannel = require('./structures/ThreadChannel');
exports.ThreadMember = require('./structures/ThreadMember'); exports.ThreadMember = require('./structures/ThreadMember');
exports.ThreadOnlyChannel = require('./structures/ThreadOnlyChannel'); exports.ThreadOnlyChannel = require('./structures/ThreadOnlyChannel');
exports.ThumbnailComponent = require('./structures/ThumbnailComponent');
exports.Typing = require('./structures/Typing'); exports.Typing = require('./structures/Typing');
exports.UnfurledMediaItem = require('./structures/UnfurledMediaItem');
exports.User = require('./structures/User'); exports.User = require('./structures/User');
exports.UserContextMenuCommandInteraction = require('./structures/UserContextMenuCommandInteraction'); exports.UserContextMenuCommandInteraction = require('./structures/UserContextMenuCommandInteraction');
exports.VoiceChannelEffect = require('./structures/VoiceChannelEffect');
exports.VoiceChannel = require('./structures/VoiceChannel'); exports.VoiceChannel = require('./structures/VoiceChannel');
exports.VoiceRegion = require('./structures/VoiceRegion'); exports.VoiceRegion = require('./structures/VoiceRegion');
exports.VoiceState = require('./structures/VoiceState'); exports.VoiceState = require('./structures/VoiceState');

View File

@@ -82,7 +82,7 @@ class ApplicationCommandManager extends CachedManager {
* Options used to fetch Application Commands from Discord * Options used to fetch Application Commands from Discord
* @typedef {BaseFetchOptions} FetchApplicationCommandOptions * @typedef {BaseFetchOptions} FetchApplicationCommandOptions
* @property {Snowflake} [guildId] The guild's id to fetch commands for, for when the guild is not cached * @property {Snowflake} [guildId] The guild's id to fetch commands for, for when the guild is not cached
* @property {Locale} [locale] The locale to use when fetching this command * @property {LocaleString} [locale] The locale to use when fetching this command
* @property {boolean} [withLocalizations] Whether to fetch all localization data * @property {boolean} [withLocalizations] Whether to fetch all localization data
*/ */
@@ -261,7 +261,6 @@ class ApplicationCommandManager extends CachedManager {
dm_permission: command.dmPermission ?? command.dm_permission, dm_permission: command.dmPermission ?? command.dm_permission,
integration_types: command.integrationTypes ?? command.integration_types, integration_types: command.integrationTypes ?? command.integration_types,
contexts: command.contexts, contexts: command.contexts,
handler: command.handler,
}; };
} }
} }

View File

@@ -65,12 +65,12 @@ class ApplicationEmojiManager extends CachedManager {
* @returns {Promise<ApplicationEmoji|Collection<Snowflake, ApplicationEmoji>>} * @returns {Promise<ApplicationEmoji|Collection<Snowflake, ApplicationEmoji>>}
* @example * @example
* // Fetch all emojis from the application * // Fetch all emojis from the application
* application.emojis.fetch() * message.application.emojis.fetch()
* .then(emojis => console.log(`There are ${emojis.size} emojis.`)) * .then(emojis => console.log(`There are ${emojis.size} emojis.`))
* .catch(console.error); * .catch(console.error);
* @example * @example
* // Fetch a single emoji * // Fetch a single emoji
* application.emojis.fetch('222078108977594368') * message.application.emojis.fetch('222078108977594368')
* .then(emoji => console.log(`The emoji name is: ${emoji.name}`)) * .then(emoji => console.log(`The emoji name is: ${emoji.name}`))
* .catch(console.error); * .catch(console.error);
*/ */

View File

@@ -1,7 +1,6 @@
'use strict'; 'use strict';
const CachedManager = require('./CachedManager'); const CachedManager = require('./CachedManager');
const ApplicationEmoji = require('../structures/ApplicationEmoji');
const GuildEmoji = require('../structures/GuildEmoji'); const GuildEmoji = require('../structures/GuildEmoji');
const ReactionEmoji = require('../structures/ReactionEmoji'); const ReactionEmoji = require('../structures/ReactionEmoji');
const { parseEmoji } = require('../util/Util'); const { parseEmoji } = require('../util/Util');
@@ -26,8 +25,7 @@ class BaseGuildEmojiManager extends CachedManager {
* * A Snowflake * * A Snowflake
* * A GuildEmoji object * * A GuildEmoji object
* * A ReactionEmoji object * * A ReactionEmoji object
* * An ApplicationEmoji object * @typedef {Snowflake|GuildEmoji|ReactionEmoji} EmojiResolvable
* @typedef {Snowflake|GuildEmoji|ReactionEmoji|ApplicationEmoji} EmojiResolvable
*/ */
/** /**
@@ -36,8 +34,7 @@ class BaseGuildEmojiManager extends CachedManager {
* @returns {?GuildEmoji} * @returns {?GuildEmoji}
*/ */
resolve(emoji) { resolve(emoji) {
if (emoji instanceof ReactionEmoji) return this.cache.get(emoji.id) ?? null; if (emoji instanceof ReactionEmoji) return super.resolve(emoji.id);
if (emoji instanceof ApplicationEmoji) return this.cache.get(emoji.id) ?? null;
return super.resolve(emoji); return super.resolve(emoji);
} }
@@ -48,7 +45,6 @@ class BaseGuildEmojiManager extends CachedManager {
*/ */
resolveId(emoji) { resolveId(emoji) {
if (emoji instanceof ReactionEmoji) return emoji.id; if (emoji instanceof ReactionEmoji) return emoji.id;
if (emoji instanceof ApplicationEmoji) return emoji.id;
return super.resolveId(emoji); return super.resolveId(emoji);
} }
@@ -69,7 +65,6 @@ class BaseGuildEmojiManager extends CachedManager {
const emojiResolvable = this.resolve(emoji); const emojiResolvable = this.resolve(emoji);
if (emojiResolvable) return emojiResolvable.identifier; if (emojiResolvable) return emojiResolvable.identifier;
if (emoji instanceof ReactionEmoji) return emoji.identifier; if (emoji instanceof ReactionEmoji) return emoji.identifier;
if (emoji instanceof ApplicationEmoji) return emoji.identifier;
if (typeof emoji === 'string') { if (typeof emoji === 'string') {
const res = parseEmoji(emoji); const res = parseEmoji(emoji);
if (res?.name.length) { if (res?.name.length) {

View File

@@ -69,13 +69,6 @@ class ChannelManager extends CachedManager {
channel?.parent?.threads?.cache.delete(id); channel?.parent?.threads?.cache.delete(id);
this.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);
}
}
} }
/** /**

View File

@@ -37,12 +37,6 @@ class EntitlementManager extends CachedManager {
* @typedef {SKU|Snowflake} SKUResolvable * @typedef {SKU|Snowflake} SKUResolvable
*/ */
/**
* Options used to fetch an entitlement
* @typedef {BaseFetchOptions} FetchEntitlementOptions
* @property {EntitlementResolvable} entitlement The entitlement to fetch
*/
/** /**
* Options used to fetch entitlements * Options used to fetch entitlements
* @typedef {Object} FetchEntitlementsOptions * @typedef {Object} FetchEntitlementsOptions
@@ -51,7 +45,6 @@ class EntitlementManager extends CachedManager {
* @property {UserResolvable} [user] The user to fetch entitlements for * @property {UserResolvable} [user] The user to fetch entitlements for
* @property {SKUResolvable[]} [skus] The SKUs to fetch entitlements for * @property {SKUResolvable[]} [skus] The SKUs to fetch entitlements for
* @property {boolean} [excludeEnded] Whether to exclude ended entitlements * @property {boolean} [excludeEnded] Whether to exclude ended entitlements
* @property {boolean} [excludeDeleted] Whether to exclude deleted entitlements
* @property {boolean} [cache=true] Whether to cache the fetched entitlements * @property {boolean} [cache=true] Whether to cache the fetched entitlements
* @property {Snowflake} [before] Consider only entitlements before this entitlement id * @property {Snowflake} [before] Consider only entitlements before this entitlement id
* @property {Snowflake} [after] Consider only entitlements after this entitlement id * @property {Snowflake} [after] Consider only entitlements after this entitlement id
@@ -60,49 +53,21 @@ class EntitlementManager extends CachedManager {
/** /**
* Fetches entitlements for this application * Fetches entitlements for this application
* @param {EntitlementResolvable|FetchEntitlementOptions|FetchEntitlementsOptions} [options] * @param {FetchEntitlementsOptions} [options={}] Options for fetching the entitlements
* Options for fetching the entitlements * @returns {Promise<Collection<Snowflake, Entitlement>>}
* @returns {Promise<Entitlement|Collection<Snowflake, Entitlement>>}
*/ */
async fetch(options) { async fetch({ limit, guild, user, skus, excludeEnded, cache = true, before, after } = {}) {
if (!options) return this._fetchMany(options);
const { entitlement, cache, force } = options;
const resolvedEntitlement = this.resolveId(entitlement ?? options);
if (resolvedEntitlement) {
return this._fetchSingle({ entitlement: resolvedEntitlement, cache, force });
}
return this._fetchMany(options);
}
async _fetchSingle({ entitlement, cache, force = false }) {
if (!force) {
const existing = this.cache.get(entitlement);
if (existing) {
return existing;
}
}
const data = await this.client.rest.get(Routes.entitlement(this.client.application.id, entitlement));
return this._add(data, cache);
}
async _fetchMany({ limit, guild, user, skus, excludeEnded, excludeDeleted, cache, before, after } = {}) {
const query = makeURLSearchParams({ const query = makeURLSearchParams({
limit, limit,
guild_id: guild && this.client.guilds.resolveId(guild), guild_id: guild && this.client.guilds.resolveId(guild),
user_id: user && this.client.users.resolveId(user), user_id: user && this.client.users.resolveId(user),
sku_ids: skus?.map(sku => resolveSKUId(sku)).join(','), sku_ids: skus?.map(sku => resolveSKUId(sku)).join(','),
exclude_ended: excludeEnded, exclude_ended: excludeEnded,
exclude_deleted: excludeDeleted,
before, before,
after, after,
}); });
const entitlements = await this.client.rest.get(Routes.entitlements(this.client.application.id), { query }); const entitlements = await this.client.rest.get(Routes.entitlements(this.client.application.id), { query });
return entitlements.reduce( return entitlements.reduce(
(coll, entitlement) => coll.set(entitlement.id, this._add(entitlement, cache)), (coll, entitlement) => coll.set(entitlement.id, this._add(entitlement, cache)),
new Collection(), new Collection(),

View File

@@ -97,14 +97,14 @@ class GuildBanManager extends CachedManager {
* .then(console.log) * .then(console.log)
* .catch(console.error); * .catch(console.error);
*/ */
async fetch(options) { fetch(options) {
if (!options) return this._fetchMany(); if (!options) return this._fetchMany();
const { user, cache, force, limit, before, after } = options; const { user, cache, force, limit, before, after } = options;
const resolvedUser = this.client.users.resolveId(user ?? options); const resolvedUser = this.client.users.resolveId(user ?? options);
if (resolvedUser) return this._fetchSingle({ user: resolvedUser, cache, force }); if (resolvedUser) return this._fetchSingle({ user: resolvedUser, cache, force });
if (!before && !after && !limit && cache === undefined) { if (!before && !after && !limit && cache === undefined) {
throw new DiscordjsError(ErrorCodes.FetchBanResolveId); return Promise.reject(new DiscordjsError(ErrorCodes.FetchBanResolveId));
} }
return this._fetchMany(options); return this._fetchMany(options);
@@ -175,7 +175,7 @@ class GuildBanManager extends CachedManager {
reason: options.reason, reason: options.reason,
}); });
if (user instanceof GuildMember) return user; if (user instanceof GuildMember) return user;
const _user = this.client.users.cache.get(id); const _user = this.client.users.resolve(id);
if (_user) { if (_user) {
return this.guild.members.resolve(_user) ?? _user; return this.guild.members.resolve(_user) ?? _user;
} }

View File

@@ -84,7 +84,7 @@ class GuildChannelManager extends CachedManager {
* @returns {?(GuildChannel|ThreadChannel)} * @returns {?(GuildChannel|ThreadChannel)}
*/ */
resolve(channel) { resolve(channel) {
if (channel instanceof ThreadChannel) return this.cache.get(channel.id) ?? null; if (channel instanceof ThreadChannel) return super.resolve(channel.id);
return super.resolve(channel); return super.resolve(channel);
} }
@@ -230,13 +230,13 @@ class GuildChannelManager extends CachedManager {
async createWebhook({ channel, name, avatar, reason }) { async createWebhook({ channel, name, avatar, reason }) {
const id = this.resolveId(channel); const id = this.resolveId(channel);
if (!id) throw new DiscordjsTypeError(ErrorCodes.InvalidType, 'channel', 'GuildChannelResolvable'); if (!id) throw new DiscordjsTypeError(ErrorCodes.InvalidType, 'channel', 'GuildChannelResolvable');
if (typeof avatar === 'string' && !avatar.startsWith('data:')) {
const resolvedImage = await resolveImage(avatar); avatar = await resolveImage(avatar);
}
const data = await this.client.rest.post(Routes.channelWebhooks(id), { const data = await this.client.rest.post(Routes.channelWebhooks(id), {
body: { body: {
name, name,
avatar: resolvedImage, avatar,
}, },
reason, reason,
}); });
@@ -287,7 +287,7 @@ class GuildChannelManager extends CachedManager {
const resolvedChannel = this.resolve(channel); const resolvedChannel = this.resolve(channel);
if (!resolvedChannel) throw new DiscordjsTypeError(ErrorCodes.InvalidType, 'channel', 'GuildChannelResolvable'); if (!resolvedChannel) throw new DiscordjsTypeError(ErrorCodes.InvalidType, 'channel', 'GuildChannelResolvable');
const parentId = options.parent && this.client.channels.resolveId(options.parent); const parent = options.parent && this.client.channels.resolveId(options.parent);
if (options.position !== undefined) { if (options.position !== undefined) {
await this.setPosition(resolvedChannel, options.position, { position: options.position, reason: options.reason }); await this.setPosition(resolvedChannel, options.position, { position: options.position, reason: options.reason });
@@ -298,8 +298,8 @@ class GuildChannelManager extends CachedManager {
); );
if (options.lockPermissions) { if (options.lockPermissions) {
if (parentId) { if (parent) {
const newParent = this.cache.get(parentId); const newParent = this.guild.channels.resolve(parent);
if (newParent?.type === ChannelType.GuildCategory) { if (newParent?.type === ChannelType.GuildCategory) {
permission_overwrites = newParent.permissionOverwrites.cache.map(overwrite => permission_overwrites = newParent.permissionOverwrites.cache.map(overwrite =>
PermissionOverwrites.resolve(overwrite, this.guild), PermissionOverwrites.resolve(overwrite, this.guild),
@@ -322,7 +322,7 @@ class GuildChannelManager extends CachedManager {
user_limit: options.userLimit, user_limit: options.userLimit,
rtc_region: options.rtcRegion, rtc_region: options.rtcRegion,
video_quality_mode: options.videoQualityMode, video_quality_mode: options.videoQualityMode,
parent_id: parentId, parent_id: parent,
lock_permissions: options.lockPermissions, lock_permissions: options.lockPermissions,
rate_limit_per_user: options.rateLimitPerUser, rate_limit_per_user: options.rateLimitPerUser,
default_auto_archive_duration: options.defaultAutoArchiveDuration, default_auto_archive_duration: options.defaultAutoArchiveDuration,

View File

@@ -39,14 +39,14 @@ class GuildEmojiRoleManager extends DataManager {
* @param {RoleResolvable|RoleResolvable[]|Collection<Snowflake, Role>} roleOrRoles The role or roles to add * @param {RoleResolvable|RoleResolvable[]|Collection<Snowflake, Role>} roleOrRoles The role or roles to add
* @returns {Promise<GuildEmoji>} * @returns {Promise<GuildEmoji>}
*/ */
async add(roleOrRoles) { add(roleOrRoles) {
if (!Array.isArray(roleOrRoles) && !(roleOrRoles instanceof Collection)) roleOrRoles = [roleOrRoles]; if (!Array.isArray(roleOrRoles) && !(roleOrRoles instanceof Collection)) roleOrRoles = [roleOrRoles];
const resolvedRoles = []; const resolvedRoles = [];
for (const role of roleOrRoles.values()) { for (const role of roleOrRoles.values()) {
const resolvedRole = this.guild.roles.resolveId(role); const resolvedRole = this.guild.roles.resolveId(role);
if (!resolvedRole) { if (!resolvedRole) {
throw new DiscordjsTypeError(ErrorCodes.InvalidElement, 'Array or Collection', 'roles', role); return Promise.reject(new DiscordjsTypeError(ErrorCodes.InvalidElement, 'Array or Collection', 'roles', role));
} }
resolvedRoles.push(resolvedRole); resolvedRoles.push(resolvedRole);
} }
@@ -60,14 +60,14 @@ class GuildEmojiRoleManager extends DataManager {
* @param {RoleResolvable|RoleResolvable[]|Collection<Snowflake, Role>} roleOrRoles The role or roles to remove * @param {RoleResolvable|RoleResolvable[]|Collection<Snowflake, Role>} roleOrRoles The role or roles to remove
* @returns {Promise<GuildEmoji>} * @returns {Promise<GuildEmoji>}
*/ */
async remove(roleOrRoles) { remove(roleOrRoles) {
if (!Array.isArray(roleOrRoles) && !(roleOrRoles instanceof Collection)) roleOrRoles = [roleOrRoles]; if (!Array.isArray(roleOrRoles) && !(roleOrRoles instanceof Collection)) roleOrRoles = [roleOrRoles];
const resolvedRoleIds = []; const resolvedRoleIds = [];
for (const role of roleOrRoles.values()) { for (const role of roleOrRoles.values()) {
const roleId = this.guild.roles.resolveId(role); const roleId = this.guild.roles.resolveId(role);
if (!roleId) { if (!roleId) {
throw new DiscordjsTypeError(ErrorCodes.InvalidElement, 'Array or Collection', 'roles', role); return Promise.reject(new DiscordjsTypeError(ErrorCodes.InvalidElement, 'Array or Collection', 'roles', role));
} }
resolvedRoleIds.push(roleId); resolvedRoleIds.push(roleId);
} }

View File

@@ -121,22 +121,22 @@ class GuildInviteManager extends CachedManager {
* .then(console.log) * .then(console.log)
* .catch(console.error); * .catch(console.error);
*/ */
async fetch(options) { fetch(options) {
if (!options) return this._fetchMany(); if (!options) return this._fetchMany();
if (typeof options === 'string') { if (typeof options === 'string') {
const code = resolveInviteCode(options); const code = resolveInviteCode(options);
if (!code) throw new DiscordjsError(ErrorCodes.InviteResolveCode); if (!code) return Promise.reject(new DiscordjsError(ErrorCodes.InviteResolveCode));
return this._fetchSingle({ code, cache: true }); return this._fetchSingle({ code, cache: true });
} }
if (!options.code) { if (!options.code) {
if (options.channelId) { if (options.channelId) {
const id = this.guild.channels.resolveId(options.channelId); const id = this.guild.channels.resolveId(options.channelId);
if (!id) throw new DiscordjsError(ErrorCodes.GuildChannelResolve); if (!id) return Promise.reject(new DiscordjsError(ErrorCodes.GuildChannelResolve));
return this._fetchChannelMany(id, options.cache); return this._fetchChannelMany(id, options.cache);
} }
if ('cache' in options) return this._fetchMany(options.cache); if ('cache' in options) return this._fetchMany(options.cache);
throw new DiscordjsError(ErrorCodes.InviteResolveCode); return Promise.reject(new DiscordjsError(ErrorCodes.InviteResolveCode));
} }
return this._fetchSingle({ return this._fetchSingle({
...options, ...options,

View File

@@ -4,9 +4,8 @@ const process = require('node:process');
const { setTimeout, clearTimeout } = require('node:timers'); const { setTimeout, clearTimeout } = require('node:timers');
const { Collection } = require('@discordjs/collection'); const { Collection } = require('@discordjs/collection');
const { makeURLSearchParams } = require('@discordjs/rest'); const { makeURLSearchParams } = require('@discordjs/rest');
const { GatewayOpcodes, Routes, RouteBases } = require('discord-api-types/v10'); const { Routes, RouteBases } = require('discord-api-types/v10');
const CachedManager = require('./CachedManager'); const CachedManager = require('./CachedManager');
const { ErrorCodes, DiscordjsError } = require('../errors/index.js');
const ShardClientUtil = require('../sharding/ShardClientUtil'); const ShardClientUtil = require('../sharding/ShardClientUtil');
const { Guild } = require('../structures/Guild'); const { Guild } = require('../structures/Guild');
const GuildChannel = require('../structures/GuildChannel'); const GuildChannel = require('../structures/GuildChannel');
@@ -19,7 +18,6 @@ const { resolveImage } = require('../util/DataResolver');
const Events = require('../util/Events'); const Events = require('../util/Events');
const PermissionsBitField = require('../util/PermissionsBitField'); const PermissionsBitField = require('../util/PermissionsBitField');
const SystemChannelFlagsBitField = require('../util/SystemChannelFlagsBitField'); const SystemChannelFlagsBitField = require('../util/SystemChannelFlagsBitField');
const { _transformAPIIncidentsData } = require('../util/Transformers.js');
const { resolveColor } = require('../util/Util'); const { resolveColor } = require('../util/Util');
let cacheWarningEmitted = false; let cacheWarningEmitted = false;
@@ -283,112 +281,6 @@ class GuildManager extends CachedManager {
return data.reduce((coll, guild) => coll.set(guild.id, new OAuth2Guild(this.client, guild)), new Collection()); return data.reduce((coll, guild) => coll.set(guild.id, new OAuth2Guild(this.client, guild)), new Collection());
} }
/**
* @typedef {Object} FetchSoundboardSoundsOptions
* @param {Snowflake[]} guildIds The ids of the guilds to fetch soundboard sounds for
* @param {number} [time=10_000] The timeout for receipt of the soundboard sounds
*/
/**
* Fetches soundboard sounds for the specified guilds.
* @param {FetchSoundboardSoundsOptions} options The options for fetching soundboard sounds
* @returns {Promise<Collection<Snowflake, Collection<Snowflake, SoundboardSound>>>}
* @example
* // Fetch soundboard sounds for multiple guilds
* const soundboardSounds = await client.guilds.fetchSoundboardSounds({
* guildIds: ['123456789012345678', '987654321098765432'],
* })
*
* console.log(soundboardSounds.get('123456789012345678'));
*/
async fetchSoundboardSounds({ guildIds, time = 10_000 }) {
const shardCount = this.client.options.shardCount;
const shardIds = new Map();
for (const guildId of guildIds) {
const shardId = ShardClientUtil.shardIdForGuildId(guildId, shardCount);
const group = shardIds.get(shardId);
if (group) group.push(guildId);
else shardIds.set(shardId, [guildId]);
}
for (const [shardId, shardGuildIds] of shardIds) {
this.client.ws.shards.get(shardId).send({
op: GatewayOpcodes.RequestSoundboardSounds,
d: {
guild_ids: shardGuildIds,
},
});
}
return new Promise((resolve, reject) => {
const remainingGuildIds = new Set(guildIds);
const fetchedSoundboardSounds = new Collection();
const handler = (soundboardSounds, guild) => {
timeout.refresh();
if (!remainingGuildIds.has(guild.id)) return;
fetchedSoundboardSounds.set(guild.id, soundboardSounds);
remainingGuildIds.delete(guild.id);
if (remainingGuildIds.size === 0) {
clearTimeout(timeout);
this.client.removeListener(Events.SoundboardSounds, handler);
this.client.decrementMaxListeners();
resolve(fetchedSoundboardSounds);
}
};
const timeout = setTimeout(() => {
this.client.removeListener(Events.SoundboardSounds, handler);
this.client.decrementMaxListeners();
reject(new DiscordjsError(ErrorCodes.GuildSoundboardSoundsTimeout));
}, time).unref();
this.client.incrementMaxListeners();
this.client.on(Events.SoundboardSounds, handler);
});
}
/**
* Options used to set incident actions. Supplying `null` to any option will disable the action.
* @typedef {Object} IncidentActionsEditOptions
* @property {?DateResolvable} [invitesDisabledUntil] When invites should be enabled again
* @property {?DateResolvable} [dmsDisabledUntil] When direct messages should be enabled again
*/
/**
* Sets the incident actions for a guild.
* @param {GuildResolvable} guild The guild
* @param {IncidentActionsEditOptions} incidentActions The incident actions to set
* @returns {Promise<IncidentActions>}
*/
async setIncidentActions(guild, { invitesDisabledUntil, dmsDisabledUntil }) {
const guildId = this.resolveId(guild);
const data = await this.client.rest.put(Routes.guildIncidentActions(guildId), {
body: {
invites_disabled_until: invitesDisabledUntil && new Date(invitesDisabledUntil).toISOString(),
dms_disabled_until: dmsDisabledUntil && new Date(dmsDisabledUntil).toISOString(),
},
});
const parsedData = _transformAPIIncidentsData(data);
const resolvedGuild = this.resolve(guild);
if (resolvedGuild) {
resolvedGuild.incidentsData = parsedData;
}
return parsedData;
}
/** /**
* Returns a URL for the PNG widget of a guild. * Returns a URL for the PNG widget of a guild.
* @param {GuildResolvable} guild The guild of the widget image * @param {GuildResolvable} guild The guild of the widget image

View File

@@ -54,8 +54,8 @@ class GuildMemberManager extends CachedManager {
resolve(member) { resolve(member) {
const memberResolvable = super.resolve(member); const memberResolvable = super.resolve(member);
if (memberResolvable) return memberResolvable; if (memberResolvable) return memberResolvable;
const userId = this.client.users.resolveId(member); const userResolvable = this.client.users.resolveId(member);
if (userId) return this.cache.get(userId) ?? null; if (userResolvable) return super.resolve(userResolvable);
return null; return null;
} }
@@ -67,8 +67,8 @@ class GuildMemberManager extends CachedManager {
resolveId(member) { resolveId(member) {
const memberResolvable = super.resolveId(member); const memberResolvable = super.resolveId(member);
if (memberResolvable) return memberResolvable; if (memberResolvable) return memberResolvable;
const userId = this.client.users.resolveId(member); const userResolvable = this.client.users.resolveId(member);
return this.cache.has(userId) ? userId : null; return this.cache.has(userResolvable) ? userResolvable : null;
} }
/** /**
@@ -144,7 +144,7 @@ class GuildMemberManager extends CachedManager {
*/ */
get me() { get me() {
return ( return (
this.cache.get(this.client.user.id) ?? this.resolve(this.client.user.id) ??
(this.client.options.partials.includes(Partials.GuildMember) (this.client.options.partials.includes(Partials.GuildMember)
? this._add({ user: { id: this.client.user.id } }, true) ? this._add({ user: { id: this.client.user.id } }, true)
: null) : null)
@@ -223,7 +223,7 @@ class GuildMemberManager extends CachedManager {
return this._add(data, cache); return this._add(data, cache);
} }
async _fetchMany({ _fetchMany({
limit = 0, limit = 0,
withPresences: presences, withPresences: presences,
users, users,
@@ -231,7 +231,7 @@ class GuildMemberManager extends CachedManager {
time = 120e3, time = 120e3,
nonce = DiscordSnowflake.generate().toString(), nonce = DiscordSnowflake.generate().toString(),
} = {}) { } = {}) {
if (nonce.length > 32) throw new DiscordjsRangeError(ErrorCodes.MemberFetchNonceLength); if (nonce.length > 32) return Promise.reject(new DiscordjsRangeError(ErrorCodes.MemberFetchNonceLength));
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
if (!query && !users) query = ''; if (!query && !users) query = '';
@@ -461,7 +461,7 @@ class GuildMemberManager extends CachedManager {
*/ */
async kick(user, reason) { async kick(user, reason) {
const id = this.client.users.resolveId(user); const id = this.client.users.resolveId(user);
if (!id) throw new DiscordjsTypeError(ErrorCodes.InvalidType, 'user', 'UserResolvable'); if (!id) return Promise.reject(new DiscordjsTypeError(ErrorCodes.InvalidType, 'user', 'UserResolvable'));
await this.client.rest.delete(Routes.guildMember(this.guild.id, id), { reason }); await this.client.rest.delete(Routes.guildMember(this.guild.id, id), { reason });
@@ -535,7 +535,7 @@ class GuildMemberManager extends CachedManager {
*/ */
async addRole(options) { async addRole(options) {
const { user, role, reason } = options; const { user, role, reason } = options;
const userId = this.resolveId(user); const userId = this.guild.members.resolveId(user);
const roleId = this.guild.roles.resolveId(role); const roleId = this.guild.roles.resolveId(role);
await this.client.rest.put(Routes.guildMemberRole(this.guild.id, userId, roleId), { reason }); await this.client.rest.put(Routes.guildMemberRole(this.guild.id, userId, roleId), { reason });
@@ -549,7 +549,7 @@ class GuildMemberManager extends CachedManager {
*/ */
async removeRole(options) { async removeRole(options) {
const { user, role, reason } = options; const { user, role, reason } = options;
const userId = this.resolveId(user); const userId = this.guild.members.resolveId(user);
const roleId = this.guild.roles.resolveId(role); const roleId = this.guild.roles.resolveId(role);
await this.client.rest.delete(Routes.guildMemberRole(this.guild.id, userId, roleId), { reason }); await this.client.rest.delete(Routes.guildMemberRole(this.guild.id, userId, roleId), { reason });

View File

@@ -65,7 +65,7 @@ class GuildMemberRoleManager extends DataManager {
* @readonly * @readonly
*/ */
get color() { get color() {
const coloredRoles = this.cache.filter(role => role.colors.primaryColor); const coloredRoles = this.cache.filter(role => role.color);
if (!coloredRoles.size) return null; if (!coloredRoles.size) return null;
return coloredRoles.reduce((prev, role) => (role.comparePositionTo(prev) > 0 ? role : prev)); return coloredRoles.reduce((prev, role) => (role.comparePositionTo(prev) > 0 ? role : prev));
} }
@@ -101,8 +101,6 @@ class GuildMemberRoleManager extends DataManager {
/** /**
* Adds a role (or multiple roles) to the member. * Adds a role (or multiple roles) to the member.
*
* <info>Uses the idempotent PUT route for singular roles, otherwise PATCHes the underlying guild member</info>
* @param {RoleResolvable|RoleResolvable[]|Collection<Snowflake, Role>} roleOrRoles The role or roles to add * @param {RoleResolvable|RoleResolvable[]|Collection<Snowflake, Role>} roleOrRoles The role or roles to add
* @param {string} [reason] Reason for adding the role(s) * @param {string} [reason] Reason for adding the role(s)
* @returns {Promise<GuildMember>} * @returns {Promise<GuildMember>}
@@ -140,8 +138,6 @@ class GuildMemberRoleManager extends DataManager {
/** /**
* Removes a role (or multiple roles) from the member. * Removes a role (or multiple roles) from the member.
*
* <info>Uses the idempotent DELETE route for singular roles, otherwise PATCHes the underlying guild member</info>
* @param {RoleResolvable|RoleResolvable[]|Collection<Snowflake, Role>} roleOrRoles The role or roles to remove * @param {RoleResolvable|RoleResolvable[]|Collection<Snowflake, Role>} roleOrRoles The role or roles to remove
* @param {string} [reason] Reason for removing the role(s) * @param {string} [reason] Reason for removing the role(s)
* @returns {Promise<GuildMember>} * @returns {Promise<GuildMember>}

View File

@@ -7,7 +7,6 @@ const CachedManager = require('./CachedManager');
const { DiscordjsTypeError, DiscordjsError, ErrorCodes } = require('../errors'); const { DiscordjsTypeError, DiscordjsError, ErrorCodes } = require('../errors');
const { GuildScheduledEvent } = require('../structures/GuildScheduledEvent'); const { GuildScheduledEvent } = require('../structures/GuildScheduledEvent');
const { resolveImage } = require('../util/DataResolver'); const { resolveImage } = require('../util/DataResolver');
const { _transformGuildScheduledEventRecurrenceRule } = require('../util/Transformers');
/** /**
* Manages API methods for GuildScheduledEvents and stores their cache. * Manages API methods for GuildScheduledEvents and stores their cache.
@@ -37,18 +36,6 @@ class GuildScheduledEventManager extends CachedManager {
* @typedef {Snowflake|GuildScheduledEvent} GuildScheduledEventResolvable * @typedef {Snowflake|GuildScheduledEvent} GuildScheduledEventResolvable
*/ */
/**
* Options for setting a recurrence rule for a guild scheduled event.
* @typedef {Object} GuildScheduledEventRecurrenceRuleOptions
* @property {DateResolvable} startAt The time the recurrence rule interval starts at
* @property {GuildScheduledEventRecurrenceRuleFrequency} frequency How often the event occurs
* @property {number} interval The spacing between the events
* @property {?GuildScheduledEventRecurrenceRuleWeekday[]} byWeekday The days within a week to recur on
* @property {?GuildScheduledEventRecurrenceRuleNWeekday[]} byNWeekday The days within a week to recur on
* @property {?GuildScheduledEventRecurrenceRuleMonth[]} byMonth The months to recur on
* @property {?number[]} byMonthDay The days within a month to recur on
*/
/** /**
* Options used to create a guild scheduled event. * Options used to create a guild scheduled event.
* @typedef {Object} GuildScheduledEventCreateOptions * @typedef {Object} GuildScheduledEventCreateOptions
@@ -67,8 +54,6 @@ class GuildScheduledEventManager extends CachedManager {
* <warn>This is required if `entityType` is {@link GuildScheduledEventEntityType.External}</warn> * <warn>This is required if `entityType` is {@link GuildScheduledEventEntityType.External}</warn>
* @property {?(BufferResolvable|Base64Resolvable)} [image] The cover image of the guild scheduled event * @property {?(BufferResolvable|Base64Resolvable)} [image] The cover image of the guild scheduled event
* @property {string} [reason] The reason for creating the guild scheduled event * @property {string} [reason] The reason for creating the guild scheduled event
* @property {GuildScheduledEventRecurrenceRuleOptions} [recurrenceRule]
* The recurrence rule of the guild scheduled event
*/ */
/** /**
@@ -96,7 +81,6 @@ class GuildScheduledEventManager extends CachedManager {
entityMetadata, entityMetadata,
reason, reason,
image, image,
recurrenceRule,
} = options; } = options;
let entity_metadata, channel_id; let entity_metadata, channel_id;
@@ -120,7 +104,6 @@ class GuildScheduledEventManager extends CachedManager {
entity_type: entityType, entity_type: entityType,
entity_metadata, entity_metadata,
image: image && (await resolveImage(image)), image: image && (await resolveImage(image)),
recurrence_rule: recurrenceRule && _transformGuildScheduledEventRecurrenceRule(recurrenceRule),
}, },
reason, reason,
}); });
@@ -170,7 +153,10 @@ class GuildScheduledEventManager extends CachedManager {
return data.reduce( return data.reduce(
(coll, rawGuildScheduledEventData) => (coll, rawGuildScheduledEventData) =>
coll.set(rawGuildScheduledEventData.id, this._add(rawGuildScheduledEventData, options.cache)), coll.set(
rawGuildScheduledEventData.id,
this.guild.scheduledEvents._add(rawGuildScheduledEventData, options.cache),
),
new Collection(), new Collection(),
); );
} }
@@ -192,8 +178,6 @@ class GuildScheduledEventManager extends CachedManager {
* {@link GuildScheduledEventEntityType.External}</warn> * {@link GuildScheduledEventEntityType.External}</warn>
* @property {?(BufferResolvable|Base64Resolvable)} [image] The cover image of the guild scheduled event * @property {?(BufferResolvable|Base64Resolvable)} [image] The cover image of the guild scheduled event
* @property {string} [reason] The reason for editing the guild scheduled event * @property {string} [reason] The reason for editing the guild scheduled event
* @property {?GuildScheduledEventRecurrenceRuleOptions} [recurrenceRule]
* The recurrence rule of the guild scheduled event
*/ */
/** /**
@@ -219,7 +203,6 @@ class GuildScheduledEventManager extends CachedManager {
entityMetadata, entityMetadata,
reason, reason,
image, image,
recurrenceRule,
} = options; } = options;
let entity_metadata; let entity_metadata;
@@ -241,7 +224,6 @@ class GuildScheduledEventManager extends CachedManager {
status, status,
image: image && (await resolveImage(image)), image: image && (await resolveImage(image)),
entity_metadata, entity_metadata,
recurrence_rule: recurrenceRule && _transformGuildScheduledEventRecurrenceRule(recurrenceRule),
}, },
reason, reason,
}); });

View File

@@ -1,214 +0,0 @@
'use strict';
const { Collection } = require('@discordjs/collection');
const { lazy } = require('@discordjs/util');
const { Routes } = require('discord-api-types/v10');
const CachedManager = require('./CachedManager.js');
const { DiscordjsTypeError, ErrorCodes } = require('../errors/index.js');
const { SoundboardSound } = require('../structures/SoundboardSound.js');
const { resolveBase64, resolveFile } = require('../util/DataResolver.js');
const fileTypeMime = lazy(() => require('magic-bytes.js').filetypemime);
/**
* Manages API methods for Soundboard Sounds and stores their cache.
* @extends {CachedManager}
*/
class GuildSoundboardSoundManager extends CachedManager {
constructor(guild, iterable) {
super(guild.client, SoundboardSound, iterable);
/**
* The guild this manager belongs to
* @type {Guild}
*/
this.guild = guild;
}
/**
* The cache of Soundboard Sounds
* @type {Collection<Snowflake, SoundboardSound>}
* @name GuildSoundboardSoundManager#cache
*/
_add(data, cache) {
return super._add(data, cache, { extras: [this.guild], id: data.sound_id });
}
/**
* Data that resolves to give a SoundboardSound object. This can be:
* * A SoundboardSound object
* * A Snowflake
* @typedef {SoundboardSound|Snowflake} SoundboardSoundResolvable
*/
/**
* Resolves a SoundboardSoundResolvable to a SoundboardSound object.
* @method resolve
* @memberof GuildSoundboardSoundManager
* @instance
* @param {SoundboardSoundResolvable} soundboardSound The SoundboardSound resolvable to identify
* @returns {?SoundboardSound}
*/
/**
* Resolves a {@link SoundboardSoundResolvable} to a {@link SoundboardSound} id.
* @param {SoundboardSoundResolvable} soundboardSound The soundboard sound resolvable to resolve
* @returns {?Snowflake}
*/
resolveId(soundboardSound) {
if (soundboardSound instanceof this.holds) return soundboardSound.soundId;
if (typeof soundboardSound === 'string') return soundboardSound;
return null;
}
/**
* Options used to create a soundboard sound in a guild.
* @typedef {Object} GuildSoundboardSoundCreateOptions
* @property {BufferResolvable|Stream} file The file for the soundboard sound
* @property {string} name The name for the soundboard sound
* @property {string} [contentType] The content type for the soundboard sound file
* @property {number} [volume] The volume (a double) for the soundboard sound, from 0 (inclusive) to 1. Defaults to 1
* @property {Snowflake} [emojiId] The emoji id for the soundboard sound
* @property {string} [emojiName] The emoji name for the soundboard sound
* @property {string} [reason] The reason for creating the soundboard sound
*/
/**
* Creates a new guild soundboard sound.
* @param {GuildSoundboardSoundCreateOptions} options Options for creating a guild soundboard sound
* @returns {Promise<SoundboardSound>} The created soundboard sound
* @example
* // Create a new soundboard sound from a file on your computer
* guild.soundboardSounds.create({ file: './sound.mp3', name: 'sound' })
* .then(sound => console.log(`Created new soundboard sound with name ${sound.name}!`))
* .catch(console.error);
*/
async create({ contentType, emojiId, emojiName, file, name, reason, volume }) {
const resolvedFile = await resolveFile(file);
const resolvedContentType = contentType ?? resolvedFile.contentType ?? fileTypeMime()(resolvedFile.data)[0];
const sound = resolveBase64(resolvedFile.data, resolvedContentType);
const body = { emoji_id: emojiId, emoji_name: emojiName, name, sound, volume };
const soundboardSound = await this.client.rest.post(Routes.guildSoundboardSounds(this.guild.id), {
body,
reason,
});
return this._add(soundboardSound);
}
/**
* Data for editing a soundboard sound.
* @typedef {Object} GuildSoundboardSoundEditOptions
* @property {string} [name] The name of the soundboard sound
* @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
*/
/**
* Edits a soundboard sound.
* @param {SoundboardSoundResolvable} soundboardSound The soundboard sound to edit
* @param {GuildSoundboardSoundEditOptions} [options={}] The new data for the soundboard sound
* @returns {Promise<SoundboardSound>}
*/
async edit(soundboardSound, options = {}) {
const soundId = this.resolveId(soundboardSound);
if (!soundId) throw new DiscordjsTypeError(ErrorCodes.InvalidType, 'soundboardSound', 'SoundboardSoundResolvable');
const { emojiId, emojiName, name, reason, volume } = options;
const body = { emoji_id: emojiId, emoji_name: emojiName, name, volume };
const data = await this.client.rest.patch(Routes.guildSoundboardSound(this.guild.id, soundId), {
body,
reason,
});
const existing = this.cache.get(soundId);
if (existing) {
const clone = existing._clone();
clone._patch(data);
return clone;
}
return this._add(data);
}
/**
* Deletes a soundboard sound.
* @param {SoundboardSoundResolvable} soundboardSound The soundboard sound to delete
* @param {string} [reason] Reason for deleting this soundboard sound
* @returns {Promise<void>}
*/
async delete(soundboardSound, reason) {
const soundId = this.resolveId(soundboardSound);
if (!soundId) throw new DiscordjsTypeError(ErrorCodes.InvalidType, 'soundboardSound', 'SoundboardSoundResolvable');
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 {SoundboardSoundResolvable|FetchSoundboardSoundOptions|FetchGuildSoundboardSoundsOptions} [options] Options for fetching soundboard sound(s)
* @returns {Promise<SoundboardSound|Collection<Snowflake, SoundboardSound>>}
* @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);
*/
/* 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 });
}
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 data.items.reduce((coll, sound) => coll.set(sound.sound_id, this._add(sound, cache)), new Collection());
}
}
exports.GuildSoundboardSoundManager = GuildSoundboardSoundManager;

View File

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

View File

@@ -62,13 +62,15 @@ class PermissionOverwriteManager extends CachedManager {
* }, * },
* ], 'Needed to change permissions'); * ], 'Needed to change permissions');
*/ */
async set(overwrites, reason) { set(overwrites, reason) {
if (!Array.isArray(overwrites) && !(overwrites instanceof Collection)) { if (!Array.isArray(overwrites) && !(overwrites instanceof Collection)) {
throw new DiscordjsTypeError( return Promise.reject(
ErrorCodes.InvalidType, new DiscordjsTypeError(
'overwrites', ErrorCodes.InvalidType,
'Array or Collection of Permission Overwrites', 'overwrites',
true, 'Array or Collection of Permission Overwrites',
true,
),
); );
} }
return this.channel.edit({ permissionOverwrites: overwrites, reason }); return this.channel.edit({ permissionOverwrites: overwrites, reason });

View File

@@ -38,8 +38,8 @@ class PresenceManager extends CachedManager {
resolve(presence) { resolve(presence) {
const presenceResolvable = super.resolve(presence); const presenceResolvable = super.resolve(presence);
if (presenceResolvable) return presenceResolvable; if (presenceResolvable) return presenceResolvable;
const userId = this.client.users.resolveId(presence); const UserResolvable = this.client.users.resolveId(presence);
return super.cache.get(userId) ?? null; return super.resolve(UserResolvable);
} }
/** /**
@@ -50,8 +50,8 @@ class PresenceManager extends CachedManager {
resolveId(presence) { resolveId(presence) {
const presenceResolvable = super.resolveId(presence); const presenceResolvable = super.resolveId(presence);
if (presenceResolvable) return presenceResolvable; if (presenceResolvable) return presenceResolvable;
const userId = this.client.users.resolveId(presence); const userResolvable = this.client.users.resolveId(presence);
return this.cache.has(userId) ? userId : null; return this.cache.has(userResolvable) ? userResolvable : null;
} }
} }

View File

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

View File

@@ -1,81 +0,0 @@
'use strict';
const { Collection } = require('@discordjs/collection');
const { makeURLSearchParams } = require('@discordjs/rest');
const { Routes } = require('discord-api-types/v10');
const CachedManager = require('./CachedManager');
const { DiscordjsTypeError, ErrorCodes } = require('../errors/index');
const { Subscription } = require('../structures/Subscription');
const { resolveSKUId } = require('../util/Util');
/**
* Manages API methods for subscriptions and stores their cache.
* @extends {CachedManager}
*/
class SubscriptionManager extends CachedManager {
constructor(client, iterable) {
super(client, Subscription, iterable);
}
/**
* The cache of this manager
* @type {Collection<Snowflake, Subscription>}
* @name SubscriptionManager#cache
*/
/**
* Options used to fetch a subscription
* @typedef {BaseFetchOptions} FetchSubscriptionOptions
* @property {SKUResolvable} sku The SKU to fetch the subscription for
* @property {Snowflake} subscriptionId The id of the subscription to fetch
*/
/**
* Options used to fetch subscriptions
* @typedef {Object} FetchSubscriptionsOptions
* @property {Snowflake} [after] Consider only subscriptions after this subscription id
* @property {Snowflake} [before] Consider only subscriptions before this subscription id
* @property {number} [limit] The maximum number of subscriptions to fetch
* @property {SKUResolvable} sku The SKU to fetch subscriptions for
* @property {UserResolvable} user The user to fetch entitlements for
* <warn>If both `before` and `after` are provided, only `before` is respected</warn>
*/
/**
* Fetches subscriptions for this application
* @param {FetchSubscriptionOptions|FetchSubscriptionsOptions} [options={}] Options for fetching the subscriptions
* @returns {Promise<Subscription|Collection<Snowflake, Subscription>>}
*/
async fetch(options = {}) {
if (typeof options !== 'object') throw new DiscordjsTypeError(ErrorCodes.InvalidType, 'options', 'object', true);
const { after, before, cache, limit, sku, subscriptionId, user } = options;
const skuId = resolveSKUId(sku);
if (!skuId) throw new DiscordjsTypeError(ErrorCodes.InvalidType, 'sku', 'SKUResolvable');
if (subscriptionId) {
const subscription = await this.client.rest.get(Routes.skuSubscription(skuId, subscriptionId));
return this._add(subscription, cache);
}
const query = makeURLSearchParams({
limit,
user_id: this.client.users.resolveId(user) ?? undefined,
sku_id: skuId,
before,
after,
});
const subscriptions = await this.client.rest.get(Routes.skuSubscriptions(skuId), { query });
return subscriptions.reduce(
(coll, subscription) => coll.set(subscription.id, this._add(subscription, cache)),
new Collection(),
);
}
}
exports.SubscriptionManager = SubscriptionManager;

Some files were not shown because too many files have changed in this diff Show More