diff --git a/gateway/platforms/discord.py b/gateway/platforms/discord.py index 257756ad..e68e5292 100644 --- a/gateway/platforms/discord.py +++ b/gateway/platforms/discord.py @@ -43,6 +43,23 @@ from gateway.platforms.base import ( ) +def _clean_discord_id(entry: str) -> str: + """Strip common prefixes from a Discord user ID or username entry. + + Users sometimes paste IDs with prefixes like ``user:123``, ``<@123>``, + or ``<@!123>`` from Discord's UI or other tools. This normalises the + entry to just the bare ID or username. + """ + entry = entry.strip() + # Strip Discord mention syntax: <@123> or <@!123> + if entry.startswith("<@") and entry.endswith(">"): + entry = entry.lstrip("<@!").rstrip(">") + # Strip "user:" prefix (seen in some Discord tools / onboarding pastes) + if entry.lower().startswith("user:"): + entry = entry[5:] + return entry.strip() + + def check_discord_requirements() -> bool: """Check if Discord dependencies are available.""" return DISCORD_AVAILABLE @@ -99,7 +116,8 @@ class DiscordAdapter(BasePlatformAdapter): allowed_env = os.getenv("DISCORD_ALLOWED_USERS", "") if allowed_env: self._allowed_user_ids = { - uid.strip() for uid in allowed_env.split(",") if uid.strip() + _clean_discord_id(uid) for uid in allowed_env.split(",") + if uid.strip() } adapter_self = self # capture for closure diff --git a/hermes_cli/gateway.py b/hermes_cli/gateway.py index 26a8f598..5ba2f64b 100644 --- a/hermes_cli/gateway.py +++ b/hermes_cli/gateway.py @@ -623,6 +623,18 @@ def _setup_standard_platform(platform: dict): value = prompt(f" {var['prompt']}", password=False) if value: cleaned = value.replace(" ", "") + # For Discord, strip common prefixes (user:123, <@123>, <@!123>) + if "DISCORD" in var["name"]: + parts = [] + for uid in cleaned.split(","): + uid = uid.strip() + if uid.startswith("<@") and uid.endswith(">"): + uid = uid.lstrip("<@!").rstrip(">") + if uid.lower().startswith("user:"): + uid = uid[5:] + if uid: + parts.append(uid) + cleaned = ",".join(parts) save_env_value(var["name"], cleaned) print_success(f" Saved — only these users can interact with the bot.") allowed_val_set = cleaned diff --git a/hermes_cli/setup.py b/hermes_cli/setup.py index baff9e6e..b2e53c87 100644 --- a/hermes_cli/setup.py +++ b/hermes_cli/setup.py @@ -1935,7 +1935,17 @@ def setup_gateway(config: dict): "Allowed user IDs or usernames (comma-separated, leave empty for open access)" ) if allowed_users: - save_env_value("DISCORD_ALLOWED_USERS", allowed_users.replace(" ", "")) + # Clean up common prefixes (user:123, <@123>, <@!123>) + cleaned_ids = [] + for uid in allowed_users.replace(" ", "").split(","): + uid = uid.strip() + if uid.startswith("<@") and uid.endswith(">"): + uid = uid.lstrip("<@!").rstrip(">") + if uid.lower().startswith("user:"): + uid = uid[5:] + if uid: + cleaned_ids.append(uid) + save_env_value("DISCORD_ALLOWED_USERS", ",".join(cleaned_ids)) print_success("Discord allowlist configured") else: print_info( @@ -1970,8 +1980,18 @@ def setup_gateway(config: dict): ) allowed_users = prompt("Allowed user IDs (comma-separated)") if allowed_users: + # Clean up common prefixes (user:123, <@123>, <@!123>) + cleaned_ids = [] + for uid in allowed_users.replace(" ", "").split(","): + uid = uid.strip() + if uid.startswith("<@") and uid.endswith(">"): + uid = uid.lstrip("<@!").rstrip(">") + if uid.lower().startswith("user:"): + uid = uid[5:] + if uid: + cleaned_ids.append(uid) save_env_value( - "DISCORD_ALLOWED_USERS", allowed_users.replace(" ", "") + "DISCORD_ALLOWED_USERS", ",".join(cleaned_ids) ) print_success("Discord allowlist configured")