PlayMesh/Docs
HomeGitHubnpm

Chat

Built-in chat with real-time server-side moderation.

Overview

Clients send chat with client.chat(text); the server delivers one message per instance the sender is a member of, each delivery carrying its instance's path. client.chatTo(path, text) targets exactly one room - it requires membership, and invalid or unauthorized targets get one generic Chat target denied error. No handlers or event names to wire up.
client.chat('hello everyone');                 // every room you are in
client.chatTo('minigames/race-42', 'Ready!');  // exactly one room
client.onChat(message => console.log(`[${message.instance}] ${message.userId}: ${message.text}`));

Moderation

The server moderates every message in real time with the onChatMessage hook. Return true to pass a message through, a string to rewrite it, or false (or throw) to block it - only the sender is notified of a block.
The hook runs once per destination instance and receives the destination in its context, so rewrites and rejections apply to that destination only (each call sees the original text). Kicking the sender stops all remaining deliveries. A sender in three rooms triggers the hook three times per message - keep it fast or make it instance-aware.
mesh.onChatMessage(({ session, instance, text }) => {
  if (containsSlurs(text)) {
    session.kick('Watch your language'); // escalate: see below
    return false;                        // and drop the message
  }
  if (instance.path === 'minigames/race-42') return `[race] ${text}`;
  return censor(text); // rewrite, or return true to pass through
});
✦
Pair chat with the built-in rateLimit middleware to stop spam: mesh.use(rateLimit({ chat: 2 })).

Kicking sessions

session.kick(reason?) is a general session control, not a chat feature - it works anywhere you have a session (event handlers, middleware, admin tooling). The client is told why via client.onKick(reason => ...), then force-disconnected. Chat moderation is simply its most common trigger.
// Server - anywhere, not just chat hooks
session.kick('AFK too long');

// Client
client.onKick(reason => showKickedScreen(reason));