From 3601a22fc213ed96b4c5f2d17033586f53d5836a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?T=C3=86MB=C3=98?= <69138346+TAEMBO@users.noreply.github.com> Date: Tue, 15 Oct 2024 23:29:06 -0700 Subject: [PATCH 1/2] feat: forwarding messages --- .../discord.js/src/managers/MessageManager.js | 31 +++++++++++++++++-- packages/discord.js/src/structures/Message.js | 24 ++++++++++++-- .../src/structures/MessagePayload.js | 14 ++++++--- .../structures/interfaces/TextBasedChannel.js | 2 +- packages/discord.js/typings/index.d.ts | 14 ++++----- 5 files changed, 67 insertions(+), 18 deletions(-) diff --git a/packages/discord.js/src/managers/MessageManager.js b/packages/discord.js/src/managers/MessageManager.js index dcddf2857383..a2c44c446352 100644 --- a/packages/discord.js/src/managers/MessageManager.js +++ b/packages/discord.js/src/managers/MessageManager.js @@ -2,9 +2,9 @@ const { Collection } = require('@discordjs/collection'); const { makeURLSearchParams } = require('@discordjs/rest'); -const { Routes } = require('discord-api-types/v10'); +const { MessageReferenceType, Routes } = require('discord-api-types/v10'); const CachedManager = require('./CachedManager'); -const { DiscordjsTypeError, ErrorCodes } = require('../errors'); +const { DiscordjsError, DiscordjsTypeError, ErrorCodes } = require('../errors'); const { Message } = require('../structures/Message'); const MessagePayload = require('../structures/MessagePayload'); const { MakeCacheOverrideSymbol } = require('../util/Symbols'); @@ -209,6 +209,33 @@ class MessageManager extends CachedManager { return this.cache.get(data.id) ?? this._add(data); } + /** + * Forwards a message to this manager's channel. + * @param {Message|MessageReference} reference The message to forward + * @returns {Promise} + */ + async forward(reference) { + if (!reference) throw new DiscordjsError(ErrorCodes.MessageReferenceMissing); + const message_id = this.resolveId(reference.messageId); + if (!message_id) throw new DiscordjsError(ErrorCodes.MessageReferenceMissing); + const channel_id = this.client.channels.resolveId(reference.channelId); + if (!channel_id) throw new DiscordjsTypeError(ErrorCodes.InvalidType, 'channel', 'ChannelResolvable'); + const guild_id = this.client.guilds.resolveId(reference.guildId); + + const data = await this.client.rest.post(Routes.channelMessages(this.channel.id), { + body: { + message_reference: { + message_id, + channel_id, + guild_id, + type: MessageReferenceType.Forward, + }, + }, + }); + + return this.cache.get(data.id) ?? this._add(data); + } + /** * Pins a message to the channel's pinned messages, even if it's not cached. * @param {MessageResolvable} message The message to pin diff --git a/packages/discord.js/src/structures/Message.js b/packages/discord.js/src/structures/Message.js index f052113e2bda..63906512884b 100644 --- a/packages/discord.js/src/structures/Message.js +++ b/packages/discord.js/src/structures/Message.js @@ -8,6 +8,7 @@ const { ChannelType, MessageType, MessageFlags, + MessageReferenceType, PermissionFlagsBits, } = require('discord-api-types/v10'); const Attachment = require('./Attachment'); @@ -20,7 +21,7 @@ const MessagePayload = require('./MessagePayload'); const { Poll } = require('./Poll.js'); const ReactionCollector = require('./ReactionCollector'); const { Sticker } = require('./Sticker'); -const { DiscordjsError, ErrorCodes } = require('../errors'); +const { DiscordjsError, DiscordjsTypeError, ErrorCodes } = require('../errors'); const ReactionManager = require('../managers/ReactionManager'); const { createComponent } = require('../util/Components'); const { NonSystemMessageTypes, MaxBulkDeletableMessageAge, UndeletableMessageTypes } = require('../util/Constants'); @@ -767,6 +768,20 @@ class Message extends Base { return message; } + /** + * Forwards this message. + * @param {ChannelResolvable} channel The channel to forward this message to + * @returns {Promise} + */ + async forward(channel) { + const resolvedChannel = this.client.channels.resolve(channel); + + if (!resolvedChannel) throw new DiscordjsTypeError(ErrorCodes.InvalidType, 'channel', 'ChannelResolvable'); + + const message = await resolvedChannel.messages.forward(this); + return message; + } + /** * Whether the message is crosspostable by the client user * @type {boolean} @@ -920,8 +935,11 @@ class Message extends Base { data = options; } else { data = MessagePayload.create(this, options, { - reply: { - messageReference: this, + messageReference: { + messageId: this.id, + channelId: this.channelId, + guildId: this.guildId, + type: MessageReferenceType.Default, failIfNotExists: options?.failIfNotExists ?? this.client.options.failIfNotExists, }, }); diff --git a/packages/discord.js/src/structures/MessagePayload.js b/packages/discord.js/src/structures/MessagePayload.js index 5420d250d928..773e6d93078c 100644 --- a/packages/discord.js/src/structures/MessagePayload.js +++ b/packages/discord.js/src/structures/MessagePayload.js @@ -168,13 +168,19 @@ class MessagePayload { } let message_reference; - if (typeof this.options.reply === 'object') { - const reference = this.options.reply.messageReference; - const message_id = this.isMessage ? (reference.id ?? reference) : this.target.messages.resolveId(reference); + if (this.options.messageReference) { + const reference = this.options.messageReference; + const message_id = this.target.messages.resolveId(reference.messageId); + const channel_id = this.target.client.channels.resolveId(reference.channelId); + const guild_id = this.target.client.guilds.resolveId(reference.guildId); + if (message_id) { message_reference = { message_id, - fail_if_not_exists: this.options.reply.failIfNotExists ?? this.target.client.options.failIfNotExists, + channel_id, + guild_id, + type: reference.type, + fail_if_not_exists: reference.failIfNotExists ?? this.target.client.options.failIfNotExists, }; } } diff --git a/packages/discord.js/src/structures/interfaces/TextBasedChannel.js b/packages/discord.js/src/structures/interfaces/TextBasedChannel.js index d2e408580253..b039197041f7 100644 --- a/packages/discord.js/src/structures/interfaces/TextBasedChannel.js +++ b/packages/discord.js/src/structures/interfaces/TextBasedChannel.js @@ -113,7 +113,7 @@ class TextBasedChannel { /** * The options for sending a message. * @typedef {BaseMessageCreateOptions} MessageCreateOptions - * @property {ReplyOptions} [reply] The options for replying to a message + * @property {MessageReference|MessageResolvable} [messageReference] The options for a reference to a message */ /** diff --git a/packages/discord.js/typings/index.d.ts b/packages/discord.js/typings/index.d.ts index ba0da0eea83c..8a2ffe806a1f 100644 --- a/packages/discord.js/typings/index.d.ts +++ b/packages/discord.js/typings/index.d.ts @@ -2242,6 +2242,7 @@ export class Message extends Base { public equals(message: Message, rawData: unknown): boolean; public fetchReference(): Promise>>; public fetchWebhook(): Promise; + public forward(channel: TextBasedChannelResolvable): Promise; public crosspost(): Promise>>; public fetch(force?: boolean): Promise>>; public pin(reason?: string): Promise>>; @@ -4423,6 +4424,7 @@ export abstract class MessageManager extends public fetch(options: MessageResolvable | FetchMessageOptions): Promise>; public fetch(options?: FetchMessagesOptions): Promise>>; public fetchPinned(cache?: boolean): Promise>>; + public forward(reference: Omit): Promise>; public react(message: MessageResolvable, emoji: EmojiIdentifierResolvable): Promise; public pin(message: MessageResolvable, reason?: string): Promise; public unpin(message: MessageResolvable, reason?: string): Promise; @@ -6394,7 +6396,7 @@ export interface MessageCreateOptions extends BaseMessageOptionsWithPoll { tts?: boolean; nonce?: string | number; enforceNonce?: boolean; - reply?: ReplyOptions; + messageReference?: MessageReference & { failIfNotExists?: boolean }; stickers?: readonly StickerResolvable[]; flags?: BitFieldResolvable< Extract, @@ -6640,12 +6642,7 @@ export interface ReactionCollectorOptions extends CollectorOptions<[MessageReact maxUsers?: number; } -export interface ReplyOptions { - messageReference: MessageResolvable; - failIfNotExists?: boolean; -} - -export interface MessageReplyOptions extends Omit { +export interface MessageReplyOptions extends Omit { failIfNotExists?: boolean; } @@ -6924,7 +6921,8 @@ export interface WebhookFetchMessageOptions { threadId?: Snowflake; } -export interface WebhookMessageCreateOptions extends Omit { +export interface WebhookMessageCreateOptions + extends Omit { username?: string; avatarURL?: string; threadId?: Snowflake; From 21c724f1f3606fc20c617dbc5d884ad016fd7fa0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?T=C3=86MB=C3=98?= <69138346+TAEMBO@users.noreply.github.com> Date: Thu, 5 Dec 2024 13:35:58 -0800 Subject: [PATCH 2/2] feat: add ChannelManager#createMessage() --- .../discord.js/src/managers/ChannelManager.js | 50 +++++++++++++++++++ .../discord.js/src/managers/MessageManager.js | 31 +----------- .../discord.js/src/structures/GuildMember.js | 34 ++++++------- packages/discord.js/src/structures/Message.js | 19 +------ .../src/structures/MessagePayload.js | 13 ++--- packages/discord.js/src/structures/User.js | 34 ++++++------- .../structures/interfaces/TextBasedChannel.js | 25 ++-------- packages/discord.js/typings/index.d.ts | 24 ++++----- packages/discord.js/typings/index.test-d.ts | 21 ++++++-- 9 files changed, 123 insertions(+), 128 deletions(-) diff --git a/packages/discord.js/src/managers/ChannelManager.js b/packages/discord.js/src/managers/ChannelManager.js index 0126d914467d..e027563402fb 100644 --- a/packages/discord.js/src/managers/ChannelManager.js +++ b/packages/discord.js/src/managers/ChannelManager.js @@ -1,13 +1,17 @@ 'use strict'; const process = require('node:process'); +const { lazy } = require('@discordjs/util'); const { Routes } = require('discord-api-types/v10'); const CachedManager = require('./CachedManager'); const { BaseChannel } = require('../structures/BaseChannel'); +const MessagePayload = require('../structures/MessagePayload'); const { createChannel } = require('../util/Channels'); const { ThreadChannelTypes } = require('../util/Constants'); const Events = require('../util/Events'); +const getMessage = lazy(() => require('../structures/Message').Message); + let cacheWarningEmitted = false; /** @@ -123,6 +127,52 @@ class ChannelManager extends CachedManager { const data = await this.client.rest.get(Routes.channel(id)); return this._add(data, null, { cache, allowUnknownGuild }); } + + /** + * Creates a message in a channel. + * @param {TextChannelResolvable} channel The channel to send the message to + * @param {string|MessagePayload|MessageCreateOptions} options The options to provide + * @returns {Promise} + * @example + * // Send a basic message + * client.channels.createMessage(channel, 'hello!') + * .then(message => console.log(`Sent message: ${message.content}`)) + * .catch(console.error); + * @example + * // Send a remote file + * client.channels.createMessage(channel, { + * files: ['https://cdn.discordapp.com/icons/222078108977594368/6e1019b3179d71046e463a75915e7244.png?size=2048'] + * }) + * .then(console.log) + * .catch(console.error); + * @example + * // Send a local file + * client.channels.createMessage(channel, { + * files: [{ + * attachment: 'entire/path/to/file.jpg', + * name: 'file.jpg', + * description: 'A description of the file' + * }] + * }) + * .then(console.log) + * .catch(console.error); + */ + async createMessage(channel, options) { + let messagePayload; + + if (options instanceof MessagePayload) { + messagePayload = options.resolveBody(); + } else { + messagePayload = MessagePayload.create(this, options).resolveBody(); + } + + const resolvedChannelId = this.resolveId(channel); + const resolvedChannel = this.resolve(channel); + const { body, files } = await messagePayload.resolveFiles(); + const data = await this.client.rest.post(Routes.channelMessages(resolvedChannelId), { body, files }); + + return resolvedChannel?.messages._add(data) ?? new (getMessage())(this.client, data); + } } module.exports = ChannelManager; diff --git a/packages/discord.js/src/managers/MessageManager.js b/packages/discord.js/src/managers/MessageManager.js index a2c44c446352..dcddf2857383 100644 --- a/packages/discord.js/src/managers/MessageManager.js +++ b/packages/discord.js/src/managers/MessageManager.js @@ -2,9 +2,9 @@ const { Collection } = require('@discordjs/collection'); const { makeURLSearchParams } = require('@discordjs/rest'); -const { MessageReferenceType, Routes } = require('discord-api-types/v10'); +const { Routes } = require('discord-api-types/v10'); const CachedManager = require('./CachedManager'); -const { DiscordjsError, DiscordjsTypeError, ErrorCodes } = require('../errors'); +const { DiscordjsTypeError, ErrorCodes } = require('../errors'); const { Message } = require('../structures/Message'); const MessagePayload = require('../structures/MessagePayload'); const { MakeCacheOverrideSymbol } = require('../util/Symbols'); @@ -209,33 +209,6 @@ class MessageManager extends CachedManager { return this.cache.get(data.id) ?? this._add(data); } - /** - * Forwards a message to this manager's channel. - * @param {Message|MessageReference} reference The message to forward - * @returns {Promise} - */ - async forward(reference) { - if (!reference) throw new DiscordjsError(ErrorCodes.MessageReferenceMissing); - const message_id = this.resolveId(reference.messageId); - if (!message_id) throw new DiscordjsError(ErrorCodes.MessageReferenceMissing); - const channel_id = this.client.channels.resolveId(reference.channelId); - if (!channel_id) throw new DiscordjsTypeError(ErrorCodes.InvalidType, 'channel', 'ChannelResolvable'); - const guild_id = this.client.guilds.resolveId(reference.guildId); - - const data = await this.client.rest.post(Routes.channelMessages(this.channel.id), { - body: { - message_reference: { - message_id, - channel_id, - guild_id, - type: MessageReferenceType.Forward, - }, - }, - }); - - return this.cache.get(data.id) ?? this._add(data); - } - /** * Pins a message to the channel's pinned messages, even if it's not cached. * @param {MessageResolvable} message The message to pin diff --git a/packages/discord.js/src/structures/GuildMember.js b/packages/discord.js/src/structures/GuildMember.js index b1f1b5283460..8ff334674ff8 100644 --- a/packages/discord.js/src/structures/GuildMember.js +++ b/packages/discord.js/src/structures/GuildMember.js @@ -3,7 +3,6 @@ const { PermissionFlagsBits } = require('discord-api-types/v10'); const Base = require('./Base'); const VoiceState = require('./VoiceState'); -const TextBasedChannel = require('./interfaces/TextBasedChannel'); const { DiscordjsError, ErrorCodes } = require('../errors'); const GuildMemberRoleManager = require('../managers/GuildMemberRoleManager'); const { GuildMemberFlagsBitField } = require('../util/GuildMemberFlagsBitField'); @@ -11,7 +10,6 @@ const PermissionsBitField = require('../util/PermissionsBitField'); /** * Represents a member of a guild on Discord. - * @implements {TextBasedChannel} * @extends {Base} */ class GuildMember extends Base { @@ -478,6 +476,22 @@ class GuildMember extends Base { return this.guild.members.fetch({ user: this.id, cache: true, force }); } + /** + * Sends a message to this user. + * @param {string|MessagePayload|MessageCreateOptions} options The options to provide + * @returns {Promise} + * @example + * // Send a direct message + * guildMember.send('Hello!') + * .then(message => console.log(`Sent message: ${message.content} to ${guildMember.displayName}`)) + * .catch(console.error); + */ + async send(options) { + const dmChannel = await this.createDM(); + + return this.client.channels.createMessage(dmChannel, options); + } + /** * Whether this guild member equals another guild member. It compares all properties, so for most * comparison it is advisable to just compare `member.id === member2.id` as it is significantly faster @@ -529,20 +543,4 @@ class GuildMember extends Base { } } -/** - * Sends a message to this user. - * @method send - * @memberof GuildMember - * @instance - * @param {string|MessagePayload|MessageCreateOptions} options The options to provide - * @returns {Promise} - * @example - * // Send a direct message - * guildMember.send('Hello!') - * .then(message => console.log(`Sent message: ${message.content} to ${guildMember.displayName}`)) - * .catch(console.error); - */ - -TextBasedChannel.applyToClass(GuildMember); - exports.GuildMember = GuildMember; diff --git a/packages/discord.js/src/structures/Message.js b/packages/discord.js/src/structures/Message.js index 63906512884b..efb44ac8027f 100644 --- a/packages/discord.js/src/structures/Message.js +++ b/packages/discord.js/src/structures/Message.js @@ -21,7 +21,7 @@ const MessagePayload = require('./MessagePayload'); const { Poll } = require('./Poll.js'); const ReactionCollector = require('./ReactionCollector'); const { Sticker } = require('./Sticker'); -const { DiscordjsError, DiscordjsTypeError, ErrorCodes } = require('../errors'); +const { DiscordjsError, ErrorCodes } = require('../errors'); const ReactionManager = require('../managers/ReactionManager'); const { createComponent } = require('../util/Components'); const { NonSystemMessageTypes, MaxBulkDeletableMessageAge, UndeletableMessageTypes } = require('../util/Constants'); @@ -768,20 +768,6 @@ class Message extends Base { return message; } - /** - * Forwards this message. - * @param {ChannelResolvable} channel The channel to forward this message to - * @returns {Promise} - */ - async forward(channel) { - const resolvedChannel = this.client.channels.resolve(channel); - - if (!resolvedChannel) throw new DiscordjsTypeError(ErrorCodes.InvalidType, 'channel', 'ChannelResolvable'); - - const message = await resolvedChannel.messages.forward(this); - return message; - } - /** * Whether the message is crosspostable by the client user * @type {boolean} @@ -928,7 +914,6 @@ class Message extends Base { * .catch(console.error); */ reply(options) { - if (!this.channel) return Promise.reject(new DiscordjsError(ErrorCodes.ChannelNotCached)); let data; if (options instanceof MessagePayload) { @@ -944,7 +929,7 @@ class Message extends Base { }, }); } - return this.channel.send(data); + return this.client.channels.createMessage(this.channelId, data); } /** diff --git a/packages/discord.js/src/structures/MessagePayload.js b/packages/discord.js/src/structures/MessagePayload.js index 773e6d93078c..22854a008d10 100644 --- a/packages/discord.js/src/structures/MessagePayload.js +++ b/packages/discord.js/src/structures/MessagePayload.js @@ -170,15 +170,12 @@ class MessagePayload { let message_reference; if (this.options.messageReference) { const reference = this.options.messageReference; - const message_id = this.target.messages.resolveId(reference.messageId); - const channel_id = this.target.client.channels.resolveId(reference.channelId); - const guild_id = this.target.client.guilds.resolveId(reference.guildId); - if (message_id) { + if (reference.messageId) { message_reference = { - message_id, - channel_id, - guild_id, + message_id: reference.messageId, + channel_id: reference.channelId, + guild_id: reference.guildId, type: reference.type, fail_if_not_exists: reference.failIfNotExists ?? this.target.client.options.failIfNotExists, }; @@ -298,7 +295,7 @@ module.exports = MessagePayload; /** * A target for a message. - * @typedef {TextBasedChannels|User|GuildMember|Webhook|WebhookClient|BaseInteraction|InteractionWebhook| + * @typedef {TextBasedChannels|ChannelManager|Webhook|WebhookClient|BaseInteraction|InteractionWebhook| * Message|MessageManager} MessageTarget */ diff --git a/packages/discord.js/src/structures/User.js b/packages/discord.js/src/structures/User.js index 6025410c30f1..7ea59929ac57 100644 --- a/packages/discord.js/src/structures/User.js +++ b/packages/discord.js/src/structures/User.js @@ -4,12 +4,10 @@ const { userMention } = require('@discordjs/formatters'); const { calculateUserDefaultAvatarIndex } = require('@discordjs/rest'); const { DiscordSnowflake } = require('@sapphire/snowflake'); const Base = require('./Base'); -const TextBasedChannel = require('./interfaces/TextBasedChannel'); const UserFlagsBitField = require('../util/UserFlagsBitField'); /** * Represents a user on Discord. - * @implements {TextBasedChannel} * @extends {Base} */ class User extends Base { @@ -277,6 +275,22 @@ class User extends Base { return this.client.users.deleteDM(this.id); } + /** + * Sends a message to this user. + * @param {string|MessagePayload|MessageCreateOptions} options The options to provide + * @returns {Promise} + * @example + * // Send a direct message + * user.send('Hello!') + * .then(message => console.log(`Sent message: ${message.content} to ${user.tag}`)) + * .catch(console.error); + */ + async send(options) { + const dmChannel = await this.createDM(); + + return this.client.channels.createMessage(dmChannel, options); + } + /** * Checks if the user is equal to another. * It compares id, username, discriminator, avatar, banner, accent color, and bot flags. @@ -361,20 +375,4 @@ class User extends Base { } } -/** - * Sends a message to this user. - * @method send - * @memberof User - * @instance - * @param {string|MessagePayload|MessageCreateOptions} options The options to provide - * @returns {Promise} - * @example - * // Send a direct message - * user.send('Hello!') - * .then(message => console.log(`Sent message: ${message.content} to ${user.tag}`)) - * .catch(console.error); - */ - -TextBasedChannel.applyToClass(User); - module.exports = User; diff --git a/packages/discord.js/src/structures/interfaces/TextBasedChannel.js b/packages/discord.js/src/structures/interfaces/TextBasedChannel.js index b039197041f7..8007fb4f6c44 100644 --- a/packages/discord.js/src/structures/interfaces/TextBasedChannel.js +++ b/packages/discord.js/src/structures/interfaces/TextBasedChannel.js @@ -7,7 +7,6 @@ const { DiscordjsTypeError, DiscordjsError, ErrorCodes } = require('../../errors const { MaxBulkDeletableMessageAge } = require('../../util/Constants'); const InteractionCollector = require('../InteractionCollector'); const MessageCollector = require('../MessageCollector'); -const MessagePayload = require('../MessagePayload'); /** * Interface for classes that have text-channel-like features. @@ -161,27 +160,8 @@ class TextBasedChannel { * .then(console.log) * .catch(console.error); */ - async send(options) { - const User = require('../User'); - const { GuildMember } = require('../GuildMember'); - - if (this instanceof User || this instanceof GuildMember) { - const dm = await this.createDM(); - return dm.send(options); - } - - let messagePayload; - - if (options instanceof MessagePayload) { - messagePayload = options.resolveBody(); - } else { - messagePayload = MessagePayload.create(this, options).resolveBody(); - } - - const { body, files } = await messagePayload.resolveFiles(); - const d = await this.client.rest.post(Routes.channelMessages(this.id), { body, files }); - - return this.messages.cache.get(d.id) ?? this.messages._add(d); + send(options) { + return this.client.channels.createMessage(this, options); } /** @@ -416,6 +396,7 @@ class TextBasedChannel { 'setNSFW', ); } + for (const prop of props) { if (ignore.includes(prop)) continue; Object.defineProperty( diff --git a/packages/discord.js/typings/index.d.ts b/packages/discord.js/typings/index.d.ts index 8a2ffe806a1f..3ff62d466556 100644 --- a/packages/discord.js/typings/index.d.ts +++ b/packages/discord.js/typings/index.d.ts @@ -2242,7 +2242,6 @@ export class Message extends Base { public equals(message: Message, rawData: unknown): boolean; public fetchReference(): Promise>>; public fetchWebhook(): Promise; - public forward(channel: TextBasedChannelResolvable): Promise; public crosspost(): Promise>>; public fetch(force?: boolean): Promise>>; public pin(reason?: string): Promise>>; @@ -3811,7 +3810,6 @@ export const Constants: { SweeperKeys: SweeperKey[]; NonSystemMessageTypes: NonSystemMessageType[]; TextBasedChannelTypes: TextBasedChannelTypes[]; - SendableChannels: SendableChannelTypes[]; GuildTextBasedChannelTypes: GuildTextBasedChannelTypes[]; ThreadChannelTypes: ThreadChannelType[]; VoiceBasedChannelTypes: VoiceBasedChannelTypes[]; @@ -4130,6 +4128,10 @@ export class CategoryChannelChildManager extends DataManager { private constructor(client: Client, iterable: Iterable); + public createMessage( + channel: Omit, + options: string | MessagePayload | MessageCreateOptions, + ): Promise; public fetch(id: Snowflake, options?: FetchChannelOptions): Promise; } @@ -4424,7 +4426,6 @@ export abstract class MessageManager extends public fetch(options: MessageResolvable | FetchMessageOptions): Promise>; public fetch(options?: FetchMessagesOptions): Promise>>; public fetchPinned(cache?: boolean): Promise>>; - public forward(reference: Omit): Promise>; public react(message: MessageResolvable, emoji: EmojiIdentifierResolvable): Promise; public pin(message: MessageResolvable, reason?: string): Promise; public unpin(message: MessageResolvable, reason?: string): Promise; @@ -6499,15 +6500,14 @@ export interface TextInputComponentData extends BaseComponentData { } export type MessageTarget = + | ChannelManager | Interaction | InteractionWebhook + | Message + | MessageManager | TextBasedChannel - | User - | GuildMember | Webhook - | WebhookClient - | Message - | MessageManager; + | WebhookClient; export interface MultipleShardRespawnOptions { shardDelay?: number; @@ -6811,26 +6811,26 @@ export type Channel = export type TextBasedChannel = Exclude, ForumChannel | MediaChannel>; -export type SendableChannels = Extract any }>; - export type TextBasedChannels = TextBasedChannel; export type TextBasedChannelTypes = TextBasedChannel['type']; export type GuildTextBasedChannelTypes = Exclude; -export type SendableChannelTypes = SendableChannels['type']; - export type VoiceBasedChannel = Extract; export type GuildBasedChannel = Extract; +export type SendableChannels = Extract any }>; + export type CategoryChildChannel = Exclude, CategoryChannel>; export type NonThreadGuildBasedChannel = Exclude; export type GuildTextBasedChannel = Extract; +export type SendableChannelTypes = SendableChannels['type']; + export type TextChannelResolvable = Snowflake | TextChannel; export type TextBasedChannelResolvable = Snowflake | TextBasedChannel; diff --git a/packages/discord.js/typings/index.test-d.ts b/packages/discord.js/typings/index.test-d.ts index b587e3bf25bd..df4fb6e164e6 100644 --- a/packages/discord.js/typings/index.test-d.ts +++ b/packages/discord.js/typings/index.test-d.ts @@ -423,12 +423,20 @@ client.on('messageCreate', async message => { assertIsMessage(channel.send({})); assertIsMessage(channel.send({ embeds: [] })); + assertIsMessage(client.channels.createMessage(channel, 'string')); + assertIsMessage(client.channels.createMessage(channel, {})); + assertIsMessage(client.channels.createMessage(channel, { embeds: [] })); + const attachment = new AttachmentBuilder('file.png'); const embed = new EmbedBuilder(); assertIsMessage(channel.send({ files: [attachment] })); assertIsMessage(channel.send({ embeds: [embed] })); assertIsMessage(channel.send({ embeds: [embed], files: [attachment] })); + assertIsMessage(client.channels.createMessage(channel, { files: [attachment] })); + assertIsMessage(client.channels.createMessage(channel, { embeds: [embed] })); + assertIsMessage(client.channels.createMessage(channel, { embeds: [embed], files: [attachment] })); + if (message.inGuild()) { expectAssignable>(message); const component = await message.awaitMessageComponent({ componentType: ComponentType.Button }); @@ -458,8 +466,13 @@ client.on('messageCreate', async message => { // @ts-expect-error channel.send(); // @ts-expect-error + client.channels.createMessage(); + // @ts-expect-error channel.send({ another: 'property' }); - + // @ts-expect-error + client.channels.createMessage({ another: 'property' }); + // @ts-expect-error + client.channels.createMessage('string'); // Check collector creations. // Verify that buttons interactions are inferred. @@ -620,7 +633,7 @@ client.on('messageCreate', async message => { const embedData = { description: 'test', color: 0xff0000 }; - channel.send({ + client.channels.createMessage(channel, { components: [row, rawButtonsRow, buttonsRow, rawStringSelectMenuRow, stringSelectRow], embeds: [embed, embedData], }); @@ -1265,7 +1278,7 @@ client.on('guildCreate', async g => { ], }); - channel.send({ components: [row, row2] }); + client.channels.createMessage(channel, { components: [row, row2] }); } channel.setName('foo').then(updatedChannel => { @@ -2540,7 +2553,7 @@ declare const sku: SKU; }); } -await textChannel.send({ +await client.channels.createMessage('123', { poll: { question: { text: 'Question',