diff --git a/bot/bot.ts b/bot/bot.ts
index f676903..5d510ad 100644
--- a/bot/bot.ts
+++ b/bot/bot.ts
@@ -517,18 +517,24 @@ function fmtTs(): string {
async function renderMain(ctx: Context) {
const [mc, pf] = await Promise.all([serverRunning(), pfRunning()]);
+ const allUp = mc && pf;
+ const allDown = !mc && !pf;
+ const headline = allUp ? "🟢 Online" : allDown ? "🔴 Offline" : "🟡 Partial";
+ const dot = (ok: boolean) => (ok ? "🟢" : "🔴");
const text =
- `🎮 Minecraft Control\n` +
+ `🎮 Minecraft\n` +
+ `${headline}\n` +
`\n` +
- `server : ${mc ? "✅ up" : "⛔ down"}\n` +
- `tunnel : ${pf ? "✅ up" : "⛔ down"}\n` +
+ `${dot(mc)} Server\n` +
+ `${dot(pf)} Tunnel\n` +
`\n` +
- `updated ${fmtTs()}`;
+ `⏱ ${fmtTs()}`;
+ // Single control button: power toggle. Drives both server + tunnel at once
+ // via actUpAll / actDownAll. Granular per-service control is still reachable
+ // via the /server_up, /server_down, /pf_up, /pf_down slash commands.
const kb = new InlineKeyboard()
- .text(mc && pf ? "⏹ Down All" : "▶ Up All", mc && pf ? "act:downall" : "act:upall").row()
- .text(mc ? "🟢 Server ▾" : "🟢 Server ▾", "nav:server").text(pf ? "🟡 Tunnel ▾" : "🟡 Tunnel ▾", "nav:tunnel").row()
- .text("📜 Logs", "nav:logs").text("👥 Users", "nav:users").row()
- .text("🔄 Refresh", "nav:main");
+ .text(allUp ? "🛑 Stop" : "▶️ Start", allUp ? "act:downall" : "act:upall").row()
+ .text("📜 Logs", "nav:logs").text("👥 Users", "nav:users").text("🔄", "nav:main");
return editPanel(ctx, "main", text, kb);
}