Bug Description
The Discord gateway adapter (gateway/platforms/discord.py) has no proxy support. In network environments where Discord is restricted (e.g., mainland China), the gateway cannot connect to Discord or send messages, even when a local SOCKS proxy (Shadowrocket, Clash, etc.) is running and working.
The bot fails to connect at startup, and if connection somehow succeeds, sending messages also fails with the same error.
Steps to Reproduce
- Set up Hermes Gateway with Discord enabled and a valid bot token
- Run on a network where
discord.com is restricted at the TCP level (e.g., mainland China, GFW blocks TLS handshake to Discord)
- Start a local SOCKS5 proxy (e.g., Shadowrocket on
127.0.0.1:1082) that can reach Discord
- Set proxy env vars or rely on auto-detection:
ALL_PROXY=socks5://127.0.0.1:1082
- Run
hermes gateway run
- Discord fails to connect with timeout
Expected Behavior
Discord adapter should detect and use the available SOCKS proxy to connect to Discord, similar to how the Telegram adapter already supports proxy configuration via _resolve_proxy_url() in gateway/platforms/telegram_network.py.
Actual Behavior
[Discord] Timeout waiting for connection to Discord
Or if connection partially succeeds, sending messages fails:
[Discord] Failed to send Discord message: General SOCKS server failure
Affected Component
Gateway (Telegram/Discord/Slack/WhatsApp)
Messaging Platform (if gateway-related)
Discord
Operating System
macOS 15.2
Python Version
3.11.12
Hermes Version
0.8.0
Relevant Logs / Traceback
Root Cause Analysis (optional)
1. No proxy configuration passed to discord.py
The DiscordAdapter.connect() method creates the bot without any proxy configuration:
self._client = commands.Bot(
command_prefix="!",
intents=intents,
)
discord.py uses aiohttp internally, which does not read standard proxy environment variables (HTTP_PROXY, HTTPS_PROXY, ALL_PROXY). The commands.Bot() constructor accepts a connector kwarg (passed through to discord.Client.__init__), but it is never set by the adapter.
For comparison, the Telegram adapter (gateway/platforms/telegram_network.py) already has _resolve_proxy_url() and properly configures proxy support.
2. Critical: aiohttp_socks.ProxyConnector requires rdns=True
When injecting a SOCKS connector, the rdns parameter must be explicitly set to True. With the default rdns=None, Shadowrocket (and likely Clash and similar proxies) rejects the connection with SOCKS5 error code 1: "General SOCKS server failure".
# FAILS -- rdns defaults to None
ProxyConnector.from_url('socks5://127.0.0.1:1082')
# -> ProxyError: General SOCKS server failure
# WORKS -- rdns explicitly set to True
ProxyConnector(host='127.0.0.1', port=1082, proxy_type=ProxyType.SOCKS5, rdns=True)
# -> Connection successful
rdns=True forces DNS resolution through the proxy (remote DNS), which is required by many SOCKS proxy implementations and essential for bypassing DNS pollution.
Proposed Fix (optional)
Add proxy auto-detection and connector injection in gateway/platforms/discord.py before commands.Bot() creation:
# Resolve proxy for Discord connection
_discord_proxy = (
os.getenv("DISCORD_PROXY", "") or
os.getenv("ALL_PROXY", "") or
os.getenv("all_proxy", "") or
os.getenv("HTTPS_PROXY", "") or
os.getenv("https_proxy", "")
)
if not _discord_proxy:
# Auto-detect common local SOCKS proxy (Shadowrocket, Clash, etc.)
import socket
for _pp in [1080, 1082, 7890, 7891]:
_s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
_s.settimeout(0.3)
_s.connect(("127.0.0.1", _pp))
_discord_proxy = f"socks5://127.0.0.1:{_pp}"
break
except (OSError, ConnectionRefusedError):
pass
finally:
_s.close()
_bot_kwargs = {}
if _discord_proxy and _discord_proxy.startswith("socks"):
try:
from aiohttp_socks import ProxyConnector
from python_socks import ProxyType, parse_proxy_url
_ptype, _phost, _pport, _puser, _ppass = parse_proxy_url(_discord_proxy)
# rdns=True is critical: resolves DNS through the proxy,
# required for Shadowrocket and many SOCKS implementations
_connector = ProxyConnector(
host=_phost, port=_pport, proxy_type=_ptype,
username=_puser, password=_ppass, rdns=True,
)
_bot_kwargs["connector"] = _connector
logger.info("[%s] Using SOCKS proxy for Discord: %s (rdns=True)", self.name, _discord_proxy)
except ImportError:
logger.warning("[%s] aiohttp_socks not installed, proxy won't work. Run: pip install aiohttp-socks", self.name)
# Create bot
self._client = commands.Bot(
command_prefix="!",
intents=intents,
**_bot_kwargs,
)
After applying the fix:
[Discord] Using SOCKS proxy for Discord: socks5://127.0.0.1:1082 (rdns=True)
[Discord] Connected as hermes_bot#1415
[Discord] Synced 100 slash command(s)
✓ discord connected
Are you willing to submit a PR for this?
Bug Description
The Discord gateway adapter (
gateway/platforms/discord.py) has no proxy support. In network environments where Discord is restricted (e.g., mainland China), the gateway cannot connect to Discord or send messages, even when a local SOCKS proxy (Shadowrocket, Clash, etc.) is running and working.The bot fails to connect at startup, and if connection somehow succeeds, sending messages also fails with the same error.
Steps to Reproduce
discord.comis restricted at the TCP level (e.g., mainland China, GFW blocks TLS handshake to Discord)127.0.0.1:1082) that can reach DiscordALL_PROXY=socks5://127.0.0.1:1082hermes gateway runExpected Behavior
Discord adapter should detect and use the available SOCKS proxy to connect to Discord, similar to how the Telegram adapter already supports proxy configuration via
_resolve_proxy_url()ingateway/platforms/telegram_network.py.Actual Behavior
Or if connection partially succeeds, sending messages fails:
Affected Component
Gateway (Telegram/Discord/Slack/WhatsApp)
Messaging Platform (if gateway-related)
Discord
Operating System
macOS 15.2
Python Version
3.11.12
Hermes Version
0.8.0
Relevant Logs / Traceback
Root Cause Analysis (optional)
1. No proxy configuration passed to
discord.pyThe
DiscordAdapter.connect()method creates the bot without any proxy configuration:discord.pyusesaiohttpinternally, which does not read standard proxy environment variables (HTTP_PROXY,HTTPS_PROXY,ALL_PROXY). Thecommands.Bot()constructor accepts aconnectorkwarg (passed through todiscord.Client.__init__), but it is never set by the adapter.For comparison, the Telegram adapter (
gateway/platforms/telegram_network.py) already has_resolve_proxy_url()and properly configures proxy support.2. Critical:
aiohttp_socks.ProxyConnectorrequiresrdns=TrueWhen injecting a SOCKS connector, the
rdnsparameter must be explicitly set toTrue. With the defaultrdns=None, Shadowrocket (and likely Clash and similar proxies) rejects the connection with SOCKS5 error code 1: "General SOCKS server failure".rdns=Trueforces DNS resolution through the proxy (remote DNS), which is required by many SOCKS proxy implementations and essential for bypassing DNS pollution.Proposed Fix (optional)
Add proxy auto-detection and
connectorinjection ingateway/platforms/discord.pybeforecommands.Bot()creation:After applying the fix:
Are you willing to submit a PR for this?