-
Groups is fully removed: No homepage navigation, Account feature, tier setting, API, or client code. Legacy group tables, entitlements, messages, voice files, and config are purged automatically. New cache-busted client: cyberchat-app.js?v=20260609.3. Browser and SQLite migration tests passed with no console errors.
This commit is contained in:
@@ -25,7 +25,7 @@ session_start();
|
||||
|
||||
function cfg(): array {
|
||||
static $c = null;
|
||||
if ($c === null) $c = json_decode(file_get_contents(CONFIG_FILE), true) ?? [];
|
||||
if ($c === null) $c = getConfig();
|
||||
return $c;
|
||||
}
|
||||
|
||||
@@ -52,11 +52,6 @@ function ensureAdminMessageColumns(PDO $d): void {
|
||||
}
|
||||
}
|
||||
|
||||
function adminPublicMessagePredicate(PDO $d, string $alias = ''): string {
|
||||
$prefix = $alias !== '' ? rtrim($alias, '.') . '.' : '';
|
||||
return isset(tableColumns($d, 'messages')['group_id']) ? "{$prefix}group_id IS NULL" : '1=1';
|
||||
}
|
||||
|
||||
function archiveDB(string $year, string $month, string $day): ?PDO {
|
||||
$tpl = cfgVal('database.archive_path', 'archive/{year}/{month}/{day}.sqlite');
|
||||
$path = storagePath(str_replace(['{year}','{month}','{day}'], [$year,$month,$day], $tpl));
|
||||
@@ -65,6 +60,8 @@ function archiveDB(string $year, string $month, string $day): ?PDO {
|
||||
$a->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
|
||||
$a->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);
|
||||
ensureAdminMessageColumns($a);
|
||||
removeLegacyGroupSchema($a, false);
|
||||
$a->exec("CREATE INDEX IF NOT EXISTS idx_archive_user ON messages(user_id,created_at)");
|
||||
return $a;
|
||||
}
|
||||
|
||||
@@ -91,10 +88,12 @@ function createArchiveDB(string $year, string $month, string $day): PDO {
|
||||
day_key TEXT NOT NULL
|
||||
)");
|
||||
ensureAdminMessageColumns($a);
|
||||
removeLegacyGroupSchema($a, false);
|
||||
$a->exec("CREATE TABLE IF NOT EXISTS archive_meta (
|
||||
key TEXT PRIMARY KEY,
|
||||
value TEXT
|
||||
)");
|
||||
$a->exec("CREATE INDEX IF NOT EXISTS idx_archive_user ON messages(user_id,created_at)");
|
||||
return $a;
|
||||
}
|
||||
|
||||
@@ -155,9 +154,7 @@ function refreshArchiveMeta(PDO $archive): void {
|
||||
key TEXT PRIMARY KEY,
|
||||
value TEXT
|
||||
)");
|
||||
$count = (int)$archive->query(
|
||||
"SELECT COUNT(*) FROM messages WHERE " . adminPublicMessagePredicate($archive)
|
||||
)->fetchColumn();
|
||||
$count = (int)$archive->query("SELECT COUNT(*) FROM messages")->fetchColumn();
|
||||
$meta = $archive->prepare("INSERT OR REPLACE INTO archive_meta(key,value) VALUES(?,?)");
|
||||
$meta->execute(['archived_at', (string)time()]);
|
||||
$meta->execute(['message_count', (string)$count]);
|
||||
@@ -199,8 +196,7 @@ if ($isLoggedIn && $_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||
if ($act === 'archive_voice_clip') {
|
||||
$id = (int)($_POST['msg_id'] ?? 0);
|
||||
$live = db();
|
||||
$stmt = $live->prepare("SELECT * FROM messages WHERE id = ? AND message_type = 'voice' AND "
|
||||
. adminPublicMessagePredicate($live));
|
||||
$stmt = $live->prepare("SELECT * FROM messages WHERE id = ? AND message_type = 'voice'");
|
||||
$stmt->execute([$id]);
|
||||
$row = $stmt->fetch();
|
||||
if (!$row) {
|
||||
@@ -241,8 +237,7 @@ if ($isLoggedIn && $_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||
if ($adb->inTransaction()) $adb->rollBack();
|
||||
throw $e;
|
||||
}
|
||||
$delete = $live->prepare("DELETE FROM messages WHERE id = ? AND message_type = 'voice' AND "
|
||||
. adminPublicMessagePredicate($live));
|
||||
$delete = $live->prepare("DELETE FROM messages WHERE id = ? AND message_type = 'voice'");
|
||||
$delete->execute([$id]);
|
||||
if ($delete->rowCount() !== 1) {
|
||||
throw new RuntimeException('The live clip changed before it could be removed.');
|
||||
@@ -259,11 +254,10 @@ if ($isLoggedIn && $_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||
$src = $_POST['msg_src'] ?? 'live'; // 'live' or 'archive:Y-m-d'
|
||||
if ($src === 'live') {
|
||||
$live = db();
|
||||
$public = adminPublicMessagePredicate($live);
|
||||
$row = $live->prepare("SELECT voice_file FROM messages WHERE id = ? AND $public");
|
||||
$row = $live->prepare("SELECT voice_file FROM messages WHERE id = ?");
|
||||
$row->execute([$id]);
|
||||
deleteRecordingsForRows($row->fetchAll());
|
||||
$live->prepare("DELETE FROM messages WHERE id = ? AND $public")->execute([$id]);
|
||||
$live->prepare("DELETE FROM messages WHERE id = ?")->execute([$id]);
|
||||
flash("Message #$id deleted.");
|
||||
} else {
|
||||
[$_, $day] = explode(':', $src, 2);
|
||||
@@ -295,8 +289,8 @@ if ($isLoggedIn && $_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||
}
|
||||
if ($src === 'live') {
|
||||
$live = db();
|
||||
$live->prepare("UPDATE messages SET message = ?, username = ? WHERE id = ? AND "
|
||||
. adminPublicMessagePredicate($live))->execute([$txt, $username, $id]);
|
||||
$live->prepare("UPDATE messages SET message = ?, username = ? WHERE id = ?")
|
||||
->execute([$txt, $username, $id]);
|
||||
flash("Message #$id updated.");
|
||||
} else {
|
||||
[$_, $day] = explode(':', $src, 2);
|
||||
@@ -314,12 +308,11 @@ if ($isLoggedIn && $_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||
$ids = array_map('intval', $_POST['msg_ids'] ?? []);
|
||||
if ($ids) {
|
||||
$live = db();
|
||||
$public = adminPublicMessagePredicate($live);
|
||||
$ph = implode(',', array_fill(0, count($ids), '?'));
|
||||
$rows = $live->prepare("SELECT voice_file FROM messages WHERE id IN ($ph) AND $public");
|
||||
$rows = $live->prepare("SELECT voice_file FROM messages WHERE id IN ($ph)");
|
||||
$rows->execute($ids);
|
||||
deleteRecordingsForRows($rows->fetchAll());
|
||||
$live->prepare("DELETE FROM messages WHERE id IN ($ph) AND $public")->execute($ids);
|
||||
$live->prepare("DELETE FROM messages WHERE id IN ($ph)")->execute($ids);
|
||||
flash(count($ids) . ' message(s) deleted.');
|
||||
}
|
||||
redirect($_POST['return_qs'] ?? '');
|
||||
@@ -328,11 +321,10 @@ if ($isLoggedIn && $_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||
if ($act === 'delete_day_live') {
|
||||
$day = $_POST['day_key'];
|
||||
$live = db();
|
||||
$public = adminPublicMessagePredicate($live);
|
||||
$rows = $live->prepare("SELECT voice_file FROM messages WHERE day_key = ? AND $public");
|
||||
$rows = $live->prepare("SELECT voice_file FROM messages WHERE day_key = ?");
|
||||
$rows->execute([$day]);
|
||||
deleteRecordingsForRows($rows->fetchAll());
|
||||
$st = $live->prepare("DELETE FROM messages WHERE day_key = ? AND $public");
|
||||
$st = $live->prepare("DELETE FROM messages WHERE day_key = ?");
|
||||
$st->execute([$day]);
|
||||
flash("All messages for $day deleted (" . $st->rowCount() . " rows).");
|
||||
redirect('tab=messages');
|
||||
@@ -356,9 +348,8 @@ if ($isLoggedIn && $_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||
|
||||
if ($act === 'clear_all_live') {
|
||||
$live = db();
|
||||
$public = adminPublicMessagePredicate($live);
|
||||
deleteRecordingsForRows($live->query("SELECT voice_file FROM messages WHERE $public")->fetchAll());
|
||||
$live->exec("DELETE FROM messages WHERE $public");
|
||||
deleteRecordingsForRows($live->query("SELECT voice_file FROM messages")->fetchAll());
|
||||
$live->exec("DELETE FROM messages");
|
||||
flash("All live messages cleared.");
|
||||
redirect('tab=messages');
|
||||
}
|
||||
@@ -474,12 +465,11 @@ $stats = [];
|
||||
if ($isLoggedIn) {
|
||||
try {
|
||||
$live = db();
|
||||
$public = adminPublicMessagePredicate($live);
|
||||
$stats['users'] = $live->query("SELECT COUNT(*) FROM users")->fetchColumn();
|
||||
$stats['messages'] = $live->query("SELECT COUNT(*) FROM messages WHERE $public")->fetchColumn();
|
||||
$stats['voice'] = $live->query("SELECT COUNT(*) FROM messages WHERE message_type = 'voice' AND $public")->fetchColumn();
|
||||
$stats['messages'] = $live->query("SELECT COUNT(*) FROM messages")->fetchColumn();
|
||||
$stats['voice'] = $live->query("SELECT COUNT(*) FROM messages WHERE message_type = 'voice'")->fetchColumn();
|
||||
$stats['sessions'] = $live->query("SELECT COUNT(*) FROM sessions")->fetchColumn();
|
||||
$stats['today'] = $live->query("SELECT COUNT(*) FROM messages WHERE day_key = '" . date('Y-m-d') . "' AND $public")->fetchColumn();
|
||||
$stats['today'] = $live->query("SELECT COUNT(*) FROM messages WHERE day_key = '" . date('Y-m-d') . "'")->fetchColumn();
|
||||
$timeout = (int)cfgVal('security.session_timeout_hours', 24) * 3600;
|
||||
$stats['active'] = db()->query("SELECT COUNT(*) FROM sessions WHERE last_active > " . (time() - $timeout))->fetchColumn();
|
||||
} catch (Exception $e) { $stats = ['users'=>'?','messages'=>'?','voice'=>'?','sessions'=>'?','today'=>'?','active'=>'?']; }
|
||||
@@ -496,8 +486,8 @@ if ($isLoggedIn) {
|
||||
$sz = filesize($f);
|
||||
$cnt = 0;
|
||||
try {
|
||||
$x = new PDO('sqlite:'.$f);
|
||||
$cnt = $x->query("SELECT COUNT(*) FROM messages WHERE " . adminPublicMessagePredicate($x))->fetchColumn();
|
||||
$x = archiveDB($m[1], $m[2], $m[3]);
|
||||
if ($x) $cnt = $x->query("SELECT COUNT(*) FROM messages")->fetchColumn();
|
||||
} catch(Exception $e) {}
|
||||
$archives[] = ['day'=>$day,'path'=>$f,'size'=>$sz,'count'=>$cnt,'year'=>$m[1],'month'=>$m[2],'daynum'=>$m[3]];
|
||||
}
|
||||
@@ -969,7 +959,7 @@ td.actions{white-space:nowrap;width:1px}
|
||||
<?php
|
||||
$live = db();
|
||||
$recent = $live->query("SELECT m.*,u.username as uname FROM messages m LEFT JOIN users u ON u.id=m.user_id
|
||||
WHERE " . adminPublicMessagePredicate($live, 'm') . " ORDER BY m.created_at DESC LIMIT 8")->fetchAll();
|
||||
ORDER BY m.created_at DESC LIMIT 8")->fetchAll();
|
||||
if (empty($recent)): ?>
|
||||
<div class="empty">NO MESSAGES YET</div>
|
||||
<?php else: ?>
|
||||
@@ -1048,7 +1038,7 @@ td.actions{white-space:nowrap;width:1px}
|
||||
$fType = trim($_GET['type'] ?? '');
|
||||
|
||||
$live = db();
|
||||
$where = [adminPublicMessagePredicate($live)]; $params = [];
|
||||
$where = []; $params = [];
|
||||
if ($fUser) { $where[] = "username LIKE ?"; $params[] = '%'.$fUser.'%'; }
|
||||
if ($fText) { $where[] = "message LIKE ?"; $params[] = '%'.$fText.'%'; }
|
||||
if ($fDay) { $where[] = "day_key = ?"; $params[] = $fDay; }
|
||||
@@ -1057,8 +1047,7 @@ td.actions{white-space:nowrap;width:1px}
|
||||
$msgs = $live->prepare($sql); $msgs->execute($params); $msgs = $msgs->fetchAll();
|
||||
|
||||
// Days available
|
||||
$days = $live->query("SELECT DISTINCT day_key FROM messages WHERE "
|
||||
. adminPublicMessagePredicate($live) . " ORDER BY day_key DESC")->fetchAll(PDO::FETCH_COLUMN);
|
||||
$days = $live->query("SELECT DISTINCT day_key FROM messages ORDER BY day_key DESC")->fetchAll(PDO::FETCH_COLUMN);
|
||||
?>
|
||||
|
||||
<div class="search-bar">
|
||||
@@ -1203,7 +1192,7 @@ td.actions{white-space:nowrap;width:1px}
|
||||
$voiceRows = [];
|
||||
if ($vSource !== 'archive') {
|
||||
$live = db();
|
||||
$vWhere = ["message_type = 'voice'", adminPublicMessagePredicate($live)];
|
||||
$vWhere = ["message_type = 'voice'"];
|
||||
$vParams = [];
|
||||
if ($vUser !== '') { $vWhere[] = 'username LIKE ?'; $vParams[] = '%' . $vUser . '%'; }
|
||||
if ($vDay !== '') { $vWhere[] = 'day_key = ?'; $vParams[] = $vDay; }
|
||||
@@ -1221,8 +1210,7 @@ td.actions{white-space:nowrap;width:1px}
|
||||
try {
|
||||
$vAdb = archiveDB($arc['year'], $arc['month'], $arc['daynum']);
|
||||
if (!$vAdb) continue;
|
||||
$vSql = "SELECT * FROM messages WHERE message_type = 'voice' AND "
|
||||
. adminPublicMessagePredicate($vAdb);
|
||||
$vSql = "SELECT * FROM messages WHERE message_type = 'voice'";
|
||||
$vParams = [];
|
||||
if ($vUser !== '') { $vSql .= ' AND username LIKE ?'; $vParams[] = '%' . $vUser . '%'; }
|
||||
$vSql .= ' ORDER BY created_at DESC LIMIT 500';
|
||||
@@ -1242,8 +1230,7 @@ td.actions{white-space:nowrap;width:1px}
|
||||
$voiceRows = array_slice($voiceRows, 0, 500);
|
||||
$live = db();
|
||||
$voiceDays = array_unique(array_merge(
|
||||
$live->query("SELECT DISTINCT day_key FROM messages WHERE message_type = 'voice' AND "
|
||||
. adminPublicMessagePredicate($live) . " ORDER BY day_key DESC")->fetchAll(PDO::FETCH_COLUMN),
|
||||
$live->query("SELECT DISTINCT day_key FROM messages WHERE message_type = 'voice' ORDER BY day_key DESC")->fetchAll(PDO::FETCH_COLUMN),
|
||||
array_column($archives, 'day')
|
||||
));
|
||||
rsort($voiceDays);
|
||||
@@ -1356,7 +1343,7 @@ td.actions{white-space:nowrap;width:1px}
|
||||
if ($adb) {
|
||||
$fAUser = trim($_GET['au'] ?? '');
|
||||
$fAText = trim($_GET['at'] ?? '');
|
||||
$awhere = [adminPublicMessagePredicate($adb)]; $aparams = [];
|
||||
$awhere = []; $aparams = [];
|
||||
if ($fAUser) { $awhere[] = "username LIKE ?"; $aparams[] = '%'.$fAUser.'%'; }
|
||||
if ($fAText) { $awhere[] = "message LIKE ?"; $aparams[] = '%'.$fAText.'%'; }
|
||||
$asql = "SELECT * FROM messages" . ($awhere ? " WHERE ".implode(" AND ", $awhere) : "") . " ORDER BY created_at DESC LIMIT 500";
|
||||
@@ -1539,8 +1526,7 @@ td.actions{white-space:nowrap;width:1px}
|
||||
$live = db();
|
||||
$allUsers = $live->query("
|
||||
SELECT u.*,p.name AS billing_plan_name,mp.name AS manual_plan_name,
|
||||
(SELECT COUNT(*) FROM messages m WHERE m.user_id = u.id AND "
|
||||
. adminPublicMessagePredicate($live, 'm') . ") as msg_count,
|
||||
(SELECT COUNT(*) FROM messages m WHERE m.user_id = u.id) as msg_count,
|
||||
(SELECT COUNT(*) FROM sessions s WHERE s.user_id = u.id) as sess_count
|
||||
FROM users u
|
||||
LEFT JOIN plans p ON p.id=u.plan_id
|
||||
|
||||
Reference in New Issue
Block a user