#13637: fix(discord): add proxy support for media attachment downloads
docs
channel: discord
channel: telegram
stale
Cluster:
Media Handling Improvements
## Summary
Fixes #2503
Discord's `resolveMediaList` calls `fetchRemoteMedia` without a `fetchImpl`, causing it to fall back to `globalThis.fetch`. On Node.js 22+ the native fetch is backed by undici and bypasses `http.request`, so `global-agent` cannot intercept it — making media downloads from `cdn.discordapp.com` fail in proxy-required environments (e.g. China mainland).
This PR adds a `channels.discord.proxy` config field (mirroring Telegram's existing pattern) and threads a proxy-aware fetch through the message handler pipeline into `resolveMediaList` → `fetchRemoteMedia`.
## Problem
```
config.proxy → ??? → resolveMediaList() → fetchRemoteMedia({ url })
↓
fetchImpl is undefined
↓
falls back to globalThis.fetch
↓
Node 22 undici fetch (no global-agent)
↓
cdn.discordapp.com unreachable ❌
```
Telegram already handles this correctly via `makeProxyFetch` → `fetchRemoteMedia({ fetchImpl })`.
## Changes
- **Config**: add `proxy?: string` to `DiscordAccountConfig` type + zod schema
- **Infra**: move `makeProxyFetch` from `src/telegram/proxy.ts` to `src/infra/net/proxy.ts` as shared infrastructure (Telegram re-exports for backward compat)
- **Provider**: create proxy-aware fetch when `channels.discord.proxy` is set
- **Pipeline**: thread `proxyFetch` through `createDiscordMessageHandler` → `preflightDiscordMessage` → `processDiscordMessage` → `resolveMediaList` → `fetchRemoteMedia`
- **Docs**: update English + Chinese Discord docs with proxy config field
- **Changelog**: add entry under Fixes
## Data flow (after fix)
```
channels.discord.proxy: "http://host:port"
↓
makeProxyFetch(proxyUrl) → undici ProxyAgent
↓
createDiscordMessageHandler({ proxyFetch })
↓
preflightDiscordMessage(params) → ctx.proxyFetch
↓
processDiscordMessage(ctx)
↓
resolveMediaList(message, maxBytes, proxyFetch)
↓
fetchRemoteMedia({ url, fetchImpl: proxyFetch }) ✅
```
## Test plan
- [x] `tsc --noEmit` passes (zero errors)
- [x] `oxlint` passes (zero warnings/errors)
- [x] All 187 existing Discord tests pass (zero regressions)
- [x] Telegram `proxy.test.ts` passes (re-export backward compat)
- [x] Added 2 unit tests: `resolveMediaList` correctly passes/omits `fetchImpl`
- [x] Added 2 integration tests: `processDiscordMessage` threads `proxyFetch` from context into `fetchRemoteMedia` for attachment downloads
## Config example
```json5
{
channels: {
discord: {
token: "YOUR_BOT_TOKEN",
proxy: "http://your-proxy:port",
},
},
}
```
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Most Similar PRs
#20186: fix(discord): thread mediaLocalRoots through reply delivery path
by pvoo · 2026-02-18
73.3%
#16897: fix(tools): route web_search requests through HTTP proxy env vars
by battman21 · 2026-02-15
72.4%
#20488: fix(discord): pass mediaLocalRoots to sendMessageDiscord
by olyashok · 2026-02-19
72.2%
#19660: fix: respect HTTP_PROXY/HTTPS_PROXY env vars for undici fetch
by 88plug · 2026-02-18
70.0%
#16144: fix: respect HTTP_PROXY/HTTPS_PROXY in SSRF-protected fetch (#2102)
by battman21 · 2026-02-14
69.7%
#20913: fix: intercept Discord embed images to enforce mediaMaxMb
by MumuTW · 2026-02-19
69.4%
#19942: feat(telegram): configurable SSRF policy for media fetch
by onewesong · 2026-02-18
68.1%
#19615: fix(discord): include default account when sub-accounts are configured
by prue-starfield · 2026-02-18
68.1%
#23627: fix(telegram,feishu): pass mediaLocalRoots through channel action a...
by rockkoca · 2026-02-22
67.0%
#20578: feat(browser): add proxy configuration option
by illusivejosiah · 2026-02-19
67.0%