# Spoiler Package Documentation **Discord Bot v2.0 - Spoiler Detection System** ## Overview The spoiler package monitors all messages for Discord spoiler tags (`||text||`) and pings the "Deez Watch" role when detected. This provides a fun, automated alert when users post spoilers in the server. ## Package Structure ``` commands/spoiler/ ├── CLAUDE.md # This documentation ├── __init__.py # Package setup with resilient loading └── listener.py # Spoiler detection listener ``` ## Components ### **SpoilerListener** (`listener.py`) **Purpose:** Monitors all messages for Discord spoiler syntax and posts role ping alerts. **Implementation:** ```python class SpoilerListener(commands.Cog): """Listens for spoiler tags and responds with Deez Watch role ping.""" @commands.Cog.listener(name='on_message') async def on_message_listener(self, message: discord.Message): # Uses shared message filters from utils.listeners if not should_process_message(message, *COMMAND_FILTERS): return # Detect Discord spoiler syntax (||) spoiler_count = message.content.count("||") if spoiler_count < 2: return # Find and ping the "Deez Watch" role deez_watch_role = discord.utils.get(message.guild.roles, name="Deez Watch") if deez_watch_role: await message.channel.send(f"{deez_watch_role.mention}!") else: # Fallback if role doesn't exist await message.channel.send("Deez Watch!") ``` ## Discord Spoiler Syntax Discord uses `||` markers to create spoiler tags: - `||hidden text||` creates a single spoiler - Multiple spoilers can exist in one message: `||spoiler 1|| some text ||spoiler 2||` - The listener detects any message with 2+ instances of `||` (i.e., at least one complete spoiler tag) ## Message Filtering Uses the shared `COMMAND_FILTERS` from `utils.listeners`, which includes: - **Ignore bot messages** - Prevents bot loops - **Ignore empty messages** - Messages with no content - **Ignore command prefix** - Messages starting with '!' (legacy commands) - **Ignore DMs** - Only process guild messages - **Guild validation** - Only process messages from configured guild See `utils/listeners.py` for filter implementation details. ## Logging The listener logs: - **Startup:** When the cog is initialized - **Detection:** When a spoiler is detected (with user info and spoiler count) - **Success:** When the alert is posted with role mention - **Warning:** When the Deez Watch role is not found (falls back to text) - **Errors:** Permission issues or send failures **Example log output (with role):** ``` INFO - SpoilerListener cog initialized INFO - Spoiler detected in message from Username (ID: 123456789) with 2 spoiler tag(s) DEBUG - Spoiler alert posted with role mention ``` **Example log output (without role):** ``` INFO - Spoiler detected in message from Username (ID: 123456789) with 1 spoiler tag(s) WARNING - Deez Watch role not found, posted without mention ``` ## Error Handling **Permission Errors:** - Catches `discord.Forbidden` when bot lacks send permissions - Logs error with channel ID for troubleshooting **General Errors:** - Catches all exceptions during message sending - Logs with full stack trace for debugging - Does not crash the bot or stop listening ## Requirements **Discord Role:** - A role named **"Deez Watch"** must exist in the guild - Bot automatically looks up the role by name at runtime - If role doesn't exist, bot falls back to posting "Deez Watch!" without mention **Permissions:** - Bot needs **Send Messages** permission in channels - Bot needs **Mention Everyone** permission to ping roles (if role is not mentionable) - Role can be set as mentionable to avoid needing special permissions ## Usage Examples **Single Spoiler (with role):** ``` User: Hey did you know that ||Bruce Willis is dead the whole time||? Bot: @Deez Watch! ``` **Multiple Spoilers:** ``` User: ||Darth Vader|| is ||Luke's father|| Bot: @Deez Watch! ``` **Fallback (no role):** ``` User: Hey did you know that ||Bruce Willis is dead the whole time||? Bot: Deez Watch! ``` **Edge Cases:** - Single `||` marker - **Not detected** (incomplete spoiler) - Text with `||` in code blocks - **Detected** (Discord doesn't parse spoilers in code blocks) - Empty spoilers `||||` - **Detected** (valid Discord syntax) ## Testing **Setup:** 1. Create a role named "Deez Watch" in your Discord server (recommended) 2. Set the role as mentionable OR ensure bot has "Mention Everyone" permission **Manual Testing:** 1. Start the bot in development mode 2. Post a message with `||test||` in the configured guild 3. Verify bot responds with @Deez Watch! (role mention) **Test Cases:** - ✅ Single spoiler tag with role mention - ✅ Multiple spoiler tags - ✅ Fallback to text if role doesn't exist - ✅ Bot ignores own messages - ✅ Bot ignores DMs - ✅ Bot ignores messages from other guilds - ✅ Bot ignores command messages (starting with '!') ## Performance Considerations **Impact:** - Listener processes every non-filtered message in the guild - String counting (`message.content.count("||")`) is O(n) but fast for typical message lengths - Only sends one message per detection (no loops) **Optimization:** - Early returns via message filters reduce processing - Simple string operation (no regex needed) - Async operations prevent blocking ## Future Enhancements Potential improvements for the spoiler system: 1. **Configurable Response:** - Custom responses per guild - Random selection from multiple responses - Embed responses with more context 2. **Cooldown System:** - Prevent spam by rate-limiting responses - Per-channel or per-user cooldowns - Configurable cooldown duration 3. **Statistics Tracking:** - Track spoiler counts per user - Leaderboard of "most spoiler-prone" users - Channel statistics 4. **Advanced Detection:** - Detect spoiler context (movie, game, book) - Different responses based on content - Integration with spoiler databases 5. **Permissions:** - Allow certain roles to bypass detection - Channel-specific enable/disable - Opt-in/opt-out system ## Related Files - **`utils/listeners.py`** - Shared message filtering utilities - **`commands/soak/listener.py`** - Similar listener pattern (template used) - **`bot.py`** - Package registration and loading --- **Last Updated:** October 2025 **Maintenance:** Keep logging and error handling consistent with other listeners **Next Review:** When additional listener features are requested