torrent/CLAUDE.md

6.4 KiB

CLAUDE.md — Torrent Faker

Project Purpose

Torrent Faker is a fake BitTorrent seeder that announces upload stats to real trackers without transferring any actual data. It simulates realistic seeding behavior to satisfy tracker requirements.

Tech Stack

Layer Technology
Runtime Bun
Language TypeScript (strict, ESNext)
HTTP Hono 4.x
Config YAML (js-yaml) + Zod validation
Linting Biome
Frontend Svelte 5 + Vite (in ui/)

Project Structure

src/
  index.ts                  # Entry point: loads config, starts registry + HTTP server
  cli/index.ts              # CLI client (talks to running API)
  config/Config.ts          # Zod schema + config loader
  config/config.default.yml # Default config values
  api/
    server.ts               # Hono app, mounts routes, serves UI
    SeederRegistry.ts       # Central in-memory store for all FakeSeeder instances
    response.ts             # HTTP response helpers
    routes/
      torrents.ts           # GET/POST/DELETE /api/torrents
      status.ts             # GET /api/status, GET /api/status/stream (SSE)
      config.ts             # GET/PATCH /api/config
  core/
    bencode/                # Bencode decoder + encoder
    client/
      ClientProfile.ts      # Profile interface + peer ID generation
      profiles/             # qbittorrent.ts, transmission.ts
    seeder/
      FakeSeeder.ts         # Announce loop, lifecycle (started → running → stopped)
      SpeedSimulator.ts     # Gaussian noise + burst/stall events
    torrent/TorrentFile.ts  # Parses .torrent, extracts info hash + tracker list
    tracker/
      ITracker.ts           # Tracker interface
      HttpTracker.ts        # HTTP/HTTPS tracker (BEP 3)
      UdpTracker.ts         # UDP tracker (BEP 15)
      TrackerResponse.ts    # Response types
config/config.yml           # Runtime config (gitignored defaults)
torrents/                   # Drop .torrent files here
ui/                         # Svelte frontend (built to ui/dist/)

TypeScript Path Aliases

@core/*   → src/core/*
@api/*    → src/api/*
@config/* → src/config/*

Dev Commands

bun run dev          # Start server (hot-reload)
bun run start        # Start server (production)
bun run cli <cmd>    # Run CLI against running server
bun test             # Run tests
bun run lint         # Biome check
bun run format       # Biome format --write
bun run build:ui     # Build Svelte UI to ui/dist/
bun run build        # Full build (UI only for now)

Architecture

SeederRegistry
  └── FakeSeeder (one per torrent)
        ├── SpeedSimulator  — random base rate, ±15% jitter, burst/stall
        └── Tracker[]
              ├── HttpTracker (BEP 3)
              └── UdpTracker  (BEP 15)
  • SeederRegistry is the single source of truth; routes call it, not FakeSeeder directly.
  • FakeSeeder extends EventEmitter; emits announce, stopped, stateChange.
  • SeederRegistry subscribes to seeder events and pushes SSE updates to connected clients.
  • Announce lifecycle: first call sends event=started, subsequent calls send event= (empty), final call on removal sends event=stopped.

Configuration

Runtime config file: config/config.yml (copied from src/config/config.default.yml).

Field Default Description
port 3000 HTTP server port (UI + API)
announcePort 6881 Port reported to trackers
minUploadRateBytesPerSec 524288 Min simulated speed (512 KB/s)
maxUploadRateBytesPerSec 2097152 Max simulated speed (2 MB/s)
clientProfile qbittorrent Client to impersonate
torrentsDir ./torrents Directory for .torrent files
autoLoad true Load all torrents in dir on startup

Config is Zod-validated at startup. PATCH /api/config persists changes back to config.yml.

API Endpoints

Method Path Description
GET /api/torrents List all active torrents
POST /api/torrents Upload .torrent file (multipart)
GET /api/torrents/:hash Stats + announce history for one
DELETE /api/torrents/:hash Stop seeding and remove
GET /api/status Global stats snapshot
GET /api/status/stream SSE stream (stats, torrent, ping)
GET /api/config Current config
PATCH /api/config Update mutable config fields
GET /* Serve Svelte SPA from ui/dist/

SSE Event Types

  • stats — global stats on every change
  • torrent — per-torrent state update on announce/change
  • torrents — full list on initial connection
  • ping — keep-alive every 30s

CLI

Requires a running server. Reads TORRENT_FAKER_API env var (default: http://localhost:3000).

bun run cli add <file.torrent>   # Start fake-seeding
bun run cli list                 # List active torrents
bun run cli remove <hash>        # Stop and remove (hash prefix OK)
bun run cli status               # Global stats

Client Profiles

Profile Peer ID prefix User-Agent
qbittorrent -qB4520- qBittorrent/4.5.2
transmission -TR3000- Transmission/3.00

Each seeder generates a unique 20-byte peer ID per session.

Code Conventions

  • Biome enforces formatting; run bun run format before committing.
  • Zod schemas for all external input (config file, API request bodies).
  • No ORM — binary protocols implemented manually (bencode, UDP packets).
  • EventEmitter pattern for seeder → registry communication.
  • SSE for live UI updates (no WebSockets, no polling).