Excommunicado

Excommunicado is a Discord moderation bot designed to combat channel flooding and spam without resorting to bans or kicks.

In stealth mode, offending users do not realize they have been moved. They continue to see the entire server normally. Their public messages are silently deleted and forwarded to the shared XCOM Lounge room, where selected staff members can also be present to converse with them. Normal members never see the spam or the moderated room. This creates the illusion of a normal experience while containing the violation.

Table of Contents

Features

  • Slash commands only (modern Discord UX)
    • /xcom-setup one-time server initialization
    • /xcom @user [reason] excommunicate a user (manual or via auto-detection)
    • /xcom-release @user restore full access (the [XCOM] mark remains)
    • /xcom-unmark @user remove the permanent [XCOM] nickname mark
    • /xcom-vow <text> let an isolated user post a vow of redemption to staff
    • /xcom-witness @staff @target add a staff member to the shared lounge
    • /xcom-absolve @user release a user early once they earn enough points
    • /xcom-vote @user up|down community vote to excommunicate (or defend) a user
    • /xcom-votes @user staff view of a user's current vote tally
    • /xcom-keywords admin panel to curate auto-score keywords/phrases
    • /xcom-list view all currently XCOM users with reasons and timestamps
  • Automatic flood protection detects ≥5 messages within 8 seconds and auto-excommunicates
  • Community voting members up/down-vote a user; reaching a net +10 (with quorum) auto-XCOMs them; tallies reset weekly
  • Keyword auto-scoring admin-curated phrases (e.g. cracked-software/warez trading) add weighted points to a sender's score and can auto-XCOM critical abuse even when no admin is online
  • Absolution Points users earn points for good behavior in the xcom-lounge; staff can absolve early
  • Shared hidden channel xcom-lounge with 5-second slowmode
  • Persistent state atomic, corruption-safe JSON storage survives bot restarts
  • Mention-safe forwarding relocated messages never ping (@everyone/@here/roles are neutralized)
  • Rich embeds + DM notifications for offenders and staff logs
  • Graceful permission handling and role-hierarchy safety checks
  • Zero bans/kicks users stay in the server

Philosophy & Use Cases

Excommunicado solves the "ban vs. mute" dilemma for flooders:

  • Bans encourage alt accounts.
  • Timeouts/mutes still allow the user to see the server and feel excluded.
  • Excommunication gives the user a dedicated space to talk to moderators while completely removing their ability to disrupt public channels.

Ideal for:

  • High-traffic community servers
  • Gaming clans with strict chat rules
  • Support servers where users sometimes vent excessively
  • Any server that values retention over punishment

Requirements

  • Python ≥ 3.10
  • discord.py ≥ 2.4.0 + python-dotenv
  • Discord bot with privileged intents enabled:
    • Server Members Intent
    • Message Content Intent
  • Bot permissions on invite: Manage Roles, Manage Channels, Send Messages, Embed Links, Read Message History (Administrator recommended for initial setup)
  • Role hierarchy: Bot role must sit above the Excommunicado role

Installation & Quick Start

  1. Make sure you have Docker and Docker Compose installed.
  2. Copy .env.example.env and fill in your token.
  3. Build and run the container:
docker compose up -d --build

The bot runs as a non-root user with healthchecks and log rotation.

To view logs:

docker compose logs -f excommunicado

To stop:

docker compose down

Manual Installation (Non-Docker)

1. Prepare the project

cd ~/Excommunicado   # or your chosen folder

2. Install dependencies

pip install -r requirements.txt

3. Configure environment

cp .env.example.env and populate:

DISCORD_TOKEN=your_token_here
GUILD_ID=123456789012345678          # optional  speeds up command registration during development
LOG_CHANNEL_ID=987654321098765432    # optional  receives audit embeds

4. Create & invite the bot (Discord Developer Portal)

  1. https://discord.com/developers/applications → New Application → Bot
  2. Enable the two privileged intents under the Bot tab
  3. Generate a token (copy to .env)
  4. OAuth2 → URL Generator → bot + applications.commands scopes + required permissions
  5. Invite the bot to your target guild

5. Run the bot

python bot.py

You should see:

✅ Logged in as Excommunicado#1234 ...
Excommunicado bot is ready (XCOM stealth isolation mode).
[COG] Moderation (Excommunicado) loaded.

6. Run /xcom-setup in Discord

(Requires Manage Server permission)

