mirror of
https://github.com/discordjs/discord.js.git
synced 2026-05-23 03:50:09 +00:00
Compare commits
9 Commits
@discordjs
...
@discordjs
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
52a9e213c2 | ||
|
|
b7e62380f2 | ||
|
|
cafde77d73 | ||
|
|
b7d4e55419 | ||
|
|
5aeed99350 | ||
|
|
452dec57ca | ||
|
|
64f814066c | ||
|
|
33a7a5cbdc | ||
|
|
edf83f02ea |
73
packages/builders/__tests__/components/components.test.ts
Normal file
73
packages/builders/__tests__/components/components.test.ts
Normal file
@@ -0,0 +1,73 @@
|
||||
import {
|
||||
APIActionRowComponent,
|
||||
APIButtonComponent,
|
||||
APIMessageActionRowComponent,
|
||||
APISelectMenuComponent,
|
||||
APITextInputComponent,
|
||||
ButtonStyle,
|
||||
ComponentType,
|
||||
TextInputStyle,
|
||||
} from 'discord-api-types/v10';
|
||||
import { describe, test, expect } from 'vitest';
|
||||
import {
|
||||
ActionRowBuilder,
|
||||
ButtonBuilder,
|
||||
createComponentBuilder,
|
||||
SelectMenuBuilder,
|
||||
TextInputBuilder,
|
||||
} from '../../src/index';
|
||||
|
||||
describe('createComponentBuilder', () => {
|
||||
test.each([ButtonBuilder, SelectMenuBuilder, TextInputBuilder])(
|
||||
'passing an instance of %j should return itself',
|
||||
(Builder) => {
|
||||
const builder = new Builder();
|
||||
expect(createComponentBuilder(builder)).toBe(builder);
|
||||
},
|
||||
);
|
||||
|
||||
test('GIVEN an action row component THEN returns a ActionRowBuilder', () => {
|
||||
const actionRow: APIActionRowComponent<APIMessageActionRowComponent> = {
|
||||
components: [],
|
||||
type: ComponentType.ActionRow,
|
||||
};
|
||||
|
||||
expect(createComponentBuilder(actionRow)).toBeInstanceOf(ActionRowBuilder);
|
||||
});
|
||||
|
||||
test('GIVEN a button component THEN returns a ButtonBuilder', () => {
|
||||
const button: APIButtonComponent = {
|
||||
custom_id: 'abc',
|
||||
style: ButtonStyle.Primary,
|
||||
type: ComponentType.Button,
|
||||
};
|
||||
|
||||
expect(createComponentBuilder(button)).toBeInstanceOf(ButtonBuilder);
|
||||
});
|
||||
|
||||
test('GIVEN a select menu component THEN returns a SelectMenuBuilder', () => {
|
||||
const selectMenu: APISelectMenuComponent = {
|
||||
custom_id: 'abc',
|
||||
options: [],
|
||||
type: ComponentType.SelectMenu,
|
||||
};
|
||||
|
||||
expect(createComponentBuilder(selectMenu)).toBeInstanceOf(SelectMenuBuilder);
|
||||
});
|
||||
|
||||
test('GIVEN a text input component THEN returns a TextInputBuilder', () => {
|
||||
const textInput: APITextInputComponent = {
|
||||
custom_id: 'abc',
|
||||
label: 'abc',
|
||||
style: TextInputStyle.Short,
|
||||
type: ComponentType.TextInput,
|
||||
};
|
||||
|
||||
expect(createComponentBuilder(textInput)).toBeInstanceOf(TextInputBuilder);
|
||||
});
|
||||
|
||||
test('GIVEN an unknown component type THEN throws error', () => {
|
||||
// @ts-expect-error
|
||||
expect(() => createComponentBuilder({ type: 'invalid' })).toThrowError();
|
||||
});
|
||||
});
|
||||
@@ -86,6 +86,10 @@ describe('Context Menu Commands', () => {
|
||||
test('GIVEN valid builder with defaultPermission false THEN does not throw error', () => {
|
||||
expect(() => getBuilder().setName('foo').setDefaultPermission(false)).not.toThrowError();
|
||||
});
|
||||
|
||||
test('GIVEN valid builder with dmPermission false THEN does not throw error', () => {
|
||||
expect(() => getBuilder().setName('foo').setDMPermission(false)).not.toThrowError();
|
||||
});
|
||||
});
|
||||
|
||||
describe('Context menu command localizations', () => {
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import {
|
||||
APIApplicationCommandAttachmentOption,
|
||||
APIApplicationCommandBooleanOption,
|
||||
APIApplicationCommandChannelOption,
|
||||
APIApplicationCommandIntegerOption,
|
||||
@@ -12,6 +13,7 @@ import {
|
||||
} from 'discord-api-types/v10';
|
||||
import { describe, test, expect } from 'vitest';
|
||||
import {
|
||||
SlashCommandAttachmentOption,
|
||||
SlashCommandBooleanOption,
|
||||
SlashCommandChannelOption,
|
||||
SlashCommandIntegerOption,
|
||||
@@ -58,6 +60,9 @@ const getRoleOption = () => new SlashCommandRoleOption().setName('owo').setDescr
|
||||
const getMentionableOption = () =>
|
||||
new SlashCommandMentionableOption().setName('owo').setDescription('Testing 123').setRequired(true);
|
||||
|
||||
const getAttachmentOption = () =>
|
||||
new SlashCommandAttachmentOption().setName('attachment').setDescription('attachment').setRequired(true);
|
||||
|
||||
describe('Application Command toJSON() results', () => {
|
||||
test('GIVEN a boolean option THEN calling toJSON should return a valid JSON', () => {
|
||||
expect(getBooleanOption().toJSON()).toEqual<APIApplicationCommandBooleanOption>({
|
||||
@@ -205,4 +210,13 @@ describe('Application Command toJSON() results', () => {
|
||||
required: true,
|
||||
});
|
||||
});
|
||||
|
||||
test('GIVEN an attachment option THEN calling toJSON should return a valid JSON', () => {
|
||||
expect(getAttachmentOption().toJSON()).toEqual<APIApplicationCommandAttachmentOption>({
|
||||
name: 'attachment',
|
||||
description: 'attachment',
|
||||
type: ApplicationCommandOptionType.Attachment,
|
||||
required: true,
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -93,6 +93,7 @@ describe('Slash Commands', () => {
|
||||
test('GIVEN valid array of options or choices THEN does not throw error', () => {
|
||||
expect(() => SlashCommandAssertions.validateMaxOptionsLength([])).not.toThrowError();
|
||||
|
||||
expect(() => SlashCommandAssertions.validateChoicesLength(25)).not.toThrowError();
|
||||
expect(() => SlashCommandAssertions.validateChoicesLength(25, [])).not.toThrowError();
|
||||
});
|
||||
|
||||
@@ -133,6 +134,7 @@ describe('Slash Commands', () => {
|
||||
getBuilder()
|
||||
.setName('example')
|
||||
.setDescription('Example command')
|
||||
.setDMPermission(false)
|
||||
.addBooleanOption((boolean) =>
|
||||
boolean.setName('iscool').setDescription('Are we cool or what?').setRequired(true),
|
||||
)
|
||||
|
||||
@@ -1,4 +1,9 @@
|
||||
import { APIModalInteractionResponseCallbackData, ComponentType, TextInputStyle } from 'discord-api-types/v10';
|
||||
import {
|
||||
APIModalInteractionResponseCallbackData,
|
||||
APITextInputComponent,
|
||||
ComponentType,
|
||||
TextInputStyle,
|
||||
} from 'discord-api-types/v10';
|
||||
import { describe, test, expect } from 'vitest';
|
||||
import {
|
||||
ActionRowBuilder,
|
||||
@@ -49,16 +54,18 @@ describe('Modals', () => {
|
||||
|
||||
test('GIVEN valid fields THEN builder does not throw', () => {
|
||||
expect(() =>
|
||||
modal()
|
||||
.setTitle('test')
|
||||
.setCustomId('foobar')
|
||||
.setComponents(new ActionRowBuilder())
|
||||
.addComponents([new ActionRowBuilder()]),
|
||||
modal().setTitle('test').setCustomId('foobar').setComponents(new ActionRowBuilder()),
|
||||
).not.toThrowError();
|
||||
|
||||
expect(() =>
|
||||
// @ts-expect-error: You can pass a TextInputBuilder and it will add it to an action row
|
||||
modal().setTitle('test').setCustomId('foobar').addComponents(new TextInputBuilder()),
|
||||
).not.toThrowError();
|
||||
});
|
||||
|
||||
test('GIVEN invalid fields THEN builder does throw', () => {
|
||||
expect(() => modal().setTitle('test').setCustomId('foobar').toJSON()).toThrowError();
|
||||
|
||||
// @ts-expect-error
|
||||
expect(() => modal().setTitle('test').setCustomId(42).toJSON()).toThrowError();
|
||||
});
|
||||
@@ -112,4 +119,55 @@ describe('Modals', () => {
|
||||
.toJSON(),
|
||||
).toEqual(modalData);
|
||||
});
|
||||
|
||||
describe('equals()', () => {
|
||||
const textInput1 = new TextInputBuilder()
|
||||
.setCustomId('custom id')
|
||||
.setLabel('label')
|
||||
.setStyle(TextInputStyle.Paragraph);
|
||||
|
||||
const textInput2: APITextInputComponent = {
|
||||
type: ComponentType.TextInput,
|
||||
custom_id: 'custom id',
|
||||
label: 'label',
|
||||
style: TextInputStyle.Paragraph,
|
||||
};
|
||||
|
||||
test('GIVEN equal builders THEN returns true', () => {
|
||||
const equalTextInput = new TextInputBuilder()
|
||||
.setCustomId('custom id')
|
||||
.setLabel('label')
|
||||
.setStyle(TextInputStyle.Paragraph);
|
||||
|
||||
expect(textInput1.equals(equalTextInput)).toBeTruthy();
|
||||
});
|
||||
|
||||
test('GIVEN the same builder THEN returns true', () => {
|
||||
expect(textInput1.equals(textInput1)).toBeTruthy();
|
||||
});
|
||||
|
||||
test('GIVEN equal builder and data THEN returns true', () => {
|
||||
expect(textInput1.equals(textInput2)).toBeTruthy();
|
||||
});
|
||||
|
||||
test('GIVEN different builders THEN returns false', () => {
|
||||
const diffTextInput = new TextInputBuilder()
|
||||
.setCustomId('custom id')
|
||||
.setLabel('label 2')
|
||||
.setStyle(TextInputStyle.Paragraph);
|
||||
|
||||
expect(textInput1.equals(diffTextInput)).toBeFalsy();
|
||||
});
|
||||
|
||||
test('GIVEN different text input builder and data THEN returns false', () => {
|
||||
const diffTextInputData: APITextInputComponent = {
|
||||
type: ComponentType.TextInput,
|
||||
custom_id: 'custom id',
|
||||
label: 'label 2',
|
||||
style: TextInputStyle.Short,
|
||||
};
|
||||
|
||||
expect(textInput1.equals(diffTextInputData)).toBeFalsy();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
42
packages/builders/__tests__/util.test.ts
Normal file
42
packages/builders/__tests__/util.test.ts
Normal file
@@ -0,0 +1,42 @@
|
||||
import { describe, test, expect } from 'vitest';
|
||||
import {
|
||||
isJSONEncodable,
|
||||
isEquatable,
|
||||
ActionRowBuilder,
|
||||
enableValidators,
|
||||
disableValidators,
|
||||
isValidationEnabled,
|
||||
} from '../src/index';
|
||||
|
||||
describe('isEquatable', () => {
|
||||
test('returns true if the object is equatable', () => {
|
||||
expect(isEquatable({ equals: () => true })).toBeTruthy();
|
||||
});
|
||||
|
||||
test('returns false if the object is not equatable', () => {
|
||||
expect(isEquatable({})).toBeFalsy();
|
||||
});
|
||||
});
|
||||
|
||||
describe('isJSONEncodable', () => {
|
||||
test('returns true if the object is JSON encodable', () => {
|
||||
expect(isJSONEncodable({ toJSON: () => ({}) })).toBeTruthy();
|
||||
expect(isJSONEncodable(new ActionRowBuilder())).toBeTruthy();
|
||||
});
|
||||
|
||||
test('returns false if the object is not JSON encodable', () => {
|
||||
expect(isJSONEncodable({})).toBeFalsy();
|
||||
});
|
||||
});
|
||||
|
||||
describe('validation', () => {
|
||||
test('enables validation', () => {
|
||||
enableValidators();
|
||||
expect(isValidationEnabled()).toBeTruthy();
|
||||
});
|
||||
|
||||
test('disables validation', () => {
|
||||
disableValidators();
|
||||
expect(isValidationEnabled()).toBeFalsy();
|
||||
});
|
||||
});
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@discordjs/collection",
|
||||
"version": "0.8.0",
|
||||
"version": "0.9.0-dev",
|
||||
"description": "Utility data structure used in discord.js",
|
||||
"scripts": {
|
||||
"test": "vitest run",
|
||||
|
||||
@@ -42,12 +42,32 @@ class WebhookClient extends BaseClient {
|
||||
}
|
||||
|
||||
// These are here only for documentation purposes - they are implemented by Webhook
|
||||
/* eslint-disable no-empty-function */
|
||||
/* eslint-disable no-empty-function, valid-jsdoc */
|
||||
/**
|
||||
* Sends a message with this webhook.
|
||||
* @param {string|MessagePayload|WebhookMessageOptions} options The content for the reply
|
||||
* @returns {Promise<APIMessage>}
|
||||
*/
|
||||
send() {}
|
||||
sendSlackMessage() {}
|
||||
|
||||
/**
|
||||
* Gets a message that was sent by this webhook.
|
||||
* @param {Snowflake} message The id of the message to fetch
|
||||
* @param {WebhookFetchMessageOptions} [options={}] The options to provide to fetch the message.
|
||||
* @returns {Promise<APIMessage>} Returns the message sent by this webhook
|
||||
*/
|
||||
fetchMessage() {}
|
||||
edit() {}
|
||||
|
||||
/**
|
||||
* Edits a message that was sent by this webhook.
|
||||
* @param {MessageResolvable} message The message to edit
|
||||
* @param {string|MessagePayload|WebhookEditMessageOptions} options The options to provide
|
||||
* @returns {Promise<APIMessage>} Returns the message edited by this webhook
|
||||
*/
|
||||
editMessage() {}
|
||||
|
||||
sendSlackMessage() {}
|
||||
edit() {}
|
||||
delete() {}
|
||||
deleteMessage() {}
|
||||
get createdTimestamp() {}
|
||||
|
||||
@@ -299,11 +299,13 @@ class GuildMemberManager extends CachedManager {
|
||||
}
|
||||
data.roles &&= data.roles.map(role => (role instanceof Role ? role.id : role));
|
||||
|
||||
data.communication_disabled_until =
|
||||
// eslint-disable-next-line eqeqeq
|
||||
data.communicationDisabledUntil != null
|
||||
? new Date(data.communicationDisabledUntil).toISOString()
|
||||
: data.communicationDisabledUntil;
|
||||
if (typeof data.communicationDisabledUntil !== 'undefined') {
|
||||
data.communication_disabled_until =
|
||||
// eslint-disable-next-line eqeqeq
|
||||
data.communicationDisabledUntil != null
|
||||
? new Date(data.communicationDisabledUntil).toISOString()
|
||||
: data.communicationDisabledUntil;
|
||||
}
|
||||
|
||||
let endpoint;
|
||||
if (id === this.client.user.id) {
|
||||
|
||||
@@ -8,7 +8,7 @@ const { setTimeout: sleep } = require('node:timers/promises');
|
||||
const { Collection } = require('@discordjs/collection');
|
||||
const Shard = require('./Shard');
|
||||
const { Error, TypeError, RangeError, ErrorCodes } = require('../errors');
|
||||
const { mergeDefault, fetchRecommendedShards } = require('../util/Util');
|
||||
const { mergeDefault, fetchRecommendedShardCount } = require('../util/Util');
|
||||
|
||||
/**
|
||||
* This is a utility class that makes multi-process sharding of a bot an easy and painless experience.
|
||||
@@ -187,7 +187,7 @@ class ShardingManager extends EventEmitter {
|
||||
async spawn({ amount = this.totalShards, delay = 5500, timeout = 30_000 } = {}) {
|
||||
// Obtain/verify the number of shards to spawn
|
||||
if (amount === 'auto') {
|
||||
amount = await fetchRecommendedShards(this.token);
|
||||
amount = await fetchRecommendedShardCount(this.token);
|
||||
} else {
|
||||
if (typeof amount !== 'number' || isNaN(amount)) {
|
||||
throw new TypeError(ErrorCodes.ClientInvalidOption, 'Amount of shards', 'a number.');
|
||||
|
||||
@@ -6,11 +6,6 @@ const isEqual = require('fast-deep-equal');
|
||||
* Represents a component
|
||||
*/
|
||||
class Component {
|
||||
/**
|
||||
* Creates a new component from API data
|
||||
* @param {APIMessageComponent} data The API component data
|
||||
* @private
|
||||
*/
|
||||
constructor(data) {
|
||||
/**
|
||||
* The API data associated with this component
|
||||
|
||||
@@ -6,14 +6,9 @@ const isEqual = require('fast-deep-equal');
|
||||
* Represents an embed.
|
||||
*/
|
||||
class Embed {
|
||||
/**
|
||||
* Creates a new embed object
|
||||
* @param {APIEmbed} data API embed data
|
||||
* @private
|
||||
*/
|
||||
constructor(data) {
|
||||
/**
|
||||
* The API embed data
|
||||
* The API embed data.
|
||||
* @type {APIEmbed}
|
||||
* @readonly
|
||||
*/
|
||||
@@ -21,16 +16,16 @@ class Embed {
|
||||
}
|
||||
|
||||
/**
|
||||
* An array of fields of this embed
|
||||
* @type {?Array<APIEmbedField>}
|
||||
* An array of fields of this embed.
|
||||
* @type {Array<APIEmbedField>}
|
||||
* @readonly
|
||||
*/
|
||||
get fields() {
|
||||
return this.data.fields ?? null;
|
||||
return this.data.fields ?? [];
|
||||
}
|
||||
|
||||
/**
|
||||
* The embed title
|
||||
* The title of this embed.
|
||||
* @type {?string}
|
||||
* @readonly
|
||||
*/
|
||||
@@ -39,7 +34,7 @@ class Embed {
|
||||
}
|
||||
|
||||
/**
|
||||
* The embed description
|
||||
* The description of this embed.
|
||||
* @type {?string}
|
||||
* @readonly
|
||||
*/
|
||||
@@ -48,7 +43,7 @@ class Embed {
|
||||
}
|
||||
|
||||
/**
|
||||
* The embed URL
|
||||
* The URL of this embed.
|
||||
* @type {?string}
|
||||
* @readonly
|
||||
*/
|
||||
@@ -57,7 +52,7 @@ class Embed {
|
||||
}
|
||||
|
||||
/**
|
||||
* The embed color
|
||||
* The color of this embed.
|
||||
* @type {?number}
|
||||
* @readonly
|
||||
*/
|
||||
@@ -66,7 +61,7 @@ class Embed {
|
||||
}
|
||||
|
||||
/**
|
||||
* The timestamp of the embed in an ISO 8601 format
|
||||
* The timestamp of this embed. This is in an ISO 8601 format.
|
||||
* @type {?string}
|
||||
* @readonly
|
||||
*/
|
||||
@@ -75,8 +70,16 @@ class Embed {
|
||||
}
|
||||
|
||||
/**
|
||||
* The embed thumbnail data
|
||||
* @type {?EmbedImageData}
|
||||
* @typedef {Object} EmbedAssetData
|
||||
* @property {?string} url The URL of the image
|
||||
* @property {?string} proxyURL The proxy URL of the image
|
||||
* @property {?string} height The height of the image
|
||||
* @property {?string} width The width of the image
|
||||
*/
|
||||
|
||||
/**
|
||||
* The thumbnail of this embed.
|
||||
* @type {?EmbedAssetData}
|
||||
* @readonly
|
||||
*/
|
||||
get thumbnail() {
|
||||
@@ -90,8 +93,8 @@ class Embed {
|
||||
}
|
||||
|
||||
/**
|
||||
* The embed image data
|
||||
* @type {?EmbedImageData}
|
||||
* The image of this embed.
|
||||
* @type {?EmbedAssetData}
|
||||
* @readonly
|
||||
*/
|
||||
get image() {
|
||||
@@ -105,16 +108,30 @@ class Embed {
|
||||
}
|
||||
|
||||
/**
|
||||
* Received video data
|
||||
* @type {?EmbedVideoData}
|
||||
* The video of this embed.
|
||||
* @type {?EmbedAssetData}
|
||||
* @readonly
|
||||
*/
|
||||
get video() {
|
||||
return this.data.video ?? null;
|
||||
if (!this.data.video) return null;
|
||||
return {
|
||||
url: this.data.image.url,
|
||||
proxyURL: this.data.image.proxy_url,
|
||||
height: this.data.image.height,
|
||||
width: this.data.image.width,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* The embed author data
|
||||
* @typedef {Object} EmbedAuthorData
|
||||
* @property {string} name The name of the author
|
||||
* @property {?string} url The URL of the author
|
||||
* @property {?string} iconURL The icon URL of the author
|
||||
* @property {?string} proxyIconURL The proxy icon URL of the author
|
||||
*/
|
||||
|
||||
/**
|
||||
* The author of this embed.
|
||||
* @type {?EmbedAuthorData}
|
||||
* @readonly
|
||||
*/
|
||||
@@ -129,8 +146,8 @@ class Embed {
|
||||
}
|
||||
|
||||
/**
|
||||
* Received data about the embed provider
|
||||
* @type {?EmbedProvider}
|
||||
* The provider of this embed.
|
||||
* @type {?APIEmbedProvider}
|
||||
* @readonly
|
||||
*/
|
||||
get provider() {
|
||||
@@ -138,7 +155,14 @@ class Embed {
|
||||
}
|
||||
|
||||
/**
|
||||
* The embed footer data
|
||||
* @typedef {Object} EmbedFooterData
|
||||
* @property {string} text The text of the footer
|
||||
* @property {?string} iconURL The URL of the icon
|
||||
* @property {?string} proxyIconURL The proxy URL of the icon
|
||||
*/
|
||||
|
||||
/**
|
||||
* The footer of this embed.
|
||||
* @type {?EmbedFooterData}
|
||||
* @readonly
|
||||
*/
|
||||
@@ -152,7 +176,7 @@ class Embed {
|
||||
}
|
||||
|
||||
/**
|
||||
* The accumulated length for the embed title, description, fields, footer text, and author name
|
||||
* The accumulated length for the embed title, description, fields, footer text, and author name.
|
||||
* @type {number}
|
||||
* @readonly
|
||||
*/
|
||||
@@ -167,7 +191,7 @@ class Embed {
|
||||
}
|
||||
|
||||
/**
|
||||
* The hex color of the current color of the embed
|
||||
* The hex color of this embed.
|
||||
* @type {?string}
|
||||
* @readonly
|
||||
*/
|
||||
@@ -178,7 +202,7 @@ class Embed {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the API-compatible JSON for this embed
|
||||
* Returns the API-compatible JSON for this embed.
|
||||
* @returns {APIEmbed}
|
||||
*/
|
||||
toJSON() {
|
||||
@@ -186,7 +210,7 @@ class Embed {
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether or not the given embeds are equal
|
||||
* Whether the given embeds are equal.
|
||||
* @param {Embed|APIEmbed} other The embed to compare against
|
||||
* @returns {boolean}
|
||||
*/
|
||||
|
||||
@@ -7,11 +7,6 @@ const { ErrorCodes } = require('../errors');
|
||||
* Represents an interaction's response
|
||||
*/
|
||||
class InteractionResponse {
|
||||
/**
|
||||
* @param {BaseInteraction} interaction The interaction associated with this response
|
||||
* @param {Snowflake?} id The interaction id associated with the original response
|
||||
* @private
|
||||
*/
|
||||
constructor(interaction, id) {
|
||||
/**
|
||||
* The interaction associated with the interaction response
|
||||
|
||||
@@ -148,7 +148,7 @@ class Webhook {
|
||||
/**
|
||||
* Sends a message with this webhook.
|
||||
* @param {string|MessagePayload|WebhookMessageOptions} options The options to provide
|
||||
* @returns {Promise<APIMessage>}
|
||||
* @returns {Promise<Message>}
|
||||
* @example
|
||||
* // Send a basic message
|
||||
* webhook.send('hello!')
|
||||
@@ -288,7 +288,7 @@ class Webhook {
|
||||
* Gets a message that was sent by this webhook.
|
||||
* @param {Snowflake|'@original'} message The id of the message to fetch
|
||||
* @param {WebhookFetchMessageOptions} [options={}] The options to provide to fetch the message.
|
||||
* @returns {Promise<APIMessage>} Returns the message sent by this webhook
|
||||
* @returns {Promise<Message>} Returns the message sent by this webhook
|
||||
*/
|
||||
async fetchMessage(message, { threadId } = {}) {
|
||||
if (!this.token) throw new Error(ErrorCodes.WebhookTokenUnavailable);
|
||||
@@ -309,7 +309,7 @@ class Webhook {
|
||||
* Edits a message that was sent by this webhook.
|
||||
* @param {MessageResolvable|'@original'} message The message to edit
|
||||
* @param {string|MessagePayload|WebhookEditMessageOptions} options The options to provide
|
||||
* @returns {Promise<APIMessage>} Returns the message edited by this webhook
|
||||
* @returns {Promise<Message>} Returns the message edited by this webhook
|
||||
*/
|
||||
async editMessage(message, options) {
|
||||
if (!this.token) throw new Error(ErrorCodes.WebhookTokenUnavailable);
|
||||
|
||||
@@ -48,6 +48,11 @@
|
||||
* @see {@link https://discord-api-types.dev/api/discord-api-types-v10/interface/APIEmbedField}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @external APIEmbedProvider
|
||||
* @see {@link https://discord-api-types.dev/api/discord-api-types-v10/interface/APIEmbedProvider}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @external APIEmoji
|
||||
* @see {@link https://discord-api-types.dev/api/discord-api-types-v10/interface/APIEmoji}
|
||||
|
||||
@@ -1,48 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* @typedef {Object} EmbedData
|
||||
* @property {?string} title The title of the embed
|
||||
* @property {?EmbedType} type The type of the embed
|
||||
* @property {?string} description The description of the embed
|
||||
* @property {?string} url The URL of the embed
|
||||
* @property {?string} timestamp The timestamp on the embed
|
||||
* @property {?number} color The color of the embed
|
||||
* @property {?EmbedFooterData} footer The footer of the embed
|
||||
* @property {?EmbedImageData} image The image of the embed
|
||||
* @property {?EmbedImageData} thumbnail The thumbnail of the embed
|
||||
* @property {?EmbedProviderData} provider The provider of the embed
|
||||
* @property {?EmbedAuthorData} author The author in the embed
|
||||
* @property {?EmbedFieldData[]} fields The fields in this embed
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {Object} EmbedFooterData
|
||||
* @property {string} text The text of the footer
|
||||
* @property {?string} iconURL The URL of the icon
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {Object} EmbedImageData
|
||||
* @property {?string} url The URL of the image
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {Object} EmbedProviderData
|
||||
* @property {?string} name The name of the provider
|
||||
* @property {?string} url The URL of the provider
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {Object} EmbedAuthorData
|
||||
* @property {string} name The name of the author
|
||||
* @property {?string} url The URL of the author
|
||||
* @property {?string} iconURL The icon URL of the author
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {Object} EmbedFieldData
|
||||
* @property {string} name The name of the field
|
||||
* @property {string} value The value of the field
|
||||
* @property {?boolean} inline Whether to inline this field
|
||||
*/
|
||||
@@ -211,7 +211,7 @@ function escapeSpoiler(text) {
|
||||
}
|
||||
|
||||
/**
|
||||
* @typedef {Object} FetchRecommendedShardsOptions
|
||||
* @typedef {Object} FetchRecommendedShardCountOptions
|
||||
* @property {number} [guildsPerShard=1000] Number of guilds assigned per shard
|
||||
* @property {number} [multipleOf=1] The multiple the shard count should round up to. (16 for large bot sharding)
|
||||
*/
|
||||
@@ -219,10 +219,10 @@ function escapeSpoiler(text) {
|
||||
/**
|
||||
* Gets the recommended shard count from Discord.
|
||||
* @param {string} token Discord auth token
|
||||
* @param {FetchRecommendedShardsOptions} [options] Options for fetching the recommended shard count
|
||||
* @param {FetchRecommendedShardCountOptions} [options] Options for fetching the recommended shard count
|
||||
* @returns {Promise<number>} The recommended number of shards
|
||||
*/
|
||||
async function fetchRecommendedShards(token, { guildsPerShard = 1_000, multipleOf = 1 } = {}) {
|
||||
async function fetchRecommendedShardCount(token, { guildsPerShard = 1_000, multipleOf = 1 } = {}) {
|
||||
if (!token) throw new DiscordError(ErrorCodes.TokenMissing);
|
||||
const response = await fetch(RouteBases.api + Routes.gatewayBot(), {
|
||||
method: 'GET',
|
||||
@@ -555,7 +555,7 @@ module.exports = {
|
||||
escapeUnderline,
|
||||
escapeStrikethrough,
|
||||
escapeSpoiler,
|
||||
fetchRecommendedShards,
|
||||
fetchRecommendedShardCount,
|
||||
parseEmoji,
|
||||
resolvePartialEmoji,
|
||||
mergeDefault,
|
||||
|
||||
68
packages/discord.js/typings/index.d.ts
vendored
68
packages/discord.js/typings/index.d.ts
vendored
@@ -113,7 +113,6 @@ import {
|
||||
APIEmbedAuthor,
|
||||
APIEmbedFooter,
|
||||
APIEmbedImage,
|
||||
APIEmbedVideo,
|
||||
VideoQualityMode,
|
||||
LocalizationMap,
|
||||
LocaleString,
|
||||
@@ -122,6 +121,7 @@ import {
|
||||
APIChannel,
|
||||
ThreadAutoArchiveDuration,
|
||||
FormattingPatterns,
|
||||
APIEmbedProvider,
|
||||
} from 'discord-api-types/v10';
|
||||
import { ChildProcess } from 'node:child_process';
|
||||
import { EventEmitter } from 'node:events';
|
||||
@@ -494,7 +494,7 @@ export abstract class BaseGuild extends Base {
|
||||
protected constructor(client: Client, data: RawBaseGuildData);
|
||||
public get createdAt(): Date;
|
||||
public get createdTimestamp(): number;
|
||||
public features: GuildFeature[];
|
||||
public features: `${GuildFeature}`[];
|
||||
public icon: string | null;
|
||||
public id: Snowflake;
|
||||
public name: string;
|
||||
@@ -667,12 +667,12 @@ export interface EmbedData {
|
||||
timestamp?: string | number | Date;
|
||||
color?: number;
|
||||
footer?: EmbedFooterData;
|
||||
image?: EmbedImageData;
|
||||
thumbnail?: EmbedImageData;
|
||||
provider?: EmbedProviderData;
|
||||
image?: EmbedAssetData;
|
||||
thumbnail?: EmbedAssetData;
|
||||
provider?: APIEmbedProvider;
|
||||
author?: EmbedAuthorData;
|
||||
fields?: EmbedFieldData[];
|
||||
video?: EmbedVideoData;
|
||||
fields?: APIEmbedField[];
|
||||
video?: EmbedAssetData;
|
||||
}
|
||||
|
||||
export interface IconData {
|
||||
@@ -684,16 +684,7 @@ export type EmbedAuthorData = Omit<APIEmbedAuthor, 'icon_url' | 'proxy_icon_url'
|
||||
|
||||
export type EmbedFooterData = Omit<APIEmbedFooter, 'icon_url' | 'proxy_icon_url'> & IconData;
|
||||
|
||||
export interface EmbedProviderData {
|
||||
name?: string;
|
||||
url?: string;
|
||||
}
|
||||
|
||||
export interface EmbedImageData extends Omit<APIEmbedImage, 'proxy_url'> {
|
||||
proxyURL?: string;
|
||||
}
|
||||
|
||||
export interface EmbedVideoData extends Omit<APIEmbedVideo, 'proxy_url'> {
|
||||
export interface EmbedAssetData extends Omit<APIEmbedImage, 'proxy_url'> {
|
||||
proxyURL?: string;
|
||||
}
|
||||
|
||||
@@ -706,7 +697,7 @@ export class EmbedBuilder extends BuildersEmbed {
|
||||
export class Embed {
|
||||
private constructor(data: APIEmbed);
|
||||
public readonly data: Readonly<APIEmbed>;
|
||||
public get fields(): APIEmbedField[] | null;
|
||||
public get fields(): APIEmbedField[];
|
||||
public get footer(): EmbedFooterData | null;
|
||||
public get title(): string | null;
|
||||
public get description(): string | null;
|
||||
@@ -714,11 +705,11 @@ export class Embed {
|
||||
public get color(): number | null;
|
||||
public get hexColor(): string | null;
|
||||
public get timestamp(): string | null;
|
||||
public get thumbnail(): EmbedImageData | null;
|
||||
public get image(): EmbedImageData | null;
|
||||
public get thumbnail(): EmbedAssetData | null;
|
||||
public get image(): EmbedAssetData | null;
|
||||
public get author(): EmbedAuthorData | null;
|
||||
public get provider(): EmbedProviderData | null;
|
||||
public get video(): EmbedVideoData | null;
|
||||
public get provider(): APIEmbedProvider | null;
|
||||
public get video(): EmbedAssetData | null;
|
||||
public get length(): number;
|
||||
public equals(other: Embed | APIEmbed): boolean;
|
||||
public toJSON(): APIEmbed;
|
||||
@@ -1344,7 +1335,7 @@ export class GuildPreview extends Base {
|
||||
public discoverySplash: string | null;
|
||||
public emojis: Collection<Snowflake, GuildPreviewEmoji>;
|
||||
public stickers: Collection<Snowflake, Sticker>;
|
||||
public features: GuildFeature[];
|
||||
public features: `${GuildFeature}`[];
|
||||
public icon: string | null;
|
||||
public id: Snowflake;
|
||||
public name: string;
|
||||
@@ -1579,10 +1570,10 @@ export class InteractionWebhook extends PartialWebhookMixin() {
|
||||
public token: string;
|
||||
public send(options: string | MessagePayload | InteractionReplyOptions): Promise<Message>;
|
||||
public editMessage(
|
||||
message: MessageResolvable,
|
||||
message: MessageResolvable | '@original',
|
||||
options: string | MessagePayload | WebhookEditMessageOptions,
|
||||
): Promise<Message>;
|
||||
public fetchMessage(message: string): Promise<Message>;
|
||||
public fetchMessage(message: Snowflake | '@original'): Promise<Message>;
|
||||
}
|
||||
|
||||
export class Invite extends Base {
|
||||
@@ -2299,7 +2290,7 @@ export class ShardingManager extends EventEmitter {
|
||||
public once(event: 'shardCreate', listener: (shard: Shard) => Awaitable<void>): this;
|
||||
}
|
||||
|
||||
export interface FetchRecommendedShardsOptions {
|
||||
export interface FetchRecommendedShardCountOptions {
|
||||
guildsPerShard?: number;
|
||||
multipleOf?: number;
|
||||
}
|
||||
@@ -2649,7 +2640,7 @@ export function escapeUnderline(text: string): string;
|
||||
export function escapeStrikethrough(text: string): string;
|
||||
export function escapeSpoiler(text: string): string;
|
||||
export function cleanCodeBlockContent(text: string): string;
|
||||
export function fetchRecommendedShards(token: string, options?: FetchRecommendedShardsOptions): Promise<number>;
|
||||
export function fetchRecommendedShardCount(token: string, options?: FetchRecommendedShardCountOptions): Promise<number>;
|
||||
export function flatten(obj: unknown, ...props: Record<string, boolean | string>[]): unknown;
|
||||
export function makeError(obj: MakeErrorOptions): Error;
|
||||
export function makePlainError(err: Error): MakeErrorOptions;
|
||||
@@ -2813,6 +2804,13 @@ export class Webhook extends WebhookMixin() {
|
||||
applicationId: null;
|
||||
owner: User | APIUser;
|
||||
};
|
||||
|
||||
public editMessage(
|
||||
message: MessageResolvable,
|
||||
options: string | MessagePayload | WebhookEditMessageOptions,
|
||||
): Promise<Message>;
|
||||
public fetchMessage(message: Snowflake, options?: WebhookFetchMessageOptions): Promise<Message>;
|
||||
public send(options: string | MessagePayload | Omit<WebhookMessageOptions, 'flags'>): Promise<Message>;
|
||||
}
|
||||
|
||||
export class WebhookClient extends WebhookMixin(BaseClient) {
|
||||
@@ -3284,11 +3282,7 @@ export class BaseGuildEmojiManager extends CachedManager<Snowflake, GuildEmoji,
|
||||
public resolveIdentifier(emoji: EmojiIdentifierResolvable): string | null;
|
||||
}
|
||||
|
||||
export class CategoryChannelChildManager extends DataManager<
|
||||
Snowflake,
|
||||
NonCategoryGuildBasedChannel,
|
||||
GuildChannelResolvable
|
||||
> {
|
||||
export class CategoryChannelChildManager extends DataManager<Snowflake, CategoryChildChannel, GuildChannelResolvable> {
|
||||
private constructor(channel: CategoryChannel);
|
||||
|
||||
public channel: CategoryChannel;
|
||||
@@ -4417,12 +4411,6 @@ export interface EmbedField {
|
||||
inline: boolean;
|
||||
}
|
||||
|
||||
export interface EmbedFieldData {
|
||||
name: string;
|
||||
value: string;
|
||||
inline?: boolean;
|
||||
}
|
||||
|
||||
export type EmojiIdentifierResolvable = string | EmojiResolvable;
|
||||
|
||||
export type EmojiResolvable = Snowflake | GuildEmoji | ReactionEmoji;
|
||||
@@ -4759,7 +4747,7 @@ export interface GuildEditData {
|
||||
preferredLocale?: Locale | null;
|
||||
premiumProgressBarEnabled?: boolean;
|
||||
description?: string | null;
|
||||
features?: GuildFeature[];
|
||||
features?: `${GuildFeature}`[];
|
||||
reason?: string;
|
||||
}
|
||||
|
||||
@@ -5436,7 +5424,7 @@ export type VoiceBasedChannel = Extract<Channel, { bitrate: number }>;
|
||||
|
||||
export type GuildBasedChannel = Extract<Channel, { guild: Guild }>;
|
||||
|
||||
export type NonCategoryGuildBasedChannel = Exclude<GuildBasedChannel, CategoryChannel>;
|
||||
export type CategoryChildChannel = Exclude<Extract<Channel, { parent: CategoryChannel | null }>, CategoryChannel>;
|
||||
|
||||
export type NonThreadGuildBasedChannel = Exclude<GuildBasedChannel, AnyThreadChannel>;
|
||||
|
||||
|
||||
@@ -23,6 +23,7 @@ import {
|
||||
APITextInputComponent,
|
||||
APIEmbed,
|
||||
ApplicationCommandType,
|
||||
APIMessage,
|
||||
} from 'discord-api-types/v10';
|
||||
import {
|
||||
ApplicationCommand,
|
||||
@@ -130,6 +131,9 @@ import {
|
||||
ThreadMemberManager,
|
||||
CollectedMessageInteraction,
|
||||
ShardEvents,
|
||||
Webhook,
|
||||
WebhookClient,
|
||||
InteractionWebhook,
|
||||
} from '.';
|
||||
import { expectAssignable, expectNotAssignable, expectNotType, expectType } from 'tsd';
|
||||
import type { ContextMenuCommandBuilder, SlashCommandBuilder } from '@discordjs/builders';
|
||||
@@ -1691,3 +1695,20 @@ expectType<ChannelMention>(partialGroupDMChannel.toString());
|
||||
expectType<UserMention>(dmChannel.toString());
|
||||
expectType<UserMention>(user.toString());
|
||||
expectType<UserMention>(guildMember.toString());
|
||||
|
||||
declare const webhook: Webhook;
|
||||
declare const webhookClient: WebhookClient;
|
||||
declare const interactionWebhook: InteractionWebhook;
|
||||
declare const snowflake: Snowflake;
|
||||
|
||||
expectType<Promise<Message>>(webhook.send('content'));
|
||||
expectType<Promise<Message>>(webhook.editMessage(snowflake, 'content'));
|
||||
expectType<Promise<Message>>(webhook.fetchMessage(snowflake));
|
||||
|
||||
expectType<Promise<APIMessage>>(webhookClient.send('content'));
|
||||
expectType<Promise<APIMessage>>(webhookClient.editMessage(snowflake, 'content'));
|
||||
expectType<Promise<APIMessage>>(webhookClient.fetchMessage(snowflake));
|
||||
|
||||
expectType<Promise<Message>>(interactionWebhook.send('content'));
|
||||
expectType<Promise<Message>>(interactionWebhook.editMessage(snowflake, 'content'));
|
||||
expectType<Promise<Message>>(interactionWebhook.fetchMessage(snowflake));
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@discordjs/rest",
|
||||
"version": "0.6.0",
|
||||
"version": "0.7.0-dev",
|
||||
"description": "The REST API for discord.js",
|
||||
"scripts": {
|
||||
"test": "vitest run",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@discordjs/voice",
|
||||
"version": "0.11.0",
|
||||
"version": "0.12.0-dev",
|
||||
"description": "Implementation of the Discord Voice API for node.js",
|
||||
"scripts": {
|
||||
"build": "tsup && node scripts/postbuild.mjs",
|
||||
|
||||
Reference in New Issue
Block a user