Py-cord does not have a native global ban feature because Discord API limits server-specific actions to individual guilds. To implement a global ban, developers must maintain a persistent database of banned user IDs and cross-reference every member join or message event against this list. This approach ensures that users banned in one server are automatically blocked from joining or interacting in any other server managed by the same bot.
The Architecture of Global Moderation
Implementing a global ban system requires a shift from local state management to a centralized data structure. Since the Discord API provides no endpoint to ban a user across all servers simultaneously, the responsibility falls on the application logic to enforce restrictions consistently. The core mechanism involves storing theUser.id of offenders in a reliable storage solution, such as SQLite, PostgreSQL, or Redis. When the bot starts or when an admin issues a command, the system loads these identifiers into memory for rapid lookup.
The enforcement logic operates at two primary levels: gateway events and command execution. For gateway events, the bot listens for on_member_join. If the joining user's ID exists in the global ban list, the bot immediately kicks or bans them from the specific guild where they attempted to enter. This prevents the user from accessing any content within that server. For command execution, the bot checks the global ban status before processing any moderation commands. If a globally banned user attempts to use a command, the bot ignores the request and optionally sends a notification explaining why the action was denied. This dual-layer approach ensures that even if a user bypasses the initial join check, they cannot participate actively in the community.
Database Schema Design
A robust global ban system needs a schema that supports efficient querying. The simplest implementation uses a single table with two columns:user_id and banned_at. The user_id serves as the primary key, ensuring uniqueness and fast retrieval using hash-based indexes. Storing the timestamp is crucial for auditing purposes and for implementing temporary bans. If you need to support expiration times, add a expires_at column. Queries should filter out expired entries during initialization to keep the in-memory cache clean and reduce false positives.
For high-traffic bots, consider using Redis with a simple set data structure. Redis allows for atomic operations and sub-millisecond lookups, which is vital when handling thousands of concurrent joins. The key can be global_bans, and each member ID is added as a member of the set. This eliminates the need for complex SQL queries during runtime. However, if persistence is required beyond restarts, ensure the Redis instance is configured with AOF (Append Only File) or RDB snapshots enabled. Always handle connection failures gracefully; if the database is unreachable, the bot should either refuse to start or operate in a degraded mode that prioritizes safety over functionality.
Implementation Details in Py-cord
To integrate this logic into a py-cord bot, start by defining a custom cog that handles the lifecycle events. Use the@commands.Cog.listener() decorator to attach functions to on_ready, on_member_join, and on_message. In on_ready, establish the database connection and populate the internal set or dictionary with existing bans. This ensures that the bot remembers bans across restarts without needing to query the database for every single event.
When implementing the on_member_join listener, retrieve the guild object and check if the member's ID is in the global ban list. If it is, call guild.ban(member, reason="Globally Banned"). This action removes the user from the guild and prevents them from rejoining until the ban is lifted. It is important to log these actions to a separate audit channel so administrators can review automated enforcement. For the on_message listener, check the author's ID against the ban list before processing any other logic. If the user is banned, delete the message and return early. This prevents spam and reduces unnecessary processing load on the bot.
Admin commands should include !gban @user to add a user to the global list and !ungban @user to remove them. These commands must verify that the executing user has appropriate permissions, typically Kick Members or a custom role. After modifying the database, update the in-memory cache immediately to reflect changes without requiring a bot restart. Always wrap database operations in try-except blocks to handle potential network errors or constraint violations.
Handling Edge Cases
One common issue is race conditions where a user joins multiple servers simultaneously. Ensure that your global ban check is idempotent; banning a user who is already banned should not cause errors. Additionally, consider the impact of mass bans. If a large number of users are banned at once, avoid iterating through all guilds to apply the ban individually, as this will hit rate limits. Instead, rely on theon_member_join trigger to handle bans dynamically as users attempt to enter. This scales better and respects Discord's API constraints.