This creates:

  • Excommunicado role (dark red color)
  • xcom-lounge text channel (hidden, slowmode 5s)

7. Manual role lockdown (critical for older non-stealth setups)

After setup, the Excommunicado role is only a marker. Do not deny View on public channels (stealth mode keeps the user seeing the full server). The xcom-lounge is already hidden from @everyone.

8. Test the flow

/xcom @SomeSpammer Flooding with repeated messages

The user is stealthily XCOM'd. Their messages are forwarded to the shared room. They receive a DM and a staff log is sent (if configured).

Detailed Command Reference

/xcom-setup

  • Permission: Manage Server
  • Purpose: Idempotent creation of role + channel
  • Output: Embed explaining next manual steps

/xcom <user> [reason]

  • Permission: Manage Roles
  • Parameters:
    • user (required) target member
    • reason (optional) default "Flooding the channel"
  • Effects:
    • Assigns Excommunicado role
    • Applies the permanent [XCOM] nickname mark (best-effort; needs Manage Nicknames)
    • Records in data/xcom_config.json
    • Posts welcome embed in xcom-lounge
    • DMs the user
    • Logs to staff channel (if set)
  • Role-hierarchy safety: refuses to XCOM the server owner, a member whose top role is equal to or higher than the invoker's, or a member ranked above the bot — each returns a clear ephemeral error instead of failing silently.
  • Cooldown: max 5 uses per 15 seconds per moderator (per guild) to prevent accidental mass-spam.
  • Edge cases: Already under XCOM, bot, self-target, missing hierarchy → clear ephemeral error

/xcom-release <user>

  • Permission: Manage Roles
  • Effects: Removes role + record. The [XCOM] nickname mark remains until an admin runs /xcom-unmark.

/xcom-unmark <user>

  • Permission: Manage Roles
  • Effects: Removes the permanent [XCOM] nickname prefix.

/xcom-vow <text>

  • Permission: None (user must be under XCOM)
  • Effects: Posts the user's vow in the xcom-lounge for staff to see.

/xcom-witness @staff @target

  • Permission: Manage Roles
  • Effects: Gives the staff member the Excommunicado role so they can join the shared lounge.

/xcom-absolve @user

  • Permission: Manage Roles
  • Cooldown: max 5 uses per 15 seconds per moderator (per guild)
  • Effects: If the user has ≥10 absolution points (earned by positive participation in the lounge), removes the role early. The mark remains.

/xcom-list

  • Permission: Manage Roles
  • Output: Embed listing up to 15 users with reason + date (truncated if more)

/xcom-vote <user> <up|down>

  • Permission: None (any member) — light cooldown of 10 uses / 60s per member
  • Effects: Casts a weighted community vote on the target's running score.
    • up = excommunicate, down = defend.
    • Admins/moderators count ±2; regular members ±1.
    • One vote per voter per target per 24h (re-voting replaces your previous vote).
    • When the net score ≥ 10 and at least 5 distinct voters have participated, the user is automatically XCOM'd and the tally is cleared.
    • Tallies reset weekly.
  • Guardrails: cannot vote on yourself, bots, the server owner, staff/moderators, or anyone ranked above the bot. Confirmations are ephemeral (preserves stealth, avoids public pile-on).

/xcom-votes <user>

  • Permission: Manage Roles
  • Output: Ephemeral embed showing the target's current score, distinct-voter count, threshold, and quorum, with a breakdown of points from human votes vs. keyword flags.

/xcom-keywords

  • Permission: Manage Server (admin)
  • Effects: Opens an interactive ephemeral panel to curate the auto-score keyword/phrase list:
    • Add / Edit — a modal to enter a phrase and its score weight (1100). Re-adding an existing phrase updates its weight.
    • Remove — a modal to delete a phrase.
    • Refresh — re-render the current list.
  • How it works: any non-staff message containing a listed phrase (case-insensitive substring match) adds that phrase's weight to the sender's community score. When the score reaches the XCOM threshold, the user is auto-isolated — no quorum required, since this path is meant to capture abuse when no admin is online. Staff, the server owner, and members ranked above the bot are immune.

All commands are ephemeral where possible to keep chat clean.

Configuration

Environment Variables

Variable Required Description
DISCORD_TOKEN Yes Bot token
GUILD_ID No Guild for faster slash command sync
LOG_CHANNEL_ID No Channel that receives action embeds

