Faction management toolkit for Torn.com — real-time member tracking, war coordination, training guides, market analysis, and 25+ tools. Built with FastAPI + Next.js 15.
  • TypeScript 55.7%
  • Python 43.8%
  • JavaScript 0.3%
  • CSS 0.1%
Find a file
Paweł Orzech 96977ecf6d
Some checks are pending
Deploy to Coolify / test (push) Waiting to run
Deploy to Coolify / lighthouse (push) Blocked by required conditions
Deploy to Coolify / deploy (push) Blocked by required conditions
fix(test): stop activity rate-limit test leaking the global rate_limiter
test_track_rate_limit_returns_429 raw-assigned api.auth.rate_limiter to a fresh
HybridRateLimiter and never restored it. Routers that did `from api.auth import
rate_limiter` at import time kept the original object, so after this test ran the
global pointed at a different limiter than the routers used. companion_rum then
flaked with 429s in the full suite: its reset fixture cleared the swapped global
while its router rate-limited against the original (now-polluted) one.

Swap via monkeypatch.setattr so pytest restores the global on teardown, and add
an autouse guard fixture that fails loudly if any test in this module leaves the
global rebound. Full suite now order-independent (1358 passed, 0 failed).
2026-06-04 10:46:26 +02:00
.github chore(actions): bump actions/upload-artifact from 4.4.3 to 7.0.1 (#7) 2026-05-24 00:56:47 +02:00
.jules 🛡️ Sentinel: [HIGH] Fix XSS in Torn News via DOMPurify (#11) 2026-05-24 00:58:40 +02:00
.playwright-mcp fix: bounties (v2 endpoint) + war history (past ranked wars) + design philosophy 2026-03-29 14:48:11 +02:00
api fix: don't cache Torn error envelope as an empty faction 2026-06-04 10:30:13 +02:00
docs docs: Mug Radar implementation plan 2026-05-29 22:09:32 +02:00
extension ci(companion): raise raw bundle-size limit 220->230 KB for Mug Radar overlays 2026-05-30 00:39:53 +02:00
frontend chore: release 1.67.0 Mug Radar 2026-05-30 00:24:12 +02:00
ops/k6 feat(perf): Sprint 1 — observability + quick wins 2026-04-27 10:27:02 +02:00
Plans fix(prod): serialize migration runner under multi-worker boot 2026-04-27 17:02:30 +02:00
screenshots feat: clickable online players list + fix PDA webview scroll wonkiness 2026-04-06 19:54:51 +02:00
scripts feat(spy): empirical stat estimator + endgame bucket for top-tier players 2026-05-17 19:44:18 +02:00
static chore: remove old vanilla JS frontend, add footer with version 2026-03-28 15:55:24 +01:00
tests fix(test): stop activity rate-limit test leaking the global rate_limiter 2026-06-04 10:46:26 +02:00
tm_war_room.egg-info fix: persist active tab across refresh, fix Stats link (Torn personalstats), remove dead TornStats URL 2026-03-27 11:26:33 +01:00
.dockerignore feat(perf): Sprint 1 — observability + quick wins 2026-04-27 10:27:02 +02:00
.env.example feat: add middleware logging test and update .env.example with admin config 2026-03-27 20:07:46 +01:00
.gitignore fix(companion): compact status chip on mobile so settings gear stays tappable 2026-05-17 10:50:09 +00:00
.mcp.json feat: MCP server embedded in FastAPI — 30 tools for faction management 2026-04-11 14:53:33 +02:00
01-login-page.png fix: bounties (v2 endpoint) + war history (past ranked wars) + design philosophy 2026-03-29 14:48:11 +02:00
02-war-room-main.png fix: bounties (v2 endpoint) + war history (past ranked wars) + design philosophy 2026-03-29 14:48:11 +02:00
03-training-guide.png fix: bounties (v2 endpoint) + war history (past ranked wars) + design philosophy 2026-03-29 14:48:11 +02:00
04-inbox.png fix: bounties (v2 endpoint) + war history (past ranked wars) + design philosophy 2026-03-29 14:48:11 +02:00
05-admin.png fix: bounties (v2 endpoint) + war history (past ranked wars) + design philosophy 2026-03-29 14:48:11 +02:00
06-war-room-our-team.png fix: bounties (v2 endpoint) + war history (past ranked wars) + design philosophy 2026-03-29 14:48:11 +02:00
07-war-room-enemy.png fix: bounties (v2 endpoint) + war history (past ranked wars) + design philosophy 2026-03-29 14:48:11 +02:00
admin-panel-test.png fix: bounties (v2 endpoint) + war history (past ranked wars) + design philosophy 2026-03-29 14:48:11 +02:00
AGENTS.md docs: add repo guidance and ignore local handovers 2026-04-11 15:49:27 +02:00
check-awards.png fix: bounties (v2 endpoint) + war history (past ranked wars) + design philosophy 2026-03-29 14:48:11 +02:00
CLAUDE.md fix(spy): /spy/<player_id> via backend route + nginx-t in CI 2026-05-16 01:47:22 +02:00
docker-compose.yml feat: multi-stage Docker build, FastAPI serves Next.js export 2026-03-28 15:54:25 +01:00
Dockerfile build(docker): ship companion.user.js.map alongside .user.js 2026-05-17 01:59:15 +02:00
firebase-debug.log fix: bounties (v2 endpoint) + war history (past ranked wars) + design philosophy 2026-03-29 14:48:11 +02:00
lighthouserc.json chore(ci): verify Lighthouse CI flow + lighthouse baseline doc 2026-05-17 02:55:24 +02:00
newsletter.md docs: professional English README with anonymized screenshots 2026-04-06 00:31:21 +02:00
nginx.conf feat(companion): Sprint 1.5 — anchor cache, gzip tune, Lighthouse CI, RUM wired 2026-05-17 01:37:49 +02:00
pyproject.toml feat(observability): Sprint 2 #13 — Sentry/Glitchtip wired with PII filter 2026-04-27 15:53:51 +02:00
README.md docs: refresh README + CLAUDE.md, add security/admin plans 2026-04-27 13:52:49 +02:00
start.sh feat(perf): Sprint 2 #1+#19 — Redis + multi-worker (chat-safe) 2026-04-27 13:39:05 +02:00
uv.lock feat(observability): Sprint 2 #13 — Sentry/Glitchtip wired with PII filter 2026-04-27 15:53:51 +02:00
war-room-test.png fix: bounties (v2 endpoint) + war history (past ranked wars) + design philosophy 2026-03-29 14:48:11 +02:00

TM Hub Login

TM Hub

Faction management toolkit for Torn.com
Real-time member tracking, war coordination, training guides, market analysis, and more.

Python 3.12 FastAPI Next.js 16 React 19 Tailwind v4 516 tests


Overview

TM Hub is a self-hosted web application built for Torn.com faction management. It pulls data from the Torn API, TornStats, and YATA to provide a unified dashboard for faction leaders and members.

Key principles:

  • Help players decide — don't just display data, explain what it means and what action to take
  • Teach the game — every page includes educational context about game mechanics
  • Show data sources — transparency about where numbers come from
  • Always fresh — background data refresh keeps everything up to date

Live instance: hub.tri.ovh (faction members only)


Screenshots

Dashboard (Dark) Our Team
Dashboard — dark mode Team overview
Training Guide Market Scanner
Training guide with gym formulas Market scanner with profit calculations
NPC Loot Timers Dashboard (Light)
NPC loot timers and reservations Dashboard — light mode

Player names in screenshots have been anonymized.


Features

Faction Management

Feature Description
Dashboard At-a-glance overview: online members, hospital, travelers, attacks, NPC loot, OC status
Our Team Live member status — online/idle/offline, hospital timers, travel, energy, drug cooldowns, revive settings
Enemies Auto-detect enemy from active Ranked War, threat scoring relative to your stats, attack buttons
Activity Member status heatmap with online/idle/offline/hospital/traveling/jail filters
War Reports Ranked war scores, raid history, territory battles
OC Planner Organized crime status, participant roles, checkpoint pass rates

Tools

Feature Description
Chain Tracker Auto-detected chains from attack data, per-member breakdown, bonus hits
Market Scanner 1,400+ items with live prices, NPC buy/sell, profit margins, tax simulation
Spy Central Player search (TornStats + local DB), faction lookup, spy data management
NPC Loot Timers Live loot levels, countdown timers, reservation system for faction coordination
Stock Tracker Portfolio with P/L calculations, benefit/dividend progress, market overview
Bounty Board Active bounties sorted by reward with attack links
Target Lists Save and tag enemy targets with difficulty ratings and notes
Stakeout Watch specific players, track status changes in real-time
Revive Tracker Revive leaderboard (given/received, success rate), recent revives
Travel Planner 11 countries with travel times, items abroad, market prices
Company Tracker Company data and employee stats
Player Compare Side-by-side stat comparison between players
Armoury Competitions Create deposit competitions for categories or specific items, autocomplete item search, live leaderboards

Guides & Education

Feature Description
Training Guide Gym formula reference, happy jumping calculator, energy management, SE vs Xanax cost comparison
Stat Growth Chart.js line charts, 30-day growth tracking, faction leaderboard
Awards Tracker Honors & medals progress with category filters and detail subpages
FAQ Common questions about Torn mechanics with detailed answers
Userscripts Curated list of useful Torn userscripts
Changelog Version history with per-player "new version" notification banner

Platform

  • Light/dark mode with system preference detection
  • Mobile-first responsive design with sidebar + bottom nav bar
  • Admin panel — analytics dashboard, announcement editor, spy data management, role management
  • Push notifications — browser notifications for important events
  • Background refresh — all data stays fresh automatically
  • Faction chat — built-in chat for faction coordination
  • Page explainers — dismissible tutorial panel on every page

Tech Stack

Layer Technology
Backend Python 3.12, FastAPI, SQLite (WAL mode), httpx, APScheduler 4
Frontend Next.js 16 (static export), React 19, TypeScript, Tailwind CSS v4, Chart.js
Auth Torn API key validation → Fernet encryption → X-Player-Id header (HttpOnly cookie session)
Integrations Torn API v1/v2, TornStats API, YATA API
Runtime gunicorn + 2 uvicorn workers behind nginx; Redis for chat pub/sub, scheduler leader-election, shared rate limits
Deploy Docker (multi-stage) → GitHub Actions → Coolify → VPS
Testing 516 pytest tests (async), static export build verification

Architecture

api/
├── main.py                 # FastAPI app, lifespan, middleware
├── config.py               # Environment configuration
├── torn_client.py          # Torn/YATA/TornStats async client with TTL cache
├── threat.py               # Threat scoring engine (relative + absolute)
├── auth.py                 # JWT + rate limiting
├── admin.py                # Admin panel router
├── db/
│   ├── __init__.py         # KeyStore facade
│   ├── migrations/         # 41 versioned SQL migrations
│   └── repos/              # SQLite repositories (BaseRepository pattern)
├── services/               # Business logic (SpyService, etc.)
├── routers/                # Feature routers (22 route modules)
└── scheduler/              # APScheduler 4 background jobs (Redis leader-election)

frontend/src/
├── app/                    # Next.js pages (36 routes)
├── components/             # React components organized by domain
├── data/changelog.ts       # Version history + CURRENT_VERSION (semver)
├── hooks/                  # Data-fetching hooks (useAuth, useWarData, etc.)
├── lib/api-client.ts       # Centralized API wrapper with auth
└── types/                  # TypeScript interfaces

Auth Flow

┌─────────┐    POST /api/keys     ┌─────────┐    Validate     ┌──────────┐
│ Browser  │ ──────────────────► │ Backend  │ ──────────────► │ Torn API │
│          │   (Torn API key)     │          │  (faction check) │          │
│          │ ◄────────────────── │          │ ◄────────────── │          │
│          │    player_id         │          │    member ✓     │          │
└─────────┘                      └─────────┘                  └──────────┘
     │                                │
     │  X-Player-Id header            │  Encrypted key stored
     │  on all API calls              │  in SQLite (Fernet)
     ▼                                ▼

Three roles: superadmin (hardcoded) → admin (DB flag) → member


Development

Prerequisites

  • Python 3.12+ with uv
  • Node.js 20+ with npm

Setup

# Clone and install
git clone https://github.com/pawelorzech/tm-war-room.git
cd tm-war-room

# Backend
uv sync
cp .env.example .env
# Edit .env with your Torn API key

# Frontend
cd frontend && npm install

Running Locally

# Backend (port 8000)
TORN_API_KEY=xxx uvicorn api.main:app --reload --port 8000

# Frontend (port 3000)
cd frontend && npm run dev

Testing

# Run all backend tests
uv run pytest tests/ -v

# Run specific test file
uv run pytest tests/test_threat.py -v

# Run by keyword
uv run pytest tests/test_routes.py -k "enemy"

# Frontend build verification (static export)
cd frontend && npm run build

# Lint
cd frontend && npm run lint

Environment Variables

Variable Required Default Description
TORN_API_KEY Yes Torn API key for server-side requests
ENCRYPTION_KEY Yes* auto-generated Fernet key for encrypting stored API keys
JWT_SECRET Yes* auto-generated JWT signing key for admin auth
TORNSTATS_API_KEY No TornStats API access
FACTION_ID No 11559 Target faction ID
CACHE_TTL No 60 Torn API cache TTL in seconds
SUPERADMIN_IDS No 2362436 Comma-separated allowlist of superadmin player IDs (break-glass)
REDIS_URL Recommended (prod) redis://.... Enables cross-worker chat pub/sub, scheduler leader-election, shared rate limits
WEB_CONCURRENCY No 2 gunicorn worker count. Multi-worker requires REDIS_URL
BACKUP_ENCRYPTION_KEY Recommended (prod) Fernet key for daily encrypted keys.db backups (store outside Coolify)
BACKUP_RETENTION_DAYS No 30 Days of encrypted backups to retain
B2_APPLICATION_KEY_ID / B2_APPLICATION_KEY / B2_BUCKET_NAME / B2_PUBLIC_URL No Backblaze B2 credentials for avatar refresh and encrypted DB backups

* Auto-generated if missing in dev/test (ephemeral — keys reset on restart). Fails fast in production (APP_VERSION != "dev").


Deployment

Push to master triggers the CI/CD pipeline:

git push origin master
    │
    ▼
GitHub Actions ─── pytest + build ──► Coolify webhook ──► Docker build ──► Live

The Docker image uses a multi-stage build: Node.js builds the static frontend, Python serves everything via FastAPI with static file mounting.

URL Target
hub.tri.ovh Main application
rw.tri.ovh Redirect → /team
train.tri.ovh Redirect → /training

License

Private tool built for The Masters [TM] faction. Not intended for general distribution.