Thyra: A Key-Based Discord Role Manager for Communities

Side Project
Software Engineer
Discord Bot, Python, Pycord, MongoDB

(opens in new window)Behind The Project

Managing access in Discord servers is tiring. If you’re managing a course, guild, or community with some private channels, you need a way to verify members before granting roles.

Most Discord bots (e.g., Carl-bot) offer Reaction Role functionality, allowing users to click emoji reactions to obtain roles. However, this approach lets users self-select their roles without restrictions. Users can click all reactions to gain every role, or click none to remain without any roles.

Thyra Discord Bot Reaction Role

I wanted something simpler: type a key, get a role. Thyra is an open source Discord bot that automatically assigns and removes roles based on unique authentication keys. Members input keys directly in Discord, and the bot instantly grants access to restricted channels—all inside Discord, with no external websites, browser redirects, or credential exposure.

Admins manage everything through Discord slash commands, no external dashboard needed. Creating a key, checking usage statistics, and revoking access all happen within Discord.

Thyra Discord Bot Set Key

Thyra Discord Bot Enter Key

(opens in new window)Technical Challenges

(opens in new window)Discord’s 3-Second Response Limit

Discord enforces a hard 3-second timeout on command responses. If the bot takes longer, users see an error, even if the action eventually succeeds. Database queries to remote instances can take 500ms to 1 second, and when you add Discord API roundtrips, the bot is cutting it close.

I addressed this with a co-location strategy: deploying the bot and database in the same cloud region reduces latency to under 100ms for most operations. For operations that might take longer, like bulk key creation, I use Discord’s defer pattern, immediately acknowledging the command, then following up with results once processing completes. This ensures users always get responsive feedback within the timeout window.

Thyra Discord Bot Tutorial

(opens in new window)Type of Keys

I designed three key types to handle different community needs. Regular keys offer unlimited usage, perfect for public access codes or course registration. Limited keys cap usage at a specific number, ideal for beta testing or exclusive invites. Protected keys require a one-time PIN, creating a verifiable link between external identities and Discord accounts. This last type proved especially valuable in educational settings where instructors need to confirm that a Discord user is actually enrolled in their course.

For communities that need to link external accounts to Discord identities, protected keys provide a privacy-respecting method that avoids OAuth flows entirely.

Key TypeFeatures
Regular KeyUnlimited usage. Users input key name to get roles.
Limited KeyCaps usage at a specific number. Counter tracks actual uses only.
Protected KeyRequires both key name and one-time PIN. Enables user source tracking.

(opens in new window)Role Hierarchy Validation

Discord’s permission system means a bot can only assign roles lower in the hierarchy than its own. If an admin creates a key for a role above the bot’s position, the command would silently fail, or worse, error at runtime when a member tries to verify days later.

I added upfront validation that checks role hierarchy before accepting key creation commands, giving admins immediate, actionable feedback instead of letting them discover issues later. This prevents a whole category of confusing errors that would otherwise surface at the worst possible time, during a student’s first interaction with the server.

(opens in new window)Fuzzy Matching for Key Management

When admins manage a lot of keys, they often forget exact names. Instead of forcing them to search through logs, I added autocomplete with fuzzy string matching using Levenshtein distance scoring. When an admin types a partial or misspelled key name, the bot suggests the top five closest matches.

This turned out to be the feature that made Thyra usable at scale. Server admins consistently reported that without fuzzy matching, managing large key sets would be impractical. A small UX investment yielded the biggest quality-of-life improvement.

async def key_name_autocomplete(ctx: discord.AutocompleteContext):
    good_matches = []
    if general.is_admin(ctx=ctx.interaction):
        keys_list = KeyUtils.get_all_keys_name_list(guild=ctx.interaction.guild)
        if ctx.value:
            matches = process.extract(ctx.value, keys_list, limit=25)
            for item in matches:
                # filter the terms which similarity over 40
                if int(item[1]) > 40:
                    good_matches.append(item[0])
        else:
            good_matches = keys_list[:min(len(keys_list), 25)]
    return good_matches

(opens in new window)Impact & Results

The original motivation came from managing justfont community.

justfont maintains strong connections with contemporary type designers and design students in Taiwan through a Discord guild. Members come from various backgrounds: typography course students, event attendees, and online followers. The key system allows us to automatically assign appropriate roles when users first join the server and track whether typography course students successfully joined our community.

This pattern extends to broader educational use cases. Universities and online courses with Discord servers can distribute unique keys to enrolled students, automatically grant access to course channels, and track verification through protected keys with student IDs as PINs. This eliminates manual role assignment for hundreds of students each semester.

Beyond education, Thyra works as an attribution tool for Discord, similar to UTM parameters for URLs. Communities create differently-named keys for different marketing channels and track which keys members used, gaining analytics on which outreach efforts drive Discord joins.

In practice, justfont’s community has adopted Thyra’s key system and design philosophy. By using keys to manage and identify user sources when members join the server, justfont demonstrates how this approach solves real-world community management challenges.

(opens in new window)Lessons Learned

Building Thyra taught me that platform constraints drive better design. Discord’s 3-second timeout forced me to think carefully about asynchronous operations and graceful degradation, skills that transferred directly to my later web development work.

The modular architecture using the Cog system paid off quickly. When I wanted to add limited keys after the initial release, I only needed to modify two modules. Clean separation meant fewer bugs and faster iteration.

The biggest lesson was that UX matters even in bots. Fuzzy matching and autocomplete took extra development time, but the feedback from server admins was clear: these nice-to-have features became essential for practical daily use.

I released Thyra under the MIT License. By open-sourcing this tool, I hope to give smaller communities access to role automation. The projects that people actually use are the ones they can set up and understand.