Files
doka2-lobby-list/public/admin.html
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

263 lines
9.7 KiB
HTML

<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Steam Auth Admin</title>
<link rel="stylesheet" href="/styles.css">
</head>
<body>
<header class="topbar">
<div class="title">
<h1>Steam auth admin</h1>
<div class="subline">
<span id="adminStatus" class="badge badge-muted">locked</span>
<a class="admin-link" href="/">Lobby list</a>
</div>
</div>
<div class="metrics" aria-label="Auth status">
<div class="metric wide">
<span class="metric-label">credentials</span>
<strong id="credentialsSource">-</strong>
</div>
<div class="metric wide">
<span class="metric-label">refresh token</span>
<strong id="tokenStatus">-</strong>
</div>
<div class="metric wide">
<span class="metric-label">steam</span>
<strong id="steamStatus">-</strong>
</div>
<div class="metric wide">
<span class="metric-label">game coordinator</span>
<strong id="gcStatus">-</strong>
</div>
</div>
</header>
<main class="admin-main">
<section id="loginPanel" class="auth-panel">
<h2>Admin password</h2>
<div class="admin-grid">
<label>
<span>password</span>
<input id="adminPassword" type="password" autocomplete="current-password">
</label>
<div class="actions">
<button id="unlockBtn" class="primary" type="button">Unlock</button>
</div>
</div>
</section>
<p id="adminError" class="error" hidden></p>
<p id="adminMessage" class="notice" hidden></p>
<section id="notificationPanel" class="auth-panel" hidden>
<h2>Browser notifications</h2>
<p class="panel-copy">Push notifications work in the background. Production deployments must use HTTPS.</p>
<div class="actions left">
<button id="enableNotificationsBtn" class="primary" type="button">Enable on this browser</button>
<button id="disableNotificationsBtn" type="button">Disable on this browser</button>
<button id="testNotificationBtn" type="button">Send test</button>
<span id="notificationStatus" class="inline-status">checking</span>
</div>
</section>
<section id="telegramPanel" class="auth-panel" hidden>
<h2>Telegram notifications</h2>
<p class="panel-copy">Create a bot with @BotFather. Each recipient must open the bot and send it a message before the bot can write to that numeric Telegram user ID. The token is stored only on the server and is never returned to this page.</p>
<div class="admin-grid">
<label>
<span>bot token</span>
<input id="telegramToken" type="password" autocomplete="off" placeholder="paste token or leave blank to keep saved token">
</label>
<label>
<span>Telegram user IDs, comma-separated</span>
<input id="telegramRecipientIds" type="text" inputmode="numeric" placeholder="123456789, 987654321">
</label>
</div>
<div class="actions left panel-actions">
<button id="saveTelegramBtn" class="primary" type="button">Save Telegram</button>
<button id="testTelegramBtn" type="button">Send test</button>
<button id="disableTelegramBtn" class="danger" type="button">Disable Telegram</button>
<span id="telegramStatus" class="inline-status">not configured</span>
</div>
</section>
<section id="lobbyPanel" class="auth-panel" hidden>
<h2>Lobby automation</h2>
<p class="panel-copy">Player thresholds count real users only; the Steam bot itself is excluded. To avoid protocol-specific IDs, click <strong>Create template</strong> on a lobby in the lobby list and this form will be prefilled after admin authorization.</p>
<div class="lobby-grid">
<label>
<span>lobby name</span>
<input id="lobbyName" type="text" maxlength="100" placeholder="Long queue lobby">
</label>
<label>
<span>region</span>
<select id="lobbyRegion"></select>
</label>
<label>
<span>workshop ID</span>
<input id="customGameId" type="text" inputmode="numeric" placeholder="1234567890">
</label>
<label>
<span>internal addon name</span>
<input id="customGameMode" type="text" placeholder="copied by Create template">
</label>
<label>
<span>map name</span>
<input id="customMapName" type="text" placeholder="map_name">
</label>
<label>
<span>lobby password</span>
<input id="lobbyPassKey" type="text" autocomplete="off">
</label>
<label>
<span>custom min players</span>
<input id="customMinPlayers" type="number" min="1" max="64">
</label>
<label>
<span>custom max players</span>
<input id="customMaxPlayers" type="number" min="2" max="64">
</label>
<label>
<span>notify at real players</span>
<input id="notifyAtPlayers" type="number" min="1" max="64">
</label>
<label>
<span>bot leaves at real players</span>
<input id="leaveAtPlayers" type="number" min="1" max="64">
</label>
<label class="span-2">
<span>admin persona names or SteamID64, comma-separated</span>
<input id="adminNames" type="text" placeholder="Alice, Bob, 7656119...">
</label>
<label>
<span>custom game CRC (optional)</span>
<input id="customGameCrc" type="text" inputmode="numeric">
</label>
<label>
<span>workshop timestamp (optional)</span>
<input id="customGameTimestamp" type="text" inputmode="numeric">
</label>
<label class="check">
<input id="allowSpectating" type="checkbox" checked>
<span>allow spectating</span>
</label>
</div>
<div class="actions left panel-actions">
<button id="saveLobbySettingsBtn" type="button">Save settings</button>
<button id="createLobbyBtn" class="primary" type="button">Create lobby</button>
<button id="stopLobbyBtn" class="danger" type="button">Leave lobby</button>
</div>
<dl class="details lobby-details">
<div>
<dt>automation</dt>
<dd id="automationPhase">-</dd>
</div>
<div>
<dt>lobby ID</dt>
<dd id="activeLobbyId">-</dd>
</div>
<div>
<dt>real players</dt>
<dd id="activePlayerCount">0</dd>
</div>
<div>
<dt>lobby browser / password</dt>
<dd id="publicationStatus">-</dd>
</div>
<div>
<dt>arcade Play queue</dt>
<dd id="arcadePublicationStatus">-</dd>
</div>
<div>
<dt>GC lobby flags</dt>
<dd id="lobbyProtocolStatus">-</dd>
</div>
<div>
<dt>Dota client version</dt>
<dd id="dotaClientVersion">-</dd>
</div>
<div>
<dt>leave reason</dt>
<dd id="leaveReason">-</dd>
</div>
</dl>
<div id="lobbyMembers" class="member-list muted">No active lobby members.</div>
</section>
<section id="credentialsPanel" class="auth-panel" hidden>
<h2>Steam credentials</h2>
<p class="panel-copy">Passwords, per-account refresh tokens, and Steam Guard machine authorization are stored on the server. Switching accounts reconnects Steam and Dota without restarting this process; leave an active lobby first.</p>
<div class="admin-grid">
<label>
<span>saved accounts</span>
<select id="savedSteamAccount"></select>
</label>
<div class="actions">
<button id="activateAccountBtn" type="button">Activate selected</button>
</div>
<label>
<span>account</span>
<input id="steamAccount" type="text" autocomplete="username">
</label>
<label>
<span>password</span>
<input id="steamPassword" type="password" autocomplete="current-password" placeholder="leave blank to keep the saved password">
</label>
<label class="check">
<input id="clearToken" type="checkbox">
<span>forget cached refresh token for this account</span>
</label>
<div class="actions">
<button id="reloadBtn" type="button">Reload</button>
<button id="saveBtn" class="primary" type="button">Save and activate</button>
</div>
</div>
</section>
<section id="guardPanel" class="auth-panel" hidden>
<h2>Steam Guard</h2>
<div class="admin-grid">
<label>
<span>code</span>
<input id="steamGuardCode" type="text" autocomplete="one-time-code" inputmode="numeric">
</label>
<div class="actions">
<button id="submitGuardBtn" class="primary" type="button">Submit code</button>
</div>
</div>
<p id="guardHint" class="hint"></p>
</section>
<section id="tokenPanel" class="auth-panel" hidden>
<h2>Saved token</h2>
<dl class="details">
<div>
<dt>SteamID</dt>
<dd id="tokenSteamId">-</dd>
</div>
<div>
<dt>Account</dt>
<dd id="tokenAccount">-</dd>
</div>
<div>
<dt>Updated</dt>
<dd id="tokenUpdated">-</dd>
</div>
<div>
<dt>Expires</dt>
<dd id="tokenExpires">-</dd>
</div>
</dl>
<div class="actions left">
<button id="clearTokenBtn" type="button">Clear refresh token</button>
</div>
</section>
</main>
<script src="/admin.js"></script>
</body>
</html>