Skip to content

Add Chrome-based Discord client for user-token hybrid mode#2

Open
fox3000foxy wants to merge 2 commits into
mainfrom
feat/discord-puppet-client
Open

Add Chrome-based Discord client for user-token hybrid mode#2
fox3000foxy wants to merge 2 commits into
mainfrom
feat/discord-puppet-client

Conversation

@fox3000foxy

Copy link
Copy Markdown
Member

TL;DR

Self-bot user tokens get flagged by Discord because Node.js HTTP clients lack real browser fingerprints. This PR adds a DiscordClient backed by Puppeteer+CDP that provides real TLS, cookies, and X-Super-Properties via Chrome's native fetch stack, plus a unified gatewayBus for Gateway events.

Files to review (5 new, 3306 added):

File Why
src/discord-client.ts (start here) Chrome client: auth via localStorage, Gateway CDP hook, __puppetFetch relay, send/edit/ack
src/core/gateway-bus.ts Typed event bus for Gateway frames (MESSAGE_CREATE, MESSAGE_REACTION_ADD)
src/bot.ts Init DiscordClient when DISCORD_USER_TOKEN present, channel navigateTo(), RPC rotation disabled
src/config.ts New DISCORD_USER_TOKEN export
state-machines/25-hybrid-mode.mmd Architecture diagram: Eris receives, Chrome sends/ACKs

How

  1. DiscordClient.init(userToken) launches a real Chrome (headless=false), injects the user token into localStorage, and lands on @me. A CDP session hooks all Gateway WebSocket frames — each MESSAGE_CREATE with mention_token triggers an auto-ACK via Chrome's native fetch.
  2. gatewayBus (TypedBus<GatewayEvents>) unifies Gateway events from both Chrome CDP and Eris. feedGatewayFrame() parses raw WebSocket JSON and emits typed events.
  3. When Eris receives a message, triggerLunaReply() calls discordClient.navigateTo()history.pushState + PopStateEvent — putting the Chrome session in the right channel without a page reload.
  4. __puppetFetch (window.fetch.bind(window)), called via page.evaluate, routes all API calls through Chrome's real TLS/cookie/fingerprint stack.
  5. Nonce format corrected to decimal string (String(Date.now()) + String(random)) matching the official web client.

Reviewer notes

  • No regression for bot-token mode. Only activates when discord_user_token is set. Without it, Eris runs exactly as before.
  • RPC rotation disabled. The dynamic status setInterval was not human-like — commented out. Easy to re-enable.
  • Non-decimal nonce. Prior commit used hex toString(16) — Discord's API expects a pure decimal numeric string.

Tests

Existing tests pass (189/195; 6 failures are pre-existing llama-server 404 — no server in CI).

Links

- New DiscordClient class (Puppeteer + CDP) for real browser fingerprint
- gateway-bus.ts: unified TypedBus for Gateway events
- Hybrid mode: Eris (bot) receives, Chrome (user) sends/ACKs
- Nonce added to DiscordClient.sendMessage (decimal format)
- BOT_RPC disabled (dynamic status rotation commented out)
- README: Hybrid Mode section, diagram 25
- puppeteer dependency
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant