Files
chat/archive-viewer.php
T
Ty Clifford 33a176f18e v2.0.0
2026-06-08 12:26:08 -04:00

226 lines
7.3 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?php
// archive-viewer.php — Browse archived chat logs
require_once __DIR__ . '/bootstrap.php';
$archiveDir = ROOT_DIR . '/' . getConfigVal('archive.archive_dir', 'archive');
$days = [];
if (is_dir($archiveDir)) {
foreach (glob($archiveDir . '/*/*/*.sqlite') as $f) {
if (preg_match('/(\d{4})\/(\d{2})\/(\d{2})\.sqlite$/', $f, $m)) {
$days[] = "{$m[1]}-{$m[2]}-{$m[3]}";
}
}
rsort($days);
}
$selectedDay = $_GET['day'] ?? null;
$archiveMessages = [];
$archiveMeta = [];
if ($selectedDay && preg_match('/^\d{4}-\d{2}-\d{2}$/', $selectedDay)) {
[$y, $mo, $d] = explode('-', $selectedDay);
$dbPath = ROOT_DIR . '/' . str_replace(
['{year}', '{month}', '{day}'], [$y, $mo, $d],
getConfigVal('database.archive_path')
);
if (file_exists($dbPath)) {
$adb = getArchiveDB($y, $mo, $d);
$archiveMessages = $adb->query("SELECT * FROM messages ORDER BY created_at ASC")->fetchAll(PDO::FETCH_ASSOC);
$metaRows = $adb->query("SELECT key, value FROM archive_meta")->fetchAll(PDO::FETCH_ASSOC);
foreach ($metaRows as $mr) $archiveMeta[$mr['key']] = $mr['value'];
}
}
?><!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>CYBERCHAT // ARCHIVE</title>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link href="https://fonts.googleapis.com/css2?family=Share+Tech+Mono&family=Rajdhani:wght@400;600&family=Orbitron:wght@700&display=swap" rel="stylesheet">
<link rel="stylesheet" href="assets/css/cyberchat.css">
<style>
html, body {
min-height: 100vh;
height: auto;
overflow: auto;
background: var(--bg0);
padding: 20px 16px 40px;
font-family: var(--ui);
}
.arc-wrap { max-width: 920px; margin: 0 auto; }
.arc-topbar {
display: flex;
align-items: center;
gap: 16px;
margin-bottom: 20px;
padding-bottom: 12px;
border-bottom: 1px solid var(--bd);
}
.arc-back {
font-family: var(--mono);
font-size: 11px;
color: var(--b);
text-decoration: none;
letter-spacing: 1px;
transition: color 0.14s;
}
.arc-back:hover { color: var(--g); }
.arc-title {
font-family: var(--disp);
font-size: 11px;
letter-spacing: 3px;
color: var(--b);
}
.arc-grid {
display: grid;
grid-template-columns: 180px 1fr;
gap: 16px;
height: calc(100vh - 130px);
min-height: 300px;
}
.arc-sidebar, .arc-content {
background: var(--bg1);
border: 1px solid var(--bd);
border-radius: 6px;
overflow: hidden;
display: flex;
flex-direction: column;
}
.arc-sidebar-head, .arc-content-head {
padding: 8px 12px;
border-bottom: 1px solid var(--bd);
font-family: var(--mono);
font-size: 9px;
letter-spacing: 2px;
color: var(--t1);
text-transform: uppercase;
flex-shrink: 0;
}
.arc-days-list { overflow-y: auto; flex: 1; }
.arc-day-item {
padding: 9px 14px;
font-family: var(--mono);
font-size: 12px;
color: var(--t1);
cursor: pointer;
border-left: 2px solid transparent;
transition: all 0.12s;
}
.arc-day-item:hover { color: var(--g); border-left-color: var(--g); background: rgba(0,255,159,0.04); }
.arc-day-item.active { color: var(--b); border-left-color: var(--b); background: rgba(0,184,255,0.06); }
.arc-messages-list { overflow-y: auto; flex: 1; padding: 4px 0; }
.arc-msg {
display: flex;
align-items: baseline;
padding: 3px 12px;
font-family: var(--mono);
font-size: 12px;
line-height: 1.65;
}
.arc-msg:hover { background: rgba(255,255,255,0.02); }
.arc-msg-time { color: var(--t2); font-size: 9px; min-width: 44px; flex-shrink: 0; margin-right: 7px; }
.arc-msg-user { font-weight: 600; font-size: 11px; flex-shrink: 0; min-width: 0; max-width: 90px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.arc-msg-sep { color: var(--t2); margin: 0 7px; flex-shrink: 0; }
.arc-msg-text { color: var(--t0); flex: 1; word-break: break-word; min-width: 0; }
.arc-msg-text audio { width: min(300px, 100%); height: 30px; vertical-align: middle; }
.arc-empty {
flex: 1;
display: flex;
align-items: center;
justify-content: center;
font-family: var(--mono);
font-size: 10px;
color: var(--t2);
letter-spacing: 1.5px;
padding: 20px;
text-align: center;
}
.arc-meta {
font-family: var(--mono);
font-size: 9px;
color: var(--o);
padding: 6px 12px;
border-bottom: 1px solid var(--bd);
letter-spacing: 0.5px;
flex-shrink: 0;
}
@media (max-width: 600px) {
.arc-grid { grid-template-columns: 1fr; grid-template-rows: auto 1fr; height: auto; }
.arc-sidebar { height: 160px; }
}
</style>
</head>
<body>
<div class="arc-wrap">
<div class="arc-topbar">
<a href="index.html" class="arc-back">◂ BACK TO CHAT</a>
<span class="arc-title">// ARCHIVE VIEWER</span>
</div>
<div class="arc-grid">
<div class="arc-sidebar">
<div class="arc-sidebar-head">// DAYS</div>
<div class="arc-days-list">
<?php if (empty($days)): ?>
<div class="arc-empty">NO ARCHIVES YET</div>
<?php else: foreach ($days as $day): ?>
<div class="arc-day-item <?= $day === $selectedDay ? 'active' : '' ?>"
onclick="location.href='?day=<?= htmlspecialchars($day) ?>'">
<?= htmlspecialchars($day) ?>
</div>
<?php endforeach; endif; ?>
</div>
</div>
<div class="arc-content">
<div class="arc-content-head">// MESSAGES</div>
<?php if (!$selectedDay): ?>
<div class="arc-empty">SELECT A DAY FROM THE LIST</div>
<?php elseif (empty($archiveMessages)): ?>
<div class="arc-empty">NO MESSAGES FOR <?= htmlspecialchars($selectedDay) ?></div>
<?php else: ?>
<div class="arc-meta">
// <?= htmlspecialchars($selectedDay) ?>
&nbsp;|&nbsp; <?= count($archiveMessages) ?> MESSAGES
<?php if (!empty($archiveMeta['archived_at'])): ?>
&nbsp;|&nbsp; ARCHIVED <?= date('Y-m-d H:i', (int)$archiveMeta['archived_at']) ?> UTC
<?php endif; ?>
</div>
<div class="arc-messages-list">
<?php foreach ($archiveMessages as $msg): ?>
<div class="arc-msg">
<span class="arc-msg-time"><?= date('H:i', (int)$msg['created_at']) ?></span>
<span class="arc-msg-user" style="color:<?= htmlspecialchars($msg['color']) ?>"><?= htmlspecialchars($msg['username']) ?></span>
<span class="arc-msg-sep"></span>
<span class="arc-msg-text">
<?php if (($msg['message_type'] ?? 'text') === 'voice' && !empty($msg['voice_file'])): ?>
<audio controls preload="metadata"
src="<?= htmlspecialchars(trim((string)getConfigVal('voice.upload_dir', 'uploads/voice'), '/') . '/' . rawurlencode($msg['voice_file'])) ?>"></audio>
<?php else: ?>
<?= htmlspecialchars($msg['message']) ?>
<?php endif; ?>
</span>
</div>
<?php endforeach; ?>
</div>
<?php endif; ?>
</div>
</div>
</div>
</body>
</html>