3.5 KiB
3.5 KiB
sidebar_position
| sidebar_position |
|---|
| 6 |
Messages and Typing API
The messages API reads current messages, sends messages, edits or deletes plugin-owned messages, moderates messages, syncs messages, and exposes typing state.
Required Capabilities
| Method | Capability |
|---|---|
messages.readCurrent() |
messages.read |
messages.send(content, channelId?) |
messages.send |
messages.sendAsPluginUser(request) |
messages.send |
messages.setTyping(isTyping, channelId?) |
messages.send |
messages.subscribeTyping(handler) |
messages.read |
messages.edit(messageId, content) |
messages.editOwn |
messages.delete(messageId) |
messages.deleteOwn |
messages.moderateDelete(messageId) |
messages.moderate |
messages.sync(messages) |
messages.sync |
Read Current Messages
export function activate(context) {
const messages = context.api.messages.readCurrent();
context.api.logger.info('Current messages', messages.slice(-3).map((message) => ({
id: message.id,
channelId: message.channelId,
senderName: message.senderName,
content: message.content
})));
}
Send a Message
export function activate(context) {
const created = context.api.messages.send(
'Reminder: raid starts at 20:00. Bring repairs and snacks.',
'general'
);
context.api.logger.info('Sent reminder', { messageId: created.id });
}
Send as a Plugin User
export function activate(context) {
const botUserId = context.api.server.registerPluginUser({
id: 'poll-bot',
displayName: 'Poll Bot'
});
context.api.messages.sendAsPluginUser({
pluginUserId: botUserId,
channelId: 'general',
content: 'Poll is open: react with 1 for dungeon, 2 for arena, 3 for crafting.'
});
}
Capabilities required: users.manage and messages.send.
Edit and Delete Plugin-Owned Messages
export function activate(context) {
const message = context.api.messages.send('Draft event reminder', 'announcements');
context.api.messages.edit(message.id, 'Event reminder: voice meetup starts in 15 minutes.');
context.api.messages.delete(message.id);
}
Moderation Delete
export function activate(context) {
context.api.messages.moderateDelete('msg-spam-20260429-001');
}
Use moderation from explicit moderator actions, not automatic activation.
Typing State
export function activate(context) {
context.api.messages.setTyping(true, 'general');
setTimeout(() => {
context.api.messages.setTyping(false, 'general');
}, 1500);
context.subscriptions.push(context.api.messages.subscribeTyping((event) => {
context.api.logger.info('Typing event', {
displayName: event.displayName,
isTyping: event.isTyping,
channelId: event.channelId,
serverId: event.serverId,
voiceChannel: event.voiceChannel?.name ?? null
});
}));
}
Example typing event:
{
"serverId": "room-7ebdde75",
"channelId": "general",
"userId": "user-muse-01",
"displayName": "Muse",
"isTyping": true
}
Sync Messages
export function activate(context) {
context.api.messages.sync([
{
id: 'external-standup-001',
roomId: 'room-7ebdde75',
channelId: 'standup',
senderId: 'standup-importer',
senderName: 'Standup Importer',
content: 'Imported note: Alice is working on plugin docs.',
timestamp: 1777473600000,
isDeleted: false
}
]);
}
Sync should preserve message ids and timestamps from the source system when possible.