Sending Messages

Fetch a channel, then channel.send. Reply with message.reply. Forward with send({ forward }).

Fetch the channel, then send. Guild text, guild voice, and DMs are text-based. channel.send throws INVALID_CHANNEL_TYPE on category and link channels only. Voice chat uses the same send / reply path as a text channel.

javascript
const channel = await client.channels.fetch(channelId);
if (!channel.isTextBased()) return;
await channel.send('hi');

From a message (full Message or PartialMessage):

javascript
const channel = await message.resolveChannel();
await channel.send('hi');

channel.toString() is <#id>. client.channels.delete(id) only drops the cache; API delete is channel.delete().

Reply vs send

message.reply() is a threaded reply. Use channel.send() for a standalone post in that channel.

javascript
client.on(Events.MessageCreate, async (message) => {
  if (message.content === '!ping') await message.reply('Pong!');
  if (message.content === '!hello') {
    const channel = message.channel ?? (await message.resolveChannel());
    await channel.send('Hello. Not a reply.');
  }
});

Skip the reply ping:

javascript
await message.reply('Got it.', { ping: false });

Forward

Post a copy of an existing message into this channel. Do not combine replyTo and forward on the same send.

javascript
const dest = await client.channels.fetch(logChannelId);
if (!dest.isTextBased()) return;

await dest.send({
  content: 'Forwarded from another channel:',
  forward: {
    channelId: message.channelId,
    messageId: message.id,
    guildId: message.guildId,
  },
});

Received forwards expose snapshots on message.messageSnapshots.

Voice text

If channel.isVoice() (or channel.isTextBased()), send works. Playing audio is a different package: Voice.

javascript
if (channel.isVoice()) {
  await channel.send('Talk in the VC chat.');
}

Another channel

javascript
const log = await client.channels.fetch(logChannelId);
if (!log.isTextBased()) return;
await log.send({ embeds: [embed] });

message.channel is the cached text, voice, or DM channel, or null. message.member is the author's cached member.

Fetch a message

javascript
const channel = await client.channels.fetch(channelId);
if (!channel.isTextBased()) return;
const msg = await channel.messages.fetch(messageId);
await msg.edit({ content: 'Updated!' });

Typing

javascript
const channel = message.channel ?? (await message.resolveChannel());
await channel.sendTyping();
await slowOperation();
await message.reply('Done!');

message.send / message.sendTo / client.channels.send still exist if you only have IDs and do not want the channel object. Prefer fetch then channel.send.

See also: Embeds, File Attachments, Allowed Mentions, Channels.

Questions?Join the Fluxer community for help with the SDK.Join Fluxer