mirror of
https://github.com/discordeno/discordeno.git
synced 2026-05-21 02:40:08 +00:00
chore: remove client pkg (#2903)
* chore: remove client pkg * yarn install * fix: yarn install --------- Co-authored-by: ITOH <to@itoh.at>
This commit is contained in:
142
.github/workflows/client-test.yml
vendored
142
.github/workflows/client-test.yml
vendored
@@ -1,142 +0,0 @@
|
|||||||
name: Client Test
|
|
||||||
|
|
||||||
on:
|
|
||||||
pull_request:
|
|
||||||
push:
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
build-type-and-test:
|
|
||||||
name: Build Type and Test
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
- uses: actions/setup-node@v3
|
|
||||||
with:
|
|
||||||
node-version: 18
|
|
||||||
- name: Get yarn cache directory path
|
|
||||||
id: yarn-cache-dir-path
|
|
||||||
run: echo "dir=$(yarn config get cacheFolder)" >> $GITHUB_OUTPUT
|
|
||||||
- uses: actions/cache@v3
|
|
||||||
with:
|
|
||||||
path: ${{ steps.yarn-cache-dir-path.outputs.dir }}
|
|
||||||
key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }}
|
|
||||||
restore-keys: |
|
|
||||||
${{ runner.os }}-yarn-
|
|
||||||
- run: yarn install --immutable
|
|
||||||
- name: Turbo Cache
|
|
||||||
id: turbo-cache
|
|
||||||
uses: actions/cache@v3
|
|
||||||
with:
|
|
||||||
path: .turbo
|
|
||||||
key: ${{ runner.os }}-turbo-build:type-${{ github.sha }}
|
|
||||||
- name: Build Type and Test
|
|
||||||
run: yarn build:type --cache-dir=".turbo" --filter=./packages/client
|
|
||||||
|
|
||||||
build-dist:
|
|
||||||
name: Build Dist
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
- uses: actions/setup-node@v3
|
|
||||||
with:
|
|
||||||
node-version: 18
|
|
||||||
- name: Get yarn cache directory path
|
|
||||||
id: yarn-cache-dir-path
|
|
||||||
run: echo "dir=$(yarn config get cacheFolder)" >> $GITHUB_OUTPUT
|
|
||||||
- uses: actions/cache@v3
|
|
||||||
with:
|
|
||||||
path: ${{ steps.yarn-cache-dir-path.outputs.dir }}
|
|
||||||
key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }}
|
|
||||||
restore-keys: |
|
|
||||||
${{ runner.os }}-yarn-
|
|
||||||
- run: yarn install --immutable
|
|
||||||
- name: Turbo Cache
|
|
||||||
id: turbo-cache
|
|
||||||
uses: actions/cache@v3
|
|
||||||
with:
|
|
||||||
path: .turbo
|
|
||||||
key: ${{ runner.os }}-turbo-build-${{ github.sha }}
|
|
||||||
- name: Type Test
|
|
||||||
run: yarn build --cache-dir=".turbo" --filter=./packages/client
|
|
||||||
|
|
||||||
format-unit-and-integration-test:
|
|
||||||
name: Format Test
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
needs: build-type-and-test
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
- uses: actions/setup-node@v3
|
|
||||||
with:
|
|
||||||
node-version: 18
|
|
||||||
- name: Get yarn cache directory path
|
|
||||||
id: yarn-cache-dir-path
|
|
||||||
run: echo "dir=$(yarn config get cacheFolder)" >> $GITHUB_OUTPUT
|
|
||||||
- uses: actions/cache@v3
|
|
||||||
with:
|
|
||||||
path: ${{ steps.yarn-cache-dir-path.outputs.dir }}
|
|
||||||
key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }}
|
|
||||||
restore-keys: |
|
|
||||||
${{ runner.os }}-yarn-
|
|
||||||
- run: yarn install --immutable
|
|
||||||
- name: Turbo Cache
|
|
||||||
id: turbo-cache
|
|
||||||
uses: actions/cache@v3
|
|
||||||
with:
|
|
||||||
path: .turbo
|
|
||||||
key: ${{ runner.os }}-turbo-lint-${{ github.sha }}
|
|
||||||
- name: Build type cache
|
|
||||||
if: steps.turbo-cache.outputs.cache-hit != 'true'
|
|
||||||
uses: actions/cache@v3
|
|
||||||
with:
|
|
||||||
path: .turbo
|
|
||||||
key: ${{ runner.os }}-turbo-build:type-${{ github.sha }}
|
|
||||||
- name: Check Formatting
|
|
||||||
run: yarn lint --cache-dir=".turbo" --filter=./packages/client
|
|
||||||
|
|
||||||
test-type-unit-and-integration-test:
|
|
||||||
name: Test Type Test
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
needs: build-type-and-test
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
- uses: actions/setup-node@v3
|
|
||||||
with:
|
|
||||||
node-version: 18
|
|
||||||
- name: Get yarn cache directory path
|
|
||||||
id: yarn-cache-dir-path
|
|
||||||
run: echo "dir=$(yarn config get cacheFolder)" >> $GITHUB_OUTPUT
|
|
||||||
- uses: actions/cache@v3
|
|
||||||
with:
|
|
||||||
path: ${{ steps.yarn-cache-dir-path.outputs.dir }}
|
|
||||||
key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }}
|
|
||||||
restore-keys: |
|
|
||||||
${{ runner.os }}-yarn-
|
|
||||||
- run: yarn install --immutable
|
|
||||||
- name: Turbo Cache
|
|
||||||
id: turbo-cache
|
|
||||||
uses: actions/cache@v3
|
|
||||||
with:
|
|
||||||
path: .turbo
|
|
||||||
key: ${{ runner.os }}-turbo-unit-and-integration-test:test-type-${{ github.sha }}
|
|
||||||
- name: Build type cache
|
|
||||||
if: steps.turbo-cache.outputs.cache-hit != 'true'
|
|
||||||
uses: actions/cache@v3
|
|
||||||
with:
|
|
||||||
path: .turbo
|
|
||||||
key: ${{ runner.os }}-turbo-build:type-${{ github.sha }}
|
|
||||||
- name: Test Type Test
|
|
||||||
run: yarn test:test-type --cache-dir=".turbo" --filter=./packages/client
|
|
||||||
|
|
||||||
# Not using matrix because test later on cant needs a specific job
|
|
||||||
client-unit-test:
|
|
||||||
name: Client
|
|
||||||
needs: build-dist
|
|
||||||
uses: ./.github/workflows/unit-test.yml
|
|
||||||
with:
|
|
||||||
package: client
|
|
||||||
client-other-runtime-test:
|
|
||||||
name: Client
|
|
||||||
needs: client-unit-test
|
|
||||||
uses: ./.github/workflows/other-runtime-unit-test.yml
|
|
||||||
with:
|
|
||||||
package: client
|
|
||||||
2
.github/workflows/release.yml
vendored
2
.github/workflows/release.yml
vendored
@@ -18,7 +18,7 @@ jobs:
|
|||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
package: ["gateway", "rest", "types", "utils", "bot", "client"]
|
package: ["gateway", "rest", "types", "utils", "bot"]
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
- uses: actions/setup-node@v3
|
- uses: actions/setup-node@v3
|
||||||
|
|||||||
@@ -29,9 +29,8 @@ Discordeno is actively maintained to guarantee **excellent performance, latest f
|
|||||||
|
|
||||||
- **Simple, Efficient, and Lightweight**: Discordeno is lightweight, simple to use, and adaptable.
|
- **Simple, Efficient, and Lightweight**: Discordeno is lightweight, simple to use, and adaptable.
|
||||||
- By default: No caching.
|
- By default: No caching.
|
||||||
- **Functional & Class API**: Discordeno is flexible enough to provide both methods.
|
- **Functional API**:
|
||||||
- The functional API eliminates the challenges of extending built-in classes and inheritance while ensuring overall simple but performant code.
|
- The functional API eliminates the challenges of extending built-in classes and inheritance while ensuring overall simple but performant code.
|
||||||
- The class based API, client package, provides a similar api as the [Eris](https://github.com/abalabahaha/eris) library to provide the best class based experience.
|
|
||||||
- **Cross Runtime**: Supports the Node.js, Deno, and Bun runtimes.
|
- **Cross Runtime**: Supports the Node.js, Deno, and Bun runtimes.
|
||||||
- **Standalone components**: Discordeno offers the option to have practically any component of a bot as a separate
|
- **Standalone components**: Discordeno offers the option to have practically any component of a bot as a separate
|
||||||
piece, including standalone REST, gateways, custom caches, and more.
|
piece, including standalone REST, gateways, custom caches, and more.
|
||||||
|
|||||||
@@ -1,9 +1,4 @@
|
|||||||
flags:
|
flags:
|
||||||
client:
|
|
||||||
carryforward: false
|
|
||||||
client-unit:
|
|
||||||
carryforward: false
|
|
||||||
|
|
||||||
discordeno:
|
discordeno:
|
||||||
carryforward: false
|
carryforward: false
|
||||||
discordeno-unit:
|
discordeno-unit:
|
||||||
|
|||||||
@@ -17,7 +17,6 @@
|
|||||||
"@discordeno/types": "./packages/types/dist/index.js",
|
"@discordeno/types": "./packages/types/dist/index.js",
|
||||||
"@discordeno/rest": "./packages/rest/dist/index.js",
|
"@discordeno/rest": "./packages/rest/dist/index.js",
|
||||||
"@discordeno/gateway": "./packages/gateway/dist/index.js",
|
"@discordeno/gateway": "./packages/gateway/dist/index.js",
|
||||||
"@discordeno/bot": "./packages/bot/dist/index.js",
|
"@discordeno/bot": "./packages/bot/dist/index.js"
|
||||||
"@discordeno/client": "./packages/client/dist/index.js"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
{
|
|
||||||
"all": true,
|
|
||||||
"src": "src",
|
|
||||||
"reporter": ["text", "lcov"],
|
|
||||||
"include": ["src/**/*.ts"],
|
|
||||||
"exclude": ["tests"]
|
|
||||||
}
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
{
|
|
||||||
"require": "ts-node/register",
|
|
||||||
"loader": "ts-node/esm",
|
|
||||||
"recursive": true,
|
|
||||||
"timeout": 2000,
|
|
||||||
"watch-extensions": "ts",
|
|
||||||
"watch-files": ["src", "tests"],
|
|
||||||
"enable-source-maps": true,
|
|
||||||
"parallel": false
|
|
||||||
}
|
|
||||||
@@ -1,24 +0,0 @@
|
|||||||
{
|
|
||||||
"jsc": {
|
|
||||||
"parser": {
|
|
||||||
"syntax": "typescript",
|
|
||||||
"decorators": true,
|
|
||||||
"dynamicImport": true
|
|
||||||
},
|
|
||||||
"transform": {
|
|
||||||
"legacyDecorator": true,
|
|
||||||
"decoratorMetadata": true
|
|
||||||
},
|
|
||||||
"target": "es2022",
|
|
||||||
"keepClassNames": true,
|
|
||||||
"loose": true
|
|
||||||
},
|
|
||||||
"module": {
|
|
||||||
"type": "es6",
|
|
||||||
"strict": false,
|
|
||||||
"strictMode": true,
|
|
||||||
"lazy": false,
|
|
||||||
"noInterop": false
|
|
||||||
},
|
|
||||||
"sourceMaps": true
|
|
||||||
}
|
|
||||||
@@ -1,36 +0,0 @@
|
|||||||
# @discordeno/client
|
|
||||||
|
|
||||||
This package is intended to provide a class based implementation on top of discordeno. It is based on Eris libraries API as it is just amazing! This also means since the API is near 1:1 the migration for Eris -> Discordeno is as simple as:
|
|
||||||
|
|
||||||
```ts
|
|
||||||
npm uninstall eris && npm install @discordeno/client
|
|
||||||
```
|
|
||||||
|
|
||||||
Then replace all `from 'eris';` with `from '@discordeno/client'` and enjoy!
|
|
||||||
|
|
||||||
## Credits
|
|
||||||
|
|
||||||
https://github.com/abalabahaha/eris
|
|
||||||
|
|
||||||
## Eris License
|
|
||||||
|
|
||||||
The MIT License (MIT)
|
|
||||||
|
|
||||||
Copyright (c) 2016-2021 abalabahaha
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
|
||||||
this software and associated documentation files (the "Software"), to deal in
|
|
||||||
the Software without restriction, including without limitation the rights to
|
|
||||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
|
||||||
the Software, and to permit persons to whom the Software is furnished to do so,
|
|
||||||
subject to the following conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in all
|
|
||||||
copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
|
||||||
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
|
||||||
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
|
||||||
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
|
||||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
@@ -1,48 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "@discordeno/client",
|
|
||||||
"version": "19.0.0-alpha.1",
|
|
||||||
"main": "./dist/index.js",
|
|
||||||
"types": "./dist/index.d.ts",
|
|
||||||
"type": "module",
|
|
||||||
"license": "Apache-2.0",
|
|
||||||
"repository": {
|
|
||||||
"type": "git",
|
|
||||||
"url": "https://github.com/discordeno/discordeno.git"
|
|
||||||
},
|
|
||||||
"scripts": {
|
|
||||||
"build": "swc --delete-dir-on-start src --out-dir dist",
|
|
||||||
"build:type": "tsc --declaration --emitDeclarationOnly --declarationDir dist",
|
|
||||||
"release-build": "yarn build && yarn build:type",
|
|
||||||
"fmt": "eslint --fix \"src/**/*.ts*\"",
|
|
||||||
"lint": "eslint \"src/**/*.ts*\"",
|
|
||||||
"test:unit-coverage": "c8 mocha --no-warnings 'tests/**/*.spec.ts'",
|
|
||||||
"test:unit": "c8 --r lcov mocha --no-warnings 'tests/**/*.spec.ts' && node ../../scripts/coveragePathFixing.js client",
|
|
||||||
"test:deno-unit": "swc tests --delete-dir-on-start --out-dir denoTestsDist && node ../../scripts/fixDenoTestExtension.js && deno test -A --import-map ../../denoImportMap.json denoTestsDist",
|
|
||||||
"test:unit:watch": "mocha --no-warnings --watch --parallel 'tests/**/*.spec.ts'",
|
|
||||||
"test:type": "tsc --noEmit",
|
|
||||||
"test:test-type": "tsc --project tsconfig.test.json"
|
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"@discordeno/gateway": "19.0.0-alpha.1",
|
|
||||||
"@discordeno/rest": "19.0.0-alpha.1",
|
|
||||||
"@discordeno/types": "19.0.0-alpha.1",
|
|
||||||
"@discordeno/utils": "19.0.0-alpha.1"
|
|
||||||
},
|
|
||||||
"devDependencies": {
|
|
||||||
"@swc/cli": "^0.1.62",
|
|
||||||
"@swc/core": "^1.3.40",
|
|
||||||
"@types/chai": "^4.3.4",
|
|
||||||
"@types/mocha": "^10.0.1",
|
|
||||||
"@types/node": "^18.15.3",
|
|
||||||
"@types/sinon": "^10.0.13",
|
|
||||||
"c8": "^7.13.0",
|
|
||||||
"chai": "^4.3.7",
|
|
||||||
"eslint": "^8.36.0",
|
|
||||||
"eslint-config-discordeno": "*",
|
|
||||||
"mocha": "^10.2.0",
|
|
||||||
"sinon": "^15.0.2",
|
|
||||||
"ts-node": "^10.9.1",
|
|
||||||
"tsconfig": "*",
|
|
||||||
"typescript": "^4.9.5"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,77 +0,0 @@
|
|||||||
import type { BigString } from './Client.js'
|
|
||||||
|
|
||||||
export class Base {
|
|
||||||
/** Internal storage of the id done in bigint to preserve memory */
|
|
||||||
_id: bigint
|
|
||||||
|
|
||||||
constructor(id: BigString) {
|
|
||||||
this._id = BigInt(id)
|
|
||||||
}
|
|
||||||
|
|
||||||
/** The snowflake id */
|
|
||||||
get id(): string {
|
|
||||||
return this._id.toString()
|
|
||||||
}
|
|
||||||
|
|
||||||
set id(value: BigString) {
|
|
||||||
this._id = BigInt(value)
|
|
||||||
}
|
|
||||||
|
|
||||||
get createdAt(): number {
|
|
||||||
return Number(this._id / 4194304n + 1420070400000n)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Calculates the timestamp in milliseconds associated with a Discord ID/snowflake.
|
|
||||||
* @deprecated Recommend using Object.createdAt or Client.snowflakeToTimestamp if you want to get a timestamp from a id. This is not desired but supported only to keep a similar api to eris.
|
|
||||||
*/
|
|
||||||
static getCreatedAt(id: string): number {
|
|
||||||
return Base.getDiscordEpoch(id) + 1420070400000
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the number of milliseconds since epoch represented by an ID/snowflake
|
|
||||||
* @deprecated Recommend using Object.createdAt or Client.snowflakeToTimestamp if you want to get a timestamp from a id. This is not desired but supported only to keep a similar api to eris.
|
|
||||||
*/
|
|
||||||
static getDiscordEpoch(id: string): number {
|
|
||||||
// @ts-expect-error some eris magic at play here
|
|
||||||
return Math.floor(id / 4194304)
|
|
||||||
}
|
|
||||||
|
|
||||||
toString(): string {
|
|
||||||
return `[${this.constructor.name} ${this.id}]`
|
|
||||||
}
|
|
||||||
|
|
||||||
toJSON(props: string[] = []): Record<string, any> {
|
|
||||||
const json = {
|
|
||||||
id: this.id,
|
|
||||||
createdAt: this.createdAt,
|
|
||||||
}
|
|
||||||
for (const prop of props) {
|
|
||||||
// @ts-expect-error some eris magic at play here
|
|
||||||
const value = this[prop]
|
|
||||||
const type = typeof value
|
|
||||||
if (value === undefined) {
|
|
||||||
continue
|
|
||||||
} else if ((type !== 'object' && type !== 'function' && type !== 'bigint') || value === null) {
|
|
||||||
// @ts-expect-error some eris magic at play here
|
|
||||||
json[prop] = value
|
|
||||||
} else if (value.toJSON !== undefined) {
|
|
||||||
// @ts-expect-error some eris magic at play here
|
|
||||||
json[prop] = value.toJSON()
|
|
||||||
} else if (value.values !== undefined) {
|
|
||||||
// @ts-expect-error some eris magic at play here
|
|
||||||
json[prop] = [...value.values()]
|
|
||||||
} else if (type === 'bigint') {
|
|
||||||
// @ts-expect-error some eris magic at play here
|
|
||||||
json[prop] = value.toString()
|
|
||||||
} else if (type === 'object') {
|
|
||||||
// @ts-expect-error some eris magic at play here
|
|
||||||
json[prop] = value
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return json
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default Base
|
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -1,140 +0,0 @@
|
|||||||
export class Collection<K, V> extends Map<K, V> {
|
|
||||||
limit: number | undefined
|
|
||||||
|
|
||||||
set(key: K, value: V): this {
|
|
||||||
// When this collection is limitd make sure we can add first
|
|
||||||
if ((this.limit ?? this.limit === 0) && this.size >= this.limit) {
|
|
||||||
return this
|
|
||||||
}
|
|
||||||
|
|
||||||
return super.set(key, value)
|
|
||||||
}
|
|
||||||
|
|
||||||
forceSet(key: K, value: V): this {
|
|
||||||
return super.set(key, value)
|
|
||||||
}
|
|
||||||
|
|
||||||
array(): V[] {
|
|
||||||
return [...this.values()]
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Retrieve the value of the first element in this collection */
|
|
||||||
first(): V | undefined {
|
|
||||||
return this.values().next().value
|
|
||||||
}
|
|
||||||
|
|
||||||
last(): V | undefined {
|
|
||||||
return [...this.values()][this.size - 1]
|
|
||||||
}
|
|
||||||
|
|
||||||
random(): V | undefined {
|
|
||||||
const array = [...this.values()]
|
|
||||||
return array[Math.floor(Math.random() * array.length)]
|
|
||||||
}
|
|
||||||
|
|
||||||
find(callback: (value: V, key: K) => boolean): V | undefined {
|
|
||||||
for (const key of this.keys()) {
|
|
||||||
const value = this.get(key)!
|
|
||||||
if (callback(value, key)) return value
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
filter(callback: (value: V, key: K) => boolean, returnArray?: true): V[]
|
|
||||||
filter(callback: (value: V, key: K) => boolean, returnArray: false): Collection<K, V>
|
|
||||||
filter(callback: (value: V, key: K) => boolean, returnArray = true): Collection<K, V> | V[] {
|
|
||||||
const relevant = new Collection<K, V>()
|
|
||||||
this.forEach((value, key) => {
|
|
||||||
if (callback(value, key)) relevant.set(key, value)
|
|
||||||
})
|
|
||||||
|
|
||||||
return returnArray ? relevant.array() : relevant
|
|
||||||
}
|
|
||||||
|
|
||||||
map<T>(callback: (value: V, key: K) => T): T[] {
|
|
||||||
const results = []
|
|
||||||
for (const key of this.keys()) {
|
|
||||||
const value = this.get(key)!
|
|
||||||
results.push(callback(value, key))
|
|
||||||
}
|
|
||||||
return results
|
|
||||||
}
|
|
||||||
|
|
||||||
some(callback: (value: V, key: K) => boolean): boolean {
|
|
||||||
for (const key of this.keys()) {
|
|
||||||
const value = this.get(key)!
|
|
||||||
if (callback(value, key)) return true
|
|
||||||
}
|
|
||||||
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
every(callback: (value: V, key: K) => boolean): boolean {
|
|
||||||
for (const key of this.keys()) {
|
|
||||||
const value = this.get(key)!
|
|
||||||
if (!callback(value, key)) return false
|
|
||||||
}
|
|
||||||
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
reduce<T>(callback: (accumulator: T, value: V, key: K) => T, initialValue?: T): T {
|
|
||||||
let accumulator: T = initialValue!
|
|
||||||
|
|
||||||
for (const key of this.keys()) {
|
|
||||||
const value = this.get(key)!
|
|
||||||
accumulator = callback(accumulator, value, key)
|
|
||||||
}
|
|
||||||
|
|
||||||
return accumulator
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Adds a object to the collection.
|
|
||||||
* @deprecated Recommend using Collection.set(). Keeping for the sake of Eris API.
|
|
||||||
* @deprecated extra parameter. No longer used, keeping for sake of Eris API.
|
|
||||||
*/
|
|
||||||
add(obj: V & { id: K }, extra?: unknown, replace?: boolean): V {
|
|
||||||
if (this.limit === 0) return obj
|
|
||||||
|
|
||||||
const existing = this.get(obj.id)
|
|
||||||
if (existing && !replace) {
|
|
||||||
return existing
|
|
||||||
}
|
|
||||||
|
|
||||||
this.set(obj.id, obj)
|
|
||||||
return obj
|
|
||||||
}
|
|
||||||
|
|
||||||
remove(obj: { id: K }): V | undefined {
|
|
||||||
const item = this.get(obj.id)
|
|
||||||
if (!item) return
|
|
||||||
|
|
||||||
this.delete(obj.id)
|
|
||||||
return item
|
|
||||||
}
|
|
||||||
|
|
||||||
update(obj: V & { id: K }, extra?: unknown, replace?: boolean): V {
|
|
||||||
const item = this.get(obj.id)
|
|
||||||
if (!item) {
|
|
||||||
this.set(obj.id, obj)
|
|
||||||
return obj
|
|
||||||
}
|
|
||||||
|
|
||||||
// @ts-expect-error some eris magic at play here
|
|
||||||
item.update?.(obj, extra)
|
|
||||||
return item
|
|
||||||
}
|
|
||||||
|
|
||||||
toRecord(): Record<string, V> {
|
|
||||||
const record: Record<string, V> = {}
|
|
||||||
for (const [key, value] of this.entries()) {
|
|
||||||
// @ts-expect-error should work fine
|
|
||||||
const finalKey = typeof key === 'string' ? key : key.toString()
|
|
||||||
record[finalKey] = value
|
|
||||||
}
|
|
||||||
|
|
||||||
return record
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default Collection
|
|
||||||
@@ -1,650 +0,0 @@
|
|||||||
export const GATEWAY_VERSION = 10
|
|
||||||
export const REST_VERSION = 10
|
|
||||||
|
|
||||||
export const MessageFlags = {
|
|
||||||
CROSSPOSTED: 1 << 0,
|
|
||||||
IS_CROSSPOST: 1 << 1,
|
|
||||||
SUPPRESS_EMBEDS: 1 << 2,
|
|
||||||
SOURCE_MESSAGE_DELETED: 1 << 3,
|
|
||||||
URGENT: 1 << 4,
|
|
||||||
HAS_THREAD: 1 << 5,
|
|
||||||
EPHEMERAL: 1 << 6,
|
|
||||||
LOADING: 1 << 7,
|
|
||||||
}
|
|
||||||
|
|
||||||
export const ActivityTypes = {
|
|
||||||
GAME: 0,
|
|
||||||
STREAMING: 1,
|
|
||||||
LISTENING: 2,
|
|
||||||
WATCHING: 3,
|
|
||||||
CUSTOM: 4,
|
|
||||||
COMPETING: 5,
|
|
||||||
}
|
|
||||||
|
|
||||||
export const ApplicationCommandOptionTypes = {
|
|
||||||
SUB_COMMAND: 1,
|
|
||||||
SUB_COMMAND_GROUP: 2,
|
|
||||||
STRING: 3,
|
|
||||||
INTEGER: 4,
|
|
||||||
BOOLEAN: 5,
|
|
||||||
USER: 6,
|
|
||||||
CHANNEL: 7,
|
|
||||||
ROLE: 8,
|
|
||||||
MENTIONABLE: 9,
|
|
||||||
NUMBER: 10,
|
|
||||||
}
|
|
||||||
|
|
||||||
export const ApplicationCommandPermissionTypes = {
|
|
||||||
ROLE: 1,
|
|
||||||
USER: 2,
|
|
||||||
}
|
|
||||||
|
|
||||||
export const ApplicationCommandTypes = {
|
|
||||||
CHAT_INPUT: 1,
|
|
||||||
USER: 2,
|
|
||||||
MESSAGE: 3,
|
|
||||||
}
|
|
||||||
|
|
||||||
export const AuditLogActions = {
|
|
||||||
GUILD_UPDATE: 1,
|
|
||||||
|
|
||||||
CHANNEL_CREATE: 10,
|
|
||||||
CHANNEL_UPDATE: 11,
|
|
||||||
CHANNEL_DELETE: 12,
|
|
||||||
CHANNEL_OVERWRITE_CREATE: 13,
|
|
||||||
CHANNEL_OVERWRITE_UPDATE: 14,
|
|
||||||
CHANNEL_OVERWRITE_DELETE: 15,
|
|
||||||
|
|
||||||
MEMBER_KICK: 20,
|
|
||||||
MEMBER_PRUNE: 21,
|
|
||||||
MEMBER_BAN_ADD: 22,
|
|
||||||
MEMBER_BAN_REMOVE: 23,
|
|
||||||
MEMBER_UPDATE: 24,
|
|
||||||
MEMBER_ROLE_UPDATE: 25,
|
|
||||||
MEMBER_MOVE: 26,
|
|
||||||
MEMBER_DISCONNECT: 27,
|
|
||||||
BOT_ADD: 28,
|
|
||||||
|
|
||||||
ROLE_CREATE: 30,
|
|
||||||
ROLE_UPDATE: 31,
|
|
||||||
ROLE_DELETE: 32,
|
|
||||||
|
|
||||||
INVITE_CREATE: 40,
|
|
||||||
INVITE_UPDATE: 41,
|
|
||||||
INVITE_DELETE: 42,
|
|
||||||
|
|
||||||
WEBHOOK_CREATE: 50,
|
|
||||||
WEBHOOK_UPDATE: 51,
|
|
||||||
WEBHOOK_DELETE: 52,
|
|
||||||
|
|
||||||
EMOJI_CREATE: 60,
|
|
||||||
EMOJI_UPDATE: 61,
|
|
||||||
EMOJI_DELETE: 62,
|
|
||||||
|
|
||||||
MESSAGE_DELETE: 72,
|
|
||||||
MESSAGE_BULK_DELETE: 73,
|
|
||||||
MESSAGE_PIN: 74,
|
|
||||||
MESSAGE_UNPIN: 75,
|
|
||||||
|
|
||||||
INTEGRATION_CREATE: 80,
|
|
||||||
INTEGRATION_UPDATE: 81,
|
|
||||||
INTEGRATION_DELETE: 82,
|
|
||||||
|
|
||||||
STAGE_INSTANCE_CREATE: 83,
|
|
||||||
STAGE_INSTANCE_UPDATE: 84,
|
|
||||||
STAGE_INSTANCE_DELETE: 85,
|
|
||||||
|
|
||||||
STICKER_CREATE: 90,
|
|
||||||
STICKER_UPDATE: 91,
|
|
||||||
STICKER_DELETE: 92,
|
|
||||||
|
|
||||||
GUILD_SCHEDULED_EVENT_CREATE: 100,
|
|
||||||
GUILD_SCHEDULED_EVENT_UPDATE: 101,
|
|
||||||
GUILD_SCHEDULED_EVENT_DELETE: 102,
|
|
||||||
|
|
||||||
THREAD_CREATE: 110,
|
|
||||||
THREAD_UPDATE: 111,
|
|
||||||
THREAD_DELETE: 112,
|
|
||||||
|
|
||||||
APPLICATION_COMMAND_PERMISSION_UPDATE: 121,
|
|
||||||
}
|
|
||||||
|
|
||||||
export const ButtonStyles = {
|
|
||||||
PRIMARY: 1,
|
|
||||||
SECONDARY: 2,
|
|
||||||
SUCCESS: 3,
|
|
||||||
DANGER: 4,
|
|
||||||
LINK: 5,
|
|
||||||
}
|
|
||||||
|
|
||||||
export enum ChannelTypes {
|
|
||||||
GUILD_TEXT = 0,
|
|
||||||
DM = 1,
|
|
||||||
GUILD_VOICE = 2,
|
|
||||||
GROUP_DM = 3,
|
|
||||||
GUILD_CATEGORY = 4,
|
|
||||||
GUILD_NEWS = 5,
|
|
||||||
GUILD_STORE = 6,
|
|
||||||
|
|
||||||
GUILD_NEWS_THREAD = 10,
|
|
||||||
GUILD_PUBLIC_THREAD = 11,
|
|
||||||
GUILD_PRIVATE_THREAD = 12,
|
|
||||||
GUILD_STAGE_VOICE = 13,
|
|
||||||
GUILD_STAGE = 13, // [DEPRECATED]
|
|
||||||
}
|
|
||||||
|
|
||||||
export const ComponentTypes = {
|
|
||||||
ACTION_ROW: 1,
|
|
||||||
BUTTON: 2,
|
|
||||||
SELECT_MENU: 3,
|
|
||||||
}
|
|
||||||
|
|
||||||
export const ConnectionVisibilityTypes = {
|
|
||||||
NONE: 0,
|
|
||||||
EVERYONE: 1,
|
|
||||||
}
|
|
||||||
|
|
||||||
export const DefaultMessageNotificationLevels = {
|
|
||||||
ALL_MESSAGES: 0,
|
|
||||||
ONLY_MENTIONS: 1,
|
|
||||||
}
|
|
||||||
|
|
||||||
export const ExplicitContentFilterLevels = {
|
|
||||||
DISABLED: 0,
|
|
||||||
MEMBERS_WITHOUT_ROLES: 1,
|
|
||||||
ALL_MEMBERS: 2,
|
|
||||||
}
|
|
||||||
|
|
||||||
export const GatewayOPCodes = {
|
|
||||||
DISPATCH: 0,
|
|
||||||
EVENT: 0, // [DEPRECATED]
|
|
||||||
HEARTBEAT: 1,
|
|
||||||
IDENTIFY: 2,
|
|
||||||
PRESENCE_UPDATE: 3,
|
|
||||||
STATUS_UPDATE: 3, // [DEPRECATED]
|
|
||||||
VOICE_STATE_UPDATE: 4,
|
|
||||||
VOICE_SERVER_PING: 5,
|
|
||||||
RESUME: 6,
|
|
||||||
RECONNECT: 7,
|
|
||||||
REQUEST_GUILD_MEMBERS: 8,
|
|
||||||
GET_GUILD_MEMBERS: 8, // [DEPRECATED]
|
|
||||||
INVALID_SESSION: 9,
|
|
||||||
HELLO: 10,
|
|
||||||
HEARTBEAT_ACK: 11,
|
|
||||||
SYNC_GUILD: 12,
|
|
||||||
SYNC_CALL: 13,
|
|
||||||
}
|
|
||||||
|
|
||||||
export const GuildFeatures = [
|
|
||||||
'ANIMATED_ICON',
|
|
||||||
'BANNER',
|
|
||||||
'COMMERCE',
|
|
||||||
'COMMUNITY',
|
|
||||||
'CREATOR_MONETIZABLE_PROVISIONAL',
|
|
||||||
'CREATOR_STORE_PAGE',
|
|
||||||
'DISCOVERABLE',
|
|
||||||
'FEATURABLE',
|
|
||||||
'INVITE_SPLASH',
|
|
||||||
'MEMBER_VERIFICATION_GATE_ENABLED',
|
|
||||||
'MORE_STICKERS',
|
|
||||||
'NEWS',
|
|
||||||
'PARTNERED',
|
|
||||||
'PREVIEW_ENABLED',
|
|
||||||
'PRIVATE_THREADS',
|
|
||||||
'ROLE_ICONS',
|
|
||||||
'ROLE_SUBSCRIPTIONS_AVAILABLE_FOR_PURCHASE',
|
|
||||||
'ROLE_SUBSCRIPTIONS_ENABLED',
|
|
||||||
'SEVEN_DAY_THREAD_ARCHIVE',
|
|
||||||
'THREE_DAY_THREAD_ARCHIVE',
|
|
||||||
'TICKETED_EVENTS_ENABLED',
|
|
||||||
'VANITY_URL',
|
|
||||||
'VERIFIED',
|
|
||||||
'VIP_REGIONS',
|
|
||||||
'WELCOME_SCREEN_ENABLED',
|
|
||||||
]
|
|
||||||
|
|
||||||
export const GuildIntegrationExpireBehavior = {
|
|
||||||
REMOVE_ROLE: 0,
|
|
||||||
KICK: 1,
|
|
||||||
}
|
|
||||||
export const GuildIntegrationTypes = ['twitch', 'youtube', 'discord']
|
|
||||||
|
|
||||||
export const GuildNSFWLevels = {
|
|
||||||
DEFAULT: 0,
|
|
||||||
EXPLICIT: 1,
|
|
||||||
SAFE: 2,
|
|
||||||
AGE_RESTRICTED: 3,
|
|
||||||
}
|
|
||||||
|
|
||||||
export const ImageFormats = ['jpg', 'jpeg', 'png', 'webp', 'gif']
|
|
||||||
|
|
||||||
export const ImageSizeBoundaries = {
|
|
||||||
MINIMUM: 16,
|
|
||||||
MAXIMUM: 4096,
|
|
||||||
}
|
|
||||||
|
|
||||||
export const Intents = {
|
|
||||||
guilds: 1 << 0,
|
|
||||||
guildMembers: 1 << 1,
|
|
||||||
guildBans: 1 << 2,
|
|
||||||
guildEmojisAndStickers: 1 << 3,
|
|
||||||
guildEmojis: 1 << 3, // [DEPRECATED]
|
|
||||||
guildIntegrations: 1 << 4,
|
|
||||||
guildWebhooks: 1 << 5,
|
|
||||||
guildInvites: 1 << 6,
|
|
||||||
guildVoiceStates: 1 << 7,
|
|
||||||
guildPresences: 1 << 8,
|
|
||||||
guildMessages: 1 << 9,
|
|
||||||
guildMessageReactions: 1 << 10,
|
|
||||||
guildMessageTyping: 1 << 11,
|
|
||||||
directMessages: 1 << 12,
|
|
||||||
directMessageReactions: 1 << 13,
|
|
||||||
directMessageTyping: 1 << 14,
|
|
||||||
|
|
||||||
guildScheduledEvents: 1 << 16,
|
|
||||||
// Override these below
|
|
||||||
allNonPrivileged: 0,
|
|
||||||
allPrivileged: 0,
|
|
||||||
all: 0,
|
|
||||||
}
|
|
||||||
|
|
||||||
Intents.allNonPrivileged =
|
|
||||||
Intents.guilds |
|
|
||||||
Intents.guildBans |
|
|
||||||
Intents.guildEmojisAndStickers |
|
|
||||||
Intents.guildIntegrations |
|
|
||||||
Intents.guildWebhooks |
|
|
||||||
Intents.guildInvites |
|
|
||||||
Intents.guildVoiceStates |
|
|
||||||
Intents.guildMessages |
|
|
||||||
Intents.guildMessageReactions |
|
|
||||||
Intents.guildMessageTyping |
|
|
||||||
Intents.directMessages |
|
|
||||||
Intents.directMessageReactions |
|
|
||||||
Intents.directMessageTyping |
|
|
||||||
Intents.guildScheduledEvents
|
|
||||||
Intents.allPrivileged = Intents.guildMembers | Intents.guildPresences
|
|
||||||
Intents.all = Intents.allNonPrivileged | Intents.allPrivileged
|
|
||||||
|
|
||||||
export const InteractionResponseTypes = {
|
|
||||||
PONG: 1,
|
|
||||||
CHANNEL_MESSAGE_WITH_SOURCE: 4,
|
|
||||||
DEFERRED_CHANNEL_MESSAGE_WITH_SOURCE: 5,
|
|
||||||
DEFERRED_UPDATE_MESSAGE: 6,
|
|
||||||
UPDATE_MESSAGE: 7,
|
|
||||||
APPLICATION_COMMAND_AUTOCOMPLETE_RESULT: 8,
|
|
||||||
}
|
|
||||||
|
|
||||||
export const InteractionTypes = {
|
|
||||||
PING: 1,
|
|
||||||
APPLICATION_COMMAND: 2,
|
|
||||||
MESSAGE_COMPONENT: 3,
|
|
||||||
APPLICATION_COMMAND_AUTOCOMPLETE: 4,
|
|
||||||
}
|
|
||||||
|
|
||||||
export const MFALevels = {
|
|
||||||
NONE: 0,
|
|
||||||
ELEVATED: 1,
|
|
||||||
}
|
|
||||||
|
|
||||||
export const MessageActivityFlags = {
|
|
||||||
INSTANCE: 1 << 0,
|
|
||||||
JOIN: 1 << 1,
|
|
||||||
SPECTATE: 1 << 2,
|
|
||||||
JOIN_REQUEST: 1 << 3,
|
|
||||||
SYNC: 1 << 4,
|
|
||||||
PLAY: 1 << 5,
|
|
||||||
PARTY_PRIVACY_FRIENDS: 1 << 6,
|
|
||||||
PARTY_PRIVACY_VOICE_CHANNEL: 1 << 7,
|
|
||||||
EMBEDDED: 1 << 8,
|
|
||||||
}
|
|
||||||
|
|
||||||
export const MessageActivityTypes = {
|
|
||||||
JOIN: 1,
|
|
||||||
SPECTATE: 2,
|
|
||||||
LISTEN: 3,
|
|
||||||
JOIN_REQUEST: 5,
|
|
||||||
}
|
|
||||||
|
|
||||||
export const MessageTypes = {
|
|
||||||
DEFAULT: 0,
|
|
||||||
RECIPIENT_ADD: 1,
|
|
||||||
RECIPIENT_REMOVE: 2,
|
|
||||||
CALL: 3,
|
|
||||||
CHANNEL_NAME_CHANGE: 4,
|
|
||||||
CHANNEL_ICON_CHANGE: 5,
|
|
||||||
CHANNEL_PINNED_MESSAGE: 6,
|
|
||||||
GUILD_MEMBER_JOIN: 7,
|
|
||||||
USER_PREMIUM_GUILD_SUBSCRIPTION: 8,
|
|
||||||
USER_PREMIUM_GUILD_SUBSCRIPTION_TIER_1: 9,
|
|
||||||
USER_PREMIUM_GUILD_SUBSCRIPTION_TIER_2: 10,
|
|
||||||
USER_PREMIUM_GUILD_SUBSCRIPTION_TIER_3: 11,
|
|
||||||
CHANNEL_FOLLOW_ADD: 12,
|
|
||||||
|
|
||||||
GUILD_DISCOVERY_DISQUALIFIED: 14,
|
|
||||||
GUILD_DISCOVERY_REQUALIFIED: 15,
|
|
||||||
GUILD_DISCOVERY_GRACE_PERIOD_INITIAL_WARNING: 16,
|
|
||||||
GUILD_DISCOVERY_GRACE_PERIOD_FINAL_WARNING: 17,
|
|
||||||
THREAD_CREATED: 18,
|
|
||||||
REPLY: 19,
|
|
||||||
CHAT_INPUT_COMMAND: 20,
|
|
||||||
THREAD_STARTER_MESSAGE: 21,
|
|
||||||
GUILD_INVITE_REMINDER: 22,
|
|
||||||
CONTEXT_MENU_COMMAND: 23,
|
|
||||||
AUTO_MODERATION_ACTION: 24,
|
|
||||||
ROLE_SUBSCRIPTION_PURCHASE: 25,
|
|
||||||
INTERACTION_PREMIUM_UPSELL: 26,
|
|
||||||
STAGE_START: 27,
|
|
||||||
STAGE_END: 28,
|
|
||||||
STAGE_SPEAKER: 29,
|
|
||||||
|
|
||||||
STAGE_TOPIC: 31,
|
|
||||||
GUILD_APPLICATION_PREMIUM_SUBSCRIPTION: 32,
|
|
||||||
}
|
|
||||||
|
|
||||||
export const PermissionOverwriteTypes = {
|
|
||||||
ROLE: 0,
|
|
||||||
USER: 1,
|
|
||||||
}
|
|
||||||
|
|
||||||
export const Permissions = {
|
|
||||||
createInstantInvite: 1n << 0n,
|
|
||||||
kickMembers: 1n << 1n,
|
|
||||||
banMembers: 1n << 2n,
|
|
||||||
administrator: 1n << 3n,
|
|
||||||
manageChannels: 1n << 4n,
|
|
||||||
manageGuild: 1n << 5n,
|
|
||||||
addReactions: 1n << 6n,
|
|
||||||
viewAuditLog: 1n << 7n,
|
|
||||||
viewAuditLogs: 1n << 7n, // [DEPRECATED]
|
|
||||||
voicePrioritySpeaker: 1n << 8n,
|
|
||||||
voiceStream: 1n << 9n,
|
|
||||||
stream: 1n << 9n, // [DEPRECATED]
|
|
||||||
viewChannel: 1n << 10n,
|
|
||||||
readMessages: 1n << 10n, // [DEPRECATED]
|
|
||||||
sendMessages: 1n << 11n,
|
|
||||||
sendTTSMessages: 1n << 12n,
|
|
||||||
manageMessages: 1n << 13n,
|
|
||||||
embedLinks: 1n << 14n,
|
|
||||||
attachFiles: 1n << 15n,
|
|
||||||
readMessageHistory: 1n << 16n,
|
|
||||||
mentionEveryone: 1n << 17n,
|
|
||||||
useExternalEmojis: 1n << 18n,
|
|
||||||
externalEmojis: 1n << 18n, // [DEPRECATED]
|
|
||||||
viewGuildInsights: 1n << 19n,
|
|
||||||
voiceConnect: 1n << 20n,
|
|
||||||
voiceSpeak: 1n << 21n,
|
|
||||||
voiceMuteMembers: 1n << 22n,
|
|
||||||
voiceDeafenMembers: 1n << 23n,
|
|
||||||
voiceMoveMembers: 1n << 24n,
|
|
||||||
voiceUseVAD: 1n << 25n,
|
|
||||||
changeNickname: 1n << 26n,
|
|
||||||
manageNicknames: 1n << 27n,
|
|
||||||
manageRoles: 1n << 28n,
|
|
||||||
manageWebhooks: 1n << 29n,
|
|
||||||
manageEmojisAndStickers: 1n << 30n,
|
|
||||||
manageEmojis: 1n << 30n, // [DEPRECATED]
|
|
||||||
useApplicationCommands: 1n << 31n,
|
|
||||||
useSlashCommands: 1n << 31n, // [DEPRECATED]
|
|
||||||
voiceRequestToSpeak: 1n << 32n,
|
|
||||||
manageEvents: 1n << 33n,
|
|
||||||
manageThreads: 1n << 34n,
|
|
||||||
createPublicThreads: 1n << 35n,
|
|
||||||
createPrivateThreads: 1n << 36n,
|
|
||||||
useExternalStickers: 1n << 37n,
|
|
||||||
sendMessagesInThreads: 1n << 38n,
|
|
||||||
startEmbeddedActivities: 1n << 39n,
|
|
||||||
moderateMembers: 1n << 40n,
|
|
||||||
// Override these below
|
|
||||||
all: 0n,
|
|
||||||
allText: 0n,
|
|
||||||
allVoice: 0n,
|
|
||||||
allGuild: 0n,
|
|
||||||
}
|
|
||||||
Permissions.allGuild =
|
|
||||||
Permissions.kickMembers |
|
|
||||||
Permissions.banMembers |
|
|
||||||
Permissions.administrator |
|
|
||||||
Permissions.manageChannels |
|
|
||||||
Permissions.manageGuild |
|
|
||||||
Permissions.viewAuditLog |
|
|
||||||
Permissions.viewGuildInsights |
|
|
||||||
Permissions.changeNickname |
|
|
||||||
Permissions.manageNicknames |
|
|
||||||
Permissions.manageRoles |
|
|
||||||
Permissions.manageWebhooks |
|
|
||||||
Permissions.manageEmojisAndStickers |
|
|
||||||
Permissions.manageEvents |
|
|
||||||
Permissions.moderateMembers
|
|
||||||
Permissions.allText =
|
|
||||||
Permissions.createInstantInvite |
|
|
||||||
Permissions.manageChannels |
|
|
||||||
Permissions.addReactions |
|
|
||||||
Permissions.viewChannel |
|
|
||||||
Permissions.sendMessages |
|
|
||||||
Permissions.sendTTSMessages |
|
|
||||||
Permissions.manageMessages |
|
|
||||||
Permissions.embedLinks |
|
|
||||||
Permissions.attachFiles |
|
|
||||||
Permissions.readMessageHistory |
|
|
||||||
Permissions.mentionEveryone |
|
|
||||||
Permissions.useExternalEmojis |
|
|
||||||
Permissions.manageRoles |
|
|
||||||
Permissions.manageWebhooks |
|
|
||||||
Permissions.useApplicationCommands |
|
|
||||||
Permissions.manageThreads |
|
|
||||||
Permissions.createPublicThreads |
|
|
||||||
Permissions.createPrivateThreads |
|
|
||||||
Permissions.useExternalStickers |
|
|
||||||
Permissions.sendMessagesInThreads
|
|
||||||
Permissions.allVoice =
|
|
||||||
Permissions.createInstantInvite |
|
|
||||||
Permissions.manageChannels |
|
|
||||||
Permissions.voicePrioritySpeaker |
|
|
||||||
Permissions.voiceStream |
|
|
||||||
Permissions.viewChannel |
|
|
||||||
Permissions.voiceConnect |
|
|
||||||
Permissions.voiceSpeak |
|
|
||||||
Permissions.voiceMuteMembers |
|
|
||||||
Permissions.voiceDeafenMembers |
|
|
||||||
Permissions.voiceMoveMembers |
|
|
||||||
Permissions.voiceUseVAD |
|
|
||||||
Permissions.manageRoles |
|
|
||||||
Permissions.voiceRequestToSpeak |
|
|
||||||
Permissions.startEmbeddedActivities
|
|
||||||
Permissions.all = Permissions.allGuild | Permissions.allText | Permissions.allVoice
|
|
||||||
|
|
||||||
export const PremiumTiers = {
|
|
||||||
NONE: 0,
|
|
||||||
TIER_1: 1,
|
|
||||||
TIER_2: 2,
|
|
||||||
TIER_3: 3,
|
|
||||||
}
|
|
||||||
|
|
||||||
export const GuildScheduledEventStatus = {
|
|
||||||
SCHEDULED: 1,
|
|
||||||
ACTIVE: 2,
|
|
||||||
COMPLETED: 3,
|
|
||||||
CANCELED: 4,
|
|
||||||
}
|
|
||||||
|
|
||||||
export const GuildScheduledEventEntityTypes = {
|
|
||||||
STAGE_INSTANCE: 1,
|
|
||||||
VOICE: 2,
|
|
||||||
EXTERNAL: 3,
|
|
||||||
}
|
|
||||||
|
|
||||||
export const GuildScheduledEventPrivacyLevel = {
|
|
||||||
PUBLIC: 1,
|
|
||||||
GUILD_ONLY: 2,
|
|
||||||
}
|
|
||||||
|
|
||||||
export const PremiumTypes = {
|
|
||||||
NONE: 0,
|
|
||||||
NITRO_CLASSIC: 1,
|
|
||||||
NITRO: 2,
|
|
||||||
}
|
|
||||||
|
|
||||||
export const StageInstancePrivacyLevel = {
|
|
||||||
PUBLIC: 1,
|
|
||||||
GUILD_ONLY: 2,
|
|
||||||
}
|
|
||||||
|
|
||||||
export const StickerFormats = {
|
|
||||||
PNG: 1,
|
|
||||||
APNG: 2,
|
|
||||||
LOTTIE: 3,
|
|
||||||
}
|
|
||||||
|
|
||||||
export const StickerTypes = {
|
|
||||||
STANDARD: 1,
|
|
||||||
GUILD: 2,
|
|
||||||
}
|
|
||||||
|
|
||||||
export const SystemChannelFlags = {
|
|
||||||
SUPPRESS_JOIN_NOTIFICATIONS: 1 << 0,
|
|
||||||
SUPPRESS_PREMIUM_SUBSCRIPTIONS: 1 << 1,
|
|
||||||
SUPPRESS_GUILD_REMINDER_NOTIFICATIONS: 1 << 2,
|
|
||||||
SUPPRESS_JOIN_NOTIFICATION_REPLIES: 1 << 3,
|
|
||||||
}
|
|
||||||
|
|
||||||
export const SystemJoinMessages = [
|
|
||||||
'%user% joined the party.',
|
|
||||||
'%user% is here.',
|
|
||||||
'Welcome, %user%. We hope you brought pizza.',
|
|
||||||
'A wild %user% appeared.',
|
|
||||||
'%user% just landed.',
|
|
||||||
'%user% just slid into the server.',
|
|
||||||
'%user% just showed up!',
|
|
||||||
'Welcome %user%. Say hi!',
|
|
||||||
'%user% hopped into the server.',
|
|
||||||
'Everyone welcome %user%!',
|
|
||||||
"Glad you're here, %user%.",
|
|
||||||
'Good to see you, %user%.',
|
|
||||||
'Yay you made it, %user%!',
|
|
||||||
]
|
|
||||||
|
|
||||||
export const ThreadMemberFlags = {
|
|
||||||
HAS_INTERACTED: 1 << 0,
|
|
||||||
ALL_MESSAGES: 1 << 1,
|
|
||||||
ONLY_MENTIONS: 1 << 2,
|
|
||||||
NO_MESSAGES: 1 << 3,
|
|
||||||
}
|
|
||||||
|
|
||||||
export const UserFlags = {
|
|
||||||
NONE: 0,
|
|
||||||
DISCORD_STAFF: 1 << 0,
|
|
||||||
DISCORD_EMPLOYEE: 1 << 0,
|
|
||||||
PARTNER: 1 << 1,
|
|
||||||
PARTNERED_SERVER_OWNER: 1 << 1,
|
|
||||||
DISCORD_PARTNER: 1 << 1, // [DEPRECATED]
|
|
||||||
HYPESQUAD: 1 << 2,
|
|
||||||
HYPESQUAD_EVENTS: 1 << 2,
|
|
||||||
BUG_HUNTER_LEVEL_1: 1 << 3,
|
|
||||||
HOUSE_BRAVERY: 1 << 6,
|
|
||||||
HYPESQUAD_ONLINE_HOUSE_1: 1 << 6,
|
|
||||||
HOUSE_BRILLIANCE: 1 << 7,
|
|
||||||
HYPESQUAD_ONLINE_HOUSE_2: 1 << 7,
|
|
||||||
HOUSE_BALANCE: 1 << 8,
|
|
||||||
HYPESQUAD_ONLINE_HOUSE_3: 1 << 8,
|
|
||||||
PREMIUM_EARLY_SUPPORTER: 1 << 9,
|
|
||||||
EARLY_SUPPORTER: 1 << 9,
|
|
||||||
TEAM_PSEUDO_USER: 1 << 10,
|
|
||||||
TEAM_USER: 1 << 10,
|
|
||||||
SYSTEM: 1 << 12,
|
|
||||||
BUG_HUNTER_LEVEL_2: 1 << 14,
|
|
||||||
VERIFIED_BOT: 1 << 16,
|
|
||||||
VERIFIED_DEVELOPER: 1 << 17,
|
|
||||||
EARLY_VERIFIED_BOT_DEVELOPER: 1 << 17,
|
|
||||||
VERIFIED_BOT_DEVELOPER: 1 << 17,
|
|
||||||
CERTIFIED_MODERATOR: 1 << 18,
|
|
||||||
DISCORD_CERTIFIED_MODERATOR: 1 << 18,
|
|
||||||
BOT_HTTP_INTERACTIONS: 1 << 19,
|
|
||||||
}
|
|
||||||
|
|
||||||
export const VerificationLevels = {
|
|
||||||
NONE: 0,
|
|
||||||
LOW: 1,
|
|
||||||
MEDIUM: 2,
|
|
||||||
HIGH: 3,
|
|
||||||
VERY_HIGH: 4,
|
|
||||||
}
|
|
||||||
|
|
||||||
export const VideoQualityModes = {
|
|
||||||
AUTO: 1,
|
|
||||||
FULL: 2,
|
|
||||||
}
|
|
||||||
|
|
||||||
export const VoiceOPCodes = {
|
|
||||||
IDENTIFY: 0,
|
|
||||||
SELECT_PROTOCOL: 1,
|
|
||||||
READY: 2,
|
|
||||||
HEARTBEAT: 3,
|
|
||||||
SESSION_DESCRIPTION: 4,
|
|
||||||
SPEAKING: 5,
|
|
||||||
HEARTBEAT_ACK: 6,
|
|
||||||
RESUME: 7,
|
|
||||||
HELLO: 8,
|
|
||||||
RESUMED: 9,
|
|
||||||
CLIENT_DISCONNECT: 13,
|
|
||||||
DISCONNECT: 13, // [DEPRECATED]
|
|
||||||
}
|
|
||||||
|
|
||||||
export const WebhookTypes = {
|
|
||||||
INCOMING: 1,
|
|
||||||
CHANNEL_FOLLOWER: 2,
|
|
||||||
APPLICATION: 3,
|
|
||||||
}
|
|
||||||
|
|
||||||
export type IntentStrings = keyof typeof Intents
|
|
||||||
export type PermissionClientStrings = keyof typeof Permissions
|
|
||||||
|
|
||||||
export const Constants = {
|
|
||||||
GATEWAY_VERSION,
|
|
||||||
REST_VERSION,
|
|
||||||
MessageFlags,
|
|
||||||
ActivityTypes,
|
|
||||||
ApplicationCommandOptionTypes,
|
|
||||||
ApplicationCommandPermissionTypes,
|
|
||||||
ApplicationCommandTypes,
|
|
||||||
AuditLogActions,
|
|
||||||
ButtonStyles,
|
|
||||||
ComponentTypes,
|
|
||||||
ConnectionVisibilityTypes,
|
|
||||||
DefaultMessageNotificationLevels,
|
|
||||||
ExplicitContentFilterLevels,
|
|
||||||
GatewayOPCodes,
|
|
||||||
GuildFeatures,
|
|
||||||
GuildIntegrationExpireBehavior,
|
|
||||||
GuildIntegrationTypes,
|
|
||||||
GuildNSFWLevels,
|
|
||||||
ImageFormats,
|
|
||||||
ImageSizeBoundaries,
|
|
||||||
Intents,
|
|
||||||
InteractionResponseTypes,
|
|
||||||
InteractionTypes,
|
|
||||||
MFALevels,
|
|
||||||
MessageActivityFlags,
|
|
||||||
MessageActivityTypes,
|
|
||||||
MessageTypes,
|
|
||||||
PermissionOverwriteTypes,
|
|
||||||
Permissions,
|
|
||||||
PremiumTiers,
|
|
||||||
GuildScheduledEventStatus,
|
|
||||||
GuildScheduledEventEntityTypes,
|
|
||||||
GuildScheduledEventPrivacyLevel,
|
|
||||||
PremiumTypes,
|
|
||||||
StageInstancePrivacyLevel,
|
|
||||||
StickerFormats,
|
|
||||||
StickerTypes,
|
|
||||||
SystemChannelFlags,
|
|
||||||
SystemJoinMessages,
|
|
||||||
ThreadMemberFlags,
|
|
||||||
UserFlags,
|
|
||||||
VerificationLevels,
|
|
||||||
VideoQualityModes,
|
|
||||||
VoiceOPCodes,
|
|
||||||
WebhookTypes,
|
|
||||||
}
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-redeclare
|
|
||||||
export type Constants = typeof Constants
|
|
||||||
@@ -1,136 +0,0 @@
|
|||||||
/* eslint-disable @typescript-eslint/explicit-function-return-type */
|
|
||||||
import type { BigString } from './Client.js'
|
|
||||||
|
|
||||||
export const ORIGINAL_INTERACTION_RESPONSE = (appID: BigString, interactToken: string) => `/webhooks/${appID}/${interactToken}`
|
|
||||||
export const COMMAND = (applicationID: BigString, commandID: BigString) => `/applications/${applicationID}/commands/${commandID}`
|
|
||||||
export const COMMANDS = (applicationID: BigString) => `/applications/${applicationID}/commands`
|
|
||||||
export const COMMAND_PERMISSIONS = (applicationID: BigString, guildID: BigString, commandID: BigString) =>
|
|
||||||
`/applications/${applicationID}/guilds/${guildID}/commands/${commandID}/permissions`
|
|
||||||
export const CHANNEL = (chanID: BigString) => `/channels/${chanID}`
|
|
||||||
export const CHANNEL_BULK_DELETE = (chanID: BigString) => `/channels/${chanID}/messages/bulk-delete`
|
|
||||||
export const CHANNEL_CALL_RING = (chanID: BigString) => `/channels/${chanID}/call/ring`
|
|
||||||
export const CHANNEL_CROSSPOST = (chanID: BigString, msgID: BigString) => `/channels/${chanID}/messages/${msgID}/crosspost`
|
|
||||||
export const CHANNEL_FOLLOW = (chanID: BigString) => `/channels/${chanID}/followers`
|
|
||||||
export const CHANNEL_INVITES = (chanID: BigString) => `/channels/${chanID}/invites`
|
|
||||||
export const CHANNEL_MESSAGE_REACTION = (chanID: BigString, msgID: BigString, reaction: string) =>
|
|
||||||
`/channels/${chanID}/messages/${msgID}/reactions/${reaction}`
|
|
||||||
export const CHANNEL_MESSAGE_REACTION_USER = (chanID: BigString, msgID: BigString, reaction: string, userID: BigString) =>
|
|
||||||
`/channels/${chanID}/messages/${msgID}/reactions/${reaction}/${userID}`
|
|
||||||
export const CHANNEL_MESSAGE_REACTIONS = (chanID: BigString, msgID: BigString) => `/channels/${chanID}/messages/${msgID}/reactions`
|
|
||||||
export const CHANNEL_MESSAGE = (chanID: BigString, msgID: BigString) => `/channels/${chanID}/messages/${msgID}`
|
|
||||||
export const CHANNEL_MESSAGES = (chanID: BigString) => `/channels/${chanID}/messages`
|
|
||||||
export const CHANNEL_MESSAGES_SEARCH = (chanID: BigString) => `/channels/${chanID}/messages/search`
|
|
||||||
export const CHANNEL_PERMISSION = (chanID: BigString, overID: BigString) => `/channels/${chanID}/permissions/${overID}`
|
|
||||||
export const CHANNEL_PERMISSIONS = (chanID: BigString) => `/channels/${chanID}/permissions`
|
|
||||||
export const CHANNEL_PIN = (chanID: BigString, msgID: BigString) => `/channels/${chanID}/pins/${msgID}`
|
|
||||||
export const CHANNEL_PINS = (chanID: BigString) => `/channels/${chanID}/pins`
|
|
||||||
export const CHANNEL_RECIPIENT = (groupID: BigString, userID: BigString) => `/channels/${groupID}/recipients/${userID}`
|
|
||||||
export const CHANNEL_TYPING = (chanID: BigString) => `/channels/${chanID}/typing`
|
|
||||||
export const CHANNEL_WEBHOOKS = (chanID: BigString) => `/channels/${chanID}/webhooks`
|
|
||||||
export const CHANNELS = '/channels'
|
|
||||||
export const CUSTOM_EMOJI_GUILD = (emojiID: BigString) => `/emojis/${emojiID}/guild`
|
|
||||||
export const DISCOVERY_CATEGORIES = '/discovery/categories'
|
|
||||||
export const DISCOVERY_VALIDATION = '/discovery/valid-term'
|
|
||||||
export const GATEWAY = '/gateway'
|
|
||||||
export const GATEWAY_BOT = '/gateway/bot'
|
|
||||||
export const GUILD = (guildID: BigString) => `/guilds/${guildID}`
|
|
||||||
export const GUILD_AUDIT_LOGS = (guildID: BigString) => `/guilds/${guildID}/audit-logs`
|
|
||||||
export const GUILD_BAN = (guildID: BigString, memberID: BigString) => `/guilds/${guildID}/bans/${memberID}`
|
|
||||||
export const GUILD_BANS = (guildID: BigString) => `/guilds/${guildID}/bans`
|
|
||||||
export const GUILD_CHANNELS = (guildID: BigString) => `/guilds/${guildID}/channels`
|
|
||||||
export const GUILD_COMMAND = (applicationID: BigString, guildID: BigString, commandID: BigString) =>
|
|
||||||
`/applications/${applicationID}/guilds/${guildID}/commands/${commandID}`
|
|
||||||
export const GUILD_COMMAND_PERMISSIONS = (applicationID: BigString, guildID: BigString) =>
|
|
||||||
`/applications/${applicationID}/guilds/${guildID}/commands/permissions`
|
|
||||||
export const GUILD_COMMANDS = (applicationID: BigString, guildID: BigString) => `/applications/${applicationID}/guilds/${guildID}/commands`
|
|
||||||
export const GUILD_DISCOVERY = (guildID: BigString) => `/guilds/${guildID}/discovery-metadata`
|
|
||||||
export const GUILD_DISCOVERY_CATEGORY = (guildID: BigString, categoryID: BigString) => `/guilds/${guildID}/discovery-categories/${categoryID}`
|
|
||||||
export const GUILD_EMOJI = (guildID: BigString, emojiID: BigString) => `/guilds/${guildID}/emojis/${emojiID}`
|
|
||||||
export const GUILD_EMOJIS = (guildID: BigString) => `/guilds/${guildID}/emojis`
|
|
||||||
export const GUILD_INTEGRATION = (guildID: BigString, inteID: BigString) => `/guilds/${guildID}/integrations/${inteID}`
|
|
||||||
export const GUILD_INTEGRATION_SYNC = (guildID: BigString, inteID: BigString) => `/guilds/${guildID}/integrations/${inteID}/sync`
|
|
||||||
export const GUILD_INTEGRATIONS = (guildID: BigString) => `/guilds/${guildID}/integrations`
|
|
||||||
export const GUILD_INVITES = (guildID: BigString) => `/guilds/${guildID}/invites`
|
|
||||||
export const GUILD_VANITY_URL = (guildID: BigString) => `/guilds/${guildID}/vanity-url`
|
|
||||||
export const GUILD_MEMBER = (guildID: BigString, memberID: BigString) => `/guilds/${guildID}/members/${memberID}`
|
|
||||||
export const GUILD_MEMBER_NICK = (guildID: BigString, memberID: BigString) => `/guilds/${guildID}/members/${memberID}/nick`
|
|
||||||
export const GUILD_MEMBER_ROLE = (guildID: BigString, memberID: BigString, roleID: BigString) =>
|
|
||||||
`/guilds/${guildID}/members/${memberID}/roles/${roleID}`
|
|
||||||
export const GUILD_MEMBERS = (guildID: BigString) => `/guilds/${guildID}/members`
|
|
||||||
export const GUILD_MEMBERS_SEARCH = (guildID: BigString) => `/guilds/${guildID}/members/search`
|
|
||||||
export const GUILD_MESSAGES_SEARCH = (guildID: BigString) => `/guilds/${guildID}/messages/search`
|
|
||||||
export const GUILD_PREVIEW = (guildID: BigString) => `/guilds/${guildID}/preview`
|
|
||||||
export const GUILD_PRUNE = (guildID: BigString) => `/guilds/${guildID}/prune`
|
|
||||||
export const GUILD_ROLE = (guildID: BigString, roleID: BigString) => `/guilds/${guildID}/roles/${roleID}`
|
|
||||||
export const GUILD_ROLES = (guildID: BigString) => `/guilds/${guildID}/roles`
|
|
||||||
export const GUILD_STICKER = (guildID: BigString, stickerID: BigString) => `/guilds/${guildID}/stickers/${stickerID}`
|
|
||||||
export const GUILD_STICKERS = (guildID: BigString) => `/guilds/${guildID}/stickers`
|
|
||||||
export const GUILD_TEMPLATE = (code: string) => `/guilds/templates/${code}`
|
|
||||||
export const GUILD_TEMPLATES = (guildID: BigString) => `/guilds/${guildID}/templates`
|
|
||||||
export const GUILD_TEMPLATE_GUILD = (guildID: BigString, code: string) => `/guilds/${guildID}/templates/${code}`
|
|
||||||
export const GUILD_VOICE_REGIONS = (guildID: BigString) => `/guilds/${guildID}/regions`
|
|
||||||
export const GUILD_WEBHOOKS = (guildID: BigString) => `/guilds/${guildID}/webhooks`
|
|
||||||
export const GUILD_WELCOME_SCREEN = (guildID: BigString) => `/guilds/${guildID}/welcome-screen`
|
|
||||||
export const GUILD_WIDGET = (guildID: BigString) => `/guilds/${guildID}/widget.json`
|
|
||||||
export const GUILD_WIDGET_SETTINGS = (guildID: BigString) => `/guilds/${guildID}/widget`
|
|
||||||
export const GUILD_VOICE_STATE = (guildID: BigString, user: BigString) => `/guilds/${guildID}/voice-states/${user}`
|
|
||||||
export const GUILDS = '/guilds'
|
|
||||||
export const INTERACTION_RESPOND = (interactID: BigString, interactToken: string) => `/interactions/${interactID}/${interactToken}/callback`
|
|
||||||
export const INVITE = (inviteID: string) => `/invites/${inviteID}`
|
|
||||||
export const OAUTH2_APPLICATION = (appID: BigString) => `/oauth2/applications/${appID}`
|
|
||||||
export const STAGE_INSTANCE = (channelID: BigString) => `/stage-instances/${channelID}`
|
|
||||||
export const STAGE_INSTANCES = '/stage-instances'
|
|
||||||
export const STICKER = (stickerID: BigString) => `/stickers/${stickerID}`
|
|
||||||
export const STICKER_PACKS = '/sticker-packs'
|
|
||||||
export const THREAD_MEMBER = (channelID: BigString, userID: BigString) => `/channels/${channelID}/thread-members/${userID}`
|
|
||||||
export const THREAD_MEMBERS = (channelID: BigString) => `/channels/${channelID}/thread-members`
|
|
||||||
export const THREAD_WITH_MESSAGE = (channelID: BigString, msgID: BigString) => `/channels/${channelID}/messages/${msgID}/threads`
|
|
||||||
export const THREAD_WITHOUT_MESSAGE = (channelID: BigString) => `/channels/${channelID}/threads`
|
|
||||||
export const THREADS_ACTIVE = (channelID: BigString) => `/channels/${channelID}/threads/active`
|
|
||||||
export const THREADS_ARCHIVED = (channelID: BigString, type: string) => `/channels/${channelID}/threads/archived/${type}`
|
|
||||||
export const THREADS_ARCHIVED_JOINED = (channelID: BigString) => `/channels/${channelID}/users/@me/threads/archived/private`
|
|
||||||
export const THREADS_GUILD_ACTIVE = (guildID: BigString) => `/guilds/${guildID}/threads/active`
|
|
||||||
export const USER = (userID: BigString) => `/users/${userID}`
|
|
||||||
export const USER_BILLING = (userID: BigString) => `/users/${userID}/billing`
|
|
||||||
export const USER_BILLING_PAYMENTS = (userID: BigString) => `/users/${userID}/billing/payments`
|
|
||||||
export const USER_BILLING_PREMIUM_SUBSCRIPTION = (userID: BigString) => `/users/${userID}/billing/premium-subscription`
|
|
||||||
export const USER_CHANNELS = (userID: BigString) => `/users/${userID}/channels`
|
|
||||||
export const USER_CONNECTIONS = (userID: BigString) => `/users/${userID}/connections`
|
|
||||||
export const USER_CONNECTION_PLATFORM = (userID: BigString, platform: string, id: string) => `/users/${userID}/connections/${platform}/${id}`
|
|
||||||
export const USER_GUILD = (userID: BigString, guildID: BigString) => `/users/${userID}/guilds/${guildID}`
|
|
||||||
export const USER_GUILDS = (userID: BigString) => `/users/${userID}/guilds`
|
|
||||||
export const USER_MFA_CODES = (userID: BigString) => `/users/${userID}/mfa/codes`
|
|
||||||
export const USER_MFA_TOTP_DISABLE = (userID: BigString) => `/users/${userID}/mfa/totp/disable`
|
|
||||||
export const USER_MFA_TOTP_ENABLE = (userID: BigString) => `/users/${userID}/mfa/totp/enable`
|
|
||||||
export const USER_NOTE = (userID: BigString, targetID: BigString) => `/users/${userID}/note/${targetID}`
|
|
||||||
export const USER_PROFILE = (userID: BigString) => `/users/${userID}/profile`
|
|
||||||
export const USER_RELATIONSHIP = (userID: BigString, relID: BigString) => `/users/${userID}/relationships/${relID}`
|
|
||||||
export const USER_SETTINGS = (userID: BigString) => `/users/${userID}/settings`
|
|
||||||
export const USERS = '/users'
|
|
||||||
export const VOICE_REGIONS = '/voice/regions'
|
|
||||||
export const WEBHOOK = (hookID: BigString) => `/webhooks/${hookID}`
|
|
||||||
export const WEBHOOK_MESSAGE = (hookID: BigString, token: string, msgID: BigString) => `/webhooks/${hookID}/${token}/messages/${msgID}`
|
|
||||||
export const WEBHOOK_SLACK = (hookID: BigString) => `/webhooks/${hookID}/slack`
|
|
||||||
export const WEBHOOK_TOKEN = (hookID: BigString, token: string) => `/webhooks/${hookID}/${token}`
|
|
||||||
export const WEBHOOK_TOKEN_SLACK = (hookID: BigString, token: string) => `/webhooks/${hookID}/${token}/slack`
|
|
||||||
|
|
||||||
// CDN Endpoints
|
|
||||||
export const ACHIEVEMENT_ICON = (applicationID: BigString, achievementID: BigString, icon: string) =>
|
|
||||||
`/app-assets/${applicationID}/achievements/${achievementID}/icons/${icon}`
|
|
||||||
export const APPLICATION_ASSET = (applicationID: BigString, asset: string) => `/app-assets/${applicationID}/${asset}`
|
|
||||||
export const APPLICATION_ICON = (applicationID: BigString, icon: string) => `/app-icons/${applicationID}/${icon}`
|
|
||||||
export const BANNER = (guildOrUserID: BigString, hash: string) => `/banners/${guildOrUserID}/${hash}`
|
|
||||||
export const CHANNEL_ICON = (chanID: BigString, chanIcon: string) => `/channel-icons/${chanID}/${chanIcon}`
|
|
||||||
export const CUSTOM_EMOJI = (emojiID: BigString) => `/emojis/${emojiID}`
|
|
||||||
export const DEFAULT_USER_AVATAR = (userDiscriminator: string) => `/embed/avatars/${userDiscriminator}`
|
|
||||||
export const GUILD_AVATAR = (guildID: BigString, userID: BigString, guildAvatar: string) =>
|
|
||||||
`/guilds/${guildID}/users/${userID}/avatars/${guildAvatar}`
|
|
||||||
export const GUILD_DISCOVERY_SPLASH = (guildID: BigString, guildDiscoverySplash: string) => `/discovery-splashes/${guildID}/${guildDiscoverySplash}`
|
|
||||||
export const GUILD_ICON = (guildID: BigString, guildIcon: string) => `/icons/${guildID}/${guildIcon}`
|
|
||||||
export const GUILD_SPLASH = (guildID: BigString, guildSplash: string) => `/splashes/${guildID}/${guildSplash}`
|
|
||||||
export const ROLE_ICON = (roleID: BigString, roleIcon: string) => `/role-icons/${roleID}/${roleIcon}`
|
|
||||||
export const TEAM_ICON = (teamID: BigString, teamIcon: string) => `/team-icons/${teamID}/${teamIcon}`
|
|
||||||
export const USER_AVATAR = (userID: BigString, userAvatar: string) => `/avatars/${userID}/${userAvatar}`
|
|
||||||
|
|
||||||
// Client Endpoints
|
|
||||||
export const MESSAGE_LINK = (guildID: BigString, channelID: BigString, messageID: BigString) => `/channels/${guildID}/${channelID}/${messageID}`
|
|
||||||
@@ -1,116 +0,0 @@
|
|||||||
import type { RequestMethods, RestManager } from '@discordeno/rest'
|
|
||||||
import { createRestManager } from '@discordeno/rest'
|
|
||||||
import Base from './Base.js'
|
|
||||||
import type Client from './Client.js'
|
|
||||||
import type { FileContent, RequestHandlerOptions } from './typings.js'
|
|
||||||
|
|
||||||
// TODO: make dynamic based on package.json file
|
|
||||||
const version = '19.0.0-alpha.1'
|
|
||||||
|
|
||||||
export class RequestHandler {
|
|
||||||
/** The client manager. */
|
|
||||||
client: Client
|
|
||||||
/** The options this manager was configured with. */
|
|
||||||
options: RequestHandlerOptions
|
|
||||||
/** The user agent used to make requests. */
|
|
||||||
userAgent: string
|
|
||||||
/** The rate limits currently in cache. */
|
|
||||||
ratelimits: Record<string, unknown>
|
|
||||||
/** The latency information for this manager. */
|
|
||||||
latencyRef: {
|
|
||||||
latency: number
|
|
||||||
raw: number[]
|
|
||||||
timeOffset: number
|
|
||||||
timeOffsets: number[]
|
|
||||||
lastTimeOffsetCheck: number
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Whether or not the manager is globally blocked. */
|
|
||||||
globalBlock: boolean
|
|
||||||
/** The ready queue */
|
|
||||||
readyQueue: unknown[]
|
|
||||||
/** The internal rest manager from dd. */
|
|
||||||
discordeno: RestManager
|
|
||||||
|
|
||||||
constructor(client: Client, options: RequestHandlerOptions) {
|
|
||||||
this.options = options = Object.assign(
|
|
||||||
{
|
|
||||||
// agent: client.options.agent || null,
|
|
||||||
agent: null,
|
|
||||||
baseURL: 'https://discord.com/api',
|
|
||||||
decodeReasons: true,
|
|
||||||
disableLatencyCompensation: false,
|
|
||||||
domain: 'discord.com',
|
|
||||||
// latencyThreshold: client.options.latencyThreshold || 30000,
|
|
||||||
latencyThreshold: 30000,
|
|
||||||
// ratelimiterOffset: client.options.ratelimiterOffset || 0,
|
|
||||||
ratelimiterOffset: 0,
|
|
||||||
// requestTimeout: client.options.requestTimeout || 15000,
|
|
||||||
requestTimeout: 15000,
|
|
||||||
},
|
|
||||||
options,
|
|
||||||
)
|
|
||||||
|
|
||||||
this.client = client
|
|
||||||
this.discordeno = createRestManager({
|
|
||||||
token: this.client.token,
|
|
||||||
proxy:
|
|
||||||
options.baseURL ?? this.client.options.proxyURL
|
|
||||||
? {
|
|
||||||
baseUrl: options.baseURL ?? this.client.options.proxyURL!,
|
|
||||||
authorization: this.client.token,
|
|
||||||
}
|
|
||||||
: undefined,
|
|
||||||
})
|
|
||||||
|
|
||||||
this.userAgent = `DiscordBot (https://github.com/discordeno/discordeno, ${version})`
|
|
||||||
this.ratelimits = {}
|
|
||||||
this.latencyRef = {
|
|
||||||
latency: this.options.ratelimiterOffset ?? 0,
|
|
||||||
raw: new Array(10).fill(this.options.ratelimiterOffset),
|
|
||||||
timeOffset: 0,
|
|
||||||
timeOffsets: new Array(10).fill(0),
|
|
||||||
lastTimeOffsetCheck: 0,
|
|
||||||
}
|
|
||||||
this.globalBlock = false
|
|
||||||
this.readyQueue = []
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @deprecated Use `.client` instead
|
|
||||||
*/
|
|
||||||
get _client(): Client {
|
|
||||||
return this.client
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @deprecated Useless, handled by discordeno itself. Kept for Eris api compatibility.
|
|
||||||
*/
|
|
||||||
globalUnblock(): void {}
|
|
||||||
|
|
||||||
warnUser(): void {}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Make an API request
|
|
||||||
* @deprecated Use a proxy rest instead.
|
|
||||||
*/
|
|
||||||
async request(method: RequestMethods, url: string, auth?: boolean, body?: any, file?: FileContent): Promise<unknown> {
|
|
||||||
if (file) body.file = file
|
|
||||||
|
|
||||||
return await this.discordeno.makeRequest(method, url, body)
|
|
||||||
}
|
|
||||||
|
|
||||||
routefy(url: string, method: RequestMethods): string {
|
|
||||||
return this.discordeno.simplifyUrl(url, method)
|
|
||||||
}
|
|
||||||
|
|
||||||
toString(): string {
|
|
||||||
return '[RequestHandler]'
|
|
||||||
}
|
|
||||||
|
|
||||||
toJSON(props: string[] = []): Record<string, any> {
|
|
||||||
return Base.prototype.toJSON.call(this, ['globalBlock', 'latencyRef', 'options', 'ratelimits', 'readyQueue', 'userAgent', ...props])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default RequestHandler
|
|
||||||
@@ -1,149 +0,0 @@
|
|||||||
/* eslint-disable no-useless-call */
|
|
||||||
|
|
||||||
import type { DiscordInvite, DiscordInviteCreate, DiscordMemberWithUser, TargetTypes } from '@discordeno/types'
|
|
||||||
import Base from '../Base.js'
|
|
||||||
import type Client from '../Client.js'
|
|
||||||
import type Channel from './channels/Channel.js'
|
|
||||||
import Guild from './guilds/Guild.js'
|
|
||||||
import Member from './guilds/Member.js'
|
|
||||||
import User from './users/User.js'
|
|
||||||
|
|
||||||
export class Invite {
|
|
||||||
/** The client object. */
|
|
||||||
client: Client
|
|
||||||
/** The invite code (unique Id) */
|
|
||||||
code: string
|
|
||||||
/** The channel this invite is for */
|
|
||||||
channel?: Channel
|
|
||||||
/** The guild this invite is for. */
|
|
||||||
guild?: Guild
|
|
||||||
/** The user who created this invite. */
|
|
||||||
inviter?: User
|
|
||||||
/** The amount of times this invite has been used. */
|
|
||||||
uses: number | null = null
|
|
||||||
/** The amount of times this invite can be used. */
|
|
||||||
maxUses: number | null = null
|
|
||||||
/** How long the invite is valid for (in seconds) */
|
|
||||||
maxAge: number | null = null
|
|
||||||
/** Whether or not the invite is temporary (invited users will be kicked on disconnect unless they're assigned a role) */
|
|
||||||
temporary: boolean = false
|
|
||||||
/** The time at which the invite was created */
|
|
||||||
createdAt?: number
|
|
||||||
|
|
||||||
presenceCount?: number | null
|
|
||||||
memberCount?: number | null
|
|
||||||
|
|
||||||
stageInstance?: {
|
|
||||||
members: Member[]
|
|
||||||
participantCount: number
|
|
||||||
speakerCount: number
|
|
||||||
topic: string
|
|
||||||
} | null
|
|
||||||
|
|
||||||
targetApplicationID?: string | null
|
|
||||||
targetType?: TargetTypes | null
|
|
||||||
targetUser?: User | null
|
|
||||||
|
|
||||||
constructor(data: DiscordInvite | DiscordInviteCreate, client: Client) {
|
|
||||||
// super();
|
|
||||||
this.client = client
|
|
||||||
this.code = data.code
|
|
||||||
// @ts-expect-error js hacks
|
|
||||||
this.channel = data.channel
|
|
||||||
|
|
||||||
if (data.inviter) {
|
|
||||||
this.inviter = new User(data.inviter, client)
|
|
||||||
client.users.set(this.inviter.id, this.inviter)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.isInviteCreate(data)) {
|
|
||||||
this.uses = data.uses !== undefined ? data.uses : null
|
|
||||||
this.maxUses = data.max_uses !== undefined ? data.max_uses : null
|
|
||||||
this.maxAge = data.max_age !== undefined ? data.max_age : null
|
|
||||||
this.temporary = data.temporary !== undefined ? data.temporary : false
|
|
||||||
this.createdAt = Date.parse(data.created_at)
|
|
||||||
} else {
|
|
||||||
if (data.guild) {
|
|
||||||
if (client.guilds.has(data.guild.id!)) {
|
|
||||||
if (data.channel) {
|
|
||||||
// @ts-expect-error should work i think dumb partials
|
|
||||||
const channel = new GuildChannel(data.channel, client)
|
|
||||||
client.guilds.get(data.guild.id!)?.channels.set(channel.id, channel)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// @ts-expect-error js hacks
|
|
||||||
this.guild = new Guild(data.guild, client)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
this.presenceCount = data.approximate_presence_count !== undefined ? data.approximate_presence_count : null
|
|
||||||
this.memberCount = data.approximate_member_count !== undefined ? data.approximate_member_count : null
|
|
||||||
if (data.stage_instance !== undefined) {
|
|
||||||
this.stageInstance = {
|
|
||||||
members: data.stage_instance.members.map((m) => {
|
|
||||||
// @ts-expect-error js hacks
|
|
||||||
const member = new Member(m as DiscordMemberWithUser, this.guild, client)
|
|
||||||
this.guild?.members.set(member.id, member)
|
|
||||||
return member
|
|
||||||
}),
|
|
||||||
participantCount: data.stage_instance.participant_count,
|
|
||||||
speakerCount: data.stage_instance.speaker_count,
|
|
||||||
topic: data.stage_instance.topic,
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
this.stageInstance = null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
this.targetApplicationID = data.target_application !== undefined ? data.target_application.id : null
|
|
||||||
this.targetType = data.target_type !== undefined ? data.target_type : null
|
|
||||||
this.targetUser = data.target_user !== undefined ? new User(data.target_user, client) : null
|
|
||||||
if (this.targetUser) client.users.set(this.targetUser.id, this.targetUser)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @deprecated Use .client
|
|
||||||
*/
|
|
||||||
get _client(): Client {
|
|
||||||
return this.client
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @deprecated Use .createdAt
|
|
||||||
*/
|
|
||||||
get _createdAt(): number | undefined {
|
|
||||||
return this.createdAt
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Delete the invite */
|
|
||||||
async delete(reason?: string): Promise<void> {
|
|
||||||
return await this.client.deleteInvite.call(this.client, this.code, reason)
|
|
||||||
}
|
|
||||||
|
|
||||||
toString(): string {
|
|
||||||
return `[Invite ${this.code}]`
|
|
||||||
}
|
|
||||||
|
|
||||||
toJSON(props = []): Record<string, any> {
|
|
||||||
return Base.prototype.toJSON([
|
|
||||||
'channel',
|
|
||||||
'code',
|
|
||||||
'createdAt',
|
|
||||||
'guild',
|
|
||||||
'maxAge',
|
|
||||||
'maxUses',
|
|
||||||
'memberCount',
|
|
||||||
'presenceCount',
|
|
||||||
'revoked',
|
|
||||||
'temporary',
|
|
||||||
'uses',
|
|
||||||
...props,
|
|
||||||
])
|
|
||||||
}
|
|
||||||
|
|
||||||
isInviteCreate(data: DiscordInvite | DiscordInviteCreate): data is DiscordInviteCreate {
|
|
||||||
return Reflect.has(data, 'created_at')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default Invite
|
|
||||||
@@ -1,444 +0,0 @@
|
|||||||
/* eslint-disable @typescript-eslint/restrict-template-expressions */
|
|
||||||
/* eslint-disable @typescript-eslint/explicit-function-return-type */
|
|
||||||
/* eslint-disable no-useless-call */
|
|
||||||
|
|
||||||
import {
|
|
||||||
MessageTypes,
|
|
||||||
type DiscordApplication,
|
|
||||||
type DiscordAttachment,
|
|
||||||
type DiscordEmbed,
|
|
||||||
type DiscordMemberWithUser,
|
|
||||||
type DiscordMessage,
|
|
||||||
type DiscordMessageActivity,
|
|
||||||
type DiscordMessageComponents,
|
|
||||||
type DiscordStickerItem,
|
|
||||||
type InteractionTypes,
|
|
||||||
} from '@discordeno/types'
|
|
||||||
import Base from '../Base.js'
|
|
||||||
import type Client from '../Client.js'
|
|
||||||
import { MessageFlags } from '../Constants.js'
|
|
||||||
import { MESSAGE_LINK } from '../Endpoints.js'
|
|
||||||
import type { GetMessageReactionOptions, MessageContentEdit, MessageWebhookContent } from '../typings.js'
|
|
||||||
import type NewsChannel from './channels/News.js'
|
|
||||||
import type PrivateChannel from './channels/Private.js'
|
|
||||||
import type TextChannel from './channels/Text.js'
|
|
||||||
import type TextVoiceChannel from './channels/TextVoice.js'
|
|
||||||
import type NewsThreadChannel from './channels/threads/NewsThread.js'
|
|
||||||
import type PrivateThreadChannel from './channels/threads/PrivateThread.js'
|
|
||||||
import type PublicThreadChannel from './channels/threads/PublicThread.js'
|
|
||||||
import type Guild from './guilds/Guild.js'
|
|
||||||
import Member from './guilds/Member.js'
|
|
||||||
import User from './users/User.js'
|
|
||||||
|
|
||||||
export class Message extends Base {
|
|
||||||
/** The client manager. */
|
|
||||||
client: Client
|
|
||||||
/** Timestamp of message creation */
|
|
||||||
timestamp: number
|
|
||||||
/** The type of the message */
|
|
||||||
type: MessageTypes
|
|
||||||
/** The channel the message is in. Can be partial with only the id if the channel is not cached. */
|
|
||||||
channel: PrivateChannel | TextChannel | NewsChannel | NewsThreadChannel | PublicThreadChannel | PrivateThreadChannel | TextVoiceChannel
|
|
||||||
/** The message content. */
|
|
||||||
content: string
|
|
||||||
/** An object containing the reactions on the message. Each key is a reaction emoji and each value is an object with properties `me` (Boolean) and `count` (Number) for that specific reaction emoji. */
|
|
||||||
reactions: Record<string, { me: boolean; count: number }>
|
|
||||||
/** The ID of the guild this message is in (undefined if in DMs) */
|
|
||||||
guildID?: string
|
|
||||||
/** ID of the webhook that sent the message */
|
|
||||||
webhookID?: string
|
|
||||||
/** An object containing the reference to the original message if it is a crossposted message or reply */
|
|
||||||
messageReference?: {
|
|
||||||
/** The id of the original message this message was crossposted from */
|
|
||||||
messageID?: string
|
|
||||||
/** The id of the channel this message was crossposted from */
|
|
||||||
channelID?: string
|
|
||||||
/** The id of the guild this message was crossposted from */
|
|
||||||
guildID?: string
|
|
||||||
} | null
|
|
||||||
|
|
||||||
/** The flags that are enabled on this message. */
|
|
||||||
flags: number
|
|
||||||
/** The message author */
|
|
||||||
author: User
|
|
||||||
/** The message author with server-specific data */
|
|
||||||
member?: Member
|
|
||||||
/** The message that was replied to. If undefined, message data was not received. If null, the message was deleted. */
|
|
||||||
referencedMessage?: Message | null
|
|
||||||
/** An object containing info about the interaction the message is responding to, if applicable */
|
|
||||||
interaction?: {
|
|
||||||
/** The id of the interaction */
|
|
||||||
id: string
|
|
||||||
/** The type of interaction */
|
|
||||||
type: InteractionTypes
|
|
||||||
/** The name of the command */
|
|
||||||
name: string
|
|
||||||
/** The user who invoked the interaction */
|
|
||||||
user: User
|
|
||||||
/** The member who invoked the interaction */
|
|
||||||
member?: Member
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Array of mentioned users */
|
|
||||||
mentions: User[] = []
|
|
||||||
/** Array of mentioned roles' ids */
|
|
||||||
roleMentions: string[] = []
|
|
||||||
/** Array of attachments */
|
|
||||||
attachments: DiscordAttachment[] = []
|
|
||||||
/** Array of embeds */
|
|
||||||
embeds: DiscordEmbed[] = []
|
|
||||||
/** The stickers sent with the message */
|
|
||||||
stickerItems: DiscordStickerItem[] = []
|
|
||||||
/** An array of component objects */
|
|
||||||
components: DiscordMessageComponents = []
|
|
||||||
/** The activity specified in the message */
|
|
||||||
activity?: DiscordMessageActivity
|
|
||||||
/** The application of the activity in the message */
|
|
||||||
application?: Partial<DiscordApplication>
|
|
||||||
/** The ID of the interaction's application */
|
|
||||||
applicationID?: string
|
|
||||||
/** Timestamp of latest message edit */
|
|
||||||
editedTimestamp?: number
|
|
||||||
/** Whether the message mentions everyone/here or not */
|
|
||||||
mentionEveryone: boolean = false
|
|
||||||
/** Whether the message is pinned or not */
|
|
||||||
pinned: boolean = false
|
|
||||||
/** Whether to play the message using TTS or not */
|
|
||||||
tts: boolean = false
|
|
||||||
|
|
||||||
constructor(data: DiscordMessage, client: Client) {
|
|
||||||
super(data.id)
|
|
||||||
|
|
||||||
this.client = client
|
|
||||||
this.timestamp = Date.parse(data.timestamp)
|
|
||||||
|
|
||||||
this.type = data.type || MessageTypes.Default
|
|
||||||
this.timestamp = Date.parse(data.timestamp)
|
|
||||||
// @ts-expect-error eris js hack
|
|
||||||
this.channel = this.client.getChannel(data.channel_id) ?? {
|
|
||||||
id: data.channel_id,
|
|
||||||
}
|
|
||||||
this.content = ''
|
|
||||||
this.reactions = {}
|
|
||||||
this.guildID = data.guild_id
|
|
||||||
this.webhookID = data.webhook_id
|
|
||||||
|
|
||||||
if (data.message_reference) {
|
|
||||||
this.messageReference = {
|
|
||||||
messageID: data.message_reference.message_id,
|
|
||||||
channelID: data.message_reference.channel_id,
|
|
||||||
guildID: data.message_reference.guild_id,
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
this.messageReference = null
|
|
||||||
}
|
|
||||||
|
|
||||||
this.flags = data.flags ?? 0
|
|
||||||
|
|
||||||
this.author = new User(data.author, client)
|
|
||||||
if (!data.webhook_id) {
|
|
||||||
this.client.users.set(this.author.id, this.author)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (data.referenced_message) {
|
|
||||||
const channel = this.client.getChannel(data.referenced_message.channel_id) as TextChannel
|
|
||||||
this.referencedMessage = new Message(data.referenced_message, this.client)
|
|
||||||
|
|
||||||
if (channel) {
|
|
||||||
channel.messages.set(this.referencedMessage.id, this.referencedMessage)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
this.referencedMessage = data.referenced_message
|
|
||||||
}
|
|
||||||
|
|
||||||
if (data.interaction) {
|
|
||||||
this.interaction = {
|
|
||||||
id: data.interaction.id,
|
|
||||||
type: data.interaction.type,
|
|
||||||
name: data.interaction.name,
|
|
||||||
user: new User(data.interaction.user, client),
|
|
||||||
}
|
|
||||||
|
|
||||||
if (data.interaction.member) {
|
|
||||||
data.interaction.member.user = data.interaction.user
|
|
||||||
|
|
||||||
if (this.guild) {
|
|
||||||
this.interaction.member = new Member(
|
|
||||||
// @ts-expect-error some eris magic at play here
|
|
||||||
data.interaction.member,
|
|
||||||
this.guild,
|
|
||||||
client,
|
|
||||||
)
|
|
||||||
this.guild.members.set(this.interaction.member.id, this.interaction.member)
|
|
||||||
} else {
|
|
||||||
// @ts-expect-error some eris magic at play here
|
|
||||||
interactionMember = data.interaction.member
|
|
||||||
}
|
|
||||||
} else if (this.guild?.members.has(data.interaction.user.id)) {
|
|
||||||
this.interaction.member = this.guild.members.get(data.interaction.user.id)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.guild) {
|
|
||||||
if (data.member) {
|
|
||||||
data.member.user = data.author
|
|
||||||
this.member = new Member(data.member as DiscordMemberWithUser, this.guild, client)
|
|
||||||
this.guild.members.set(this.member.id, this.member)
|
|
||||||
} else if (this.guild.members.has(this.author.id)) {
|
|
||||||
this.member = this.guild.members.get(this.author.id)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
this.update(data)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @deprecated Use `.client` instead.
|
|
||||||
*/
|
|
||||||
get _client(): Client {
|
|
||||||
return this.client
|
|
||||||
}
|
|
||||||
|
|
||||||
get guild(): Guild | undefined {
|
|
||||||
return this.guildID ? this.client.guilds.get(this.guildID) : undefined
|
|
||||||
}
|
|
||||||
|
|
||||||
update(data: DiscordMessage) {
|
|
||||||
if (data.pinned !== undefined) this.pinned = !!data.pinned
|
|
||||||
|
|
||||||
if (data.tts !== undefined) this.tts = data.tts
|
|
||||||
if (data.attachments !== undefined) this.attachments = data.attachments
|
|
||||||
if (data.embeds !== undefined) this.embeds = data.embeds
|
|
||||||
if (data.flags !== undefined) this.flags = data.flags
|
|
||||||
if (data.activity !== undefined) this.activity = data.activity
|
|
||||||
if (data.components !== undefined) this.components = data.components
|
|
||||||
if (data.application !== undefined) this.application = data.application
|
|
||||||
|
|
||||||
if (data.edited_timestamp) this.editedTimestamp = Date.parse(data.edited_timestamp)
|
|
||||||
if (data.application_id !== undefined) this.applicationID = data.application_id
|
|
||||||
if (data.sticker_items !== undefined) this.stickerItems = data.sticker_items
|
|
||||||
|
|
||||||
if (data.content !== undefined) {
|
|
||||||
this.content = data.content || ''
|
|
||||||
this.mentionEveryone = !!data.mention_everyone
|
|
||||||
this.mentions = []
|
|
||||||
|
|
||||||
for (const mention of data.mentions ?? []) {
|
|
||||||
const user = new User(mention, this.client)
|
|
||||||
this.client.users.set(user.id, user)
|
|
||||||
|
|
||||||
if (mention.member && this.guild) {
|
|
||||||
mention.member.user = mention
|
|
||||||
this.guild.members.set(mention.id, new Member(mention.member as DiscordMemberWithUser, this.guild, this.client))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (data.mention_roles) this.roleMentions = data.mention_roles
|
|
||||||
}
|
|
||||||
|
|
||||||
if (data.reactions) {
|
|
||||||
for (const reaction of data.reactions ?? []) {
|
|
||||||
this.reactions[reaction.emoji.id ? `${reaction.emoji.name}:${reaction.emoji.id}` : reaction.emoji.name!] = {
|
|
||||||
count: reaction.count,
|
|
||||||
me: reaction.me,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
get channelMentions(): string[] {
|
|
||||||
return (this.content.match(/<#[0-9]+>/g) ?? []).map((mention) => mention.substring(2, mention.length - 1))
|
|
||||||
}
|
|
||||||
|
|
||||||
get cleanContent() {
|
|
||||||
let cleanContent = this.content?.replace(/<a?(:\w+:)[0-9]+>/g, '$1') || ''
|
|
||||||
|
|
||||||
let authorName = this.author.username
|
|
||||||
if (this.guild) {
|
|
||||||
const member = this.guild.members.get(this.author.id)
|
|
||||||
if (member?.nick) {
|
|
||||||
authorName = member.nick
|
|
||||||
}
|
|
||||||
}
|
|
||||||
cleanContent = cleanContent.replace(new RegExp(`<@!?${this.author.id}>`, 'g'), '@\u200b' + authorName)
|
|
||||||
|
|
||||||
if (this.mentions) {
|
|
||||||
this.mentions.forEach((mention) => {
|
|
||||||
if (this.guild) {
|
|
||||||
const member = this.guild.members.get(mention.id)
|
|
||||||
if (member?.nick) {
|
|
||||||
cleanContent = cleanContent.replace(new RegExp(`<@!?${mention.id}>`, 'g'), '@\u200b' + member.nick)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
cleanContent = cleanContent.replace(new RegExp(`<@!?${mention.id}>`, 'g'), '@\u200b' + mention.username)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.guild && this.roleMentions) {
|
|
||||||
for (const roleID of this.roleMentions) {
|
|
||||||
const role = this.guild.roles.get(roleID)
|
|
||||||
const roleName = role ? role.name : 'deleted-role'
|
|
||||||
cleanContent = cleanContent.replace(new RegExp(`<@&${roleID}>`, 'g'), '@\u200b' + roleName)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
this.channelMentions.forEach((id) => {
|
|
||||||
const channel = this.client.getChannel(id) as TextChannel
|
|
||||||
if (channel?.name && channel.mention) {
|
|
||||||
cleanContent = cleanContent.replace(channel.mention, '#' + channel.name)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
return cleanContent.replace(/@everyone/g, '@\u200beveryone').replace(/@here/g, '@\u200bhere')
|
|
||||||
}
|
|
||||||
|
|
||||||
get jumpLink() {
|
|
||||||
return `${this.client.CLIENT_URL}${MESSAGE_LINK(this.guildID ?? '@me', this.channel.id, this.id)}`
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Add a reaction to a message */
|
|
||||||
async addReaction(reaction: string): Promise<void> {
|
|
||||||
if (this.flags & MessageFlags.EPHEMERAL) {
|
|
||||||
throw new Error('Ephemeral messages cannot have reactions')
|
|
||||||
}
|
|
||||||
return await this.client.addMessageReaction.call(this.client, this.channel.id, this.id, reaction)
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Create a thread with this message */
|
|
||||||
async createThreadWithMessage(options: {
|
|
||||||
name: string
|
|
||||||
autoArchiveDuration: 60 | 1440 | 4320 | 10080
|
|
||||||
}): Promise<NewsThreadChannel | PublicThreadChannel> {
|
|
||||||
return await this.client.createThreadWithMessage.call(this.client, this.channel.id, this.id, options)
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Crosspost (publish) a message to subscribed channels (NewsChannel only) */
|
|
||||||
async crosspost(): Promise<Message> {
|
|
||||||
if (this.flags & MessageFlags.EPHEMERAL) {
|
|
||||||
throw new Error('Ephemeral messages cannot be crossposted')
|
|
||||||
}
|
|
||||||
|
|
||||||
return await this.client.crosspostMessage.call(this.client, this.channel.id, this.id)
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Delete the message */
|
|
||||||
async delete(reason?: string): Promise<void> {
|
|
||||||
if (this.flags & MessageFlags.EPHEMERAL) {
|
|
||||||
throw new Error('Ephemeral messages cannot be deleted')
|
|
||||||
}
|
|
||||||
|
|
||||||
return await this.client.deleteMessage.call(this.client, this.channel.id, this.id, reason)
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Delete the message as a webhook */
|
|
||||||
async deleteWebhook(token: string): Promise<void> {
|
|
||||||
if (!this.webhookID) throw new Error('Message is not a webhook')
|
|
||||||
if (this.flags & MessageFlags.EPHEMERAL) throw new Error('Ephemeral messages cannot be deleted')
|
|
||||||
|
|
||||||
return await this.client.deleteWebhookMessage.call(this.client, this.webhookID, token, this.id)
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Edit the message */
|
|
||||||
async edit(content: MessageContentEdit): Promise<Message> {
|
|
||||||
if (this.flags & MessageFlags.EPHEMERAL) {
|
|
||||||
throw new Error('Ephemeral messages cannot be edited via this method')
|
|
||||||
}
|
|
||||||
|
|
||||||
return await this.client.editMessage.call(this.client, this.channel.id, this.id, content)
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Edit the message as a webhook */
|
|
||||||
async editWebhook(token: string, options: MessageWebhookContent): Promise<Message> {
|
|
||||||
if (!this.webhookID) {
|
|
||||||
throw new Error('Message is not a webhook')
|
|
||||||
}
|
|
||||||
|
|
||||||
return await this.client.editWebhookMessage.call(this.client, this.webhookID, token, this.id, options)
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Get a list of users who reacted with a specific reaction */
|
|
||||||
async getReaction(reaction: string, options?: GetMessageReactionOptions): Promise<User[]> {
|
|
||||||
if (this.flags & MessageFlags.EPHEMERAL) {
|
|
||||||
throw new Error('Ephemeral messages cannot have reactions')
|
|
||||||
}
|
|
||||||
|
|
||||||
return await this.client.getMessageReaction.call(this.client, this.channel.id, this.id, reaction, options)
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Pin the message */
|
|
||||||
async pin(): Promise<void> {
|
|
||||||
if (this.flags & MessageFlags.EPHEMERAL) {
|
|
||||||
throw new Error('Ephemeral messages cannot be pinned')
|
|
||||||
}
|
|
||||||
|
|
||||||
return await this.client.pinMessage.call(this.client, this.channel.id, this.id)
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Remove a reaction from a message */
|
|
||||||
async removeReaction(reaction: string): Promise<void> {
|
|
||||||
if (this.flags & MessageFlags.EPHEMERAL) {
|
|
||||||
throw new Error('Ephemeral messages cannot have reactions')
|
|
||||||
}
|
|
||||||
|
|
||||||
return await this.client.removeMessageReaction.call(this.client, this.channel.id, this.id, reaction)
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Remove all reactions from a message for a single emoji */
|
|
||||||
async removeReactionEmoji(reaction: string): Promise<void> {
|
|
||||||
if (this.flags & MessageFlags.EPHEMERAL) {
|
|
||||||
throw new Error('Ephemeral messages cannot have reactions')
|
|
||||||
}
|
|
||||||
|
|
||||||
return await this.client.removeMessageReactionEmoji.call(this.client, this.channel.id, this.id, reaction)
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Remove all reactions from a message */
|
|
||||||
async removeReactions(): Promise<void> {
|
|
||||||
if (this.flags & MessageFlags.EPHEMERAL) {
|
|
||||||
throw new Error('Ephemeral messages cannot have reactions')
|
|
||||||
}
|
|
||||||
|
|
||||||
return await this.client.removeMessageReactions.call(this.client, this.channel.id, this.id)
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Unpin the message */
|
|
||||||
async unpin(): Promise<void> {
|
|
||||||
if (this.flags & MessageFlags.EPHEMERAL) {
|
|
||||||
throw new Error('Ephemeral messages cannot be pinned')
|
|
||||||
}
|
|
||||||
|
|
||||||
return await this.client.unpinMessage.call(this.client, this.channel.id, this.id)
|
|
||||||
}
|
|
||||||
|
|
||||||
toJSON(props: string[] = []): Record<string, any> {
|
|
||||||
return super.toJSON([
|
|
||||||
'activity',
|
|
||||||
'application',
|
|
||||||
'attachments',
|
|
||||||
'author',
|
|
||||||
'content',
|
|
||||||
'editedTimestamp',
|
|
||||||
'embeds',
|
|
||||||
'flags',
|
|
||||||
'guildID',
|
|
||||||
'hit',
|
|
||||||
'member',
|
|
||||||
'mentionEveryone',
|
|
||||||
'mentions',
|
|
||||||
'messageReference',
|
|
||||||
'pinned',
|
|
||||||
'reactions',
|
|
||||||
'referencedMesssage',
|
|
||||||
'roleMentions',
|
|
||||||
'stickers',
|
|
||||||
'stickerItems',
|
|
||||||
'timestamp',
|
|
||||||
'tts',
|
|
||||||
'type',
|
|
||||||
'webhookID',
|
|
||||||
...props,
|
|
||||||
])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default Message
|
|
||||||
@@ -1,59 +0,0 @@
|
|||||||
/* eslint-disable @typescript-eslint/explicit-function-return-type */
|
|
||||||
import { BitwisePermissionFlags } from '@discordeno/types'
|
|
||||||
import { Base } from '../Base.js'
|
|
||||||
import type { BigString } from '../Client.js'
|
|
||||||
import type { PermissionClientStrings } from '../Constants.js'
|
|
||||||
import { Permissions } from '../Constants.js'
|
|
||||||
|
|
||||||
export class Permission {
|
|
||||||
allow: bigint
|
|
||||||
deny: bigint
|
|
||||||
_json?: Record<string, boolean>
|
|
||||||
|
|
||||||
constructor(allow: BigString | number = 0, deny: BigString | number = 0) {
|
|
||||||
this.allow = BigInt(allow)
|
|
||||||
this.deny = BigInt(deny)
|
|
||||||
}
|
|
||||||
|
|
||||||
get isAdmin(): boolean {
|
|
||||||
return !!(this.allow & BigInt(BitwisePermissionFlags.ADMINISTRATOR))
|
|
||||||
}
|
|
||||||
|
|
||||||
get json() {
|
|
||||||
if (!this._json) {
|
|
||||||
this._json = {}
|
|
||||||
for (const key of Object.keys(BitwisePermissionFlags)) {
|
|
||||||
if (typeof key === 'number') continue
|
|
||||||
|
|
||||||
const perm = key as keyof typeof BitwisePermissionFlags
|
|
||||||
|
|
||||||
if (this.allow & BigInt(BitwisePermissionFlags[perm])) {
|
|
||||||
this._json[perm] = true
|
|
||||||
} else if (this.deny & BigInt(BitwisePermissionFlags[perm])) {
|
|
||||||
this._json[perm] = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return this._json
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Check if this permission allows a specific permission */
|
|
||||||
has(permission: bigint | PermissionClientStrings): boolean {
|
|
||||||
if (this.isAdmin) return true
|
|
||||||
|
|
||||||
if (typeof permission === 'bigint') {
|
|
||||||
return (this.allow & permission) === permission
|
|
||||||
}
|
|
||||||
return !!(this.allow & Permissions[permission])
|
|
||||||
}
|
|
||||||
|
|
||||||
toString() {
|
|
||||||
return `[${this.constructor.name} +${this.allow} -${this.deny}]`
|
|
||||||
}
|
|
||||||
|
|
||||||
toJSON(props: string[] = []): Record<string, any> {
|
|
||||||
return Base.prototype.toJSON.call(['allow', 'deny', ...props])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default Permission
|
|
||||||
@@ -1,21 +0,0 @@
|
|||||||
import type { DiscordOverwrite, OverwriteTypes } from '@discordeno/types'
|
|
||||||
import { Base } from '../Base.js'
|
|
||||||
import Permission from './Permission.js'
|
|
||||||
|
|
||||||
export class PermissionOverwrite extends Permission {
|
|
||||||
id: string
|
|
||||||
type: OverwriteTypes
|
|
||||||
|
|
||||||
constructor(data: DiscordOverwrite) {
|
|
||||||
super(data.allow, data.deny)
|
|
||||||
|
|
||||||
this.id = data.id
|
|
||||||
this.type = data.type
|
|
||||||
}
|
|
||||||
|
|
||||||
toJSON(props: string[] = []): Record<string, any> {
|
|
||||||
return Base.prototype.toJSON.call(['id', 'type', ...props])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default PermissionOverwrite
|
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
import type { BigString } from '@discordeno/types'
|
|
||||||
import type Collection from '../../Collection.js'
|
|
||||||
import type { AnyGuildChannel } from '../../typings.js'
|
|
||||||
import GuildChannel from './Guild.js'
|
|
||||||
|
|
||||||
export class CategoryChannel extends GuildChannel {
|
|
||||||
get channels(): Collection<BigString, Exclude<AnyGuildChannel, CategoryChannel>> {
|
|
||||||
return this.guild?.channels.filter((c) => c.parentID === this.id) as unknown as Collection<BigString, Exclude<AnyGuildChannel, CategoryChannel>>
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default CategoryChannel
|
|
||||||
@@ -1,32 +0,0 @@
|
|||||||
import type { ChannelTypes, DiscordChannel } from '@discordeno/types'
|
|
||||||
import Base from '../../Base.js'
|
|
||||||
import type Client from '../../Client.js'
|
|
||||||
|
|
||||||
export class Channel extends Base {
|
|
||||||
type: ChannelTypes
|
|
||||||
client: Client
|
|
||||||
|
|
||||||
constructor(data: DiscordChannel | Pick<DiscordChannel, 'id' | 'permissions' | 'name' | 'type'>, client: Client) {
|
|
||||||
super(data.id)
|
|
||||||
this.type = data.type
|
|
||||||
this.client = client
|
|
||||||
}
|
|
||||||
|
|
||||||
get mention(): string {
|
|
||||||
return `<#${this.id}>`
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @deprecated Removed this circular dependency hack for better alternative.
|
|
||||||
*/
|
|
||||||
static from(_data: DiscordChannel, client: Client): void {
|
|
||||||
console.error('Usage of channel.from is deprecated, please use generateChannelFrom(data, client)')
|
|
||||||
client.emit('warn', new Error(`Usage of "Channel.from" is deprecated. Use "generateChanneFrom()"`))
|
|
||||||
}
|
|
||||||
|
|
||||||
toJSON(props: string[] = []): Record<string, any> {
|
|
||||||
return super.toJSON(['type', ...props])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default Channel
|
|
||||||
@@ -1,117 +0,0 @@
|
|||||||
/* eslint-disable @typescript-eslint/explicit-function-return-type */
|
|
||||||
/* eslint-disable no-useless-call */
|
|
||||||
import type { BigString, DiscordChannel, OverwriteTypes } from '@discordeno/types'
|
|
||||||
import { BitwisePermissionFlags, ChannelTypes } from '@discordeno/types'
|
|
||||||
import { Collection } from '@discordeno/utils'
|
|
||||||
import type Client from '../../Client.js'
|
|
||||||
import type { EditChannelOptions, EditChannelPositionOptions } from '../../typings.js'
|
|
||||||
import type Guild from '../guilds/Guild.js'
|
|
||||||
import type Member from '../guilds/Member.js'
|
|
||||||
import Permission from '../Permission.js'
|
|
||||||
import PermissionOverwrite from '../PermissionOverwrite.js'
|
|
||||||
import Channel from './Channel.js'
|
|
||||||
|
|
||||||
export class GuildChannel extends Channel {
|
|
||||||
position: number
|
|
||||||
name: string
|
|
||||||
parentID?: string | null
|
|
||||||
guild: Guild
|
|
||||||
nsfw: boolean
|
|
||||||
permissionOverwrites = new Collection<BigString, PermissionOverwrite>()
|
|
||||||
/** The RTC region ID of the channel (automatic if `null`) (guild voice channels only) */
|
|
||||||
rtcRegion: string | null = null
|
|
||||||
|
|
||||||
constructor(data: DiscordChannel, client: Client) {
|
|
||||||
super(data, client)
|
|
||||||
|
|
||||||
this.position = data.position ?? 0
|
|
||||||
this.guild = client.guilds.get(data.guild_id!)!
|
|
||||||
this.name = data.name ?? ''
|
|
||||||
this.parentID = data.parent_id
|
|
||||||
this.nsfw = !!data.nsfw
|
|
||||||
}
|
|
||||||
|
|
||||||
update(data: DiscordChannel): void {
|
|
||||||
if (data.type !== undefined) {
|
|
||||||
this.type = data.type
|
|
||||||
}
|
|
||||||
if (data.name !== undefined) {
|
|
||||||
this.name = data.name
|
|
||||||
}
|
|
||||||
if (data.position !== undefined) {
|
|
||||||
this.position = data.position
|
|
||||||
}
|
|
||||||
if (data.parent_id !== undefined) {
|
|
||||||
this.parentID = data.parent_id
|
|
||||||
}
|
|
||||||
this.nsfw = !!data.nsfw
|
|
||||||
if (data.permission_overwrites) {
|
|
||||||
data.permission_overwrites.forEach((overwrite) => {
|
|
||||||
const perms = new PermissionOverwrite(overwrite)
|
|
||||||
this.permissionOverwrites.set(perms.id, perms)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Delete the channel */
|
|
||||||
async delete(reason?: string): Promise<void> {
|
|
||||||
return await this.client.deleteChannel.call(this.client, this.id, reason)
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Delete a channel permission overwrite */
|
|
||||||
async deletePermission(overwriteID: BigString, reason?: string): Promise<void> {
|
|
||||||
return await this.client.deleteChannelPermission.call(this.client, this.id, overwriteID, reason)
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Edit the channel's properties */
|
|
||||||
async edit(options: EditChannelOptions, reason?: string) {
|
|
||||||
return await this.client.editChannel.call(this.client, this.id, options, reason)
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Create a channel permission overwrite */
|
|
||||||
async editPermission(overwriteID: BigString, allow: bigint | number, deny: bigint | number, type: OverwriteTypes, reason?: string): Promise<void> {
|
|
||||||
return await this.client.editChannelPermission.call(this.client, this.id, overwriteID, allow, deny, type, reason)
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Edit the channel's position. Note that channel position numbers are lowest on top and highest at the bottom. */
|
|
||||||
async editPosition(position: number, options?: EditChannelPositionOptions): Promise<void> {
|
|
||||||
return await this.client.editChannelPosition.call(this.client, this.id, position, options)
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Get the channel-specific permissions of a member */
|
|
||||||
permissionsOf(memberID: BigString | Member): Permission {
|
|
||||||
const member = ['string', 'bigint'].includes(typeof memberID) ? this.guild.members.get(memberID as BigString)! : (memberID as Member)
|
|
||||||
let permission = this.guild.permissionsOf(member).allow
|
|
||||||
if (permission & BigInt(BitwisePermissionFlags.ADMINISTRATOR)) {
|
|
||||||
return new Permission(BitwisePermissionFlags.ADMINISTRATOR)
|
|
||||||
}
|
|
||||||
const channel =
|
|
||||||
[ChannelTypes.PublicThread, ChannelTypes.PrivateThread, ChannelTypes.AnnouncementThread].includes(this.type) && this.parentID
|
|
||||||
? this.guild.channels.get(this.parentID)
|
|
||||||
: this
|
|
||||||
let overwrite = channel?.permissionOverwrites.get(this.guild.id)
|
|
||||||
if (overwrite) {
|
|
||||||
permission = (permission & ~overwrite.deny) | overwrite.allow
|
|
||||||
}
|
|
||||||
let deny = 0n
|
|
||||||
let allow = 0n
|
|
||||||
for (const roleID of member.roles) {
|
|
||||||
if ((overwrite = channel?.permissionOverwrites.get(roleID))) {
|
|
||||||
deny |= overwrite.deny
|
|
||||||
allow |= overwrite.allow
|
|
||||||
}
|
|
||||||
}
|
|
||||||
permission = (permission & ~deny) | allow
|
|
||||||
overwrite = channel?.permissionOverwrites.get(member.id)
|
|
||||||
if (overwrite) {
|
|
||||||
permission = (permission & ~overwrite.deny) | overwrite.allow
|
|
||||||
}
|
|
||||||
return new Permission(permission)
|
|
||||||
}
|
|
||||||
|
|
||||||
toJSON(props: string[] = []): Record<string, any> {
|
|
||||||
return super.toJSON(['name', 'nsfw', 'parentID', 'permissionOverwrites', 'position', ...props])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default GuildChannel
|
|
||||||
@@ -1,28 +0,0 @@
|
|||||||
/* eslint-disable no-useless-call */
|
|
||||||
/* eslint-disable @typescript-eslint/return-await */
|
|
||||||
import type { BigString, DiscordChannel } from '@discordeno/types'
|
|
||||||
import type Client from '../../Client.js'
|
|
||||||
import type { ChannelFollow } from '../../typings.js'
|
|
||||||
import type Message from '../Message.js'
|
|
||||||
import TextChannel from './Text.js'
|
|
||||||
|
|
||||||
export class NewsChannel extends TextChannel {
|
|
||||||
constructor(data: DiscordChannel, client: Client, messageLimit?: number) {
|
|
||||||
super(data, client, messageLimit)
|
|
||||||
|
|
||||||
this.rateLimitPerUser = 0
|
|
||||||
this.update(data)
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Crosspost (publish) a message to subscribed channels */
|
|
||||||
async crosspostMessage(messageID: BigString): Promise<Message> {
|
|
||||||
return await this.client.crosspostMessage.call(this.client, this.id, messageID)
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Follow this channel in another channel. This creates a webhook in the target channel */
|
|
||||||
async follow(webhookChannelID: BigString): Promise<ChannelFollow> {
|
|
||||||
return await this.client.followChannel.call(this.client, this.id, webhookChannelID)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default NewsChannel
|
|
||||||
@@ -1,104 +0,0 @@
|
|||||||
/* eslint-disable no-useless-call */
|
|
||||||
import { ChannelTypes, type BigString, type DiscordChannel, type GetMessagesOptions } from '@discordeno/types'
|
|
||||||
import type Client from '../../Client.js'
|
|
||||||
import Collection from '../../Collection.js'
|
|
||||||
import type { FileContent, GetMessageReactionOptions, MessageContent, MessageContentEdit } from '../../typings.js'
|
|
||||||
import type Message from '../Message.js'
|
|
||||||
import User from '../users/User.js'
|
|
||||||
import Channel from './Channel.js'
|
|
||||||
|
|
||||||
export class PrivateChannel extends Channel {
|
|
||||||
/** The ID of the last message in this channel */
|
|
||||||
lastMessageID = ""
|
|
||||||
// TODO: THIS A THING IN DMS????
|
|
||||||
/** The rate limit per user. */
|
|
||||||
rateLimitPerUser?: number
|
|
||||||
/** Collection of Messages in this channel */
|
|
||||||
messages: Collection<string, Message>
|
|
||||||
/** The recipient in this private channel */
|
|
||||||
recipient?: User
|
|
||||||
|
|
||||||
constructor(data: DiscordChannel, client: Client) {
|
|
||||||
super(data, client)
|
|
||||||
|
|
||||||
this.lastMessageID = data.last_message_id ?? ""
|
|
||||||
this.rateLimitPerUser = data.rate_limit_per_user
|
|
||||||
if (this.type === ChannelTypes.DM || this.type === undefined) {
|
|
||||||
if (data.recipients?.[0]) this.recipient = new User(data.recipients[0], client)
|
|
||||||
}
|
|
||||||
this.messages = new Collection()
|
|
||||||
this.messages.limit = client.options.messageLimit
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Add a reaction to a message */
|
|
||||||
async addMessageReaction(messageID: BigString, reaction: string): Promise<void> {
|
|
||||||
return await this.client.addMessageReaction.call(this.client, this.id, messageID, reaction)
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Create a message in a text channel */
|
|
||||||
async createMessage(content: MessageContent, file?: FileContent | FileContent[]): Promise<Message> {
|
|
||||||
return await this.client.createMessage.call(this.client, this.id, content, file)
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: REASONS ARE A THING FOR AUDIT LOGS IN DMS???
|
|
||||||
/** Delete a message */
|
|
||||||
async deleteMessage(messageID: BigString, reason?: string): Promise<void> {
|
|
||||||
return await this.client.deleteMessage.call(this.client, this.id, messageID, reason)
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Edit a message */
|
|
||||||
async editMessage(messageID: BigString, content: MessageContentEdit): Promise<Message> {
|
|
||||||
return await this.client.editMessage.call(this.client, this.id, messageID, content)
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Get a previous message in a text channel */
|
|
||||||
async getMessage(messageID: BigString): Promise<Message> {
|
|
||||||
return await this.client.getMessage.call(this.client, this.id, messageID)
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Get a list of users who reacted with a specific reaction */
|
|
||||||
async getMessageReaction(messageID: BigString, reaction: string, options: GetMessageReactionOptions): Promise<User[]> {
|
|
||||||
return await this.client.getMessageReaction.call(this.client, this.id, messageID, reaction, options)
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Get a previous message in a text channel */
|
|
||||||
async getMessages(options: GetMessagesOptions): Promise<Message[]> {
|
|
||||||
return await this.client.getMessages.call(this.client, this.id, options)
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Get all the pins in a text channel */
|
|
||||||
async getPins(): Promise<Message[]> {
|
|
||||||
return await this.client.getPins.call(this.client, this.id)
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Leave the channel */
|
|
||||||
async leave(): Promise<void> {
|
|
||||||
return await this.client.deleteChannel.call(this.client, this.id)
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Pin a message */
|
|
||||||
async pinMessage(messageID: BigString): Promise<void> {
|
|
||||||
return await this.client.pinMessage.call(this.client, this.id, messageID)
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Remove a reaction from a message */
|
|
||||||
async removeMessageReaction(messageID: BigString, reaction: string): Promise<void> {
|
|
||||||
return await this.client.removeMessageReaction.call(this.client, this.id, messageID, reaction)
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Send typing status in a text channel */
|
|
||||||
async sendTyping(): Promise<void> {
|
|
||||||
return await this.client.sendChannelTyping.call(this.client, this.id)
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Unpin a message */
|
|
||||||
async unpinMessage(messageID: BigString): Promise<void> {
|
|
||||||
return await this.client.unpinMessage.call(this.client, this.id, messageID)
|
|
||||||
}
|
|
||||||
|
|
||||||
toJSON(props: string[] = []): Record<string, any> {
|
|
||||||
return super.toJSON(['call', 'lastCall', 'lastMessageID', 'messages', 'recipient', ...props])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default PrivateChannel
|
|
||||||
@@ -1,45 +0,0 @@
|
|||||||
/* eslint-disable no-useless-call */
|
|
||||||
/* eslint-disable @typescript-eslint/return-await */
|
|
||||||
import type { DiscordChannel } from '@discordeno/types'
|
|
||||||
import type { StageInstanceOptions } from '../../typings.js'
|
|
||||||
import type StageInstance from '../guilds/StageInstance.js'
|
|
||||||
import VoiceChannel from './Voice.js'
|
|
||||||
|
|
||||||
export class StageChannel extends VoiceChannel {
|
|
||||||
/** The topic of the channel */
|
|
||||||
topic?: string | null
|
|
||||||
|
|
||||||
update(data: DiscordChannel): void {
|
|
||||||
super.update(data)
|
|
||||||
|
|
||||||
if (data.topic !== undefined) {
|
|
||||||
this.topic = data.topic
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Create a stage instance */
|
|
||||||
async createInstance(options: StageInstanceOptions): Promise<StageInstance> {
|
|
||||||
return await this.client.createStageInstance.call(this.client, this.id, options)
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Delete the stage instance for this channel */
|
|
||||||
async deleteInstance(): Promise<void> {
|
|
||||||
return await this.client.deleteStageInstance.call(this.client, this.id)
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Update the stage instance for this channel */
|
|
||||||
async editInstance(options: StageInstanceOptions): Promise<StageInstance> {
|
|
||||||
return await this.client.editStageInstance.call(this.client, this.id, options)
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Get the stage instance for this channel */
|
|
||||||
async getInstance(): Promise<StageInstance> {
|
|
||||||
return await this.client.getStageInstance.call(this.client, this.id)
|
|
||||||
}
|
|
||||||
|
|
||||||
toJSON(props: string[] = []): Record<string, any> {
|
|
||||||
return super.toJSON(['topic', ...props])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default StageChannel
|
|
||||||
@@ -1,376 +0,0 @@
|
|||||||
/* eslint-disable @typescript-eslint/explicit-function-return-type */
|
|
||||||
/* eslint-disable no-useless-call */
|
|
||||||
/* eslint-disable @typescript-eslint/return-await */
|
|
||||||
import type { BigString, DiscordChannel, GetMessagesOptions } from '@discordeno/types'
|
|
||||||
import type Client from '../../Client.js'
|
|
||||||
import Collection from '../../Collection.js'
|
|
||||||
import type {
|
|
||||||
CreateChannelInviteOptions,
|
|
||||||
CreateThreadOptions,
|
|
||||||
CreateThreadWithoutMessageOptions,
|
|
||||||
FileContent,
|
|
||||||
GetArchivedThreadsOptions,
|
|
||||||
GetMessageReactionOptions,
|
|
||||||
ListedChannelThreads,
|
|
||||||
MessageContent,
|
|
||||||
MessageContentEdit,
|
|
||||||
PurgeChannelOptions,
|
|
||||||
} from '../../typings.js'
|
|
||||||
import type Invite from '../Invite.js'
|
|
||||||
import type Message from '../Message.js'
|
|
||||||
import GuildChannel from './Guild.js'
|
|
||||||
import type PrivateThreadChannel from './threads/PrivateThread.js'
|
|
||||||
import type PublicThreadChannel from './threads/PublicThread.js'
|
|
||||||
|
|
||||||
export class TextChannel extends GuildChannel {
|
|
||||||
/** Collection of Messages in this channel */
|
|
||||||
messages: Collection<string, Message>
|
|
||||||
/** The ratelimit of the channel, in seconds. 0 means no ratelimit is enabled */
|
|
||||||
rateLimitPerUser: number | null
|
|
||||||
/** The ID of the last message in this channel */
|
|
||||||
lastMessageID = ""
|
|
||||||
/** The timestamp of the last pinned message */
|
|
||||||
lastPinTimestamp?: number | null
|
|
||||||
/** Default duration for newly created threads, in minutes, to automatically archive the thread after recent activity, can be set to: 60, 1440, 4320, 10080 */
|
|
||||||
defaultAutoArchiveDuration?: number
|
|
||||||
/** The channel topic (0-4096 characters for GUILD_FORUM channels, 0-1024 characters for all others) */
|
|
||||||
topic?: string | null
|
|
||||||
|
|
||||||
constructor(data: DiscordChannel, client: Client, messageLimit?: number) {
|
|
||||||
super(data, client)
|
|
||||||
|
|
||||||
this.messages = new Collection()
|
|
||||||
if (messageLimit == null) this.messages.limit = client.options.messageLimit
|
|
||||||
else this.messages.limit = messageLimit
|
|
||||||
|
|
||||||
this.rateLimitPerUser = data.rate_limit_per_user == null ? null : data.rate_limit_per_user
|
|
||||||
|
|
||||||
this.lastMessageID = data.last_message_id ?? ""
|
|
||||||
this.lastPinTimestamp = data.last_pin_timestamp ? Date.parse(data.last_pin_timestamp) : null
|
|
||||||
|
|
||||||
this.update(data)
|
|
||||||
}
|
|
||||||
|
|
||||||
update(data: DiscordChannel): void {
|
|
||||||
super.update(data)
|
|
||||||
|
|
||||||
if (data.rate_limit_per_user !== undefined) this.rateLimitPerUser = data.rate_limit_per_user
|
|
||||||
if (data.topic !== undefined) this.topic = data.topic
|
|
||||||
if (data.default_auto_archive_duration !== undefined) this.defaultAutoArchiveDuration = data.default_auto_archive_duration
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Add a reaction to a message */
|
|
||||||
async addMessageReaction(messageID: BigString, reaction: string): Promise<void> {
|
|
||||||
return this.client.addMessageReaction.call(this.client, this.id, messageID, reaction)
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Create an invite for the channel */
|
|
||||||
async createInvite(options?: CreateChannelInviteOptions, reason?: string): Promise<Invite> {
|
|
||||||
return await this.client.createChannelInvite.call(this.client, this.id, options, reason)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a message in the channel
|
|
||||||
* @arg {String | Object} content A string or object. If an object is passed:
|
|
||||||
* @arg {Object} [content.allowedMentions] A list of mentions to allow (overrides default)
|
|
||||||
* @arg {Boolean} [content.allowedMentions.everyone] Whether or not to allow @everyone/@here.
|
|
||||||
* @arg {Boolean | Array<String>} [content.allowedMentions.roles] Whether or not to allow all role mentions, or an array of specific role mentions to allow.
|
|
||||||
* @arg {Boolean | Array<String>} [content.allowedMentions.users] Whether or not to allow all user mentions, or an array of specific user mentions to allow.
|
|
||||||
* @arg {Boolean} [content.allowedMentions.repliedUser] Whether or not to mention the author of the message being replied to.
|
|
||||||
* @arg {Array<Object>} [content.components] An array of component objects
|
|
||||||
* @arg {String} [content.components[].custom_id] The ID of the component (type 2 style 0-4 and type 3 only)
|
|
||||||
* @arg {Boolean} [content.components[].disabled] Whether the component is disabled (type 2 and 3 only)
|
|
||||||
* @arg {Object} [content.components[].emoji] The emoji to be displayed in the component (type 2)
|
|
||||||
* @arg {String} [content.components[].label] The label to be displayed in the component (type 2)
|
|
||||||
* @arg {Number} [content.components[].max_values] The maximum number of items that can be chosen (1-25, default 1)
|
|
||||||
* @arg {Number} [content.components[].min_values] The minimum number of items that must be chosen (0-25, default 1)
|
|
||||||
* @arg {Array<Object>} [content.components[].options] The options for this component (type 3 only)
|
|
||||||
* @arg {Boolean} [content.components[].options[].default] Whether this option should be the default value selected
|
|
||||||
* @arg {String} [content.components[].options[].description] The description for this option
|
|
||||||
* @arg {Object} [content.components[].options[].emoji] The emoji to be displayed in this option
|
|
||||||
* @arg {String} content.components[].options[].label The label for this option
|
|
||||||
* @arg {Number | String} content.components[].options[].value The value for this option
|
|
||||||
* @arg {String} [content.components[].placeholder] The placeholder text for the component when no option is selected (type 3 only)
|
|
||||||
* @arg {Number} [content.components[].style] The style of the component (type 2 only) - If 0-4, `custom_id` is required; if 5, `url` is required
|
|
||||||
* @arg {Number} content.components[].type The type of component - If 1, it is a collection and a `components` array (nested) is required; if 2, it is a button; if 3, it is a select menu
|
|
||||||
* @arg {String} [content.components[].url] The URL that the component should open for users (type 2 style 5 only)
|
|
||||||
* @arg {String} [content.content] A content string
|
|
||||||
* @arg {Object} [content.embed] An embed object. See [the official Discord API documentation entry](https://discord.com/developers/docs/resources/channel#embed-object) for object structure
|
|
||||||
* @arg {Array<Object>} [content.embeds] An array of embed objects. See [the official Discord API documentation entry](https://discord.com/developers/docs/resources/channel#embed-object) for object structure
|
|
||||||
* @arg {Object} [content.messageReference] The message reference, used when replying to messages
|
|
||||||
* @arg {String} [content.messageReference.channelID] The channel ID of the referenced message
|
|
||||||
* @arg {Boolean} [content.messageReference.failIfNotExists=true] Whether to throw an error if the message reference doesn't exist. If false, and the referenced message doesn't exist, the message is created without a referenced message
|
|
||||||
* @arg {String} [content.messageReference.guildID] The guild ID of the referenced message
|
|
||||||
* @arg {String} content.messageReference.messageID The message ID of the referenced message. This cannot reference a system message
|
|
||||||
* @arg {String} [content.messageReferenceID] [DEPRECATED] The ID of the message should be replied to. Use `messageReference` instead
|
|
||||||
* @arg {Array<String>} [content.stickerIDs] An array of IDs corresponding to stickers to send
|
|
||||||
* @arg {Boolean} [content.tts] Set the message TTS flag
|
|
||||||
* @arg {Object | Array<Object>} [file] A file object (or an Array of them)
|
|
||||||
* @arg {Buffer} file.file A buffer containing file data
|
|
||||||
* @arg {String} file.name What to name the file
|
|
||||||
* @returns {Promise<Message>}
|
|
||||||
*/
|
|
||||||
async createMessage(content: MessageContent, file?: FileContent | FileContent[]) {
|
|
||||||
return this.client.createMessage.call(this.client, this.id, content, file)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a thread with an existing message
|
|
||||||
* @arg {String} messageID The ID of the message to create the thread from
|
|
||||||
* @arg {Object} options The thread options
|
|
||||||
* @arg {Number} options.autoArchiveDuration Duration in minutes to automatically archive the thread after recent activity, either 60, 1440, 4320 or 10080
|
|
||||||
* @arg {String} options.name The thread channel name
|
|
||||||
* @returns {Promise<NewsThreadChannel | PublicThreadChannel>}
|
|
||||||
*/
|
|
||||||
async createThreadWithMessage(messageID: string, options: CreateThreadOptions) {
|
|
||||||
return this.client.createThreadWithMessage.call(this.client, this.id, messageID, options)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a thread without an existing message
|
|
||||||
* @arg {Object} options The thread options
|
|
||||||
* @arg {Number} options.autoArchiveDuration Duration in minutes to automatically archive the thread after recent activity, either 60, 1440, 4320 or 10080
|
|
||||||
* @arg {boolean} [options.invitable] Whether non-moderators can add other non-moderators to the thread (private threads only)
|
|
||||||
* @arg {String} options.name The thread channel name
|
|
||||||
* @arg {Number} [options.type] The channel type of the thread to create. It is recommended to explicitly set this property as this will be a required property in API v10
|
|
||||||
* @returns {Promise<PrivateThreadChannel>}
|
|
||||||
*/
|
|
||||||
async createThreadWithoutMessage(options: CreateThreadWithoutMessageOptions) {
|
|
||||||
return this.client.createThreadWithoutMessage.call(this.client, this.id, options)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a channel webhook
|
|
||||||
* @arg {Object} options Webhook options
|
|
||||||
* @arg {String} [options.avatar] The default avatar as a base64 data URI. Note: base64 strings alone are not base64 data URI strings
|
|
||||||
* @arg {String} options.name The default name
|
|
||||||
* @arg {String} [reason] The reason to be displayed in audit logs
|
|
||||||
* @returns {Promise<Object>} Resolves with a webhook object
|
|
||||||
*/
|
|
||||||
async createWebhook(options: { name: string; avatar?: string | null }, reason: string) {
|
|
||||||
return this.client.createChannelWebhook.call(this.client, this.id, options, reason)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Delete a message
|
|
||||||
* @arg {String} messageID The ID of the message
|
|
||||||
* @arg {String} [reason] The reason to be displayed in audit logs
|
|
||||||
* @returns {Promise}
|
|
||||||
*/
|
|
||||||
async deleteMessage(messageID: string, reason: string) {
|
|
||||||
return this.client.deleteMessage.call(this.client, this.id, messageID, reason)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Bulk delete messages (bot accounts only)
|
|
||||||
* @arg {Array<String>} messageIDs Array of message IDs to delete
|
|
||||||
* @arg {String} [reason] The reason to be displayed in audit logs
|
|
||||||
* @returns {Promise}
|
|
||||||
*/
|
|
||||||
async deleteMessages(messageIDs: string[], reason: string) {
|
|
||||||
return this.client.deleteMessages.call(this.client, this.id, messageIDs, reason)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Edit a message
|
|
||||||
* @arg {String} messageID The ID of the message
|
|
||||||
* @arg {String | Array | Object} content A string, array of strings, or object. If an object is passed:
|
|
||||||
* @arg {Object} [content.allowedMentions] A list of mentions to allow (overrides default)
|
|
||||||
* @arg {Boolean} [content.allowedMentions.everyone] Whether or not to allow @everyone/@here.
|
|
||||||
* @arg {Boolean | Array<String>} [content.allowedMentions.roles] Whether or not to allow all role mentions, or an array of specific role mentions to allow.
|
|
||||||
* @arg {Boolean | Array<String>} [content.allowedMentions.users] Whether or not to allow all user mentions, or an array of specific user mentions to allow.
|
|
||||||
* @arg {Array<Object>} [content.components] An array of component objects
|
|
||||||
* @arg {String} [content.components[].custom_id] The ID of the component (type 2 style 0-4 and type 3 only)
|
|
||||||
* @arg {Boolean} [content.components[].disabled] Whether the component is disabled (type 2 and 3 only)
|
|
||||||
* @arg {Object} [content.components[].emoji] The emoji to be displayed in the component (type 2)
|
|
||||||
* @arg {String} [content.components[].label] The label to be displayed in the component (type 2)
|
|
||||||
* @arg {Number} [content.components[].max_values] The maximum number of items that can be chosen (1-25, default 1)
|
|
||||||
* @arg {Number} [content.components[].min_values] The minimum number of items that must be chosen (0-25, default 1)
|
|
||||||
* @arg {Array<Object>} [content.components[].options] The options for this component (type 3 only)
|
|
||||||
* @arg {Boolean} [content.components[].options[].default] Whether this option should be the default value selected
|
|
||||||
* @arg {String} [content.components[].options[].description] The description for this option
|
|
||||||
* @arg {Object} [content.components[].options[].emoji] The emoji to be displayed in this option
|
|
||||||
* @arg {String} content.components[].options[].label The label for this option
|
|
||||||
* @arg {Number | String} content.components[].options[].value The value for this option
|
|
||||||
* @arg {String} [content.components[].placeholder] The placeholder text for the component when no option is selected (type 3 only)
|
|
||||||
* @arg {Number} [content.components[].style] The style of the component (type 2 only) - If 0-4, `custom_id` is required; if 5, `url` is required
|
|
||||||
* @arg {Number} content.components[].type The type of component - If 1, it is a collection and a `components` array (nested) is required; if 2, it is a button; if 3, it is a select menu
|
|
||||||
* @arg {String} [content.components[].url] The URL that the component should open for users (type 2 style 5 only)
|
|
||||||
* @arg {String} [content.content] A content string
|
|
||||||
* @arg {Object} [content.embed] An embed object. See [the official Discord API documentation entry](https://discord.com/developers/docs/resources/channel#embed-object) for object structure
|
|
||||||
* @arg {Array<Object>} [content.embeds] An array of embed objects. See [the official Discord API documentation entry](https://discord.com/developers/docs/resources/channel#embed-object) for object structure
|
|
||||||
* @arg {Object | Array<Object>} [content.file] A file object (or an Array of them)
|
|
||||||
* @arg {Buffer} content.file[].file A buffer containing file data
|
|
||||||
* @arg {String} content.file[].name What to name the file
|
|
||||||
* @arg {Number} [content.flags] A number representing the flags to apply to the message. See [the official Discord API documentation entry](https://discord.com/developers/docs/resources/channel#message-object-message-flags) for flags reference
|
|
||||||
* @returns {Promise<Message>}
|
|
||||||
*/
|
|
||||||
async editMessage(messageID: string, content: MessageContentEdit) {
|
|
||||||
return this.client.editMessage.call(this.client, this.id, messageID, content)
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Get all archived threads in this channel */
|
|
||||||
async getArchivedThreads(type: 'private', options?: GetArchivedThreadsOptions): Promise<ListedChannelThreads<PrivateThreadChannel>>
|
|
||||||
async getArchivedThreads(type: 'public', options?: GetArchivedThreadsOptions): Promise<ListedChannelThreads<PublicThreadChannel>>
|
|
||||||
async getArchivedThreads(
|
|
||||||
type: 'public' | 'private',
|
|
||||||
options?: GetArchivedThreadsOptions,
|
|
||||||
): Promise<ListedChannelThreads<PrivateThreadChannel | PublicThreadChannel>> {
|
|
||||||
return await this.client.getArchivedThreads.call(this.client, this.id, type as 'public', options)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get all invites in the channel
|
|
||||||
* @returns {Promise<Array<Invite>>}
|
|
||||||
*/
|
|
||||||
async getInvites() {
|
|
||||||
return this.client.getChannelInvites.call(this.client, this.id)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get joined private archived threads in this channel
|
|
||||||
* @arg {Object} [options] Additional options when requesting archived threads
|
|
||||||
* @arg {Date} [options.before] List of threads to return before the timestamp
|
|
||||||
* @arg {Number} [options.limit] Maximum number of threads to return
|
|
||||||
* @returns {Promise<Object>} An object containing an array of `threads`, an array of `members` and whether the response `hasMore` threads that could be returned in a subsequent call
|
|
||||||
*/
|
|
||||||
async getJoinedPrivateArchivedThreads(options: GetArchivedThreadsOptions) {
|
|
||||||
return this.client.getJoinedPrivateArchivedThreads.call(this.client, this.id, options)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get a previous message in the channel
|
|
||||||
* @arg {String} messageID The ID of the message
|
|
||||||
* @returns {Promise<Message>}
|
|
||||||
*/
|
|
||||||
async getMessage(messageID: string) {
|
|
||||||
return this.client.getMessage.call(this.client, this.id, messageID)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get a list of users who reacted with a specific reaction
|
|
||||||
* @arg {String} messageID The ID of the message
|
|
||||||
* @arg {String} reaction The reaction (Unicode string if Unicode emoji, `emojiName:emojiID` if custom emoji)
|
|
||||||
* @arg {Object} [options] Options for the request. If this is a number, it is treated as `options.limit` ([DEPRECATED] behavior)
|
|
||||||
* @arg {Number} [options.limit=100] The maximum number of users to get
|
|
||||||
* @arg {String} [options.after] Get users after this user ID
|
|
||||||
* @returns {Promise<Array<User>>}
|
|
||||||
*/
|
|
||||||
async getMessageReaction(messageID: string, reaction: string, options: GetMessageReactionOptions) {
|
|
||||||
return this.client.getMessageReaction.call(this.client, this.id, messageID, reaction, options)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get previous messages in the channel
|
|
||||||
* @arg {Object} [options] Options for the request. If this is a number ([DEPRECATED] behavior), it is treated as `options.limit`
|
|
||||||
* @arg {String} [options.after] Get messages after this message ID
|
|
||||||
* @arg {String} [options.around] Get messages around this message ID (does not work with limit > 100)
|
|
||||||
* @arg {String} [options.before] Get messages before this message ID
|
|
||||||
* @arg {Number} [options.limit=50] The max number of messages to get
|
|
||||||
* @returns {Promise<Array<Message>>}
|
|
||||||
*/
|
|
||||||
async getMessages(options: GetMessagesOptions) {
|
|
||||||
return this.client.getMessages.call(this.client, this.id, options)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get all the pins in the channel
|
|
||||||
* @returns {Promise<Array<Message>>}
|
|
||||||
*/
|
|
||||||
async getPins() {
|
|
||||||
return this.client.getPins.call(this.client, this.id)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get all the webhooks in the channel
|
|
||||||
* @returns {Promise<Array<Object>>} Resolves with an array of webhook objects
|
|
||||||
*/
|
|
||||||
async getWebhooks() {
|
|
||||||
return this.client.getChannelWebhooks.call(this.client, this.id)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Pin a message
|
|
||||||
* @arg {String} messageID The ID of the message
|
|
||||||
* @returns {Promise}
|
|
||||||
*/
|
|
||||||
async pinMessage(messageID: string) {
|
|
||||||
return this.client.pinMessage.call(this.client, this.id, messageID)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Purge previous messages in the channel with an optional filter (bot accounts only)
|
|
||||||
* @arg {Object} options Options for the request. If this is a number ([DEPRECATED] behavior), it is treated as `options.limit`
|
|
||||||
* @arg {String} [options.after] Get messages after this message ID
|
|
||||||
* @arg {String} [options.before] Get messages before this message ID
|
|
||||||
* @arg {Function} [options.filter] Optional filter function that returns a boolean when passed a Message object
|
|
||||||
* @arg {Number} options.limit The max number of messages to search through, -1 for no limit
|
|
||||||
* @arg {String} [options.reason] The reason to be displayed in audit logs
|
|
||||||
* @returns {Promise<Number>} Resolves with the number of messages deleted
|
|
||||||
*/
|
|
||||||
async purge(limit: PurgeChannelOptions) {
|
|
||||||
return this.client.purgeChannel.call(this.client, this.id, limit)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Remove a reaction from a message
|
|
||||||
* @arg {String} messageID The ID of the message
|
|
||||||
* @arg {String} reaction The reaction (Unicode string if Unicode emoji, `emojiName:emojiID` if custom emoji)
|
|
||||||
* @arg {String} [userID="@me"] The ID of the user to remove the reaction for
|
|
||||||
* @returns {Promise}
|
|
||||||
*/
|
|
||||||
async removeMessageReaction(messageID: string, reaction: string, userID: string) {
|
|
||||||
return this.client.removeMessageReaction.call(this.client, this.id, messageID, reaction, userID)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Remove all reactions from a message for a single emoji
|
|
||||||
* @arg {String} messageID The ID of the message
|
|
||||||
* @arg {String} reaction The reaction (Unicode string if Unicode emoji, `emojiName:emojiID` if custom emoji)
|
|
||||||
* @returns {Promise}
|
|
||||||
*/
|
|
||||||
async removeMessageReactionEmoji(messageID: string, reaction: string) {
|
|
||||||
return this.client.removeMessageReactionEmoji.call(this.client, this.id, messageID, reaction)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Remove all reactions from a message
|
|
||||||
* @arg {String} messageID The ID of the message
|
|
||||||
* @returns {Promise}
|
|
||||||
*/
|
|
||||||
async removeMessageReactions(messageID: string) {
|
|
||||||
return this.client.removeMessageReactions.call(this.client, this.id, messageID)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Send typing status in the channel
|
|
||||||
* @returns {Promise}
|
|
||||||
*/
|
|
||||||
async sendTyping() {
|
|
||||||
return this.client.sendChannelTyping.call(this.client, this.id)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Unpin a message
|
|
||||||
* @arg {String} messageID The ID of the message
|
|
||||||
* @returns {Promise}
|
|
||||||
*/
|
|
||||||
async unpinMessage(messageID: string) {
|
|
||||||
return this.client.unpinMessage.call(this.client, this.id, messageID)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Un-send a message. You're welcome Programmix
|
|
||||||
* @arg {String} messageID The ID of the message
|
|
||||||
* @returns {Promise}
|
|
||||||
*/
|
|
||||||
async unsendMessage(messageID: string) {
|
|
||||||
return this.client.deleteMessage.call(this.client, this.id, messageID)
|
|
||||||
}
|
|
||||||
|
|
||||||
toJSON(props: string[] = []): Record<string, any> {
|
|
||||||
return super.toJSON(['lastMessageID', 'lastPinTimestamp', 'messages', 'rateLimitPerUser', 'topic', ...props])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default TextChannel
|
|
||||||
@@ -1,271 +0,0 @@
|
|||||||
/* eslint-disable no-useless-call */
|
|
||||||
/* eslint-disable @typescript-eslint/explicit-function-return-type */
|
|
||||||
import type { DiscordChannel, GetMessagesOptions } from '@discordeno/types'
|
|
||||||
import type Client from '../../Client.js'
|
|
||||||
import Collection from '../../Collection.js'
|
|
||||||
import type {
|
|
||||||
CreateInviteOptions,
|
|
||||||
FileContent,
|
|
||||||
GetMessageReactionOptions,
|
|
||||||
MessageContent,
|
|
||||||
MessageContentEdit,
|
|
||||||
PurgeChannelOptions,
|
|
||||||
} from '../../typings.js'
|
|
||||||
import type Message from '../Message.js'
|
|
||||||
import VoiceChannel from './Voice.js'
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Represents a Text-in-Voice channel. See VoiceChannel for more properties and methods.
|
|
||||||
* @extends VoiceChannel
|
|
||||||
* @prop {String} lastMessageID The ID of the last message in this channel
|
|
||||||
* @prop {Collection<Message>} messages Collection of Messages in this channel
|
|
||||||
* @prop {Number} rateLimitPerUser The ratelimit of the channel, in seconds. 0 means no ratelimit is enabled
|
|
||||||
*/
|
|
||||||
export class TextVoiceChannel extends VoiceChannel {
|
|
||||||
lastMessageID = ""
|
|
||||||
messages: Collection<string, Message>
|
|
||||||
rateLimitPerUser: number | null
|
|
||||||
|
|
||||||
constructor(data: DiscordChannel, client: Client, messageLimit?: number) {
|
|
||||||
super(data, client)
|
|
||||||
|
|
||||||
this.messages = new Collection()
|
|
||||||
if (messageLimit == null) this.messages.limit = client.options.messageLimit
|
|
||||||
else this.messages.limit = messageLimit
|
|
||||||
|
|
||||||
this.lastMessageID = data.last_message_id ?? ""
|
|
||||||
this.rateLimitPerUser = data.rate_limit_per_user == null ? null : data.rate_limit_per_user
|
|
||||||
}
|
|
||||||
|
|
||||||
update(data: DiscordChannel) {
|
|
||||||
super.update(data)
|
|
||||||
// "not yet, possibly TBD"
|
|
||||||
if (data.rate_limit_per_user !== undefined) {
|
|
||||||
this.rateLimitPerUser = data.rate_limit_per_user
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Add a reaction to a message
|
|
||||||
* @arg {String} messageID The ID of the message
|
|
||||||
* @arg {String} reaction The reaction (Unicode string if Unicode emoji, `emojiName:emojiID` if custom emoji)
|
|
||||||
* @returns {Promise}
|
|
||||||
*/
|
|
||||||
async addMessageReaction(messageID: string, reaction: string) {
|
|
||||||
return await this.client.addMessageReaction.call(this.client, this.id, messageID, reaction)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create an invite for the channel
|
|
||||||
* @arg {Object} [options] Invite generation options
|
|
||||||
* @arg {Number} [options.maxAge] How long the invite should last in seconds
|
|
||||||
* @arg {Number} [options.maxUses] How many uses the invite should last for
|
|
||||||
* @arg {Boolean} [options.temporary] Whether the invite grants temporary membership or not
|
|
||||||
* @arg {Boolean} [options.unique] Whether the invite is unique or not
|
|
||||||
* @arg {String} [reason] The reason to be displayed in audit logs
|
|
||||||
* @returns {Promise<Invite>}
|
|
||||||
*/
|
|
||||||
async createInvite(options: CreateInviteOptions, reason: string) {
|
|
||||||
return await this.client.createChannelInvite.call(this.client, this.id, options, reason)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a message in the channel
|
|
||||||
* Note: If you want to DM someone, the user ID is **not** the DM channel ID. use Client.getDMChannel() to get the DM channel ID for a user
|
|
||||||
* @arg {String | Object} content A string or object. If an object is passed:
|
|
||||||
* @arg {Object} [content.allowedMentions] A list of mentions to allow (overrides default)
|
|
||||||
* @arg {Boolean} [content.allowedMentions.everyone] Whether or not to allow @everyone/@here.
|
|
||||||
* @arg {Boolean | Array<String>} [content.allowedMentions.roles] Whether or not to allow all role mentions, or an array of specific role mentions to allow.
|
|
||||||
* @arg {Boolean | Array<String>} [content.allowedMentions.users] Whether or not to allow all user mentions, or an array of specific user mentions to allow.
|
|
||||||
* @arg {Boolean} [options.allowedMentions.repliedUser] Whether or not to mention the author of the message being replied to
|
|
||||||
* @arg {Array<Object>} [content.components] An array of component objects
|
|
||||||
* @arg {String} [content.components[].custom_id] The ID of the component (type 2 style 0-4 and type 3 only)
|
|
||||||
* @arg {Boolean} [content.components[].disabled] Whether the component is disabled (type 2 and 3 only)
|
|
||||||
* @arg {Object} [content.components[].emoji] The emoji to be displayed in the component (type 2)
|
|
||||||
* @arg {String} [content.components[].label] The label to be displayed in the component (type 2)
|
|
||||||
* @arg {Number} [content.components[].max_values] The maximum number of items that can be chosen (1-25, default 1)
|
|
||||||
* @arg {Number} [content.components[].min_values] The minimum number of items that must be chosen (0-25, default 1)
|
|
||||||
* @arg {Array<Object>} [content.components[].options] The options for this component (type 3 only)
|
|
||||||
* @arg {Boolean} [content.components[].options[].default] Whether this option should be the default value selected
|
|
||||||
* @arg {String} [content.components[].options[].description] The description for this option
|
|
||||||
* @arg {Object} [content.components[].options[].emoji] The emoji to be displayed in this option
|
|
||||||
* @arg {String} content.components[].options[].label The label for this option
|
|
||||||
* @arg {Number | String} content.components[].options[].value The value for this option
|
|
||||||
* @arg {String} [content.components[].placeholder] The placeholder text for the component when no option is selected (type 3 only)
|
|
||||||
* @arg {Number} [content.components[].style] The style of the component (type 2 only) - If 0-4, `custom_id` is required; if 5, `url` is required
|
|
||||||
* @arg {Number} content.components[].type The type of component - If 1, it is a collection and a `components` array (nested) is required; if 2, it is a button; if 3, it is a select menu
|
|
||||||
* @arg {String} [content.components[].url] The URL that the component should open for users (type 2 style 5 only)
|
|
||||||
* @arg {String} content.content A content string
|
|
||||||
* @arg {Array<Object>} [content.embeds] An array of embed objects. See [the official Discord API documentation entry](https://discord.com/developers/docs/resources/channel#embed-object) for object structure
|
|
||||||
* @arg {Object} [content.messageReference] The message reference, used when replying to messages
|
|
||||||
* @arg {String} [content.messageReference.channelID] The channel ID of the referenced message
|
|
||||||
* @arg {Boolean} [content.messageReference.failIfNotExists=true] Whether to throw an error if the message reference doesn't exist. If false, and the referenced message doesn't exist, the message is created without a referenced message
|
|
||||||
* @arg {String} [content.messageReference.guildID] The guild ID of the referenced message
|
|
||||||
* @arg {String} content.messageReference.messageID The message ID of the referenced message. This cannot reference a system message
|
|
||||||
* @arg {Array<String>} [content.stickerIDs] An array of IDs corresponding to the stickers to send
|
|
||||||
* @arg {Boolean} [content.tts] Set the message TTS flag
|
|
||||||
* @arg {Object} [file] A file object
|
|
||||||
* @arg {Buffer} file.file A buffer containing file data
|
|
||||||
* @arg {String} file.name What to name the file
|
|
||||||
* @returns {Promise<Message>}
|
|
||||||
*/
|
|
||||||
async createMessage(content: MessageContent, file?: FileContent | FileContent[]) {
|
|
||||||
return await this.client.createMessage.call(this.client, this.id, content, file)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Delete a message
|
|
||||||
* @arg {String} messageID The ID of the message
|
|
||||||
* @arg {String} [reason] The reason to be displayed in audit logs
|
|
||||||
* @returns {Promise}
|
|
||||||
*/
|
|
||||||
async deleteMessage(messageID: string, reason: string) {
|
|
||||||
return await this.client.deleteMessage.call(this.client, this.id, messageID, reason)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Bulk delete messages (bot accounts only)
|
|
||||||
* @arg {Array<String>} messageIDs Array of message IDs to delete
|
|
||||||
* @arg {String} [reason] The reason to be displayed in audit logs
|
|
||||||
* @returns {Promise}
|
|
||||||
*/
|
|
||||||
async deleteMessages(messageIDs: string[], reason: string) {
|
|
||||||
return await this.client.deleteMessages.call(this.client, this.id, messageIDs, reason)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Edit a message
|
|
||||||
* @arg {String} messageID The ID of the message
|
|
||||||
* @arg {String | Array | Object} content A string, array of strings, or object. If an object is passed:
|
|
||||||
* @arg {Object} [content.allowedMentions] A list of mentions to allow (overrides default)
|
|
||||||
* @arg {Boolean} [content.allowedMentions.everyone] Whether or not to allow @everyone/@here.
|
|
||||||
* @arg {Boolean | Array<String>} [content.allowedMentions.roles] Whether or not to allow all role mentions, or an array of specific role mentions to allow.
|
|
||||||
* @arg {Boolean | Array<String>} [content.allowedMentions.users] Whether or not to allow all user mentions, or an array of specific user mentions to allow.
|
|
||||||
* @arg {Array<Object>} [content.components] An array of component objects
|
|
||||||
* @arg {String} [content.components[].custom_id] The ID of the component (type 2 style 0-4 and type 3 only)
|
|
||||||
* @arg {Boolean} [content.components[].disabled] Whether the component is disabled (type 2 and 3 only)
|
|
||||||
* @arg {Object} [content.components[].emoji] The emoji to be displayed in the component (type 2)
|
|
||||||
* @arg {String} [content.components[].label] The label to be displayed in the component (type 2)
|
|
||||||
* @arg {Number} [content.components[].max_values] The maximum number of items that can be chosen (1-25, default 1)
|
|
||||||
* @arg {Number} [content.components[].min_values] The minimum number of items that must be chosen (0-25, default 1)
|
|
||||||
* @arg {Array<Object>} [content.components[].options] The options for this component (type 3 only)
|
|
||||||
* @arg {Boolean} [content.components[].options[].default] Whether this option should be the default value selected
|
|
||||||
* @arg {String} [content.components[].options[].description] The description for this option
|
|
||||||
* @arg {Object} [content.components[].options[].emoji] The emoji to be displayed in this option
|
|
||||||
* @arg {String} content.components[].options[].label The label for this option
|
|
||||||
* @arg {Number | String} content.components[].options[].value The value for this option
|
|
||||||
* @arg {String} [content.components[].placeholder] The placeholder text for the component when no option is selected (type 3 only)
|
|
||||||
* @arg {Number} [content.components[].style] The style of the component (type 2 only) - If 0-4, `custom_id` is required; if 5, `url` is required
|
|
||||||
* @arg {Number} content.components[].type The type of component - If 1, it is a collection and a `components` array (nested) is required; if 2, it is a button; if 3, it is a select menu
|
|
||||||
* @arg {String} [content.components[].url] The URL that the component should open for users (type 2 style 5 only)
|
|
||||||
* @arg {String} content.content A content string
|
|
||||||
* @arg {Boolean} [content.disableEveryone] Whether to filter @everyone/@here or not (overrides default)
|
|
||||||
* @arg {Array<Object>} [content.embeds] An array of embed objects. See [the official Discord API documentation entry](https://discord.com/developers/docs/resources/channel#embed-object) for object structure
|
|
||||||
* @arg {Number} [content.flags] A number representing the flags to apply to the message. See [the official Discord API documentation entry](https://discord.com/developers/docs/resources/channel#message-object-message-flags) for flags reference
|
|
||||||
* @returns {Promise<Message>}
|
|
||||||
*/
|
|
||||||
async editMessage(messageID: string, content: MessageContentEdit) {
|
|
||||||
return await this.client.editMessage.call(this.client, this.id, messageID, content)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get all invites in the channel
|
|
||||||
* @returns {Promise<Array<Invite>>}
|
|
||||||
*/
|
|
||||||
async getInvites() {
|
|
||||||
return await this.client.getChannelInvites.call(this.client, this.id)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get a previous message in the channel
|
|
||||||
* @arg {String} messageID The ID of the message
|
|
||||||
* @returns {Promise<Message>}
|
|
||||||
*/
|
|
||||||
async getMessage(messageID: string) {
|
|
||||||
return await this.client.getMessage.call(this.client, this.id, messageID)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get a list of users who reacted with a specific reaction
|
|
||||||
* @arg {String} messageID The ID of the message
|
|
||||||
* @arg {String} reaction The reaction (Unicode string if Unicode emoji, `emojiName:emojiID` if custom emoji)
|
|
||||||
* @arg {Object} [options] Options for the request. If this is a number, it is treated as `options.limit` ([DEPRECATED] behavior)
|
|
||||||
* @arg {Number} [options.limit=100] The maximum number of users to get
|
|
||||||
* @arg {String} [options.after] Get users after this user ID
|
|
||||||
* @returns {Promise<Array<User>>}
|
|
||||||
*/
|
|
||||||
async getMessageReaction(messageID: string, reaction: string, options: GetMessageReactionOptions) {
|
|
||||||
return await this.client.getMessageReaction.call(this.client, this.id, messageID, reaction, options)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get previous messages in the channel
|
|
||||||
* @arg {Object} [options] Options for the request. If this is a number ([DEPRECATED] behavior), it is treated as `options.limit`
|
|
||||||
* @arg {String} [options.after] Get messages after this message ID
|
|
||||||
* @arg {String} [options.around] Get messages around this message ID (does not work with limit > 100)
|
|
||||||
* @arg {String} [options.before] Get messages before this message ID
|
|
||||||
* @arg {Number} [options.limit=50] The max number of messages to get
|
|
||||||
* @returns {Promise<Array<Message>>}
|
|
||||||
*/
|
|
||||||
async getMessages(options: GetMessagesOptions) {
|
|
||||||
return await this.client.getMessages.call(this.client, this.id, options)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Purge previous messages in the channel with an optional filter (bot accounts only)
|
|
||||||
* @arg {Object} options Options for the request. If this is a number ([DEPRECATED] behavior), it is treated as `options.limit`
|
|
||||||
* @arg {String} [options.after] Get messages after this message ID
|
|
||||||
* @arg {String} [options.before] Get messages before this message ID
|
|
||||||
* @arg {Function} [options.filter] Optional filter function that returns a boolean when passed a Message object
|
|
||||||
* @arg {Number} options.limit The max number of messages to search through, -1 for no limit
|
|
||||||
* @arg {String} [options.reason] The reason to be displayed in audit logs
|
|
||||||
* @returns {Promise<Number>} Resolves with the number of messages deleted
|
|
||||||
*/
|
|
||||||
async purge(options: PurgeChannelOptions) {
|
|
||||||
return await this.client.purgeChannel.call(this.client, this.id, options)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Remove a reaction from a message
|
|
||||||
* @arg {String} messageID The ID of the message
|
|
||||||
* @arg {String} reaction The reaction (Unicode string if Unicode emoji, `emojiName:emojiID` if custom emoji)
|
|
||||||
* @arg {String} [userID="@me"] The ID of the user to remove the reaction for
|
|
||||||
* @returns {Promise}
|
|
||||||
*/
|
|
||||||
async removeMessageReaction(messageID: string, reaction: string, userID: string) {
|
|
||||||
return await this.client.removeMessageReaction.call(this.client, this.id, messageID, reaction, userID)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Remove all reactions from a message for a single emoji
|
|
||||||
* @arg {String} messageID The ID of the message
|
|
||||||
* @arg {String} reaction The reaction (Unicode string if Unicode emoji, `emojiName:emojiID` if custom emoji)
|
|
||||||
* @returns {Promise}
|
|
||||||
*/
|
|
||||||
async removeMessageReactionEmoji(messageID: string, reaction: string) {
|
|
||||||
return await this.client.removeMessageReactionEmoji.call(this.client, this.id, messageID, reaction)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Remove all reactions from a message
|
|
||||||
* @arg {String} messageID The ID of the message
|
|
||||||
* @returns {Promise}
|
|
||||||
*/
|
|
||||||
async removeMessageReactions(messageID: string) {
|
|
||||||
return await this.client.removeMessageReactions.call(this.client, this.id, messageID)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Send typing status in the channel
|
|
||||||
* @returns {Promise}
|
|
||||||
*/
|
|
||||||
async sendTyping() {
|
|
||||||
return await this.client.sendChannelTyping.call(this.client, this.id)
|
|
||||||
}
|
|
||||||
|
|
||||||
toJSON(props: string[] = []): Record<string, any> {
|
|
||||||
return super.toJSON(['lastMessageID', 'messages', 'rateLimitPerUser', ...props])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default TextVoiceChannel
|
|
||||||
@@ -1,91 +0,0 @@
|
|||||||
/* eslint-disable no-useless-call */
|
|
||||||
/* eslint-disable @typescript-eslint/explicit-function-return-type */
|
|
||||||
import type { DiscordChannel } from '@discordeno/types'
|
|
||||||
import type Client from '../../Client.js'
|
|
||||||
import Collection from '../../Collection.js'
|
|
||||||
import type { CreateInviteOptions, TextVoiceChannelTypes, VideoQualityMode } from '../../typings.js'
|
|
||||||
import type Member from '../guilds/Member.js'
|
|
||||||
import GuildChannel from './Guild.js'
|
|
||||||
|
|
||||||
export class VoiceChannel extends GuildChannel {
|
|
||||||
bitrate: number = 0
|
|
||||||
rtcRegion: string | null = null
|
|
||||||
type: TextVoiceChannelTypes = 0
|
|
||||||
userLimit: number = 0
|
|
||||||
videoQualityMode: VideoQualityMode = 0
|
|
||||||
voiceMembers: Collection<string, Member>
|
|
||||||
|
|
||||||
constructor(data: DiscordChannel, client: Client) {
|
|
||||||
super(data, client)
|
|
||||||
|
|
||||||
this.voiceMembers = new Collection()
|
|
||||||
this.update(data)
|
|
||||||
}
|
|
||||||
|
|
||||||
update(data: DiscordChannel): void {
|
|
||||||
super.update(data)
|
|
||||||
|
|
||||||
if (data.bitrate !== undefined) {
|
|
||||||
this.bitrate = data.bitrate
|
|
||||||
}
|
|
||||||
if (data.rtc_region !== undefined) {
|
|
||||||
this.rtcRegion = data.rtc_region
|
|
||||||
}
|
|
||||||
if (data.user_limit !== undefined) {
|
|
||||||
this.userLimit = data.user_limit
|
|
||||||
}
|
|
||||||
if (data.video_quality_mode !== undefined) {
|
|
||||||
this.videoQualityMode = data.video_quality_mode
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create an invite for the channel
|
|
||||||
* @arg {Object} [options] Invite generation options
|
|
||||||
* @arg {Number} [options.maxAge] How long the invite should last in seconds
|
|
||||||
* @arg {Number} [options.maxUses] How many uses the invite should last for
|
|
||||||
* @arg {Boolean} [options.temporary] Whether the invite grants temporary membership or not
|
|
||||||
* @arg {Boolean} [options.unique] Whether the invite is unique or not
|
|
||||||
* @arg {String} [reason] The reason to be displayed in audit logs
|
|
||||||
* @returns {Promise<Invite>}
|
|
||||||
*/
|
|
||||||
async createInvite(options: CreateInviteOptions, reason: string) {
|
|
||||||
return await this.client.createChannelInvite.call(this.client, this.id, options, reason)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get all invites in the channel
|
|
||||||
* @returns {Promise<Array<Invite>>}
|
|
||||||
*/
|
|
||||||
async getInvites() {
|
|
||||||
return await this.client.getChannelInvites.call(this.client, this.id)
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: gateway
|
|
||||||
// /**
|
|
||||||
// * Joins the channel.
|
|
||||||
// * @arg {Object} [options] VoiceConnection constructor options
|
|
||||||
// * @arg {Object} [options.opusOnly] Skip opus encoder initialization. You should not enable this unless you know what you are doing
|
|
||||||
// * @arg {Object} [options.shared] Whether the VoiceConnection will be part of a SharedStream or not
|
|
||||||
// * @arg {Boolean} [options.selfMute] Whether the bot joins the channel muted or not
|
|
||||||
// * @arg {Boolean} [options.selfDeaf] Whether the bot joins the channel deafened or not
|
|
||||||
// * @returns {Promise<VoiceConnection>} Resolves with a VoiceConnection
|
|
||||||
// */
|
|
||||||
// join(options: JoinVoiceChannelOptions) {
|
|
||||||
// return this.client.joinVoiceChannel.call(this.client, this.id, options);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// TODO: gateway
|
|
||||||
// /**
|
|
||||||
// * Leaves the channel.
|
|
||||||
// */
|
|
||||||
// leave() {
|
|
||||||
// return this.client.leaveVoiceChannel.call(this.client, this.id);
|
|
||||||
// }
|
|
||||||
|
|
||||||
toJSON(props: string[] = []): Record<string, any> {
|
|
||||||
return super.toJSON(['bitrate', 'rtcRegion', 'userLimit', 'videoQualityMode', 'voiceMembers', ...props])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default VoiceChannel
|
|
||||||
@@ -1,41 +0,0 @@
|
|||||||
/* eslint-disable no-useless-call */
|
|
||||||
import type { DiscordThreadMember } from '@discordeno/types'
|
|
||||||
import Base from '../../../Base.js'
|
|
||||||
import type Client from '../../../Client.js'
|
|
||||||
import type Member from '../../guilds/Member.js'
|
|
||||||
|
|
||||||
export class ThreadMember extends Base {
|
|
||||||
client: Client
|
|
||||||
/** The user-thread settings of this member */
|
|
||||||
flags: number
|
|
||||||
/** The ID of the thread this member is a part of */
|
|
||||||
threadID: string
|
|
||||||
/** Timestamp of when the member joined the thread */
|
|
||||||
joinTimestamp: number
|
|
||||||
/** The guild member that this thread member belongs to. This will never be present when fetching over REST */
|
|
||||||
guildMember?: Member
|
|
||||||
|
|
||||||
constructor(data: DiscordThreadMember, client: Client) {
|
|
||||||
super(data.user_id)
|
|
||||||
|
|
||||||
this.client = client
|
|
||||||
this.flags = data.flags
|
|
||||||
this.threadID = data.id
|
|
||||||
this.joinTimestamp = Date.parse(data.join_timestamp)
|
|
||||||
}
|
|
||||||
|
|
||||||
get _client(): Client {
|
|
||||||
return this.client
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Remove the member from the thread */
|
|
||||||
async leave(): Promise<void> {
|
|
||||||
return await this._client.leaveThread.call(this._client, this.threadID, this.id)
|
|
||||||
}
|
|
||||||
|
|
||||||
toJSON(props: string[] = []): Record<string, any> {
|
|
||||||
return super.toJSON(['threadID', 'joinTimestamp', ...props])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default ThreadMember
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
import ThreadChannel from './Thread.js'
|
|
||||||
|
|
||||||
export class NewsThreadChannel extends ThreadChannel {}
|
|
||||||
|
|
||||||
export default NewsThreadChannel
|
|
||||||
@@ -1,25 +0,0 @@
|
|||||||
import type { DiscordChannel } from '@discordeno/types'
|
|
||||||
import type Client from '../../../Client.js'
|
|
||||||
import ThreadChannel from './Thread.js'
|
|
||||||
|
|
||||||
export class PrivateThreadChannel extends ThreadChannel {
|
|
||||||
constructor(data: DiscordChannel, client: Client, messageLimit?: number) {
|
|
||||||
super(data, client, messageLimit)
|
|
||||||
|
|
||||||
this.update(data)
|
|
||||||
}
|
|
||||||
|
|
||||||
update(data: DiscordChannel): void {
|
|
||||||
if (data.thread_metadata !== undefined) {
|
|
||||||
this.threadMetadata = {
|
|
||||||
archiveTimestamp: Date.parse(data.thread_metadata.archive_timestamp),
|
|
||||||
archived: data.thread_metadata.archived,
|
|
||||||
autoArchiveDuration: data.thread_metadata.auto_archive_duration,
|
|
||||||
invitable: data.thread_metadata.invitable,
|
|
||||||
locked: data.thread_metadata.locked,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default PrivateThreadChannel
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
import ThreadChannel from './Thread.js'
|
|
||||||
|
|
||||||
export class PublicThreadChannel extends ThreadChannel {}
|
|
||||||
|
|
||||||
export default PublicThreadChannel
|
|
||||||
@@ -1,180 +0,0 @@
|
|||||||
/* eslint-disable @typescript-eslint/explicit-function-return-type */
|
|
||||||
/* eslint-disable no-useless-call */
|
|
||||||
import type { BigString, DiscordChannel, GetMessagesOptions } from '@discordeno/types'
|
|
||||||
import type Client from '../../../Client.js'
|
|
||||||
import Collection from '../../../Collection.js'
|
|
||||||
import type { FileContent, GetMessageReactionOptions, MessageContent, MessageContentEdit, PurgeChannelOptions } from '../../../typings.js'
|
|
||||||
import type Message from '../../Message.js'
|
|
||||||
import type User from '../../users/User.js'
|
|
||||||
import GuildChannel from '../Guild.js'
|
|
||||||
import ThreadMember from './Member.js'
|
|
||||||
|
|
||||||
export class ThreadChannel extends GuildChannel {
|
|
||||||
/** The cached messages that were sent in this channel. */
|
|
||||||
messages: Collection<BigString, Message>
|
|
||||||
/** The cached thread members that are in this channel. */
|
|
||||||
members: Collection<BigString, ThreadMember>
|
|
||||||
/** The id of the last message in this channel. */
|
|
||||||
lastMessageID: string
|
|
||||||
/** The id of the user who created this thread. */
|
|
||||||
ownerID: string
|
|
||||||
/** The approximate amount of members that have joined this thread. */
|
|
||||||
memberCount?: number
|
|
||||||
/** The approximate amount of messages in this channel. */
|
|
||||||
messageCount?: number
|
|
||||||
/** The rate limit that users can send messages in this channel. 0 means no rate limit has been enabled. */
|
|
||||||
rateLimitPerUser?: number
|
|
||||||
/** The data relevant to this thread. */
|
|
||||||
threadMetadata?: {
|
|
||||||
/** Timestamp when the thread's archive status was last changed, used for calculating recent activity */
|
|
||||||
archiveTimestamp: number
|
|
||||||
/** Whether the thread is archived. */
|
|
||||||
archived: boolean
|
|
||||||
/** Duration in minutes to automatically archive the thread after recent activity, either 60, 1440, 4320 or 10080 */
|
|
||||||
autoArchiveDuration: number
|
|
||||||
/** Whether the thread is locked. */
|
|
||||||
locked: boolean
|
|
||||||
/** Whether or not the thread is inviteable. */
|
|
||||||
invitable?: boolean
|
|
||||||
}
|
|
||||||
|
|
||||||
/** The bot's thread member object if it has joined the thread. */
|
|
||||||
member?: ThreadMember
|
|
||||||
|
|
||||||
constructor(data: DiscordChannel, client: Client, messageLimit?: number) {
|
|
||||||
super(data, client)
|
|
||||||
|
|
||||||
this.members = new Collection()
|
|
||||||
this.messages = new Collection()
|
|
||||||
|
|
||||||
this.messages.limit = messageLimit ?? client.options.messageLimit
|
|
||||||
this.lastMessageID = data.last_message_id ?? ""
|
|
||||||
this.ownerID = data.owner_id!
|
|
||||||
|
|
||||||
this.update(data)
|
|
||||||
}
|
|
||||||
|
|
||||||
update(data: DiscordChannel): void {
|
|
||||||
super.update(data)
|
|
||||||
|
|
||||||
if (data.member_count !== undefined) {
|
|
||||||
this.memberCount = data.member_count
|
|
||||||
}
|
|
||||||
if (data.message_count !== undefined) {
|
|
||||||
this.messageCount = data.message_count
|
|
||||||
}
|
|
||||||
if (data.rate_limit_per_user !== undefined) {
|
|
||||||
this.rateLimitPerUser = data.rate_limit_per_user
|
|
||||||
}
|
|
||||||
if (data.thread_metadata !== undefined) {
|
|
||||||
this.threadMetadata = {
|
|
||||||
archiveTimestamp: Date.parse(data.thread_metadata.archive_timestamp),
|
|
||||||
archived: data.thread_metadata.archived,
|
|
||||||
autoArchiveDuration: data.thread_metadata.auto_archive_duration,
|
|
||||||
locked: data.thread_metadata.locked,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (data.member !== undefined) {
|
|
||||||
this.member = new ThreadMember(data.member, this.client)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async addMessageReaction(messageID: BigString, reaction: string): Promise<void> {
|
|
||||||
return await this.client.addMessageReaction.call(this.client, this.id, messageID, reaction)
|
|
||||||
}
|
|
||||||
|
|
||||||
async createMessage(content: MessageContent, file?: FileContent | FileContent[]) {
|
|
||||||
return await this.client.createMessage.call(this.client, this.id, content, file)
|
|
||||||
}
|
|
||||||
|
|
||||||
async deleteMessage(messageID: BigString, reason?: string): Promise<void> {
|
|
||||||
return await this.client.deleteMessage.call(this.client, this.id, messageID, reason)
|
|
||||||
}
|
|
||||||
|
|
||||||
async deleteMessages(messageIDs: BigString[], reason?: string): Promise<void> {
|
|
||||||
return await this.client.deleteMessages.call(this.client, this.id, messageIDs, reason)
|
|
||||||
}
|
|
||||||
|
|
||||||
async editMessage(messageID: BigString, content: MessageContentEdit) {
|
|
||||||
return await this.client.editMessage.call(this.client, this.id, messageID, content)
|
|
||||||
}
|
|
||||||
|
|
||||||
async getMembers(): Promise<ThreadMember[]> {
|
|
||||||
return await this.client.getThreadMembers.call(this.client, this.id)
|
|
||||||
}
|
|
||||||
|
|
||||||
async getMessage(messageID: BigString): Promise<Message> {
|
|
||||||
return await this.client.getMessage.call(this.client, this.id, messageID)
|
|
||||||
}
|
|
||||||
|
|
||||||
async getMessageReaction(messageID: BigString, reaction: string, options?: GetMessageReactionOptions): Promise<User[]> {
|
|
||||||
return await this.client.getMessageReaction.call(this.client, this.id, messageID, reaction, options)
|
|
||||||
}
|
|
||||||
|
|
||||||
async getMessages(options: GetMessagesOptions) {
|
|
||||||
return await this.client.getMessages.call(this.client, this.id, options)
|
|
||||||
}
|
|
||||||
|
|
||||||
async getPins(): Promise<Message[]> {
|
|
||||||
return await this.client.getPins.call(this.client, this.id)
|
|
||||||
}
|
|
||||||
|
|
||||||
async join(userID: BigString = '@me'): Promise<void> {
|
|
||||||
return await this.client.joinThread.call(this.client, this.id, userID)
|
|
||||||
}
|
|
||||||
|
|
||||||
async leave(userID: BigString): Promise<void> {
|
|
||||||
return await this.client.leaveThread.call(this.client, this.id, userID)
|
|
||||||
}
|
|
||||||
|
|
||||||
async pinMessage(messageID: BigString): Promise<void> {
|
|
||||||
return await this.client.pinMessage.call(this.client, this.id, messageID)
|
|
||||||
}
|
|
||||||
|
|
||||||
async purge(options: PurgeChannelOptions): Promise<number> {
|
|
||||||
return await this.client.purgeChannel.call(this.client, this.id, options)
|
|
||||||
}
|
|
||||||
|
|
||||||
async removeMessageReaction(messageID: BigString, reaction: string, userID: BigString = '@me') {
|
|
||||||
return await this.client.removeMessageReaction.call(this.client, this.id, messageID, reaction, userID)
|
|
||||||
}
|
|
||||||
|
|
||||||
async removeMessageReactionEmoji(messageID: BigString, reaction: string): Promise<void> {
|
|
||||||
return await this.client.removeMessageReactionEmoji.call(this.client, this.id, messageID, reaction)
|
|
||||||
}
|
|
||||||
|
|
||||||
async removeMessageReactions(messageID: BigString): Promise<void> {
|
|
||||||
return await this.client.removeMessageReactions.call(this.client, this.id, messageID)
|
|
||||||
}
|
|
||||||
|
|
||||||
async sendTyping(): Promise<void> {
|
|
||||||
return await this.client.sendChannelTyping.call(this.client, this.id)
|
|
||||||
}
|
|
||||||
|
|
||||||
async unpinMessage(messageID: BigString): Promise<void> {
|
|
||||||
return await this.client.unpinMessage.call(this.client, this.id, messageID)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @deprecated Use deleteMessage instead
|
|
||||||
*/
|
|
||||||
async unsendMessage(messageID: BigString): Promise<void> {
|
|
||||||
return await this.client.deleteMessage.call(this.client, this.id, messageID)
|
|
||||||
}
|
|
||||||
|
|
||||||
toJSON(props: string[] = []): Record<string, any> {
|
|
||||||
return super.toJSON([
|
|
||||||
'lastMessageID',
|
|
||||||
'memberCount',
|
|
||||||
'messageCount',
|
|
||||||
'messages',
|
|
||||||
'ownerID',
|
|
||||||
'rateLimitPerUser',
|
|
||||||
'threadMetadata',
|
|
||||||
'member',
|
|
||||||
...props,
|
|
||||||
])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default ThreadChannel
|
|
||||||
@@ -1,181 +0,0 @@
|
|||||||
/* eslint-disable @typescript-eslint/explicit-function-return-type */
|
|
||||||
import type { DiscordAuditLogChange, DiscordAuditLogEntry } from '@discordeno/types'
|
|
||||||
import { AuditLogEvents } from '@discordeno/types'
|
|
||||||
import Base from '../../Base.js'
|
|
||||||
import type GuildChannel from '../channels/Guild.js'
|
|
||||||
import type TextChannel from '../channels/Text.js'
|
|
||||||
import Invite from '../Invite.js'
|
|
||||||
import type Message from '../Message.js'
|
|
||||||
import type User from '../users/User.js'
|
|
||||||
import type Guild from './Guild.js'
|
|
||||||
import type Member from './Member.js'
|
|
||||||
import type Role from './Role.js'
|
|
||||||
|
|
||||||
export class GuildAuditLogEntry extends Base {
|
|
||||||
/** The guild to which this entry belongs. */
|
|
||||||
guild: Guild
|
|
||||||
/** The action type of the entry. */
|
|
||||||
actionType: AuditLogEvents
|
|
||||||
/** The reason for the action. */
|
|
||||||
reason: string | null
|
|
||||||
/** The user that performed the action. */
|
|
||||||
user?: User
|
|
||||||
/** The properties of the targeted object before the action was taken. For example, if a channel was renamed from #general to #potato, this would be `{name: "general"}`` */
|
|
||||||
before: Record<DiscordAuditLogChange['key'], DiscordAuditLogChange['old_value']>
|
|
||||||
|
|
||||||
/** The properties of the targeted object after the action was taken. For example, if a channel was renamed from #general to #potato, this would be `{name: "potato"}`` */
|
|
||||||
after: Record<DiscordAuditLogChange['key'], DiscordAuditLogChange['new_value']>
|
|
||||||
|
|
||||||
/** The ID of the action target */
|
|
||||||
targetID?: string
|
|
||||||
/** The number of entities targeted. For example, for action type 26 (MEMBER_MOVE), this is the number of members that were moved/disconnected from the voice channel */
|
|
||||||
count?: number
|
|
||||||
/** The channel targeted in the entry, action types 26 (MEMBER_MOVE), 72/74/75 (MESSAGE_DELETE/PIN/UNPIN) and 83/84/85 (STAGE_INSTANCE_CREATE/UPDATE/DELETE) only */
|
|
||||||
channel?: GuildChannel
|
|
||||||
/** The message that was (un)pinned, action types 74/75 (MESSAGE_PIN/UNPIN) only. If the message is not cached, this will be an object with an `id` key. No other property is guaranteed. */
|
|
||||||
message?: Message | { id: string }
|
|
||||||
/** The number of days of inactivity to prune for, action type 21 (MEMBER_PRUNE) only */
|
|
||||||
deleteMemberDays?: number
|
|
||||||
/** The number of members pruned from the server, action type 21 (MEMBER_PRUNE) only */
|
|
||||||
membersRemoved?: number
|
|
||||||
/** The member described by the permission overwrite, action types 13-15 (CHANNEL\_OVERWRITE\_CREATE/UPDATE/DELETE) only. If the member is not cached, this could be {id: String} */
|
|
||||||
member?: Member | { id: string }
|
|
||||||
/** The role described by the permission overwrite, action types 13-15 (CHANNEL\_OVERWRITE\_CREATE/UPDATE/DELETE) only. If the role is not cached, this could be {id: String, name: String} */
|
|
||||||
role?: Role | { id: string; name: string }
|
|
||||||
|
|
||||||
constructor(data: DiscordAuditLogEntry, guild: Guild) {
|
|
||||||
super(data.id)
|
|
||||||
|
|
||||||
this.guild = guild
|
|
||||||
this.actionType = data.action_type
|
|
||||||
this.reason = data.reason ?? null
|
|
||||||
this.user = data.user_id ? guild.client.users.get(data.user_id) : undefined
|
|
||||||
this.before = {} as any
|
|
||||||
this.after = {} as any
|
|
||||||
if (data.changes) {
|
|
||||||
data.changes.forEach((change) => {
|
|
||||||
if (change.old_value !== undefined) {
|
|
||||||
this.before[change.key] = change.old_value
|
|
||||||
}
|
|
||||||
if (change.new_value !== undefined) {
|
|
||||||
this.after[change.key] = change.new_value
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
if (data.target_id) {
|
|
||||||
this.targetID = data.target_id
|
|
||||||
}
|
|
||||||
if (data.options) {
|
|
||||||
if (data.options.count) {
|
|
||||||
this.count = +data.options.count
|
|
||||||
}
|
|
||||||
if (data.options.channel_id) {
|
|
||||||
if (this.actionType >= 83) {
|
|
||||||
this.channel = guild.threads.get(data.options.channel_id)
|
|
||||||
} else {
|
|
||||||
this.channel = guild.channels.get(data.options.channel_id)
|
|
||||||
}
|
|
||||||
if (data.options.message_id) {
|
|
||||||
this.message = (this.channel && (this.channel as TextChannel).messages.get(data.options.message_id)) ?? {
|
|
||||||
id: data.options.message_id,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (data.options.delete_member_days) {
|
|
||||||
this.deleteMemberDays = +data.options.delete_member_days
|
|
||||||
this.membersRemoved = +data.options.members_removed
|
|
||||||
}
|
|
||||||
if (data.options.type) {
|
|
||||||
if (data.options.type === '1') {
|
|
||||||
this.member = guild.members.get(data.options.id) ?? {
|
|
||||||
id: data.options.id,
|
|
||||||
}
|
|
||||||
} else if (data.options.type === '0') {
|
|
||||||
this.role = guild.roles.get(data.options.id) ?? {
|
|
||||||
id: data.options.id,
|
|
||||||
name: data.options.role_name,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
get target() {
|
|
||||||
// pay more, get less
|
|
||||||
if (this.actionType < 10) {
|
|
||||||
// Guild
|
|
||||||
return this.guild
|
|
||||||
} else if (this.actionType < 20) {
|
|
||||||
// Channel
|
|
||||||
return this.guild?.channels.get(this.targetID!)
|
|
||||||
} else if (this.actionType < 30) {
|
|
||||||
// Member
|
|
||||||
if (this.actionType === AuditLogEvents.MemberMove || this.actionType === AuditLogEvents.MemberDisconnect) {
|
|
||||||
// MEMBER_MOVE / MEMBER_DISCONNECT
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
return this.guild?.members.get(this.targetID!)
|
|
||||||
} else if (this.actionType < 40) {
|
|
||||||
// Role
|
|
||||||
return this.guild?.roles.get(this.targetID!)
|
|
||||||
} else if (this.actionType < 50) {
|
|
||||||
// Invite
|
|
||||||
const changes = this.actionType === 42 ? this.before : this.after // Apparently the meaning of life is a deleted invite
|
|
||||||
return new Invite(
|
|
||||||
{
|
|
||||||
code: changes.code as string,
|
|
||||||
// @ts-expect-error idk why this is happening
|
|
||||||
channel: changes.channel,
|
|
||||||
guild: this.guild.toJSON(),
|
|
||||||
uses: changes.uses as number,
|
|
||||||
max_uses: changes.max_uses as number,
|
|
||||||
max_age: changes.max_age as number,
|
|
||||||
temporary: changes.temporary as boolean,
|
|
||||||
},
|
|
||||||
this.guild?.client,
|
|
||||||
)
|
|
||||||
} else if (this.actionType < 60) {
|
|
||||||
// Webhook
|
|
||||||
return null // Go get the webhook yourself
|
|
||||||
} else if (this.actionType < 70) {
|
|
||||||
// Emoji
|
|
||||||
return this.guild?.emojis?.find((emoji) => emoji.id === this.targetID)
|
|
||||||
} else if (this.actionType < 80) {
|
|
||||||
// Message
|
|
||||||
return this.guild?.client.users.get(this.targetID!)
|
|
||||||
} else if (this.actionType < 83) {
|
|
||||||
// Integrations
|
|
||||||
return null
|
|
||||||
} else if (this.actionType < 90) {
|
|
||||||
// Stage Instances
|
|
||||||
return this.guild?.threads.get(this.targetID!)
|
|
||||||
} else if (this.actionType < 100) {
|
|
||||||
// Sticker
|
|
||||||
return this.guild?.stickers?.find((sticker) => sticker.id === this.targetID)
|
|
||||||
} else {
|
|
||||||
// eslint-disable-next-line @typescript-eslint/restrict-plus-operands
|
|
||||||
throw new Error('Unrecognized action type: ' + this.actionType)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
toJSON(props: string[] = []): Record<string, any> {
|
|
||||||
return super.toJSON([
|
|
||||||
'actionType',
|
|
||||||
'after',
|
|
||||||
'before',
|
|
||||||
'channel',
|
|
||||||
'count',
|
|
||||||
'deleteMemberDays',
|
|
||||||
'member',
|
|
||||||
'membersRemoved',
|
|
||||||
'reason',
|
|
||||||
'role',
|
|
||||||
'targetID',
|
|
||||||
'user',
|
|
||||||
...props,
|
|
||||||
])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default GuildAuditLogEntry
|
|
||||||
@@ -1,952 +0,0 @@
|
|||||||
/* eslint-disable @typescript-eslint/explicit-function-return-type */
|
|
||||||
/* eslint-disable no-useless-call */
|
|
||||||
import {
|
|
||||||
BitwisePermissionFlags,
|
|
||||||
ChannelTypes,
|
|
||||||
type ApplicationCommandTypes,
|
|
||||||
type BigString,
|
|
||||||
type DefaultMessageNotificationLevels,
|
|
||||||
type DiscordEmoji,
|
|
||||||
type DiscordGuild,
|
|
||||||
type DiscordMemberWithUser,
|
|
||||||
type DiscordSticker,
|
|
||||||
type ExplicitContentFilterLevels,
|
|
||||||
type GuildFeatures,
|
|
||||||
type GuildNsfwLevel,
|
|
||||||
type MfaLevels,
|
|
||||||
type PremiumTiers,
|
|
||||||
type RequestGuildMembers,
|
|
||||||
type SystemChannelFlags,
|
|
||||||
type VerificationLevels,
|
|
||||||
} from '@discordeno/types'
|
|
||||||
import Base from '../../Base.js'
|
|
||||||
import type Client from '../../Client.js'
|
|
||||||
import type { ImageFormat, ImageSize } from '../../Client.js'
|
|
||||||
import Collection from '../../Collection.js'
|
|
||||||
import { BANNER, GUILD_DISCOVERY_SPLASH, GUILD_ICON, GUILD_SPLASH } from '../../Endpoints.js'
|
|
||||||
import type Shard from '../../gateway/Shard.js'
|
|
||||||
import type {
|
|
||||||
AnyGuildChannel,
|
|
||||||
AnyThreadChannel,
|
|
||||||
ApplicationCommand,
|
|
||||||
ApplicationCommandPermissions,
|
|
||||||
ApplicationCommandStructure,
|
|
||||||
ChannelPosition,
|
|
||||||
CreateChannelOptions,
|
|
||||||
CreateStickerOptions,
|
|
||||||
DiscoveryMetadata,
|
|
||||||
DiscoveryOptions,
|
|
||||||
DiscoverySubcategoryResponse,
|
|
||||||
EditStickerOptions,
|
|
||||||
Emoji,
|
|
||||||
EmojiOptions,
|
|
||||||
GetGuildAuditLogOptions,
|
|
||||||
GetGuildBansOptions,
|
|
||||||
GetPruneOptions,
|
|
||||||
GetRESTGuildMembersOptions,
|
|
||||||
GuildApplicationCommandPermissions,
|
|
||||||
GuildAuditLog,
|
|
||||||
GuildBan,
|
|
||||||
GuildOptions,
|
|
||||||
GuildTemplateOptions,
|
|
||||||
GuildVanity,
|
|
||||||
IntegrationOptions,
|
|
||||||
ListedGuildThreads,
|
|
||||||
MemberOptions,
|
|
||||||
PruneMemberOptions,
|
|
||||||
RoleOptions,
|
|
||||||
Sticker,
|
|
||||||
VoiceRegion,
|
|
||||||
VoiceStateOptions,
|
|
||||||
Webhook,
|
|
||||||
WelcomeScreen,
|
|
||||||
WelcomeScreenOptions,
|
|
||||||
Widget,
|
|
||||||
WidgetData,
|
|
||||||
} from '../../typings.js'
|
|
||||||
import { generateChannelFrom } from '../../utils/generate.js'
|
|
||||||
import type CategoryChannel from '../channels/Category.js'
|
|
||||||
import type GuildChannel from '../channels/Guild.js'
|
|
||||||
import type StageChannel from '../channels/Stage.js'
|
|
||||||
import type TextChannel from '../channels/Text.js'
|
|
||||||
import type TextVoiceChannel from '../channels/TextVoice.js'
|
|
||||||
import type ThreadChannel from '../channels/threads/Thread.js'
|
|
||||||
import type VoiceChannel from '../channels/Voice.js'
|
|
||||||
import type Invite from '../Invite.js'
|
|
||||||
import Permission from '../Permission.js'
|
|
||||||
import User from '../users/User.js'
|
|
||||||
import type GuildIntegration from './Integration.js'
|
|
||||||
import Member from './Member.js'
|
|
||||||
import Role from './Role.js'
|
|
||||||
import StageInstance from './StageInstance.js'
|
|
||||||
import type GuildTemplate from './Template.js'
|
|
||||||
import type { VoiceState } from './VoiceState.js'
|
|
||||||
|
|
||||||
export class Guild extends Base {
|
|
||||||
/** The client object */
|
|
||||||
client: Client
|
|
||||||
/** The id of the guild owner. */
|
|
||||||
ownerID: string
|
|
||||||
/** The id of the application. */
|
|
||||||
applicationID?: string | null
|
|
||||||
/** The id of the widget channel. */
|
|
||||||
widgetChannelID?: string | null
|
|
||||||
/** The afk channel id if one is set. */
|
|
||||||
afkChannelID?: string | null
|
|
||||||
/** The system channel id if one is set. */
|
|
||||||
systemChannelID?: string | null
|
|
||||||
/** The public updates channel id if one is set. */
|
|
||||||
publicUpdatesChannelID?: string | null
|
|
||||||
/** The rules channel id if one is set. */
|
|
||||||
rulesChannelID?: string | null
|
|
||||||
/** The name of the guild. */
|
|
||||||
name?: string
|
|
||||||
/** The description of the guild. */
|
|
||||||
description?: string | null
|
|
||||||
/** The vanity url if one is set. */
|
|
||||||
vanityURL?: string | null
|
|
||||||
/** The preferred locale of the server. */
|
|
||||||
preferredLocale?: string
|
|
||||||
/** The system channel flags. */
|
|
||||||
systemChannelFlags?: SystemChannelFlags
|
|
||||||
/** The verification level of the guild. */
|
|
||||||
verificationLevel?: VerificationLevels
|
|
||||||
/** The default notification level. */
|
|
||||||
defaultNotifications?: DefaultMessageNotificationLevels
|
|
||||||
/** The explicit content filter setting for this guild. */
|
|
||||||
explicitContentFilter?: ExplicitContentFilterLevels
|
|
||||||
/** Array of guild features */
|
|
||||||
features: GuildFeatures[] = []
|
|
||||||
/** The premium tier of the guild. */
|
|
||||||
premiumTier?: PremiumTiers
|
|
||||||
/** The MFA level of the guild. */
|
|
||||||
mfaLevel?: MfaLevels
|
|
||||||
/** The NSFW level of the guild. */
|
|
||||||
nsfwLevel?: GuildNsfwLevel
|
|
||||||
/** The compressed form of the guild splash image. */
|
|
||||||
_splash?: bigint
|
|
||||||
/** The compressed form of the guild's discovery splash image. */
|
|
||||||
_discoverySplash?: bigint
|
|
||||||
/** The compressed form of the guild's banner image. */
|
|
||||||
_banner?: bigint
|
|
||||||
/** The compressed form of the guild's icon image. */
|
|
||||||
_icon?: bigint
|
|
||||||
/** The cached emojis in the guild. */
|
|
||||||
emojis?: DiscordEmoji[]
|
|
||||||
/** The cached stickers in the guild. */
|
|
||||||
stickers?: DiscordSticker[]
|
|
||||||
/** The afk timeout in seconds. */
|
|
||||||
afkTimeout?: number
|
|
||||||
/** When this guild was joined at. */
|
|
||||||
joinedAt: number
|
|
||||||
/** The amount of members in the guild. */
|
|
||||||
memberCount: number
|
|
||||||
/** The approximate member count in the guild. */
|
|
||||||
approximateMemberCount?: number
|
|
||||||
/** The approximate presence count in the guild. */
|
|
||||||
approximatePresenceCount?: number
|
|
||||||
/** The amount of subscribers to the server. */
|
|
||||||
premiumSubscriptionCount?: number
|
|
||||||
/** The maximum amount of presences that can be in a guild. */
|
|
||||||
maxPresences?: number | null
|
|
||||||
/** The maximum amount of members that can be in the guild. */
|
|
||||||
maxMembers?: number
|
|
||||||
/** The maximum amount of members that can be in a video channel. */
|
|
||||||
maxVideoChannelUsers?: number | null
|
|
||||||
/** Whether or not this guild is unavailable. */
|
|
||||||
unavailable: boolean
|
|
||||||
/** Whether or not the widget is enabled in this guild. */
|
|
||||||
widgetEnabled: boolean
|
|
||||||
/** Whether or not this guild is considered large. */
|
|
||||||
large?: boolean
|
|
||||||
/** Whether or not the premium progress bar is enabled. */
|
|
||||||
premiumProgressBarEnabled?: boolean
|
|
||||||
/** Whether or not this server is nsfw. */
|
|
||||||
nsfw?: boolean
|
|
||||||
/** The welcome screen settings. */
|
|
||||||
welcomeScreen?: {
|
|
||||||
description: string | null
|
|
||||||
welcomeChannels?: Array<{
|
|
||||||
channelID: string
|
|
||||||
description: string
|
|
||||||
emojiID: string | null
|
|
||||||
emojiName: string | null
|
|
||||||
}>
|
|
||||||
}
|
|
||||||
|
|
||||||
/** The cached members in this guild. */
|
|
||||||
members = new Collection<BigString, Member>()
|
|
||||||
/** The cached roles in this guild. */
|
|
||||||
roles = new Collection<BigString, Role>()
|
|
||||||
/** The cached channels in this guild. */
|
|
||||||
channels = new Collection<BigString, GuildChannel>()
|
|
||||||
/** The cached threads in this guild. */
|
|
||||||
threads = new Collection<BigString, ThreadChannel>()
|
|
||||||
/** The cached voice states in this guild. */
|
|
||||||
voiceStates = new Collection<BigString, VoiceState>()
|
|
||||||
/** The cached stage instances in this guild. */
|
|
||||||
stageInstances = new Collection<BigString, StageInstance>()
|
|
||||||
/** The shard that manages this guild. */
|
|
||||||
shard: Shard;
|
|
||||||
|
|
||||||
constructor(data: DiscordGuild, client: Client) {
|
|
||||||
super(data.id)
|
|
||||||
this.client = client
|
|
||||||
this.shard = client.shards.get(client.guildShardMap[this.id] || (Base.getDiscordEpoch(data.id) % (client.options.maxShards as number)) || 0)!;
|
|
||||||
|
|
||||||
this.ownerID = data.owner_id
|
|
||||||
|
|
||||||
this.unavailable = !!data.unavailable
|
|
||||||
this.joinedAt = Date.parse(data.joined_at!)
|
|
||||||
this.memberCount = data.member_count ?? 0
|
|
||||||
this.applicationID = data.application_id
|
|
||||||
this.widgetEnabled = !!data.widget_enabled
|
|
||||||
|
|
||||||
if (data.widget_channel_id !== undefined) {
|
|
||||||
this.widgetChannelID = data.widget_channel_id
|
|
||||||
}
|
|
||||||
|
|
||||||
if (data.approximate_member_count !== undefined) {
|
|
||||||
this.approximateMemberCount = data.approximate_member_count
|
|
||||||
}
|
|
||||||
if (data.approximate_presence_count !== undefined) {
|
|
||||||
this.approximatePresenceCount = data.approximate_presence_count
|
|
||||||
}
|
|
||||||
|
|
||||||
if (data.roles) {
|
|
||||||
for (const r of data.roles) {
|
|
||||||
const role = new Role(r, this)
|
|
||||||
this.roles.set(role.id, role)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (data.channels) {
|
|
||||||
for (const channelData of data.channels) {
|
|
||||||
channelData.guild_id = this.id.toString()
|
|
||||||
const channel = generateChannelFrom(channelData, client) as GuildChannel
|
|
||||||
this.channels.set(channel.id, channel)
|
|
||||||
client._channelGuildMap.set(channel.id, this.id)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (data.threads) {
|
|
||||||
for (const threadData of data.threads) {
|
|
||||||
threadData.guild_id = this.id.toString()
|
|
||||||
const thread = generateChannelFrom(threadData, client) as unknown as ThreadChannel
|
|
||||||
this.threads.set(thread.id, thread)
|
|
||||||
client._threadGuildMap.set(thread.id, this.id)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (data.members) {
|
|
||||||
for (const m of data.members) {
|
|
||||||
const member = new Member(m as DiscordMemberWithUser, this, client)
|
|
||||||
this.members.set(member.id, member)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (data.stage_instances) {
|
|
||||||
for (const stageInstance of data.stage_instances) {
|
|
||||||
stageInstance.guild_id = this.id
|
|
||||||
|
|
||||||
const instance = new StageInstance(stageInstance, client)
|
|
||||||
this.stageInstances.set(instance.id, instance)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (data.presences) {
|
|
||||||
for (const presence of data.presences) {
|
|
||||||
if (presence.user?.id) {
|
|
||||||
const cached = this.client.users.get(presence.user.id)
|
|
||||||
if (cached) cached.update(presence.user)
|
|
||||||
else {
|
|
||||||
const user = new User(presence.user, this.client)
|
|
||||||
this.client.users.set(user.id, user)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (data.voice_states) {
|
|
||||||
for (const voiceState of data.voice_states) {
|
|
||||||
if (!this.members.get(voiceState.user_id)) continue
|
|
||||||
|
|
||||||
if (voiceState.member) {
|
|
||||||
const member = new Member(voiceState.member, this, client)
|
|
||||||
this.members.set(member.id, member)
|
|
||||||
const user = new User(voiceState.member.user, client)
|
|
||||||
this.client.users.set(user.id, user)
|
|
||||||
|
|
||||||
// TODO: check channel type maybe voice channel?
|
|
||||||
;(this.channels.get(voiceState.channel_id!) as VoiceChannel)?.voiceMembers.set(member.id, member)
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: voice support
|
|
||||||
// if (
|
|
||||||
// client.options.seedVoiceConnections &&
|
|
||||||
// voiceState.user_id === client.id &&
|
|
||||||
// !client.voiceConnections.get(this.id)
|
|
||||||
// ) {
|
|
||||||
// process.nextTick(() =>
|
|
||||||
// this.client.joinVoiceChannel(voiceState.channel_id)
|
|
||||||
// );
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
this.update(data)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @deprecated - please use .client
|
|
||||||
*/
|
|
||||||
get _client() {
|
|
||||||
return this.client
|
|
||||||
}
|
|
||||||
|
|
||||||
update(data: DiscordGuild) {
|
|
||||||
if (data.name !== undefined) {
|
|
||||||
this.name = data.name
|
|
||||||
}
|
|
||||||
if (data.verification_level !== undefined) {
|
|
||||||
this.verificationLevel = data.verification_level
|
|
||||||
}
|
|
||||||
if (data.splash !== undefined) {
|
|
||||||
this._splash = data.splash ? this.client.iconHashToBigInt(data.splash) : undefined
|
|
||||||
}
|
|
||||||
|
|
||||||
if (data.discovery_splash !== undefined) {
|
|
||||||
this._discoverySplash = data.discovery_splash ? this.client.iconHashToBigInt(data.discovery_splash) : undefined
|
|
||||||
}
|
|
||||||
|
|
||||||
if (data.banner !== undefined) {
|
|
||||||
this._banner = data.banner ? this.client.iconHashToBigInt(data.banner) : undefined
|
|
||||||
}
|
|
||||||
|
|
||||||
if (data.owner_id !== undefined) {
|
|
||||||
this.ownerID = data.owner_id
|
|
||||||
}
|
|
||||||
|
|
||||||
if (data.icon !== undefined) {
|
|
||||||
this._icon = data.icon ? this.client.iconHashToBigInt(data.icon) : undefined
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: compress features.
|
|
||||||
if (data.features !== undefined) {
|
|
||||||
this.features = data.features
|
|
||||||
}
|
|
||||||
|
|
||||||
if (data.emojis !== undefined) {
|
|
||||||
this.emojis = data.emojis
|
|
||||||
}
|
|
||||||
|
|
||||||
if (data.stickers !== undefined) {
|
|
||||||
this.stickers = data.stickers
|
|
||||||
}
|
|
||||||
|
|
||||||
if (data.afk_channel_id !== undefined) {
|
|
||||||
this.afkChannelID = data.afk_channel_id
|
|
||||||
}
|
|
||||||
|
|
||||||
if (data.afk_timeout !== undefined) {
|
|
||||||
this.afkTimeout = data.afk_timeout
|
|
||||||
}
|
|
||||||
|
|
||||||
if (data.default_message_notifications !== undefined) {
|
|
||||||
this.defaultNotifications = data.default_message_notifications
|
|
||||||
}
|
|
||||||
|
|
||||||
if (data.mfa_level !== undefined) {
|
|
||||||
this.mfaLevel = data.mfa_level
|
|
||||||
}
|
|
||||||
|
|
||||||
if (data.large !== undefined) {
|
|
||||||
this.large = data.large
|
|
||||||
}
|
|
||||||
|
|
||||||
if (data.max_presences !== undefined) {
|
|
||||||
this.maxPresences = data.max_presences
|
|
||||||
}
|
|
||||||
|
|
||||||
if (data.explicit_content_filter !== undefined) {
|
|
||||||
this.explicitContentFilter = data.explicit_content_filter
|
|
||||||
}
|
|
||||||
|
|
||||||
if (data.system_channel_id !== undefined) {
|
|
||||||
this.systemChannelID = data.system_channel_id
|
|
||||||
}
|
|
||||||
|
|
||||||
if (data.system_channel_flags !== undefined) {
|
|
||||||
this.systemChannelFlags = data.system_channel_flags
|
|
||||||
}
|
|
||||||
if (data.premium_progress_bar_enabled !== undefined) {
|
|
||||||
this.premiumProgressBarEnabled = data.premium_progress_bar_enabled
|
|
||||||
}
|
|
||||||
if (data.premium_tier !== undefined) {
|
|
||||||
this.premiumTier = data.premium_tier
|
|
||||||
}
|
|
||||||
if (data.premium_subscription_count !== undefined) {
|
|
||||||
this.premiumSubscriptionCount = data.premium_subscription_count
|
|
||||||
}
|
|
||||||
if (data.vanity_url_code !== undefined) {
|
|
||||||
this.vanityURL = data.vanity_url_code
|
|
||||||
}
|
|
||||||
if (data.preferred_locale !== undefined) {
|
|
||||||
this.preferredLocale = data.preferred_locale
|
|
||||||
}
|
|
||||||
if (data.description !== undefined) {
|
|
||||||
this.description = data.description
|
|
||||||
}
|
|
||||||
if (data.max_members !== undefined) {
|
|
||||||
this.maxMembers = data.max_members
|
|
||||||
}
|
|
||||||
if (data.public_updates_channel_id !== undefined) {
|
|
||||||
this.publicUpdatesChannelID = data.public_updates_channel_id
|
|
||||||
}
|
|
||||||
if (data.rules_channel_id !== undefined) {
|
|
||||||
this.rulesChannelID = data.rules_channel_id
|
|
||||||
}
|
|
||||||
if (data.max_video_channel_users !== undefined) {
|
|
||||||
this.maxVideoChannelUsers = data.max_video_channel_users
|
|
||||||
}
|
|
||||||
if (data.welcome_screen !== undefined) {
|
|
||||||
this.welcomeScreen = {
|
|
||||||
description: data.welcome_screen.description,
|
|
||||||
welcomeChannels: data.welcome_screen.welcome_channels?.map((c) => {
|
|
||||||
return {
|
|
||||||
channelID: c.channel_id,
|
|
||||||
description: c.description,
|
|
||||||
emojiID: c.emoji_id,
|
|
||||||
emojiName: c.emoji_name,
|
|
||||||
}
|
|
||||||
}),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// if (data.nsfw !== undefined) {
|
|
||||||
// this.nsfw = data.nsfw;
|
|
||||||
// }
|
|
||||||
if (data.nsfw_level !== undefined) {
|
|
||||||
this.nsfwLevel = data.nsfw_level
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
get banner(): string | undefined {
|
|
||||||
return this._banner ? this.client.iconBigintToHash(this._banner) : undefined
|
|
||||||
}
|
|
||||||
|
|
||||||
get bannerURL(): string | null {
|
|
||||||
return this.banner ? this.client._formatImage(BANNER(this.id, this.banner)) : null
|
|
||||||
}
|
|
||||||
|
|
||||||
get icon(): string | undefined {
|
|
||||||
return this._icon ? this.client.iconBigintToHash(this._icon) : undefined
|
|
||||||
}
|
|
||||||
|
|
||||||
get iconURL(): string | null {
|
|
||||||
return this.icon ? this.client._formatImage(GUILD_ICON(this.id, this.icon)) : null
|
|
||||||
}
|
|
||||||
|
|
||||||
get splash(): string | undefined {
|
|
||||||
return this._splash ? this.client.iconBigintToHash(this._splash) : undefined
|
|
||||||
}
|
|
||||||
|
|
||||||
get splashURL(): string | null {
|
|
||||||
return this.splash ? this.client._formatImage(GUILD_SPLASH(this.id, this.splash)) : null
|
|
||||||
}
|
|
||||||
|
|
||||||
get discoverySplash(): string | undefined {
|
|
||||||
return this._discoverySplash ? this.client.iconBigintToHash(this._discoverySplash) : undefined
|
|
||||||
}
|
|
||||||
|
|
||||||
get discoverySplashURL(): string | null {
|
|
||||||
return this.discoverySplash ? this.client._formatImage(GUILD_DISCOVERY_SPLASH(this.id, this.discoverySplash)) : null
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Add a discovery subcategory */
|
|
||||||
async addDiscoverySubcategory(categoryID: BigString, reason?: string): Promise<DiscoverySubcategoryResponse> {
|
|
||||||
return await this.client.addGuildDiscoverySubcategory.call(this.client, this.id, categoryID, reason)
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Add a role to a guild member */
|
|
||||||
async addMemberRole(memberID: BigString, roleID: BigString, reason?: string): Promise<void> {
|
|
||||||
return await this.client.addGuildMemberRole.call(this.client, this.id, memberID, roleID, reason)
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Ban a user from the guild */
|
|
||||||
async banMember(userID: BigString, deleteMessageDays = 0, reason?: string): Promise<void> {
|
|
||||||
return await this.client.banGuildMember.call(this.client, this.id, userID, deleteMessageDays, reason)
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Bulk create/edit guild application commands */
|
|
||||||
async bulkEditCommands(commands: Array<ApplicationCommand<ApplicationCommandTypes>>): Promise<Array<ApplicationCommand<ApplicationCommandTypes>>> {
|
|
||||||
return await this.client.bulkEditGuildCommands.call(this.client, this.id, commands)
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Create a channel in the guild */
|
|
||||||
async createChannel(
|
|
||||||
name: string,
|
|
||||||
type = ChannelTypes.GuildText,
|
|
||||||
options: CreateChannelOptions,
|
|
||||||
): Promise<CategoryChannel | TextChannel | TextVoiceChannel | StageChannel> {
|
|
||||||
return await this.client.createChannel.call(this.client, this.id, name, type as number, options)
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Create a guild application command */
|
|
||||||
async createCommand(command: ApplicationCommandStructure): Promise<ApplicationCommand<ApplicationCommandTypes>> {
|
|
||||||
return await this.client.createGuildCommand.call(this.client, this.id, command)
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Create a emoji in the guild */
|
|
||||||
async createEmoji(options: EmojiOptions, reason?: string): Promise<Emoji> {
|
|
||||||
return await this.client.createGuildEmoji.call(this.client, this.id, options, reason)
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Create a guild role */
|
|
||||||
async createRole(options: Role | RoleOptions, reason?: string): Promise<Role> {
|
|
||||||
return await this.client.createRole.call(this.client, this.id, options, reason)
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Create a guild sticker */
|
|
||||||
async createSticker(options: CreateStickerOptions, reason?: string): Promise<Sticker> {
|
|
||||||
return await this.client.createGuildSticker.call(this.client, this.id, options, reason)
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Create a template for this guild */
|
|
||||||
async createTemplate(name: string, description?: string): Promise<GuildTemplate> {
|
|
||||||
return await this.client.createGuildTemplate.call(this.client, this.id, name, description)
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Delete the guild (bot user must be owner) */
|
|
||||||
async delete(): Promise<void> {
|
|
||||||
if (this.ownerID !== this.client.id) throw new Error('To delete a guild, the bot must be the owner of the guild.')
|
|
||||||
|
|
||||||
return await this.client.deleteGuild.call(this.client, this.id)
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Delete a guild application command */
|
|
||||||
async deleteCommand(commandID: BigString): Promise<void> {
|
|
||||||
return await this.client.deleteGuildCommand.call(this.client, this.id, commandID)
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Delete a discovery subcategory */
|
|
||||||
async deleteDiscoverySubcategory(categoryID: BigString, reason?: string): Promise<void> {
|
|
||||||
return await this.client.deleteGuildDiscoverySubcategory.call(this.client, this.id, categoryID, reason)
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Delete a emoji in the guild */
|
|
||||||
async deleteEmoji(emojiID: BigString, reason?: string): Promise<void> {
|
|
||||||
return await this.client.deleteGuildEmoji.call(this.client, this.id, emojiID, reason)
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Delete a guild integration */
|
|
||||||
async deleteIntegration(integrationID: BigString): Promise<void> {
|
|
||||||
return await this.client.deleteGuildIntegration.call(this.client, this.id, integrationID)
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Delete a role */
|
|
||||||
async deleteRole(roleID: BigString, reason?: string): Promise<void> {
|
|
||||||
return await this.client.deleteRole.call(this.client, this.id, roleID, reason)
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Delete a guild sticker */
|
|
||||||
async deleteSticker(stickerID: BigString, reason?: string): Promise<void> {
|
|
||||||
return await this.client.deleteGuildSticker.call(this.client, this.id, stickerID, reason)
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Delete a guild template */
|
|
||||||
async deleteTemplate(code: string): Promise<void> {
|
|
||||||
return await this.client.deleteGuildTemplate.call(this.client, this.id, code)
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Get the guild's banner with the given format and size */
|
|
||||||
dynamicBannerURL(format?: ImageFormat, size?: ImageSize): string | null {
|
|
||||||
return this.banner ? this.client._formatImage(BANNER(this.id, this.banner), format, size) : null
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Get the guild's discovery splash with the given format and size */
|
|
||||||
dynamicDiscoverySplashURL(format?: ImageFormat, size?: ImageSize): string | null {
|
|
||||||
return this.discoverySplash ? this.client._formatImage(GUILD_DISCOVERY_SPLASH(this.id, this.discoverySplash), format, size) : null
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Get the guild's icon with the given format and size */
|
|
||||||
dynamicIconURL(format?: ImageFormat, size?: ImageSize): string | null {
|
|
||||||
return this.icon ? this.client._formatImage(GUILD_ICON(this.id, this.icon), format, size) : null
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Get the guild's splash with the given format and size */
|
|
||||||
dynamicSplashURL(format?: ImageFormat, size?: ImageSize): string | null {
|
|
||||||
return this.splash ? this.client._formatImage(GUILD_SPLASH(this.id, this.splash), format, size) : null
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Edit the guild */
|
|
||||||
async edit(options: GuildOptions, reason?: string): Promise<Guild> {
|
|
||||||
return await this.client.editGuild.call(this.client, this.id, options, reason)
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Edit multiple channels' positions. Note that channel position numbers are grouped by type (category, text, voice), then sorted in ascending order (lowest number is on top). */
|
|
||||||
async editChannelPositions(channelPositions: ChannelPosition[]): Promise<void> {
|
|
||||||
return await this.client.editChannelPositions.call(this.client, this.id, channelPositions)
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Edit a guild application command */
|
|
||||||
async editCommand(commandID: BigString, commands: ApplicationCommandStructure): Promise<ApplicationCommand<ApplicationCommandTypes>> {
|
|
||||||
return await this.client.editGuildCommand.call(this.client, this.id, commandID, commands)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Edits command permissions for a specific command in a guild.
|
|
||||||
* Note: You can only add up to 10 permission overwrites for a command.
|
|
||||||
*/
|
|
||||||
async editCommandPermissions(commandID: BigString, permissions: ApplicationCommandPermissions[]): Promise<GuildApplicationCommandPermissions> {
|
|
||||||
return await this.client.editCommandPermissions.call(this.client, this.id, commandID, permissions)
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Edit the guild's discovery data */
|
|
||||||
async editDiscovery(options: DiscoveryOptions): Promise<DiscoveryMetadata> {
|
|
||||||
return await this.client.editGuildDiscovery.call(this.client, this.id, options)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Edit a emoji in the guild
|
|
||||||
* @arg {String} emojiID The ID of the emoji you want to modify
|
|
||||||
* @arg {Object} options Emoji options
|
|
||||||
* @arg {String} [options.name] The name of emoji
|
|
||||||
* @arg {Array} [options.roles] An array containing authorized role IDs
|
|
||||||
* @arg {String} [reason] The reason to be displayed in audit logs
|
|
||||||
* @returns {Promise<Object>} A guild emoji object
|
|
||||||
*/
|
|
||||||
async editEmoji(
|
|
||||||
emojiID: BigString,
|
|
||||||
options: {
|
|
||||||
name?: string | undefined
|
|
||||||
roles?: string[] | undefined
|
|
||||||
},
|
|
||||||
reason?: string,
|
|
||||||
): Promise<Emoji> {
|
|
||||||
return await this.client.editGuildEmoji.call(this.client, this.id, emojiID, options, reason)
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Edit a guild integration */
|
|
||||||
async editIntegration(integrationID: BigString, options: IntegrationOptions): Promise<void> {
|
|
||||||
return await this.client.editGuildIntegration.call(this.client, this.id, integrationID, options)
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Edit a guild member */
|
|
||||||
async editMember(memberID: BigString, options: MemberOptions, reason?: string): Promise<Member> {
|
|
||||||
return await this.client.editGuildMember.call(this.client, this.id, memberID, options, reason)
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Edit the guild role */
|
|
||||||
async editRole(roleID: BigString, options: RoleOptions, reason?: string): Promise<Role> {
|
|
||||||
return await this.client.editRole.call(this.client, this.id, roleID, options, reason)
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Edit a guild sticker */
|
|
||||||
async editSticker(stickerID: BigString, options: EditStickerOptions, reason?: string): Promise<Sticker> {
|
|
||||||
return await this.client.editGuildSticker.call(this.client, this.id, stickerID, options, reason)
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Edit a guild template */
|
|
||||||
async editTemplate(code: string, options: GuildTemplateOptions): Promise<GuildTemplate> {
|
|
||||||
return await this.client.editGuildTemplate.call(this.client, this.id, code, options)
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Modify the guild's vanity code */
|
|
||||||
async editVanity(code: string | null): Promise<unknown> {
|
|
||||||
return await this.client.editGuildVanity.call(this.client, this.id, code)
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Update a user's voice state - See [caveats](https://discord.com/developers/docs/resources/guild#modify-user-voice-state-caveats) */
|
|
||||||
async editVoiceState(options: VoiceStateOptions, userID: BigString = '@me'): Promise<void> {
|
|
||||||
return await this.client.editGuildVoiceState.call(this.client, this.id, options, userID)
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Edit the guild welcome screen */
|
|
||||||
async editWelcomeScreen(options: WelcomeScreenOptions): Promise<WelcomeScreen> {
|
|
||||||
return await this.client.editGuildWelcomeScreen.call(this.client, this.id, options)
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Modify a guild's widget */
|
|
||||||
async editWidget(options: Widget): Promise<Widget> {
|
|
||||||
return await this.client.editGuildWidget.call(this.client, this.id, options)
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Request all guild members from Discord */
|
|
||||||
async fetchAllMembers(timeout?: number): Promise<number> {
|
|
||||||
return await this.fetchMembers({
|
|
||||||
guildId: this.id,
|
|
||||||
limit: 0,
|
|
||||||
}).then((m: any[]) => m.length)
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Request specific guild members through the gateway connection */
|
|
||||||
async fetchMembers(options: RequestGuildMembers): Promise<Member[]> {
|
|
||||||
// TODO: Use gateway fetch
|
|
||||||
return await this.client.getRESTGuildMembers(this.id, options)
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Get all active threads in this guild */
|
|
||||||
async getActiveThreads(): Promise<ListedGuildThreads<AnyThreadChannel>> {
|
|
||||||
return await this.client.getActiveGuildThreads.call(this.client, this.id)
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Get the audit log for the guild */
|
|
||||||
async getAuditLog(options: GetGuildAuditLogOptions): Promise<GuildAuditLog> {
|
|
||||||
return await this.client.getGuildAuditLog.call(this.client, this.id, options)
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Get a ban from the ban list of a guild */
|
|
||||||
async getBan(userID: BigString): Promise<GuildBan> {
|
|
||||||
return await this.client.getGuildBan.call(this.client, this.id, userID)
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Get the ban list of the guild */
|
|
||||||
async getBans(options?: GetGuildBansOptions): Promise<GuildBan[]> {
|
|
||||||
return await this.client.getGuildBans.call(this.client, this.id, options)
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Get a guild application command */
|
|
||||||
async getCommand(commandID: BigString): Promise<ApplicationCommand<ApplicationCommandTypes>> {
|
|
||||||
return await this.client.getGuildCommand.call(this.client, this.id, commandID)
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Get the a guild's application command permissions */
|
|
||||||
async getCommandPermissions(commandID: BigString): Promise<GuildApplicationCommandPermissions> {
|
|
||||||
return await this.client.getCommandPermissions.call(this.client, this.id, commandID)
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Get the guild's application commands */
|
|
||||||
async getCommands(): Promise<ApplicationCommand<ApplicationCommandTypes>> {
|
|
||||||
return await this.client.getGuildCommands.call(this.client, this.id)
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Get the guild's discovery object */
|
|
||||||
async getDiscovery(): Promise<DiscoveryMetadata> {
|
|
||||||
return await this.client.getGuildDiscovery.call(this.client, this.id)
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Get the all of a guild's application command permissions */
|
|
||||||
async getGuildCommandPermissions(): Promise<GuildApplicationCommandPermissions[]> {
|
|
||||||
return await this.client.getGuildCommandPermissions.call(this.client, this.id)
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Get a list of integrations for the guild */
|
|
||||||
async getIntegrations(): Promise<GuildIntegration[]> {
|
|
||||||
return await this.client.getGuildIntegrations.call(this.client, this.id)
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Get all invites in the guild */
|
|
||||||
async getInvites(): Promise<Invite[]> {
|
|
||||||
return await this.client.getGuildInvites.call(this.client, this.id)
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Get the prune count for the guild */
|
|
||||||
async getPruneCount(options: GetPruneOptions): Promise<number> {
|
|
||||||
return await this.client.getPruneCount.call(this.client, this.id, options)
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Get a guild's channels via the REST API. REST mode is required to use this endpoint. */
|
|
||||||
async getRESTChannels(): Promise<AnyGuildChannel[]> {
|
|
||||||
return await this.client.getRESTGuildChannels.call(this.client, this.id)
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Get a guild emoji via the REST API. REST mode is required to use this endpoint. */
|
|
||||||
async getRESTEmoji(emojiID: BigString): Promise<Emoji> {
|
|
||||||
return await this.client.getRESTGuildEmoji.call(this.client, this.id, emojiID)
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Get a guild's emojis via the REST API. REST mode is required to use this endpoint. */
|
|
||||||
async getRESTEmojis(): Promise<Emoji[]> {
|
|
||||||
return await this.client.getRESTGuildEmojis.call(this.client, this.id)
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Get a guild's members via the REST API. REST mode is required to use this endpoint. */
|
|
||||||
async getRESTMember(memberID: BigString): Promise<Member> {
|
|
||||||
return await this.client.getRESTGuildMember.call(this.client, this.id, memberID)
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Get a guild's members via the REST API. REST mode is required to use this endpoint. */
|
|
||||||
async getRESTMembers(options?: GetRESTGuildMembersOptions): Promise<Member[]> {
|
|
||||||
return await this.client.getRESTGuildMembers.call(this.client, this.id, options)
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Get a guild's roles via the REST API. REST mode is required to use this endpoint. */
|
|
||||||
async getRESTRoles(): Promise<Role[]> {
|
|
||||||
return await this.client.getRESTGuildRoles.call(this.client, this.id)
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Get a guild sticker via the REST API. REST mode is required to use this endpoint. */
|
|
||||||
async getRESTSticker(stickerID: BigString): Promise<Sticker> {
|
|
||||||
return await this.client.getRESTGuildSticker.call(this.client, this.id, stickerID)
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Get a guild's stickers via the REST API. REST mode is required to use this endpoint. */
|
|
||||||
async getRESTStickers(): Promise<Sticker[]> {
|
|
||||||
return await this.client.getRESTGuildStickers.call(this.client, this.id)
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Get the guild's templates */
|
|
||||||
async getTemplates(): Promise<GuildTemplate[]> {
|
|
||||||
return await this.client.getGuildTemplates.call(this.client, this.id)
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Returns the vanity url of the guild */
|
|
||||||
async getVanity(): Promise<GuildVanity> {
|
|
||||||
return await this.client.getGuildVanity.call(this.client, this.id)
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Get possible voice regions for a guild */
|
|
||||||
async getVoiceRegions(): Promise<VoiceRegion[]> {
|
|
||||||
return await this.client.getVoiceRegions.call(this.client, this.id)
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Get all the webhooks in the guild */
|
|
||||||
async getWebhooks(): Promise<Webhook[]> {
|
|
||||||
return await this.client.getGuildWebhooks.call(this.client, this.id)
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Get the welcome screen of the Community guild, shown to new members */
|
|
||||||
async getWelcomeScreen(): Promise<WelcomeScreen> {
|
|
||||||
return await this.client.getGuildWelcomeScreen.call(this.client, this.id)
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Get a guild's widget object */
|
|
||||||
async getWidget(): Promise<WidgetData> {
|
|
||||||
return await this.client.getGuildWidget.call(this.client, this.id)
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Get a guild's widget settings object */
|
|
||||||
async getWidgetSettings(): Promise<Widget> {
|
|
||||||
return await this.client.getGuildWidgetSettings.call(this.client, this.id)
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Kick a member from the guild */
|
|
||||||
async kickMember(userID: BigString, reason?: string): Promise<void> {
|
|
||||||
return await this.client.kickGuildMember.call(this.client, this.id, userID, reason)
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Leave the guild */
|
|
||||||
async leave(): Promise<void> {
|
|
||||||
return await this.client.leaveGuild.call(this.client, this.id)
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: gateway voice
|
|
||||||
// /** Leaves the voice channel in this guild */
|
|
||||||
// async leaveVoiceChannel(): Promise<void> {
|
|
||||||
// return await this.client.closeVoiceConnection.call(this.client, this.id);
|
|
||||||
// }
|
|
||||||
|
|
||||||
/** Get the guild permissions of a member */
|
|
||||||
permissionsOf(memberID: BigString | Member): Permission {
|
|
||||||
const member = ['string', 'bigint'].includes(typeof memberID) ? this.members.get(memberID as BigString)! : (memberID as Member)
|
|
||||||
if (member.id === this.ownerID) {
|
|
||||||
return new Permission(BitwisePermissionFlags.ADMINISTRATOR)
|
|
||||||
} else {
|
|
||||||
let permissions = this.roles.get(this.id)!.permissions.allow
|
|
||||||
if (permissions & BigInt(BitwisePermissionFlags.ADMINISTRATOR)) {
|
|
||||||
return new Permission(BitwisePermissionFlags.ADMINISTRATOR)
|
|
||||||
}
|
|
||||||
for (const id of member.roles) {
|
|
||||||
const role = this.roles.get(id)
|
|
||||||
if (!role) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
const { allow: perm } = role.permissions
|
|
||||||
if (perm & BigInt(BitwisePermissionFlags.ADMINISTRATOR)) {
|
|
||||||
permissions = BigInt(BitwisePermissionFlags.ADMINISTRATOR)
|
|
||||||
break
|
|
||||||
} else {
|
|
||||||
permissions |= perm
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return new Permission(permissions)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Begin pruning the guild */
|
|
||||||
async pruneMembers(options?: PruneMemberOptions): Promise<number> {
|
|
||||||
return await this.client.pruneMembers.call(this.client, this.id, options)
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Remove a role from a guild member */
|
|
||||||
async removeMemberRole(memberID: BigString, roleID: BigString, reason?: string): Promise<void> {
|
|
||||||
return await this.client.removeGuildMemberRole.call(this.client, this.id, memberID, roleID, reason)
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Search for guild members by partial nickname/username */
|
|
||||||
async searchMembers(query: string, limit = 1): Promise<Member[]> {
|
|
||||||
return await this.client.searchGuildMembers.call(this.client, this.id, query, limit)
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Force a guild integration to sync */
|
|
||||||
async syncIntegration(integrationID: BigString): Promise<void> {
|
|
||||||
return await this.client.syncGuildIntegration.call(this.client, this.id, integrationID)
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Force a guild template to sync */
|
|
||||||
async syncTemplate(code: string): Promise<GuildTemplate> {
|
|
||||||
return await this.client.syncGuildTemplate.call(this.client, this.id, code)
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Unban a user from the guild */
|
|
||||||
async unbanMember(userID: BigString, reason?: string): Promise<void> {
|
|
||||||
return await this.client.unbanGuildMember.call(this.client, this.id, userID, reason)
|
|
||||||
}
|
|
||||||
|
|
||||||
toJSON(props: string[] = []): Record<string, any> {
|
|
||||||
return super.toJSON([
|
|
||||||
'afkChannelID',
|
|
||||||
'afkTimeout',
|
|
||||||
'applicationID',
|
|
||||||
'approximateMemberCount',
|
|
||||||
'approximatePresenceCount',
|
|
||||||
'autoRemoved',
|
|
||||||
'banner',
|
|
||||||
'categories',
|
|
||||||
'channels',
|
|
||||||
'defaultNotifications',
|
|
||||||
'description',
|
|
||||||
'discoverySplash',
|
|
||||||
'emojiCount',
|
|
||||||
'emojis',
|
|
||||||
'explicitContentFilter',
|
|
||||||
'features',
|
|
||||||
'icon',
|
|
||||||
'joinedAt',
|
|
||||||
'keywords',
|
|
||||||
'large',
|
|
||||||
'maxMembers',
|
|
||||||
'maxPresences',
|
|
||||||
'maxVideoChannelUsers',
|
|
||||||
'memberCount',
|
|
||||||
'members',
|
|
||||||
'mfaLevel',
|
|
||||||
'name',
|
|
||||||
'ownerID',
|
|
||||||
'pendingVoiceStates',
|
|
||||||
'preferredLocale',
|
|
||||||
'premiumProgressBarEnabled',
|
|
||||||
'premiumSubscriptionCount',
|
|
||||||
'premiumTier',
|
|
||||||
'primaryCategory',
|
|
||||||
'primaryCategoryID',
|
|
||||||
'publicUpdatesChannelID',
|
|
||||||
'roles',
|
|
||||||
'rulesChannelID',
|
|
||||||
'splash',
|
|
||||||
'stickers',
|
|
||||||
'systemChannelFlags',
|
|
||||||
'systemChannelID',
|
|
||||||
'unavailable',
|
|
||||||
'vanityURL',
|
|
||||||
'verificationLevel',
|
|
||||||
'voiceStates',
|
|
||||||
'welcomeScreen',
|
|
||||||
'widgetChannelID',
|
|
||||||
'widgetEnabled',
|
|
||||||
...props,
|
|
||||||
])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default Guild
|
|
||||||
@@ -1,131 +0,0 @@
|
|||||||
/* eslint-disable no-useless-call */
|
|
||||||
import type { DiscordIntegration, DiscordIntegrationApplication } from '@discordeno/types'
|
|
||||||
import Base from '../../Base.js'
|
|
||||||
import type { IntegrationOptions } from '../../typings.js'
|
|
||||||
import User from '../users/User.js'
|
|
||||||
import type Guild from './Guild.js'
|
|
||||||
|
|
||||||
export class GuildIntegration extends Base {
|
|
||||||
/** The guild where this integration exists. */
|
|
||||||
guild: Guild
|
|
||||||
/** The name of the integration. */
|
|
||||||
name: string
|
|
||||||
/** The type of integration. */
|
|
||||||
type: string
|
|
||||||
/** The user connected to the integration. */
|
|
||||||
user?: User
|
|
||||||
/** Whether the integration is syncing or not. */
|
|
||||||
syncing?: boolean
|
|
||||||
/** THe Unix timestamp of last integration sync. */
|
|
||||||
syncedAt?: number
|
|
||||||
/** The number of subscribers. */
|
|
||||||
subscriberCount?: number
|
|
||||||
/** The role id of the role connected to the integration. */
|
|
||||||
roleID?: string
|
|
||||||
/** WHether or not the application was revoked. */
|
|
||||||
revoked?: boolean
|
|
||||||
/** Whether integration emoticons are enabled or not. */
|
|
||||||
enableEmoticons?: boolean
|
|
||||||
/** Behavior of expired subscriptions */
|
|
||||||
expireBehavior?: number
|
|
||||||
/** Grace period for expired subscriptions. */
|
|
||||||
expireGracePeriod?: number
|
|
||||||
/** Whether the integration is enabled or not. */
|
|
||||||
enabled?: boolean
|
|
||||||
/** The bot/oauth2 application for integration. */
|
|
||||||
application?: DiscordIntegrationApplication
|
|
||||||
|
|
||||||
/** Info on the integration account */
|
|
||||||
account: {
|
|
||||||
/** The id of the integration account. */
|
|
||||||
id: string
|
|
||||||
/** The name of the integration account. */
|
|
||||||
name: string
|
|
||||||
}
|
|
||||||
|
|
||||||
constructor(data: DiscordIntegration, guild: Guild) {
|
|
||||||
super(data.id)
|
|
||||||
|
|
||||||
this.guild = guild
|
|
||||||
this.name = data.name
|
|
||||||
this.type = data.type
|
|
||||||
|
|
||||||
if (data.role_id !== undefined) {
|
|
||||||
this.roleID = data.role_id
|
|
||||||
}
|
|
||||||
|
|
||||||
if (data.user) {
|
|
||||||
this.user = new User(data.user, guild.client)
|
|
||||||
guild.client.users.set(this.user.id, this.user)
|
|
||||||
}
|
|
||||||
|
|
||||||
this.account = data.account // not worth making a class for
|
|
||||||
|
|
||||||
this.update(data)
|
|
||||||
}
|
|
||||||
|
|
||||||
update(data: DiscordIntegration): void {
|
|
||||||
this.enabled = data.enabled
|
|
||||||
if (data.syncing !== undefined) {
|
|
||||||
this.syncing = data.syncing
|
|
||||||
}
|
|
||||||
if (data.expire_behavior !== undefined) {
|
|
||||||
this.expireBehavior = data.expire_behavior
|
|
||||||
}
|
|
||||||
if (data.expire_behavior !== undefined) {
|
|
||||||
this.expireGracePeriod = data.expire_grace_period
|
|
||||||
}
|
|
||||||
if (data.enable_emoticons) {
|
|
||||||
this.enableEmoticons = data.enable_emoticons
|
|
||||||
}
|
|
||||||
if (data.subscriber_count !== undefined) {
|
|
||||||
this.subscriberCount = data.subscriber_count
|
|
||||||
}
|
|
||||||
if (data.synced_at !== undefined) {
|
|
||||||
this.syncedAt = Date.parse(data.synced_at)
|
|
||||||
}
|
|
||||||
if (data.revoked !== undefined) {
|
|
||||||
this.revoked = data.revoked
|
|
||||||
}
|
|
||||||
if (data.application !== undefined) {
|
|
||||||
this.application = data.application
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Delete the guild integration */
|
|
||||||
async delete(): Promise<void> {
|
|
||||||
return await this.guild.client.deleteGuildIntegration.call(this.guild.client, this.guild.id, this.id)
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Edit the guild integration */
|
|
||||||
async edit(options: IntegrationOptions): Promise<void> {
|
|
||||||
return await this.guild.client.editGuildIntegration.call(this.guild.client, this.guild.id, this.id, options)
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Force the guild integration to sync */
|
|
||||||
async sync(): Promise<void> {
|
|
||||||
return await this.guild.client.syncGuildIntegration.call(this.guild.client, this.guild.id, this.id)
|
|
||||||
}
|
|
||||||
|
|
||||||
toJSON(props: string[] = []): Record<string, any> {
|
|
||||||
return super.toJSON([
|
|
||||||
'account',
|
|
||||||
'application',
|
|
||||||
'enabled',
|
|
||||||
'enableEmoticons',
|
|
||||||
'expireBehavior',
|
|
||||||
'expireGracePeriod',
|
|
||||||
'name',
|
|
||||||
'revoked',
|
|
||||||
'roleID',
|
|
||||||
'subscriberCount',
|
|
||||||
'syncedAt',
|
|
||||||
'syncing',
|
|
||||||
'type',
|
|
||||||
'user',
|
|
||||||
...props,
|
|
||||||
])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default GuildIntegration
|
|
||||||
@@ -1,222 +0,0 @@
|
|||||||
/* eslint-disable @typescript-eslint/restrict-plus-operands */
|
|
||||||
/* eslint-disable @typescript-eslint/explicit-function-return-type */
|
|
||||||
/* eslint-disable no-useless-call */
|
|
||||||
/* eslint-disable @typescript-eslint/return-await */
|
|
||||||
|
|
||||||
import type { BigString, DiscordMember, DiscordMemberWithUser } from '@discordeno/types'
|
|
||||||
import Base from '../../Base.js'
|
|
||||||
import type Client from '../../Client.js'
|
|
||||||
import type { ImageFormat, ImageSize } from '../../Client.js'
|
|
||||||
import { GUILD_AVATAR } from '../../Endpoints.js'
|
|
||||||
import type { MemberOptions, Status } from '../../typings.js'
|
|
||||||
import User from '../users/User.js'
|
|
||||||
import type Guild from './Guild.js'
|
|
||||||
|
|
||||||
export class Member extends Base {
|
|
||||||
/** The client manager */
|
|
||||||
client: Client
|
|
||||||
/** An array of role IDs this member is a part of */
|
|
||||||
roles: string[]
|
|
||||||
/** The guild the member is in */
|
|
||||||
guild: Guild
|
|
||||||
/** The user object of the member */
|
|
||||||
user: User
|
|
||||||
/** The server nickname of the member. */
|
|
||||||
nick: string | null
|
|
||||||
/** The timestamp when this member joined the server. */
|
|
||||||
joinedAt?: number
|
|
||||||
/** Timestamp of when the member boosted the guild */
|
|
||||||
premiumSince?: number
|
|
||||||
/** Whether the user has not yet passed the guild's Membership Screening requirements */
|
|
||||||
pending?: boolean
|
|
||||||
/** Timestamp of timeout expiry. If `null`, the member is not timed out */
|
|
||||||
communicationDisabledUntil?: number | null
|
|
||||||
/** The members current status */
|
|
||||||
status?: Status;
|
|
||||||
|
|
||||||
/** The compressed form of the members avatar. */
|
|
||||||
_avatar?: bigint
|
|
||||||
|
|
||||||
constructor(data: (DiscordMember & { id: BigString }) | DiscordMemberWithUser, guild: Guild, client: Client) {
|
|
||||||
super(client.isDiscordMemberWithUser(data) ? data.user.id : data.id)
|
|
||||||
this.client = client
|
|
||||||
this.guild = guild
|
|
||||||
this.nick = null
|
|
||||||
this.roles = data.roles ?? []
|
|
||||||
|
|
||||||
const userID = client.isDiscordMemberWithUser(data) ? data.user.id : data.id
|
|
||||||
|
|
||||||
this.user = client.users.get(userID)!
|
|
||||||
if (data.user) {
|
|
||||||
this.user = new User(data.user, client)
|
|
||||||
client.users.set(this.user.id, this.user)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!this.user) {
|
|
||||||
throw new Error('User associated with Member not found: ' + userID)
|
|
||||||
}
|
|
||||||
|
|
||||||
this.update(data)
|
|
||||||
}
|
|
||||||
|
|
||||||
update(data: (DiscordMember & { id: BigString }) | DiscordMemberWithUser) {
|
|
||||||
if (data.joined_at !== undefined) {
|
|
||||||
this.joinedAt = data.joined_at ? Date.parse(data.joined_at) : undefined
|
|
||||||
}
|
|
||||||
|
|
||||||
if (data.premium_since !== undefined) {
|
|
||||||
this.premiumSince = data.premium_since === null ? undefined : Date.parse(data.premium_since)
|
|
||||||
}
|
|
||||||
|
|
||||||
// eslint-disable-next-line no-prototype-builtins
|
|
||||||
if (data.hasOwnProperty('mute') && this.guild) {
|
|
||||||
// TODO: voice stuff
|
|
||||||
// const state = this.guild.voiceStates.get(this.id);
|
|
||||||
// if (
|
|
||||||
// data.channel_id === null &&
|
|
||||||
// !data.mute &&
|
|
||||||
// !data.deaf &&
|
|
||||||
// !data.suppress
|
|
||||||
// ) {
|
|
||||||
// this.guild.voiceStates.delete(this.id);
|
|
||||||
// } else if (state) {
|
|
||||||
// state.update(data);
|
|
||||||
// } else if (data.channel_id || data.mute || data.deaf || data.suppress) {
|
|
||||||
// this.guild.voiceStates.update(data);
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
|
|
||||||
if (data.nick !== undefined) this.nick = data.nick
|
|
||||||
if (data.roles !== undefined) this.roles = data.roles
|
|
||||||
if (data.pending !== undefined) this.pending = data.pending
|
|
||||||
if (data.avatar !== undefined) this._avatar = data.avatar ? this.client.iconHashToBigInt(data.avatar) : undefined
|
|
||||||
|
|
||||||
if (data.communication_disabled_until !== undefined) {
|
|
||||||
if (data.communication_disabled_until !== null) {
|
|
||||||
this.communicationDisabledUntil = Date.parse(data.communication_disabled_until)
|
|
||||||
} else {
|
|
||||||
this.communicationDisabledUntil = data.communication_disabled_until
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
get avatar(): string | undefined {
|
|
||||||
return this._avatar ? this.client.iconBigintToHash(this._avatar) : undefined
|
|
||||||
}
|
|
||||||
|
|
||||||
get accentColor() {
|
|
||||||
return this.user.accentColor
|
|
||||||
}
|
|
||||||
|
|
||||||
get avatarURL() {
|
|
||||||
return this.avatar ? this.client._formatImage(GUILD_AVATAR(this.guild.id, this.id, this.avatar)) : this.user.avatarURL
|
|
||||||
}
|
|
||||||
|
|
||||||
get banner() {
|
|
||||||
return this.user.banner
|
|
||||||
}
|
|
||||||
|
|
||||||
get bannerURL() {
|
|
||||||
return this.user.bannerURL
|
|
||||||
}
|
|
||||||
|
|
||||||
get bot() {
|
|
||||||
return this.user.bot
|
|
||||||
}
|
|
||||||
|
|
||||||
get createdAt() {
|
|
||||||
return this.user.createdAt
|
|
||||||
}
|
|
||||||
|
|
||||||
get defaultAvatar() {
|
|
||||||
return this.user.defaultAvatar
|
|
||||||
}
|
|
||||||
|
|
||||||
get defaultAvatarURL() {
|
|
||||||
return this.user.defaultAvatarURL
|
|
||||||
}
|
|
||||||
|
|
||||||
get discriminator() {
|
|
||||||
return this.user.discriminator
|
|
||||||
}
|
|
||||||
|
|
||||||
get mention() {
|
|
||||||
return `<@!${this.id}>`
|
|
||||||
}
|
|
||||||
|
|
||||||
get permissions() {
|
|
||||||
return this.guild.permissionsOf(this)
|
|
||||||
}
|
|
||||||
|
|
||||||
get staticAvatarURL() {
|
|
||||||
return this.user.staticAvatarURL
|
|
||||||
}
|
|
||||||
|
|
||||||
get username() {
|
|
||||||
return this.user.username
|
|
||||||
}
|
|
||||||
|
|
||||||
get voiceState() {
|
|
||||||
if (this.guild?.voiceStates.has(this.id)) {
|
|
||||||
return this.guild.voiceStates.get(this.id)
|
|
||||||
} else {
|
|
||||||
// @ts-expect-error some eris magic at play here
|
|
||||||
return new VoiceState({ id: this.id })
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Add a role to the guild member */
|
|
||||||
async addRole(roleID: BigString, reason?: string): Promise<void> {
|
|
||||||
return await this.client.addGuildMemberRole.call(this.client, this.guild.id, this.id, roleID, reason)
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Ban the user from the guild */
|
|
||||||
async ban(deleteMessageDays = 0, reason?: string): Promise<void> {
|
|
||||||
return await this.client.banGuildMember.call(this.client, this.guild.id, this.id, deleteMessageDays, reason)
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Edit the guild member */
|
|
||||||
async edit(options: MemberOptions, reason?: string): Promise<Member> {
|
|
||||||
return await this.client.editGuildMember.call(this.client, this.guild.id, this.id, options, reason)
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Get the member's avatar with the given format and size */
|
|
||||||
dynamicAvatarURL(format?: ImageFormat, size?: ImageSize): string {
|
|
||||||
return this.avatar
|
|
||||||
? this.client._formatImage(GUILD_AVATAR(this.guild.id, this.id, this.avatar), format, size)
|
|
||||||
: this.user.dynamicAvatarURL(format, size)
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Kick the member from the guild */
|
|
||||||
async kick(reason?: string): Promise<void> {
|
|
||||||
return await this.client.kickGuildMember.call(this.client, this.guild.id, this.id, reason)
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Remove a role from the guild member */
|
|
||||||
async removeRole(roleID: BigString, reason?: string): Promise<void> {
|
|
||||||
return await this.client.removeGuildMemberRole.call(this.client, this.guild.id, this.id, roleID, reason)
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Unban the user from the guild */
|
|
||||||
async unban(reason?: string): Promise<void> {
|
|
||||||
return await this.client.unbanGuildMember.call(this.client, this.guild.id, this.id, reason)
|
|
||||||
}
|
|
||||||
|
|
||||||
toJSON(props: string[] = []): Record<string, any> {
|
|
||||||
return super.toJSON([
|
|
||||||
'activities',
|
|
||||||
'communicationDisabledUntil',
|
|
||||||
'joinedAt',
|
|
||||||
'nick',
|
|
||||||
'pending',
|
|
||||||
'premiumSince',
|
|
||||||
'roles',
|
|
||||||
'status',
|
|
||||||
'user',
|
|
||||||
'voiceState',
|
|
||||||
...props,
|
|
||||||
])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default Member
|
|
||||||
@@ -1,114 +0,0 @@
|
|||||||
import type { DiscordEmoji, DiscordGuildPreview } from '@discordeno/types'
|
|
||||||
import Base from '../../Base.js'
|
|
||||||
import type Client from '../../Client.js'
|
|
||||||
import type { ImageFormat, ImageSize } from '../../Client.js'
|
|
||||||
import { GUILD_DISCOVERY_SPLASH, GUILD_ICON, GUILD_SPLASH } from '../../Endpoints.js'
|
|
||||||
import { GuildToggles } from '../toggles/Guild.js'
|
|
||||||
|
|
||||||
export class GuildPreview extends Base {
|
|
||||||
/** The client object */
|
|
||||||
client: Client
|
|
||||||
/** The name of the guild. */
|
|
||||||
name: string
|
|
||||||
/** The description of the guild. */
|
|
||||||
description: string | null
|
|
||||||
/** An array of guild emojis. */
|
|
||||||
emojis: DiscordEmoji[]
|
|
||||||
/** The approximate number of members in the guild. */
|
|
||||||
approximateMemberCount: number
|
|
||||||
/** The approximate number of presences in the guild. */
|
|
||||||
approximatePresenceCount: number
|
|
||||||
|
|
||||||
/** The guild's icon image url. */
|
|
||||||
_icon: bigint | null
|
|
||||||
/** The guild's splash image url. */
|
|
||||||
_splash: bigint | null
|
|
||||||
/** The guild's discovery splash image url. */
|
|
||||||
_discoverySplash: bigint | null
|
|
||||||
/** The guild's features. */
|
|
||||||
_features: GuildToggles
|
|
||||||
|
|
||||||
constructor(data: DiscordGuildPreview, client: Client) {
|
|
||||||
super(data.id)
|
|
||||||
|
|
||||||
this.client = client
|
|
||||||
this.name = data.name
|
|
||||||
this.description = data.description
|
|
||||||
this._icon = data.icon ? client.iconHashToBigInt(data.icon) : null
|
|
||||||
this._splash = data.splash ? client.iconHashToBigInt(data.splash) : null
|
|
||||||
this._discoverySplash = data.discovery_splash ? client.iconHashToBigInt(data.discovery_splash) : null
|
|
||||||
this.approximateMemberCount = data.approximate_member_count
|
|
||||||
this.approximatePresenceCount = data.approximate_presence_count
|
|
||||||
this.emojis = data.emojis
|
|
||||||
// TODO: make dd version accept a specific subset of discord guild here
|
|
||||||
// @ts-expect-error this should not cause an issue
|
|
||||||
this._features = new GuildToggles(data)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @deprecated Use .client
|
|
||||||
*/
|
|
||||||
get _client(): Client {
|
|
||||||
return this.client
|
|
||||||
}
|
|
||||||
|
|
||||||
get icon(): string | undefined {
|
|
||||||
return this._icon ? this.client.iconBigintToHash(this._icon) : undefined
|
|
||||||
}
|
|
||||||
|
|
||||||
get iconURL(): string | null {
|
|
||||||
return this.icon ? this.client._formatImage(GUILD_ICON(this.id, this.icon)) : null
|
|
||||||
}
|
|
||||||
|
|
||||||
get splash(): string | undefined {
|
|
||||||
return this._splash ? this.client.iconBigintToHash(this._splash) : undefined
|
|
||||||
}
|
|
||||||
|
|
||||||
get splashURL(): string | null {
|
|
||||||
return this.splash ? this.client._formatImage(GUILD_SPLASH(this.id, this.splash)) : null
|
|
||||||
}
|
|
||||||
|
|
||||||
get discoverySplash(): string | undefined {
|
|
||||||
return this._discoverySplash ? this.client.iconBigintToHash(this._discoverySplash) : undefined
|
|
||||||
}
|
|
||||||
|
|
||||||
get discoverySplashURL(): string | null {
|
|
||||||
return this.discoverySplash ? this.client._formatImage(GUILD_DISCOVERY_SPLASH(this.id, this.discoverySplash)) : null
|
|
||||||
}
|
|
||||||
|
|
||||||
get features(): string[] {
|
|
||||||
return this._features.features.map((feature) => feature.replace(/([a-z])([A-Z])/, '$1_$2').toUpperCase())
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Get the guild's splash with the given format and size */
|
|
||||||
dynamicDiscoverySplashURL(format?: ImageFormat, size?: ImageSize): string | null {
|
|
||||||
return this.discoverySplash ? this.client._formatImage(GUILD_DISCOVERY_SPLASH(this.id, this.discoverySplash), format, size) : null
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Get the guild's icon with the given format and size */
|
|
||||||
dynamicIconURL(format?: ImageFormat, size?: ImageSize): string | null {
|
|
||||||
return this.icon ? this.client._formatImage(GUILD_ICON(this.id, this.icon), format, size) : null
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Get the guild's splash with the given format and size */
|
|
||||||
dynamicSplashURL(format?: ImageFormat, size?: ImageSize): string | null {
|
|
||||||
return this.splash ? this.client._formatImage(GUILD_SPLASH(this.id, this.splash), format, size) : null
|
|
||||||
}
|
|
||||||
|
|
||||||
toJSON(props: string[] = []): Record<string, any> {
|
|
||||||
return super.toJSON([
|
|
||||||
'approximateMemberCount',
|
|
||||||
'approximatePresenceCount',
|
|
||||||
'description',
|
|
||||||
'discoverySplash',
|
|
||||||
'emojis',
|
|
||||||
'features',
|
|
||||||
'icon',
|
|
||||||
'name',
|
|
||||||
'splash',
|
|
||||||
...props,
|
|
||||||
])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default GuildPreview
|
|
||||||
@@ -1,125 +0,0 @@
|
|||||||
/* eslint-disable @typescript-eslint/explicit-function-return-type */
|
|
||||||
/* eslint-disable no-useless-call */
|
|
||||||
/* eslint-disable @typescript-eslint/return-await */
|
|
||||||
|
|
||||||
import type { DiscordRole, DiscordRoleTags } from '@discordeno/types'
|
|
||||||
import Base from '../../Base.js'
|
|
||||||
import { ROLE_ICON } from '../../Endpoints.js'
|
|
||||||
import type { RoleOptions } from '../../typings.js'
|
|
||||||
import Permission from '../Permission.js'
|
|
||||||
import type Guild from './Guild.js'
|
|
||||||
|
|
||||||
export class Role extends Base {
|
|
||||||
permissions: Permission
|
|
||||||
name: string
|
|
||||||
color: number
|
|
||||||
hoist: boolean
|
|
||||||
mentionable: boolean
|
|
||||||
managed: boolean
|
|
||||||
icon?: string
|
|
||||||
unicodeEmoji?: string
|
|
||||||
position: number
|
|
||||||
guild: Guild
|
|
||||||
tags?: Omit<DiscordRoleTags, 'premium_subscriber' | 'available_for_purchase' | 'guild_connections'> & {
|
|
||||||
premium_subscriber?: boolean
|
|
||||||
available_for_purchase?: boolean
|
|
||||||
guild_connections?: boolean
|
|
||||||
}
|
|
||||||
|
|
||||||
constructor(data: DiscordRole, guild: Guild) {
|
|
||||||
super(data.id)
|
|
||||||
this.guild = guild
|
|
||||||
|
|
||||||
this.name = data.name
|
|
||||||
this.permissions = new Permission(data.permissions)
|
|
||||||
this.color = data.color
|
|
||||||
this.hoist = !!data.hoist
|
|
||||||
this.mentionable = !!data.mentionable
|
|
||||||
this.managed = !!data.managed
|
|
||||||
this.icon = data.icon
|
|
||||||
this.unicodeEmoji = data.unicode_emoji
|
|
||||||
this.position = data.position
|
|
||||||
this.tags = data.tags
|
|
||||||
? {
|
|
||||||
bot_id: data.tags.bot_id,
|
|
||||||
integration_id: data.tags.integration_id,
|
|
||||||
premium_subscriber: data.tags.premium_subscriber === null,
|
|
||||||
subscription_listing_id: data.tags.subscription_listing_id,
|
|
||||||
available_for_purchase: data.tags.available_for_purchase === null,
|
|
||||||
guild_connections: data.tags.guild_connections === null,
|
|
||||||
}
|
|
||||||
: undefined
|
|
||||||
}
|
|
||||||
|
|
||||||
update(data: DiscordRole) {
|
|
||||||
if (data.name !== undefined) {
|
|
||||||
this.name = data.name
|
|
||||||
}
|
|
||||||
if (data.mentionable !== undefined) {
|
|
||||||
this.mentionable = data.mentionable
|
|
||||||
}
|
|
||||||
if (data.managed !== undefined) {
|
|
||||||
this.managed = data.managed
|
|
||||||
}
|
|
||||||
if (data.hoist !== undefined) {
|
|
||||||
this.hoist = data.hoist
|
|
||||||
}
|
|
||||||
if (data.color !== undefined) {
|
|
||||||
this.color = data.color
|
|
||||||
}
|
|
||||||
if (data.position !== undefined) {
|
|
||||||
this.position = data.position
|
|
||||||
}
|
|
||||||
if (data.permissions !== undefined) {
|
|
||||||
this.permissions = new Permission(data.permissions)
|
|
||||||
}
|
|
||||||
if (data.tags !== undefined) {
|
|
||||||
this.tags = {
|
|
||||||
bot_id: data.tags.bot_id,
|
|
||||||
integration_id: data.tags.integration_id,
|
|
||||||
subscription_listing_id: data.tags.subscription_listing_id,
|
|
||||||
available_for_purchase: data.tags.available_for_purchase === null,
|
|
||||||
premium_subscriber: data.tags.premium_subscriber === null,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (data.icon !== undefined) {
|
|
||||||
this.icon = data.icon
|
|
||||||
}
|
|
||||||
if (data.unicode_emoji !== undefined) {
|
|
||||||
this.unicodeEmoji = data.unicode_emoji
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
get iconURL() {
|
|
||||||
return this.icon ? this.guild.client._formatImage(ROLE_ICON(this.id, this.icon)) : null
|
|
||||||
}
|
|
||||||
|
|
||||||
get json() {
|
|
||||||
return this.permissions.json
|
|
||||||
}
|
|
||||||
|
|
||||||
get mention() {
|
|
||||||
return `<@&${this.id}>`
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Delete the role */
|
|
||||||
async delete(reason: string): Promise<void> {
|
|
||||||
return await this.guild.client.deleteRole.call(this.guild.client, this.guild.id, this.id, reason)
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Edit the guild role */
|
|
||||||
async edit(options: RoleOptions, reason?: string): Promise<Role> {
|
|
||||||
return await this.guild.client.editRole.call(this.guild.client, this.guild.id, this.id, options, reason)
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Edit the role's position. Note that role position numbers are highest on top and lowest at the bottom. */
|
|
||||||
async editPosition(position: number): Promise<void> {
|
|
||||||
return await this.guild.client.editRolePosition.call(this.guild.client, this.guild.id, this.id, position)
|
|
||||||
}
|
|
||||||
|
|
||||||
toJSON(props: string[] = []): Record<string, any> {
|
|
||||||
return super.toJSON(['color', 'hoist', 'icon', 'managed', 'mentionable', 'name', 'permissions', 'position', 'tags', 'unicodeEmoji', ...props])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default Role
|
|
||||||
@@ -1,56 +0,0 @@
|
|||||||
/* eslint-disable @typescript-eslint/explicit-function-return-type */
|
|
||||||
/* eslint-disable no-useless-call */
|
|
||||||
import Base from '../../Base.js'
|
|
||||||
|
|
||||||
import type { DiscordStageInstance } from '@discordeno/types'
|
|
||||||
import type Client from '../../Client.js'
|
|
||||||
import type { StageInstanceOptions } from '../../typings.js'
|
|
||||||
import type StageChannel from '../channels/Stage.js'
|
|
||||||
import type Guild from './Guild.js'
|
|
||||||
|
|
||||||
export class StageInstance extends Base {
|
|
||||||
/** The client manager. */
|
|
||||||
client: Client
|
|
||||||
/** The associated stage channel */
|
|
||||||
channel: StageChannel | { id: string }
|
|
||||||
/** The guild of the associated stage channel */
|
|
||||||
guild: Guild | { id: string }
|
|
||||||
/** The stage channel topic */
|
|
||||||
topic?: string | null
|
|
||||||
|
|
||||||
constructor(data: DiscordStageInstance, client: Client) {
|
|
||||||
super(data.id)
|
|
||||||
|
|
||||||
this.client = client
|
|
||||||
this.channel = client.getChannel(data.channel_id) ?? {
|
|
||||||
id: data.channel_id,
|
|
||||||
}
|
|
||||||
this.guild = client.guilds.get(data.guild_id) ?? { id: data.guild_id }
|
|
||||||
this.update(data)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @deprecated Use `.client` instead.
|
|
||||||
*/
|
|
||||||
get _client(): Client {
|
|
||||||
return this.client
|
|
||||||
}
|
|
||||||
|
|
||||||
update(data: DiscordStageInstance) {
|
|
||||||
if (data.topic !== undefined) {
|
|
||||||
this.topic = data.topic
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Delete this stage instance */
|
|
||||||
async delete(): Promise<void> {
|
|
||||||
return await this.client.deleteStageInstance.call(this.client, this.channel.id)
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Update this stage instance */
|
|
||||||
async edit(options: StageInstanceOptions): Promise<StageInstance> {
|
|
||||||
return await this.client.editStageInstance.call(this.client, this.channel.id, options)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default StageInstance
|
|
||||||
@@ -1,95 +0,0 @@
|
|||||||
/* eslint-disable no-useless-call */
|
|
||||||
import type { DiscordTemplate } from '@discordeno/types'
|
|
||||||
import Base from '../../Base.js'
|
|
||||||
import type Client from '../../Client.js'
|
|
||||||
import type { GuildTemplateOptions } from '../../typings.js'
|
|
||||||
import User from '../users/User.js'
|
|
||||||
import Guild from './Guild.js'
|
|
||||||
|
|
||||||
export class GuildTemplate {
|
|
||||||
/** The client class itself. */
|
|
||||||
client: Client
|
|
||||||
/** The template code (unique Id) */
|
|
||||||
code: string
|
|
||||||
/** Template name */
|
|
||||||
name: string
|
|
||||||
/** The description for the template */
|
|
||||||
description: string | null
|
|
||||||
/** Number of times this template has been used */
|
|
||||||
usageCount: number
|
|
||||||
/** The user who created the template */
|
|
||||||
creator: User
|
|
||||||
/** When this template was created */
|
|
||||||
createdAt: number
|
|
||||||
/** When this template was last synced to the source guild */
|
|
||||||
updatedAt: number
|
|
||||||
/** The guild snapshot this template contains */
|
|
||||||
serializedSourceGuild: Guild
|
|
||||||
/** The guild this template is based on. If the guild is not cached, this will be an object with `id` key. No other property is guaranteed */
|
|
||||||
sourceGuild: Guild | { id: string }
|
|
||||||
/** Whether the template has un-synced changes */
|
|
||||||
isDirty: boolean | null
|
|
||||||
|
|
||||||
constructor(data: DiscordTemplate, client: Client) {
|
|
||||||
this.client = client
|
|
||||||
this.code = data.code
|
|
||||||
this.createdAt = Date.parse(data.created_at)
|
|
||||||
this.creator = new User(data.creator, client)
|
|
||||||
this.client.users.set(this.creator.id, this.creator)
|
|
||||||
this.description = data.description
|
|
||||||
this.isDirty = data.is_dirty
|
|
||||||
this.name = data.name
|
|
||||||
this.sourceGuild = client.guilds.get(data.source_guild_id) ?? { id: data.source_guild_id }
|
|
||||||
this.updatedAt = Date.parse(data.updated_at)
|
|
||||||
this.usageCount = data.usage_count
|
|
||||||
|
|
||||||
data.serialized_source_guild.features = []
|
|
||||||
// @ts-expect-error Hacks to get this to not error
|
|
||||||
this.serializedSourceGuild = new Guild(data.serialized_source_guild, client)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @deprecated Use .client instead.
|
|
||||||
*/
|
|
||||||
get _client(): Client {
|
|
||||||
return this.client
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Create a guild based on this template. Only for bots in less than 10 guilds */
|
|
||||||
async createGuild(name: string, icon?: string): Promise<Guild> {
|
|
||||||
return await this.client.createGuildFromTemplate.call(this.client, this.code, name, icon)
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Delete this template */
|
|
||||||
async delete(): Promise<void> {
|
|
||||||
return await this.client.deleteGuildTemplate.call(this.client, this.sourceGuild.id, this.code)
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Edit this template */
|
|
||||||
async edit(options: GuildTemplateOptions): Promise<GuildTemplate> {
|
|
||||||
return await this.client.editGuildTemplate.call(this.client, this.sourceGuild.id, this.code, options)
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Force this template to sync to the guild's current state */
|
|
||||||
async sync(): Promise<GuildTemplate> {
|
|
||||||
return await this.client.syncGuildTemplate.call(this.client, this.sourceGuild.id, this.code)
|
|
||||||
}
|
|
||||||
|
|
||||||
toJSON(props: string[] = []): Record<string, any> {
|
|
||||||
return Base.prototype.toJSON.call(this, [
|
|
||||||
'code',
|
|
||||||
'createdAt',
|
|
||||||
'creator',
|
|
||||||
'description',
|
|
||||||
'isDirty',
|
|
||||||
'name',
|
|
||||||
'serializedSourceGuild',
|
|
||||||
'sourceGuild',
|
|
||||||
'updatedAt',
|
|
||||||
'usageCount',
|
|
||||||
...props,
|
|
||||||
])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default GuildTemplate
|
|
||||||
@@ -1,22 +0,0 @@
|
|||||||
import type { DiscordUnavailableGuild } from '@discordeno/types'
|
|
||||||
import Base from '../../Base.js'
|
|
||||||
import type Client from '../../Client.js'
|
|
||||||
|
|
||||||
export class UnavailableGuild extends Base {
|
|
||||||
/** Whether or not the guild is unavailable. */
|
|
||||||
unavailable: boolean
|
|
||||||
|
|
||||||
constructor(data: DiscordUnavailableGuild, client: Client) {
|
|
||||||
super(data.id)
|
|
||||||
|
|
||||||
// TODO: gateway
|
|
||||||
// this.shard = client.shards.get(client.guildShardMap[this.id]);
|
|
||||||
this.unavailable = !!data.unavailable
|
|
||||||
}
|
|
||||||
|
|
||||||
toJSON(props: string[] = []): Record<string, any> {
|
|
||||||
return super.toJSON(['unavailable', ...props])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default UnavailableGuild
|
|
||||||
@@ -1,132 +0,0 @@
|
|||||||
/* eslint-disable @typescript-eslint/explicit-function-return-type */
|
|
||||||
import type { DiscordVoiceState } from '@discordeno/types'
|
|
||||||
import Base from '../../Base.js'
|
|
||||||
import { VoiceStateToggle, VoiceStateToggles } from '../toggles/Voice.js'
|
|
||||||
|
|
||||||
export class VoiceState extends Base {
|
|
||||||
channelID: string | null = null
|
|
||||||
requestToSpeakTimestamp: number | null
|
|
||||||
sessionID!: string | null
|
|
||||||
|
|
||||||
bitfield: VoiceStateToggles
|
|
||||||
|
|
||||||
constructor(data: DiscordVoiceState & { id: string }) {
|
|
||||||
super(data.id)
|
|
||||||
|
|
||||||
this.requestToSpeakTimestamp = null
|
|
||||||
this.bitfield = new VoiceStateToggles(data)
|
|
||||||
|
|
||||||
this.update(data)
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Whether or not the user is deafened by the server. */
|
|
||||||
get deaf(): boolean {
|
|
||||||
return this.bitfield.deaf
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Set whether or not the user is deafened by the server. */
|
|
||||||
set deaf(value: boolean) {
|
|
||||||
if (value) this.bitfield.add(VoiceStateToggle.deaf)
|
|
||||||
else this.bitfield.remove(VoiceStateToggle.deaf)
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Whether or not the user is muted by the server. */
|
|
||||||
get mute(): boolean {
|
|
||||||
return this.bitfield.mute
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Set whether or not the user is muted by the server. */
|
|
||||||
set mute(value: boolean) {
|
|
||||||
if (value) this.bitfield.add(VoiceStateToggle.mute)
|
|
||||||
else this.bitfield.remove(VoiceStateToggle.mute)
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Whether or not the user has deafened themself. */
|
|
||||||
get selfDeaf(): boolean {
|
|
||||||
return this.bitfield.selfDeaf
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Set whether or not the user has deafened themself. */
|
|
||||||
set selfDeaf(value: boolean) {
|
|
||||||
if (value) this.bitfield.add(VoiceStateToggle.selfDeaf)
|
|
||||||
else this.bitfield.remove(VoiceStateToggle.selfDeaf)
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Whether or not the user has muted themself. */
|
|
||||||
get selfMute(): boolean {
|
|
||||||
return this.bitfield.selfMute
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Set whether or not the user has muted themself. */
|
|
||||||
set selfMute(value: boolean) {
|
|
||||||
if (value) this.bitfield.add(VoiceStateToggle.selfMute)
|
|
||||||
else this.bitfield.remove(VoiceStateToggle.selfMute)
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Whether or not the user is streaming. */
|
|
||||||
get selfStream(): boolean {
|
|
||||||
return this.bitfield.selfStream
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Set whether or not the user is streaming. */
|
|
||||||
set selfStream(value: boolean) {
|
|
||||||
if (value) this.bitfield.add(VoiceStateToggle.selfStream)
|
|
||||||
else this.bitfield.remove(VoiceStateToggle.selfStream)
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Whether or not the user is video calling. */
|
|
||||||
get selfVideo(): boolean {
|
|
||||||
return this.bitfield.selfVideo
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Set whether or not the user is video calling. */
|
|
||||||
set selfVideo(value: boolean) {
|
|
||||||
if (value) this.bitfield.add(VoiceStateToggle.selfVideo)
|
|
||||||
else this.bitfield.remove(VoiceStateToggle.selfVideo)
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Whether or not the user is suppressed from speaking. */
|
|
||||||
get suppress(): boolean {
|
|
||||||
return this.bitfield.suppress
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Set whether or not the user is suppressed from speaking. */
|
|
||||||
set suppress(value: boolean) {
|
|
||||||
if (value) this.bitfield.add(VoiceStateToggle.suppress)
|
|
||||||
else this.bitfield.remove(VoiceStateToggle.suppress)
|
|
||||||
}
|
|
||||||
|
|
||||||
update(data: DiscordVoiceState) {
|
|
||||||
if (data.channel_id !== undefined) {
|
|
||||||
this.channelID = data.channel_id
|
|
||||||
this.sessionID = data.channel_id === null ? null : data.session_id
|
|
||||||
} else if (this.channelID === undefined) {
|
|
||||||
this.channelID = this.sessionID = null
|
|
||||||
}
|
|
||||||
|
|
||||||
if (data.mute !== undefined) this.mute = data.mute
|
|
||||||
if (data.deaf !== undefined) this.deaf = data.deaf
|
|
||||||
if (data.request_to_speak_timestamp) this.requestToSpeakTimestamp = Date.parse(data.request_to_speak_timestamp)
|
|
||||||
if (data.self_mute !== undefined) this.selfMute = data.self_mute
|
|
||||||
if (data.self_deaf !== undefined) this.selfDeaf = data.self_deaf
|
|
||||||
if (data.self_video !== undefined) this.selfVideo = data.self_video
|
|
||||||
if (data.self_stream !== undefined) this.selfStream = data.self_stream
|
|
||||||
if (data.suppress !== undefined) this.suppress = data.suppress
|
|
||||||
}
|
|
||||||
|
|
||||||
toJSON(props: string[] = []): Record<string, any> {
|
|
||||||
return super.toJSON([
|
|
||||||
'channelID',
|
|
||||||
'deaf',
|
|
||||||
'mute',
|
|
||||||
'requestToSpeakTimestamp',
|
|
||||||
'selfDeaf',
|
|
||||||
'selfMute',
|
|
||||||
'selfStream',
|
|
||||||
'selfVideo',
|
|
||||||
'sessionID',
|
|
||||||
'suppress',
|
|
||||||
...props,
|
|
||||||
])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,80 +0,0 @@
|
|||||||
/* eslint-disable @typescript-eslint/return-await */
|
|
||||||
/* eslint-disable no-useless-call */
|
|
||||||
/* eslint-disable @typescript-eslint/explicit-function-return-type */
|
|
||||||
import type { DiscordInteraction, DiscordInteractionData } from '@discordeno/types'
|
|
||||||
import { InteractionResponseTypes } from '@discordeno/types'
|
|
||||||
import type Client from '../../Client.js'
|
|
||||||
import type { ApplicationCommandOptionChoice } from '../../typings.js'
|
|
||||||
import type NewsChannel from '../channels/News.js'
|
|
||||||
import type PrivateChannel from '../channels/Private.js'
|
|
||||||
import type TextChannel from '../channels/Text.js'
|
|
||||||
import type Guild from '../guilds/Guild.js'
|
|
||||||
import Member from '../guilds/Member.js'
|
|
||||||
import Permission from '../Permission.js'
|
|
||||||
import User from '../users/User.js'
|
|
||||||
import Interaction from './Interaction.js'
|
|
||||||
|
|
||||||
export class AutocompleteInteraction extends Interaction {
|
|
||||||
/** The guild id if this interaction occurred in a guild. */
|
|
||||||
guildID?: string
|
|
||||||
/** The permissions the app or bot has within the channel, the interaction was sent from. */
|
|
||||||
appPermissions?: Permission
|
|
||||||
/** The channel id where this interaction was created in. */
|
|
||||||
channelID: string
|
|
||||||
/** The user who triggered the interaction. */
|
|
||||||
user: User
|
|
||||||
/** The data attached to this interaction. */
|
|
||||||
data?: DiscordInteractionData
|
|
||||||
/** The member who triggered the interaction. Sent when used in a guild. */
|
|
||||||
member?: Member
|
|
||||||
|
|
||||||
constructor(data: DiscordInteraction, client: Client) {
|
|
||||||
super(data, client)
|
|
||||||
|
|
||||||
this.channelID = data.channel_id!
|
|
||||||
this.data = data.data
|
|
||||||
|
|
||||||
if (data.guild_id !== undefined) {
|
|
||||||
this.guildID = data.guild_id
|
|
||||||
}
|
|
||||||
|
|
||||||
if (data.member !== undefined && this.guild) {
|
|
||||||
this.member = new Member(data.member, this.guild, this.client)
|
|
||||||
this.guild.members.set(this.member.id, this.member)
|
|
||||||
}
|
|
||||||
|
|
||||||
this.user = new User(data.user ?? data.member!.user, this.client)
|
|
||||||
this.client.users.set(this.user.id, this.user)
|
|
||||||
|
|
||||||
if (data.app_permissions !== undefined) {
|
|
||||||
this.appPermissions = new Permission(data.app_permissions)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** The channel the interaction was created in. */
|
|
||||||
get channel(): PrivateChannel | TextChannel | NewsChannel {
|
|
||||||
return this.client.getChannel(this.channelID) as PrivateChannel | TextChannel | NewsChannel
|
|
||||||
}
|
|
||||||
|
|
||||||
/** The guild the interaction was created in. */
|
|
||||||
get guild(): Guild | undefined {
|
|
||||||
return this.guildID ? this.client.guilds.get(this.guildID) : undefined
|
|
||||||
}
|
|
||||||
|
|
||||||
async acknowledge(choices: ApplicationCommandOptionChoice[]) {
|
|
||||||
return await this.result(choices)
|
|
||||||
}
|
|
||||||
|
|
||||||
async result(choices: ApplicationCommandOptionChoice[]) {
|
|
||||||
if (this.acknowledged) throw new Error('You have already acknowledged this interaction.')
|
|
||||||
|
|
||||||
return this.client.createInteractionResponse
|
|
||||||
.call(this.client, this.id, this.token, {
|
|
||||||
type: InteractionResponseTypes.ApplicationCommandAutocompleteResult,
|
|
||||||
data: { choices },
|
|
||||||
})
|
|
||||||
.then(() => this.update())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default AutocompleteInteraction
|
|
||||||
@@ -1,321 +0,0 @@
|
|||||||
/* eslint-disable @typescript-eslint/restrict-plus-operands */
|
|
||||||
/* eslint-disable @typescript-eslint/explicit-function-return-type */
|
|
||||||
/* eslint-disable no-useless-call */
|
|
||||||
/* eslint-disable @typescript-eslint/return-await */
|
|
||||||
import { ApplicationCommandTypes, InteractionResponseTypes } from '@discordeno/types'
|
|
||||||
|
|
||||||
import Collection from '../../Collection.js'
|
|
||||||
import Channel from '../channels/Channel.js'
|
|
||||||
import Member from '../guilds/Member.js'
|
|
||||||
import Role from '../guilds/Role.js'
|
|
||||||
import Message from '../Message.js'
|
|
||||||
import User from '../users/User.js'
|
|
||||||
import Interaction from './Interaction.js'
|
|
||||||
|
|
||||||
import type {
|
|
||||||
BigString,
|
|
||||||
DiscordAttachment,
|
|
||||||
DiscordInteraction,
|
|
||||||
DiscordInteractionDataOption,
|
|
||||||
DiscordMessageComponents,
|
|
||||||
MessageComponentTypes,
|
|
||||||
} from '@discordeno/types'
|
|
||||||
import type Client from '../../Client.js'
|
|
||||||
import type { AnyChannel, FileContent, InteractionContent, InteractionContentEdit } from '../../typings.js'
|
|
||||||
export class CommandInteraction extends Interaction {
|
|
||||||
name: string = "";
|
|
||||||
channel: AnyChannel
|
|
||||||
/** The type of component */
|
|
||||||
componentType?: MessageComponentTypes
|
|
||||||
/** The custom id provided for this component. */
|
|
||||||
customId?: string
|
|
||||||
/** The components if its a Modal Submit interaction. */
|
|
||||||
components?: DiscordMessageComponents
|
|
||||||
/** The values chosen by the user. */
|
|
||||||
values?: string[]
|
|
||||||
/** the type of the invoked command */
|
|
||||||
commandType: ApplicationCommandTypes = ApplicationCommandTypes.ChatInput
|
|
||||||
/** The Ids and Message objects */
|
|
||||||
messages = new Collection<BigString, Message>()
|
|
||||||
/** The Ids and User objects */
|
|
||||||
users = new Collection<BigString, User>()
|
|
||||||
/** The Ids and partial Member objects */
|
|
||||||
members = new Collection<BigString, Member>()
|
|
||||||
/** The Ids and Role objects */
|
|
||||||
roles = new Collection<BigString, Role>()
|
|
||||||
/** The Ids and partial Channel objects */
|
|
||||||
channels = new Collection<BigString, Channel>()
|
|
||||||
/** The ids and attachment objects */
|
|
||||||
attachments = new Collection<BigString, DiscordAttachment>()
|
|
||||||
/** The params + values from the user */
|
|
||||||
options?: DiscordInteractionDataOption[]
|
|
||||||
/** The target id if this is a context menu command. */
|
|
||||||
targetID?: string
|
|
||||||
/** the id of the guild the command is registered to */
|
|
||||||
guildID?: string
|
|
||||||
|
|
||||||
member?: Member
|
|
||||||
user: User
|
|
||||||
|
|
||||||
constructor(info: DiscordInteraction, client: Client) {
|
|
||||||
super(info, client)
|
|
||||||
|
|
||||||
this.channel = this.client.getChannel(info.channel_id!) ?? {
|
|
||||||
id: info.channel_id!,
|
|
||||||
}
|
|
||||||
|
|
||||||
// this.data = info.data!;
|
|
||||||
const guild = this.client.guilds.get(info.guild_id!)
|
|
||||||
|
|
||||||
if (info.data?.resolved !== undefined) {
|
|
||||||
// Users
|
|
||||||
if (info.data.resolved.users !== undefined) {
|
|
||||||
for (const u of Object.values(info.data.resolved.users)) {
|
|
||||||
const user = new User(u, this.client)
|
|
||||||
this.users.set(user.id, user)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Members
|
|
||||||
if (info.data.resolved.members !== undefined) {
|
|
||||||
for (const [, m] of Object.entries(info.data.resolved.members)) {
|
|
||||||
// @ts-expect-error some eris magic at play here
|
|
||||||
m.id = m
|
|
||||||
// @ts-expect-error some eris magic at play here
|
|
||||||
const member = new Member(m, guild, this.client)
|
|
||||||
this.members.set(member.id, member)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Roles
|
|
||||||
if (info.data.resolved.roles !== undefined) {
|
|
||||||
for (const r of Object.values(info.data.resolved.roles)) {
|
|
||||||
// @ts-expect-error some eris magic at play here
|
|
||||||
const role = new Role(r, guild)
|
|
||||||
this.roles.set(role.id, role)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Channels
|
|
||||||
if (info.data.resolved.channels !== undefined) {
|
|
||||||
for (const c of Object.values(info.data.resolved.channels)) {
|
|
||||||
const channel = new Channel(c, this.client)
|
|
||||||
this.channels.set(channel.id, channel)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Messages
|
|
||||||
if (info.data.resolved.messages !== undefined) {
|
|
||||||
for (const m of Object.values(info.data.resolved.messages)) {
|
|
||||||
const message = new Message(m, this.client)
|
|
||||||
this.messages.set(message.id, message)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Attachments
|
|
||||||
if (info.data.resolved.attachments !== undefined) {
|
|
||||||
for (const attachment of Object.values(info.data.resolved.attachments)) {
|
|
||||||
this.attachments.set(attachment.id, attachment)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
this.guildID = info.guild_id
|
|
||||||
|
|
||||||
if (info.member !== undefined) {
|
|
||||||
// @ts-expect-error some eris magic at play here
|
|
||||||
this.member = new Member(info.member, guild, this.client)
|
|
||||||
guild?.members.set(this.member.id, this.member)
|
|
||||||
}
|
|
||||||
|
|
||||||
this.user = new User(info.user ?? info.member!.user, this.client)
|
|
||||||
this.client.users.set(this.user.id, this.user)
|
|
||||||
|
|
||||||
if (info.data) {
|
|
||||||
this.name = info.data.name;
|
|
||||||
this.componentType = info.data.component_type
|
|
||||||
this.customId = info.data.custom_id
|
|
||||||
this.components = info.data.components
|
|
||||||
this.values = info.data.values
|
|
||||||
this.commandType = info.data.type
|
|
||||||
this.options = info.data.options
|
|
||||||
this.targetID = info.data.target_id
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
get data() {
|
|
||||||
return {
|
|
||||||
name: this.name,
|
|
||||||
component_type: this.componentType,
|
|
||||||
custom_id: this.customId,
|
|
||||||
components: this.components,
|
|
||||||
values: this.values,
|
|
||||||
type: this.commandType,
|
|
||||||
resolved: {
|
|
||||||
messages: this.messages.toRecord(),
|
|
||||||
users: this.users.toRecord(),
|
|
||||||
members: this.members.toRecord(),
|
|
||||||
roles: this.roles.toRecord(),
|
|
||||||
channels: this.channels.toRecord(),
|
|
||||||
attachments: this.attachments.toRecord(),
|
|
||||||
},
|
|
||||||
options: this.options,
|
|
||||||
target_id: this.targetID,
|
|
||||||
guild_id: this.guildID,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Acknowledges the interaction with a defer response
|
|
||||||
* Note: You can **not** use more than 1 initial interaction response per interaction.
|
|
||||||
*/
|
|
||||||
async acknowledge(flags?: number): Promise<void> {
|
|
||||||
return this.defer(flags)
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Respond to the interaction with a followup message */
|
|
||||||
async createFollowup(content: string | InteractionContent, file?: FileContent | FileContent[]): Promise<Message> {
|
|
||||||
if (!this.acknowledged) {
|
|
||||||
throw new Error('createFollowup cannot be used to acknowledge an interaction, please use acknowledge, createMessage, or defer first.')
|
|
||||||
}
|
|
||||||
if (content !== undefined) {
|
|
||||||
if (typeof content !== 'object' || content === null) {
|
|
||||||
content = {
|
|
||||||
content: '' + content,
|
|
||||||
}
|
|
||||||
} else if (content.content !== undefined && typeof content.content !== 'string') {
|
|
||||||
content.content = '' + content.content
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return await this.client.executeWebhook.call(this.client, this.applicationID, this.token, {
|
|
||||||
...content,
|
|
||||||
wait: true,
|
|
||||||
file,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Acknowledges the interaction with a message. If already acknowledged runs createFollowup
|
|
||||||
* Note: You can **not** use more than 1 initial interaction response per interaction, use createFollowup if you have already responded with a different interaction response.
|
|
||||||
*/
|
|
||||||
async createMessage(content: string | InteractionContent, file?: FileContent | FileContent[]): Promise<void> {
|
|
||||||
if (this.acknowledged) {
|
|
||||||
// @ts-expect-error some eris magic at play here
|
|
||||||
return await this.createFollowup(content, file)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (typeof content !== 'object' || content === null) {
|
|
||||||
content = {
|
|
||||||
content: '' + content,
|
|
||||||
}
|
|
||||||
} else if (content.content !== undefined && typeof content.content !== 'string') {
|
|
||||||
content.content = '' + content.content
|
|
||||||
}
|
|
||||||
|
|
||||||
return this.client.createInteractionResponse
|
|
||||||
.call(
|
|
||||||
this.client,
|
|
||||||
this.id,
|
|
||||||
this.token,
|
|
||||||
{
|
|
||||||
type: InteractionResponseTypes.ChannelMessageWithSource,
|
|
||||||
data: content,
|
|
||||||
},
|
|
||||||
file,
|
|
||||||
)
|
|
||||||
.then(() => this.update())
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Acknowledges the interaction with a defer response
|
|
||||||
* Note: You can **not** use more than 1 initial interaction response per interaction.
|
|
||||||
*/
|
|
||||||
async defer(flags?: number): Promise<void> {
|
|
||||||
if (this.acknowledged) {
|
|
||||||
throw new Error('You have already acknowledged this interaction.')
|
|
||||||
}
|
|
||||||
return this.client.createInteractionResponse
|
|
||||||
.call(this.client, this.id, this.token, {
|
|
||||||
type: InteractionResponseTypes.DeferredChannelMessageWithSource,
|
|
||||||
data: {
|
|
||||||
flags: flags ?? 0,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
.then(() => this.update())
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Delete a message */
|
|
||||||
async deleteMessage(messageID: BigString): Promise<void> {
|
|
||||||
if (!this.acknowledged) {
|
|
||||||
throw new Error('deleteMessage cannot be used to acknowledge an interaction, please use acknowledge, createMessage, or defer first.')
|
|
||||||
}
|
|
||||||
return this.client.deleteWebhookMessage.call(this.client, this.applicationID, this.token, messageID)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Delete the Original message
|
|
||||||
* Warning: Will error with ephemeral messages.
|
|
||||||
*/
|
|
||||||
async deleteOriginalMessage(): Promise<void> {
|
|
||||||
if (!this.acknowledged) {
|
|
||||||
throw new Error('deleteOriginalMessage cannot be used to acknowledge an interaction, please use acknowledge, createMessage, or defer first.')
|
|
||||||
}
|
|
||||||
return this.client.deleteWebhookMessage.call(this.client, this.applicationID, this.token, '@original')
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Edit a message */
|
|
||||||
async editMessage(messageID: BigString, content: string | InteractionContentEdit, file?: FileContent | FileContent[]): Promise<Message> {
|
|
||||||
if (!this.acknowledged) {
|
|
||||||
throw new Error('editMessage cannot be used to acknowledge an interaction, please use acknowledge, createMessage, or defer first.')
|
|
||||||
}
|
|
||||||
if (content !== undefined) {
|
|
||||||
if (typeof content !== 'object' || content === null) {
|
|
||||||
content = {
|
|
||||||
content: '' + content,
|
|
||||||
}
|
|
||||||
} else if (content.content !== undefined && typeof content.content !== 'string') {
|
|
||||||
content.content = '' + content.content
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return await this.client.editWebhookMessage.call(this.client, this.applicationID, this.token, messageID, {
|
|
||||||
...content,
|
|
||||||
file,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Edit the Original response message */
|
|
||||||
async editOriginalMessage(content: string | InteractionContentEdit, file?: FileContent | FileContent[]): Promise<Message> {
|
|
||||||
if (!this.acknowledged) {
|
|
||||||
throw new Error('editOriginalMessage cannot be used to acknowledge an interaction, please use acknowledge, createMessage, or defer first.')
|
|
||||||
}
|
|
||||||
if (content !== undefined) {
|
|
||||||
if (typeof content !== 'object' || content === null) {
|
|
||||||
content = {
|
|
||||||
content: '' + content,
|
|
||||||
}
|
|
||||||
} else if (content.content !== undefined && typeof content.content !== 'string') {
|
|
||||||
content.content = '' + content.content
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return this.client.editWebhookMessage.call(this.client, this.applicationID, this.token, '@original', {
|
|
||||||
...content,
|
|
||||||
file,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the Original response message
|
|
||||||
* Warning: Will error with ephemeral messages.
|
|
||||||
*/
|
|
||||||
async getOriginalMessage(): Promise<Message> {
|
|
||||||
if (!this.acknowledged) {
|
|
||||||
throw new Error('getOriginalMessage cannot be used to acknowledge an interaction, please use acknowledge, createMessage, or defer first.')
|
|
||||||
}
|
|
||||||
return this.client.getWebhookMessage.call(this.client, this.applicationID, this.token, '@original')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default CommandInteraction
|
|
||||||
@@ -1,296 +0,0 @@
|
|||||||
/* eslint-disable @typescript-eslint/restrict-plus-operands */
|
|
||||||
/* eslint-disable no-useless-call */
|
|
||||||
/* eslint-disable @typescript-eslint/return-await */
|
|
||||||
|
|
||||||
import type { BigString, DiscordInteraction, MessageComponentTypes } from '@discordeno/types'
|
|
||||||
import { InteractionResponseTypes } from '@discordeno/types'
|
|
||||||
import type Client from '../../Client.js'
|
|
||||||
import type { AnyChannel, FileContent, InteractionApplicationCommandCallbackData, MessageWebhookContent, WebhookPayload } from '../../typings.js'
|
|
||||||
import type Guild from '../guilds/Guild.js'
|
|
||||||
import Member from '../guilds/Member.js'
|
|
||||||
import Message from '../Message.js'
|
|
||||||
import Permission from '../Permission.js'
|
|
||||||
import User from '../users/User.js'
|
|
||||||
import Interaction from './Interaction.js'
|
|
||||||
|
|
||||||
export class ComponentInteraction extends Interaction {
|
|
||||||
/** The channel id where this interaction occurred in. */
|
|
||||||
channelID: string
|
|
||||||
/** The guild id where this interaction occurred in. */
|
|
||||||
guildID?: string
|
|
||||||
/** The member object if this interaction occurred in a guild. */
|
|
||||||
member?: Member
|
|
||||||
/** The user object for the user that created this interaction. */
|
|
||||||
user: User
|
|
||||||
/** The permissions the app or bot has within the channel, the interaction was sent from. */
|
|
||||||
appPermissions?: Permission
|
|
||||||
/** The message object, if this interaction occurred on a message. */
|
|
||||||
message?: Message
|
|
||||||
/** The custom id of the component. */
|
|
||||||
customID: string
|
|
||||||
/** The type of component. */
|
|
||||||
componentType: MessageComponentTypes
|
|
||||||
/** The values from a selector component. */
|
|
||||||
values?: string[]
|
|
||||||
|
|
||||||
constructor(data: DiscordInteraction, client: Client) {
|
|
||||||
super(data, client)
|
|
||||||
|
|
||||||
this.channelID = data.channel_id!
|
|
||||||
// this.data = data.data;
|
|
||||||
this.guildID = data.guild_id
|
|
||||||
// Required to make a component
|
|
||||||
this.customID = data.data!.custom_id!
|
|
||||||
this.componentType = data.data!.component_type!
|
|
||||||
this.values = data.data!.values
|
|
||||||
|
|
||||||
if (data.member !== undefined && this.guild) {
|
|
||||||
this.member = new Member(data.member, this.guild, this.client)
|
|
||||||
this.guild.members.set(this.member.id, this.member)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (data.message !== undefined) {
|
|
||||||
this.message = new Message(data.message, this.client)
|
|
||||||
}
|
|
||||||
|
|
||||||
this.user = new User(data.user ?? data.member!.user, this.client)
|
|
||||||
this.client.users.set(this.user.id, this.user)
|
|
||||||
|
|
||||||
if (data.app_permissions !== undefined) {
|
|
||||||
this.appPermissions = new Permission(data.app_permissions)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** The channel if cached, where this interaction occurred. */
|
|
||||||
get channel(): AnyChannel | undefined {
|
|
||||||
return this.channelID ? this.client.getChannel(this.channelID) : undefined
|
|
||||||
}
|
|
||||||
|
|
||||||
/** The guild if cached, where this interaction occurred. */
|
|
||||||
get guild(): Guild | undefined {
|
|
||||||
return this.guildID ? this.client.guilds.get(this.guildID) : undefined
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Acknowledges the interaction with a defer message update response */
|
|
||||||
async acknowledge(): Promise<void> {
|
|
||||||
return await this.deferUpdate()
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Respond to the interaction with a followup message. */
|
|
||||||
async createFollowup(content: WebhookPayload, file?: FileContent | FileContent[]): Promise<Message> {
|
|
||||||
if (!this.acknowledged) {
|
|
||||||
throw new Error(
|
|
||||||
'createFollowup cannot be used to acknowledge an interaction, please use acknowledge, createMessage, defer, deferUpdate, or editParent first.',
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (content !== undefined) {
|
|
||||||
if (typeof content !== 'object' || content === null) {
|
|
||||||
content = {
|
|
||||||
content: '' + content,
|
|
||||||
}
|
|
||||||
} else if (content.content !== undefined && typeof content.content !== 'string') {
|
|
||||||
content.content = '' + content.content
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (file) {
|
|
||||||
content.file = file
|
|
||||||
}
|
|
||||||
|
|
||||||
return await this.client.executeWebhook.call(this.client, this.applicationID, this.token, { ...content, wait: true })
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Acknowledges the interaction with a message. If already acknowledged runs createFollowup
|
|
||||||
* Note: You can **not** use more than 1 initial interaction response per interaction, use createFollowup if you have already responded with a different interaction response.
|
|
||||||
*/
|
|
||||||
async createMessage(content: InteractionApplicationCommandCallbackData, file?: FileContent | FileContent[]): Promise<Message | undefined> {
|
|
||||||
if (this.acknowledged) {
|
|
||||||
return await this.createFollowup(content, file)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (content !== undefined) {
|
|
||||||
if (typeof content !== 'object' || content === null) {
|
|
||||||
content = {
|
|
||||||
content: '' + content,
|
|
||||||
}
|
|
||||||
} else if (content.content !== undefined && typeof content.content !== 'string') {
|
|
||||||
content.content = '' + content.content
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
await this.client.createInteractionResponse
|
|
||||||
.call(
|
|
||||||
this.client,
|
|
||||||
this.id,
|
|
||||||
this.token,
|
|
||||||
{
|
|
||||||
type: InteractionResponseTypes.ChannelMessageWithSource,
|
|
||||||
data: content,
|
|
||||||
},
|
|
||||||
file,
|
|
||||||
)
|
|
||||||
.then(() => this.update())
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Acknowledges the interaction with a defer response
|
|
||||||
* Note: You can **not** use more than 1 initial interaction response per interaction.
|
|
||||||
*/
|
|
||||||
async defer(flags: number): Promise<void> {
|
|
||||||
if (this.acknowledged) {
|
|
||||||
throw new Error('You have already acknowledged this interaction.')
|
|
||||||
}
|
|
||||||
|
|
||||||
return await this.client.createInteractionResponse
|
|
||||||
.call(this.client, this.id, this.token, {
|
|
||||||
type: InteractionResponseTypes.DeferredChannelMessageWithSource,
|
|
||||||
data: {
|
|
||||||
flags: flags || 0,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
.then(() => this.update())
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Acknowledges the interaction with a defer message update response
|
|
||||||
* Note: You can **not** use more than 1 initial interaction response per interaction.
|
|
||||||
*/
|
|
||||||
async deferUpdate(): Promise<void> {
|
|
||||||
if (this.acknowledged) {
|
|
||||||
throw new Error('You have already acknowledged this interaction.')
|
|
||||||
}
|
|
||||||
|
|
||||||
return await this.client.createInteractionResponse
|
|
||||||
.call(this.client, this.id, this.token, {
|
|
||||||
type: InteractionResponseTypes.DeferredUpdateMessage,
|
|
||||||
})
|
|
||||||
.then(() => this.update())
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Delete a message */
|
|
||||||
async deleteMessage(messageID: BigString): Promise<void> {
|
|
||||||
if (!this.acknowledged) {
|
|
||||||
throw new Error(
|
|
||||||
'deleteMessage cannot be used to acknowledge an interaction, please use acknowledge, createMessage, defer, deferUpdate, or editParent first.',
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
return await this.client.deleteWebhookMessage.call(this.client, this.applicationID, this.token, messageID)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Delete the parent message
|
|
||||||
* Warning: Will error with ephemeral messages.
|
|
||||||
*/
|
|
||||||
async deleteOriginalMessage(): Promise<void> {
|
|
||||||
if (!this.acknowledged) {
|
|
||||||
throw new Error(
|
|
||||||
'deleteOriginalMessage cannot be used to acknowledge an interaction, please use acknowledge, createMessage, defer, deferUpdate, or editParent first.',
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
return await this.client.deleteWebhookMessage.call(this.client, this.applicationID, this.token, '@original')
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Edit a message */
|
|
||||||
async editMessage(messageID: BigString, content: MessageWebhookContent, file?: FileContent | FileContent[]): Promise<Message> {
|
|
||||||
if (!this.acknowledged) {
|
|
||||||
throw new Error(
|
|
||||||
'editMessage cannot be used to acknowledge an interaction, please use acknowledge, createMessage, defer, deferUpdate, or editParent first.',
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (content !== undefined) {
|
|
||||||
if (typeof content !== 'object' || content === null) {
|
|
||||||
content = {
|
|
||||||
content: '' + content,
|
|
||||||
}
|
|
||||||
} else if (content.content !== undefined && typeof content.content !== 'string') {
|
|
||||||
content.content = '' + content.content
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (file) {
|
|
||||||
content.file = file
|
|
||||||
}
|
|
||||||
|
|
||||||
return await this.client.editWebhookMessage.call(this.client, this.applicationID, this.token, messageID, content)
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Edit the parent message */
|
|
||||||
async editOriginalMessage(content: MessageWebhookContent, file?: FileContent | FileContent[]): Promise<Message> {
|
|
||||||
if (!this.acknowledged) {
|
|
||||||
throw new Error(
|
|
||||||
'editOriginalMessage cannot be used to acknowledge an interaction, please use acknowledge, createMessage, defer, deferUpdate, or editParent first.',
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (content !== undefined) {
|
|
||||||
if (typeof content !== 'object' || content === null) {
|
|
||||||
content = {
|
|
||||||
content: '' + content,
|
|
||||||
}
|
|
||||||
} else if (content.content !== undefined && typeof content.content !== 'string') {
|
|
||||||
content.content = '' + content.content
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (file) {
|
|
||||||
content.file = file
|
|
||||||
}
|
|
||||||
|
|
||||||
return await this.client.editWebhookMessage.call(this.client, this.applicationID, this.token, '@original', content)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Acknowledges the interaction by editing the parent message. If already acknowledged runs editOriginalMessage
|
|
||||||
* Note: You can **not** use more than 1 initial interaction response per interaction, use edit if you have already responded with a different interaction response.
|
|
||||||
* Warning: Will error with ephemeral messages.
|
|
||||||
*/
|
|
||||||
async editParent(content: InteractionApplicationCommandCallbackData, file?: FileContent | FileContent[]): Promise<Message | undefined> {
|
|
||||||
if (this.acknowledged) {
|
|
||||||
return this.editOriginalMessage(content)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (content !== undefined) {
|
|
||||||
if (typeof content !== 'object' || content === null) {
|
|
||||||
content = {
|
|
||||||
content: '' + content,
|
|
||||||
}
|
|
||||||
} else if (content.content !== undefined && typeof content.content !== 'string') {
|
|
||||||
content.content = '' + content.content
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
await this.client.createInteractionResponse
|
|
||||||
.call(
|
|
||||||
this.client,
|
|
||||||
this.id,
|
|
||||||
this.token,
|
|
||||||
{
|
|
||||||
type: InteractionResponseTypes.UpdateMessage,
|
|
||||||
data: content,
|
|
||||||
},
|
|
||||||
file,
|
|
||||||
)
|
|
||||||
.then(() => this.update())
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the parent message
|
|
||||||
* Warning: Will error with ephemeral messages.
|
|
||||||
*/
|
|
||||||
async getOriginalMessage(): Promise<Message> {
|
|
||||||
if (!this.acknowledged) {
|
|
||||||
throw new Error(
|
|
||||||
'getOriginalMessage cannot be used to acknowledge an interaction, please use acknowledge, createMessage, defer, deferUpdate, or editParent first.',
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
return this.client.getWebhookMessage.call(this.client, this.applicationID, this.token, '@original')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default ComponentInteraction
|
|
||||||
@@ -1,46 +0,0 @@
|
|||||||
/* eslint-disable @typescript-eslint/explicit-function-return-type */
|
|
||||||
import type { DiscordInteraction, InteractionTypes } from '@discordeno/types'
|
|
||||||
import Base from '../../Base.js'
|
|
||||||
import type Client from '../../Client.js'
|
|
||||||
|
|
||||||
export class Interaction extends Base {
|
|
||||||
client: Client
|
|
||||||
applicationID: string
|
|
||||||
token: string
|
|
||||||
type: InteractionTypes
|
|
||||||
version: 1
|
|
||||||
acknowledged: boolean
|
|
||||||
|
|
||||||
constructor(data: DiscordInteraction, client: Client) {
|
|
||||||
super(data.id)
|
|
||||||
this.client = client
|
|
||||||
|
|
||||||
this.applicationID = data.application_id
|
|
||||||
this.token = data.token
|
|
||||||
this.type = data.type
|
|
||||||
this.version = data.version
|
|
||||||
this.acknowledged = false
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @deprecated Use `.client`
|
|
||||||
*/
|
|
||||||
get _client(): Client {
|
|
||||||
return this.client
|
|
||||||
}
|
|
||||||
|
|
||||||
update() {
|
|
||||||
this.acknowledged = true
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @deprecated Use generateInteractionFrom(data, client) instead.
|
|
||||||
*/
|
|
||||||
static from(data: DiscordInteraction, client: Client) {
|
|
||||||
// Remove js hack of circular deps
|
|
||||||
console.error('Usage of Interaction.from() is deprecated. Use generateInteractionFrom(data, client) instead.')
|
|
||||||
client.emit('warn', new Error(`Usage of Interaction.from() is deprecated. Use generateInteractionFrom(data, client) instead.`))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default Interaction
|
|
||||||
@@ -1,33 +0,0 @@
|
|||||||
/* eslint-disable no-useless-call */
|
|
||||||
/* eslint-disable @typescript-eslint/return-await */
|
|
||||||
|
|
||||||
import { InteractionResponseTypes } from '@discordeno/types'
|
|
||||||
import Interaction from './Interaction.js'
|
|
||||||
|
|
||||||
export class PingInteraction extends Interaction {
|
|
||||||
/**
|
|
||||||
* Acknowledges the ping interaction with a pong response.
|
|
||||||
* Note: You can **not** use more than 1 initial interaction response per interaction.
|
|
||||||
*/
|
|
||||||
async acknowledge(): Promise<void> {
|
|
||||||
return this.pong()
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Acknowledges the ping interaction with a pong response.
|
|
||||||
* Note: You can **not** use more than 1 initial interaction response per interaction.
|
|
||||||
*/
|
|
||||||
async pong(): Promise<void> {
|
|
||||||
if (this.acknowledged) {
|
|
||||||
throw new Error('You have already acknowledged this interaction.')
|
|
||||||
}
|
|
||||||
|
|
||||||
return await this.client.createInteractionResponse
|
|
||||||
.call(this.client, this.id, this.token, {
|
|
||||||
type: InteractionResponseTypes.Pong,
|
|
||||||
})
|
|
||||||
.then(() => this.update())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default PingInteraction
|
|
||||||
@@ -1,493 +0,0 @@
|
|||||||
/* eslint-disable @typescript-eslint/restrict-plus-operands */
|
|
||||||
/* eslint-disable @typescript-eslint/explicit-function-return-type */
|
|
||||||
/* eslint-disable no-useless-call */
|
|
||||||
|
|
||||||
import type { DiscordInteraction } from '@discordeno/types'
|
|
||||||
import { InteractionResponseTypes } from '@discordeno/types'
|
|
||||||
import type Client from '../../Client.js'
|
|
||||||
import type {
|
|
||||||
ApplicationCommandOptionChoice,
|
|
||||||
FileContent,
|
|
||||||
InteractionContent,
|
|
||||||
InteractionContentEdit,
|
|
||||||
InteractionResponse,
|
|
||||||
PossiblyUncachedTextable,
|
|
||||||
TextableChannel,
|
|
||||||
} from '../../typings.js'
|
|
||||||
import Member from '../guilds/Member.js'
|
|
||||||
import Message from '../Message.js'
|
|
||||||
import Permission from '../Permission.js'
|
|
||||||
import User from '../users/User.js'
|
|
||||||
import Interaction from './Interaction.js'
|
|
||||||
|
|
||||||
export class UnknownInteraction<T extends PossiblyUncachedTextable = TextableChannel> extends Interaction {
|
|
||||||
channel?: T
|
|
||||||
data?: unknown
|
|
||||||
guildID?: string
|
|
||||||
member?: Member
|
|
||||||
message?: Message
|
|
||||||
type: number = 0
|
|
||||||
user?: User
|
|
||||||
appPermissions?: Permission
|
|
||||||
|
|
||||||
constructor(data: DiscordInteraction, client: Client) {
|
|
||||||
super(data, client)
|
|
||||||
|
|
||||||
if (data.channel_id !== undefined) {
|
|
||||||
this.channel = (this.client.getChannel(data.channel_id) as unknown as T) || {
|
|
||||||
id: data.channel_id,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (data.data !== undefined) {
|
|
||||||
this.data = data.data
|
|
||||||
}
|
|
||||||
|
|
||||||
if (data.guild_id !== undefined) {
|
|
||||||
this.guildID = data.guild_id
|
|
||||||
}
|
|
||||||
|
|
||||||
if (data.member !== undefined) {
|
|
||||||
const guild = this.client.guilds.get(data.guild_id ?? '')!
|
|
||||||
this.member = new Member(data.member, guild, this.client)
|
|
||||||
guild.members.set(this.member.id, this.member)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (data.message !== undefined) {
|
|
||||||
this.message = new Message(data.message, this.client)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (data.user !== undefined) {
|
|
||||||
this.user = new User(data.user, this.client)
|
|
||||||
this.client.users.set(this.user.id, this.user)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (data.app_permissions !== undefined) {
|
|
||||||
this.appPermissions = new Permission(data.app_permissions)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Acknowledges the autocomplete interaction with a result of choices.
|
|
||||||
* Note: You can **not** use more than 1 initial interaction response per interaction.
|
|
||||||
* @arg {Object} data The data object
|
|
||||||
* @arg {Number} data.type The type of [interaction response](https://discord.com/developers/docs/interactions/receiving-and-responding#interaction-response-object-interaction-callback-type) to send
|
|
||||||
* @arg {Object} data.data The data to return to discord
|
|
||||||
* @returns {Promise}
|
|
||||||
*/
|
|
||||||
async acknowledge(data: InteractionResponse) {
|
|
||||||
if (this.acknowledged) {
|
|
||||||
throw new Error('You have already acknowledged this interaction.')
|
|
||||||
}
|
|
||||||
return await this.client.createInteractionResponse.call(this.client, this.id, this.token, data).then(() => this.update())
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Respond to the interaction with a followup message
|
|
||||||
* @arg {String | Object} content A string or object. If an object is passed:
|
|
||||||
* @arg {Object} [content.allowedMentions] A list of mentions to allow (overrides default)
|
|
||||||
* @arg {Boolean} [content.allowedMentions.everyone] Whether or not to allow @everyone/@here.
|
|
||||||
* @arg {Boolean | Array<String>} [content.allowedMentions.roles] Whether or not to allow all role mentions, or an array of specific role mentions to allow.
|
|
||||||
* @arg {Boolean | Array<String>} [content.allowedMentions.users] Whether or not to allow all user mentions, or an array of specific user mentions to allow.
|
|
||||||
* @arg {Array<Object>} [content.components] An array of component objects
|
|
||||||
* @arg {String} [content.components[].custom_id] The ID of the component (type 2 style 0-4 and type 3 only)
|
|
||||||
* @arg {Boolean} [content.components[].disabled] Whether the component is disabled (type 2 and 3 only)
|
|
||||||
* @arg {Object} [content.components[].emoji] The emoji to be displayed in the component (type 2)
|
|
||||||
* @arg {String} [content.components[].label] The label to be displayed in the component (type 2)
|
|
||||||
* @arg {Number} [content.components[].max_values] The maximum number of items that can be chosen (1-25, default 1)
|
|
||||||
* @arg {Number} [content.components[].min_values] The minimum number of items that must be chosen (0-25, default 1)
|
|
||||||
* @arg {Array<Object>} [content.components[].options] The options for this component (type 3 only)
|
|
||||||
* @arg {Boolean} [content.components[].options[].default] Whether this option should be the default value selected
|
|
||||||
* @arg {String} [content.components[].options[].description] The description for this option
|
|
||||||
* @arg {Object} [content.components[].options[].emoji] The emoji to be displayed in this option
|
|
||||||
* @arg {String} content.components[].options[].label The label for this option
|
|
||||||
* @arg {Number | String} content.components[].options[].value The value for this option
|
|
||||||
* @arg {String} [content.components[].placeholder] The placeholder text for the component when no option is selected (type 3 only)
|
|
||||||
* @arg {Number} [content.components[].style] The style of the component (type 2 only) - If 0-4, `custom_id` is required; if 5, `url` is required
|
|
||||||
* @arg {Number} content.components[].type The type of component - If 1, it is a collection and a `components` array (nested) is required; if 2, it is a button; if 3, it is a select menu
|
|
||||||
* @arg {String} [content.components[].url] The URL that the component should open for users (type 2 style 5 only)
|
|
||||||
* @arg {String} [content.content] A content string
|
|
||||||
* @arg {Object} [content.embed] An embed object. See [the official Discord API documentation entry](https://discord.com/developers/docs/resources/channel#embed-object) for object structure
|
|
||||||
* @arg {Array<Object>} [options.embeds] An array of embed objects. See [the official Discord API documentation entry](https://discord.com/developers/docs/resources/channel#embed-object) for object structure
|
|
||||||
* @arg {Number} [content.flags] 64 for Ephemeral
|
|
||||||
* @arg {Boolean} [content.tts] Set the message TTS flag
|
|
||||||
* @arg {Object | Array<Object>} [file] A file object (or an Array of them)
|
|
||||||
* @arg {Buffer} file.file A buffer containing file data
|
|
||||||
* @arg {String} file.name What to name the file
|
|
||||||
* @returns {Promise<Message?>}
|
|
||||||
*/
|
|
||||||
async createFollowup(content: string | InteractionContent, file?: FileContent | FileContent[]) {
|
|
||||||
if (!this.acknowledged) {
|
|
||||||
throw new Error(
|
|
||||||
'createFollowup cannot be used to acknowledge an interaction, please use acknowledge, createMessage, defer, deferUpdate, editParent, pong, or result first.',
|
|
||||||
)
|
|
||||||
}
|
|
||||||
if (content !== undefined) {
|
|
||||||
if (typeof content !== 'object' || content === null) {
|
|
||||||
content = {
|
|
||||||
content: '' + content,
|
|
||||||
}
|
|
||||||
} else if (content.content !== undefined && typeof content.content !== 'string') {
|
|
||||||
content.content = '' + content.content
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (file) {
|
|
||||||
content.file = file
|
|
||||||
}
|
|
||||||
return await this.client.executeWebhook.call(this.client, this.applicationID, this.token, Object.assign({ wait: true as true }, content))
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Acknowledges the interaction with a message. If already acknowledged runs createFollowup
|
|
||||||
* Note: You can **not** use more than 1 initial interaction response per interaction, use createFollowup if you have already responded with a different interaction response.
|
|
||||||
* @arg {String | Object} content A string or object. If an object is passed:
|
|
||||||
* @arg {Object} [content.allowedMentions] A list of mentions to allow (overrides default)
|
|
||||||
* @arg {Boolean} [content.allowedMentions.everyone] Whether or not to allow @everyone/@here.
|
|
||||||
* @arg {Boolean | Array<String>} [content.allowedMentions.roles] Whether or not to allow all role mentions, or an array of specific role mentions to allow.
|
|
||||||
* @arg {Boolean | Array<String>} [content.allowedMentions.users] Whether or not to allow all user mentions, or an array of specific user mentions to allow.
|
|
||||||
* @arg {Array<Object>} [content.components] An array of component objects
|
|
||||||
* @arg {String} [content.components[].custom_id] The ID of the component (type 2 style 0-4 and type 3 only)
|
|
||||||
* @arg {Boolean} [content.components[].disabled] Whether the component is disabled (type 2 and 3 only)
|
|
||||||
* @arg {Object} [content.components[].emoji] The emoji to be displayed in the component (type 2)
|
|
||||||
* @arg {String} [content.components[].label] The label to be displayed in the component (type 2)
|
|
||||||
* @arg {Number} [content.components[].max_values] The maximum number of items that can be chosen (1-25, default 1)
|
|
||||||
* @arg {Number} [content.components[].min_values] The minimum number of items that must be chosen (0-25, default 1)
|
|
||||||
* @arg {Array<Object>} [content.components[].options] The options for this component (type 3 only)
|
|
||||||
* @arg {Boolean} [content.components[].options[].default] Whether this option should be the default value selected
|
|
||||||
* @arg {String} [content.components[].options[].description] The description for this option
|
|
||||||
* @arg {Object} [content.components[].options[].emoji] The emoji to be displayed in this option
|
|
||||||
* @arg {String} content.components[].options[].label The label for this option
|
|
||||||
* @arg {Number | String} content.components[].options[].value The value for this option
|
|
||||||
* @arg {String} [content.components[].placeholder] The placeholder text for the component when no option is selected (type 3 only)
|
|
||||||
* @arg {Number} [content.components[].style] The style of the component (type 2 only) - If 0-4, `custom_id` is required; if 5, `url` is required
|
|
||||||
* @arg {Number} content.components[].type The type of component - If 1, it is a collection and a `components` array (nested) is required; if 2, it is a button; if 3, it is a select menu
|
|
||||||
* @arg {String} [content.components[].url] The URL that the component should open for users (type 2 style 5 only)
|
|
||||||
* @arg {String} [content.content] A content string
|
|
||||||
* @arg {Object} [content.embed] An embed object. See [the official Discord API documentation entry](https://discord.com/developers/docs/resources/channel#embed-object) for object structure
|
|
||||||
* @arg {Array<Object>} [content.embeds] An array of embed objects. See [the official Discord API documentation entry](https://discord.com/developers/docs/resources/channel#embed-object) for object structure
|
|
||||||
* @arg {Boolean} [content.flags] 64 for Ephemeral
|
|
||||||
* @arg {Boolean} [content.tts] Set the message TTS flag
|
|
||||||
* @arg {Object | Array<Object>} [file] A file object (or an Array of them)
|
|
||||||
* @arg {Buffer} file.file A buffer containing file data
|
|
||||||
* @arg {String} file.name What to name the file
|
|
||||||
* @returns {Promise}
|
|
||||||
*/
|
|
||||||
async createMessage(content: string | InteractionContent, file?: FileContent | FileContent[]) {
|
|
||||||
if (this.acknowledged) {
|
|
||||||
return await this.createFollowup(content, file)
|
|
||||||
}
|
|
||||||
if (content !== undefined) {
|
|
||||||
if (typeof content !== 'object' || content === null) {
|
|
||||||
content = {
|
|
||||||
content: '' + content,
|
|
||||||
}
|
|
||||||
} else if (content.content !== undefined && typeof content.content !== 'string') {
|
|
||||||
content.content = '' + content.content
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return await this.client.createInteractionResponse
|
|
||||||
.call(
|
|
||||||
this.client,
|
|
||||||
this.id,
|
|
||||||
this.token,
|
|
||||||
{
|
|
||||||
type: InteractionResponseTypes.ChannelMessageWithSource,
|
|
||||||
data: content,
|
|
||||||
},
|
|
||||||
file,
|
|
||||||
)
|
|
||||||
.then(() => this.update())
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Acknowledges the interaction with a defer response
|
|
||||||
* Note: You can **not** use more than 1 initial interaction response per interaction.
|
|
||||||
* @arg {Number} [flags] 64 for Ephemeral
|
|
||||||
* @returns {Promise}
|
|
||||||
*/
|
|
||||||
async defer(flags: number) {
|
|
||||||
if (this.acknowledged) {
|
|
||||||
throw new Error('You have already acknowledged this interaction.')
|
|
||||||
}
|
|
||||||
return await this.client.createInteractionResponse
|
|
||||||
.call(this.client, this.id, this.token, {
|
|
||||||
type: InteractionResponseTypes.DeferredChannelMessageWithSource,
|
|
||||||
data: {
|
|
||||||
flags: flags || 0,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
.then(() => this.update())
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Acknowledges the interaction with a defer message update response (Message Component only)
|
|
||||||
* Note: You can **not** use more than 1 initial interaction response per interaction.
|
|
||||||
* @returns {Promise}
|
|
||||||
*/
|
|
||||||
async deferUpdate() {
|
|
||||||
if (this.acknowledged) {
|
|
||||||
throw new Error('You have already acknowledged this interaction.')
|
|
||||||
}
|
|
||||||
return await this.client.createInteractionResponse
|
|
||||||
.call(this.client, this.id, this.token, {
|
|
||||||
type: InteractionResponseTypes.DeferredUpdateMessage,
|
|
||||||
})
|
|
||||||
.then(() => this.update())
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Delete a message
|
|
||||||
* @arg {String} messageID the id of the message to delete, or "@original" for the original response.
|
|
||||||
* @returns {Promise}
|
|
||||||
*/
|
|
||||||
async deleteMessage(messageID: string) {
|
|
||||||
if (!this.acknowledged) {
|
|
||||||
throw new Error(
|
|
||||||
'deleteMessage cannot be used to acknowledge an interaction, please use acknowledge, createMessage, defer, deferUpdate, editParent, or pong first.',
|
|
||||||
)
|
|
||||||
}
|
|
||||||
return await this.client.deleteWebhookMessage.call(this.client, this.applicationID, this.token, messageID)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Delete the Original message (or the parent message for components)
|
|
||||||
* Warning: Will error with ephemeral messages.
|
|
||||||
* @returns {Promise}
|
|
||||||
*/
|
|
||||||
async deleteOriginalMessage() {
|
|
||||||
if (!this.acknowledged) {
|
|
||||||
throw new Error(
|
|
||||||
'deleteOriginalMessage cannot be used to acknowledge an interaction, please use acknowledge, createMessage, defer, deferUpdate, editParent, or pong first.',
|
|
||||||
)
|
|
||||||
}
|
|
||||||
return await this.client.deleteWebhookMessage.call(this.client, this.applicationID, this.token, '@original')
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Edit a message
|
|
||||||
* @arg {String} messageID the id of the message to edit, or "@original" for the original response.
|
|
||||||
* @arg {Object} content Interaction message edit options
|
|
||||||
* @arg {Object} [content.allowedMentions] A list of mentions to allow (overrides default)
|
|
||||||
* @arg {Boolean} [content.allowedMentions.everyone] Whether or not to allow @everyone/@here.
|
|
||||||
* @arg {Boolean} [content.allowedMentions.repliedUser] Whether or not to mention the author of the message being replied to.
|
|
||||||
* @arg {Boolean | Array<String>} [content.allowedMentions.roles] Whether or not to allow all role mentions, or an array of specific role mentions to allow.
|
|
||||||
* @arg {Boolean | Array<String>} [content.allowedMentions.users] Whether or not to allow all user mentions, or an array of specific user mentions to allow.
|
|
||||||
* @arg {Array<Object>} [content.components] An array of component objects
|
|
||||||
* @arg {String} [content.components[].custom_id] The ID of the component (type 2 style 0-4 and type 3 only)
|
|
||||||
* @arg {Boolean} [content.components[].disabled] Whether the component is disabled (type 2 and 3 only)
|
|
||||||
* @arg {Object} [content.components[].emoji] The emoji to be displayed in the component (type 2)
|
|
||||||
* @arg {String} [content.components[].label] The label to be displayed in the component (type 2)
|
|
||||||
* @arg {Number} [content.components[].max_values] The maximum number of items that can be chosen (1-25, default 1)
|
|
||||||
* @arg {Number} [content.components[].min_values] The minimum number of items that must be chosen (0-25, default 1)
|
|
||||||
* @arg {Array<Object>} [content.components[].options] The options for this component (type 3 only)
|
|
||||||
* @arg {Boolean} [content.components[].options[].default] Whether this option should be the default value selected
|
|
||||||
* @arg {String} [content.components[].options[].description] The description for this option
|
|
||||||
* @arg {Object} [content.components[].options[].emoji] The emoji to be displayed in this option
|
|
||||||
* @arg {String} content.components[].options[].label The label for this option
|
|
||||||
* @arg {Number | String} content.components[].options[].value The value for this option
|
|
||||||
* @arg {String} [content.components[].placeholder] The placeholder text for the component when no option is selected (type 3 only)
|
|
||||||
* @arg {Number} [content.components[].style] The style of the component (type 2 only) - If 0-4, `custom_id` is required; if 5, `url` is required
|
|
||||||
* @arg {Number} content.components[].type The type of component - If 1, it is a collection and a `components` array (nested) is required; if 2, it is a button; if 3, it is a select menu
|
|
||||||
* @arg {String} [content.components[].url] The URL that the component should open for users (type 2 style 5 only)
|
|
||||||
* @arg {String} [content.content] A content string
|
|
||||||
* @arg {Object} [content.embed] An embed object. See [the official Discord API documentation entry](https://discord.com/developers/docs/resources/channel#embed-object) for object structure
|
|
||||||
* @arg {Array<Object>} [content.embeds] An array of embed objects. See [the official Discord API documentation entry](https://discord.com/developers/docs/resources/channel#embed-object) for object structure
|
|
||||||
* @arg {Object | Array<Object>} [file] A file object (or an Array of them)
|
|
||||||
* @arg {Buffer} file.file A buffer containing file data
|
|
||||||
* @arg {String} file.name What to name the file
|
|
||||||
* @returns {Promise<Message>}
|
|
||||||
*/
|
|
||||||
async editMessage(messageID: string, content: string | InteractionContentEdit, file?: FileContent | FileContent[]) {
|
|
||||||
if (!this.acknowledged) {
|
|
||||||
throw new Error(
|
|
||||||
'editMessage cannot be used to acknowledge an interaction, please use acknowledge, createMessage, defer, deferUpdate, editParent, pong, or result first.',
|
|
||||||
)
|
|
||||||
}
|
|
||||||
if (content !== undefined) {
|
|
||||||
if (typeof content !== 'object' || content === null) {
|
|
||||||
content = {
|
|
||||||
content: '' + content,
|
|
||||||
}
|
|
||||||
} else if (content.content !== undefined && typeof content.content !== 'string') {
|
|
||||||
content.content = '' + content.content
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (file) {
|
|
||||||
content.file = file
|
|
||||||
}
|
|
||||||
return await this.client.editWebhookMessage.call(this.client, this.applicationID, this.token, messageID, content)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Edit the Original response message
|
|
||||||
* @arg {Object} content Interaction message edit options (or the parent message for components)
|
|
||||||
* @arg {Object} [content.allowedMentions] A list of mentions to allow (overrides default)
|
|
||||||
* @arg {Boolean} [content.allowedMentions.everyone] Whether or not to allow @everyone/@here.
|
|
||||||
* @arg {Boolean} [content.allowedMentions.repliedUser] Whether or not to mention the author of the message being replied to.
|
|
||||||
* @arg {Boolean | Array<String>} [content.allowedMentions.roles] Whether or not to allow all role mentions, or an array of specific role mentions to allow.
|
|
||||||
* @arg {Boolean | Array<String>} [content.allowedMentions.users] Whether or not to allow all user mentions, or an array of specific user mentions to allow.
|
|
||||||
* @arg {Array<Object>} [content.components] An array of component objects
|
|
||||||
* @arg {String} [content.components[].custom_id] The ID of the component (type 2 style 0-4 and type 3 only)
|
|
||||||
* @arg {Boolean} [content.components[].disabled] Whether the component is disabled (type 2 and 3 only)
|
|
||||||
* @arg {Object} [content.components[].emoji] The emoji to be displayed in the component (type 2)
|
|
||||||
* @arg {String} [content.components[].label] The label to be displayed in the component (type 2)
|
|
||||||
* @arg {Number} [content.components[].max_values] The maximum number of items that can be chosen (1-25, default 1)
|
|
||||||
* @arg {Number} [content.components[].min_values] The minimum number of items that must be chosen (0-25, default 1)
|
|
||||||
* @arg {Array<Object>} [content.components[].options] The options for this component (type 3 only)
|
|
||||||
* @arg {Boolean} [content.components[].options[].default] Whether this option should be the default value selected
|
|
||||||
* @arg {String} [content.components[].options[].description] The description for this option
|
|
||||||
* @arg {Object} [content.components[].options[].emoji] The emoji to be displayed in this option
|
|
||||||
* @arg {String} content.components[].options[].label The label for this option
|
|
||||||
* @arg {Number | String} content.components[].options[].value The value for this option
|
|
||||||
* @arg {String} [content.components[].placeholder] The placeholder text for the component when no option is selected (type 3 only)
|
|
||||||
* @arg {Number} [content.components[].style] The style of the component (type 2 only) - If 0-4, `custom_id` is required; if 5, `url` is required
|
|
||||||
* @arg {Number} content.components[].type The type of component - If 1, it is a collection and a `components` array (nested) is required; if 2, it is a button; if 3, it is a select menu
|
|
||||||
* @arg {String} [content.components[].url] The URL that the component should open for users (type 2 style 5 only)
|
|
||||||
* @arg {String} [content.content] A content string
|
|
||||||
* @arg {Object} [content.embed] An embed object. See [the official Discord API documentation entry](https://discord.com/developers/docs/resources/channel#embed-object) for object structure
|
|
||||||
* @arg {Array<Object>} [content.embeds] An array of embed objects. See [the official Discord API documentation entry](https://discord.com/developers/docs/resources/channel#embed-object) for object structure
|
|
||||||
* @arg {Object | Array<Object>} [file] A file object (or an Array of them)
|
|
||||||
* @arg {Buffer} file.file A buffer containing file data
|
|
||||||
* @arg {String} file.name What to name the file
|
|
||||||
* @returns {Promise<Message>}
|
|
||||||
*/
|
|
||||||
async editOriginalMessage(content: string | InteractionContentEdit, file?: FileContent | FileContent[]) {
|
|
||||||
if (!this.acknowledged) {
|
|
||||||
throw new Error(
|
|
||||||
'editOriginalMessage cannot be used to acknowledge an interaction, please use acknowledge, createMessage, defer, deferUpdate, editParent, pong, or result first.',
|
|
||||||
)
|
|
||||||
}
|
|
||||||
if (content !== undefined) {
|
|
||||||
if (typeof content !== 'object' || content === null) {
|
|
||||||
content = {
|
|
||||||
content: '' + content,
|
|
||||||
}
|
|
||||||
} else if (content.content !== undefined && typeof content.content !== 'string') {
|
|
||||||
content.content = '' + content.content
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (file) {
|
|
||||||
content.file = file
|
|
||||||
}
|
|
||||||
|
|
||||||
return await this.client.editWebhookMessage.call(this.client, this.applicationID, this.token, '@original', content)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Acknowledges the interaction by editing the parent message. If already acknowledged runs editOriginalMessage (Message Component only)
|
|
||||||
* Note: You can **not** use more than 1 initial interaction response per interaction, use edit if you have already responded with a different interaction response.
|
|
||||||
* Warning: Will error with ephemeral messages.
|
|
||||||
* @arg {String | Object} content What to edit the message with
|
|
||||||
* @arg {Object} [content.allowedMentions] A list of mentions to allow (overrides default)
|
|
||||||
* @arg {Boolean} [content.allowedMentions.everyone] Whether or not to allow @everyone/@here.
|
|
||||||
* @arg {Boolean} [content.allowedMentions.repliedUser] Whether or not to mention the author of the message being replied to.
|
|
||||||
* @arg {Boolean | Array<String>} [content.allowedMentions.roles] Whether or not to allow all role mentions, or an array of specific role mentions to allow.
|
|
||||||
* @arg {Boolean | Array<String>} [content.allowedMentions.users] Whether or not to allow all user mentions, or an array of specific user mentions to allow.
|
|
||||||
* @arg {Array<Object>} [content.components] An array of component objects
|
|
||||||
* @arg {String} [content.components[].custom_id] The ID of the component (type 2 style 0-4 and type 3 only)
|
|
||||||
* @arg {Boolean} [content.components[].disabled] Whether the component is disabled (type 2 and 3 only)
|
|
||||||
* @arg {Object} [content.components[].emoji] The emoji to be displayed in the component (type 2)
|
|
||||||
* @arg {String} [content.components[].label] The label to be displayed in the component (type 2)
|
|
||||||
* @arg {Number} [content.components[].max_values] The maximum number of items that can be chosen (1-25, default 1)
|
|
||||||
* @arg {Number} [content.components[].min_values] The minimum number of items that must be chosen (0-25, default 1)
|
|
||||||
* @arg {Array<Object>} [content.components[].options] The options for this component (type 3 only)
|
|
||||||
* @arg {Boolean} [content.components[].options[].default] Whether this option should be the default value selected
|
|
||||||
* @arg {String} [content.components[].options[].description] The description for this option
|
|
||||||
* @arg {Object} [content.components[].options[].emoji] The emoji to be displayed in this option
|
|
||||||
* @arg {String} content.components[].options[].label The label for this option
|
|
||||||
* @arg {Number | String} content.components[].options[].value The value for this option
|
|
||||||
* @arg {String} [content.components[].placeholder] The placeholder text for the component when no option is selected (type 3 only)
|
|
||||||
* @arg {Number} [content.components[].style] The style of the component (type 2 only) - If 0-4, `custom_id` is required; if 5, `url` is required
|
|
||||||
* @arg {Number} content.components[].type The type of component - If 1, it is a collection and a `components` array (nested) is required; if 2, it is a button; if 3, it is a select menu
|
|
||||||
* @arg {String} [content.components[].url] The URL that the component should open for users (type 2 style 5 only)
|
|
||||||
* @arg {String} [content.content] A content string
|
|
||||||
* @arg {Object} [content.embed] An embed object. See [the official Discord API documentation entry](https://discord.com/developers/docs/resources/channel#embed-object) for object structure
|
|
||||||
* @arg {Array<Object>} [content.embeds] An array of embed objects. See [the official Discord API documentation entry](https://discord.com/developers/docs/resources/channel#embed-object) for object structure
|
|
||||||
* @arg {Boolean} [content.flags] 64 for Ephemeral
|
|
||||||
* @arg {Boolean} [content.tts] Set the message TTS flag
|
|
||||||
* @arg {Object | Array<Object>} [file] A file object (or an Array of them)
|
|
||||||
* @arg {Buffer} file.file A buffer containing file data
|
|
||||||
* @arg {String} file.name What to name the file
|
|
||||||
* @returns {Promise}
|
|
||||||
*/
|
|
||||||
async editParent(content: InteractionContentEdit, file?: FileContent | FileContent[]) {
|
|
||||||
if (this.acknowledged) {
|
|
||||||
return await this.editOriginalMessage(content)
|
|
||||||
}
|
|
||||||
if (content !== undefined) {
|
|
||||||
if (typeof content !== 'object' || content === null) {
|
|
||||||
content = {
|
|
||||||
content: '' + content,
|
|
||||||
}
|
|
||||||
} else if (content.content !== undefined && typeof content.content !== 'string') {
|
|
||||||
content.content = '' + content.content
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return await this.client.createInteractionResponse
|
|
||||||
.call(
|
|
||||||
this.client,
|
|
||||||
this.id,
|
|
||||||
this.token,
|
|
||||||
{
|
|
||||||
type: InteractionResponseTypes.UpdateMessage,
|
|
||||||
data: content,
|
|
||||||
},
|
|
||||||
file,
|
|
||||||
)
|
|
||||||
.then(() => this.update())
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the Original response message (or the parent message for components)
|
|
||||||
* Warning: Will error with ephemeral messages.
|
|
||||||
* @returns {Promise<Message>}
|
|
||||||
*/
|
|
||||||
async getOriginalMessage() {
|
|
||||||
if (!this.acknowledged) {
|
|
||||||
throw new Error(
|
|
||||||
'getOriginalMessage cannot be used to acknowledge an interaction, please use acknowledge, createMessage, defer, deferUpdate, editParent, or pong first.',
|
|
||||||
)
|
|
||||||
}
|
|
||||||
return await this.client.getWebhookMessage.call(this.client, this.applicationID, this.token, '@original')
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Acknowledges the ping interaction with a pong response (Ping Only)
|
|
||||||
* Note: You can **not** use more than 1 initial interaction response per interaction.
|
|
||||||
* @returns {Promise}
|
|
||||||
*/
|
|
||||||
async pong() {
|
|
||||||
if (this.acknowledged) {
|
|
||||||
throw new Error('You have already acknowledged this interaction.')
|
|
||||||
}
|
|
||||||
return await this.client.createInteractionResponse
|
|
||||||
.call(this.client, this.id, this.token, {
|
|
||||||
type: InteractionResponseTypes.Pong,
|
|
||||||
})
|
|
||||||
.then(() => this.update())
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Acknowledges the autocomplete interaction with a result of choices.
|
|
||||||
* Note: You can **not** use more than 1 initial interaction response per interaction.
|
|
||||||
* @arg {Array<Object>} choices The autocomplete choices to return to the user
|
|
||||||
* @arg {String | Number} choices[].name The choice display name
|
|
||||||
* @arg {String} choices[].value The choice value to return to the bot
|
|
||||||
* @returns {Promise}
|
|
||||||
*/
|
|
||||||
async result(choices: ApplicationCommandOptionChoice[]) {
|
|
||||||
if (this.acknowledged) {
|
|
||||||
throw new Error('You have already acknowledged this interaction.')
|
|
||||||
}
|
|
||||||
return await this.client.createInteractionResponse
|
|
||||||
.call(this.client, this.id, this.token, {
|
|
||||||
type: InteractionResponseTypes.ApplicationCommandAutocompleteResult,
|
|
||||||
data: { choices },
|
|
||||||
})
|
|
||||||
.then(() => this.update())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default UnknownInteraction
|
|
||||||
@@ -1,304 +0,0 @@
|
|||||||
/* eslint-disable @typescript-eslint/explicit-function-return-type */
|
|
||||||
import { GuildFeatures, type DiscordGuild } from '@discordeno/types'
|
|
||||||
import { ToggleBitfieldBigint } from './Toggle.js'
|
|
||||||
|
|
||||||
const featureNames = [
|
|
||||||
'inviteSplash',
|
|
||||||
'vipRegions',
|
|
||||||
'vanityUrl',
|
|
||||||
'verified',
|
|
||||||
'partnered',
|
|
||||||
'community',
|
|
||||||
'developerSupportServer',
|
|
||||||
'news',
|
|
||||||
'discoverable',
|
|
||||||
'featurable',
|
|
||||||
'animatedIcon',
|
|
||||||
'banner',
|
|
||||||
'welcomeScreenEnabled',
|
|
||||||
'memberVerificationGateEnabled',
|
|
||||||
'previewEnabled',
|
|
||||||
'ticketedEventsEnabled',
|
|
||||||
'monetizationEnabled',
|
|
||||||
'moreStickers',
|
|
||||||
'privateThreads',
|
|
||||||
'roleIcons',
|
|
||||||
'autoModeration',
|
|
||||||
'invitesDisabled',
|
|
||||||
'animatedBanner',
|
|
||||||
]
|
|
||||||
|
|
||||||
export const GuildToggle = {
|
|
||||||
/** Whether the bot is the owner of the guild */
|
|
||||||
owner: 1n << 0n,
|
|
||||||
/** Whether the server widget is enabled */
|
|
||||||
widgetEnabled: 1n << 1n,
|
|
||||||
/** Whether this is considered a large guild */
|
|
||||||
large: 1n << 2n,
|
|
||||||
/** Whether this guild is unavailable due to an outage */
|
|
||||||
unavailable: 1n << 3n,
|
|
||||||
/** Whether the guild has the boost progress bar enabled */
|
|
||||||
premiumProgressBarEnabled: 1n << 4n,
|
|
||||||
|
|
||||||
// GUILD FEATURES ARE BELOW THIS
|
|
||||||
|
|
||||||
/** Whether the guild has access to set an invite splash background */
|
|
||||||
inviteSplash: 1n << 5n,
|
|
||||||
/** Whether the guild has access to set 384 kbps bitrate in voice (previously VIP voice servers) */
|
|
||||||
vipRegions: 1n << 6n,
|
|
||||||
/** Whether the guild has access to set a vanity URL */
|
|
||||||
vanityUrl: 1n << 7n,
|
|
||||||
/** Whether the guild is verified */
|
|
||||||
verified: 1n << 8n,
|
|
||||||
/** Whether the guild is partnered */
|
|
||||||
partnered: 1n << 9n,
|
|
||||||
/** Whether the guild can enable welcome screen, Membership Screening, stage channels and discovery, and receives community updates */
|
|
||||||
community: 1n << 10n,
|
|
||||||
/** Whether the guild has access to set an animated guild banner image */
|
|
||||||
animatedBanner: 1n << 11n,
|
|
||||||
/** Whether the guild has access to create news channels */
|
|
||||||
news: 1n << 12n,
|
|
||||||
/** Whether the guild is able to be discovered in the directory */
|
|
||||||
discoverable: 1n << 13n,
|
|
||||||
/** Whether the guild is able to be featured in the directory */
|
|
||||||
featurable: 1n << 15n,
|
|
||||||
/** Whether the guild has access to set an animated guild icon */
|
|
||||||
animatedIcon: 1n << 16n,
|
|
||||||
/** Whether the guild has access to set a guild banner image */
|
|
||||||
banner: 1n << 17n,
|
|
||||||
/** Whether the guild has enabled the welcome screen */
|
|
||||||
welcomeScreenEnabled: 1n << 18n,
|
|
||||||
/** Whether the guild has enabled [Membership Screening](https://discord.com/developers/docs/resources/guild#membership-screening-object) */
|
|
||||||
memberVerificationGateEnabled: 1n << 19n,
|
|
||||||
/** Whether the guild can be previewed before joining via Membership Screening or the directory */
|
|
||||||
previewEnabled: 1n << 20n,
|
|
||||||
/** Whether the guild has enabled ticketed events */
|
|
||||||
ticketedEventsEnabled: 1n << 21n,
|
|
||||||
/** Whether the guild has enabled monetization */
|
|
||||||
monetizationEnabled: 1n << 22n,
|
|
||||||
/** Whether the guild has increased custom sticker slots */
|
|
||||||
moreStickers: 1n << 23n,
|
|
||||||
/** Whether the guild has access to create private threads */
|
|
||||||
privateThreads: 1n << 26n,
|
|
||||||
/** Whether the guild is able to set role icons */
|
|
||||||
roleIcons: 1n << 27n,
|
|
||||||
/** Whether the guild has set up auto moderation rules */
|
|
||||||
autoModeration: 1n << 28n,
|
|
||||||
/** Whether the guild has paused invites, preventing new users from joining */
|
|
||||||
invitesDisabled: 1n << 29n,
|
|
||||||
/** Whether the guild has been set as a support server on the App Directory */
|
|
||||||
developerSupportServer: 1n << 30n,
|
|
||||||
}
|
|
||||||
|
|
||||||
export class GuildToggles extends ToggleBitfieldBigint {
|
|
||||||
constructor(guildOrTogglesBigint: DiscordGuild | bigint) {
|
|
||||||
super()
|
|
||||||
|
|
||||||
if (typeof guildOrTogglesBigint === 'bigint') this.bitfield = guildOrTogglesBigint
|
|
||||||
else {
|
|
||||||
const guild = guildOrTogglesBigint
|
|
||||||
|
|
||||||
if (guild.owner) this.add(GuildToggle.owner)
|
|
||||||
if (guild.widget_enabled) this.add(GuildToggle.widgetEnabled)
|
|
||||||
if (guild.large) this.add(GuildToggle.large)
|
|
||||||
if (guild.unavailable) this.add(GuildToggle.unavailable)
|
|
||||||
if (guild.premium_progress_bar_enabled) this.add(GuildToggle.premiumProgressBarEnabled)
|
|
||||||
|
|
||||||
if (guild.features.includes(GuildFeatures.InviteSplash)) this.add(GuildToggle.inviteSplash)
|
|
||||||
if (guild.features.includes(GuildFeatures.VipRegions)) this.add(GuildToggle.vipRegions)
|
|
||||||
if (guild.features.includes(GuildFeatures.VanityUrl)) this.add(GuildToggle.vanityUrl)
|
|
||||||
if (guild.features.includes(GuildFeatures.Verified)) this.add(GuildToggle.verified)
|
|
||||||
if (guild.features.includes(GuildFeatures.Partnered)) this.add(GuildToggle.partnered)
|
|
||||||
if (guild.features.includes(GuildFeatures.Community)) this.add(GuildToggle.community)
|
|
||||||
if (guild.features.includes(GuildFeatures.DeveloperSupportServer)) this.add(GuildToggle.developerSupportServer)
|
|
||||||
if (guild.features.includes(GuildFeatures.AnimatedBanner)) this.add(GuildToggle.animatedBanner)
|
|
||||||
if (guild.features.includes(GuildFeatures.News)) this.add(GuildToggle.news)
|
|
||||||
if (guild.features.includes(GuildFeatures.Discoverable)) this.add(GuildToggle.discoverable)
|
|
||||||
if (guild.features.includes(GuildFeatures.Featurable)) this.add(GuildToggle.featurable)
|
|
||||||
if (guild.features.includes(GuildFeatures.AnimatedIcon)) this.add(GuildToggle.animatedIcon)
|
|
||||||
if (guild.features.includes(GuildFeatures.Banner)) this.add(GuildToggle.banner)
|
|
||||||
if (guild.features.includes(GuildFeatures.WelcomeScreenEnabled)) this.add(GuildToggle.welcomeScreenEnabled)
|
|
||||||
if (guild.features.includes(GuildFeatures.MemberVerificationGateEnabled)) {
|
|
||||||
this.add(GuildToggle.memberVerificationGateEnabled)
|
|
||||||
}
|
|
||||||
if (guild.features.includes(GuildFeatures.PreviewEnabled)) this.add(GuildToggle.previewEnabled)
|
|
||||||
if (guild.features.includes(GuildFeatures.TicketedEventsEnabled)) this.add(GuildToggle.ticketedEventsEnabled)
|
|
||||||
if (guild.features.includes(GuildFeatures.MoreStickers)) this.add(GuildToggle.moreStickers)
|
|
||||||
if (guild.features.includes(GuildFeatures.PrivateThreads)) this.add(GuildToggle.privateThreads)
|
|
||||||
if (guild.features.includes(GuildFeatures.RoleIcons)) this.add(GuildToggle.roleIcons)
|
|
||||||
if (guild.features.includes(GuildFeatures.AutoModeration)) this.add(GuildToggle.autoModeration)
|
|
||||||
if (guild.features.includes(GuildFeatures.InvitesDisabled)) this.add(GuildToggle.invitesDisabled)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
get features() {
|
|
||||||
const features: GuildToggleKeys[] = []
|
|
||||||
for (const key of Object.keys(GuildToggle)) {
|
|
||||||
if (!featureNames.includes(key)) continue
|
|
||||||
if (!super.contains(GuildToggle[key as GuildToggleKeys])) continue
|
|
||||||
|
|
||||||
features.push(key as GuildToggleKeys)
|
|
||||||
}
|
|
||||||
|
|
||||||
return features
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Whether the bot is the owner of the guild */
|
|
||||||
get owner() {
|
|
||||||
return this.has('owner')
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Whether the server widget is enabled */
|
|
||||||
get widgetEnabled() {
|
|
||||||
return this.has('widgetEnabled')
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Whether this is considered a large guild */
|
|
||||||
get large() {
|
|
||||||
return this.has('large')
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Whether this guild is unavailable due to an outage */
|
|
||||||
get unavailable() {
|
|
||||||
return this.has('unavailable')
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Whether the guild has the boost progress bar enabled */
|
|
||||||
get premiumProgressBarEnabled() {
|
|
||||||
return this.has('premiumProgressBarEnabled')
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Whether the guild has access to set an invite splash background */
|
|
||||||
get inviteSplash() {
|
|
||||||
return this.has('inviteSplash')
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Whether the guild has access to set 384 kbps bitrate in voice (previously VIP voice servers) */
|
|
||||||
get vipRegions() {
|
|
||||||
return this.has('vipRegions')
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Whether the guild has access to set a vanity URL */
|
|
||||||
get vanityUrl() {
|
|
||||||
return this.has('vanityUrl')
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Whether the guild is verified */
|
|
||||||
get verified() {
|
|
||||||
return this.has('verified')
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Whether the guild is partnered */
|
|
||||||
get partnered() {
|
|
||||||
return this.has('partnered')
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Whether the guild can enable welcome screen, Membership Screening, stage channels and discovery, and receives community updates */
|
|
||||||
get community() {
|
|
||||||
return this.has('community')
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Whether the Guild has been set as a support server on the App Directory */
|
|
||||||
get developerSupportServer() {
|
|
||||||
return this.has('developerSupportServer')
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Whether the guild has access to set an animated guild banner image */
|
|
||||||
get animatedBanner() {
|
|
||||||
return this.has('animatedBanner')
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Whether the guild has access to create news channels */
|
|
||||||
get news() {
|
|
||||||
return this.has('news')
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Whether the guild is able to be discovered in the directory */
|
|
||||||
get discoverable() {
|
|
||||||
return this.has('discoverable')
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Whether the guild is able to be featured in the directory */
|
|
||||||
get featurable() {
|
|
||||||
return this.has('featurable')
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Whether the guild has access to set an animated guild icon */
|
|
||||||
get animatedIcon() {
|
|
||||||
return this.has('animatedIcon')
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Whether the guild has access to set a guild banner image */
|
|
||||||
get banner() {
|
|
||||||
return this.has('banner')
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Whether the guild has enabled the welcome screen */
|
|
||||||
get welcomeScreenEnabled() {
|
|
||||||
return this.has('welcomeScreenEnabled')
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Whether the guild has enabled [Membership Screening](https://discord.com/developers/docs/resources/guild#membership-screening-object) */
|
|
||||||
get memberVerificationGateEnabled() {
|
|
||||||
return this.has('memberVerificationGateEnabled')
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Whether the guild can be previewed before joining via Membership Screening or the directory */
|
|
||||||
get previewEnabled() {
|
|
||||||
return this.has('previewEnabled')
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Whether the guild has enabled ticketed events */
|
|
||||||
get ticketedEventsEnabled() {
|
|
||||||
return this.has('ticketedEventsEnabled')
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Whether the guild has enabled monetization */
|
|
||||||
get monetizationEnabled() {
|
|
||||||
return this.has('monetizationEnabled')
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Whether the guild has increased custom sticker slots */
|
|
||||||
get moreStickers() {
|
|
||||||
return this.has('moreStickers')
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Whether the guild has access to create private threads */
|
|
||||||
get privateThreads() {
|
|
||||||
return this.has('privateThreads')
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Whether the guild is able to set role icons */
|
|
||||||
get roleIcons() {
|
|
||||||
return this.has('roleIcons')
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Whether the guild has set up auto moderation rules */
|
|
||||||
get autoModeration() {
|
|
||||||
return this.has('autoModeration')
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Whether the guild has paused invites, preventing new users from joining */
|
|
||||||
get invitesDisabled() {
|
|
||||||
return this.has('invitesDisabled')
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Checks whether or not the permissions exist in this */
|
|
||||||
has(permissions: GuildToggleKeys | GuildToggleKeys[]) {
|
|
||||||
if (!Array.isArray(permissions)) return super.contains(GuildToggle[permissions])
|
|
||||||
|
|
||||||
return super.contains(permissions.reduce((a, b) => (a |= GuildToggle[b]), 0n))
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Lists all the toggles for the role and whether or not each is true or false. */
|
|
||||||
list() {
|
|
||||||
const json: Record<string, boolean> = {}
|
|
||||||
for (const [key, value] of Object.entries(GuildToggle)) {
|
|
||||||
json[key] = super.contains(value)
|
|
||||||
}
|
|
||||||
|
|
||||||
return json as Record<GuildToggleKeys, boolean>
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export type GuildToggleKeys = keyof typeof GuildToggle
|
|
||||||
@@ -1,50 +0,0 @@
|
|||||||
/* eslint-disable @typescript-eslint/explicit-function-return-type */
|
|
||||||
export class ToggleBitfield {
|
|
||||||
bitfield = 0
|
|
||||||
|
|
||||||
constructor(bitfield?: number) {
|
|
||||||
if (bitfield) this.bitfield = bitfield
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Tests whether or not this bitfield has the permission requested. */
|
|
||||||
contains(bits: number) {
|
|
||||||
return Boolean(this.bitfield & bits)
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Adds some bits to the bitfield. */
|
|
||||||
add(bits: number) {
|
|
||||||
this.bitfield |= bits
|
|
||||||
return this
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Removes some bits from the bitfield. */
|
|
||||||
remove(bits: number) {
|
|
||||||
this.bitfield &= ~bits
|
|
||||||
return this
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export class ToggleBitfieldBigint {
|
|
||||||
bitfield = 0n
|
|
||||||
|
|
||||||
constructor(bitfield?: bigint) {
|
|
||||||
if (bitfield) this.bitfield = bitfield
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Tests whether or not this bitfield has the permission requested. */
|
|
||||||
contains(bits: bigint) {
|
|
||||||
return Boolean(this.bitfield & bits)
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Adds some bits to the bitfield. */
|
|
||||||
add(bits: bigint) {
|
|
||||||
this.bitfield |= bits
|
|
||||||
return this
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Removes some bits from the bitfield. */
|
|
||||||
remove(bits: bigint) {
|
|
||||||
this.bitfield &= ~bits
|
|
||||||
return this
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,93 +0,0 @@
|
|||||||
/* eslint-disable @typescript-eslint/explicit-function-return-type */
|
|
||||||
import type { DiscordVoiceState } from '@discordeno/types'
|
|
||||||
import { ToggleBitfield } from './Toggle.js'
|
|
||||||
|
|
||||||
export const VoiceStateToggle = {
|
|
||||||
/** Whether this user is deafened by the server */
|
|
||||||
deaf: 1 << 0,
|
|
||||||
/** Whether this user is muted by the server */
|
|
||||||
mute: 1 << 1,
|
|
||||||
/** Whether this user is locally deafened */
|
|
||||||
selfDeaf: 1 << 2,
|
|
||||||
/** Whether this user is locally muted */
|
|
||||||
selfMute: 1 << 3,
|
|
||||||
/** Whether this user is streaming using "Go Live" */
|
|
||||||
selfStream: 1 << 4,
|
|
||||||
/** Whether this user's camera is enabled */
|
|
||||||
selfVideo: 1 << 5,
|
|
||||||
/** Whether this user is muted by the current user */
|
|
||||||
suppress: 1 << 6,
|
|
||||||
}
|
|
||||||
|
|
||||||
export class VoiceStateToggles extends ToggleBitfield {
|
|
||||||
constructor(voiceOrTogglesInt: DiscordVoiceState | number) {
|
|
||||||
super()
|
|
||||||
|
|
||||||
if (typeof voiceOrTogglesInt === 'number') this.bitfield = voiceOrTogglesInt
|
|
||||||
else {
|
|
||||||
const voice = voiceOrTogglesInt
|
|
||||||
|
|
||||||
if (voice.deaf) this.add(VoiceStateToggle.deaf)
|
|
||||||
if (voice.mute) this.add(VoiceStateToggle.mute)
|
|
||||||
if (voice.self_deaf) this.add(VoiceStateToggle.selfDeaf)
|
|
||||||
if (voice.self_mute) this.add(VoiceStateToggle.selfMute)
|
|
||||||
if (voice.self_stream) this.add(VoiceStateToggle.selfStream)
|
|
||||||
if (voice.self_video) this.add(VoiceStateToggle.selfVideo)
|
|
||||||
if (voice.suppress) this.add(VoiceStateToggle.suppress)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Whether this user is deafened by the server */
|
|
||||||
get deaf() {
|
|
||||||
return this.has('deaf')
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Whether this user is muted by the server */
|
|
||||||
get mute() {
|
|
||||||
return this.has('mute')
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Whether this user is locally deafened */
|
|
||||||
get selfDeaf() {
|
|
||||||
return this.has('selfDeaf')
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Whether this user is locally muted */
|
|
||||||
get selfMute() {
|
|
||||||
return this.has('selfMute')
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Whether this user is streaming using "Go Live" */
|
|
||||||
get selfStream() {
|
|
||||||
return this.has('selfStream')
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Whether this user's camera is enabled */
|
|
||||||
get selfVideo() {
|
|
||||||
return this.has('selfVideo')
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Whether this user is muted by the current user */
|
|
||||||
get suppress() {
|
|
||||||
return this.has('suppress')
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Checks whether or not the permissions exist in this */
|
|
||||||
has(permissions: VoiceStateToggleKeys | VoiceStateToggleKeys[]) {
|
|
||||||
if (!Array.isArray(permissions)) return super.contains(VoiceStateToggle[permissions])
|
|
||||||
|
|
||||||
return super.contains(permissions.reduce((a, b) => (a |= VoiceStateToggle[b]), 0))
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Lists all the toggles for the role and whether or not each is true or false. */
|
|
||||||
list() {
|
|
||||||
const json: Record<string, boolean> = {}
|
|
||||||
for (const [key, value] of Object.entries(VoiceStateToggle)) {
|
|
||||||
json[key] = super.contains(value)
|
|
||||||
}
|
|
||||||
|
|
||||||
return json as Record<VoiceStateToggleKeys, boolean>
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export type VoiceStateToggleKeys = keyof typeof VoiceStateToggle
|
|
||||||
@@ -1,37 +0,0 @@
|
|||||||
import type { PremiumTypes, DiscordUser } from '@discordeno/types'
|
|
||||||
import type Client from '../../Client.js'
|
|
||||||
import User from './User.js'
|
|
||||||
|
|
||||||
export class ExtendedUser extends User {
|
|
||||||
email?: string | null
|
|
||||||
verified?: boolean
|
|
||||||
mfaEnabled?: boolean
|
|
||||||
premiumType?: PremiumTypes
|
|
||||||
|
|
||||||
constructor(data: DiscordUser, client: Client) {
|
|
||||||
super(data, client)
|
|
||||||
this.update(data)
|
|
||||||
}
|
|
||||||
|
|
||||||
update(data: DiscordUser): void {
|
|
||||||
super.update(data)
|
|
||||||
if (data.email !== undefined) {
|
|
||||||
this.email = data.email
|
|
||||||
}
|
|
||||||
if (data.verified !== undefined) {
|
|
||||||
this.verified = data.verified
|
|
||||||
}
|
|
||||||
if (data.mfa_enabled !== undefined) {
|
|
||||||
this.mfaEnabled = data.mfa_enabled
|
|
||||||
}
|
|
||||||
if (data.premium_type !== undefined) {
|
|
||||||
this.premiumType = data.premium_type
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
toJSON(props: string[] = []): Record<string, any> {
|
|
||||||
return super.toJSON(['email', 'mfaEnabled', 'premium', 'verified', ...props])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default ExtendedUser
|
|
||||||
@@ -1,128 +0,0 @@
|
|||||||
/* eslint-disable no-useless-call */
|
|
||||||
import type { BigString, DiscordUser, UserFlags } from '@discordeno/types'
|
|
||||||
import Base from '../../Base.js'
|
|
||||||
import type Client from '../../Client.js'
|
|
||||||
import type { ImageFormat, ImageSize } from '../../Client.js'
|
|
||||||
import { BANNER, DEFAULT_USER_AVATAR, USER_AVATAR } from '../../Endpoints.js'
|
|
||||||
import type PrivateChannel from '../channels/Private.js'
|
|
||||||
|
|
||||||
export class User extends Base {
|
|
||||||
client: Client
|
|
||||||
bot: boolean
|
|
||||||
system: boolean
|
|
||||||
_avatar!: bigint | null
|
|
||||||
username!: string
|
|
||||||
discriminator!: string
|
|
||||||
publicFlags?: UserFlags
|
|
||||||
_banner!: bigint | null
|
|
||||||
accentColor?: number
|
|
||||||
|
|
||||||
constructor(data: DiscordUser, client: Client) {
|
|
||||||
super(data.id)
|
|
||||||
|
|
||||||
this.client = client
|
|
||||||
this.bot = !!data.bot
|
|
||||||
this.system = !!data.system
|
|
||||||
|
|
||||||
this.update(data)
|
|
||||||
}
|
|
||||||
|
|
||||||
/** @deprecated Use User.client Supported for Eris api compatibility. */
|
|
||||||
get _client(): Client {
|
|
||||||
return this.client
|
|
||||||
}
|
|
||||||
|
|
||||||
get avatar(): string | null {
|
|
||||||
if (!this._avatar) return null
|
|
||||||
|
|
||||||
return this.client.iconBigintToHash(this._avatar)
|
|
||||||
}
|
|
||||||
|
|
||||||
set avatar(value: BigString | null) {
|
|
||||||
this._avatar = typeof value === 'string' ? this.client.iconHashToBigInt(value) : value
|
|
||||||
}
|
|
||||||
|
|
||||||
get banner(): string | null {
|
|
||||||
if (!this._banner) return null
|
|
||||||
|
|
||||||
return this.client.iconBigintToHash(this._banner)
|
|
||||||
}
|
|
||||||
|
|
||||||
set banner(value: BigString | null) {
|
|
||||||
this._banner = typeof value === 'string' ? this.client.iconHashToBigInt(value) : value
|
|
||||||
}
|
|
||||||
|
|
||||||
get avatarURL(): string | null {
|
|
||||||
return this.avatar ? this.client._formatImage(USER_AVATAR(this.id, this.avatar)) : this.defaultAvatarURL
|
|
||||||
}
|
|
||||||
|
|
||||||
get bannerURL(): string | null {
|
|
||||||
if (!this.banner) {
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
|
|
||||||
return this.client._formatImage(BANNER(this.id, this.banner))
|
|
||||||
}
|
|
||||||
|
|
||||||
get defaultAvatar(): string {
|
|
||||||
// @ts-expect-error some eris magic at play here
|
|
||||||
return (this.discriminator % 5).toString()
|
|
||||||
}
|
|
||||||
|
|
||||||
get defaultAvatarURL(): string {
|
|
||||||
return `${this.client.CDN_URL}${DEFAULT_USER_AVATAR(this.defaultAvatar)}.png`
|
|
||||||
}
|
|
||||||
|
|
||||||
get mention(): string {
|
|
||||||
return `<@${this.id}>`
|
|
||||||
}
|
|
||||||
|
|
||||||
get staticAvatarURL(): string {
|
|
||||||
return this.avatar ? this.client._formatImage(USER_AVATAR(this.id, this.avatar), 'jpg') : this.defaultAvatarURL
|
|
||||||
}
|
|
||||||
|
|
||||||
update(data: DiscordUser): void {
|
|
||||||
if (data.avatar !== undefined) {
|
|
||||||
this.avatar = data.avatar
|
|
||||||
}
|
|
||||||
if (data.username !== undefined) {
|
|
||||||
this.username = data.username
|
|
||||||
}
|
|
||||||
if (data.discriminator !== undefined) {
|
|
||||||
this.discriminator = data.discriminator
|
|
||||||
}
|
|
||||||
if (data.public_flags !== undefined) {
|
|
||||||
this.publicFlags = data.public_flags
|
|
||||||
}
|
|
||||||
if (data.banner !== undefined) {
|
|
||||||
this.banner = data.banner
|
|
||||||
}
|
|
||||||
if (data.accent_color !== undefined) {
|
|
||||||
this.accentColor = data.accent_color
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Get the user's avatar with the given format and size */
|
|
||||||
dynamicAvatarURL(format?: ImageFormat, size?: ImageSize): string {
|
|
||||||
return this.avatar ? this.client._formatImage(USER_AVATAR(this.id, this.avatar), format, size) : this.defaultAvatarURL
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Get the user's banner with the given format and size */
|
|
||||||
dynamicBannerURL(format?: ImageFormat, size?: ImageSize): string | null {
|
|
||||||
return this.banner ? this.client._formatImage(BANNER(this.id, this.banner), format, size) : null
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get a DM channel with the user, or create one if it does not exist
|
|
||||||
* @returns {Promise<PrivateChannel>}
|
|
||||||
*/
|
|
||||||
async getDMChannel(): Promise<PrivateChannel> {
|
|
||||||
return await this.client.getDMChannel.call(this.client, this.id)
|
|
||||||
}
|
|
||||||
|
|
||||||
toJSON(props: string[] = []): Record<string, any> {
|
|
||||||
return super.toJSON(['accentColor', 'avatar', 'banner', 'bot', 'discriminator', 'publicFlags', 'system', 'username', ...props])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default User
|
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -1,151 +0,0 @@
|
|||||||
/* eslint-disable @typescript-eslint/explicit-function-return-type */
|
|
||||||
import Base from '../Base.js'
|
|
||||||
import type Client from '../Client.js'
|
|
||||||
import Collection from '../Collection.js'
|
|
||||||
import type { ShardManagerOptions } from '../typings.js'
|
|
||||||
import Shard from './Shard.js'
|
|
||||||
|
|
||||||
export class ShardManager extends Collection<number, Shard> {
|
|
||||||
/** The client manager */
|
|
||||||
client: Client
|
|
||||||
/** The options that were used to configure this manager. */
|
|
||||||
options: ShardManagerOptions
|
|
||||||
/** The buckets that this manager is handling. */
|
|
||||||
buckets: Map<number, number>
|
|
||||||
/** The queue in which to connect a shard. */
|
|
||||||
connectQueue: Shard[]
|
|
||||||
/** The timeout to use for connecting a shard. */
|
|
||||||
connectTimeout: NodeJS.Timeout | null
|
|
||||||
|
|
||||||
constructor(client: Client, options: ShardManagerOptions = {}) {
|
|
||||||
super()
|
|
||||||
this.client = client
|
|
||||||
|
|
||||||
this.options = Object.assign({ concurrency: 1 }, options)
|
|
||||||
this.buckets = new Map()
|
|
||||||
this.connectQueue = []
|
|
||||||
this.connectTimeout = null
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @deprecated Use `.client` instead.
|
|
||||||
*/
|
|
||||||
get _client(): Client {
|
|
||||||
return this.client
|
|
||||||
}
|
|
||||||
|
|
||||||
connect(shard: Shard) {
|
|
||||||
this.connectQueue.push(shard)
|
|
||||||
this.tryConnect()
|
|
||||||
}
|
|
||||||
|
|
||||||
get concurrency(): number {
|
|
||||||
return this.options.concurrency as number
|
|
||||||
}
|
|
||||||
|
|
||||||
setConcurrency(concurrency: number) {
|
|
||||||
this.options.concurrency = concurrency
|
|
||||||
}
|
|
||||||
|
|
||||||
spawn(id: number) {
|
|
||||||
let shard = this.get(id)
|
|
||||||
|
|
||||||
if (!shard) {
|
|
||||||
shard = new Shard(id, this.client)
|
|
||||||
this.set(id, shard)
|
|
||||||
|
|
||||||
shard
|
|
||||||
.on('ready', () => {
|
|
||||||
this.client.emit('shardReady', shard!.id)
|
|
||||||
if (this.client.ready) return
|
|
||||||
|
|
||||||
for (const other of this.values()) if (!other.ready) return
|
|
||||||
|
|
||||||
this.client.ready = true
|
|
||||||
this.client.startTime = Date.now()
|
|
||||||
|
|
||||||
this.client.emit('ready')
|
|
||||||
})
|
|
||||||
.on('resume', () => {
|
|
||||||
this.client.emit('shardResume', shard!.id)
|
|
||||||
if (this.client.ready) return
|
|
||||||
|
|
||||||
for (const other of this.values()) if (!other.ready) return
|
|
||||||
|
|
||||||
this.client.ready = true
|
|
||||||
this.client.startTime = Date.now()
|
|
||||||
this.client.emit('ready')
|
|
||||||
})
|
|
||||||
.on('disconnect', (error) => {
|
|
||||||
this.client.emit('shardDisconnect', error, shard!.id)
|
|
||||||
for (const other of this.values()) if (other.ready) return
|
|
||||||
|
|
||||||
this.client.ready = false
|
|
||||||
this.client.startTime = 0
|
|
||||||
this.client.emit('disconnect')
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
if (shard.status === 'disconnected') {
|
|
||||||
return this.connect(shard)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
tryConnect() {
|
|
||||||
// nothing in queue
|
|
||||||
if (this.connectQueue.length === 0) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// loop over the connectQueue
|
|
||||||
for (const shard of this.connectQueue) {
|
|
||||||
// find the bucket for our shard
|
|
||||||
const rateLimitKey = shard.id % this.concurrency || 0
|
|
||||||
const lastConnect = this.buckets.get(rateLimitKey) ?? 0
|
|
||||||
|
|
||||||
// has enough time passed since the last connect for this bucket (5s/bucket)?
|
|
||||||
// alternatively if we have a sessionID, we can skip this check
|
|
||||||
if (!shard.sessionID && Date.now() - lastConnect < 5000) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
// Are there any connecting shards in the same bucket we should wait on?
|
|
||||||
if (this.some((s) => s.connecting && (s.id % this.concurrency || 0) === rateLimitKey)) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
// connect the shard
|
|
||||||
shard.identify()
|
|
||||||
this.buckets.set(rateLimitKey, Date.now())
|
|
||||||
|
|
||||||
// remove the shard from the queue
|
|
||||||
const index = this.connectQueue.findIndex((s) => s.id === shard.id)
|
|
||||||
this.connectQueue.splice(index, 1)
|
|
||||||
}
|
|
||||||
|
|
||||||
// set the next timeout if we have more shards to connect
|
|
||||||
if (!this.connectTimeout && this.connectQueue.length > 0) {
|
|
||||||
this.connectTimeout = setTimeout(() => {
|
|
||||||
this.connectTimeout = null
|
|
||||||
this.tryConnect()
|
|
||||||
}, 500)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
_readyPacketCB(shardID: number) {
|
|
||||||
const rateLimitKey = shardID % this.concurrency || 0
|
|
||||||
this.buckets.set(rateLimitKey, Date.now())
|
|
||||||
|
|
||||||
this.tryConnect()
|
|
||||||
}
|
|
||||||
|
|
||||||
toString() {
|
|
||||||
return `[ShardManager ${this.size}]`
|
|
||||||
}
|
|
||||||
|
|
||||||
toJSON(props = []) {
|
|
||||||
return Base.prototype.toJSON.call(this, ['buckets', 'connectQueue', 'connectTimeout', 'options', ...props])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default ShardManager
|
|
||||||
@@ -1,145 +0,0 @@
|
|||||||
import Base from './Base.js'
|
|
||||||
import type { ClientOptions } from './Client.js'
|
|
||||||
import Client from './Client.js'
|
|
||||||
import Collection from './Collection.js'
|
|
||||||
import * as Constants from './Constants.js'
|
|
||||||
import Shard from './gateway/Shard.js'
|
|
||||||
import RequestHandler from './RequestHandler.js'
|
|
||||||
import { CategoryChannel } from './Structures/channels/Category.js'
|
|
||||||
import Channel from './Structures/channels/Channel.js'
|
|
||||||
import Guild, { GuildChannel } from './Structures/channels/Guild.js'
|
|
||||||
import { NewsChannel } from './Structures/channels/News.js'
|
|
||||||
import { PrivateChannel } from './Structures/channels/Private.js'
|
|
||||||
import { StageChannel } from './Structures/channels/Stage.js'
|
|
||||||
import { TextChannel } from './Structures/channels/Text.js'
|
|
||||||
import { TextVoiceChannel } from './Structures/channels/TextVoice.js'
|
|
||||||
import Member, { ThreadMember } from './Structures/channels/threads/Member.js'
|
|
||||||
import { NewsThreadChannel } from './Structures/channels/threads/NewsThread.js'
|
|
||||||
import { PrivateThreadChannel } from './Structures/channels/threads/PrivateThread.js'
|
|
||||||
import { PublicThreadChannel } from './Structures/channels/threads/PublicThread.js'
|
|
||||||
import { ThreadChannel } from './Structures/channels/threads/Thread.js'
|
|
||||||
import { VoiceChannel } from './Structures/channels/Voice.js'
|
|
||||||
import { GuildIntegration } from './Structures/guilds/Integration.js'
|
|
||||||
import { GuildPreview } from './Structures/guilds/Preview.js'
|
|
||||||
import Role from './Structures/guilds/Role.js'
|
|
||||||
import StageInstance from './Structures/guilds/StageInstance.js'
|
|
||||||
import { GuildTemplate } from './Structures/guilds/Template.js'
|
|
||||||
import { UnavailableGuild } from './Structures/guilds/Unavailable.js'
|
|
||||||
import { VoiceState } from './Structures/guilds/VoiceState.js'
|
|
||||||
import { AutocompleteInteraction } from './Structures/interactions/Autocomplete.js'
|
|
||||||
import Command, { CommandInteraction } from './Structures/interactions/Command.js'
|
|
||||||
import { ComponentInteraction } from './Structures/interactions/Component.js'
|
|
||||||
import Interaction from './Structures/interactions/Interaction.js'
|
|
||||||
import { PingInteraction } from './Structures/interactions/Ping.js'
|
|
||||||
import { UnknownInteraction } from './Structures/interactions/Unknown.js'
|
|
||||||
import Invite from './Structures/Invite.js'
|
|
||||||
import Message from './Structures/Message.js'
|
|
||||||
import Permission from './Structures/Permission.js'
|
|
||||||
import PermissionOverwrite from './Structures/PermissionOverwrite.js'
|
|
||||||
import { ExtendedUser } from './Structures/users/Extended.js'
|
|
||||||
import User from './Structures/users/User.js'
|
|
||||||
import Bucket from './utils/Bucket.js'
|
|
||||||
import DiscordRESTError from './utils/DiscordRESTError.js'
|
|
||||||
// TODO: MAKE THIS DYNAMIC FROM PACKAGE.JSON
|
|
||||||
export const VERSION = "19.0.0";
|
|
||||||
|
|
||||||
export function DiscordenoClient(token: string, options: ClientOptions): Client {
|
|
||||||
return new Client(token, options)
|
|
||||||
}
|
|
||||||
|
|
||||||
DiscordenoClient.AutocompleteInteraction = AutocompleteInteraction
|
|
||||||
DiscordenoClient.Base = Base
|
|
||||||
DiscordenoClient.Bucket = Bucket
|
|
||||||
DiscordenoClient.CategoryChannel = CategoryChannel
|
|
||||||
DiscordenoClient.Channel = Channel
|
|
||||||
DiscordenoClient.CommandInteraction = CommandInteraction
|
|
||||||
DiscordenoClient.ComponentInteraction = ComponentInteraction
|
|
||||||
DiscordenoClient.Client = Client
|
|
||||||
DiscordenoClient.Collection = Collection
|
|
||||||
DiscordenoClient.Command = Command
|
|
||||||
// DiscordenoClient.CommandClient = CommandClient
|
|
||||||
DiscordenoClient.Constants = Constants
|
|
||||||
// DiscordenoClient.DiscordHTTPError = DiscordHTTPError
|
|
||||||
DiscordenoClient.DiscordRESTError = DiscordRESTError
|
|
||||||
DiscordenoClient.ExtendedUser = ExtendedUser
|
|
||||||
DiscordenoClient.Guild = Guild
|
|
||||||
DiscordenoClient.GuildChannel = GuildChannel
|
|
||||||
DiscordenoClient.GuildIntegration = GuildIntegration
|
|
||||||
DiscordenoClient.GuildPreview = GuildPreview
|
|
||||||
DiscordenoClient.GuildTemplate = GuildTemplate
|
|
||||||
DiscordenoClient.Interaction = Interaction
|
|
||||||
DiscordenoClient.Invite = Invite
|
|
||||||
DiscordenoClient.Member = Member
|
|
||||||
DiscordenoClient.Message = Message
|
|
||||||
DiscordenoClient.NewsChannel = NewsChannel
|
|
||||||
DiscordenoClient.NewsThreadChannel = NewsThreadChannel
|
|
||||||
DiscordenoClient.Permission = Permission
|
|
||||||
DiscordenoClient.PermissionOverwrite = PermissionOverwrite
|
|
||||||
DiscordenoClient.PingInteraction = PingInteraction
|
|
||||||
DiscordenoClient.PrivateChannel = PrivateChannel
|
|
||||||
DiscordenoClient.PrivateThreadChannel = PrivateThreadChannel
|
|
||||||
DiscordenoClient.PublicThreadChannel = PublicThreadChannel
|
|
||||||
DiscordenoClient.RequestHandler = RequestHandler
|
|
||||||
DiscordenoClient.Role = Role
|
|
||||||
DiscordenoClient.Shard = Shard
|
|
||||||
DiscordenoClient.StageChannel = StageChannel
|
|
||||||
DiscordenoClient.StageInstance = StageInstance
|
|
||||||
DiscordenoClient.TextChannel = TextChannel
|
|
||||||
DiscordenoClient.TextVoiceChannel = TextVoiceChannel
|
|
||||||
DiscordenoClient.ThreadChannel = ThreadChannel
|
|
||||||
DiscordenoClient.ThreadMember = ThreadMember
|
|
||||||
DiscordenoClient.UnavailableGuild = UnavailableGuild
|
|
||||||
DiscordenoClient.UnknownInteraction = UnknownInteraction
|
|
||||||
DiscordenoClient.User = User
|
|
||||||
DiscordenoClient.VERSION = VERSION
|
|
||||||
DiscordenoClient.VoiceChannel = VoiceChannel
|
|
||||||
DiscordenoClient.VoiceState = VoiceState
|
|
||||||
|
|
||||||
export * from './Base.js'
|
|
||||||
export * from './Client.js'
|
|
||||||
export * from './Collection.js'
|
|
||||||
export * from './Constants.js'
|
|
||||||
export * from './Endpoints.js'
|
|
||||||
export * from './gateway/Shard.js'
|
|
||||||
export * from './gateway/ShardManager.js'
|
|
||||||
export * from './Structures/channels/Category.js'
|
|
||||||
export * from './Structures/channels/Channel.js'
|
|
||||||
export * from './Structures/channels/Guild.js'
|
|
||||||
export * from './Structures/channels/News.js'
|
|
||||||
export * from './Structures/channels/Private.js'
|
|
||||||
export * from './Structures/channels/Stage.js'
|
|
||||||
export * from './Structures/channels/Text.js'
|
|
||||||
export * from './Structures/channels/TextVoice.js'
|
|
||||||
export * from './Structures/channels/threads/Member.js'
|
|
||||||
export * from './Structures/channels/threads/NewsThread.js'
|
|
||||||
export * from './Structures/channels/threads/PrivateThread.js'
|
|
||||||
export * from './Structures/channels/threads/PublicThread.js'
|
|
||||||
export * from './Structures/channels/threads/Thread.js'
|
|
||||||
export * from './Structures/channels/Voice.js'
|
|
||||||
export * from './Structures/guilds/AuditLogEntry.js'
|
|
||||||
export * from './Structures/guilds/Guild.js'
|
|
||||||
export * from './Structures/guilds/Integration.js'
|
|
||||||
export * from './Structures/guilds/Member.js'
|
|
||||||
export * from './Structures/guilds/Preview.js'
|
|
||||||
export * from './Structures/guilds/Role.js'
|
|
||||||
export * from './Structures/guilds/StageInstance.js'
|
|
||||||
export * from './Structures/guilds/Template.js'
|
|
||||||
export * from './Structures/guilds/Unavailable.js'
|
|
||||||
export * from './Structures/guilds/VoiceState.js'
|
|
||||||
export * from './Structures/interactions/Autocomplete.js'
|
|
||||||
export * from './Structures/interactions/Command.js'
|
|
||||||
export * from './Structures/interactions/Component.js'
|
|
||||||
export * from './Structures/interactions/Interaction.js'
|
|
||||||
export * from './Structures/interactions/Ping.js'
|
|
||||||
export * from './Structures/interactions/Unknown.js'
|
|
||||||
export * from './Structures/Invite.js'
|
|
||||||
export * from './Structures/Message.js'
|
|
||||||
export * from './Structures/Permission.js'
|
|
||||||
export * from './Structures/PermissionOverwrite.js'
|
|
||||||
export * from './Structures/users/Extended.js'
|
|
||||||
export * from './Structures/users/User.js'
|
|
||||||
export * from './typings.js'
|
|
||||||
export * from './utils/BrowserWebSocket.js'
|
|
||||||
export * from './utils/Bucket.js'
|
|
||||||
export * from './utils/DiscordRESTError.js'
|
|
||||||
export * from './utils/generate.js'
|
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -1,105 +0,0 @@
|
|||||||
/* eslint-disable @typescript-eslint/class-literal-property-style */
|
|
||||||
/* eslint-disable @typescript-eslint/explicit-function-return-type */
|
|
||||||
/* eslint-disable @typescript-eslint/no-var-requires */
|
|
||||||
import { EventEmitter } from 'node:events'
|
|
||||||
|
|
||||||
class BrowserWebSocketError extends Error {
|
|
||||||
static CONNECTING: 0 = 0
|
|
||||||
static OPEN: 1
|
|
||||||
static CLOSING: 2
|
|
||||||
static CLOSED: 3
|
|
||||||
|
|
||||||
readyState: number = 0
|
|
||||||
event: Event
|
|
||||||
|
|
||||||
constructor(message: string | undefined, event: Event) {
|
|
||||||
super(message)
|
|
||||||
|
|
||||||
this.event = event
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Represents a browser's websocket usable by Eris
|
|
||||||
* @extends EventEmitter
|
|
||||||
* @prop {String} url The URL to connect to
|
|
||||||
*/
|
|
||||||
class BrowserWebSocket extends EventEmitter {
|
|
||||||
_ws: WebSocket
|
|
||||||
|
|
||||||
constructor(url: string) {
|
|
||||||
super()
|
|
||||||
|
|
||||||
if (typeof window === 'undefined') {
|
|
||||||
throw new Error('BrowserWebSocket cannot be used outside of a browser environment')
|
|
||||||
}
|
|
||||||
|
|
||||||
this._ws = new window.WebSocket(url)
|
|
||||||
this._ws.onopen = () => this.emit('open')
|
|
||||||
this._ws.onmessage = this._onMessage.bind(this)
|
|
||||||
this._ws.onerror = (event) => this.emit('error', new BrowserWebSocketError('Unknown error', event))
|
|
||||||
this._ws.onclose = (event) => this.emit('close', event.code, event.reason)
|
|
||||||
}
|
|
||||||
|
|
||||||
get readyState() {
|
|
||||||
return this._ws.readyState
|
|
||||||
}
|
|
||||||
|
|
||||||
static get CONNECTING() {
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
static set CONNECTING(state: number) {
|
|
||||||
BrowserWebSocket.CONNECTING = state
|
|
||||||
}
|
|
||||||
|
|
||||||
static get OPEN() {
|
|
||||||
return 1
|
|
||||||
}
|
|
||||||
|
|
||||||
static set OPEN(state: number) {
|
|
||||||
BrowserWebSocket.OPEN = state
|
|
||||||
}
|
|
||||||
|
|
||||||
static get CLOSING() {
|
|
||||||
return 2
|
|
||||||
}
|
|
||||||
|
|
||||||
static set CLOSING(state: number) {
|
|
||||||
BrowserWebSocket.CLOSING = state
|
|
||||||
}
|
|
||||||
|
|
||||||
static get CLOSED() {
|
|
||||||
return 3
|
|
||||||
}
|
|
||||||
|
|
||||||
static set CLOSED(state: number) {
|
|
||||||
BrowserWebSocket.CLOSED = state
|
|
||||||
}
|
|
||||||
|
|
||||||
close(code?: number, reason?: string) {
|
|
||||||
return this._ws.close(code, reason)
|
|
||||||
}
|
|
||||||
|
|
||||||
removeEventListener(type: string | symbol, listener: (...args: any[]) => void): this {
|
|
||||||
return this.removeListener(type, listener)
|
|
||||||
}
|
|
||||||
|
|
||||||
send(data: string | ArrayBufferLike | Blob | ArrayBufferView) {
|
|
||||||
return this._ws.send(data)
|
|
||||||
}
|
|
||||||
|
|
||||||
terminate() {
|
|
||||||
return this._ws.close()
|
|
||||||
}
|
|
||||||
|
|
||||||
async _onMessage(event: MessageEvent<any>) {
|
|
||||||
if (event.data instanceof window.Blob) {
|
|
||||||
this.emit('message', await event.data.arrayBuffer())
|
|
||||||
} else {
|
|
||||||
this.emit('message', event.data)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default BrowserWebSocket
|
|
||||||
@@ -1,102 +0,0 @@
|
|||||||
/* eslint-disable @typescript-eslint/explicit-function-return-type */
|
|
||||||
interface BucketOptions {
|
|
||||||
latencyRef?: { latency: number }
|
|
||||||
reservedTokens?: number
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handle ratelimiting something
|
|
||||||
* @prop {Number} interval How long (in ms) to wait between clearing used tokens
|
|
||||||
* @prop {Number} lastReset Timestamp of last token clearing
|
|
||||||
* @prop {Number} lastSend Timestamp of last token consumption
|
|
||||||
* @prop {Number} tokenLimit The max number tokens the bucket can consume per interval
|
|
||||||
* @prop {Number} tokens How many tokens the bucket has consumed in this interval
|
|
||||||
*/
|
|
||||||
class Bucket {
|
|
||||||
interval: number
|
|
||||||
latencyRef: { latency: number }
|
|
||||||
lastReset: number
|
|
||||||
lastSend: number
|
|
||||||
tokenLimit: number
|
|
||||||
tokens: number
|
|
||||||
reservedTokens: number
|
|
||||||
// eslint-disable-next-line @typescript-eslint/ban-types
|
|
||||||
_queue: Array<{ func: Function; priority: boolean }>
|
|
||||||
timeout: NodeJS.Timeout | null = null
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Construct a Bucket
|
|
||||||
* @arg {Number} tokenLimit The max number of tokens the bucket can consume per interval
|
|
||||||
* @arg {Number} interval How long (in ms) to wait between clearing used tokens
|
|
||||||
* @arg {Object} [options] Optional parameters
|
|
||||||
* @arg {Object} options.latencyRef A latency reference object
|
|
||||||
* @arg {Number} options.latencyRef.latency Interval between consuming tokens
|
|
||||||
* @arg {Number} options.reservedTokens How many tokens to reserve for priority operations
|
|
||||||
*/
|
|
||||||
constructor(tokenLimit: number, interval: number, options: BucketOptions = {} as BucketOptions) {
|
|
||||||
this.tokenLimit = tokenLimit
|
|
||||||
this.interval = interval
|
|
||||||
this.latencyRef = options.latencyRef ?? { latency: 0 }
|
|
||||||
this.lastReset = this.tokens = this.lastSend = 0
|
|
||||||
this.reservedTokens = options.reservedTokens ?? 0
|
|
||||||
this._queue = []
|
|
||||||
}
|
|
||||||
|
|
||||||
check() {
|
|
||||||
if (this.timeout ?? this._queue.length === 0) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if (this.lastReset + this.interval + this.tokenLimit * this.latencyRef.latency < Date.now()) {
|
|
||||||
this.lastReset = Date.now()
|
|
||||||
this.tokens = Math.max(0, this.tokens - this.tokenLimit)
|
|
||||||
}
|
|
||||||
|
|
||||||
let val
|
|
||||||
let tokensAvailable = this.tokens < this.tokenLimit
|
|
||||||
let unreservedTokensAvailable = this.tokens < this.tokenLimit - this.reservedTokens
|
|
||||||
while (this._queue.length > 0 && (unreservedTokensAvailable || (tokensAvailable && this._queue[0].priority))) {
|
|
||||||
this.tokens++
|
|
||||||
tokensAvailable = this.tokens < this.tokenLimit
|
|
||||||
unreservedTokensAvailable = this.tokens < this.tokenLimit - this.reservedTokens
|
|
||||||
const item = this._queue.shift()
|
|
||||||
val = this.latencyRef.latency - Date.now() + this.lastSend
|
|
||||||
if (this.latencyRef.latency === 0 || val <= 0) {
|
|
||||||
item!.func()
|
|
||||||
this.lastSend = Date.now()
|
|
||||||
} else {
|
|
||||||
setTimeout(() => {
|
|
||||||
item!.func()
|
|
||||||
}, val)
|
|
||||||
this.lastSend = Date.now() + val
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this._queue.length > 0 && !this.timeout) {
|
|
||||||
this.timeout = setTimeout(
|
|
||||||
() => {
|
|
||||||
this.timeout = null
|
|
||||||
this.check()
|
|
||||||
},
|
|
||||||
this.tokens < this.tokenLimit
|
|
||||||
? this.latencyRef.latency
|
|
||||||
: Math.max(0, this.lastReset + this.interval + this.tokenLimit * this.latencyRef.latency - Date.now()),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Queue something in the Bucket
|
|
||||||
* @arg {Function} func A callback to call when a token can be consumed
|
|
||||||
* @arg {Boolean} [priority=false] Whether or not the callback should use reserved tokens
|
|
||||||
*/
|
|
||||||
queue(func: () => void, priority = false) {
|
|
||||||
if (priority) {
|
|
||||||
this._queue.unshift({ func, priority })
|
|
||||||
} else {
|
|
||||||
this._queue.push({ func, priority })
|
|
||||||
}
|
|
||||||
this.check()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default Bucket
|
|
||||||
@@ -1,86 +0,0 @@
|
|||||||
import type { ClientRequest, IncomingHttpHeaders, IncomingMessage } from 'http'
|
|
||||||
import type { HTTPResponse } from '../typings.js'
|
|
||||||
|
|
||||||
export class DiscordRESTError extends Error {
|
|
||||||
code: number = -1
|
|
||||||
req!: ClientRequest
|
|
||||||
res!: IncomingMessage
|
|
||||||
response!: HTTPResponse
|
|
||||||
|
|
||||||
constructor(req: ClientRequest, res: IncomingMessage, response: HTTPResponse, stack: string) {
|
|
||||||
super()
|
|
||||||
|
|
||||||
Object.defineProperty(this, 'req', {
|
|
||||||
enumerable: false,
|
|
||||||
value: req,
|
|
||||||
})
|
|
||||||
Object.defineProperty(this, 'res', {
|
|
||||||
enumerable: false,
|
|
||||||
value: res,
|
|
||||||
})
|
|
||||||
Object.defineProperty(this, 'response', {
|
|
||||||
enumerable: false,
|
|
||||||
value: response,
|
|
||||||
})
|
|
||||||
|
|
||||||
Object.defineProperty(this, 'code', {
|
|
||||||
enumerable: false,
|
|
||||||
value: +response.code || -1,
|
|
||||||
})
|
|
||||||
let message = response.message || 'Unknown error'
|
|
||||||
if (response.errors) {
|
|
||||||
message += '\n ' + this.flattenErrors(response.errors).join('\n ')
|
|
||||||
} else {
|
|
||||||
const errors = this.flattenErrors(response)
|
|
||||||
if (errors.length > 0) {
|
|
||||||
message += '\n ' + errors.join('\n ')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Object.defineProperty(this, 'message', {
|
|
||||||
enumerable: false,
|
|
||||||
value: message,
|
|
||||||
})
|
|
||||||
|
|
||||||
if (stack) {
|
|
||||||
this.stack = this.name + ': ' + this.message + '\n' + stack
|
|
||||||
} else {
|
|
||||||
Error.captureStackTrace(this, DiscordRESTError)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
get headers(): IncomingHttpHeaders {
|
|
||||||
return this.response.headers
|
|
||||||
}
|
|
||||||
|
|
||||||
get name(): string {
|
|
||||||
return `${this.constructor.name} [${this.code}]`
|
|
||||||
}
|
|
||||||
|
|
||||||
flattenErrors(errors: HTTPResponse, keyPrefix?: string): string[] {
|
|
||||||
let messages: string[] = []
|
|
||||||
for (const fieldName of Object.keys(errors)) {
|
|
||||||
if (fieldName === 'message' || fieldName === 'code') {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
const prefix = `${keyPrefix ?? ""}${fieldName}`;
|
|
||||||
|
|
||||||
// @ts-expect-error js hack from eris
|
|
||||||
if (errors[fieldName]._errors) {
|
|
||||||
// @ts-expect-error js hack from eris
|
|
||||||
messages = messages.concat(errors[fieldName]._errors.map((obj: any) => `${prefix}: ${obj.message as string}`))
|
|
||||||
// @ts-expect-error js hack from eris
|
|
||||||
} else if (Array.isArray(errors[fieldName])) {
|
|
||||||
// @ts-expect-error js hack from eris
|
|
||||||
messages = messages.concat(errors[fieldName].map((str: string) => `${prefix}: ${str}`))
|
|
||||||
// @ts-expect-error js hack from eris
|
|
||||||
} else if (typeof errors[fieldName] === 'object') {
|
|
||||||
// @ts-expect-error js hack from eris
|
|
||||||
messages = messages.concat(this.flattenErrors(errors[fieldName], `${prefix}.`))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return messages
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default DiscordRESTError
|
|
||||||
@@ -1,85 +0,0 @@
|
|||||||
import type { DiscordChannel, DiscordInteraction } from '@discordeno/types'
|
|
||||||
import { ChannelTypes, InteractionTypes } from '@discordeno/types'
|
|
||||||
import type Client from '../Client.js'
|
|
||||||
import type { TextableChannel } from '../index.js'
|
|
||||||
import CategoryChannel from '../Structures/channels/Category.js'
|
|
||||||
import Channel from '../Structures/channels/Channel.js'
|
|
||||||
import GuildChannel from '../Structures/channels/Guild.js'
|
|
||||||
import NewsChannel from '../Structures/channels/News.js'
|
|
||||||
import PrivateChannel from '../Structures/channels/Private.js'
|
|
||||||
import StageChannel from '../Structures/channels/Stage.js'
|
|
||||||
import TextChannel from '../Structures/channels/Text.js'
|
|
||||||
import TextVoiceChannel from '../Structures/channels/TextVoice.js'
|
|
||||||
import NewsThreadChannel from '../Structures/channels/threads/NewsThread.js'
|
|
||||||
import PrivateThreadChannel from '../Structures/channels/threads/PrivateThread.js'
|
|
||||||
import PublicThreadChannel from '../Structures/channels/threads/PublicThread.js'
|
|
||||||
import AutocompleteInteraction from '../Structures/interactions/Autocomplete.js'
|
|
||||||
import CommandInteraction from '../Structures/interactions/Command.js'
|
|
||||||
import ComponentInteraction from '../Structures/interactions/Component.js'
|
|
||||||
import PingInteraction from '../Structures/interactions/Ping.js'
|
|
||||||
import UnknownInteraction from '../Structures/interactions/Unknown.js'
|
|
||||||
|
|
||||||
export function generateChannelFrom(data: DiscordChannel, client: Client): Channel {
|
|
||||||
switch (data.type) {
|
|
||||||
case ChannelTypes.GuildText: {
|
|
||||||
return new TextChannel(data, client)
|
|
||||||
}
|
|
||||||
case ChannelTypes.DM: {
|
|
||||||
return new PrivateChannel(data, client)
|
|
||||||
}
|
|
||||||
case ChannelTypes.GuildVoice: {
|
|
||||||
return new TextVoiceChannel(data, client)
|
|
||||||
}
|
|
||||||
case ChannelTypes.GuildCategory: {
|
|
||||||
return new CategoryChannel(data, client)
|
|
||||||
}
|
|
||||||
case ChannelTypes.GuildAnnouncement: {
|
|
||||||
return new NewsChannel(data, client)
|
|
||||||
}
|
|
||||||
case ChannelTypes.AnnouncementThread: {
|
|
||||||
return new NewsThreadChannel(data, client)
|
|
||||||
}
|
|
||||||
case ChannelTypes.PublicThread: {
|
|
||||||
return new PublicThreadChannel(data, client)
|
|
||||||
}
|
|
||||||
case ChannelTypes.PrivateThread: {
|
|
||||||
return new PrivateThreadChannel(data, client)
|
|
||||||
}
|
|
||||||
case ChannelTypes.GuildStageVoice: {
|
|
||||||
return new StageChannel(data, client)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (data.guild_id) {
|
|
||||||
if (data.last_message_id !== undefined) {
|
|
||||||
client.emit('warn', new Error(`Unknown guild text channel type: ${data.type}\n${JSON.stringify(data)}`))
|
|
||||||
return new TextChannel(data, client)
|
|
||||||
}
|
|
||||||
client.emit('warn', new Error(`Unknown guild channel type: ${data.type}\n${JSON.stringify(data)}`))
|
|
||||||
return new GuildChannel(data, client)
|
|
||||||
}
|
|
||||||
client.emit('warn', new Error(`Unknown channel type: ${data.type}\n${JSON.stringify(data)}`))
|
|
||||||
return new Channel(data, client)
|
|
||||||
}
|
|
||||||
|
|
||||||
export function generateInteractionFrom(
|
|
||||||
data: DiscordInteraction,
|
|
||||||
client: Client,
|
|
||||||
): UnknownInteraction<TextableChannel> | PingInteraction | CommandInteraction | ComponentInteraction | AutocompleteInteraction {
|
|
||||||
switch (data.type) {
|
|
||||||
case InteractionTypes.Ping: {
|
|
||||||
return new PingInteraction(data, client)
|
|
||||||
}
|
|
||||||
case InteractionTypes.ApplicationCommand: {
|
|
||||||
return new CommandInteraction(data, client)
|
|
||||||
}
|
|
||||||
case InteractionTypes.MessageComponent: {
|
|
||||||
return new ComponentInteraction(data, client)
|
|
||||||
}
|
|
||||||
case InteractionTypes.ApplicationCommandAutocomplete: {
|
|
||||||
return new AutocompleteInteraction(data, client)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
client.emit('warn', new Error(`Unknown interaction type: ${data.type}\n${JSON.stringify(data)}`))
|
|
||||||
return new UnknownInteraction(data, client)
|
|
||||||
}
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
import { describe, it } from 'mocha'
|
|
||||||
|
|
||||||
describe('index.ts', () => {
|
|
||||||
it('will import without error', async () => {
|
|
||||||
await import('../src/index.js')
|
|
||||||
})
|
|
||||||
})
|
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
{
|
|
||||||
"extends": "tsconfig/base.json",
|
|
||||||
"compilerOptions": {
|
|
||||||
"outDir": "./dist",
|
|
||||||
},
|
|
||||||
"include": [
|
|
||||||
"./src/**/*.ts",
|
|
||||||
"./src/**/*.tsx"
|
|
||||||
],
|
|
||||||
"exclude": [
|
|
||||||
"node_modules",
|
|
||||||
"dist",
|
|
||||||
"test",
|
|
||||||
"tests"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
{
|
|
||||||
"extends": "tsconfig/test.json",
|
|
||||||
"include": [
|
|
||||||
"tests",
|
|
||||||
],
|
|
||||||
"exclude": [
|
|
||||||
"node_modules",
|
|
||||||
"dist",
|
|
||||||
"src"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
@@ -147,9 +147,6 @@ describe('bucket.ts', () => {
|
|||||||
await bucket.acquire()
|
await bucket.acquire()
|
||||||
expect(bucket.remaining).equals(0)
|
expect(bucket.remaining).equals(0)
|
||||||
expect(bucket.used).equals(1)
|
expect(bucket.used).equals(1)
|
||||||
// await clock.tickAsync(600)
|
|
||||||
// expect(bucket.remaining).equals(1)
|
|
||||||
// expect(bucket.used).equals(0)
|
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -40,13 +40,11 @@ for await (let filepath of walk(typedocOutPath)) {
|
|||||||
// Converts ugly names to clean names for example discordeno_types.ActionRow becomes ActionRow
|
// Converts ugly names to clean names for example discordeno_types.ActionRow becomes ActionRow
|
||||||
const cleanForms = [
|
const cleanForms = [
|
||||||
{ ugly: 'discordeno_bot.md', clean: 'Bot.md'},
|
{ ugly: 'discordeno_bot.md', clean: 'Bot.md'},
|
||||||
{ ugly: 'discordeno_client.md', clean: 'Client.md'},
|
|
||||||
{ ugly: 'discordeno_gateway.md', clean: 'Gateway.md'},
|
{ ugly: 'discordeno_gateway.md', clean: 'Gateway.md'},
|
||||||
{ ugly: 'discordeno_rest.md', clean: 'Rest.md'},
|
{ ugly: 'discordeno_rest.md', clean: 'Rest.md'},
|
||||||
{ ugly: 'discordeno_types.md', clean: 'Types.md'},
|
{ ugly: 'discordeno_types.md', clean: 'Types.md'},
|
||||||
{ ugly: 'discordeno_utils.md', clean: 'Utils.md'},
|
{ ugly: 'discordeno_utils.md', clean: 'Utils.md'},
|
||||||
{ ugly: 'discordeno_bot.' },
|
{ ugly: 'discordeno_bot.' },
|
||||||
{ ugly: 'discordeno_client.' },
|
|
||||||
{ ugly: 'discordeno_gateway.' },
|
{ ugly: 'discordeno_gateway.' },
|
||||||
{ ugly: 'discordeno_rest.' },
|
{ ugly: 'discordeno_rest.' },
|
||||||
{ ugly: 'discordeno_types.' },
|
{ ugly: 'discordeno_types.' },
|
||||||
|
|||||||
@@ -2,7 +2,6 @@
|
|||||||
"entryPointStrategy": "packages",
|
"entryPointStrategy": "packages",
|
||||||
"entryPoints": [
|
"entryPoints": [
|
||||||
"packages/bot",
|
"packages/bot",
|
||||||
"packages/client",
|
|
||||||
"packages/gateway",
|
"packages/gateway",
|
||||||
"packages/rest",
|
"packages/rest",
|
||||||
"packages/types",
|
"packages/types",
|
||||||
|
|||||||
@@ -236,7 +236,7 @@ One of the last things we should do, is make it possible to run commands on this
|
|||||||
Let's make a small bot on this process. Make a file called `services/rest/bot.ts`. Then paste the code below.
|
Let's make a small bot on this process. Make a file called `services/rest/bot.ts`. Then paste the code below.
|
||||||
|
|
||||||
```ts
|
```ts
|
||||||
import { Client } from '@discordeno/client'
|
import { createBot } from '@discordeno/bot'
|
||||||
import { logger } from '@discordeno/utils'
|
import { logger } from '@discordeno/utils'
|
||||||
import * as util from 'util'
|
import * as util from 'util'
|
||||||
|
|
||||||
@@ -244,11 +244,11 @@ const inspectOptions = {
|
|||||||
depth: 1
|
depth: 1
|
||||||
}
|
}
|
||||||
|
|
||||||
const client = new Client(process.env.TOKEN, {
|
const bot = createBot({
|
||||||
// client options here
|
token: process.env.TOKEN,
|
||||||
})
|
events: {
|
||||||
|
// This is just to keep code short for the guide, there are cleaner ways to write events.
|
||||||
client.on('messageCreate', (message) => {
|
async messageCreate(message) {
|
||||||
// If the message is from a bot simply ignore
|
// If the message is from a bot simply ignore
|
||||||
if (message.author.bot) return
|
if (message.author.bot) return
|
||||||
// If the message is not from bot owner simply ignore
|
// If the message is not from bot owner simply ignore
|
||||||
@@ -289,6 +289,8 @@ client.on('messageCreate', (message) => {
|
|||||||
response.push('```')
|
response.push('```')
|
||||||
|
|
||||||
await message.channel.createMessage(response.join('\n'))
|
await message.channel.createMessage(response.join('\n'))
|
||||||
|
}
|
||||||
|
}
|
||||||
})
|
})
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|||||||
@@ -7,7 +7,6 @@
|
|||||||
### Modules
|
### Modules
|
||||||
|
|
||||||
- [@discordeno/bot](modules/Bot.md)
|
- [@discordeno/bot](modules/Bot.md)
|
||||||
- [@discordeno/client](modules/Client.md)
|
|
||||||
- [@discordeno/gateway](modules/Gateway.md)
|
- [@discordeno/gateway](modules/Gateway.md)
|
||||||
- [@discordeno/rest](modules/Rest.md)
|
- [@discordeno/rest](modules/Rest.md)
|
||||||
- [@discordeno/types](modules/Types.md)
|
- [@discordeno/types](modules/Types.md)
|
||||||
|
|||||||
@@ -12,9 +12,8 @@ Discordeno is actively maintained to guarantee **excellent performance, latest f
|
|||||||
|
|
||||||
- **Simple, Efficient, and Lightweight**: Discordeno is lightweight, simple to use, and adaptable.
|
- **Simple, Efficient, and Lightweight**: Discordeno is lightweight, simple to use, and adaptable.
|
||||||
- By default: No caching.
|
- By default: No caching.
|
||||||
- **Functional & Class API**: Discordeno is flexible enough to provide both methods.
|
- **Functional API**:
|
||||||
- The functional API eliminates the challenges of extending built-in classes and inheritance while ensuring overall simple but performant code.
|
- The functional API eliminates the challenges of extending built-in classes and inheritance while ensuring overall simple but performant code.
|
||||||
- The class based API, client package, provides a similar api as the [Eris](https://github.com/abalabahaha/eris) library to provide the best class based experience.
|
|
||||||
- **Cross Runtime**: Supports the Node.js, Deno, and Bun runtimes.
|
- **Cross Runtime**: Supports the Node.js, Deno, and Bun runtimes.
|
||||||
- **Standalone components**: Discordeno offers the option to have practically any component of a bot as a separate
|
- **Standalone components**: Discordeno offers the option to have practically any component of a bot as a separate
|
||||||
piece, including standalone REST, gateways, custom caches, and more.
|
piece, including standalone REST, gateways, custom caches, and more.
|
||||||
|
|||||||
@@ -5,75 +5,5 @@ sidebar_label: Eris To Discordeno
|
|||||||
|
|
||||||
# Migrating From Eris To Discordeno Guide
|
# Migrating From Eris To Discordeno Guide
|
||||||
|
|
||||||
## Understanding The Goals of This Guide
|
1. Fix code to be better.
|
||||||
|
2. Enjoy
|
||||||
This guide is a quick-paced walkthrough meant for explaining the migration process for Eris bots to using Discordeno. If you are not sure whether you want to migrate, please read [Should I Migrate?](../intro.md)
|
|
||||||
|
|
||||||
## TypeScript
|
|
||||||
|
|
||||||
I really hope you wrote your bot with TypeScript as it is going to save you a lot of time. If you have not written it in TypeScript, you should probably start now. Using this migrating as a push to switch to TypeScript.
|
|
||||||
|
|
||||||
If your bot is using TypeScript, this migration will be a lot easier.
|
|
||||||
|
|
||||||
First, update typescript to the latest version available. This will be required if your bot is using a much older version. Discordeno uses the leverages the latest and greatest TypeScript features. Please make sure you have the latest version of typescript before going forward.
|
|
||||||
|
|
||||||
## ESM
|
|
||||||
|
|
||||||
If you are using a runtime like Deno that supports ESM from the get go then this step is not required.
|
|
||||||
|
|
||||||
Discordeno uses ESM. More than likely, your bot does not use it and if you do not know what ESM is don't worry. It's just the new standard of using JavaScript. Let's keep it simple, to make Discordeno work add `"type": "module"` to your `package.json` file.
|
|
||||||
|
|
||||||
Next go to your tsconfig.json file:
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"module": "ES2022",
|
|
||||||
"target": "ES2022",
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
:::tip
|
|
||||||
You can use any version above ES2022 should you be reading this guide in the future and it is not updated.
|
|
||||||
- P.S. If it is not updated, blame Yui!!! 🤣
|
|
||||||
:::
|
|
||||||
|
|
||||||
## Getting Started
|
|
||||||
|
|
||||||
Open up a terminal and run `tsc --watch --noEmit` to keep TypeScript warning of us of errors that may appear as we migrate.
|
|
||||||
|
|
||||||
Once you are ready, let's go ahead and install Discordeno, while we are at it we can uninstall eris. Open a new terminal and run the following command for the package manager you use:
|
|
||||||
|
|
||||||
```ts
|
|
||||||
// NPM users
|
|
||||||
npm uninstall eris && npm install @discordeno/client@19.0.0-next.99fbe1e
|
|
||||||
// Yarn users
|
|
||||||
yarn remove eris && yarn add @discordeno/client@19.0.0-next.99fbe1e
|
|
||||||
```
|
|
||||||
|
|
||||||
:::caution
|
|
||||||
Currently, Discordeno v19 is in development. This is why you can not install it as @discordeno/client but have to specify the commit version. Once this version is released, it will be as easy as `@discordeno/client`.
|
|
||||||
:::
|
|
||||||
|
|
||||||
We are going to use [NayuBot](https://github.com/AwesomeStickz/Nayu-Bot) which is a small bot written in TypeScript with Eris and is open source as the example we are going to migrate to Discordeno.
|
|
||||||
|
|
||||||
At this moment in time, the tsc terminal(from now on we are going to refer to this as TypeScript), is telling us we have 13 errors. This is because when we removed eris, we also need to fix any imports it may have. So let's run a search in VSC to find any `from 'eris';` and `from "eris"`. We need to replace these with `from '@discordeno/client'` and `from "@discordeno/client"`.
|
|
||||||
|
|
||||||
## Intents
|
|
||||||
|
|
||||||
Eris was still using an older version of the api. This meant, that intents like MessageContent was not yet supported. When switching to Discordeno, we use the latest API version possible to provide the best experience possible. This requires that if your bot needs the `MessageContent` intent, that it provide it in the intents.
|
|
||||||
|
|
||||||
```ts
|
|
||||||
// If your code is a number like this, update the number.
|
|
||||||
intents: 4086,
|
|
||||||
// If your code is an array, add Intents.MessageContent
|
|
||||||
intents: ["guilds", "guildMessages", Intents.MessageContent],
|
|
||||||
```
|
|
||||||
|
|
||||||
## Known Issues
|
|
||||||
|
|
||||||
Currently, there are a few issues with the migration.
|
|
||||||
|
|
||||||
- `voice` - Currently **@discordeno/client** does not support voice features. Until we have a large music bot with the desire to migrate to discordeno we don't plan to support this as it is a massive endeavor. It will require a willing developer with good ability to test our implementation and make sure it scales well, like the rest of discordeno. If you are a music bot developer looking to migrate, and are willing to work with us to support this, please do contact me on Discord.
|
|
||||||
- `selfbots/userbots` - Eris supported a lot of selfbot features that Discordeno does not. All of these features were removed. If you are trying to migrate a self bot, you will not be able to access a lot of features. This will never be supported. Please don't ask.
|
|
||||||
- `command frameworks` - If you made your bot with a command framework package such as Yuuko, you may have some issues. This is because that package itself depends on Eris. It would need updating to support **@discordeno/client** instead of Eris. In a near future, when both typescript and node.js, you will be able to use *import maps* to replace all instance of eris with discordeno in all your packages.
|
|
||||||
- `deprecations` - If your bot was written using old code that Eris had marked as deprecated, we removed that behavior. Take this time, to fix those few errors in the new cleaner fashion. The following is a list of reported methods that were effected:
|
|
||||||
- getMessages
|
|
||||||
|
|||||||
26
yarn.lock
26
yarn.lock
@@ -47,32 +47,6 @@ __metadata:
|
|||||||
languageName: unknown
|
languageName: unknown
|
||||||
linkType: soft
|
linkType: soft
|
||||||
|
|
||||||
"@discordeno/client@workspace:packages/client":
|
|
||||||
version: 0.0.0-use.local
|
|
||||||
resolution: "@discordeno/client@workspace:packages/client"
|
|
||||||
dependencies:
|
|
||||||
"@discordeno/gateway": 19.0.0-alpha.1
|
|
||||||
"@discordeno/rest": 19.0.0-alpha.1
|
|
||||||
"@discordeno/types": 19.0.0-alpha.1
|
|
||||||
"@discordeno/utils": 19.0.0-alpha.1
|
|
||||||
"@swc/cli": ^0.1.62
|
|
||||||
"@swc/core": ^1.3.40
|
|
||||||
"@types/chai": ^4.3.4
|
|
||||||
"@types/mocha": ^10.0.1
|
|
||||||
"@types/node": ^18.15.3
|
|
||||||
"@types/sinon": ^10.0.13
|
|
||||||
c8: ^7.13.0
|
|
||||||
chai: ^4.3.7
|
|
||||||
eslint: ^8.36.0
|
|
||||||
eslint-config-discordeno: "*"
|
|
||||||
mocha: ^10.2.0
|
|
||||||
sinon: ^15.0.2
|
|
||||||
ts-node: ^10.9.1
|
|
||||||
tsconfig: "*"
|
|
||||||
typescript: ^4.9.5
|
|
||||||
languageName: unknown
|
|
||||||
linkType: soft
|
|
||||||
|
|
||||||
"@discordeno/gateway@19.0.0-alpha.1, @discordeno/gateway@workspace:packages/gateway":
|
"@discordeno/gateway@19.0.0-alpha.1, @discordeno/gateway@workspace:packages/gateway":
|
||||||
version: 0.0.0-use.local
|
version: 0.0.0-use.local
|
||||||
resolution: "@discordeno/gateway@workspace:packages/gateway"
|
resolution: "@discordeno/gateway@workspace:packages/gateway"
|
||||||
|
|||||||
Reference in New Issue
Block a user