v0.0..1
This commit is contained in:
Thomas
2025-10-05 14:58:05 +02:00
parent df30542248
commit a184c31cca
41 changed files with 3439 additions and 0 deletions

View File

@@ -0,0 +1,140 @@
<?php
require_once __DIR__ . '/guard.php';
require_login();
require_once __DIR__ . '/api.php';
require_once __DIR__ . '/db.php';
$env = env_load(dirname(__DIR__) . '/.env');
$login = strtolower($env['TWITCH_CHANNEL'] ?? '');
$uid = $login ? get_user_id($login) : null;
$uptime = 'Offline';
$started_at = null;
// Cachet Helix-kald (20s) for hurtigere side-loads
if ($uid) {
$s = helix_get_cached('/streams', ['user_id' => $uid], 20);
if (($s['http'] ?? 0) === 200 && !empty($s['data']['data'][0])) {
$started_at = $s['data']['data'][0]['started_at'];
$t1 = new DateTime($started_at);
$t2 = new DateTime('now', new DateTimeZone('UTC'));
$diff = $t2->getTimestamp() - $t1->getTimestamp();
$uptime = sprintf('%02d:%02d', floor($diff / 3600), floor(($diff % 3600) / 60));
}
}
$db = db(); // bruger web/db.php (WAL + busy_timeout)
$bits_total = 0;
$cheerers = [];
$subs = [];
// Summér bits og list subs KUN hvis streamen kører
if ($started_at) {
$st = $db->prepare(
'SELECT user_name, SUM(value) AS bits
FROM events
WHERE type = "cheer" AND ts >= ?
GROUP BY user_name
ORDER BY bits DESC'
);
$st->execute([$started_at]);
$cheerers = $st->fetchAll(PDO::FETCH_ASSOC);
foreach ($cheerers as $c) {
$bits_total += (int)($c['bits'] ?? 0);
}
$st = $db->prepare(
'SELECT user_name
FROM events
WHERE (type = "sub" OR type = "subgift") AND ts >= ?
ORDER BY id DESC'
);
$st->execute([$started_at]);
$subs = $st->fetchAll(PDO::FETCH_ASSOC);
}
?>
<!DOCTYPE html>
<html lang="da">
<head>
<meta charset="utf-8">
<title>Dashboard</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<div class="wrap">
<div class="card">
<div class="right"><a class="btn" href="logout.php">Log ud</a></div>
<h1>✨ Twitch PHP Bot Dashboard</h1>
<p>Uptime: <span class="badge"><?php echo htmlspecialchars($uptime); ?></span></p>
<p>
<a class="btn" href="timers.php">⏱️ Timers</a>
<a class="btn" href="poll.php">📊 Poll</a>
<a class="btn" href="giveaway.php">🎁 Giveaway</a>
<a class="btn" href="commands.php">⚙️ Kommandoer</a>
<a class="btn" href="permissions.php">🔐 Rettigheder</a>
<a class="btn" href="points.php" target="_blank">🏆 Loyalty Points</a>
<a class="btn" href="bets.php">💸 Bets</a>
<a class="btn" href="raffle.php">🎟️ Raffle</a>
<a class="btn" href="slots.php">🎰 Slots</a>
<a class="btn" href="eventsub_setup.php">⚡ EventSub</a>
<a class="btn" href="control.php?action=start">Start</a>
<a class="btn" href="control.php?action=stop">Stop</a>
<a class="btn" href="control.php?action=restart">Restart</a>
<a class="btn" href="send.php">Send test</a>
<a class="btn" href="validate.php" target="_blank">Validate token</a>
<a class="btn" href="log.php" target="_blank">Åbn fuld log</a>
<a class="btn" href="settings.php">⚙️ Indstillinger</a>
</p>
</div>
<div class="grid">
<div class="card">
<h3>Total bits (denne stream)</h3>
<p class="badge"><?php echo (int)$bits_total; ?></p>
<h4>Cheerers</h4>
<ul>
<?php foreach ($cheerers as $c): ?>
<li><?php echo htmlspecialchars($c['user_name']); ?> — <?php echo (int)$c['bits']; ?> bits</li>
<?php endforeach; ?>
</ul>
</div>
<div class="card">
<h3>Subs (denne stream)</h3>
<ul>
<?php foreach ($subs as $s): ?>
<li><?php echo htmlspecialchars($s['user_name']); ?></li>
<?php endforeach; ?>
</ul>
</div>
<div class="card">
<h3>Live log</h3>
<pre id="logpre">Indlæser...</pre>
<p class="small">SSE først; fallback til WebSocket (kræver <code>node ws_server.js</code>).</p>
</div>
</div>
<script>
(function(){
const pre = document.getElementById('logpre');
function setLog(t){ pre.textContent = t; }
if (!!window.EventSource) {
try {
const sse = new EventSource('events.php');
let used = false;
sse.addEventListener('log', (e) => {
used = true;
setLog(e.data.replaceAll('\\n', '\n'));
});
setTimeout(() => {
if (!used) { sse.close(); tryWS(); }
}, 2000);
return;
} catch (e) {}
}
tryWS();
funct