Tunable Constants (in bot.py)

FLOOD_THRESHOLD = 5       # messages
FLOOD_WINDOW_SECONDS = 8  # within this many seconds

A user who sends FLOOD_THRESHOLD messages within FLOOD_WINDOW_SECONDS is auto-excommunicated. Change and restart to adjust sensitivity.

Community Vote Constants (in cogs/moderation.py)

VOTE_XCOM_THRESHOLD = 10      # net score required to auto-XCOM a user
VOTE_ADMIN_WEIGHT = 2         # admins / moderators count double
VOTE_USER_WEIGHT = 1          # regular members
VOTE_COOLDOWN_HOURS = 24      # one vote per voter per target per 24h
VOTE_RESET_DAYS = 7           # tallies reset weekly
VOTE_MIN_UNIQUE_VOTERS = 5    # quorum: distinct voters required before XCOM fires

Recommended guardrails (already enforced):

  • Quorum (VOTE_MIN_UNIQUE_VOTERS) prevents a handful of admins (±2 each) or a tiny brigade from instantly triggering an XCOM — a genuine community consensus is required.
  • Staff immunity — moderators/admins and the server owner can't be vote-targeted.
  • Hierarchy check — the bot refuses votes it couldn't enforce.
  • Ephemeral results keep the target unaware (stealth) and discourage public harassment campaigns.
  • Auto-clear on trigger stops a target from being re-XCOM'd on the very next vote.

Tune VOTE_XCOM_THRESHOLD and VOTE_MIN_UNIQUE_VOTERS together to match your server size — larger servers should raise both.

Keyword Auto-Scoring

Admins curate the phrase list live via /xcom-keywords (no restart needed). Each phrase has an integer weight; a matching message adds that weight to the sender's community score (the same score /xcom-vote feeds). Notes:

  • Matching is case-insensitive substring, so curate carefully — this is a cybersecurity channel where some terms are legitimate in context. Prefer specific phrases ("selling cracked") over broad single words ("crack").
  • Multiple distinct phrases matched in one message stack their weights.
  • A high weight (e.g. 10) makes a single message enough to XCOM instantly; low weights (13) require repeated abuse.
  • Keyword points are part of the weekly-resetting score and are shown separately in /xcom-votes.
  • The keyword path bypasses the human voter quorum by design, but still respects staff/owner immunity and bot role hierarchy.

Data File

data/xcom_config.json (auto-created). Writes are atomic (written to a temp file, then os.replaced) and the file is cached in memory, so the bot does not re-read disk on every message:

{
  "123456789": {
    "xcom_role_id": 111111111,
    "xcom_channel_id": 222222222,
    "isolated_users": {
      "333333333": {
        "reason": "Auto-detected flooding...",
        "timestamp": "2026-06-08T12:34:56.789012+00:00",
        "absolution_points": 0,
        "marked": true
      }
    },
    "votes": {
      "444444444": {
        "week_start": "2026-06-08T00:00:00+00:00",
        "voters": {
          "555555555": { "direction": 1, "weight": 2, "timestamp": "2026-06-08T12:00:00+00:00" }
        },
        "keyword_points": 3
      }
    },
    "keywords": {
      "selling cracked software": {
        "weight": 5,
        "added_by": 555555555,
        "added_at": "2026-06-08T10:00:00+00:00",
        "display": "selling cracked software"
      }
    }
  }
}
  • absolution_points earned by positive participation in the lounge; /xcom-absolve needs ≥10.
  • marked whether the permanent [XCOM] nickname mark is applied.
  • votes per-target community-vote tallies; each voter's direction (±1) × weight is summed, plus keyword_points from auto-scoring, into the net score; the whole record is discarded once week_start is older than a week.
  • keywords admin-curated auto-score phrases (managed via /xcom-keywords).

If the file is ever corrupted, the bot backs it up to xcom_config.json.corrupt and starts fresh instead of crashing.

How Isolation Works (Technical) — Stealth Mode

  1. On /xcom-setup, the bot creates:
    • Excommunicado role (marker only)
    • xcom-lounge channel (hidden from @everyone, visible to Excommunicado role holders)
  2. When a user is excommunicated (manually or automatically):
    • They receive the Excommunicado role (grants access to the shared room)
    • No view permissions are removed from public channels — the user continues to see the full server and does not realize anything changed.
  3. On every message the isolated user sends outside xcom-lounge:
    • The message is instantly deleted (public never sees the spam)
    • The content is forwarded to the shared xcom-lounge room with all mentions neutralized (no @everyone/@here/role pings) and truncated to Discord's 2000-character limit
    • Staff members who also hold the Excommunicado role can see and reply in the same room
  4. The offender experiences normal server browsing + "their messages just go to the moderated lounge where staff are"
  5. /xcom-release removes the role — full normal behavior is restored instantly

