mirror of
https://github.com/discordjs/discord.js.git
synced 2026-03-18 04:23:31 +01:00
feat(components): Add unsafe message component builders (#7387)
This commit is contained in:
@@ -5,7 +5,7 @@ import {
|
|||||||
ComponentType,
|
ComponentType,
|
||||||
} from 'discord-api-types/v9';
|
} from 'discord-api-types/v9';
|
||||||
import { buttonLabelValidator, buttonStyleValidator } from '../../src/components/Assertions';
|
import { buttonLabelValidator, buttonStyleValidator } from '../../src/components/Assertions';
|
||||||
import { ButtonComponent } from '../../src/components/Button';
|
import { ButtonComponent } from '../../src/components/button/Button';
|
||||||
|
|
||||||
const buttonComponent = () => new ButtonComponent();
|
const buttonComponent = () => new ButtonComponent();
|
||||||
|
|
||||||
|
|||||||
42
packages/builders/src/components/button/Button.ts
Normal file
42
packages/builders/src/components/button/Button.ts
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
import type { ButtonStyle, APIMessageComponentEmoji, APIButtonComponent } from 'discord-api-types/v9';
|
||||||
|
import {
|
||||||
|
buttonLabelValidator,
|
||||||
|
buttonStyleValidator,
|
||||||
|
customIdValidator,
|
||||||
|
disabledValidator,
|
||||||
|
emojiValidator,
|
||||||
|
urlValidator,
|
||||||
|
validateRequiredButtonParameters,
|
||||||
|
} from '../Assertions';
|
||||||
|
import { UnsafeButtonComponent } from './UnsafeButton';
|
||||||
|
|
||||||
|
export class ButtonComponent extends UnsafeButtonComponent {
|
||||||
|
public override setStyle(style: ButtonStyle) {
|
||||||
|
return super.setStyle(buttonStyleValidator.parse(style));
|
||||||
|
}
|
||||||
|
|
||||||
|
public override setURL(url: string) {
|
||||||
|
return super.setURL(urlValidator.parse(url));
|
||||||
|
}
|
||||||
|
|
||||||
|
public override setCustomId(customId: string) {
|
||||||
|
return super.setCustomId(customIdValidator.parse(customId));
|
||||||
|
}
|
||||||
|
|
||||||
|
public override setEmoji(emoji: APIMessageComponentEmoji) {
|
||||||
|
return super.setEmoji(emojiValidator.parse(emoji));
|
||||||
|
}
|
||||||
|
|
||||||
|
public override setDisabled(disabled: boolean) {
|
||||||
|
return super.setDisabled(disabledValidator.parse(disabled));
|
||||||
|
}
|
||||||
|
|
||||||
|
public override setLabel(label: string) {
|
||||||
|
return super.setLabel(buttonLabelValidator.parse(label));
|
||||||
|
}
|
||||||
|
|
||||||
|
public override toJSON(): APIButtonComponent {
|
||||||
|
validateRequiredButtonParameters(this.style, this.label, this.emoji, this.custom_id, this.url);
|
||||||
|
return super.toJSON();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,16 +1,12 @@
|
|||||||
import { APIButtonComponent, APIMessageComponentEmoji, ButtonStyle, ComponentType } from 'discord-api-types/v9';
|
|
||||||
import {
|
import {
|
||||||
buttonLabelValidator,
|
ComponentType,
|
||||||
buttonStyleValidator,
|
ButtonStyle,
|
||||||
customIdValidator,
|
type APIMessageComponentEmoji,
|
||||||
disabledValidator,
|
type APIButtonComponent,
|
||||||
emojiValidator,
|
} from 'discord-api-types/v9';
|
||||||
urlValidator,
|
import type { Component } from '../Component';
|
||||||
validateRequiredButtonParameters,
|
|
||||||
} from './Assertions';
|
|
||||||
import type { Component } from './Component';
|
|
||||||
|
|
||||||
export class ButtonComponent implements Component {
|
export class UnsafeButtonComponent implements Component {
|
||||||
public readonly type = ComponentType.Button as const;
|
public readonly type = ComponentType.Button as const;
|
||||||
public readonly style!: ButtonStyle;
|
public readonly style!: ButtonStyle;
|
||||||
public readonly label?: string;
|
public readonly label?: string;
|
||||||
@@ -41,7 +37,6 @@ export class ButtonComponent implements Component {
|
|||||||
* @param style The style of the button
|
* @param style The style of the button
|
||||||
*/
|
*/
|
||||||
public setStyle(style: ButtonStyle) {
|
public setStyle(style: ButtonStyle) {
|
||||||
buttonStyleValidator.parse(style);
|
|
||||||
Reflect.set(this, 'style', style);
|
Reflect.set(this, 'style', style);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
@@ -51,7 +46,6 @@ export class ButtonComponent implements Component {
|
|||||||
* @param url The URL to open when this button is clicked
|
* @param url The URL to open when this button is clicked
|
||||||
*/
|
*/
|
||||||
public setURL(url: string) {
|
public setURL(url: string) {
|
||||||
urlValidator.parse(url);
|
|
||||||
Reflect.set(this, 'url', url);
|
Reflect.set(this, 'url', url);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
@@ -61,7 +55,6 @@ export class ButtonComponent implements Component {
|
|||||||
* @param customId The custom ID to use for this button
|
* @param customId The custom ID to use for this button
|
||||||
*/
|
*/
|
||||||
public setCustomId(customId: string) {
|
public setCustomId(customId: string) {
|
||||||
customIdValidator.parse(customId);
|
|
||||||
Reflect.set(this, 'custom_id', customId);
|
Reflect.set(this, 'custom_id', customId);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
@@ -71,7 +64,6 @@ export class ButtonComponent implements Component {
|
|||||||
* @param emoji The emoji to display on this button
|
* @param emoji The emoji to display on this button
|
||||||
*/
|
*/
|
||||||
public setEmoji(emoji: APIMessageComponentEmoji) {
|
public setEmoji(emoji: APIMessageComponentEmoji) {
|
||||||
emojiValidator.parse(emoji);
|
|
||||||
Reflect.set(this, 'emoji', emoji);
|
Reflect.set(this, 'emoji', emoji);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
@@ -81,7 +73,6 @@ export class ButtonComponent implements Component {
|
|||||||
* @param disabled Whether or not to disable this button or not
|
* @param disabled Whether or not to disable this button or not
|
||||||
*/
|
*/
|
||||||
public setDisabled(disabled: boolean) {
|
public setDisabled(disabled: boolean) {
|
||||||
disabledValidator.parse(disabled);
|
|
||||||
Reflect.set(this, 'disabled', disabled);
|
Reflect.set(this, 'disabled', disabled);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
@@ -91,13 +82,11 @@ export class ButtonComponent implements Component {
|
|||||||
* @param label The label to display on this button
|
* @param label The label to display on this button
|
||||||
*/
|
*/
|
||||||
public setLabel(label: string) {
|
public setLabel(label: string) {
|
||||||
buttonLabelValidator.parse(label);
|
|
||||||
Reflect.set(this, 'label', label);
|
Reflect.set(this, 'label', label);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public toJSON(): APIButtonComponent {
|
public toJSON(): APIButtonComponent {
|
||||||
validateRequiredButtonParameters(this.style, this.label, this.emoji, this.custom_id, this.url);
|
|
||||||
return {
|
return {
|
||||||
...this,
|
...this,
|
||||||
};
|
};
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
import { APISelectMenuComponent, ComponentType } from 'discord-api-types/v9';
|
import type { APISelectMenuComponent } from 'discord-api-types/v9';
|
||||||
import {
|
import {
|
||||||
customIdValidator,
|
customIdValidator,
|
||||||
disabledValidator,
|
disabledValidator,
|
||||||
@@ -6,106 +6,34 @@ import {
|
|||||||
placeholderValidator,
|
placeholderValidator,
|
||||||
validateRequiredSelectMenuParameters,
|
validateRequiredSelectMenuParameters,
|
||||||
} from '../Assertions';
|
} from '../Assertions';
|
||||||
import type { Component } from '../Component';
|
import { UnsafeSelectMenuComponent } from './UnsafeSelectMenu';
|
||||||
import { SelectMenuOption } from './SelectMenuOption';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents a select menu component
|
* Represents a select menu component
|
||||||
*/
|
*/
|
||||||
export class SelectMenuComponent implements Component {
|
export class SelectMenuComponent extends UnsafeSelectMenuComponent {
|
||||||
public readonly type = ComponentType.SelectMenu as const;
|
public override setPlaceholder(placeholder: string) {
|
||||||
public readonly options: SelectMenuOption[];
|
return super.setPlaceholder(placeholderValidator.parse(placeholder));
|
||||||
public readonly placeholder?: string;
|
|
||||||
public readonly min_values?: number;
|
|
||||||
public readonly max_values?: number;
|
|
||||||
public readonly custom_id!: string;
|
|
||||||
public readonly disabled?: boolean;
|
|
||||||
|
|
||||||
public constructor(data?: APISelectMenuComponent & { type?: ComponentType.SelectMenu }) {
|
|
||||||
this.options = data?.options.map((option) => new SelectMenuOption(option)) ?? [];
|
|
||||||
this.placeholder = data?.placeholder;
|
|
||||||
this.min_values = data?.min_values;
|
|
||||||
this.max_values = data?.max_values;
|
|
||||||
/* eslint-disable @typescript-eslint/non-nullable-type-assertion-style */
|
|
||||||
this.custom_id = data?.custom_id as string;
|
|
||||||
/* eslint-enable @typescript-eslint/non-nullable-type-assertion-style */
|
|
||||||
this.disabled = data?.disabled;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
public override setMinValues(minValues: number) {
|
||||||
* Sets the placeholder for this select menu
|
return super.setMinValues(minMaxValidator.parse(minValues));
|
||||||
* @param placeholder The placeholder to use for this select menu
|
|
||||||
*/
|
|
||||||
public setPlaceholder(placeholder: string) {
|
|
||||||
placeholderValidator.parse(placeholder);
|
|
||||||
Reflect.set(this, 'placeholder', placeholder);
|
|
||||||
return this;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
public override setMaxValues(maxValues: number) {
|
||||||
* Sets the minimum values that must be selected in the select menu
|
return super.setMaxValues(minMaxValidator.parse(maxValues));
|
||||||
* @param minValues The minimum values that must be selected
|
|
||||||
*/
|
|
||||||
public setMinValues(minValues: number) {
|
|
||||||
minMaxValidator.parse(minValues);
|
|
||||||
Reflect.set(this, 'min_values', minValues);
|
|
||||||
return this;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
public override setCustomId(customId: string) {
|
||||||
* Sets the maximum values that must be selected in the select menu
|
return super.setCustomId(customIdValidator.parse(customId));
|
||||||
* @param minValues The maximum values that must be selected
|
|
||||||
*/
|
|
||||||
public setMaxValues(maxValues: number) {
|
|
||||||
minMaxValidator.parse(maxValues);
|
|
||||||
Reflect.set(this, 'max_values', maxValues);
|
|
||||||
return this;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
public override setDisabled(disabled: boolean) {
|
||||||
* Sets the custom Id for this select menu
|
return super.setDisabled(disabledValidator.parse(disabled));
|
||||||
* @param customId The custom ID to use for this select menu
|
|
||||||
*/
|
|
||||||
public setCustomId(customId: string) {
|
|
||||||
customIdValidator.parse(customId);
|
|
||||||
Reflect.set(this, 'custom_id', customId);
|
|
||||||
return this;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
public override toJSON(): APISelectMenuComponent {
|
||||||
* Sets whether or not this select menu is disabled
|
|
||||||
* @param disabled Whether or not this select menu is disabled
|
|
||||||
*/
|
|
||||||
public setDisabled(disabled: boolean) {
|
|
||||||
disabledValidator.parse(disabled);
|
|
||||||
Reflect.set(this, 'disabled', disabled);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Adds options to this select menu
|
|
||||||
* @param options The options to add to this select menu
|
|
||||||
* @returns
|
|
||||||
*/
|
|
||||||
public addOptions(...options: SelectMenuOption[]) {
|
|
||||||
this.options.push(...options);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the options on this select menu
|
|
||||||
* @param options The options to set on this select menu
|
|
||||||
*/
|
|
||||||
public setOptions(options: SelectMenuOption[]) {
|
|
||||||
Reflect.set(this, 'options', [...options]);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public toJSON(): APISelectMenuComponent {
|
|
||||||
validateRequiredSelectMenuParameters(this.options, this.custom_id);
|
validateRequiredSelectMenuParameters(this.options, this.custom_id);
|
||||||
return {
|
return super.toJSON();
|
||||||
...this,
|
|
||||||
options: this.options.map((option) => option.toJSON()),
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,79 +5,26 @@ import {
|
|||||||
labelValueValidator,
|
labelValueValidator,
|
||||||
validateRequiredSelectMenuOptionParameters,
|
validateRequiredSelectMenuOptionParameters,
|
||||||
} from '../Assertions';
|
} from '../Assertions';
|
||||||
|
import { UnsafeSelectMenuOption } from './UnsafeSelectMenuOption';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents an option within a select menu component
|
* Represents an option within a select menu component
|
||||||
*/
|
*/
|
||||||
export class SelectMenuOption {
|
export class SelectMenuOption extends UnsafeSelectMenuOption {
|
||||||
public readonly label!: string;
|
public override setDescription(description: string) {
|
||||||
public readonly value!: string;
|
return super.setDescription(labelValueValidator.parse(description));
|
||||||
public readonly description?: string;
|
|
||||||
public readonly emoji?: APIMessageComponentEmoji;
|
|
||||||
public readonly default?: boolean;
|
|
||||||
|
|
||||||
public constructor(data?: APISelectMenuOption) {
|
|
||||||
/* eslint-disable @typescript-eslint/non-nullable-type-assertion-style */
|
|
||||||
this.label = data?.label as string;
|
|
||||||
this.value = data?.value as string;
|
|
||||||
/* eslint-enable @typescript-eslint/non-nullable-type-assertion-style */
|
|
||||||
this.description = data?.description;
|
|
||||||
this.emoji = data?.emoji;
|
|
||||||
this.default = data?.default;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
public override setDefault(isDefault: boolean) {
|
||||||
* Sets the label of this option
|
return super.setDefault(defaultValidator.parse(isDefault));
|
||||||
* @param label The label to show on this option
|
|
||||||
*/
|
|
||||||
public setLabel(label: string) {
|
|
||||||
Reflect.set(this, 'label', label);
|
|
||||||
return this;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
public override setEmoji(emoji: APIMessageComponentEmoji) {
|
||||||
* Sets the value of this option
|
return super.setEmoji(emojiValidator.parse(emoji));
|
||||||
* @param value The value of this option
|
|
||||||
*/
|
|
||||||
public setValue(value: string) {
|
|
||||||
Reflect.set(this, 'value', value);
|
|
||||||
return this;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
public override toJSON(): APISelectMenuOption {
|
||||||
* Sets the description of this option.
|
|
||||||
* @param description The description of this option
|
|
||||||
*/
|
|
||||||
public setDescription(description: string) {
|
|
||||||
labelValueValidator.parse(description);
|
|
||||||
Reflect.set(this, 'description', description);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets whether this option is selected by default
|
|
||||||
* @param isDefault Whether or not this option is selected by default
|
|
||||||
*/
|
|
||||||
public setDefault(isDefault: boolean) {
|
|
||||||
defaultValidator.parse(isDefault);
|
|
||||||
Reflect.set(this, 'default', isDefault);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the emoji to display on this button
|
|
||||||
* @param emoji The emoji to display on this button
|
|
||||||
*/
|
|
||||||
public setEmoji(emoji: APIMessageComponentEmoji) {
|
|
||||||
emojiValidator.parse(emoji);
|
|
||||||
Reflect.set(this, 'emoji', emoji);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public toJSON(): APISelectMenuOption {
|
|
||||||
validateRequiredSelectMenuOptionParameters(this.label, this.value);
|
validateRequiredSelectMenuOptionParameters(this.label, this.value);
|
||||||
return {
|
return super.toJSON();
|
||||||
...this,
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,98 @@
|
|||||||
|
import { ComponentType, type APISelectMenuComponent } from 'discord-api-types/v9';
|
||||||
|
import type { Component } from '../Component';
|
||||||
|
import { SelectMenuOption } from './SelectMenuOption';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents a non-validated select menu component
|
||||||
|
*/
|
||||||
|
export class UnsafeSelectMenuComponent implements Component {
|
||||||
|
public readonly type = ComponentType.SelectMenu as const;
|
||||||
|
public readonly options: SelectMenuOption[];
|
||||||
|
public readonly placeholder?: string;
|
||||||
|
public readonly min_values?: number;
|
||||||
|
public readonly max_values?: number;
|
||||||
|
public readonly custom_id!: string;
|
||||||
|
public readonly disabled?: boolean;
|
||||||
|
|
||||||
|
public constructor(data?: APISelectMenuComponent) {
|
||||||
|
this.options = data?.options.map((option) => new SelectMenuOption(option)) ?? [];
|
||||||
|
this.placeholder = data?.placeholder;
|
||||||
|
this.min_values = data?.min_values;
|
||||||
|
this.max_values = data?.max_values;
|
||||||
|
/* eslint-disable @typescript-eslint/non-nullable-type-assertion-style */
|
||||||
|
this.custom_id = data?.custom_id as string;
|
||||||
|
/* eslint-enable @typescript-eslint/non-nullable-type-assertion-style */
|
||||||
|
this.disabled = data?.disabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the placeholder for this select menu
|
||||||
|
* @param placeholder The placeholder to use for this select menu
|
||||||
|
*/
|
||||||
|
public setPlaceholder(placeholder: string) {
|
||||||
|
Reflect.set(this, 'placeholder', placeholder);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets thes minimum values that must be selected in the select menu
|
||||||
|
* @param minValues The minimum values that must be selected
|
||||||
|
*/
|
||||||
|
public setMinValues(minValues: number) {
|
||||||
|
Reflect.set(this, 'min_values', minValues);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets thes maximum values that must be selected in the select menu
|
||||||
|
* @param minValues The maximum values that must be selected
|
||||||
|
*/
|
||||||
|
public setMaxValues(maxValues: number) {
|
||||||
|
Reflect.set(this, 'max_values', maxValues);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the custom Id for this select menu
|
||||||
|
* @param customId The custom ID to use for this select menu
|
||||||
|
*/
|
||||||
|
public setCustomId(customId: string) {
|
||||||
|
Reflect.set(this, 'custom_id', customId);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets whether or not this select menu is disabled
|
||||||
|
* @param disabled Whether or not this select menu is disabled
|
||||||
|
*/
|
||||||
|
public setDisabled(disabled: boolean) {
|
||||||
|
Reflect.set(this, 'disabled', disabled);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds options to this select menu
|
||||||
|
* @param options The options to add to this select menu
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
public addOptions(...options: SelectMenuOption[]) {
|
||||||
|
this.options.push(...options);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the options on this select menu
|
||||||
|
* @param options The options to set on this select menu
|
||||||
|
*/
|
||||||
|
public setOptions(options: SelectMenuOption[]) {
|
||||||
|
Reflect.set(this, 'options', [...options]);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public toJSON(): APISelectMenuComponent {
|
||||||
|
return {
|
||||||
|
...this,
|
||||||
|
options: this.options.map((option) => option.toJSON()),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,73 @@
|
|||||||
|
import type { APIMessageComponentEmoji, APISelectMenuOption } from 'discord-api-types/v9';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents a non-validated option within a select menu component
|
||||||
|
*/
|
||||||
|
export class UnsafeSelectMenuOption {
|
||||||
|
public readonly label!: string;
|
||||||
|
public readonly value!: string;
|
||||||
|
public readonly description?: string;
|
||||||
|
public readonly emoji?: APIMessageComponentEmoji;
|
||||||
|
public readonly default?: boolean;
|
||||||
|
|
||||||
|
public constructor(data?: APISelectMenuOption) {
|
||||||
|
/* eslint-disable @typescript-eslint/non-nullable-type-assertion-style */
|
||||||
|
this.label = data?.label as string;
|
||||||
|
this.value = data?.value as string;
|
||||||
|
/* eslint-enable @typescript-eslint/non-nullable-type-assertion-style */
|
||||||
|
this.description = data?.description;
|
||||||
|
this.emoji = data?.emoji;
|
||||||
|
this.default = data?.default;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the label of this option
|
||||||
|
* @param label The label to show on this option
|
||||||
|
*/
|
||||||
|
public setLabel(label: string) {
|
||||||
|
Reflect.set(this, 'label', label);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the value of this option
|
||||||
|
* @param value The value of this option
|
||||||
|
*/
|
||||||
|
public setValue(value: string) {
|
||||||
|
Reflect.set(this, 'value', value);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the description of this option.
|
||||||
|
* @param description The description of this option
|
||||||
|
*/
|
||||||
|
public setDescription(description: string) {
|
||||||
|
Reflect.set(this, 'description', description);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets whether this option is selected by default
|
||||||
|
* @param isDefault Whether or not this option is selected by default
|
||||||
|
*/
|
||||||
|
public setDefault(isDefault: boolean) {
|
||||||
|
Reflect.set(this, 'default', isDefault);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the emoji to display on this button
|
||||||
|
* @param emoji The emoji to display on this button
|
||||||
|
*/
|
||||||
|
public setEmoji(emoji: APIMessageComponentEmoji) {
|
||||||
|
Reflect.set(this, 'emoji', emoji);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public toJSON(): APISelectMenuOption {
|
||||||
|
return {
|
||||||
|
...this,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,14 +1,18 @@
|
|||||||
export * as EmbedAssertions from './messages/embed/Assertions';
|
export * as EmbedAssertions from './messages/embed/Assertions';
|
||||||
export * from './messages/embed/Embed';
|
export * from './messages/embed/Embed';
|
||||||
export * from './messages/formatters';
|
export * from './messages/formatters';
|
||||||
|
export * from './messages/embed/UnsafeEmbed';
|
||||||
|
|
||||||
export * as ComponentAssertions from './components/Assertions';
|
export * as ComponentAssertions from './components/Assertions';
|
||||||
export * from './components/ActionRow';
|
export * from './components/ActionRow';
|
||||||
export * from './components/Button';
|
export * from './components/button/Button';
|
||||||
export * from './components/Component';
|
export * from './components/Component';
|
||||||
export * from './components/Components';
|
export * from './components/Components';
|
||||||
export * from './components/selectMenu/SelectMenu';
|
export * from './components/selectMenu/SelectMenu';
|
||||||
export * from './components/selectMenu/SelectMenuOption';
|
export * from './components/selectMenu/SelectMenuOption';
|
||||||
|
export * from './components/button/UnsafeButton';
|
||||||
|
export * from './components/selectMenu/UnsafeSelectMenu';
|
||||||
|
export * from './components/selectMenu/UnsafeSelectMenuOption';
|
||||||
|
|
||||||
export * as SlashCommandAssertions from './interactions/slashCommands/Assertions';
|
export * as SlashCommandAssertions from './interactions/slashCommands/Assertions';
|
||||||
export * from './interactions/slashCommands/SlashCommandBuilder';
|
export * from './interactions/slashCommands/SlashCommandBuilder';
|
||||||
|
|||||||
@@ -1,13 +1,4 @@
|
|||||||
import type {
|
import type { APIEmbedField } from 'discord-api-types/v9';
|
||||||
APIEmbed,
|
|
||||||
APIEmbedAuthor,
|
|
||||||
APIEmbedField,
|
|
||||||
APIEmbedFooter,
|
|
||||||
APIEmbedImage,
|
|
||||||
APIEmbedProvider,
|
|
||||||
APIEmbedThumbnail,
|
|
||||||
APIEmbedVideo,
|
|
||||||
} from 'discord-api-types/v9';
|
|
||||||
import {
|
import {
|
||||||
authorNamePredicate,
|
authorNamePredicate,
|
||||||
colorPredicate,
|
colorPredicate,
|
||||||
@@ -22,300 +13,86 @@ import {
|
|||||||
urlPredicate,
|
urlPredicate,
|
||||||
validateFieldLength,
|
validateFieldLength,
|
||||||
} from './Assertions';
|
} from './Assertions';
|
||||||
|
import { AuthorOptions, FooterOptions, UnsafeEmbed } from './UnsafeEmbed';
|
||||||
export interface AuthorOptions {
|
|
||||||
name: string;
|
|
||||||
url?: string;
|
|
||||||
iconURL?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface FooterOptions {
|
|
||||||
text: string;
|
|
||||||
iconURL?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents an embed in a message (image/video preview, rich embed, etc.)
|
* Represents an embed in a message (image/video preview, rich embed, etc.)
|
||||||
*/
|
*/
|
||||||
export class Embed implements APIEmbed {
|
export class Embed extends UnsafeEmbed {
|
||||||
/**
|
public override addFields(...fields: APIEmbedField[]): this {
|
||||||
* An array of fields of this embed
|
|
||||||
*/
|
|
||||||
public readonly fields: APIEmbedField[];
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The embed title
|
|
||||||
*/
|
|
||||||
public readonly title?: string;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The embed description
|
|
||||||
*/
|
|
||||||
public readonly description?: string;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The embed url
|
|
||||||
*/
|
|
||||||
public readonly url?: string;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The embed color
|
|
||||||
*/
|
|
||||||
public readonly color?: number;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The timestamp of the embed in the ISO format
|
|
||||||
*/
|
|
||||||
public readonly timestamp?: string;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The embed thumbnail data
|
|
||||||
*/
|
|
||||||
public readonly thumbnail?: APIEmbedThumbnail;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The embed image data
|
|
||||||
*/
|
|
||||||
public readonly image?: APIEmbedImage;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Received video data
|
|
||||||
*/
|
|
||||||
public readonly video?: APIEmbedVideo;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The embed author data
|
|
||||||
*/
|
|
||||||
public readonly author?: APIEmbedAuthor;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Received data about the embed provider
|
|
||||||
*/
|
|
||||||
public readonly provider?: APIEmbedProvider;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The embed footer data
|
|
||||||
*/
|
|
||||||
public readonly footer?: APIEmbedFooter;
|
|
||||||
|
|
||||||
public constructor(data: APIEmbed = {}) {
|
|
||||||
this.title = data.title;
|
|
||||||
this.description = data.description;
|
|
||||||
this.url = data.url;
|
|
||||||
this.color = data.color;
|
|
||||||
this.thumbnail = data.thumbnail;
|
|
||||||
this.image = data.image;
|
|
||||||
this.video = data.video;
|
|
||||||
this.author = data.author;
|
|
||||||
this.provider = data.provider;
|
|
||||||
this.footer = data.footer;
|
|
||||||
this.fields = data.fields ?? [];
|
|
||||||
|
|
||||||
if (data.timestamp) this.timestamp = new Date(data.timestamp).toISOString();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The accumulated length for the embed title, description, fields, footer text, and author name
|
|
||||||
*/
|
|
||||||
public get length(): number {
|
|
||||||
return (
|
|
||||||
(this.title?.length ?? 0) +
|
|
||||||
(this.description?.length ?? 0) +
|
|
||||||
this.fields.reduce((prev, curr) => prev + curr.name.length + curr.value.length, 0) +
|
|
||||||
(this.footer?.text.length ?? 0) +
|
|
||||||
(this.author?.name.length ?? 0)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Adds a field to the embed (max 25)
|
|
||||||
*
|
|
||||||
* @param field The field to add.
|
|
||||||
*/
|
|
||||||
public addField(field: APIEmbedField): this {
|
|
||||||
return this.addFields(field);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Adds fields to the embed (max 25)
|
|
||||||
*
|
|
||||||
* @param fields The fields to add
|
|
||||||
*/
|
|
||||||
public addFields(...fields: APIEmbedField[]): this {
|
|
||||||
// Data assertions
|
|
||||||
embedFieldsArrayPredicate.parse(fields);
|
|
||||||
|
|
||||||
// Ensure adding these fields won't exceed the 25 field limit
|
// Ensure adding these fields won't exceed the 25 field limit
|
||||||
validateFieldLength(this.fields, fields.length);
|
validateFieldLength(this.fields, fields.length);
|
||||||
|
|
||||||
this.fields.push(...Embed.normalizeFields(...fields));
|
// Data assertions
|
||||||
return this;
|
return super.addFields(...embedFieldsArrayPredicate.parse(fields));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
public override spliceFields(index: number, deleteCount: number, ...fields: APIEmbedField[]): this {
|
||||||
* Removes, replaces, or inserts fields in the embed (max 25)
|
|
||||||
*
|
|
||||||
* @param index The index to start at
|
|
||||||
* @param deleteCount The number of fields to remove
|
|
||||||
* @param fields The replacing field objects
|
|
||||||
*/
|
|
||||||
public spliceFields(index: number, deleteCount: number, ...fields: APIEmbedField[]): this {
|
|
||||||
// Data assertions
|
|
||||||
embedFieldsArrayPredicate.parse(fields);
|
|
||||||
|
|
||||||
// Ensure adding these fields won't exceed the 25 field limit
|
// Ensure adding these fields won't exceed the 25 field limit
|
||||||
validateFieldLength(this.fields, fields.length - deleteCount);
|
validateFieldLength(this.fields, fields.length - deleteCount);
|
||||||
|
|
||||||
this.fields.splice(index, deleteCount, ...Embed.normalizeFields(...fields));
|
// Data assertions
|
||||||
return this;
|
return super.spliceFields(index, deleteCount, ...embedFieldsArrayPredicate.parse(fields));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
public override setAuthor(options: AuthorOptions | null): this {
|
||||||
* Sets the embed's fields (max 25).
|
|
||||||
* @param fields The fields to set
|
|
||||||
*/
|
|
||||||
public setFields(...fields: APIEmbedField[]) {
|
|
||||||
this.spliceFields(0, this.fields.length, ...fields);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the author of this embed
|
|
||||||
*
|
|
||||||
* @param options The options for the author
|
|
||||||
*/
|
|
||||||
public setAuthor(options: AuthorOptions | null): this {
|
|
||||||
if (options === null) {
|
if (options === null) {
|
||||||
Reflect.set(this, 'author', undefined);
|
return super.setAuthor(null);
|
||||||
return this;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const { name, iconURL, url } = options;
|
|
||||||
// Data assertions
|
// Data assertions
|
||||||
authorNamePredicate.parse(name);
|
authorNamePredicate.parse(options.name);
|
||||||
urlPredicate.parse(iconURL);
|
urlPredicate.parse(options.iconURL);
|
||||||
urlPredicate.parse(url);
|
urlPredicate.parse(options.url);
|
||||||
|
|
||||||
Reflect.set(this, 'author', { name, url, icon_url: iconURL });
|
return super.setAuthor(options);
|
||||||
return this;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
public override setColor(color: number | null): this {
|
||||||
* Sets the color of this embed
|
|
||||||
*
|
|
||||||
* @param color The color of the embed
|
|
||||||
*/
|
|
||||||
public setColor(color: number | null): this {
|
|
||||||
// Data assertions
|
// Data assertions
|
||||||
colorPredicate.parse(color);
|
return super.setColor(colorPredicate.parse(color));
|
||||||
|
|
||||||
Reflect.set(this, 'color', color ?? undefined);
|
|
||||||
return this;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
public override setDescription(description: string | null): this {
|
||||||
* Sets the description of this embed
|
|
||||||
*
|
|
||||||
* @param description The description
|
|
||||||
*/
|
|
||||||
public setDescription(description: string | null): this {
|
|
||||||
// Data assertions
|
// Data assertions
|
||||||
descriptionPredicate.parse(description);
|
return super.setDescription(descriptionPredicate.parse(description));
|
||||||
|
|
||||||
Reflect.set(this, 'description', description ?? undefined);
|
|
||||||
return this;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
public override setFooter(options: FooterOptions | null): this {
|
||||||
* Sets the footer of this embed
|
|
||||||
*
|
|
||||||
* @param options The options for the footer
|
|
||||||
*/
|
|
||||||
public setFooter(options: FooterOptions | null): this {
|
|
||||||
if (options === null) {
|
if (options === null) {
|
||||||
Reflect.set(this, 'footer', undefined);
|
return super.setFooter(null);
|
||||||
return this;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const { text, iconURL } = options;
|
|
||||||
// Data assertions
|
// Data assertions
|
||||||
footerTextPredicate.parse(text);
|
footerTextPredicate.parse(options.text);
|
||||||
urlPredicate.parse(iconURL);
|
urlPredicate.parse(options.iconURL);
|
||||||
|
|
||||||
Reflect.set(this, 'footer', { text, icon_url: iconURL });
|
return super.setFooter(options);
|
||||||
return this;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
public override setImage(url: string | null): this {
|
||||||
* Sets the image of this embed
|
|
||||||
*
|
|
||||||
* @param url The URL of the image
|
|
||||||
*/
|
|
||||||
public setImage(url: string | null): this {
|
|
||||||
// Data assertions
|
// Data assertions
|
||||||
urlPredicate.parse(url);
|
return super.setImage(urlPredicate.parse(url)!);
|
||||||
|
|
||||||
Reflect.set(this, 'image', url ? { url } : undefined);
|
|
||||||
return this;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
public override setThumbnail(url: string | null): this {
|
||||||
* Sets the thumbnail of this embed
|
|
||||||
*
|
|
||||||
* @param url The URL of the thumbnail
|
|
||||||
*/
|
|
||||||
public setThumbnail(url: string | null): this {
|
|
||||||
// Data assertions
|
// Data assertions
|
||||||
urlPredicate.parse(url);
|
return super.setThumbnail(urlPredicate.parse(url)!);
|
||||||
|
|
||||||
Reflect.set(this, 'thumbnail', url ? { url } : undefined);
|
|
||||||
return this;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
public override setTimestamp(timestamp: number | Date | null = Date.now()): this {
|
||||||
* Sets the timestamp of this embed
|
|
||||||
*
|
|
||||||
* @param timestamp The timestamp or date
|
|
||||||
*/
|
|
||||||
public setTimestamp(timestamp: number | Date | null = Date.now()): this {
|
|
||||||
// Data assertions
|
// Data assertions
|
||||||
timestampPredicate.parse(timestamp);
|
return super.setTimestamp(timestampPredicate.parse(timestamp));
|
||||||
|
|
||||||
Reflect.set(this, 'timestamp', timestamp ? new Date(timestamp).toISOString() : undefined);
|
|
||||||
return this;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
public override setTitle(title: string | null): this {
|
||||||
* Sets the title of this embed
|
|
||||||
*
|
|
||||||
* @param title The title
|
|
||||||
*/
|
|
||||||
public setTitle(title: string | null): this {
|
|
||||||
// Data assertions
|
// Data assertions
|
||||||
titlePredicate.parse(title);
|
return super.setTitle(titlePredicate.parse(title));
|
||||||
|
|
||||||
Reflect.set(this, 'title', title ?? undefined);
|
|
||||||
return this;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
public override setURL(url: string | null): this {
|
||||||
* Sets the URL of this embed
|
|
||||||
*
|
|
||||||
* @param url The URL
|
|
||||||
*/
|
|
||||||
public setURL(url: string | null): this {
|
|
||||||
// Data assertions
|
// Data assertions
|
||||||
urlPredicate.parse(url);
|
return super.setURL(urlPredicate.parse(url)!);
|
||||||
|
|
||||||
Reflect.set(this, 'url', url ?? undefined);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Transforms the embed to a plain object
|
|
||||||
*/
|
|
||||||
public toJSON(): APIEmbed {
|
|
||||||
return { ...this };
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -323,7 +100,7 @@ export class Embed implements APIEmbed {
|
|||||||
*
|
*
|
||||||
* @param fields Fields to normalize
|
* @param fields Fields to normalize
|
||||||
*/
|
*/
|
||||||
public static normalizeFields(...fields: APIEmbedField[]): APIEmbedField[] {
|
public static override normalizeFields(...fields: APIEmbedField[]): APIEmbedField[] {
|
||||||
return fields.flat(Infinity).map((field) => {
|
return fields.flat(Infinity).map((field) => {
|
||||||
fieldNamePredicate.parse(field.name);
|
fieldNamePredicate.parse(field.name);
|
||||||
fieldValuePredicate.parse(field.value);
|
fieldValuePredicate.parse(field.value);
|
||||||
|
|||||||
271
packages/builders/src/messages/embed/UnsafeEmbed.ts
Normal file
271
packages/builders/src/messages/embed/UnsafeEmbed.ts
Normal file
@@ -0,0 +1,271 @@
|
|||||||
|
import type {
|
||||||
|
APIEmbed,
|
||||||
|
APIEmbedAuthor,
|
||||||
|
APIEmbedField,
|
||||||
|
APIEmbedFooter,
|
||||||
|
APIEmbedImage,
|
||||||
|
APIEmbedProvider,
|
||||||
|
APIEmbedThumbnail,
|
||||||
|
APIEmbedVideo,
|
||||||
|
} from 'discord-api-types/v9';
|
||||||
|
import { Embed } from './Embed';
|
||||||
|
|
||||||
|
export interface AuthorOptions {
|
||||||
|
name: string;
|
||||||
|
url?: string;
|
||||||
|
iconURL?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface FooterOptions {
|
||||||
|
text: string;
|
||||||
|
iconURL?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class UnsafeEmbed implements APIEmbed {
|
||||||
|
/**
|
||||||
|
* An array of fields of this embed
|
||||||
|
*/
|
||||||
|
public readonly fields: APIEmbedField[];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The embed title
|
||||||
|
*/
|
||||||
|
public readonly title?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The embed description
|
||||||
|
*/
|
||||||
|
public readonly description?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The embed url
|
||||||
|
*/
|
||||||
|
public readonly url?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The embed color
|
||||||
|
*/
|
||||||
|
public readonly color?: number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The timestamp of the embed in the ISO format
|
||||||
|
*/
|
||||||
|
public readonly timestamp?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The embed thumbnail data
|
||||||
|
*/
|
||||||
|
public readonly thumbnail?: APIEmbedThumbnail;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The embed image data
|
||||||
|
*/
|
||||||
|
public readonly image?: APIEmbedImage;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Received video data
|
||||||
|
*/
|
||||||
|
public readonly video?: APIEmbedVideo;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The embed author data
|
||||||
|
*/
|
||||||
|
public readonly author?: APIEmbedAuthor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Received data about the embed provider
|
||||||
|
*/
|
||||||
|
public readonly provider?: APIEmbedProvider;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The embed footer data
|
||||||
|
*/
|
||||||
|
public readonly footer?: APIEmbedFooter;
|
||||||
|
|
||||||
|
public constructor(data: APIEmbed = {}) {
|
||||||
|
this.title = data.title;
|
||||||
|
this.description = data.description;
|
||||||
|
this.url = data.url;
|
||||||
|
this.color = data.color;
|
||||||
|
this.thumbnail = data.thumbnail;
|
||||||
|
this.image = data.image;
|
||||||
|
this.video = data.video;
|
||||||
|
this.author = data.author;
|
||||||
|
this.provider = data.provider;
|
||||||
|
this.footer = data.footer;
|
||||||
|
this.fields = data.fields ?? [];
|
||||||
|
|
||||||
|
if (data.timestamp) this.timestamp = new Date(data.timestamp).toISOString();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The accumulated length for the embed title, description, fields, footer text, and author name
|
||||||
|
*/
|
||||||
|
public get length(): number {
|
||||||
|
return (
|
||||||
|
(this.title?.length ?? 0) +
|
||||||
|
(this.description?.length ?? 0) +
|
||||||
|
this.fields.reduce((prev, curr) => prev + curr.name.length + curr.value.length, 0) +
|
||||||
|
(this.footer?.text.length ?? 0) +
|
||||||
|
(this.author?.name.length ?? 0)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a field to the embed (max 25)
|
||||||
|
*
|
||||||
|
* @param field The field to add.
|
||||||
|
*/
|
||||||
|
public addField(field: APIEmbedField): this {
|
||||||
|
return this.addFields(field);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds fields to the embed (max 25)
|
||||||
|
*
|
||||||
|
* @param fields The fields to add
|
||||||
|
*/
|
||||||
|
public addFields(...fields: APIEmbedField[]): this {
|
||||||
|
this.fields.push(...Embed.normalizeFields(...fields));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes, replaces, or inserts fields in the embed (max 25)
|
||||||
|
*
|
||||||
|
* @param index The index to start at
|
||||||
|
* @param deleteCount The number of fields to remove
|
||||||
|
* @param fields The replacing field objects
|
||||||
|
*/
|
||||||
|
public spliceFields(index: number, deleteCount: number, ...fields: APIEmbedField[]): this {
|
||||||
|
this.fields.splice(index, deleteCount, ...Embed.normalizeFields(...fields));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the embed's fields (max 25).
|
||||||
|
* @param fields The fields to set
|
||||||
|
*/
|
||||||
|
public setFields(...fields: APIEmbedField[]) {
|
||||||
|
this.spliceFields(0, this.fields.length, ...fields);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the author of this embed
|
||||||
|
*
|
||||||
|
* @param options The options for the author
|
||||||
|
*/
|
||||||
|
public setAuthor(options: AuthorOptions | null): this {
|
||||||
|
if (options === null) {
|
||||||
|
Reflect.set(this, 'author', undefined);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
Reflect.set(this, 'author', { name: options.name, url: options.url, icon_url: options.iconURL });
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the color of this embed
|
||||||
|
*
|
||||||
|
* @param color The color of the embed
|
||||||
|
*/
|
||||||
|
public setColor(color: number | null): this {
|
||||||
|
Reflect.set(this, 'color', color ?? undefined);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the description of this embed
|
||||||
|
*
|
||||||
|
* @param description The description
|
||||||
|
*/
|
||||||
|
public setDescription(description: string | null): this {
|
||||||
|
Reflect.set(this, 'description', description ?? undefined);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the footer of this embed
|
||||||
|
*
|
||||||
|
* @param options The options for the footer
|
||||||
|
*/
|
||||||
|
public setFooter(options: FooterOptions | null): this {
|
||||||
|
if (options === null) {
|
||||||
|
Reflect.set(this, 'footer', undefined);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
Reflect.set(this, 'footer', { text: options.text, icon_url: options.iconURL });
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the image of this embed
|
||||||
|
*
|
||||||
|
* @param url The URL of the image
|
||||||
|
*/
|
||||||
|
public setImage(url: string | null): this {
|
||||||
|
Reflect.set(this, 'image', url ? { url } : undefined);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the thumbnail of this embed
|
||||||
|
*
|
||||||
|
* @param url The URL of the thumbnail
|
||||||
|
*/
|
||||||
|
public setThumbnail(url: string | null): this {
|
||||||
|
Reflect.set(this, 'thumbnail', url ? { url } : undefined);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the timestamp of this embed
|
||||||
|
*
|
||||||
|
* @param timestamp The timestamp or date
|
||||||
|
*/
|
||||||
|
public setTimestamp(timestamp: number | Date | null = Date.now()): this {
|
||||||
|
Reflect.set(this, 'timestamp', timestamp ? new Date(timestamp).toISOString() : undefined);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the title of this embed
|
||||||
|
*
|
||||||
|
* @param title The title
|
||||||
|
*/
|
||||||
|
public setTitle(title: string | null): this {
|
||||||
|
Reflect.set(this, 'title', title ?? undefined);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the URL of this embed
|
||||||
|
*
|
||||||
|
* @param url The URL
|
||||||
|
*/
|
||||||
|
public setURL(url: string | null): this {
|
||||||
|
Reflect.set(this, 'url', url ?? undefined);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Transforms the embed to a plain object
|
||||||
|
*/
|
||||||
|
public toJSON(): APIEmbed {
|
||||||
|
return { ...this };
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Normalizes field input and resolves strings
|
||||||
|
*
|
||||||
|
* @param fields Fields to normalize
|
||||||
|
*/
|
||||||
|
public static normalizeFields(...fields: APIEmbedField[]): APIEmbedField[] {
|
||||||
|
return fields
|
||||||
|
.flat(Infinity)
|
||||||
|
.map((field) => ({ name: field.name, value: field.value, inline: field.inline ?? undefined }));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -89,6 +89,7 @@ exports.CommandInteractionOptionResolver = require('./structures/CommandInteract
|
|||||||
exports.ContextMenuCommandInteraction = require('./structures/ContextMenuCommandInteraction');
|
exports.ContextMenuCommandInteraction = require('./structures/ContextMenuCommandInteraction');
|
||||||
exports.DMChannel = require('./structures/DMChannel');
|
exports.DMChannel = require('./structures/DMChannel');
|
||||||
exports.Embed = require('@discordjs/builders').Embed;
|
exports.Embed = require('@discordjs/builders').Embed;
|
||||||
|
exports.UnsafeEmbed = require('@discordjs/builders').UnsafeEmbed;
|
||||||
exports.Emoji = require('./structures/Emoji').Emoji;
|
exports.Emoji = require('./structures/Emoji').Emoji;
|
||||||
exports.Guild = require('./structures/Guild').Guild;
|
exports.Guild = require('./structures/Guild').Guild;
|
||||||
exports.GuildAuditLogs = require('./structures/GuildAuditLogs');
|
exports.GuildAuditLogs = require('./structures/GuildAuditLogs');
|
||||||
@@ -182,8 +183,11 @@ exports.UserFlags = require('discord-api-types/v9').UserFlags;
|
|||||||
exports.WebhookType = require('discord-api-types/v9').WebhookType;
|
exports.WebhookType = require('discord-api-types/v9').WebhookType;
|
||||||
exports.ActionRow = require('@discordjs/builders').ActionRow;
|
exports.ActionRow = require('@discordjs/builders').ActionRow;
|
||||||
exports.ButtonComponent = require('@discordjs/builders').ButtonComponent;
|
exports.ButtonComponent = require('@discordjs/builders').ButtonComponent;
|
||||||
|
exports.UnsafeButtonComponent = require('@discordjs/builders').UnsafeButtonComponent;
|
||||||
exports.SelectMenuComponent = require('@discordjs/builders').SelectMenuComponent;
|
exports.SelectMenuComponent = require('@discordjs/builders').SelectMenuComponent;
|
||||||
|
exports.UnsafeSelectMenuComponent = require('@discordjs/builders').UnsafeButtonComponent;
|
||||||
exports.SelectMenuOption = require('@discordjs/builders').SelectMenuOption;
|
exports.SelectMenuOption = require('@discordjs/builders').SelectMenuOption;
|
||||||
|
exports.UnsafeSelectMenuOption = require('@discordjs/builders').UnsafeSelectMenuOption;
|
||||||
exports.DiscordAPIError = require('@discordjs/rest').DiscordAPIError;
|
exports.DiscordAPIError = require('@discordjs/rest').DiscordAPIError;
|
||||||
exports.HTTPError = require('@discordjs/rest').HTTPError;
|
exports.HTTPError = require('@discordjs/rest').HTTPError;
|
||||||
exports.RateLimitError = require('@discordjs/rest').RateLimitError;
|
exports.RateLimitError = require('@discordjs/rest').RateLimitError;
|
||||||
|
|||||||
7
packages/discord.js/typings/index.d.ts
vendored
7
packages/discord.js/typings/index.d.ts
vendored
@@ -4615,8 +4615,6 @@ export interface MessageMentionOptions {
|
|||||||
|
|
||||||
export type MessageMentionTypes = 'roles' | 'users' | 'everyone';
|
export type MessageMentionTypes = 'roles' | 'users' | 'everyone';
|
||||||
|
|
||||||
export { Embed };
|
|
||||||
|
|
||||||
export interface MessageOptions {
|
export interface MessageOptions {
|
||||||
tts?: boolean;
|
tts?: boolean;
|
||||||
nonce?: string | number;
|
nonce?: string | number;
|
||||||
@@ -5216,8 +5214,13 @@ export {
|
|||||||
export {
|
export {
|
||||||
ActionRow,
|
ActionRow,
|
||||||
ButtonComponent,
|
ButtonComponent,
|
||||||
|
UnsafeButtonComponent,
|
||||||
SelectMenuComponent,
|
SelectMenuComponent,
|
||||||
|
UnsafeSelectMenuComponent,
|
||||||
SelectMenuOption,
|
SelectMenuOption,
|
||||||
|
UnsafeSelectMenuOption,
|
||||||
ActionRowComponent,
|
ActionRowComponent,
|
||||||
|
Embed,
|
||||||
|
UnsafeEmbed,
|
||||||
} from '@discordjs/builders';
|
} from '@discordjs/builders';
|
||||||
export { DiscordAPIError, HTTPError, RateLimitError } from '@discordjs/rest';
|
export { DiscordAPIError, HTTPError, RateLimitError } from '@discordjs/rest';
|
||||||
|
|||||||
Reference in New Issue
Block a user