Sync Bot — Server Mirroring
Synchronisation
How structure, messages, reactions and names are synced in detail.
Synchronisation
Structure (A → B)
Changes to the category on Server A are carried over to Server B:
- Creating, deleting, renaming channels
- Order (position) of the channels
- Properties: type (text, voice, forum, announcement), topic, slowmode, NSFW
Channel and category names
Names follow Server A by default:
- Without a custom name, a channel on B always follows A's name — including later renames on A.
- If a channel on B is renamed via the Discord UI, the bot reverts the name (to A's name, or to the custom name if one is set).
- A custom name is only created through
/sync rename-channel— the channel is then locked and no longer overwritten by renames on A. - The category on B can only be permanently renamed through
/sync rename-category.
Messages (A ↔ B)
Messages are mirrored both ways through webhooks — with the original author's display name and avatar. Text, attachments and embeds are carried over.
- Edits and deletes are mirrored, as are bulk deletes (purge).
- Messages from bots and third-party webhooks are mirrored too.
- Mentions trigger real pings — @user, roles and
@everyone/@here.
Loop prevention: messages that originate from the bot's own webhooks are detected and never
re-mirrored. This is exactly why a persistent database is needed (see below).
Reactions
Reactions are mirrored 1:1 (add and remove).
Discord does not allow reacting "on behalf of" another user — the mirrored reaction is added by the
bot. The emoji appears correctly on the partner post, but as a bot reaction. Custom emojis from
servers the bot is not a member of can't be added and are skipped.
Limits
- Message mirroring runs for text and announcement channels. Voice and forum channels are mirrored structurally, but not as a message stream.
Database
The bot stores its state in a SQLite database with four tables:
| Table | Contents |
|---|---|
sync_pairs | The A ↔ B connection incl. category info and status |
channel_mappings | Source channel ↔ target channel plus both webhooks |
message_mappings | Original message ↔ mirrored message (for edits/deletes) |
custom_names | Locked channel names on Server B |
The database is state-critical. If it does not live on a persistent path (
DATABASE_PATH), the
webhook IDs are lost after a restart and loop prevention no longer works.