Appearance
Sending Without Reply
Send messages to the same channel or to specific channels. Covers message.send(), message.sendTo(), client.channels.send(), and client.channels.resolve().
message.send() vs message.reply()
message.reply() sends a message that references another message (shows as a "reply" in Discord). message.send() sends to the same channel with no reference—a regular standalone message.
Sending to the same channel
Use message.send() when you want to post in the channel without replying. Same signature as reply(): pass a string or object with content and/or embeds.
javascript
import { Client, Events } from '@erinjs/core';
const client = new Client({ intents: 0 });
client.on(Events.MessageCreate, async (message) => {
if (message.content === '!hello') {
await message.send('Hello! This is a regular message, not a reply.');
}
});
await client.login(process.env.ERIN_BOT_TOKEN);Sending to a specific channel (e.g. logging)
Use message.sendTo(channelId, payload) to send to another channel—handy for logging, announcements, or forwarding. You only need the target channel ID.
javascript
import { Client, Events, EmbedBuilder } from '@erinjs/core';
const client = new Client({ intents: 0 });
const LOG_CHANNEL_ID = process.env.LOG_CHANNEL_ID; // Your log channel's snowflake
client.on(Events.MessageCreate, async (message) => {
if (message.content === '!report' && message.guildId && LOG_CHANNEL_ID) {
const embed = new EmbedBuilder()
.setTitle('User report')
.setDescription(message.content)
.addFields(
{ name: 'Author', value: message.author.username, inline: true },
{ name: 'Channel', value: `<#${message.channelId}>`, inline: true }
)
.setTimestamp();
await message.sendTo(LOG_CHANNEL_ID, { embeds: [embed] });
await message.send('Report logged.');
}
});
await client.login(process.env.ERIN_BOT_TOKEN);client.channels.send() — send by channel ID
Use client.channels.send(channelId, payload) when you have a channel ID. Works even if the channel is not cached. No need to fetch first when you only need to send.
javascript
import { Client, Events } from '@erinjs/core';
const client = new Client({ intents: 0 });
const ANNOUNCE_CHANNEL_ID = process.env.ANNOUNCE_CHANNEL_ID;
client.on(Events.Ready, async () => {
if (ANNOUNCE_CHANNEL_ID) {
await client.channels.send(ANNOUNCE_CHANNEL_ID, 'Bot is online!');
}
});
await client.login(process.env.ERIN_BOT_TOKEN);client.channels.resolve() — get channel by ID
Resolve a channel by ID from cache or API. Use channel.canSendMessage() or channel.isTextBased() before sending. For sending when you only have an ID, prefer client.channels.send() which skips the fetch.
javascript
import { Client } from '@erinjs/core';
const client = new Client({ intents: 0 });
await client.login(process.env.ERIN_BOT_TOKEN);
// Fetch channel (from API if not cached)
const channel = await client.channels.resolve(channelId);
if (channel?.canSendMessage()) {
await channel.send('Hello!');
}
// Or for webhooks: if (channel?.createWebhook) { ... }fetch message by id
Use channel.messages.fetch(messageId) when you have the channel. For IDs-only, fetch the channel first.
javascript
// When you have the channel
const message = await channel.messages.fetch(messageId);
if (message) {
await message.edit({ content: 'Updated!' });
await message.react('👍');
}
// When you only have IDs (e.g. from sqlite)
const ch = await client.channels.resolve(channelId);
const msg = await ch?.messages?.fetch(messageId);
if (msg) await msg.delete();
// When channel is cached
const m = client.channels.get(channelId);
if (m?.canSendMessage()) {
const mes = await m.messages.fetch(messageId);
if (mes) await mes.edit({ content: 'Edited!' });
}
// Refresh a stale message instance
const updated = await message.fetch();
if (updated) console.log(updated.content);message.channel and message.channel.send()
message.channel returns the channel (from cache); null if not cached. Messages only exist in text-based channels, so when non-null it always has send(). Use message.channel.send() for the same as message.send() but via the channel object.
javascript
client.on(Events.MessageCreate, async (message) => {
const channel = message.channel; // TextChannel | DMChannel | GuildChannel | null
const guild = message.guild; // Guild | null (null for DMs)
if (channel) {
await channel.send('Same channel, different API'); // or message.send()
}
});channel.canSendMessage() — permission check
Before sending, use canSendMessage() to check if the bot has ViewChannel and SendMessages. For DMs always true; for guild channels uses guild.members.me permissions.
javascript
const channel = await client.channels.resolve(channelId);
if (channel?.canSendMessage()) {
await channel.send('Hello!');
}Typing indicator
Use channel.sendTyping() before a slow operation so users see "Bot is typing...". Lasts ~10 seconds.
javascript
const channel = message.channel ?? (await message.resolveChannel());
if (channel?.canSendMessage?.()) {
await channel.sendTyping();
await slowOperation(); // e.g. fetch external API
await message.reply('Done!');
}Quick reference
javascript
// Same channel, no reply
await message.send('Pong!');
// Reply to the message
await message.reply('Pong!');
// Send to a specific channel
await message.sendTo(logChannelId, 'User joined!');
await client.channels.send(channelId, 'New update available!');