Compare commits
157 Commits
feat/appli
...
@discordjs
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2a067216c4 | ||
|
|
fe5e3c2a82 | ||
|
|
c486fb8127 | ||
|
|
f3942a6319 | ||
|
|
84b85f4c91 | ||
|
|
52173b6ca8 | ||
|
|
41439d3a40 | ||
|
|
d6e1609408 | ||
|
|
3e6364070b | ||
|
|
3c9d90ad7e | ||
|
|
ec796caf00 | ||
|
|
f1949271a0 | ||
|
|
fce498982a | ||
|
|
307b64f139 | ||
|
|
0cb8be490c | ||
|
|
77e767277b | ||
|
|
ccce987fa1 | ||
|
|
a3e189df00 | ||
|
|
c460a920ac | ||
|
|
c71228aab3 | ||
|
|
b0e413c116 | ||
|
|
65386034b6 | ||
|
|
1251d479b0 | ||
|
|
693fcbc32b | ||
|
|
c126367140 | ||
|
|
fc5ba6be70 | ||
|
|
7a7fecbe3c | ||
|
|
323d8e7571 | ||
|
|
3550b497f6 | ||
|
|
838cd2da34 | ||
|
|
017176926a | ||
|
|
be78e26729 | ||
|
|
52a69d77d0 | ||
|
|
3d74122215 | ||
|
|
69432a1bca | ||
|
|
8ccae833e7 | ||
|
|
c921e84531 | ||
|
|
311413e5f2 | ||
|
|
7884ecd3a0 | ||
|
|
427636ee75 | ||
|
|
cad826fc03 | ||
|
|
51b5d38342 | ||
|
|
5f93fbd0f2 | ||
|
|
c4fc79a3cd | ||
|
|
5b4dbd541e | ||
|
|
df0c28afc2 | ||
|
|
451a6380c6 | ||
|
|
01f31f374a | ||
|
|
9bf1f739e0 | ||
|
|
548d75258b | ||
|
|
6a129bc054 | ||
|
|
f60d3d65fe | ||
|
|
4db1092f8f | ||
|
|
eaa6863f93 | ||
|
|
06c8da23d1 | ||
|
|
2c3bf5c817 | ||
|
|
ec3ef7b1bd | ||
|
|
c9bc33c758 | ||
|
|
f38395ec4e | ||
|
|
ec76b17be3 | ||
|
|
d90a86a048 | ||
|
|
fa43c40d34 | ||
|
|
d0745afbea | ||
|
|
d518c97840 | ||
|
|
9005c8ae9c | ||
|
|
5888663392 | ||
|
|
8d33188ac1 | ||
|
|
5e6bd4b3d7 | ||
|
|
0aaba0305f | ||
|
|
633fdd8f28 | ||
|
|
87b359e44d | ||
|
|
ec7047572e | ||
|
|
2520a0fb96 | ||
|
|
a57b4d4d29 | ||
|
|
8162ae8ce0 | ||
|
|
ace834b274 | ||
|
|
d59857e901 | ||
|
|
19253f6b7b | ||
|
|
aeb8986aa1 | ||
|
|
444e55a093 | ||
|
|
b2cbdf1567 | ||
|
|
02fc101069 | ||
|
|
db41d5cb68 | ||
|
|
179525d9fc | ||
|
|
0b12263371 | ||
|
|
456a6f4548 | ||
|
|
5130d6f56c | ||
|
|
5dea94602e | ||
|
|
68bb8af58a | ||
|
|
315f422781 | ||
|
|
9d5c6b4588 | ||
|
|
7349a6ee3e | ||
|
|
87364c7ed9 | ||
|
|
25aff7e218 | ||
|
|
9f18cb2129 | ||
|
|
837af56cf8 | ||
|
|
e8217e335c | ||
|
|
538b47dd00 | ||
|
|
d923e90ae6 | ||
|
|
8ed93b3269 | ||
|
|
5619137acd | ||
|
|
35996b7d75 | ||
|
|
d3d6777ef8 | ||
|
|
37a38883d7 | ||
|
|
c85f18c1ee | ||
|
|
9723cc590b | ||
|
|
3cb3ecae21 | ||
|
|
dafdc78e73 | ||
|
|
3122da4ea4 | ||
|
|
4da0c03784 | ||
|
|
4c18a89c2f | ||
|
|
4359914d1a | ||
|
|
b026d0ee35 | ||
|
|
3bb13f96b4 | ||
|
|
06a75e80bc | ||
|
|
f26a5ed869 | ||
|
|
d06d8c0806 | ||
|
|
d8b913449e | ||
|
|
fb5c629638 | ||
|
|
178c9cb348 | ||
|
|
94a9b4d03c | ||
|
|
4c0d667773 | ||
|
|
4f9475d937 | ||
|
|
868be4eafc | ||
|
|
ed143a6cda | ||
|
|
56662ebad7 | ||
|
|
8066821faa | ||
|
|
3048c3c0aa | ||
|
|
2a5d99f0a0 | ||
|
|
633d4813ef | ||
|
|
08b87d9087 | ||
|
|
756eac6bb1 | ||
|
|
ee3be2c3c3 | ||
|
|
c05f653f0a | ||
|
|
0c1ff5ea29 | ||
|
|
a990eefa31 | ||
|
|
63417e8b6c | ||
|
|
c9a9b6ce9d | ||
|
|
83ec0fdcdf | ||
|
|
c84024968e | ||
|
|
63b5923deb | ||
|
|
886d4a7fcb | ||
|
|
697556fd16 | ||
|
|
68835b3ff7 | ||
|
|
0cc92bd5b0 | ||
|
|
d03eb5e26e | ||
|
|
25b22c67aa | ||
|
|
0add790169 | ||
|
|
1a305fe4ad | ||
|
|
93e96eb6c0 | ||
|
|
7a3a21b26e | ||
|
|
a2d4f187ca | ||
|
|
f9ca29e3e4 | ||
|
|
180dd60c61 | ||
|
|
dd795252d6 | ||
|
|
847fa9938d | ||
|
|
a97ac82619 |
4
.github/CODEOWNERS
vendored
@@ -6,8 +6,11 @@
|
||||
package.json @discordjs/core
|
||||
pnpm-lock.yaml @discordjs/core
|
||||
|
||||
/.github/ISSUE_TEMPLATE/ @discordjs/guide @discordjs/core
|
||||
|
||||
/apps/guide/ @discordjs/website @discordjs/guide
|
||||
/apps/guide/content/ @discordjs/guide
|
||||
/apps/proxy-container/ @discordjs/proxy
|
||||
/apps/website/ @discordjs/website
|
||||
|
||||
/packages/actions/ @discordjs/actions
|
||||
@@ -24,7 +27,6 @@ pnpm-lock.yaml @discordjs/core
|
||||
/packages/formatters/ @discordjs/formatters
|
||||
/packages/next/ @discordjs/core
|
||||
/packages/proxy/ @discordjs/proxy
|
||||
/packages/proxy-container/ @discordjs/proxy
|
||||
/packages/rest/ @discordjs/rest
|
||||
/packages/scripts/ @discordjs/scripts
|
||||
/packages/structures/ @discordjs/structures
|
||||
|
||||
@@ -22,7 +22,6 @@ body:
|
||||
- formatters
|
||||
- next
|
||||
- proxy
|
||||
- proxy-container
|
||||
- rest
|
||||
- structures
|
||||
- ui
|
||||
@@ -62,9 +61,9 @@ body:
|
||||
label: Versions
|
||||
description: List necessary versions here. This includes your package version, runtime version, operating system etc.
|
||||
placeholder: |
|
||||
- discord.js 14.12.1 (`npm ls discord.js` or another package)
|
||||
- Node.js 22.12.0 (`node --version`)
|
||||
- TypeScript 5.1.6 (`npm ls typescript` if you use it)
|
||||
- discord.js 14.24.2 (`npm ls discord.js` or another package)
|
||||
- Node.js 24.11.0 (`node --version`)
|
||||
- TypeScript 5.9.3 (`npm ls typescript` if you use it)
|
||||
- macOS Ventura 13.3.1
|
||||
validations:
|
||||
required: true
|
||||
|
||||
51
.github/ISSUE_TEMPLATE/03-proxy_container_bug_report.yml
vendored
Normal file
@@ -0,0 +1,51 @@
|
||||
name: Proxy Container bug report
|
||||
description: Report an issue with the proxy container.
|
||||
labels: [bug, need repro, apps:proxy-container]
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
Thank you for filing an issue! If you are here to ask a question, use Discord instead: https://discord.gg/djs
|
||||
|
||||
This issue form is for the proxy container.
|
||||
- type: textarea
|
||||
id: description
|
||||
attributes:
|
||||
label: Issue description
|
||||
description: Describe the issue in as much detail as possible.
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: steps_to_reproduce
|
||||
attributes:
|
||||
label: Steps to Reproduce
|
||||
description: What steps must be taken to reproduce this issue?
|
||||
placeholder: |
|
||||
1. Pull the container image
|
||||
2. Run the container with specific configuration
|
||||
3. Send a request
|
||||
4. Observe behavior
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: versions
|
||||
attributes:
|
||||
label: Versions
|
||||
description: List necessary versions here. This includes the container image tag, Docker version, operating system etc.
|
||||
placeholder: |
|
||||
- discordjs/proxy 1.0.0
|
||||
- Docker 27.5.1
|
||||
- Linux 6.1.0
|
||||
validations:
|
||||
required: true
|
||||
- type: dropdown
|
||||
id: priority
|
||||
attributes:
|
||||
label: Issue priority
|
||||
description: Please be realistic. If you need to elaborate on your reasoning, please use the issue description field above.
|
||||
options:
|
||||
- Low (slightly annoying)
|
||||
- Medium (should be fixed soon)
|
||||
- High (immediate attention needed)
|
||||
validations:
|
||||
required: true
|
||||
@@ -16,6 +16,7 @@ body:
|
||||
- discord.js
|
||||
- Documentation
|
||||
- Guide
|
||||
- Proxy Container
|
||||
- brokers
|
||||
- builders
|
||||
- collection
|
||||
@@ -24,7 +25,6 @@ body:
|
||||
- formatters
|
||||
- next
|
||||
- proxy
|
||||
- proxy-container
|
||||
- rest
|
||||
- structures
|
||||
- ui
|
||||
27
.github/ISSUE_TEMPLATE/05-guide.yml
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
name: Guide content
|
||||
description: Request to add to the guide or change existing content
|
||||
labels: [apps:guide]
|
||||
type: Task
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
Thanks for filing a suggestion! If you are here to ask a question, use Discord instead: https://discord.gg/djs
|
||||
- type: dropdown
|
||||
id: issuetype
|
||||
attributes:
|
||||
label: What is your suggestion about?
|
||||
options:
|
||||
- Requesting new content
|
||||
- Changing existing content
|
||||
- Correcting wrong information
|
||||
validations:
|
||||
required: true
|
||||
- type: input
|
||||
id: section
|
||||
attributes:
|
||||
label: Guide section the suggestion is about.
|
||||
- type: textarea
|
||||
id: body
|
||||
attributes:
|
||||
label: Describe your suggestion in detail.
|
||||
12
.github/PULL_REQUEST_TEMPLATE.md
vendored
@@ -1,12 +0,0 @@
|
||||
**Please describe the changes this PR makes and why it should be merged:**
|
||||
|
||||
**Status and versioning classification:**
|
||||
|
||||
<!--
|
||||
Please move lines that apply to you out of the comment:
|
||||
- Code changes have been tested against the Discord API, or there are no code changes
|
||||
- I know how to update typings and have done so, or typings don't need updating
|
||||
- This PR changes the library's interface (methods or parameters added)
|
||||
- This PR includes breaking changes (methods removed or renamed, parameters moved or removed)
|
||||
- This PR **only** includes non-code changes, like changes to documentation, README, etc.
|
||||
-->
|
||||
6
.github/issue-labeler.yml
vendored
@@ -1,6 +1,9 @@
|
||||
apps:guide:
|
||||
- "### Which (application|package|application or package) is this (bug
|
||||
report|feature request) for\\?\\n\\nGuide\\n"
|
||||
apps:proxy-container:
|
||||
- "### Which (application|package|application or package) is this (bug
|
||||
report|feature request) for\\?\\n\\nProxy Container\\n"
|
||||
apps:website:
|
||||
- "### Which (application|package|application or package) is this (bug
|
||||
report|feature request) for\\?\\n\\nDocumentation\\n"
|
||||
@@ -31,9 +34,6 @@ packages:next:
|
||||
packages:proxy:
|
||||
- "### Which (application|package|application or package) is this (bug
|
||||
report|feature request) for\\?\\n\\nproxy\\n"
|
||||
packages:proxy-container:
|
||||
- "### Which (application|package|application or package) is this (bug
|
||||
report|feature request) for\\?\\n\\nproxy-container\\n"
|
||||
packages:rest:
|
||||
- "### Which (application|package|application or package) is this (bug
|
||||
report|feature request) for\\?\\n\\nrest\\n"
|
||||
|
||||
10
.github/labeler.yml
vendored
@@ -3,6 +3,11 @@ apps:guide:
|
||||
- any-glob-to-any-file:
|
||||
- apps/guide/*
|
||||
- apps/guide/**/*
|
||||
apps:proxy-container:
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
- apps/proxy-container/*
|
||||
- apps/proxy-container/**/*
|
||||
apps:website:
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
@@ -68,11 +73,6 @@ packages:proxy:
|
||||
- any-glob-to-any-file:
|
||||
- packages/proxy/*
|
||||
- packages/proxy/**/*
|
||||
packages:proxy-container:
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
- packages/proxy-container/*
|
||||
- packages/proxy-container/**/*
|
||||
packages:rest:
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
|
||||
4
.github/labels.yml
vendored
@@ -4,6 +4,8 @@
|
||||
color: '5663e9'
|
||||
- name: apps:guide
|
||||
color: fbca04
|
||||
- name: apps:proxy-container
|
||||
color: fbca04
|
||||
- name: apps:website
|
||||
color: fbca04
|
||||
- name: backlog
|
||||
@@ -76,8 +78,6 @@
|
||||
color: fbca04
|
||||
- name: packages:proxy
|
||||
color: fbca04
|
||||
- name: packages:proxy-container
|
||||
color: fbca04
|
||||
- name: packages:rest
|
||||
color: fbca04
|
||||
- name: packages:structures
|
||||
|
||||
2
.github/workflows/cleanup-cache.yml
vendored
@@ -11,7 +11,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v5
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Cleanup caches
|
||||
run: |
|
||||
|
||||
8
.github/workflows/deploy-website.yml
vendored
@@ -14,12 +14,12 @@ jobs:
|
||||
if: github.repository_owner == 'discordjs'
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v5
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Install Node.js v22
|
||||
uses: actions/setup-node@v5
|
||||
- name: Install Node.js v24
|
||||
uses: actions/setup-node@v6
|
||||
with:
|
||||
node-version: 22
|
||||
node-version: 24
|
||||
package-manager-cache: false
|
||||
|
||||
- name: Install dependencies
|
||||
|
||||
17
.github/workflows/deprecate-version.yml
vendored
@@ -36,18 +36,21 @@ jobs:
|
||||
if: github.repository_owner == 'discordjs'
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v5
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Install Node.js v22
|
||||
uses: actions/setup-node@v5
|
||||
- name: Install Node.js v24
|
||||
uses: actions/setup-node@v6
|
||||
with:
|
||||
node-version: 22
|
||||
node-version: 24
|
||||
package-manager-cache: false
|
||||
|
||||
- name: Install dependencies
|
||||
uses: ./packages/actions/src/pnpmCache
|
||||
|
||||
- name: Deprecate
|
||||
run: pnpm exec npm-deprecate --name "${{inputs.version}}" --message "${{inputs.message || 'This version is deprecated. Please use a newer version.'}}" --package ${{inputs.package}}
|
||||
env:
|
||||
NODE_AUTH_TOKEN: ${{ secrets.NPM_PUBLISH_TOKEN }}
|
||||
uses: ./packages/actions/src/deprecateVersion
|
||||
with:
|
||||
package: ${{ inputs.package }}
|
||||
version: ${{ inputs.version }}
|
||||
message: ${{ inputs.message }}
|
||||
node-auth-token: ${{ secrets.NPM_PUBLISH_TOKEN }}
|
||||
|
||||
79
.github/workflows/documentation.yml
vendored
@@ -6,10 +6,11 @@ on:
|
||||
paths:
|
||||
- 'packages/*/src/**'
|
||||
- '!packages/create-discord-bot/**'
|
||||
- '!packages/proxy-container/**'
|
||||
- '!packages/ui/**'
|
||||
tags:
|
||||
- '**'
|
||||
- '!create-discord-app@*'
|
||||
- '!create-discord-bot@*'
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
ref:
|
||||
@@ -31,19 +32,19 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}
|
||||
TURBO_TEAM: ${{ secrets.TURBO_TEAM }}
|
||||
TURBO_TEAM: ${{ vars.TURBO_TEAM }}
|
||||
REF_TYPE: ${{ inputs.ref_type || github.ref_type }}
|
||||
if: github.repository_owner == 'discordjs'
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v5
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
ref: ${{ inputs.ref || '' }}
|
||||
|
||||
- name: Install Node.js v22
|
||||
uses: actions/setup-node@v5
|
||||
- name: Install Node.js v24
|
||||
uses: actions/setup-node@v6
|
||||
with:
|
||||
node-version: 22
|
||||
node-version: 24
|
||||
package-manager-cache: false
|
||||
|
||||
- name: Install dependencies
|
||||
@@ -54,7 +55,7 @@ jobs:
|
||||
|
||||
- name: Checkout main repository
|
||||
if: ${{ inputs.ref && inputs.ref != 'main' }}
|
||||
uses: actions/checkout@v5
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
path: 'main'
|
||||
|
||||
@@ -101,13 +102,6 @@ jobs:
|
||||
cd ../..
|
||||
done
|
||||
|
||||
- name: Checkout docs repository
|
||||
uses: actions/checkout@v5
|
||||
with:
|
||||
repository: 'discordjs/docs'
|
||||
token: ${{ secrets.DJS_DOCS }}
|
||||
path: 'out'
|
||||
|
||||
- name: Upload documentation to database
|
||||
if: ${{ env.REF_TYPE == 'tag' && (!inputs.ref || inputs.ref == 'main') }}
|
||||
env:
|
||||
@@ -164,20 +158,6 @@ jobs:
|
||||
package: ${{ steps.extract-tag.outputs.package }}
|
||||
version: ${{ steps.extract-tag.outputs.semver }}
|
||||
|
||||
- name: Move docs to correct directory
|
||||
if: ${{ env.REF_TYPE == 'tag' }}
|
||||
env:
|
||||
PACKAGE: ${{ steps.extract-tag.outputs.package }}
|
||||
SEMVER: ${{ steps.extract-tag.outputs.semver }}
|
||||
run: |
|
||||
mkdir -p "out/${PACKAGE}"
|
||||
if [[ "${PACKAGE}" == "discord.js" ]]; then
|
||||
mv "packages/${PACKAGE}/docs/docs.json" "out/${PACKAGE}/${SEMVER}.json"
|
||||
mv "packages/${PACKAGE}/docs/docs.api.json" "out/${PACKAGE}/${SEMVER}.api.json"
|
||||
else
|
||||
mv "packages/${PACKAGE}/docs/docs.api.json" "out/${PACKAGE}/${SEMVER}.api.json"
|
||||
fi
|
||||
|
||||
- name: Upload documentation to database
|
||||
if: ${{ env.REF_TYPE == 'branch' && (!inputs.ref || inputs.ref == 'main') }}
|
||||
env:
|
||||
@@ -222,51 +202,22 @@ jobs:
|
||||
CF_R2_DOCS_BUCKET: ${{ secrets.CF_R2_DOCS_BUCKET }}
|
||||
uses: ./main/packages/actions/src/uploadSplitDocumentation
|
||||
|
||||
- name: Move docs to correct directory
|
||||
if: ${{ env.REF_TYPE == 'branch' }}
|
||||
run: |
|
||||
declare -a PACKAGES=("brokers" "builders" "collection" "core" "discord.js" "formatters" "next" "proxy" "rest" "structures" "util" "voice" "ws")
|
||||
for PACKAGE in "${PACKAGES[@]}"; do
|
||||
if [ ! -d "packages/${PACKAGE}" ]; then
|
||||
echo "::notice::${PACKAGE} does not exist on this ref. Skipping..."
|
||||
continue
|
||||
fi
|
||||
|
||||
if [[ "${PACKAGE}" == "discord.js" ]]; then
|
||||
mkdir -p "out/${PACKAGE}"
|
||||
mv "packages/${PACKAGE}/docs/docs.json" "out/${PACKAGE}/${GITHUB_REF_NAME}.json"
|
||||
mv "packages/${PACKAGE}/docs/docs.api.json" "out/${PACKAGE}/${GITHUB_REF_NAME}.api.json"
|
||||
else
|
||||
mkdir -p "out/${PACKAGE}"
|
||||
mv "packages/${PACKAGE}/docs/docs.api.json" "out/${PACKAGE}/${GITHUB_REF_NAME}.api.json"
|
||||
fi
|
||||
done
|
||||
|
||||
- name: Commit and push
|
||||
run: |
|
||||
cd out
|
||||
git config user.name github-actions[bot]
|
||||
git config user.email 41898282+github-actions[bot]@users.noreply.github.com
|
||||
git add .
|
||||
git commit -m "Docs build for ${GITHUB_REF_TYPE} ${GITHUB_REF_NAME}: ${GITHUB_SHA}" || true
|
||||
git push
|
||||
|
||||
build-indices:
|
||||
needs: build-docs
|
||||
name: Build & upload search indices
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}
|
||||
TURBO_TEAM: ${{ secrets.TURBO_TEAM }}
|
||||
TURBO_TEAM: ${{ vars.TURBO_TEAM }}
|
||||
if: github.repository_owner == 'discordjs'
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v5
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Install Node.js v22
|
||||
uses: actions/setup-node@v5
|
||||
- name: Install Node.js v24
|
||||
uses: actions/setup-node@v6
|
||||
with:
|
||||
node-version: 22
|
||||
node-version: 24
|
||||
package-manager-cache: false
|
||||
|
||||
- name: Install dependencies
|
||||
@@ -277,7 +228,9 @@ jobs:
|
||||
|
||||
- name: Upload search indices to meilisearch
|
||||
env:
|
||||
DATABASE_URL: ${{ secrets.DATABASE_URL }}
|
||||
CF_D1_DOCS_API_KEY: ${{ secrets.CF_D1_DOCS_API_KEY }}
|
||||
CF_D1_DOCS_ID: ${{ secrets.CF_D1_DOCS_ID }}
|
||||
CF_ACCOUNT_ID: ${{ secrets.CF_ACCOUNT_ID }}
|
||||
SEARCH_API_URL: ${{ secrets.SEARCH_API_URL }}
|
||||
SEARCH_API_KEY: ${{ secrets.SEARCH_API_KEY }}
|
||||
uses: ./packages/actions/src/uploadSearchIndices
|
||||
|
||||
2
.github/workflows/label-sync.yml
vendored
@@ -15,7 +15,7 @@ jobs:
|
||||
if: github.repository_owner == 'discordjs'
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v5
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Label sync
|
||||
uses: crazy-max/ghaction-github-labeler@v5
|
||||
|
||||
93
.github/workflows/publish-dev-docker.yml
vendored
@@ -3,29 +3,88 @@ on:
|
||||
schedule:
|
||||
- cron: '0 */12 * * *'
|
||||
workflow_dispatch:
|
||||
env:
|
||||
IMAGE_NAME: discordjs/proxy
|
||||
jobs:
|
||||
docker-publish:
|
||||
name: Docker publish
|
||||
runs-on: ubuntu-latest
|
||||
if: github.repository_owner == 'discordjs'
|
||||
build:
|
||||
name: Build ${{ matrix.platform }}
|
||||
runs-on: ${{ matrix.runner }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- platform: linux/amd64
|
||||
runner: ubuntu-latest
|
||||
- platform: linux/arm64
|
||||
runner: ubuntu-24.04-arm
|
||||
steps:
|
||||
- name: Prepare
|
||||
run: |
|
||||
platform=${{ matrix.platform }}
|
||||
echo "PLATFORM_PAIR=${platform//\//-}" >> $GITHUB_ENV
|
||||
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v5
|
||||
|
||||
- name: Install Node.js v22
|
||||
uses: actions/setup-node@v5
|
||||
with:
|
||||
node-version: 22
|
||||
package-manager-cache: false
|
||||
|
||||
- name: Install dependencies
|
||||
uses: ./packages/actions/src/pnpmCache
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
|
||||
- name: Login to DockerHub
|
||||
run: echo ${{ secrets.DOCKER_ACCESS_TOKEN }} | docker login -u ${{ secrets.DOCKER_USERNAME }} --password-stdin
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
username: ${{ secrets.DOCKER_USERNAME }}
|
||||
password: ${{ secrets.DOCKER_ACCESS_TOKEN }}
|
||||
|
||||
- name: Build & push docker image
|
||||
run: docker build -f packages/proxy-container/Dockerfile -t discordjs/proxy:latest --push .
|
||||
- name: Build and push by digest
|
||||
id: build
|
||||
uses: docker/build-push-action@v6
|
||||
with:
|
||||
context: .
|
||||
file: apps/proxy-container/Dockerfile
|
||||
platforms: ${{ matrix.platform }}
|
||||
outputs: type=image,name=${{ env.IMAGE_NAME }},push-by-digest=true,name-canonical=true,push=true
|
||||
|
||||
- name: Export digest
|
||||
run: |
|
||||
mkdir -p /tmp/digests
|
||||
digest="${{ steps.build.outputs.digest }}"
|
||||
touch "/tmp/digests/${digest#sha256:}"
|
||||
|
||||
- name: Upload digest
|
||||
uses: actions/upload-artifact@v5
|
||||
with:
|
||||
name: digests-${{ env.PLATFORM_PAIR }}
|
||||
path: /tmp/digests/*
|
||||
if-no-files-found: error
|
||||
retention-days: 1
|
||||
|
||||
merge:
|
||||
name: Create and push manifest list
|
||||
runs-on: ubuntu-latest
|
||||
needs: build
|
||||
steps:
|
||||
- name: Download digests
|
||||
uses: actions/download-artifact@v6
|
||||
with:
|
||||
path: /tmp/digests
|
||||
pattern: digests-*
|
||||
merge-multiple: true
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
|
||||
- name: Login to DockerHub
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
username: ${{ secrets.DOCKER_USERNAME }}
|
||||
password: ${{ secrets.DOCKER_ACCESS_TOKEN }}
|
||||
|
||||
- name: Create manifest list and push
|
||||
working-directory: /tmp/digests
|
||||
run: |
|
||||
docker buildx imagetools create -t ${{ env.IMAGE_NAME }}:latest \
|
||||
$(printf '${{ env.IMAGE_NAME }}@sha256:%s ' *)
|
||||
|
||||
- name: Inspect image
|
||||
run: |
|
||||
docker buildx imagetools inspect ${{ env.IMAGE_NAME }}:latest
|
||||
|
||||
35
.github/workflows/publish-dev.yml
vendored
@@ -4,8 +4,8 @@ on:
|
||||
- cron: '0 */12 * * *'
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
pull:
|
||||
description: 'The pull number to check out'
|
||||
ref:
|
||||
description: 'The ref to check out. e.g. main, feat/new-feature, refs/pull/1234/head'
|
||||
required: false
|
||||
default: 'main'
|
||||
tag:
|
||||
@@ -24,7 +24,7 @@ jobs:
|
||||
id-token: write
|
||||
env:
|
||||
TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}
|
||||
TURBO_TEAM: ${{ secrets.TURBO_TEAM }}
|
||||
TURBO_TEAM: ${{ vars.TURBO_TEAM }}
|
||||
if: github.repository_owner == 'discordjs'
|
||||
steps:
|
||||
- uses: actions/create-github-app-token@v2
|
||||
@@ -33,26 +33,17 @@ jobs:
|
||||
app-id: ${{ vars.DISCORDJS_APP_ID }}
|
||||
private-key: ${{ secrets.DISCORDJS_APP_KEY_RELEASE }}
|
||||
|
||||
- name: Decide ref
|
||||
id: ref
|
||||
run: |
|
||||
if [ -n "${{ github.event.inputs.pull }}" ]; then
|
||||
echo "ref=refs/pull/${{ github.event.inputs.pull }}/head" >> $GITHUB_OUTPUT
|
||||
else
|
||||
echo "ref=refs/heads/main" >> $GITHUB_OUTPUT
|
||||
fi
|
||||
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v5
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
fetch-depth: 0
|
||||
token: ${{ steps.app-token.outputs.token }}
|
||||
ref: ${{ steps.ref.outputs.ref }}
|
||||
ref: ${{ inputs.ref }}
|
||||
|
||||
- name: Install Node.js v22
|
||||
uses: actions/setup-node@v5
|
||||
- name: Install Node.js v24
|
||||
uses: actions/setup-node@v6
|
||||
with:
|
||||
node-version: 22
|
||||
node-version: 24
|
||||
package-manager-cache: false
|
||||
registry-url: https://registry.npmjs.org/
|
||||
|
||||
@@ -63,13 +54,13 @@ jobs:
|
||||
run: pnpm run build
|
||||
|
||||
- name: Checkout main repository (non-main ref)
|
||||
if: ${{ steps.ref.outputs.ref != 'refs/heads/main' }}
|
||||
uses: actions/checkout@v5
|
||||
if: ${{ inputs.ref != 'main' }}
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
path: 'main'
|
||||
|
||||
- name: Install action deps (non-main ref)
|
||||
if: ${{ steps.ref.outputs.ref != 'refs/heads/main' }}
|
||||
if: ${{ inputs.ref != 'main' }}
|
||||
shell: bash
|
||||
working-directory: ./main
|
||||
env:
|
||||
@@ -79,7 +70,7 @@ jobs:
|
||||
pnpm install --filter @discordjs/actions --frozen-lockfile --prefer-offline --loglevel error
|
||||
|
||||
- name: Publish packages (non-main ref)
|
||||
if: ${{ steps.ref.outputs.ref != 'refs/heads/main' }}
|
||||
if: ${{ inputs.ref != 'main' }}
|
||||
uses: ./main/packages/actions/src/releasePackages
|
||||
with:
|
||||
exclude: '@discordjs/docgen'
|
||||
@@ -91,7 +82,7 @@ jobs:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Publish packages (main ref)
|
||||
if: ${{ steps.ref.outputs.ref == 'refs/heads/main' }}
|
||||
if: ${{ inputs.ref == 'main' }}
|
||||
uses: ./packages/actions/src/releasePackages
|
||||
with:
|
||||
exclude: '@discordjs/docgen'
|
||||
|
||||
102
.github/workflows/publish-docker.yml
vendored
@@ -1,28 +1,98 @@
|
||||
name: Publish docker images
|
||||
on:
|
||||
workflow_dispatch:
|
||||
env:
|
||||
IMAGE_NAME: discordjs/proxy
|
||||
jobs:
|
||||
docker-publish:
|
||||
name: Docker publish
|
||||
runs-on: ubuntu-latest
|
||||
build:
|
||||
name: Build ${{ matrix.platform }}
|
||||
runs-on: ${{ matrix.runner }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- platform: linux/amd64
|
||||
runner: ubuntu-latest
|
||||
- platform: linux/arm64
|
||||
runner: ubuntu-24.04-arm
|
||||
steps:
|
||||
- name: Prepare
|
||||
run: |
|
||||
platform=${{ matrix.platform }}
|
||||
echo "PLATFORM_PAIR=${platform//\//-}" >> $GITHUB_ENV
|
||||
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v5
|
||||
|
||||
- name: Install Node.js v22
|
||||
uses: actions/setup-node@v5
|
||||
with:
|
||||
node-version: 22
|
||||
package-manager-cache: false
|
||||
|
||||
- name: Install dependencies
|
||||
uses: ./packages/actions/src/pnpmCache
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
|
||||
- name: Login to DockerHub
|
||||
run: echo ${{ secrets.DOCKER_ACCESS_TOKEN }} | docker login -u ${{ secrets.DOCKER_USERNAME }} --password-stdin
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
username: ${{ secrets.DOCKER_USERNAME }}
|
||||
password: ${{ secrets.DOCKER_ACCESS_TOKEN }}
|
||||
|
||||
- name: Build & push docker image
|
||||
run: docker build -f packages/proxy-container/Dockerfile -t discordjs/proxy:$(cut -d '.' -f1 <<< $(jq --raw-output '.version' packages/proxy-container/package.json)) --push .
|
||||
- name: Build and push by digest
|
||||
id: build
|
||||
uses: docker/build-push-action@v6
|
||||
with:
|
||||
context: .
|
||||
file: apps/proxy-container/Dockerfile
|
||||
platforms: ${{ matrix.platform }}
|
||||
outputs: type=image,name=${{ env.IMAGE_NAME }},push-by-digest=true,name-canonical=true,push=true
|
||||
|
||||
- name: Export digest
|
||||
run: |
|
||||
mkdir -p /tmp/digests
|
||||
digest="${{ steps.build.outputs.digest }}"
|
||||
touch "/tmp/digests/${digest#sha256:}"
|
||||
|
||||
- name: Upload digest
|
||||
uses: actions/upload-artifact@v5
|
||||
with:
|
||||
name: digests-${{ env.PLATFORM_PAIR }}
|
||||
path: /tmp/digests/*
|
||||
if-no-files-found: error
|
||||
retention-days: 1
|
||||
|
||||
merge:
|
||||
name: Create and push manifest list
|
||||
runs-on: ubuntu-latest
|
||||
needs: build
|
||||
steps:
|
||||
- name: Download digests
|
||||
uses: actions/download-artifact@v6
|
||||
with:
|
||||
path: /tmp/digests
|
||||
pattern: digests-*
|
||||
merge-multiple: true
|
||||
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Get Major Version
|
||||
id: version
|
||||
run: |
|
||||
FULL_VER=$(jq --raw-output '.version' apps/proxy-container/package.json)
|
||||
MAJOR=$(echo $FULL_VER | cut -d '.' -f1)
|
||||
echo "major=$MAJOR" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
|
||||
- name: Login to DockerHub
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
username: ${{ secrets.DOCKER_USERNAME }}
|
||||
password: ${{ secrets.DOCKER_ACCESS_TOKEN }}
|
||||
|
||||
- name: Create manifest list and push
|
||||
working-directory: /tmp/digests
|
||||
run: |
|
||||
docker buildx imagetools create -t ${{ env.IMAGE_NAME }}:${{ steps.version.outputs.major }} \
|
||||
$(printf '${{ env.IMAGE_NAME }}@sha256:%s ' *)
|
||||
|
||||
- name: Inspect image
|
||||
run: |
|
||||
docker buildx imagetools inspect ${{ env.IMAGE_NAME }}:${{ steps.version.outputs.major }}
|
||||
|
||||
50
.github/workflows/publish-release.yml
vendored
@@ -1,50 +0,0 @@
|
||||
name: Publish Release
|
||||
on:
|
||||
release:
|
||||
types: [released]
|
||||
jobs:
|
||||
npm-publish:
|
||||
name: npm publish
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
id-token: write
|
||||
env:
|
||||
TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}
|
||||
TURBO_TEAM: ${{ secrets.TURBO_TEAM }}
|
||||
if: github.repository_owner == 'discordjs'
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v5
|
||||
|
||||
- name: Install Node.js v22
|
||||
uses: actions/setup-node@v5
|
||||
with:
|
||||
node-version: 22
|
||||
package-manager-cache: false
|
||||
registry-url: https://registry.npmjs.org/
|
||||
|
||||
- name: Install dependencies
|
||||
uses: ./packages/actions/src/pnpmCache
|
||||
|
||||
- name: Build dependencies
|
||||
run: pnpm run build
|
||||
|
||||
- name: Extract package and semver from tag
|
||||
id: extract-tag
|
||||
uses: ./packages/actions/src/formatTag
|
||||
with:
|
||||
tag: ${{ github.ref_name }}
|
||||
|
||||
- name: Publish package
|
||||
run: |
|
||||
pnpm --filter=${{ steps.extract-tag.outputs.subpackage == 'true' && '@discordjs/' || '' }}${{ steps.extract-tag.outputs.package }} publish --provenance --no-git-checks
|
||||
env:
|
||||
NODE_AUTH_TOKEN: ${{ secrets.NPM_PUBLISH_TOKEN }}
|
||||
|
||||
- name: create-discord-bot -> create-discord-app
|
||||
if: steps.extract-tag.outputs.package == 'create-discord-bot'
|
||||
run: |
|
||||
pnpm --filter=create-discord-bot run rename-to-app
|
||||
pnpm --filter=create-discord-app publish --provenance --no-git-checks
|
||||
env:
|
||||
NODE_AUTH_TOKEN: ${{ secrets.NPM_PUBLISH_TOKEN }}
|
||||
14
.github/workflows/release.yml
vendored
@@ -18,7 +18,7 @@ on:
|
||||
- '@discordjs/collection'
|
||||
- '@discordjs/core'
|
||||
- 'create-discord-bot'
|
||||
- '@discordjs/docgen'
|
||||
# - '@discordjs/docgen'
|
||||
- '@discordjs/formatters'
|
||||
- '@discordjs/next'
|
||||
- '@discordjs/proxy'
|
||||
@@ -44,7 +44,7 @@ jobs:
|
||||
id-token: write
|
||||
env:
|
||||
TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}
|
||||
TURBO_TEAM: ${{ secrets.TURBO_TEAM }}
|
||||
TURBO_TEAM: ${{ vars.TURBO_TEAM }}
|
||||
if: github.repository_owner == 'discordjs'
|
||||
steps:
|
||||
- uses: actions/create-github-app-token@v2
|
||||
@@ -55,15 +55,15 @@ jobs:
|
||||
permission-contents: write
|
||||
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v5
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
token: ${{ steps.app-token.outputs.token }}
|
||||
ref: ${{ inputs.ref || '' }}
|
||||
|
||||
- name: Install Node.js v22
|
||||
uses: actions/setup-node@v5
|
||||
- name: Install Node.js v24
|
||||
uses: actions/setup-node@v6
|
||||
with:
|
||||
node-version: 22
|
||||
node-version: 24
|
||||
package-manager-cache: false
|
||||
registry-url: https://registry.npmjs.org/
|
||||
|
||||
@@ -75,7 +75,7 @@ jobs:
|
||||
|
||||
- name: Checkout main repository
|
||||
if: ${{ inputs.ref && inputs.ref != 'main' }}
|
||||
uses: actions/checkout@v5
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
path: 'main'
|
||||
|
||||
|
||||
60
.github/workflows/remove-tag.yml
vendored
Normal file
@@ -0,0 +1,60 @@
|
||||
name: Remove tag
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
tag:
|
||||
description: The tag to remove
|
||||
required: true
|
||||
type: string
|
||||
message:
|
||||
description: Deprecation message
|
||||
required: false
|
||||
type: string
|
||||
jobs:
|
||||
removal:
|
||||
runs-on: ubuntu-latest
|
||||
if: github.repository_owner == 'discordjs'
|
||||
strategy:
|
||||
matrix:
|
||||
package:
|
||||
- '@discordjs/brokers'
|
||||
- '@discordjs/builders'
|
||||
- '@discordjs/collection'
|
||||
- '@discordjs/core'
|
||||
- 'create-discord-app'
|
||||
- 'create-discord-bot'
|
||||
- '@discordjs/formatters'
|
||||
- 'discord.js'
|
||||
- '@discordjs/next'
|
||||
- '@discordjs/proxy'
|
||||
- '@discordjs/rest'
|
||||
- '@discordjs/structures'
|
||||
- '@discordjs/util'
|
||||
- '@discordjs/voice'
|
||||
- '@discordjs/ws'
|
||||
fail-fast: false
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Install Node.js
|
||||
uses: actions/setup-node@v6
|
||||
with:
|
||||
node-version: 24
|
||||
registry-url: 'https://registry.npmjs.org'
|
||||
|
||||
- name: Install dependencies
|
||||
uses: ./packages/actions/src/pnpmCache
|
||||
|
||||
- name: Remove tag
|
||||
run: pnpm dist-tag rm "${{ matrix.package }}" "${{ inputs.tag }}"
|
||||
env:
|
||||
NODE_AUTH_TOKEN: ${{ secrets.NPM_PUBLISH_TOKEN }}
|
||||
|
||||
- name: Deprecate version
|
||||
uses: ./packages/actions/src/deprecateVersion
|
||||
with:
|
||||
package: ${{ matrix.package }}
|
||||
version: '*-${{ inputs.tag }}.*'
|
||||
message: ${{ inputs.message }}
|
||||
node-auth-token: ${{ secrets.NPM_PUBLISH_TOKEN }}
|
||||
10
.github/workflows/tests.yml
vendored
@@ -12,17 +12,17 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}
|
||||
TURBO_TEAM: ${{ secrets.TURBO_TEAM }}
|
||||
TURBO_TEAM: ${{ vars.TURBO_TEAM }}
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v5
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Install Node.js v22
|
||||
uses: actions/setup-node@v5
|
||||
- name: Install Node.js v24
|
||||
uses: actions/setup-node@v6
|
||||
with:
|
||||
node-version: 22
|
||||
node-version: 24
|
||||
package-manager-cache: false
|
||||
|
||||
- name: Install dependencies
|
||||
|
||||
42
.github/workflows/upload-readmes.yml
vendored
Normal file
@@ -0,0 +1,42 @@
|
||||
name: Upload README.md files
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- 'main'
|
||||
paths:
|
||||
- 'packages/*/README.md'
|
||||
workflow_dispatch:
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.head_ref || github.ref }}
|
||||
cancel-in-progress: true
|
||||
jobs:
|
||||
upload-readmes:
|
||||
name: Upload README.md files
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}
|
||||
TURBO_TEAM: ${{ vars.TURBO_TEAM }}
|
||||
if: github.repository_owner == 'discordjs'
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Install Node.js
|
||||
uses: actions/setup-node@v6
|
||||
with:
|
||||
node-version: 24
|
||||
package-manager-cache: false
|
||||
|
||||
- name: Install dependencies
|
||||
uses: ./packages/actions/src/pnpmCache
|
||||
|
||||
- name: Build dependencies
|
||||
run: pnpm --filter @discordjs/actions... run build
|
||||
|
||||
- name: Upload README.md files
|
||||
env:
|
||||
CF_R2_READMES_ACCESS_KEY_ID: ${{ secrets.CF_R2_READMES_ACCESS_KEY_ID }}
|
||||
CF_R2_READMES_SECRET_ACCESS_KEY: ${{ secrets.CF_R2_READMES_SECRET_ACCESS_KEY }}
|
||||
CF_R2_READMES_BUCKET: ${{ secrets.CF_R2_READMES_BUCKET }}
|
||||
CF_R2_READMES_URL: ${{ secrets.CF_R2_READMES_URL }}
|
||||
uses: ./packages/actions/src/uploadReadmeFiles
|
||||
20
README.md
@@ -5,12 +5,13 @@
|
||||
</p>
|
||||
<br />
|
||||
<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/badge/join_us-on_discord-5865F2?logo=discord&logoColor=white" alt="Discord server" /></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://github.com/discordjs/discord.js/actions"><img src="https://github.com/discordjs/discord.js/actions/workflows/tests.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://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://opencollective.com/discordjs"><img src="https://img.shields.io/opencollective/backers/discordjs?maxAge=3600&logo=opencollective" alt="backers" /></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>
|
||||
@@ -26,6 +27,7 @@ This repository contains multiple packages with separate [releases][github-relea
|
||||
## Packages
|
||||
|
||||
- `discord.js` ([source][source]) - A powerful Node.js module for interacting with the Discord API
|
||||
- `create-discord-bot` ([source][create-discord-bot-source]) - A CLI tool to quickly scaffold a Discord bot project
|
||||
- `@discordjs/brokers` ([source][brokers-source]) - A collection of brokers for use with discord.js
|
||||
- `@discordjs/builders` ([source][builders-source]) - A utility package for easily building Discord API payloads
|
||||
- `@discordjs/collection` ([source][collection-source]) - A powerful utility data structure
|
||||
@@ -34,10 +36,14 @@ This repository contains multiple packages with separate [releases][github-relea
|
||||
- `@discordjs/proxy` ([source][proxy-source]) - A wrapper around `@discordjs/rest` for running an HTTP proxy
|
||||
- `@discordjs/rest` ([source][rest-source]) - A module for interacting with the Discord REST API
|
||||
- `@discordjs/structures` ([source][structures-source]) - A wrapper around Discord's structures
|
||||
- `@discordjs/voice` ([source][voice-source]) - A module for interacting with the Discord Voice API
|
||||
- `@discordjs/util` ([source][util-source]) - A collection of utility functions
|
||||
- `@discordjs/voice` ([source][voice-source]) - A module for interacting with the Discord Voice API
|
||||
- `@discordjs/ws` ([source][ws-source]) - A wrapper around Discord's gateway
|
||||
|
||||
## Containers
|
||||
|
||||
- `discordjs/proxy` ([source][proxy-container-source]) - A lightweight HTTP proxy for Discord's API
|
||||
|
||||
## Links
|
||||
|
||||
- [Website][website] ([source][website-source])
|
||||
@@ -65,9 +71,9 @@ If you don't understand something in the documentation, you are experiencing pro
|
||||
[website]: https://discord.js.org
|
||||
[website-source]: https://github.com/discordjs/discord.js/tree/main/apps/website
|
||||
[documentation]: https://discord.js.org/docs
|
||||
[guide]: https://discordjs.guide/
|
||||
[guide-source]: https://github.com/discordjs/guide
|
||||
[guide-update]: https://discordjs.guide/additional-info/changes-in-v14.html
|
||||
[guide]: https://discordjs.guide
|
||||
[guide-source]: https://github.com/discordjs/discord.js/tree/main/apps/guide
|
||||
[guide-update]: https://discordjs.guide/legacy/additional-info/changes-in-v14
|
||||
[discord]: https://discord.gg/djs
|
||||
[discord-developers]: https://discord.gg/discord-developers
|
||||
[source]: https://github.com/discordjs/discord.js/tree/main/packages/discord.js
|
||||
@@ -77,6 +83,7 @@ If you don't understand something in the documentation, you are experiencing pro
|
||||
[rpc-source]: https://github.com/discordjs/RPC
|
||||
[contributing]: https://github.com/discordjs/discord.js/blob/main/.github/CONTRIBUTING.md
|
||||
[github-releases]: https://github.com/discordjs/discord.js/releases
|
||||
[create-discord-bot-source]: https://github.com/discordjs/discord.js/tree/main/packages/create-discord-bot
|
||||
[brokers-source]: https://github.com/discordjs/discord.js/tree/main/packages/brokers
|
||||
[builders-source]: https://github.com/discordjs/discord.js/tree/main/packages/builders
|
||||
[collection-source]: https://github.com/discordjs/discord.js/tree/main/packages/collection
|
||||
@@ -85,7 +92,8 @@ If you don't understand something in the documentation, you are experiencing pro
|
||||
[proxy-source]: https://github.com/discordjs/discord.js/tree/main/packages/proxy
|
||||
[rest-source]: https://github.com/discordjs/discord.js/tree/main/packages/rest
|
||||
[structures-source]: https://github.com/discordjs/discord.js/tree/main/packages/structures
|
||||
[voice-source]: https://github.com/discordjs/discord.js/tree/main/packages/voice
|
||||
[util-source]: https://github.com/discordjs/discord.js/tree/main/packages/util
|
||||
[voice-source]: https://github.com/discordjs/discord.js/tree/main/packages/voice
|
||||
[ws-source]: https://github.com/discordjs/discord.js/tree/main/packages/ws
|
||||
[proxy-container-source]: https://github.com/discordjs/discord.js/tree/main/apps/proxy-container
|
||||
[good-first-issue]: https://github.com/discordjs/discord.js/contribute
|
||||
|
||||
@@ -107,7 +107,7 @@
|
||||
"allowArbitraryExtensions": false,
|
||||
"allowImportingTsExtensions": false,
|
||||
"module": "ESNext",
|
||||
"moduleResolution": "nodenext",
|
||||
"moduleResolution": "Bundler",
|
||||
"resolveJsonModule": true,
|
||||
"resolvePackageJsonExports": false,
|
||||
"resolvePackageJsonImports": false,
|
||||
|
||||
2
apps/guide/.gitignore
vendored
@@ -16,7 +16,9 @@ pids
|
||||
.env*.local
|
||||
|
||||
# Dist
|
||||
.open-next
|
||||
.next
|
||||
.wrangler
|
||||
.source
|
||||
|
||||
# Miscellaneous
|
||||
|
||||
@@ -5,8 +5,9 @@
|
||||
</p>
|
||||
<br />
|
||||
<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/badge/join_us-on_discord-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/tests.yml/badge.svg" alt="Build status" /></a>
|
||||
<a href="https://opencollective.com/discordjs"><img src="https://img.shields.io/opencollective/backers/discordjs?maxAge=3600&logo=opencollective" alt="backers" /></a>
|
||||
</p>
|
||||
<p>
|
||||
<a href="https://vercel.com/?utm_source=discordjs&utm_campaign=oss"><img src="https://raw.githubusercontent.com/discordjs/discord.js/main/.github/powered-by-vercel.svg" alt="Vercel" /></a>
|
||||
@@ -24,8 +25,7 @@
|
||||
|
||||
## Contributing
|
||||
|
||||
Before creating an issue, please ensure that it hasn't already been reported/suggested, and double-check the existing guide.
|
||||
See [the contribution guide][./contributing] if you'd like to submit a PR.
|
||||
Before creating an issue, please ensure that it hasn't already been reported/suggested, and double-check the existing guide. See [the contributing guide][contributing] if you'd like to submit a pull request.
|
||||
|
||||
## Local Development
|
||||
|
||||
@@ -38,9 +38,9 @@ If you don't understand something in the documentation, you are experiencing pro
|
||||
[website]: https://discord.js.org
|
||||
[website-source]: https://github.com/discordjs/discord.js/tree/main/apps/website
|
||||
[documentation]: https://discord.js.org/docs
|
||||
[guide]: https://discord.js/guide
|
||||
[guide]: https://discordjs.guide
|
||||
[guide-source]: https://github.com/discordjs/discord.js/tree/main/apps/guide
|
||||
[guide-update]: https://discordjs.guide/additional-info/changes-in-v14.html
|
||||
[guide-update]: https://discordjs.guide/legacy/additional-info/changes-in-v14
|
||||
[discord]: https://discord.gg/djs
|
||||
[source]: https://github.com/discordjs/discord.js/tree/main/apps/guide
|
||||
[contributing]: https://github.com/discordjs/discord.js/blob/main/.github/CONTRIBUTING.md
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"title": "Additional Features"
|
||||
}
|
||||
@@ -143,7 +143,7 @@ client.on(Events.InteractionCreate, (interaction) => {
|
||||
});
|
||||
```
|
||||
|
||||
In this piece of code, the Promises are [chain resolved](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/then#Chaining) with each other, and if one of the Promises gets rejected, the function passed to `.catch()` gets called. Here's the same code but with async/await:
|
||||
In this piece of code, the Promises are [chain resolved](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Promise/then#Chaining) with each other, and if one of the Promises gets rejected, the function passed to `.catch()` gets called. Here's the same code but with async/await:
|
||||
|
||||
```js title="promise-example.js" lineNumbers=9
|
||||
client.on(Events.InteractionCreate, async (interaction) => {
|
||||
|
||||
@@ -519,7 +519,7 @@ You can no longer use the `deleted` property to check if a structure was deleted
|
||||
|
||||
### ApplicationCommand
|
||||
|
||||
NFSW commands are supported.
|
||||
NSFW commands are supported.
|
||||
|
||||
### Attachment
|
||||
|
||||
|
||||
@@ -7,10 +7,9 @@ It extends JavaScript's native `Map` class, so it has all the `Map` features and
|
||||
|
||||
<Callout type="warn">
|
||||
If you're not familiar with `Map`, read [MDN's page on
|
||||
it](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map) before continuing. You
|
||||
should be familiar with `Array`
|
||||
[methods](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array) as well. We will
|
||||
also use some ES6 features, so read up [here](./es6-syntax) if you do not know what they are.
|
||||
it](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Map) before continuing. You should be
|
||||
familiar with `Array` [methods](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array) as
|
||||
well. We will also use some ES6 features, so read up [here](./es6-syntax) if you do not know what they are.
|
||||
</Callout>
|
||||
|
||||
A `Map` allows for an association between unique keys and their values.
|
||||
@@ -45,7 +44,7 @@ Methods that follow this philosophy of staying close to the `Array` interface ar
|
||||
|
||||
## Converting to Array
|
||||
|
||||
Since `Collection` extends `Map`, it is an [iterable](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols), and can be converted to an `Array` through either `Array.from()` or spread syntax (`...collection`).
|
||||
Since `Collection` extends `Map`, it is an [iterable](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Iteration_protocols), and can be converted to an `Array` through either `Array.from()` or spread syntax (`...collection`).
|
||||
|
||||
```js
|
||||
// For values.
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
{
|
||||
"title": "Additional Info",
|
||||
"pages": ["async-await", "collections", "es6-syntax", "notation", "rest-api", "proxy"]
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
---
|
||||
title: Using a proxy
|
||||
title: Using a Proxy
|
||||
---
|
||||
|
||||
This guide will show you how to set up a proxy with discord.js. This may be necessary if you are deploying your bot to a server with a firewall only allowing outside traffic through the proxy.
|
||||
|
||||
@@ -69,7 +69,7 @@ const { request } = require('undici');
|
||||
showcase!
|
||||
</Callout>
|
||||
|
||||
Random cat's API is available at [https://aws.random.cat/meow](https://aws.random.cat/meow) and returns a [JSON](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON) response. To actually fetch data from the API, you're going to do the following:
|
||||
Random cat's API is available at [https://aws.random.cat/meow](https://aws.random.cat/meow) and returns a [JSON](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/JSON) response. To actually fetch data from the API, you're going to do the following:
|
||||
|
||||
```js
|
||||
const catResult = await request('https://aws.random.cat/meow');
|
||||
@@ -119,7 +119,7 @@ client.on(Events.InteractionCreate, async (interaction) => {
|
||||
});
|
||||
```
|
||||
|
||||
Here, you are using JavaScript's native [URLSearchParams class](https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams) to create a [query string](https://en.wikipedia.org/wiki/Query_string) for the URL so that the Urban Dictionary server can parse it and know what you want to look up.
|
||||
Here, you are using JavaScript's native [URLSearchParams class](https://developer.mozilla.org/docs/Web/API/URLSearchParams) to create a [query string](https://en.wikipedia.org/wiki/Query_string) for the URL so that the Urban Dictionary server can parse it and know what you want to look up.
|
||||
|
||||
If you were to do `/urban hello world`, then the URL would become https://api.urbandictionary.com/v0/define?term=hello%20world since the string `"hello world"` is encoded.
|
||||
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
---
|
||||
title: Creating slash commands
|
||||
title: Creating Slash Commands
|
||||
---
|
||||
|
||||
## Creating slash commands
|
||||
|
||||
import { Step, Steps } from 'fumadocs-ui/components/steps';
|
||||
import { File, Folder, Files } from 'fumadocs-ui/components/files';
|
||||
|
||||
|
||||
@@ -49,7 +49,7 @@ Create a `deploy-commands.js` file in your project directory. This file will be
|
||||
Add two more properties to your `config.json` file, which we'll need in the deployment script:
|
||||
|
||||
- `clientId`: Your application's client id ([Discord Developer Portal](https://discord.com/developers/applications) > "General Information" > application id)
|
||||
- `guildId`: Your development server's id ([Enable developer mode](https://support.discord.com/hc/en-us/articles/206346498) > Right-click the server title > "Copy ID")
|
||||
- `guildId`: Your development server's id ([Enable developer mode](https://support.discord.com/hc/articles/206346498) > Right-click the server title > "Copy ID")
|
||||
|
||||
```json title="config.json"
|
||||
{
|
||||
|
||||
@@ -64,7 +64,7 @@ We recommend attaching a `.commands` property to your client instance so that yo
|
||||
native path utility module. `path` helps construct paths to access files and directories. One of the advantages of the
|
||||
`path` module is that it automatically detects the operating system and uses the appropriate joiners. - The
|
||||
`Collection` class extends JavaScript's native
|
||||
[`Map`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map) class, and includes more
|
||||
[`Map`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Map) class, and includes more
|
||||
extensive, useful functionality. `Collection` is used to store and efficiently retrieve commands for execution.
|
||||
</Callout>
|
||||
|
||||
|
||||
@@ -204,7 +204,7 @@ You'll notice the code looks very similar to the command loading above it - read
|
||||
|
||||
The `Client` class in discord.js extends the [`EventEmitter`](https://nodejs.org/api/events.html#events_class_eventemitter) class. Therefore, the `client` object exposes the [`.on()`](https://nodejs.org/api/events.html#events_emitter_on_eventname_listener) and [`.once()`](https://nodejs.org/api/events.html#events_emitter_once_eventname_listener) methods that you can use to register event listeners. These methods take two arguments: the event name and a callback function. These are defined in your separate event files as `name` and `execute`.
|
||||
|
||||
The callback function passed takes argument(s) returned by its respective event, collects them in an `args` array using the `...` [rest parameter syntax](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/rest_parameters), then calls `event.execute()` while passing in the `args` array using the `...` [spread syntax](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax). They are used here because different events in discord.js have different numbers of arguments. The rest parameter collects these variable number of arguments into a single array, and the spread syntax then takes these elements and passes them to the `execute` function.
|
||||
The callback function passed takes argument(s) returned by its respective event, collects them in an `args` array using the `...` [rest parameter syntax](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Functions/rest_parameters), then calls `event.execute()` while passing in the `args` array using the `...` [spread syntax](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Operators/Spread_syntax). They are used here because different events in discord.js have different numbers of arguments. The rest parameter collects these variable number of arguments into a single array, and the spread syntax then takes these elements and passes them to the `execute` function.
|
||||
|
||||
After this, listening for other events is as easy as creating a new file in the `events` folder. The event handler will automatically retrieve and register it whenever you restart your bot.
|
||||
|
||||
|
||||
@@ -33,7 +33,7 @@ console.log(token);
|
||||
|
||||
## Using environment variables
|
||||
|
||||
Environment variables are, as the name suggets, values you can pass to your environment (e.g. terminal session, Docker container, node process). This has the benefit that you can keep your code the same for different execution contexts.
|
||||
Environment variables are, as the name suggests, values you can pass to your environment (e.g. terminal session, Docker container, node process). This has the benefit that you can keep your code the same for different execution contexts.
|
||||
|
||||
```txt title=".env"
|
||||
A=Hello World
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"title": "Improving Your Dev Environment"
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
---
|
||||
title: Package scripts
|
||||
title: Package Scripts
|
||||
---
|
||||
|
||||
## Setting up package.json scripts
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
title: Introduction
|
||||
---
|
||||
|
||||
import { GithubInfo } from 'fumadocs-ui/components/github-info';
|
||||
import { GithubInfo } from '@/components/GitHubInfo';
|
||||
|
||||
<GithubInfo owner="discordjs" repo="discord.js" />
|
||||
|
||||
@@ -11,7 +11,7 @@ This guide will teach you things such as:
|
||||
|
||||
- How to get a bot [up and running](./legacy/preparations/app-setup) from scratch;
|
||||
- How to properly [create](./legacy/app-creation/project-setup), [organize](./legacy/app-creation/handling-commands), and expand on your commands;
|
||||
- In-depth explanations and examples regarding popular topics (e.g. [components](./legacy/popular-topics/display-components) ,[reactions](./legacy/popular-topics/reactions), [embeds](./legacy/popular-topics/embeds), [canvas](./legacy/popular-topics/canvas));
|
||||
- In-depth explanations and examples regarding popular topics (e.g. [components](./legacy/popular-topics/display-components), [reactions](./legacy/popular-topics/reactions), [embeds](./legacy/popular-topics/embeds), [canvas](./legacy/popular-topics/canvas));
|
||||
- Working with databases (e.g. [sequelize](./legacy/sequelize/) and [keyv](./legacy/keyv/keyv));
|
||||
- Getting started with [sharding](./legacy/sharding/);
|
||||
- And much more.
|
||||
@@ -30,7 +30,7 @@ If you don't know JavaScript but would like to learn about it, here are a few li
|
||||
- [JavaScript.info, a modern javascript tutorial](https://javascript.info/)
|
||||
- [Codecademy's interactive JavaScript course](https://www.codecademy.com/learn/introduction-to-javascript)
|
||||
- [Nodeschool, for both JavaScript and Node.js lessons](https://nodeschool.io/)
|
||||
- [MDN's JavaScript guide and full documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript)
|
||||
- [MDN's JavaScript guide and full documentation](https://developer.mozilla.org/docs/Web/JavaScript)
|
||||
- [Google, your best friend](https://google.com)
|
||||
|
||||
Take your pick, learn some JavaScript, and once you feel like you're confident enough to make a bot, come back and get started!
|
||||
|
||||
|
Before Width: | Height: | Size: 55 KiB After Width: | Height: | Size: 59 KiB |
|
Before Width: | Height: | Size: 25 KiB |
@@ -2,30 +2,27 @@
|
||||
title: Modals
|
||||
---
|
||||
|
||||
With modals you can create pop-up forms that allow users to provide you with formatted inputs through submissions. We'll cover how to create, show, and receive modal forms using discord.js!
|
||||
Modals are pop-up forms that allow you to prompt users for additional input. This form-like interaction response blocks the user from interacting with Discord until the modal is submitted or dismissed. In this section, we will cover how to create, show, and receive modals using discord.js!
|
||||
|
||||
<Callout>
|
||||
This page is a follow-up to the [interactions (slash commands) page](../slash-commands/advanced-creation). Please
|
||||
carefully read that section first, so that you can understand the methods used in this section.
|
||||
This page is a follow-up to the [interactions (slash commands) page](../slash-commands/advanced-creation). Reading
|
||||
that page first will help you understand the concepts introduced in this page.
|
||||
</Callout>
|
||||
|
||||
## Building and responding with modals
|
||||
|
||||
Unlike message components, modals aren't strictly components themselves. They're a callback structure used to respond to interactions.
|
||||
With the `ModalBuilder` class, discord.js offers a convenient way to build modals step by step using setters and callbacks.
|
||||
|
||||
<Callout>
|
||||
You can have a maximum of five `ActionRowBuilder`s per modal builder, and one `TextInputBuilder` within an
|
||||
`ActionRowBuilder`. Currently, you can only use `TextInputBuilder`s in modal action rows builders.
|
||||
You can have a maximum of five top-level components per modal, each of which can be a label or a text display
|
||||
component.
|
||||
</Callout>
|
||||
|
||||
To create a modal you construct a new `ModalBuilder`. You can then use the setters to add the custom id and title.
|
||||
|
||||
```js
|
||||
const { Events, ModalBuilder } = require('discord.js');
|
||||
|
||||
client.on(Events.InteractionCreate, async (interaction) => {
|
||||
if (!interaction.isChatInputCommand()) return;
|
||||
|
||||
if (interaction.commandName === 'ping') {
|
||||
const modal = new ModalBuilder().setCustomId('myModal').setTitle('My Modal');
|
||||
|
||||
@@ -35,105 +32,321 @@ client.on(Events.InteractionCreate, async (interaction) => {
|
||||
```
|
||||
|
||||
<Callout>
|
||||
The custom id is a developer-defined string of up to 100 characters. Use this field to ensure you can uniquely define
|
||||
all incoming interactions from your modals!
|
||||
The `customId` is a developer-defined string of up to 100 characters and uniquely identifies this modal instance. You
|
||||
can use it to differentiate incoming interactions.
|
||||
</Callout>
|
||||
|
||||
The next step is to add the input fields in which users responding can enter free-text. Adding inputs is similar to adding components to messages.
|
||||
The next step is adding components to the modal, which may either request input or present information.
|
||||
|
||||
At the end, we then call `ChatInputCommandInteraction#showModal` to display the modal to the user.
|
||||
### Label
|
||||
|
||||
<Callout type="warn">
|
||||
If you're using typescript you'll need to specify the type of components your action row holds. This can be done by specifying the generic parameter in `ActionRowBuilder`:
|
||||
|
||||
```diff
|
||||
- new ActionRowBuilder()
|
||||
+ new ActionRowBuilder<ModalActionRowComponentBuilder>()
|
||||
```
|
||||
|
||||
</Callout>
|
||||
Label components wrap around other modal components (text input, select menus, etc.) to add a label and description to it.
|
||||
Since labels are not stand-alone components, we will use this example label to wrap a text input component in the next section:
|
||||
|
||||
```js
|
||||
const { ActionRowBuilder, Events, ModalBuilder, TextInputBuilder, TextInputStyle } = require('discord.js');
|
||||
const { LabelBuilder, ModalBuilder } = require('discord.js');
|
||||
|
||||
client.on(Events.InteractionCreate, async (interaction) => {
|
||||
if (!interaction.isChatInputCommand()) return;
|
||||
|
||||
if (interaction.commandName === 'ping') {
|
||||
// [!code focus:11]
|
||||
// Create the modal
|
||||
const modal = new ModalBuilder().setCustomId('myModal').setTitle('My Modal');
|
||||
|
||||
// Add components to modal
|
||||
// [!code ++:5]
|
||||
const hobbiesLabel = new LabelBuilder()
|
||||
// The label is a large header text that identifies the interactive component for the user.
|
||||
.setLabel('What are some of your favorite hobbies?')
|
||||
// The description is an additional optional subtext that aids the label.
|
||||
.setDescription('Activities you like to participate in');
|
||||
|
||||
// Create the text input components
|
||||
const favoriteColorInput = new TextInputBuilder()
|
||||
.setCustomId('favoriteColorInput')
|
||||
// The label is the prompt the user sees for this input
|
||||
.setLabel("What's your favorite color?")
|
||||
// Short means only a single line of text
|
||||
.setStyle(TextInputStyle.Short);
|
||||
|
||||
const hobbiesInput = new TextInputBuilder()
|
||||
.setCustomId('hobbiesInput')
|
||||
.setLabel("What's some of your favorite hobbies?")
|
||||
// Paragraph means multiple lines of text.
|
||||
.setStyle(TextInputStyle.Paragraph);
|
||||
|
||||
// An action row only holds one text input,
|
||||
// so you need one action row per text input.
|
||||
const firstActionRow = new ActionRowBuilder().addComponents(favoriteColorInput);
|
||||
const secondActionRow = new ActionRowBuilder().addComponents(hobbiesInput);
|
||||
|
||||
// Add inputs to the modal
|
||||
modal.addComponents(firstActionRow, secondActionRow);
|
||||
|
||||
// Show the modal to the user
|
||||
await interaction.showModal(modal); // [!code word:showModal]
|
||||
// [!code ++:2]
|
||||
// Add label to the modal
|
||||
modal.addLabelComponents(hobbiesLabel);
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
Restart your bot and invoke the `/ping` command again. You should see a popup form resembling the image below:
|
||||
|
||||

|
||||
|
||||
<Callout type="warn">
|
||||
Showing a modal must be the first response to an interaction. You cannot `defer()` or `deferUpdate()` then show a
|
||||
modal later.
|
||||
<Callout>
|
||||
The `label` field has a max length of 45 characters. The `description` field has a max length of 100 characters.
|
||||
</Callout>
|
||||
|
||||
### Input styles
|
||||
### Text input
|
||||
|
||||
Currently there are two different input styles available:
|
||||
Text input components prompt users for single or multi line free-form text.
|
||||
|
||||
- `Short`, a single-line text entry;
|
||||
- `Paragraph`, a multi-line text entry similar to the HTML `<textarea>`;
|
||||
```js
|
||||
const { LabelBuilder, ModalBuilder, TextInputBuilder, TextInputStyle } = require('discord.js');
|
||||
|
||||
### Input properties
|
||||
client.on(Events.InteractionCreate, async (interaction) => {
|
||||
if (!interaction.isChatInputCommand()) return;
|
||||
if (interaction.commandName === 'ping') {
|
||||
// [!code focus:10]
|
||||
// Create the modal
|
||||
const modal = new ModalBuilder().setCustomId('myModal').setTitle('My Modal');
|
||||
|
||||
In addition to the `customId`, `label` and `style`, a text input can be customised in a number of ways to apply validation, prompt the user, or set default values via the `TextInputBuilder` methods:
|
||||
// [!code ++:6]
|
||||
const hobbiesInput = new TextInputBuilder()
|
||||
.setCustomId('hobbiesInput')
|
||||
// Short means a single line of text.
|
||||
.setStyle(TextInputStyle.Short)
|
||||
// Placeholder text displayed inside the text input box
|
||||
.setPlaceholder('card games, films, books, etc.');
|
||||
|
||||
// [!code focus:10]
|
||||
const hobbiesLabel = new LabelBuilder()
|
||||
// The label is a large header that identifies the interactive component for the user.
|
||||
.setLabel("What's some of your favorite hobbies?")
|
||||
// The description is an additional optional subtext that aids the label.
|
||||
.setDescription('Activities you like to participate in')
|
||||
// [!code ++:2]
|
||||
// Set text input as the component of the label
|
||||
.setTextInputComponent(hobbiesInput);
|
||||
|
||||
// Add the label to the modal
|
||||
modal.addLabelComponents(hobbiesLabel);
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
#### Input styles
|
||||
|
||||
Discord offers two different input styles:
|
||||
|
||||
- `Short`, a single-line text entry
|
||||
- `Paragraph`, a multi-line text entry
|
||||
|
||||
#### Input properties
|
||||
|
||||
A text input field can be customized in a number of ways to apply validation or set default values via the following `TextInputBuilder` methods:
|
||||
|
||||
```js
|
||||
const input = new TextInputBuilder()
|
||||
// set the maximum number of characters to allow
|
||||
// Set the component id (this is not the custom id)
|
||||
.setId(1)
|
||||
// Set the maximum number of characters allowed
|
||||
.setMaxLength(1_000)
|
||||
// set the minimum number of characters required for submission
|
||||
// Set the minimum number of characters required for submission
|
||||
.setMinLength(10)
|
||||
// set a placeholder string to prompt the user
|
||||
.setPlaceholder('Enter some text!')
|
||||
// set a default value to pre-fill the input
|
||||
// Set a default value to prefill the text input
|
||||
.setValue('Default')
|
||||
// require a value in this input field
|
||||
// Require a value in this text input field (defaults to true)
|
||||
.setRequired(true);
|
||||
```
|
||||
|
||||
<Callout>
|
||||
The `id` field is used to differentiate components within interactions (which text input, selection, etc.). In
|
||||
contrast, the `customId` covered earlier identifies the interaction (which modal, command, etc.).
|
||||
</Callout>
|
||||
|
||||
### Select menu
|
||||
|
||||
Select menus allow you to limit user input to a preselected list of values. Discord also offers select menus linked directly to native Discord entities like users, roles, and channels.
|
||||
Since they behave very similarly to how they do in messages, please refer to the [corresponding guide page](../interactive-components/select-menus) for more information on configuring select menus.
|
||||
|
||||
Here again, you wrap the select menu with a label component to add context to the selection and add the label to the modal:
|
||||
|
||||
```js
|
||||
// ...
|
||||
|
||||
client.on(Events.InteractionCreate, async (interaction) => {
|
||||
if (!interaction.isChatInputCommand()) return;
|
||||
if (interaction.commandName === 'ping') {
|
||||
// Create the modal
|
||||
const modal = new ModalBuilder().setCustomId('myModal').setTitle('My Modal');
|
||||
|
||||
// ...
|
||||
|
||||
// [!code focus:24]
|
||||
// [!code ++:23]
|
||||
const favoriteStarterSelect = new StringSelectMenuBuilder()
|
||||
.setCustomId('starter')
|
||||
.setPlaceholder('Make a selection!')
|
||||
// Modal only property on select menus to prevent submission, defaults to true
|
||||
.setRequired(true)
|
||||
.addOptions(
|
||||
// String select menu options
|
||||
new StringSelectMenuOptionBuilder()
|
||||
// Label displayed to user
|
||||
.setLabel('Bulbasaur')
|
||||
// Description of option
|
||||
.setDescription('The dual-type Grass/Poison Seed Pokémon.')
|
||||
// Value returned to you in modal submission
|
||||
.setValue('bulbasaur'),
|
||||
new StringSelectMenuOptionBuilder()
|
||||
.setLabel('Charmander')
|
||||
.setDescription('The Fire-type Lizard Pokémon.')
|
||||
.setValue('charmander'),
|
||||
new StringSelectMenuOptionBuilder()
|
||||
.setLabel('Squirtle')
|
||||
.setDescription('The Water-type Tiny Turtle Pokémon.')
|
||||
.setValue('squirtle'),
|
||||
);
|
||||
|
||||
// ...
|
||||
|
||||
// [!code focus:4]
|
||||
// [!code ++:4]
|
||||
const favoriteStarterLabel = new LabelBuilder()
|
||||
.setLabel("What's your favorite Gen 1 Pokémon starter?")
|
||||
// Set string select menu as component of the label
|
||||
.setStringSelectMenuComponent(favoriteStarterSelect);
|
||||
|
||||
// [!code focus:3]
|
||||
// Add labels to modal
|
||||
modal.addLabelComponents(hobbiesLabel); // [!code --]
|
||||
modal.addLabelComponents(hobbiesLabel, favoriteStarterLabel); // [!code ++]
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
### Text display
|
||||
|
||||
Text display components offer you a way to give additional context to the user that doesn't fit into labels or isn't directly connected to any specific input field.
|
||||
|
||||
```js
|
||||
// ...
|
||||
|
||||
client.on(Events.InteractionCreate, async (interaction) => {
|
||||
if (!interaction.isChatInputCommand()) return;
|
||||
if (interaction.commandName === 'ping') {
|
||||
// Create the modal
|
||||
const modal = new ModalBuilder().setCustomId('myModal').setTitle('My Modal');
|
||||
|
||||
// ...
|
||||
|
||||
// [!code focus:3]
|
||||
// [!code ++:3]
|
||||
const text = new TextDisplayBuilder().setContent(
|
||||
'Text that could not fit in to a label or description\n-# Markdown can also be used',
|
||||
);
|
||||
|
||||
// [!code focus:5]
|
||||
// Add components to modal
|
||||
modal
|
||||
// [!code --]
|
||||
.addLabelComponents(hobbiesLabel, favoriteStarterLabel);
|
||||
// [!code ++:2]
|
||||
.addLabelComponents(hobbiesLabel, favoriteStarterLabel)
|
||||
.addTextDisplayComponents(text);
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
### File upload
|
||||
|
||||
File upload components allow you to prompt the user to upload a file from their system.
|
||||
|
||||
<Callout type="warn">
|
||||
Discord **does not send the file data** itself in the resulting interaction. You will have to download it from
|
||||
Discords CDN to process and validate it. Do not execute arbitrary code people upload via your app!
|
||||
</Callout>
|
||||
|
||||
```js
|
||||
// ...
|
||||
|
||||
client.on(Events.InteractionCreate, async (interaction) => {
|
||||
if (!interaction.isChatInputCommand()) return;
|
||||
if (interaction.commandName === 'ping') {
|
||||
// Create the modal
|
||||
const modal = new ModalBuilder().setCustomId('myModal').setTitle('My Modal');
|
||||
|
||||
// ...
|
||||
|
||||
// [!code focus:2]
|
||||
// [!code ++]
|
||||
const pictureOfTheWeekUpload = new FileUploadBuilder().setCustomId('picture');
|
||||
|
||||
// ...
|
||||
|
||||
// [!code focus:12]
|
||||
// [!code ++:5]
|
||||
const pictureOfTheWeekLabel = new LabelBuilder()
|
||||
.setLabel('Picture of the Week')
|
||||
.setDescription('The best pictures you have taken this week')
|
||||
// Set file upload as component of the label
|
||||
.setFileUploadComponent(pictureOfTheWeekUpload);
|
||||
|
||||
// Add components to modal
|
||||
modal
|
||||
.addLabelComponents(hobbiesLabel, favoriteStarterLabel)
|
||||
// [!code --]
|
||||
.addTextDisplayComponents(text);
|
||||
// [!code ++:2]
|
||||
.addTextDisplayComponents(text)
|
||||
.addLabelComponents(pictureOfTheWeekLabel);
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
#### File upload properties
|
||||
|
||||
A file upload component can be customized to apply validation via the following `FileUploadBuilder` methods:
|
||||
|
||||
```js
|
||||
const pictureOfTheWeekUpload = new FileUploadBuilder()
|
||||
// Set the optional identifier for component
|
||||
.setId(1)
|
||||
// Minimum number of items that must be uploaded (defaults to 1); min 0, max 10
|
||||
.setMinValues(1)
|
||||
// Maximum number of items that can be uploaded (defaults to 1); max 10
|
||||
.setMaxValues(1)
|
||||
// Require a value in this file upload component (defaults to true)
|
||||
.setRequired(true);
|
||||
```
|
||||
|
||||
<Callout>
|
||||
The `id` field is used to differentiate components within interactions (which text input, selection, etc.).
|
||||
In contrast, the `customId` covered earlier identifies the interaction (which modal, command, etc.).
|
||||
|
||||
You **cannot** limit and validate the **file size** or the **file extension**.
|
||||
|
||||
</Callout>
|
||||
|
||||
### Responding with a modal
|
||||
|
||||
With the modal built, call `ChatInputCommandInteraction#showModal()` to send the interaction response to Discord and display the modal to the user.
|
||||
|
||||
<Callout type="warn">
|
||||
Showing a modal must be the first response to an interaction. You **cannot** defer modals.
|
||||
</Callout>
|
||||
|
||||
```js
|
||||
// ...
|
||||
// [!code focus:5]
|
||||
client.on(Events.InteractionCreate, async (interaction) => {
|
||||
if (!interaction.isChatInputCommand()) return;
|
||||
if (interaction.commandName === 'ping') {
|
||||
// Create the modal
|
||||
const modal = new ModalBuilder().setCustomId('myModal').setTitle('My Modal');
|
||||
|
||||
// ...
|
||||
|
||||
// [!code focus:9]
|
||||
// Add components to modal
|
||||
modal
|
||||
.addLabelComponents(hobbiesLabel, favoriteStarterLabel)
|
||||
.addTextDisplayComponents(text)
|
||||
.addLabelComponents(pictureOfTheWeekLabel);
|
||||
|
||||
// [!code ++:2]
|
||||
// Show modal to the user
|
||||
await interaction.showModal(modal);
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
Restart your bot and invoke the `/ping` command again. You should see the modal as shown below:
|
||||
|
||||

|
||||
|
||||
## Receiving modal submissions
|
||||
|
||||
### Interaction collectors
|
||||
|
||||
Modal submissions can be collected within the scope of the interaction that showed it by utilising an `InteractionCollector`, or the `ChatInputCommandInteraction#awaitModalSubmit` promisified method. These both provide instances of the `ModalSubmitInteraction` class as collected items.
|
||||
Modal submissions can be collected within the scope of the interaction that sent the modal by utilizing an `InteractionCollector`, or the `ChatInputCommandInteraction#awaitModalSubmit` promisified version. These both provide instances of the `ModalSubmitInteraction` class as collected items.
|
||||
|
||||
For a detailed guide on receiving message components via collectors, please refer to the [collectors guide](../popular-topics/collectors#interaction-collectors).
|
||||
For a detailed guide on handling interactions with collectors, please refer to the [collectors guide](../popular-topics/collectors#interaction-collectors).
|
||||
|
||||
### The interactionCreate event
|
||||
|
||||
@@ -141,6 +354,8 @@ To receive a `ModalSubmitInteraction` event, attach an `Client#interactionCreate
|
||||
|
||||
```js
|
||||
client.on(Events.InteractionCreate, (interaction) => {
|
||||
// ...
|
||||
// [!code word:isModalSubmit] [!code highlight:2]
|
||||
if (!interaction.isModalSubmit()) return;
|
||||
console.log(interaction);
|
||||
});
|
||||
@@ -157,7 +372,7 @@ The `ModalSubmitInteraction` class provides the same methods as the `ChatInputCo
|
||||
- `deleteReply()`
|
||||
- `followUp()`
|
||||
|
||||
If the modal was shown from a `ButtonInteraction` or `StringSelectMenuInteraction`, it will also provide these methods, which behave equally:
|
||||
If the modal was prompted through a button or select menu interaction, these methods may be used to update the underlying message:
|
||||
|
||||
- `update()`
|
||||
- `deferUpdate()`
|
||||
@@ -165,28 +380,40 @@ If the modal was shown from a `ButtonInteraction` or `StringSelectMenuInteractio
|
||||
```js
|
||||
client.on(Events.InteractionCreate, async (interaction) => {
|
||||
if (!interaction.isModalSubmit()) return;
|
||||
console.log(interaction);
|
||||
if (interaction.customId === 'myModal') {
|
||||
// [!code highlight] [!code word:reply]
|
||||
await interaction.reply({ content: 'Your submission was received successfully!' });
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
<Callout>
|
||||
If you're using typescript, you can use the `ModalSubmitInteraction#isFromMessage` typeguard, to make sure the
|
||||
received interaction was from a `MessageComponentInteraction`.
|
||||
If you're using TypeScript, you can use the `ModalSubmitInteraction#isFromMessage()` type guard to make sure the
|
||||
received interaction originated from a `MessageComponentInteraction`.
|
||||
</Callout>
|
||||
|
||||
## Extracting data from modal submissions
|
||||
|
||||
You'll most likely need to read the data sent by the user in the modal. You can do this by accessing the `ModalSubmitInteraction#fields`. From there you can call `ModalSubmitFields#getTextInputValue` with the custom id of the text input to get the value.
|
||||
You can process the submitted input fields through the use of convenience getters on `ModalSubmitInteraction#fields`. The library provides getters for all modal components with user submitted data:
|
||||
|
||||
```js
|
||||
client.on(Events.InteractionCreate, (interaction) => {
|
||||
if (!interaction.isModalSubmit()) return;
|
||||
if (interaction.customId === 'myModal') {
|
||||
await interaction.reply({ content: 'Your submission was received successfully!' });
|
||||
|
||||
// Get the data entered by the user
|
||||
const favoriteColor = interaction.fields.getTextInputValue('favoriteColorInput');
|
||||
const hobbies = interaction.fields.getTextInputValue('hobbiesInput');
|
||||
console.log({ favoriteColor, hobbies });
|
||||
// [!code focus:6]
|
||||
// Get the data entered by the user
|
||||
const hobbies = interaction.fields.getTextInputValue('hobbiesInput');
|
||||
const starter = interaction.fields.getStringSelectValues('starter');
|
||||
const picture = interaction.fields.getUploadedFiles('picture');
|
||||
|
||||
console.log({ hobbies, starter, picture });
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
<Callout>
|
||||
Empty text input submissions return an empty string `""`. Select menus without a selection return an empty array `[]`.
|
||||
</Callout>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
---
|
||||
title: Action rows
|
||||
title: Action Rows
|
||||
---
|
||||
|
||||
Action rows are a layout component with five "slots" that can be filled with other components. At the time of writing this guide, buttons take up one slot and select menus take up five "slots". Accordingly, each `ActionRow` can hold up to 5 buttons or a single select menu. A message can have up to five rows without providing the `IsComponentsV2` message flag. If you want to place buttons or action rows into the message body, they have to be wrapped inside rows.
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
{
|
||||
"title": "Interactive Components",
|
||||
"pages": ["action-rows", "buttons", "select-menus", "interactions"]
|
||||
}
|
||||
|
||||
@@ -2,13 +2,17 @@
|
||||
title: Select Menus
|
||||
---
|
||||
|
||||
Select menus are one of the `MessageComponent` classes, which can be sent via messages or interaction responses.
|
||||
Select menus are interactive components which can be sent via messages, interaction responses, or in modals.
|
||||
|
||||
<Callout>
|
||||
This page is a follow-up to the [slash commands](../slash-commands/advanced-creation) section and [action
|
||||
rows](../interactive-components/action-rows) page. Please carefully read those pages first so that you can understand
|
||||
the methods used here.
|
||||
</Callout>
|
||||
<Callout>
|
||||
This page is for using select menus in messages. For using [select menus in
|
||||
modals](../interactions/modals#select-menu) visit the modal page
|
||||
</Callout>
|
||||
|
||||
## Building string select menus
|
||||
|
||||
@@ -22,13 +26,17 @@ const { StringSelectMenuBuilder, StringSelectMenuOptionBuilder, SlashCommandBuil
|
||||
module.exports = {
|
||||
// data: new SlashCommandBuilder()...
|
||||
async execute(interaction) {
|
||||
const select = new StringSelectMenuBuilder()
|
||||
const favoriteStarterSelect = new StringSelectMenuBuilder()
|
||||
.setCustomId('starter')
|
||||
.setPlaceholder('Make a selection!')
|
||||
.addOptions(
|
||||
// String select menu options
|
||||
new StringSelectMenuOptionBuilder()
|
||||
// Label displayed to user
|
||||
.setLabel('Bulbasaur')
|
||||
// Description of option
|
||||
.setDescription('The dual-type Grass/Poison Seed Pokémon.')
|
||||
// Value returned in select menu interaction
|
||||
.setValue('bulbasaur'),
|
||||
new StringSelectMenuOptionBuilder()
|
||||
.setLabel('Charmander')
|
||||
@@ -59,17 +67,21 @@ const {
|
||||
StringSelectMenuOptionBuilder,
|
||||
SlashCommandBuilder,
|
||||
} = require('discord.js');
|
||||
// [!code focus:30]
|
||||
// [!code focus:33]
|
||||
module.exports = {
|
||||
// data: new SlashCommandBuilder()...
|
||||
async execute(interaction) {
|
||||
const select = new StringSelectMenuBuilder()
|
||||
const favoriteStarterSelect = new StringSelectMenuBuilder()
|
||||
.setCustomId('starter')
|
||||
.setPlaceholder('Make a selection!')
|
||||
.addOptions(
|
||||
// String select menu options
|
||||
new StringSelectMenuOptionBuilder()
|
||||
// Label displayed to user
|
||||
.setLabel('Bulbasaur')
|
||||
// Description of option
|
||||
.setDescription('The dual-type Grass/Poison Seed Pokémon.')
|
||||
// Value returned in select menu interaction
|
||||
.setValue('bulbasaur'),
|
||||
new StringSelectMenuOptionBuilder()
|
||||
.setLabel('Charmander')
|
||||
@@ -81,9 +93,11 @@ module.exports = {
|
||||
.setValue('squirtle'),
|
||||
);
|
||||
|
||||
// [!code ++:6]
|
||||
const row = new ActionRowBuilder().addComponents(select);
|
||||
// [!code ++:8]
|
||||
// Adding a string select menu to an action row
|
||||
const row = new ActionRowBuilder().addComponents(favoriteStarterSelect);
|
||||
|
||||
// Reply with the action row
|
||||
await interaction.reply({
|
||||
content: 'Choose your starter!',
|
||||
components: [row],
|
||||
@@ -99,7 +113,7 @@ module.exports = {
|
||||
components](../popular-topics/display-components) system.
|
||||
</Callout>
|
||||
|
||||
### String select menu options
|
||||
## String select menu options
|
||||
|
||||
String select menu options are custom-defined by the user, as shown in the example above. At a minimum, each option must have it's `label` and `value` defined. The label is shown to the user, while the value is included in the interaction sent to the bot.
|
||||
|
||||
|
||||
@@ -80,7 +80,7 @@ For a more detailed setup, check out the [Keyv readme](https://github.com/jaredw
|
||||
|
||||
## Usage
|
||||
|
||||
Keyv exposes a familiar [Map](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map)-like API. However, it only has `set`, `get`, `delete`, and `clear` methods. Additionally, instead of immediately returning data, these methods return [Promises](../additional-info/async-await) that resolve with the data.
|
||||
Keyv exposes a familiar [Map](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Map)-like API. However, it only has `set`, `get`, `delete`, and `clear` methods. Additionally, instead of immediately returning data, these methods return [Promises](../additional-info/async-await) that resolve with the data.
|
||||
|
||||
```js
|
||||
(async () => {
|
||||
@@ -105,7 +105,7 @@ Although Keyv can assist in any scenario where you need key-value data, we will
|
||||
<Callout>
|
||||
This section will still work with any provider supported by Keyv. We recommend PostgreSQL for larger applications.
|
||||
|
||||
Do note that "large" here should be interpreted as absolutely massive. Sqlite is used at scale by many companies and products you use every single day. The slight overhead should not be noticable for the application of a Discord bot at all unless you are dealing with super complicated queries or are using specific features that do not exist in sqlite.
|
||||
Do note that "large" here should be interpreted as absolutely massive. Sqlite is used at scale by many companies and products you use every single day. The slight overhead should not be noticeable for the application of a Discord bot at all unless you are dealing with super complicated queries or are using specific features that do not exist in sqlite.
|
||||
|
||||
You can find out if sqlite might be a good choice for your project (it very likely is) by reading [their own article](https://www.sqlite.org/whentouse.html) on the topic.
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
"pages": [
|
||||
"[MessageCircleQuestion][FAQ](/legacy/popular-topics/faq)",
|
||||
"[ArrowDownToLine][Updating to v14](/legacy/additional-info/changes-in-v14)",
|
||||
"[LibraryBig][Documentation](https://discord.js.org/docs)",
|
||||
"external:[LibraryBig][Documentation](https://discord.js.org/docs)",
|
||||
"[Info][Introduction](/legacy)",
|
||||
"---Setup---",
|
||||
"preparations",
|
||||
|
||||
@@ -75,7 +75,7 @@ await interaction.followUp(`You sent the two messages ${formatted} apart.`);
|
||||
|
||||
Common-tags is a library all about working with template literals.
|
||||
So far, you have probably only used them for interpolating variables into your strings, but they can do a whole lot more.
|
||||
If you've got time, you should check out [the MDN's documentation about _tagged literals_.](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals#Tagged_templates).
|
||||
If you've got time, you should check out [the MDN's documentation about _tagged literals_.](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Template_literals#Tagged_templates).
|
||||
|
||||
Ever got annoyed your multi-line strings had nasty bits of indentation in them,
|
||||
but you did not want to remove the indentation in your source code?
|
||||
|
||||
@@ -81,7 +81,7 @@ After importing the `@napi-rs/canvas` module and initializing it, you should loa
|
||||
<Callout>
|
||||
`@napi-rs/canvas` works almost identical to HTML5 Canvas. You can read the HTML5 Canvas tutorials on
|
||||
[w3Schools](https://www.w3schools.com/html/html5_canvas.asp) and
|
||||
[MDN](https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API) for more information later!
|
||||
[MDN](https://developer.mozilla.org/docs/Web/API/Canvas_API) for more information later!
|
||||
</Callout>
|
||||
|
||||
```js lineNumbers=10 title="index.js"
|
||||
@@ -101,7 +101,7 @@ client.on(Events.InteractionCreate, async (interaction) => {
|
||||
|
||||
Now, you need to load the image you want to use into Canvas.
|
||||
|
||||
We'll be using [this image](https://github.com/discordjs/guide/blob/main/guide/popular-topics/images/canvas.jpg) as the background in the welcome image, but you can use whatever you want. Be sure to download the file, name it `wallpaper.jpg`, and save it inside the same directory as your main bot file.
|
||||
We'll be using [this image](https://github.com/discordjs/discord.js/blob/main/apps/guide/content/docs/legacy/popular-topics/images/canvas.jpg) as the background in the welcome image, but you can use whatever you want. Be sure to download the file, name it `wallpaper.jpg`, and save it inside the same directory as your main bot file.
|
||||
|
||||
```js lineNumbers=10 title="index.js"
|
||||
client.on(Events.InteractionCreate, async (interaction) => {
|
||||
@@ -222,7 +222,7 @@ client.on(Events.InteractionCreate, async (interaction) => {
|
||||
|
||||
<Callout>
|
||||
You can read more about `context.arc()` on [w3schools](https://www.w3schools.com/tags/canvas_arc.asp) or
|
||||
[MDN](https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/arc).
|
||||
[MDN](https://developer.mozilla.org/docs/Web/API/CanvasRenderingContext2D/arc).
|
||||
</Callout>
|
||||
|
||||
### Adding in text
|
||||
|
||||
@@ -24,9 +24,9 @@ collector.on('end', (collected) => {
|
||||
});
|
||||
```
|
||||
|
||||
You can provide a `filter` key to the object parameter of `createMessageCollector()`. The value to this key should be a function that returns a boolean value to indicate if this message should be collected or not. To check for multiple conditions in your filter you can connect them using [logical operators](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Expressions_and_Operators#logical_operators). If you don't provide a filter all messages in the channel the collector was started on will be collected.
|
||||
You can provide a `filter` key to the object parameter of `createMessageCollector()`. The value to this key should be a function that returns a boolean value to indicate if this message should be collected or not. To check for multiple conditions in your filter you can connect them using [logical operators](https://developer.mozilla.org/docs/Web/JavaScript/Guide/Expressions_and_Operators#logical_operators). If you don't provide a filter all messages in the channel the collector was started on will be collected.
|
||||
|
||||
Note that the above example uses [implicit return](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions#function_body) for the filter function and passes it to the options object using the [object property shorthand](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Object_initializer#property_definitions) notation.
|
||||
Note that the above example uses [implicit return](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Functions/Arrow_functions#function_body) for the filter function and passes it to the options object using the [object property shorthand](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Operators/Object_initializer#property_definitions) notation.
|
||||
|
||||
If a message passes through the filter, it will trigger the `collect` event for the `collector` you've created. This message is then passed into the event listener as `collected` and the provided function is executed. In the above example, you simply log the message. Once the collector finishes collecting based on the provided end conditions the `end` event emits.
|
||||
|
||||
@@ -81,7 +81,7 @@ interaction.reply({ content: item.question, withResponse: true }).then((response
|
||||
|
||||
<Callout>
|
||||
If you don't understand how `.some()` works, you can read about it in more detail
|
||||
[here](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/some).
|
||||
[here](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array/some).
|
||||
</Callout>
|
||||
|
||||
In this filter, you iterate through the answers to find what you want. You would like to ignore the case because simple typos can happen, so you convert each answer to its lowercase form and check if it's equal to the response in lowercase form as well. In the options section, you only want to allow one answer to pass through, hence the `max: 1` setting.
|
||||
|
||||
@@ -20,7 +20,7 @@ To use the display components, you need to pass the `IsComponentsV2` message fla
|
||||
|
||||
## The component `id`
|
||||
|
||||
All components can be passed an optional, unique, `id` field holding a 32-bit integer identifier to later identify them in interaction responses. Do not confuse this with the `custom_id` field for interactive components! You can find more information about this [in the discord api documentation](https://discord.com/developers/docs/components/reference#anatomy-of-a-component). Discord will automatically populate the `id` of components that don't have the `id` specified in the payload sequentially starting from `1`. The `id` value `0` is treated as empty. The order components are automatically filled in is an implementation detail and not officially document. If you want to work with the `id` (for example to find and replace the content of a specific component lateron), you should explicitly specify it.
|
||||
All components can be passed an optional, unique, `id` field holding a 32-bit integer identifier to later identify them in interaction responses. Do not confuse this with the `custom_id` field for interactive components! You can find more information about this [in the discord api documentation](https://discord.com/developers/docs/components/reference#anatomy-of-a-component). Discord will automatically populate the `id` of components that don't have the `id` specified in the payload sequentially starting from `1`. The `id` value `0` is treated as empty. The order components are automatically filled in is an implementation detail and not officially document. If you want to work with the `id` (for example to find and replace the content of a specific component later on), you should explicitly specify it.
|
||||
|
||||
In the following sections, we will explain all available display component types in detail and show you some examples on how you can use them.
|
||||
|
||||
@@ -32,6 +32,9 @@ Text Display components let you add markdown-formatted text to your message and
|
||||
Sending user and role mentions in text display components **will notify users and roles**! You can and should control
|
||||
mentions with the `allowedMentions` message option.
|
||||
</Callout>
|
||||
<Callout>
|
||||
Text display components can be used in modals. See the [modal guide](../interactions/modals#text-display) for usage.
|
||||
</Callout>
|
||||
|
||||
The example below shows how you can send a Text Display component in a channel.
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@ Example: `The messages must be an Array, Collection, or number.`
|
||||
|
||||
### JavaScript errors
|
||||
|
||||
JavaScript errors are thrown by node itself or by discord.js. These errors can easily be fixed by looking at the type of error and the stack trace. You can find a full list of types [here](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error) and a list of common JavaScript errors [here](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Errors).
|
||||
JavaScript errors are thrown by node itself or by discord.js. These errors can easily be fixed by looking at the type of error and the stack trace. You can find a full list of types [here](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Error) and a list of common JavaScript errors [here](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Errors).
|
||||
|
||||
Examples:
|
||||
|
||||
@@ -189,12 +189,18 @@ This error originates from an invalid call to `bulkDelete()`. Make sure you are
|
||||
|
||||
This error happens when fetching multiple members via `GuildMemberManager#fetch()` and:
|
||||
|
||||
- The `GuildMembers` intent is not specified or enabled in the dev dashboard
|
||||
- The internet connection is somewhat bad
|
||||
- The amount of members fetched is large (about 50 thousand and upwards)
|
||||
- The `GuildMembers` intent is not specified or enabled in the [developer portal](https://discord.com/developers/applications).
|
||||
- The internet connection is somewhat bad.
|
||||
|
||||
You can specify the time to wait for with the `time` option in the `.fetch()` call. Another solution could be to move your bot to a faster infrastructure, if available.
|
||||
|
||||
### Request with opcode 8 was rate limited.
|
||||
|
||||
You are requesting all guild members too frequently on the same guild.
|
||||
|
||||
- Look for instances of `GuildMemberManager#fetch()` that do not specify users.
|
||||
- Make sure to handle the returned promise gracefully. Discord may change the exact values of this rate limit in the future. You can find all relevant details in the caught error.
|
||||
|
||||
### MaxListenersExceededWarning: Possible EventEmitter memory leak detected...
|
||||
|
||||
This error is caused by spawning a large number of event listeners, usually for the client. The most common cause of this is nesting your event listeners instead of separating them. The way to fix this error is to make sure you do not nest your listeners; it is **not** to use `emitter.setMaxListeners()` as the error suggests.
|
||||
|
||||
@@ -8,7 +8,7 @@ Rather than blindly enabling all intents, consider what information you actually
|
||||
|
||||
## Privileged Intents
|
||||
|
||||
Discord defines some intents as "privileged" due to the data's sensitive nature. At the time of writing this article, privileged intents are `GuildPresences`, `MessageContent` and `GuildMembers`. If your bot is not verified and in less than 100 guilds, you can enable privileged gateway intents in the [Discord Developer Portal](https://discord.com/developers/applications) under "Privileged Gateway Intents" in the "Bot" section. If your bot is already verified or is about to [require verification](https://support-dev.discord.com/hc/en-us/articles/23926564536471), you need to request privileged intents. You can do this in your verification application or by reaching out to Discord's [support team](https://dis.gd/contact), including why you require access to each privileged intent.
|
||||
Discord defines some intents as "privileged" due to the data's sensitive nature. At the time of writing this article, privileged intents are `GuildPresences`, `MessageContent` and `GuildMembers`. If your bot is not verified and in less than 100 guilds, you can enable privileged gateway intents in the [Discord Developer Portal](https://discord.com/developers/applications) under "Privileged Gateway Intents" in the "Bot" section. If your bot is already verified or is about to [require verification](https://support-dev.discord.com/hc/articles/23926564536471), you need to request privileged intents. You can do this in your verification application or by reaching out to Discord's [support team](https://dis.gd/contact), including why you require access to each privileged intent.
|
||||
|
||||
Before storming off and doing so, you should stop and carefully think about if you need these events. Discord made them opt-in so users across the platform can enjoy a higher level of [privacy](https://en.wikipedia.org/wiki/Privacy_by_design). Presences can expose quite a bit of personal information, including the games being played and overall online time. You might find that it isn't necessary for your bot to have this level of information about all guild members at all times, considering you still get the command author as GuildMember from the command execution message and can fetch other targets separately.
|
||||
|
||||
@@ -75,6 +75,6 @@ If you want to view the built flags you can utilize the `.toArray()`, `.serializ
|
||||
|
||||
## More on Bitfields
|
||||
|
||||
Discord Intents and Permissions are stored in a 53-bit integer and calculated using bitwise operations. If you want to dive deeper into what's happening behind the curtains, check the [Wikipedia](https://en.wikipedia.org/wiki/Bit_field) and [MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators#binary_bitwise_operators) articles on the topic.
|
||||
Discord Intents and Permissions are stored in a 53-bit integer and calculated using bitwise operations. If you want to dive deeper into what's happening behind the curtains, check the [Wikipedia](https://en.wikipedia.org/wiki/Bit_field) and [MDN](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Operators#binary_bitwise_operators) articles on the topic.
|
||||
|
||||
In discord.js, Permissions and Intents bitfields are represented as either the decimal value of said bit field or its referenced flags. Every position in a permissions bitfield represents one of these flags and its state (either referenced `1` or not referenced `0`).
|
||||
|
||||
@@ -1,4 +1,21 @@
|
||||
{
|
||||
"title": "Popular Topics",
|
||||
"defaultOpen": true,
|
||||
"pages": ["!faq", "...", "!display-components"]
|
||||
"pages": [
|
||||
"!faq",
|
||||
"!display-components",
|
||||
"audit-logs",
|
||||
"canvas",
|
||||
"collectors",
|
||||
"errors",
|
||||
"formatters",
|
||||
"intents",
|
||||
"embeds",
|
||||
"partials",
|
||||
"permissions",
|
||||
"permissions-extended",
|
||||
"reactions",
|
||||
"threads",
|
||||
"webhooks"
|
||||
]
|
||||
}
|
||||
|
||||
@@ -49,7 +49,7 @@ if (message.partial) {
|
||||
|
||||
## Obtaining the full structure
|
||||
|
||||
Along with `.partial` to check if the structure you call it on is partial or not, the library also introduced a `.fetch()` method to retrieve the missing data from the API and complete the structure. The method returns a [Promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise) you need to handle. After the Promise resolves (and with it, the missing data arrived), you can use the structure as you would before.
|
||||
Along with `.partial` to check if the structure you call it on is partial or not, the library also introduced a `.fetch()` method to retrieve the missing data from the API and complete the structure. The method returns a [Promise](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Promise) you need to handle. After the Promise resolves (and with it, the missing data arrived), you can use the structure as you would before.
|
||||
|
||||
```js
|
||||
// [!code word:partial]
|
||||
|
||||
@@ -4,7 +4,7 @@ title: Permissions (extended)
|
||||
|
||||
## Discord's permission system
|
||||
|
||||
Discord permissions are stored in a 53-bit integer and calculated using bitwise operations. If you want to dive deeper into what's happening behind the curtains, check the [Wikipedia](https://en.wikipedia.org/wiki/Bit_field) and [MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators#binary_bitwise_operators) articles on the topic.
|
||||
Discord permissions are stored in a 53-bit integer and calculated using bitwise operations. If you want to dive deeper into what's happening behind the curtains, check the [Wikipedia](https://en.wikipedia.org/wiki/Bit_field) and [MDN](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Operators#binary_bitwise_operators) articles on the topic.
|
||||
|
||||
In discord.js, permission bit fields are represented as either the decimal value of said bit field or its referenced flags.
|
||||
Every position in a permissions bit field represents one of these flags and its state (either referenced `1` or not referenced `0`).
|
||||
@@ -56,6 +56,7 @@ As you only check for `SendMessages`, the bot will try to execute the send, but
|
||||
- When deploying slash commands: Enable the `applications.commands` scope (for more information see the [adding your bot](../preparations/adding-your-app) section).
|
||||
- Timing out a member requires `ModerateMembers`.
|
||||
- Editing threads (tags, locking, closing, renaming etc.) requires `SendMessagesInThreads`.
|
||||
- Adding a member to a thread requires `ViewChannel` in the parent channel for the member being added.
|
||||
</Callout>
|
||||
|
||||
## Limitations and oddities
|
||||
|
||||
@@ -183,7 +183,7 @@ If you try again with either of the code blocks above, you'll get the result you
|
||||
|
||||
<Callout>
|
||||
If you aren't familiar with Promises or `async`/`await`, you can read more about them on
|
||||
[MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise) or [our guide page on
|
||||
[MDN](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Promise) or [our guide page on
|
||||
async/await](../additional-info/async-await.md)!
|
||||
</Callout>
|
||||
|
||||
@@ -234,8 +234,8 @@ message.reactions.cache
|
||||
|
||||
<Callout>
|
||||
If you are not familiar with `Collection#filter` and
|
||||
[`Map.has()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map/has) take the time
|
||||
to understand what they do and then come back.
|
||||
[`Map.has()`](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Map/has) take the time to
|
||||
understand what they do and then come back.
|
||||
</Callout>
|
||||
|
||||
Removing reactions by a user is not as straightforward as removing by emoji or removing all reactions. The API does not provide a method for selectively removing the reactions of a user. This means you will have to iterate through reactions that include the user and remove them.
|
||||
|
||||
@@ -93,7 +93,7 @@ const thread = await channel.threads.create({
|
||||
console.log(`Created thread: ${thread.name}`);
|
||||
```
|
||||
|
||||
They can also be created from an existing message with the `Message#startThread` method, but will be "orphaned" if that message is deleted. The thread is not deleted along with the message and will still be available through the hcannels thread list!
|
||||
They can also be created from an existing message with the `Message#startThread` method, but will be "orphaned" if that message is deleted. The thread is not deleted along with the message and will still be available through the channels thread list!
|
||||
|
||||
```js
|
||||
// [!code word:startThread]
|
||||
|
||||
@@ -29,7 +29,7 @@ If you would like to get the webhook object that sent the message, you can use `
|
||||
Webhook fetching will always make use of collections and Promises. If you do not understand either concept, revise
|
||||
them, and then come back to this section. You can read about collections [here](../additional-info/collections), and
|
||||
Promises [here](../additional-info/async-await) and
|
||||
[here](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Using_promises).
|
||||
[here](https://developer.mozilla.org/docs/Web/JavaScript/Guide/Using_promises).
|
||||
</Callout>
|
||||
|
||||
### Fetching all webhooks of a guild
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
---
|
||||
title: Adding your App
|
||||
title: Adding Your App
|
||||
---
|
||||
|
||||
After you set up a bot application, you'll notice that it's not in any servers yet. So how does that work?
|
||||
|
||||
@@ -42,7 +42,7 @@ bun add discord.js sequelize sqlite3
|
||||
<Callout>
|
||||
This section will still work with any provider supported by sequelize. We recommend PostgreSQL for larger applications.
|
||||
|
||||
Do note that "large" here should be interpreted as absolutely massive. Sqlite is used at scale by many companies and products you use every single day. The slight overhead should not be noticable for the application of a Discord bot at all unless you are dealing with super complicated queries or are using specific features that do not exist in sqlite.
|
||||
Do note that "large" here should be interpreted as absolutely massive. Sqlite is used at scale by many companies and products you use every single day. The slight overhead should not be noticeable for the application of a Discord bot at all unless you are dealing with super complicated queries or are using specific features that do not exist in sqlite.
|
||||
|
||||
You can find out if sqlite might be a good choice for your project (it very likely is) by reading [their own article](https://www.sqlite.org/whentouse.html) on the topic.
|
||||
|
||||
@@ -106,7 +106,7 @@ In any relational database, you need to create tables to store your data. This s
|
||||
| bob | is the best | bob | 0 |
|
||||
| tableflip | (╯°□°)╯︵ ┻━┻ | joe | 8 |
|
||||
|
||||
To do that in Sequelize, define a model based on this structure below the connection information, as shown below, after the `sequelize` initalisation.
|
||||
To do that in Sequelize, define a model based on this structure below the connection information, as shown below, after the `sequelize` initialization.
|
||||
|
||||
```js title="sequelize-example.js"
|
||||
// ...
|
||||
|
||||
@@ -50,7 +50,7 @@ The above code utilizes the discord.js sharding manager to spawn the recommended
|
||||
<Callout>
|
||||
You can find the methods available for the ShardingManager class `ShardingManager`. Though, you may not be making much
|
||||
use of this section, unlike the next feature we will explore, which you may learn about by clicking [this
|
||||
link](./additional-information).
|
||||
link](./sharding/additional-information).
|
||||
</Callout>
|
||||
|
||||
## Getting started
|
||||
@@ -91,12 +91,12 @@ Take the following snippet of code:
|
||||
client.shard.fetchClientValues('guilds.cache.size').then(console.log); // [!code word:fetchClientValues]
|
||||
```
|
||||
|
||||
If you run it, you will notice an output like `[898, 901, 900, 901]`. You will be correct in assuming that that's the total number of guilds per shard stored in an array in the Promise. This probably isn't the ideal output for guild count, so let's use [Array.reduce()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/Reduce) to provide a better output.
|
||||
If you run it, you will notice an output like `[898, 901, 900, 901]`. You will be correct in assuming that that's the total number of guilds per shard stored in an array in the Promise. This probably isn't the ideal output for guild count, so let's use [Array.reduce()](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array/Reduce) to provide a better output.
|
||||
|
||||
<Callout>
|
||||
It's highly recommended for you to visit [the
|
||||
documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/Reduce) to
|
||||
understand how the `reduce()` method works, as you will probably find great use of it in sharding.
|
||||
documentation](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array/Reduce) to understand
|
||||
how the `reduce()` method works, as you will probably find great use of it in sharding.
|
||||
</Callout>
|
||||
|
||||
In this case, this method iterates through the array and adds each current value to the total amount:
|
||||
@@ -149,7 +149,7 @@ This will run the code given to `broadcastEval` on each shard and return the res
|
||||
|
||||
```js
|
||||
client.shard
|
||||
.broadcastEval((c) => c.guilds.cache.reduce((acc, guild) => acc + guild.memberCount, 0)) // [!code word:boradcastEval]
|
||||
.broadcastEval((c) => c.guilds.cache.reduce((acc, guild) => acc + guild.memberCount, 0)) // [!code word:broadcastEval]
|
||||
.then((results) => {
|
||||
return interaction.reply(`Total member count: ${results.reduce((acc, memberCount) => acc + memberCount, 0)}`);
|
||||
})
|
||||
@@ -158,7 +158,7 @@ client.shard
|
||||
|
||||
## Putting them together
|
||||
|
||||
You'd likely want to output both pieces of information in the stats command. You can combine these two results with [Promise.all()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/all):
|
||||
You'd likely want to output both pieces of information in the stats command. You can combine these two results with [Promise.all()](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Promise/all):
|
||||
|
||||
```js
|
||||
const promises = [
|
||||
@@ -192,7 +192,7 @@ client.on(Events.InteractionCreate, (interaction) => {
|
||||
// [!code ++:12]
|
||||
const promises = [
|
||||
client.shard.fetchClientValues('guilds.cache.size'),
|
||||
lient.shard.broadcastEval((c) => c.guilds.cache.reduce((acc, guild) => acc + guild.memberCount, 0)),
|
||||
client.shard.broadcastEval((c) => c.guilds.cache.reduce((acc, guild) => acc + guild.memberCount, 0)),
|
||||
];
|
||||
|
||||
return Promise.all(promises)
|
||||
|
||||
3
apps/guide/content/docs/legacy/slash-commands/meta.json
Normal file
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"title": "Slash Commands"
|
||||
}
|
||||
@@ -37,12 +37,12 @@ module.exports = {
|
||||
};
|
||||
```
|
||||
|
||||
Since `reason` isn't a required option, the example above uses the `??` [nullish coalescing operator](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Nullish_coalescing_operator) to set a default value in case the user does not supply a value for `reason`.
|
||||
Since `reason` isn't a required option, the example above uses the `??` [nullish coalescing operator](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Operators/Nullish_coalescing_operator) to set a default value in case the user does not supply a value for `reason`.
|
||||
|
||||
If the target user is still in the guild where the command is being run, you can also use `.getMember('target')` to get their `GuildMember` object.
|
||||
|
||||
<Callout>
|
||||
If you want the id (Snowflake) of a structure instead, grab the option via `get()` and access the Snowflake via the `value` property. Note that you should use `const { value: name } = ...` here to [destructure and rename](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment) the value obtained from the `CommandInteractionOption` structure to avoid identifier name conflicts.
|
||||
If you want the id (Snowflake) of a structure instead, grab the option via `get()` and access the Snowflake via the `value` property. Note that you should use `const { value: name } = ...` here to [destructure and rename](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment) the value obtained from the `CommandInteractionOption` structure to avoid identifier name conflicts.
|
||||
</Callout>
|
||||
|
||||
In the same way as the above examples, you can get values of any type using the corresponding `CommandInteractionOptionResolver#get_____()` method. `String`, `Integer`, `Number` and `Boolean` options all provide the respective primitive types, while `User`, `Channel`, `Role`, and `Mentionable` options will provide either the respective discord.js class instance if your application has a bot user in the guild or a raw API structure for commands-only deployments.
|
||||
|
||||
@@ -28,13 +28,13 @@ const data = new SlashCommandBuilder()
|
||||
.setDefaultMemberPermissions(PermissionFlagsBits.BanMembers); // [!code ++]
|
||||
```
|
||||
|
||||
For a kick command however, yout can allow members with the `KickMembers` permission to execute the command, so that's why the flag is listed here here.
|
||||
For a kick command however, you can allow members with the `KickMembers` permission to execute the command, so that's why the flag is listed here here.
|
||||
|
||||
<Callout>
|
||||
You can require the user to have all of multiple permissions by merging them with the `|` bitwise OR operator (for example `PermissionFlagsBits.BanMembers | PermissionFlagsBits.KickMembers`).
|
||||
You cannot require any of multiple permissions. Discord evaluates against the combined permission bitfield!
|
||||
|
||||
If you want to learn more about the `|` bitwise OR operator you can check the [Wikipedia](https://en.wikipedia.org/wiki/Bitwise_operation#OR) and [MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Bitwise_OR) articles on the topic.
|
||||
If you want to learn more about the `|` bitwise OR operator you can check the [Wikipedia](https://en.wikipedia.org/wiki/Bitwise_operation#OR) and [MDN](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Operators/Bitwise_OR) articles on the topic.
|
||||
|
||||
</Callout>
|
||||
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
{
|
||||
"pages": ["legacy", "voice"]
|
||||
"pages": ["legacy", "v15", "voice"]
|
||||
}
|
||||
|
||||
359
apps/guide/content/docs/v15/index.mdx
Normal file
@@ -0,0 +1,359 @@
|
||||
---
|
||||
title: Updating to v15
|
||||
icon: ArrowDownToLine
|
||||
---
|
||||
|
||||
import { Github } from 'lucide-react';
|
||||
|
||||
<Callout type="idea">
|
||||
**Version 15 is in a pre-release** state, but should be usable!
|
||||
That being said, we do not recommend you update your production instance without careful and thorough testing!
|
||||
Please report any bugs you experience at our GitHub repository:
|
||||
|
||||
<Github className="inline text-red-400"/> https://github.com/discordjs/discord.js/issues
|
||||
|
||||
</Callout>
|
||||
|
||||
## Before you start
|
||||
|
||||
Make sure you're using the latest LTS version of Node. To check your Node version, use `node --version` in your terminal or command prompt, and if it's not high enough, update it! There are many resources online to help you with this step based on your host system.
|
||||
|
||||
## Breaking Changes
|
||||
|
||||
### ActionRow
|
||||
|
||||
`ActionRow.from()` has been removed. Use `ActionRowBuilder.from()` instead.
|
||||
|
||||
### ApplicationCommand
|
||||
|
||||
`ApplicationCommand#dmPermission` and `ApplicationCommand#setDMPermission()` have been removed. This was legacy functionality for commands—use contexts instead.
|
||||
|
||||
### ApplicationCommandManager
|
||||
|
||||
`ApplicationCommandManager#fetch()` method has been updated for consistency with other managers. Previously, it accepted two parameters: `id` (a snowflake or an options object) and an `options` object. Now, it only accepts a single `options` argument, which can be a snowflake or an options object that may include an `id` property.
|
||||
|
||||
### AnnouncementChannel
|
||||
|
||||
`AnnouncementChannel#addFollower()` now returns `FollowedChannelData` instead of a snowflake. This helps to expose the created webhook id in the target channel.
|
||||
|
||||
### BaseInteraction
|
||||
|
||||
`BaseInteraction#isAnySelectMenu()` has been removed. Use `BaseInteraction#isSelectMenu()` instead, which has been repurposed to accept all select menu component types.
|
||||
|
||||
### Client
|
||||
|
||||
#### Emojis
|
||||
|
||||
`Client#emojis` has been removed due to confusion with the introduction of application emojis and performance impact. Use the `resolveGuildEmoji()` utility function to get a cached guild emoji.
|
||||
|
||||
#### Ping
|
||||
|
||||
`Client#ping` has been added to replace the old `WebSocketManager#ping`. This will be `null` when the heartbeat from the gateway is yet to be received.
|
||||
|
||||
#### Premium sticker packs
|
||||
|
||||
`Client#fetchPremiumStickerPacks()` has been removed. Use `Client#fetchStickerPacks()` instead.
|
||||
|
||||
#### Ready event
|
||||
|
||||
`client.on("")` has been removed. `"clientReady"` is the replacement. If you used `client.on(Events.ClientReady)`, you do not need to change anything.
|
||||
|
||||
#### Shard disconnect event
|
||||
|
||||
`client.on("shardDisconnect")` has been removed as the WebSocket manager replaces this functionality.
|
||||
|
||||
#### Shard error event
|
||||
|
||||
`client.on("shardError")` has been removed as the WebSocket manager replaces this functionality.
|
||||
|
||||
#### Shard ready event
|
||||
|
||||
`client.on("shardReady")` has been removed as the WebSocket manager replaces this functionality.
|
||||
|
||||
#### Shard reconnecting event
|
||||
|
||||
`client.on("shardReconnecting")` has been removed as the WebSocket manager replaces this functionality.
|
||||
|
||||
#### Shard resume event
|
||||
|
||||
`client.on("shardResume")` has been removed as the WebSocket manager replaces this functionality.
|
||||
|
||||
#### Webhook update event
|
||||
|
||||
`client.on("webhookUpdate")` has been removed. `"webhooksUpdate"` is the replacement. If you used `client.on(Events.WebhooksUpdate)`, you do not need to change anything.
|
||||
|
||||
#### WebSocket
|
||||
|
||||
The underlying WebSocket behaviour has changed. In version 14, this was a non-breaking implementation of [ws](https://discord.js.org/docs/packages/ws/stable). Now, it is fully integrated. See these pull requests for more information:
|
||||
|
||||
- [discordjs/discord.js#10420](https://github.com/discordjs/discord.js/pull/10420)
|
||||
- [discordjs/discord.js#10556](https://github.com/discordjs/discord.js/pull/10556)
|
||||
|
||||
### ClientEvents
|
||||
|
||||
`ClientEvents` type has been removed. Use `ClientEventTypes` instead. This change ensures consistency with the rest of the event types across the library.
|
||||
|
||||
### ClientOptions
|
||||
|
||||
Removed `ClientOptions#shards` and `ClientOptions#shardCount` in favor of `ClientOptions#ws#shardIds` and `ClientOptions#ws#shardCount`.
|
||||
|
||||
### ClientUser
|
||||
|
||||
`ClientUser#setPresence()` now returns a promise which resolves when the gateway call was sent successfully.
|
||||
|
||||
### ClientPresence
|
||||
|
||||
`ClientPresence#set()` now returns a promise which resolves when the gateway call was sent successfully.
|
||||
|
||||
### CommandInteractionOptionResolver
|
||||
|
||||
`CommandInteractionOptionResolver#getFocused()`'s parameter has been removed. `AutocompleteFocusedOption` will always be returned.
|
||||
|
||||
### Constants
|
||||
|
||||
`DeletableMessageTypes` has been removed. Use `UndeletableMessageTypes` instead.
|
||||
|
||||
### DiscordjsErrorCodes
|
||||
|
||||
The following error codes have been removed as they either have no use or are handled in another package instead:
|
||||
|
||||
- `WSCloseRequested`
|
||||
- `WSConnectionExists`
|
||||
- `WSNotOpen`
|
||||
- `ManagerDestroyed`
|
||||
- `ShardingInvalid`
|
||||
- `ShardingRequired`
|
||||
- `InvalidIntents`
|
||||
- `DisallowedIntents`
|
||||
- `ButtonLabel`
|
||||
- `ButtonURL`
|
||||
- `ButtonCustomId`
|
||||
- `SelectMenuCustomId`
|
||||
- `SelectMenuPlaceholder`
|
||||
- `SelectOptionLabel`
|
||||
- `SelectOptionValue`
|
||||
- `SelectOptionDescription`
|
||||
- `UserBannerNotFetched`
|
||||
- `ImageFormat`
|
||||
- `ImageSize`
|
||||
- `SplitMaxLen`
|
||||
- `MissingManageEmojisAndStickersPermission`
|
||||
- `VanityURL`
|
||||
- `InteractionEphemeralReplied`
|
||||
|
||||
### Emoji
|
||||
|
||||
#### Image URL is now dynamic
|
||||
|
||||
`Emoji#imageURL()` now dynamically handles the extension. Previously, you would have to do this:
|
||||
|
||||
```js
|
||||
emoji.imageURL({ extension: emoji.animated ? 'gif' : 'webp' });
|
||||
```
|
||||
|
||||
Now, you can simply do this:
|
||||
|
||||
```js
|
||||
emoji.imageURL();
|
||||
```
|
||||
|
||||
#### Emoji URL getter removal
|
||||
|
||||
`Emoji#url` has been removed. To allow more granular control of the returned extension, Use `Emoji#imageURL()` instead.
|
||||
|
||||
### EventEmitter
|
||||
|
||||
`BaseClient`, `Shard`, `ShardingManager`, and `Collector` now extend `AsyncEventEmitter` instead of `EventEmitter`. This comes from [@vladfrangu/async_event_emitter](https://npmjs.com/package/@vladfrangu/async_event_emitter).
|
||||
|
||||
### Events
|
||||
|
||||
- `Events.ShardError` has been removed.
|
||||
- `Events.ShardReady` has been removed.
|
||||
- `Events.ShardReconnecting` has been removed.
|
||||
- `Events.ShardResume` has been removed.
|
||||
- `Events.WebhooksUpdate` now returns a string of `"webhooksUpdate"`. Previously, it returned `"webhookUpdate"`. This is to bring it in line with the name of Discord's gateway event (`WEBHOOKS_UPDATE`).
|
||||
- `Events.ClientReady` now returns a string of `"clientReady"`. Previously, it returned `"ready"`. This is to ensure there's no confusion with Discord's `READY` gateway event.
|
||||
|
||||
### Formatters
|
||||
|
||||
This utility has been removed. Everything in this class is redundant as all methods of the class can be imported from discord.js directly.
|
||||
|
||||
```js
|
||||
import { Formatters } from 'discord.js'; // [!code --]
|
||||
import { userMention } from 'discord.js'; // [!code ++]
|
||||
|
||||
Formatters.userMention('123456789012345678'); // [!code --]
|
||||
userMention('123456789012345678'); // [!code ++]
|
||||
```
|
||||
|
||||
### Guild
|
||||
|
||||
Removed `Guild#shard` as WebSocket shards are now handled by @discordjs/ws.
|
||||
|
||||
### GuildApplicationCommandManager
|
||||
|
||||
`GuildApplicationCommandManager#fetch()` method has been updated for consistency with other managers. Previously, it accepted two parameters: `id` (a snowflake or an options object) and an `options` object. Now, it only accepts a single `options` argument, which can be a snowflake or an options object that may include an `id` property.
|
||||
|
||||
### GuildAuditLogs
|
||||
|
||||
`GuildAuditLogsEntry.Targets.All` has been removed. It was not being used.
|
||||
|
||||
### GuildBanManager
|
||||
|
||||
`GuildBanManager#create()` no longer accepts `deleteMessageDays`. This is replaced with `deleteMessageSeconds`.
|
||||
|
||||
### GuildChannelManager
|
||||
|
||||
`GuildChannelManager#addFollower()` now returns `FollowedChannelData` instead of a snowflake. This helps to expose the created webhook id in the target channel.
|
||||
|
||||
### GuildMemberResolvable
|
||||
|
||||
`GuildMemberResolvable` type has been removed. It was defined as `GuildMember | UserResolvable`, but `UserResolvable` already includes `GuildMember`. Use `UserResolvable` instead.
|
||||
|
||||
### MessageManager
|
||||
|
||||
`MessageManager#crosspost()` has been moved to `GuildMessageManager`. This means it will no longer be exposed in `DMMessageManager`.
|
||||
|
||||
### IntegrationApplication
|
||||
|
||||
`IntegrationApplication#hook` has been removed.
|
||||
|
||||
### InteractionResponse
|
||||
|
||||
`InteractionResponse` has been removed. This class was encountered when responding to an interaction without `fetchReply` to allow ease of creating interaction collectors. This is no longer necessary as `withResponse` exposes the message.
|
||||
|
||||
### InteractionResponses
|
||||
|
||||
#### Ephemeral option removal
|
||||
|
||||
Previously, you would respond to an interaction ephemerally like so:
|
||||
|
||||
```js
|
||||
// Way 1:
|
||||
await interaction.reply({ content: 'This is an ephemeral response.', ephemeral: true });
|
||||
|
||||
// Way 2:
|
||||
await interaction.reply({ content: 'This is an ephemeral response.', flags: MessageFlags.Ephemeral });
|
||||
```
|
||||
|
||||
There are two ways to achieve the same behaviour, so the "helper" option has been removed. In this case, that would be `ephemeral`, as all that did was assign `MessageFlags.Ephemeral` internally.
|
||||
|
||||
#### Fetch reply option removal
|
||||
|
||||
`fetchReply` has been removed in favor of `withResponse`. If you were using the `fetchReply` option or fetching the response of an interaction, it is recommended to use `withResponse` instead, as the message is exposed without an additional API call:
|
||||
|
||||
```js
|
||||
const message = await interaction.reply({ content: 'Hello!', fetchReply: true }); // [!code --]
|
||||
const response = await interaction.reply({ content: 'Hello!', withResponse: true }); // [!code ++:2]
|
||||
const { message } = response.resource;
|
||||
```
|
||||
|
||||
#### Premium response type
|
||||
|
||||
Discord no longer supports the `PREMIUM_REQUIRED` interaction response type. In the past, you would have done this:
|
||||
|
||||
```js
|
||||
if (!premiumLogicCheck) {
|
||||
// User does not have access to our premium features.
|
||||
await interaction.sendPremiumRequired();
|
||||
return;
|
||||
}
|
||||
|
||||
await interaction.reply('You have access to our premium features!');
|
||||
```
|
||||
|
||||
However, you would have already noticed that this no longer works, so this method has been removed. Sending a premium button has been the replacement ever since.
|
||||
|
||||
### Invite
|
||||
|
||||
`Invite#stageInstance` has been removed.
|
||||
|
||||
### InviteStageInstance
|
||||
|
||||
`InviteStageInstance` has been removed.
|
||||
|
||||
### Message
|
||||
|
||||
`Message#interaction` has been removed. Use `Message#interactionMetadata` instead.
|
||||
|
||||
### MessagePayload
|
||||
|
||||
`MessagePayload#isInteraction` no longer serves a purpose and has been removed.
|
||||
|
||||
### NewsChannel
|
||||
|
||||
`NewsChannel` has been renamed to `AnnouncementChannel`.
|
||||
|
||||
### PermissionOverwrites
|
||||
|
||||
`PermissionOverwrites.resolve()` previously relied on cache if a snowflake was passed. This method no longer relies on cache and instead requires an explicit `type` if supplied.
|
||||
|
||||
### RoleManager
|
||||
|
||||
`RoleManager#fetch()` used to return `null` when fetching a role that did not exist. This logic has been removed and will throw an error instead.
|
||||
|
||||
### SelectMenuBuilder
|
||||
|
||||
`SelectMenuBuilder` has been removed. Use `StringSelectMenuBuilder` instead.
|
||||
|
||||
### SelectMenuComponent
|
||||
|
||||
`SelectMenuComponent` has been removed. Use `StringSelectMenuComponent` instead.
|
||||
|
||||
### SelectMenuInteraction
|
||||
|
||||
`SelectMenuInteraction` has been removed. Use `StringSelectMenuInteraction` instead.
|
||||
|
||||
### SelectMenuOptionBuilder
|
||||
|
||||
`SelectMenuOptionBuilder` has been removed. Use `StringSelectMenuOptionBuilder` instead.
|
||||
|
||||
### ShardClientUtil
|
||||
|
||||
`ShardClientUtil#ids` and `ShardClientUtil#count` have been removed in favor of `Client#ws#getShardIds()` and `Client#ws#getShardCount()`.
|
||||
|
||||
### StageInstance
|
||||
|
||||
`StageInstance#discoverableDisabled` has been removed.
|
||||
|
||||
### TeamMember
|
||||
|
||||
`TeamMember#permissions` has been removed. Use `TeamMemberManager#role` instead.
|
||||
|
||||
### TextBasedChannel
|
||||
|
||||
`TextBasedChannel#bulkDelete()` could return a collection containing `undefined` values. This was because in order to return these messages, the cache must be checked, especially when only snowflakes were provided. The return type of this method has thus changed to only return an array of snowflakes that were bulk deleted.
|
||||
|
||||
### ThreadChannel
|
||||
|
||||
`ThreadChannel#fetchOwner()` used to return `null` when the thread owner was not present in the thread. This logic has been removed and will throw an error instead.
|
||||
|
||||
### ThreadManager
|
||||
|
||||
`ThreadManager#fetch()` now throws an error when the provided thread id doesn't belong to the current channel.
|
||||
|
||||
### ThreadMember
|
||||
|
||||
The reason parameter of `ThreadMember#add()` and `ThreadMember#remove()` have been removed. Discord did not respect this parameter, so it did not do anything.
|
||||
|
||||
### ThreadMemberManager
|
||||
|
||||
The reason parameter of `ThreadMemberManager#remove()` has been removed. Discord did not respect this parameter, so it did not do anything.
|
||||
|
||||
### User
|
||||
|
||||
#### Avatar decoration
|
||||
|
||||
Discord no longer sends avatar decoration data via `User#avatarDecoration`, so this property has been removed. `User#avatarDecorationData` is the replacement.
|
||||
|
||||
#### Flags
|
||||
|
||||
`User#fetchFlags()` has been removed. All this did was fetch the user and return only its `flags` property. It was quite redundant.
|
||||
|
||||
### UserManager
|
||||
|
||||
`UserManager#fetchFlags()` has been removed. All this did was fetch the user and return only its `flags` property. It was quite redundant.
|
||||
|
||||
### WebSocketShardEvents
|
||||
|
||||
`WebSocketShardEvents` has been replaced with `WebSocketShardEvents` from @discordjs/ws.
|
||||
7
apps/guide/content/docs/v15/meta.json
Normal file
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"title": "discord.js v15",
|
||||
"description": "Work in progress...",
|
||||
"pages": ["external:[LibraryBig][Documentation](https://discord.js.org/docs/packages/discord.js/main)", "index"],
|
||||
"icon": "FlaskConical",
|
||||
"root": true
|
||||
}
|
||||
@@ -81,7 +81,7 @@ const resource = createAudioResource('/home/user/voice/music.mp3', {
|
||||
},
|
||||
});
|
||||
|
||||
// Not recommended - listen to errors from the audio player instead for most usecases!
|
||||
// Not recommended - listen to errors from the audio player instead for most use cases!
|
||||
resource.playStream.on('error', (error) => {
|
||||
console.error('Error:', error.message, 'with track', resource.metadata.title);
|
||||
});
|
||||
|
||||
@@ -2,13 +2,17 @@
|
||||
title: Installation
|
||||
---
|
||||
|
||||
"Voice" refers to Discord bots being able to send audio in voice channels. This is supported in discord.js via @discordjs/voice](https://github.com/discordjs/discord.js/tree/main/packages/voice), a standalone library made by the developers of discord.js. While you can use it with any Node.js Discord API library, this guide will focus on using it with discord.js.
|
||||
"Voice" refers to Discord bots being able to send audio in voice channels. This is supported in discord.js via [@discordjs/voice](https://github.com/discordjs/discord.js/tree/main/packages/voice), a standalone library made by the developers of discord.js. While you can use it with any Node.js Discord API library, this guide will focus on using it with discord.js.
|
||||
|
||||
## Installation
|
||||
|
||||
### Barebones
|
||||
|
||||
To add voice functionality to your discord.js bot, you will need the `@discordjs/voice` package, as well as one of the encryption packages listed below. For example:
|
||||
To add voice functionality to your discord.js bot, you will need the `@discordjs/voice` package. If your system does not support aes-256-gcm you also need one of the encryption packages listed below. For example:
|
||||
|
||||
<Callout>
|
||||
You can verify aes-256-gcm support by running `require('node:crypto').getCiphers().includes('aes-256-gcm')`.
|
||||
</Callout>
|
||||
|
||||
```sh tab="npm"
|
||||
npm install @discordjs/voice
|
||||
@@ -58,6 +62,15 @@ After this, you'll be able to play Ogg and WebM Opus files without any other dep
|
||||
- [`@noble/ciphers`](https://www.npmjs.com/package/@noble/ciphers)
|
||||
- [`libsodium-wrappers`](https://www.npmjs.com/package/libsodium-wrappers)
|
||||
|
||||
#### DAVE Protocol Support for end-to-end encryption of voice audio
|
||||
|
||||
- [`@snazzah/davey`](https://www.npmjs.com/package/@snazzah/davey)
|
||||
|
||||
<Callout>
|
||||
At this time, `@snazzah/davey` is the only supported DAVE protocol library in this package, and comes pre-installed.
|
||||
In the future, we may support other libraries once they are created.
|
||||
</Callout>
|
||||
|
||||
<Callout>
|
||||
If you are facing issues when installing these dependencies, make sure you ticked the box to install optional build
|
||||
tools when installing Node.js or try manually installing build tools and python: ```sh winget install "Visual Studio
|
||||
@@ -91,6 +104,9 @@ Encryption Libraries
|
||||
FFmpeg
|
||||
- version: 4.2.4-1ubuntu0.1
|
||||
- libopus: yes
|
||||
|
||||
DAVE Protocol
|
||||
- @snazzah/davey: 0.1.6
|
||||
--------------------------------------------------
|
||||
*/
|
||||
```
|
||||
@@ -104,3 +120,5 @@ FFmpeg
|
||||
- **FFmpeg**
|
||||
- If you want to play audio from many different file types, you will need to have FFmpeg installed.
|
||||
- If `libopus` is enabled, you will be able to benefit from increased performance if real-time volume alteration is disabled.
|
||||
- **DAVE Protocol**
|
||||
- Required for enabling end-to-end encryption in voice channels.
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
"title": "Voice",
|
||||
"description": "Working with the voice library",
|
||||
"pages": [
|
||||
"[LibraryBig][Documentation](https://discord.js.org/docs/packages/voice/main)",
|
||||
"external:[LibraryBig][Documentation](https://discord.js.org/docs/packages/voice/main)",
|
||||
"---Working with Voice---",
|
||||
"index",
|
||||
"life-cycles",
|
||||
|
||||
@@ -4,7 +4,6 @@ import type { NextConfig } from 'next';
|
||||
const withMDX = createMDX();
|
||||
|
||||
export default withMDX({
|
||||
reactStrictMode: true,
|
||||
serverExternalPackages: ['typescript', 'twoslash'],
|
||||
images: {
|
||||
dangerouslyAllowSVG: true,
|
||||
@@ -23,14 +22,6 @@ export default withMDX({
|
||||
fullUrl: true,
|
||||
},
|
||||
},
|
||||
experimental: {
|
||||
ppr: true,
|
||||
useCache: true,
|
||||
dynamicOnHover: true,
|
||||
},
|
||||
eslint: {
|
||||
ignoreDuringBuilds: true,
|
||||
},
|
||||
reactCompiler: true,
|
||||
typescript: {
|
||||
ignoreBuildErrors: true,
|
||||
|
||||
3
apps/guide/open-next.config.ts
Normal file
@@ -0,0 +1,3 @@
|
||||
import { defineCloudflareConfig } from '@opennextjs/cloudflare';
|
||||
|
||||
export default defineCloudflareConfig();
|
||||
@@ -5,11 +5,15 @@
|
||||
"description": "Imagine a bot... the most popular way to build discord bots",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"cf-typegen": "wrangler types --env-interface CloudflareEnv cloudflare-env.d.ts",
|
||||
"build:check": "tsc --noEmit",
|
||||
"build:local": "cross-env NEXT_PUBLIC_LOCAL_DEV=true pnpm run build:prod",
|
||||
"build:prod": "pnpm run build:next",
|
||||
"build:next": "next build",
|
||||
"build": "next build",
|
||||
"preview": "next start",
|
||||
"preview:cf": "opennextjs-cloudflare build && opennextjs-cloudflare preview",
|
||||
"deploy:cf": "opennextjs-cloudflare build && opennextjs-cloudflare deploy",
|
||||
"dev": "next dev -p 3001 --turbopack",
|
||||
"lint": "pnpm run build:check && prettier --check . && cross-env TIMING=1 eslint --format=pretty src ",
|
||||
"format": "pnpm run build:check && prettier --write . && cross-env TIMING=1 eslint --fix --format=pretty src ",
|
||||
@@ -44,65 +48,51 @@
|
||||
"homepage": "https://discord.js.org",
|
||||
"funding": "https://github.com/discordjs/discord.js?sponsor",
|
||||
"dependencies": {
|
||||
"@react-icons/all-files": "^4.1.0",
|
||||
"@vercel/analytics": "^1.5.0",
|
||||
"cmdk": "^1.1.1",
|
||||
"cva": "1.0.0-beta.3",
|
||||
"fumadocs-core": "^15.8.4",
|
||||
"fumadocs-mdx": "^12.0.3",
|
||||
"fumadocs-twoslash": "^3.1.8",
|
||||
"fumadocs-ui": "^15.8.4",
|
||||
"geist": "^1.5.1",
|
||||
"immer": "^10.1.3",
|
||||
"jotai": "^2.15.0",
|
||||
"jotai-immer": "^0.4.1",
|
||||
"lucide-react": "^0.545.0",
|
||||
"mermaid": "^11.12.0",
|
||||
"motion": "^12.23.22",
|
||||
"next": "15.6.0-canary.45",
|
||||
"next-mdx-remote-client": "^2.1.6",
|
||||
"@opennextjs/cloudflare": "^1.16.5",
|
||||
"@vercel/analytics": "^1.6.1",
|
||||
"fumadocs-core": "^16.6.3",
|
||||
"fumadocs-mdx": "^14.2.7",
|
||||
"fumadocs-twoslash": "^3.1.13",
|
||||
"fumadocs-ui": "^16.6.3",
|
||||
"geist": "^1.7.0",
|
||||
"lucide-react": "^0.559.0",
|
||||
"mermaid": "^11.12.3",
|
||||
"next": "^16.1.6",
|
||||
"next-themes": "^0.4.6",
|
||||
"nuqs": "^2.7.1",
|
||||
"react": "^19.2.0",
|
||||
"react-aria": "^3.44.0",
|
||||
"react-aria-components": "^1.13.0",
|
||||
"react-dom": "^19.2.0",
|
||||
"react-error-boundary": "^6.0.0",
|
||||
"sharp": "^0.34.4",
|
||||
"tailwind-merge": "^3.3.1",
|
||||
"p-retry": "^7.1.1",
|
||||
"react": "^19.2.4",
|
||||
"react-dom": "^19.2.4",
|
||||
"sharp": "^0.34.5",
|
||||
"tailwind-merge": "^3.5.0",
|
||||
"tw-animate-css": "^1.4.0",
|
||||
"twoslash": "^0.3.4",
|
||||
"usehooks-ts": "^3.1.1"
|
||||
"twoslash": "^0.3.6"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@next/env": "^15.5.4",
|
||||
"@shikijs/rehype": "^3.13.0",
|
||||
"@tailwindcss/postcss": "^4.1.14",
|
||||
"@tailwindcss/typography": "^0.5.19",
|
||||
"@tailwindcss/vite": "^4.1.14",
|
||||
"@shikijs/rehype": "^3.22.0",
|
||||
"@tailwindcss/postcss": "^4.2.0",
|
||||
"@types/mdx": "^2.0.13",
|
||||
"@types/node": "^22.18.8",
|
||||
"@types/react": "^19.2.0",
|
||||
"@types/react-dom": "^19.2.0",
|
||||
"autoprefixer": "^10.4.21",
|
||||
"babel-plugin-react-compiler": "19.1.0-rc.3",
|
||||
"@types/node": "^24.10.13",
|
||||
"@types/react": "^19.2.14",
|
||||
"@types/react-dom": "^19.2.3",
|
||||
"autoprefixer": "^10.4.24",
|
||||
"babel-plugin-react-compiler": "^1.0.0",
|
||||
"cpy-cli": "^6.0.0",
|
||||
"cross-env": "^10.1.0",
|
||||
"eslint": "^9.37.0",
|
||||
"eslint-config-neon": "^0.2.7",
|
||||
"eslint": "^9.39.2",
|
||||
"eslint-config-neon": "^0.3.2",
|
||||
"eslint-formatter-pretty": "^7.0.0",
|
||||
"git-describe": "^4.1.1",
|
||||
"postcss": "^8.5.6",
|
||||
"prettier": "^3.6.2",
|
||||
"prettier-plugin-tailwindcss": "^0.6.14",
|
||||
"prettier": "^3.8.1",
|
||||
"prettier-plugin-tailwindcss": "^0.7.2",
|
||||
"remark-gfm": "^4.0.1",
|
||||
"remark-rehype": "^11.1.2",
|
||||
"shiki": "^3.13.0",
|
||||
"tailwindcss": "^4.1.14",
|
||||
"tailwindcss-react-aria-components": "^2.0.1",
|
||||
"turbo": "^2.5.8",
|
||||
"typescript": "^5.9.3",
|
||||
"vercel": "^48.2.1"
|
||||
"shiki": "^3.22.0",
|
||||
"tailwindcss": "^4.2.0",
|
||||
"turbo": "^2.8.10",
|
||||
"typescript": "~5.9.3",
|
||||
"vercel": "^49.2.0",
|
||||
"wrangler": "^4.67.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=22.12.0"
|
||||
|
||||
2
apps/guide/public/_headers
Normal file
@@ -0,0 +1,2 @@
|
||||
/_next/static/*
|
||||
Cache-Control: public,max-age=31536000,immutable
|
||||
|
Before Width: | Height: | Size: 4.5 KiB |
|
Before Width: | Height: | Size: 7.6 KiB |
|
Before Width: | Height: | Size: 2.9 KiB |
|
Before Width: | Height: | Size: 2.6 KiB |
|
Before Width: | Height: | Size: 3.4 KiB |
|
Before Width: | Height: | Size: 3.1 KiB |
|
Before Width: | Height: | Size: 3.8 KiB |
|
Before Width: | Height: | Size: 3.4 KiB |
|
Before Width: | Height: | Size: 1.8 KiB |
|
Before Width: | Height: | Size: 1.6 KiB |
|
Before Width: | Height: | Size: 2.1 KiB |
|
Before Width: | Height: | Size: 1.9 KiB |
|
Before Width: | Height: | Size: 3.8 KiB |
|
Before Width: | Height: | Size: 3.4 KiB After Width: | Height: | Size: 8.9 KiB |
@@ -1,12 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<browserconfig>
|
||||
<msapplication>
|
||||
<tile>
|
||||
<square70x70logo src="/mstile-70x70.png"/>
|
||||
<square150x150logo src="/mstile-150x150.png"/>
|
||||
<square310x310logo src="/mstile-310x310.png"/>
|
||||
<wide310x150logo src="/mstile-310x150.png"/>
|
||||
<TileColor>#090a16</TileColor>
|
||||
</tile>
|
||||
</msapplication>
|
||||
</browserconfig>
|
||||
|
Before Width: | Height: | Size: 561 B |
|
Before Width: | Height: | Size: 1.1 KiB |
BIN
apps/guide/public/favicon-96x96.png
Normal file
|
After Width: | Height: | Size: 5.4 KiB |
|
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 15 KiB |
3
apps/guide/public/favicon.svg
Normal file
@@ -0,0 +1,3 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" xmlns:xlink="http://www.w3.org/1999/xlink" width="180" height="180" viewBox="0 0 180 180"><image width="180" height="180" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAALQAAAC0CAMAAAAKE/YAAAAABGdBTUEAALGPC/xhBQAAAAFzUkdCAK7OHOkAAAKjUExURQkKFveUVAgIFAQFEv/bXFz/nVxs/////7dc//9cXAYHEwUIFbld/wcJFRESHsHBxAsLF//dXV3/n11t//v7++vr7FBRWgsNGf/bW2NkbP39/To6RP7+/viVVP/fXQwOH/9fXFts/1r/nvtbWzucZ/yXVZs7Pw8OGQ0WHIqLkBYOGREOI/9bXBMQGGVq//T09Px0WFxq/6lf/6xX8CIXHRMRKRYUGT4iXZlfO0S7d1tcZLVb/PqWVRYZI7RtQiEhLBwdKGMoMDMcIeTk5ZFKzLlFSP5nWrJd/zc9kLJZ+JuGP0ZSwRQXNrqgSFtp+O5WVyEVN6iorTQeUCgpNG86n2lCL/CPUvx8WPmNVX5m/9DR01IsdyoZQ0xNVndAr1fvlVNh5q5e/29o/2tsc5+gpJKSmIpGw+zLVhsSL/3HWlv4nRgcQvuEVi4vObe3u9nZ2/n5+a+wtMnJzKVT6PbUWVgvgTU2QPaSVDtGoFx5+Mfncp5h/4pk/7freUFMtHR0e4CBh0cnaVhNLNWBSyMpYTQoIf7TWykwcT4xJEtYzxUuKvXfYYP3jZ9R30YeJ1ZWX8NIS0M7JoBDuPDw8WI0jnlnNpaDP09c2/27WFdp7/mhVR8lU1g4Ksd3R1zRvSdjR5Vi/3X8lC93Umb+mVDei9/jaaLxgU4qcr29wUdIUVlZYXUvNCJUPos1OptP2VMiKzeHWt/AU2s4mVyK6/uuV96ETVDNgOzhZeNSVKxARGUpMKyURJNZOmZZMEBBSsGmSqdlPoNRNlzuqs2xTly6zF3prh5JOZTzh14mLs1LTbadR0ZFp2Fg6LlgRVyj21zetWZb4TxIqkO3dVlY1FyV41yx0a+IRFVQw5ygUDhzd1S2cFye3aikT0SPk6bVb2RPxmBZ2kyJzQcAAApJSURBVHja7Zr5WxNJGoDb4grdKWgI2CAwkZE1QARcSQxyCAuMgrrcoNwi54AIiAfe4on3gfd934o66jiOt6Nz7xy7O3sff8pWJaHTHTpJR9Myz7P1/uRjqlJvf/3VV1+noSgCgUAgEAgEAoFAIBAIBAKBQCAQCAQCgUAgEAgEAoFA+NVCe0lD0wBCJ/MgY8PZOApCy1Cn3+YeXG24JKljn3ZmBSBzB/OY3Y9+N8yj3azDK6PiDdlDX6FBQ7sN8SzjGfGAK5EhUnQnDeZU9azfU8rRkgvBif4ThvH/KF46xLrsRxP3PiwsNI8qfLh34vXseMoD3gGBfs7o7mpKzZLShhPH+/NISxu++uzhBH8xhXtvZuugwtLYOzA8i3ZbGhquf21vbPX+bOhdtV1LI+0rtRxwSxqyQ3ullS3au1motLSfX2hcFnBDGhpuFvo7o/CmASou7ReyqJOWLQ2zP5rg74Kvh1jFpf38ApfRMqVh9l7/SRjnwb4eDxWX9lvcCWRJQ8P3kzEzZswYP97fsfyEifHKS/stygRypBNSosZgls+bN2/hXCxvdbeXn3CTVV56XLNOjnR5hUV6mOXYfa418uP5WZP8C4c8E+nIcVYipayTrgGX0jB7o8g5Kr3i/snpKSnPp5+8j+wRczE4f66zHpEOibuWaia8Ma64KmlkWtsShJee5D9j8vcJ/Pexj4XOUVH3U05kx7MInWHziZSNy9P5zx4neKZ6dNei5s4CZDPHNoXaJ8g6e2mkPHde+vQE6UBHVTzfTPFNEsOwhvLpFRbtqOnvUKnF0mMFZQ3QutpAuzSp4kONpSf5j5+xcN6YMQJppny50PlFPGPXQ00tPzkGXVbUyWxIKSCNe+3S4nHiAz3Vy9blobxYaFYUSOuepwuyIyVhpBljeFGBsmaAoRSSpujMReJQF+t46ck4yGPE0tAgyI6ojdlSZpA9sbGi3HMN0whpil7WJZLuKrXmB/P4N7ydTZoZENS79BQH5QFuLtcpKU3BdSGi/LhmzQ8mRVJamNLLyx2mgCdbUwlpkFklCnUc5VxauA1PMJQyuJKmYJz4LA9wKv0iPYrPj1GUpq+KDpmuTOhM+uDHZo4cuXfv2LHyUZO2y48ca4fKS0elH7v3y9Rh6Sdh3sNs2fKLbrSkqYAeUf9xlearR9SxY/eOfLxlS9DveekNS3hp76DWfcxoSYNm0SPMHi9rpI9gX4udTXqg1Vtg/czAjJb0etFODLdKz/rAJsdLQ8OrIIG19zebmdGRZtaJGpBw2ok0RR0SSXu/2pDAjIY03ThOvrQoqfFHSz7f53ltGdJuRXrqM3Go0Xb8fMNUBo5uTqd6OZVmnohDbY72s4ObWebXUD0cSFNTvwnyHqEddufQPh3zHqXZYqH04FXn6UEx++6MtPYOCmrF2vA9ScOsxeITETiXpqgnrd5S4OQ2eOaXdde9R4ToSbEqC7qSZg8u8ZbWXvLKM8ntWlpcPPgub9YHYRiksuPTf4qkqYSDrUEOtL3vHBp4d22XDwEZV0TFY731/jKHdly8uHLlmktf7tx59u+xdttgw52gsDBp7aDWWQMsUFaa3iPqTJNqrSNAzNmz58/7fIgJnhZrf6kDf1356Q7vMHtz/B87Lv779nagpDTICrT7DQEOSwd/6GNlpDQFY8892HlpzcqLFnVLJqFEurjm0s7zwT4P3igoDXVxIZJPW1jax4k0egrcfu6Cz/nzZ3d+eWnNmpUokXAmncX3Bs+oPxerlDRkGwfFbwQiaJnSaATSftCO08c6zPYvNKX9dqwy0nTAOlu5iwxdXNzcGABlS6MxIOP0z/XBtoFC2m9zHpeGgNY9LeY3YWRXXEQWJ3gVKkcaD4t9E3PBR1K7/jT0kLQXNEOxGZ2pTTm2D4qXUeK3iTKl0UBu++0H7RLawRfeuoaIpMf1xJlpbuoJzOkWFLr1AbQ5+F40dFcaJ3fG6Wn1I7WDYzhPSDt6jxingxSkAzprayMyAHRXGid37I2Ykdr1b4By0j0ZyFm3pycnKSk0sDEDuC1tzpIbP9trv3WoZUiHPqXRaR43OJze5t+o3ZXGe/LGNHFuv3VWy5Bu0lEUZztkIotR4EXSPtPk1VwQe84u2KeVku6+RlP0VUF/GtIIhNLtr0/9K0DucjcuCG7Qyx/+plR65JQCim0SvbxFoTZLt7889cUfPlmhma2Vuxw4XW85EF+f+uIfn6yQP9FN6cUZEGZV2R/mIOb1qT//aYXmtwg3pCku5uUPlitFE323GaEy0osCICjNEfenXhToswj7IjRr5UuD40cFEw/PAUpId1eFs5S99Fj0RN6n8R1G85Mbpct42Nc2cb7npSOTuopT8TPhiIdbmuLWCqTz3FhaO1vz7tI9g6FS5HRdaVo/tlRnObeh6LePRRkQGLfZ1vbdCsTHttLSbGeEFJ2lmRmcF9/VgQhBfiSlApyaNueCTcKlueNOTfSCq33bnKYALQUQ/iUhThDb00BIM26q84Tx6hAsDTYdnd3hWAXMmS+Y+ZYlzyUQsHocv0ZrrAfjcJXuEC2tF1aHwxrN4U2cI22wtUCwEfuUMQb6krK6NtQwscuaF+eEdjXV4o5PK9iGaB8KnDrw3dcczTNKWwOjIKV9o7cCzwtTxpqlLclqVZkedxtsVmlpJocaa6DNE4TLt+A4sHfS+G7bpJUS4vKieeNozXcdHpZmi0qqy3KT09QqlSqtrA1YLsPc4OlFzpptRv469X3DTpqCtce1wM5p+Gqjo6N9ExdUrqrzdEqzd/PT1NjYTItJa9maALAdawXOaH1blebyFiQmJmosVpqja7fOYW3eAHBopgZ/goTPTJmpyu/3dHYAU77Khjq5rr9Ir9Vq52zqQ3sw2gJaPnHBf/myxVYnN0yZsmrVmdWVlcheoyk43Le1w6hF5yXLoZk/zcfjK1evQsL4O1v00NMprd+vVgm103pz99f958eCRDMLFlRWrl59ZtWUhqW2y+y1zZjZMMUi/90fZ3+bl9f37V9+tIyfyQ9JNgGPVw5QkiyyVqkRWAbT0DDTsro6t43/Y5uSW+IJ2H1mQ0ODdYL9Z3c5BeodeyBN5Qq1MFygJlclG3VLG1CiSBv3q10tnX+AFd6coro0tUzn3BqgzGFY1OJCIe2ueC9B/dJetUxnSCkDrGlx7lxmv/8hW9IiJ9gtijkjh7a6fLXjfD6gBxIH9dJbKrWLjXC3TTlnp/dbvesyJ7U0hEUHbjmJtjot18QBSkkgW1OXrB6hoFYnl9U4LJZs0dLcfLWUt1qdn1ttVFbZrK011fWqBAqoXOfvKivhnNxhAI0m1LjgoaIyn7+rzmQEkHoPAK5m6f5byWlmh7Tk3tyy/iJXL6hQG27EHdeu5HzLqZTfe2v/AVMR936ULQrathLT5erq6n5TSZGepYGsSTSnLyox9aN5l/tNNUYtpAH1XkEK6CHM8iTmVlNOD8+DFIFAIBAIBAKBQCAQCAQCgUAgEAgEAoFAIBAIBAKBQPg/5H/D3r7K3BZFuAAAAFd6VFh0UmF3IHByb2ZpbGUgdHlwZSBpcHRjAAB4nOPyDAhxVigoyk/LzEnlUgADIwsuYwsTIxNLkxQDEyBEgDTDZAMjs1Qgy9jUyMTMxBzEB8uASKBKLgDqFxF08kI1lQAAAABJRU5ErkJggg=="></image><style>@media (prefers-color-scheme: light) { :root { filter: none; } }
|
||||
@media (prefers-color-scheme: dark) { :root { filter: none; } }
|
||||
</style></svg>
|
||||
|
After Width: | Height: | Size: 4.9 KiB |
|
Before Width: | Height: | Size: 3.1 KiB |
|
Before Width: | Height: | Size: 2.8 KiB |
|
Before Width: | Height: | Size: 5.8 KiB |