Files
doka2-lobby-list/README.md
T
Aleksandr Bogomiakov c239669932
Docker image / build-and-push (push) Successful in 57s
Added lobby auto creation
2026-08-06 20:33:27 +01:00

6.6 KiB

doka-lobby

Web UI for Dota 2 joinable custom lobbies from the game coordinator. The admin page can also create a custom-game lobby, notify browsers and Telegram recipients as it fills, and make the Steam bot leave safely before the lobby launches.

The app keeps the latest lobby snapshot in memory, refreshes it every 3 minutes, and streams updates to the browser. There is no database. Steam account credentials and the refresh token can be persisted on a PVC.

Local run

npm install
$env:AUTH_ADMIN_PASSWORD = "admin-password"
npm start

Open:

http://localhost:3000

Use /admin to enter the admin password, save and switch Steam accounts, submit a Steam Guard code when Steam asks for it, configure lobby creation, and enable notifications.

Steam accounts and Steam Guard

The admin page can store multiple Steam account/password profiles. Save and activate updates the selected profile and reconnects Steam and the Dota GC without restarting Node. Activate selected switches to another saved profile in the same way. Account switching is blocked while the bot owns or monitors a lobby so it cannot disconnect unexpectedly and spoil a game.

Passwords are stored only in the server-side credentials file and are never returned by the admin API. Each account has its own cached refresh token. steam-user machine authorization files are persisted in STEAM_DATA_DIR; together these normally avoid repeated Steam Guard prompts. Steam Guard codes themselves are not cached because they are one-time, short-lived values.

Lobby automation

The Create lobby form requires the Workshop ID, internal addon/game-mode name, map name, region, and custom-game player limits. The internal name, CRC, and Workshop timestamp are copied automatically when you click Create template on an existing lobby in the lobby list; after admin authorization, the creation form is prefilled. This prevents the GC from accepting a half-configured lobby object that is not published in the custom-game list.

Two thresholds are configured for every lobby start:

  • Notify at real players sends a Web Push notification once the lobby reaches that many users.
  • Bot leaves at real players sends CMsgPracticeLobbyLeave immediately at that many users while the lobby is still in its UI/waiting state.

Both values exclude the bot. The leave threshold must be lower than the custom-game maximum because Dota initially places the lobby owner in Radiant slot 1. The bot stays there while waiting, matching the official client and known working GC clients, then leaves at the configured real-player threshold so its slot becomes available before the lobby is full.

Admin identities are exact, case-insensitive Steam persona names separated by commas. A SteamID64 can be entered instead of a name for immediate matching that is not affected by renames or duplicate persona names. When any configured admin identity appears, the bot leaves immediately.

The application never sends an abandon command. If the lobby has already left the UI/waiting state, automatic and manual leave are blocked and a critical browser notification is sent, avoiding an abandon penalty.

Browser push requires HTTPS outside localhost. Click Enable on this browser, allow notifications, then use Send test. Subscriptions and VAPID keys are stored on the same persistent volume as Steam auth.

Telegram notifications

Create a bot with @BotFather, enter its token and numeric Telegram user IDs on /admin, then click Save Telegram and Send test. Every recipient must first open the bot and send it a message; Telegram does not let a bot initiate a private conversation.

For each lobby the bot sends one tracker message to every configured recipient. It edits that message whenever the phase, publication state, player count, player names, or roster changes. Threshold, leave, and safety events are also sent as separate Telegram alerts so they generate a normal notification.

When Dota 2 Workshop content is installed on the same machine, the app reads publish_data.txt to resolve the internal addon name immediately. Set DOTA_WORKSHOP_DIR to the steamapps/workshop/content/570 directory when Steam uses a non-standard library path.

The app also reads ClientVersion from game/dota/steam.inf and sends it in GC hello/lobby-create messages. On a container without Dota files, set DOTA_CLIENT_VERSION to that value from an up-to-date Dota installation, or mount the file and set DOTA_STEAM_INF to its container path. The admin page shows the detected value and source.

Kubernetes configuration

Mount a PVC to /data and set:

env:
  - name: AUTH_ADMIN_PASSWORD
    valueFrom:
      secretKeyRef:
        name: doka-lobby-admin
        key: password
  - name: STEAM_AUTH_FILE
    value: /data/.steam-auth.json
  - name: STEAM_CREDENTIALS_FILE
    value: /data/.steam-credentials.json
  - name: STEAM_DATA_DIR
    value: /data/node-steam-user
  - name: LOBBY_SETTINGS_FILE
    value: /data/.lobby-settings.json
  - name: WEB_PUSH_FILE
    value: /data/.web-push.json
  - name: TELEGRAM_FILE
    value: /data/.telegram.json
  - name: WEB_PUSH_SUBJECT
    value: mailto:admin@example.com
  - name: DOTA_CLIENT_VERSION
    value: "6888" # example only; copy the current value from game/dota/steam.inf
  - name: PORT
    value: "3000"
volumeMounts:
  - name: data
    mountPath: /data

Run one replica only. A single Steam account should not be used by multiple pods at once.

Auth files

  • .steam-credentials.json stores saved Steam account/password profiles and the active account.
  • .steam-auth.json stores a separate Steam refresh token for every saved account.
  • node-steam-user/ stores Steam Guard machine authorization files.
  • .lobby-settings.json stores the last validated lobby form values.
  • .web-push.json stores VAPID keys and browser subscriptions.
  • .telegram.json stores the Telegram bot token, recipient IDs, and tracker message IDs.
  • All credential and notification state is ignored by git and the Docker build context.

If the refresh token is still valid, restarts use it. If it is missing or expired, the app falls back to the saved Steam account/password and may ask for Steam Guard again.

Docker image CI

GitHub Actions builds and pushes:

ultradesu/doka2-lobby-list

Configure repository secrets:

  • DOCKERHUB_USERNAME
  • DOCKERHUB_TOKEN

The workflow publishes latest on the default branch, branch/tag refs, and sha-* tags.

Options

node index.js --port 3001
node index.js --region 3
node index.js --game-id 123456789
node index.js --refresh-ms 180000

One-shot console mode:

node index.js --once --map "ffa"