This design ensures the violation holder shares the room with real staff members while never realizing they have been isolated.

Architecture & Code Structure

Excommunicado/
├── bot.py                 # Entry point, flood detector (on_message), ExcommunicadoBot class
├── requirements.txt
├── .env.example
├── README.md              # This file (full documentation)
├── utils/
│   ├── config.py          # JSON load/save helpers + isolated user CRUD
│   └── __init__.py
├── cogs/
│   ├── moderation.py      # All slash commands + helper functions
│   └── __init__.py
└── data/
    └── xcom_config.json

Key flows:

  • on_message → rate-limit deque → auto call to get_or_create_* + add_roles
  • Commands → permission checks → role/channel helpers → config persistence → DM + embed

Customization

  • Change role name/color in get_or_create_xcom_role
  • Change channel name/slowmode in get_or_create_xcom_channel
  • Add more commands by creating additional cogs
  • Integrate with existing mod bots via webhooks or shared log channel

Troubleshooting

  • "Missing Permissions" on role assign → Bot role not high enough in hierarchy
  • Commands not appearing → Restart bot after GUILD_ID change; wait 1h for global sync
  • Isolated user messages still appear publicly → The stealth suppression logic in on_message is not triggering (check that the user has the Excommunicado role or is in the isolated_users JSON)
  • Auto-detection too sensitive → Increase FLOOD_WINDOW_SECONDS or threshold
  • JSON corrupted → The bot auto-recovers: the bad file is moved to data/xcom_config.json.corrupt and a fresh one is created. Restore from the backup if you need the old data.
  • [XCOM] mark not applied → Bot is missing Manage Nicknames, or the target outranks the bot (role assignment still succeeds; the mark is best-effort)

Security Best Practices

  • Never commit .env or the token (the provided .gitignore already excludes .env, .env.*, and data/)
  • Use a dedicated bot account (not your personal account)
  • Give the bot the minimum permissions required
  • Regularly audit data/xcom_config.json for old entries
  • Give trusted staff the Excommunicado role so they can share the moderated room with XCOM users and respond naturally

Built-in hardening

  • No mention abuse: forwarded messages are sent with mentions disabled, so an isolated user cannot make the bot ping @everyone, @here, or any role.
  • Length-safe forwarding: relocated messages are truncated to Discord's 2000-character limit; image/sticker-only messages forward a placeholder instead of failing.
  • Atomic persistence: config writes can't half-complete and corrupt state; a corrupt file is quarantined automatically.
  • Role-hierarchy enforcement: /xcom will not target the owner, equal/higher-ranked members, or members above the bot.
  • Command cooldowns: /xcom and /xcom-absolve are rate-limited (5 per 15s per moderator) and surface a friendly "slow down" message instead of erroring.
  • Runs as non-root in Docker with healthchecks and log rotation.

Extending the Bot

Example: add a /xcom-stats command counting total excommunications.

  1. Add new @app_commands.command in moderation.py
  2. Use get_isolated_users to aggregate data
  3. Register in setup()

The modular cog design makes extension trivial.

License

Internal moderation tool. Free to modify and use within your communities.


Excommunicado Excommunicate the flood, keep the member.

(End of full documentation)

Made to keep your server clean without destroying community members.

Usage Examples

  • /xcom @Spammer42 Spamming links and flooding
  • /xcom-list
  • /xcom-release @Spammer42

The user is now under XCOM in the shared moderated room — problem contained.

S
Description
Excommunicado is a Discord moderation bot designed to combat channel flooding and spam without resorting to bans or kicks. In stealth mode, offending users do not realize they have been moved. They continue to see the entire server normally. Their public messages are silently deleted and forwarded to the shared XCOM Lounge room, where selected staff members can also be present to converse with them. Normal members never see the spam or the moderated room. This creates the illusion of a normal experience while containing the violation.
https://churchofmalware.org
Readme 123 KiB
Languages
Python 98.9%
Dockerfile 1.1%