Prefix-command bot — latency, embeds, DMs, replies, and reactions.
ping-bot.js · 246 lines
Prefix-command bot — latency, embeds, DMs, replies, and reactions.
View on GitHubnode examples/ping-bot.js
javascript
/**
* Prefix-command bot — latency, embeds, DMs, replies, and reactions.
*
* Commands: !ping, !info, !help, !dm, !dmuser, !replytest, !replynoping, !react, !editembed, !attachurl
*
* Usage (from repo root after pnpm install && pnpm run build):
* FLUXER_BOT_TOKEN=your_token node examples/ping-bot.js
*
* For voice see voice-bot.js; for profiles / server info see info-bot.js.
*/
import {
Client,
Events,
EmbedBuilder,
Routes,
User,
parsePrefixCommand,
parseUserMention,
} from '@fluxerjs/core';
const PREFIX = '!';
const BRAND_COLOR = 0x4641d9;
function formatUptime(ms) {
const s = Math.floor(ms / 1000) % 60;
const m = Math.floor(ms / (1000 * 60)) % 60;
const h = Math.floor(ms / (1000 * 60 * 60)) % 24;
const d = Math.floor(ms / (1000 * 60 * 60 * 24));
const parts = [];
if (d > 0) parts.push(`${d}d`);
if (h > 0) parts.push(`${h}h`);
if (m > 0) parts.push(`${m}m`);
parts.push(`${s}s`);
return parts.join(' ');
}
async function measureApiLatency(client) {
const start = Date.now();
try {
await client.rest.get(Routes.gatewayBot());
} catch {
// Round-trip only
}
return Date.now() - start;
}
/** @type {Map<string, { description: string, execute: Function }>} */
const commands = new Map();
commands.set('ping', {
description: 'Check API latency',
async execute(message, client) {
const apiLatency = await measureApiLatency(client);
const embed = new EmbedBuilder()
.setTitle('Pong!')
.setColor(BRAND_COLOR)
.addFields({ name: 'API Latency', value: `\`${apiLatency}ms\``, inline: true })
.setFooter({ text: 'Fluxer Bot' })
.setTimestamp();
await message.reply({ embeds: [embed] });
},
});
commands.set('info', {
description: 'Display bot information',
async execute(message, client) {
const uptime = client.readyAt ? Date.now() - client.readyAt.getTime() : 0;
const apiLatency = await measureApiLatency(client);
const embed = new EmbedBuilder()
.setTitle('Bot Information')
.setColor(BRAND_COLOR)
.setThumbnail(client.user?.avatarURL?.() ?? null)
.addFields(
{ name: 'Username', value: client.user?.username ?? 'Unknown', inline: true },
{ name: 'Guilds', value: `${client.guilds.size}`, inline: true },
{ name: 'Channels', value: `${client.channels.size}`, inline: true },
{ name: 'Uptime', value: formatUptime(uptime), inline: true },
{ name: 'API Latency', value: `${apiLatency}ms`, inline: true },
{ name: 'Node.js', value: process.version, inline: true },
)
.setFooter({ text: 'Powered by @fluxerjs/core' })
.setTimestamp();
await message.reply({ embeds: [embed] });
},
});
commands.set('dm', {
description: 'DM yourself (demo of user.send)',
async execute(message) {
try {
await message.author.send('You requested a DM from the bot.');
await message.reply('Check your DMs!');
} catch {
await message.reply('Could not DM you. You may have DMs disabled.').catch(() => {});
}
},
});
commands.set('dmuser', {
description: 'DM a user: !dmuser @user [message]',
async execute(message, client, args) {
const userId = parseUserMention(args[0] ?? '');
if (!userId) {
await message.reply('Provide a user mention or ID. Example: `!dmuser @Someone Hello!`');
return;
}
const text = args.slice(1).join(' ') || 'Hello from the bot!';
try {
const userData = await client.rest.get(Routes.user(userId));
const user = new User(client, userData);
await user.send(text);
await message.reply(`Sent DM to **${user.globalName ?? user.username}**.`);
} catch {
await message
.reply('Could not send DM. The user may not exist or may have DMs disabled.')
.catch(() => {});
}
},
});
commands.set('replytest', {
description: 'Reply to your message (threaded reply)',
async execute(message) {
await message.reply('This message is a reply to yours.');
},
});
commands.set('replynoping', {
description: 'Reply without pinging you',
async execute(message) {
await message.reply('Replied silently — no @mention ping!', { ping: false });
},
});
commands.set('react', {
description: 'Reply and add reactions',
async execute(message) {
const reply = await message.reply('React below!');
await reply.react('👍');
await reply.react('❤️');
await reply.react('🎉');
},
});
commands.set('editembed', {
description: 'Edit an embed after sending',
async execute(message) {
const embed = new EmbedBuilder()
.setTitle('Original Embed')
.setDescription('This embed will be edited in 2 seconds...')
.setColor(BRAND_COLOR)
.setTimestamp();
const reply = await message.reply({ embeds: [embed] });
await new Promise((r) => setTimeout(r, 2000));
const updated = new EmbedBuilder()
.setTitle('Edited Embed')
.setDescription('Use `message.edit({ embeds: [...] })` — pass EmbedBuilder directly.')
.setColor(0x57f287)
.addFields(
{ name: 'Original', value: 'First state', inline: true },
{ name: 'Edited', value: 'Updated state', inline: true },
)
.setTimestamp();
await reply.edit({ embeds: [updated] });
},
});
commands.set('attachurl', {
description: 'Attach a file by URL',
async execute(message) {
await message.reply({
content: 'File attached from URL:',
files: [{ name: 'trulli.jpg', url: 'https://www.w3schools.com/html/pic_trulli.jpg' }],
});
},
});
commands.set('help', {
description: 'List available commands',
async execute(message) {
const fields = [...commands.entries()].map(([name, cmd]) => ({
name: `${PREFIX}${name}`,
value: cmd.description,
inline: true,
}));
const embed = new EmbedBuilder()
.setTitle('Commands')
.setDescription(
`Use \`${PREFIX}<command>\`. Also try \`examples/voice-bot.js\` (voice being reworked) and \`info-bot.js\`.`,
)
.setColor(BRAND_COLOR)
.addFields(...fields)
.setTimestamp();
await message.reply({ embeds: [embed] });
},
});
const token = process.env.FLUXER_BOT_TOKEN;
if (!token) {
console.error('Error: Set FLUXER_BOT_TOKEN environment variable');
process.exit(1);
}
const client = new Client({
intents: 0,
rest: process.env.FLUXER_API_URL ? { api: process.env.FLUXER_API_URL } : undefined,
});
client.on(Events.Ready, () => {
console.log(`Logged in as ${client.user?.username}`);
console.log(`Serving ${client.guilds.size} guild(s)`);
client.user?.setPresence({
status: 'online',
customStatus: { text: 'Try !help' },
});
});
client.on(Events.MessageCreate, async (message) => {
if (message.author.bot || !message.content) return;
const parsed = parsePrefixCommand(message.content, PREFIX);
if (!parsed) return;
const command = commands.get(parsed.command);
if (!command) return;
try {
await command.execute(message, client, parsed.args);
} catch (err) {
console.error(`Error executing ${parsed.command}:`, err);
await message.reply('An error occurred while running that command.').catch(() => {});
}
});
client.on(Events.Error, (err) => console.error('Client error:', err));
try {
await client.login(token);
} catch (err) {
console.error('Login failed:', err);
process.exit(1);
}