first commit

This commit is contained in:
Vlastislav Svatek
2026-04-26 02:23:11 +02:00
commit 153c83f7fa
31 changed files with 3804 additions and 0 deletions

228
api/community_ratings.php Normal file
View File

@@ -0,0 +1,228 @@
<?php
// ============================================================
// api/community_ratings.php
//
// GET /api/community_ratings?streamer_id=N — get all group ratings for a streamer (public)
// GET /api/community_ratings?my_rating=N — get my group's rating for a streamer (rater)
// PUT /api/community_ratings?streamer_id=N — submit/update group rating (rater/admin)
// DELETE /api/community_ratings?id=N — delete a rating (admin)
// ============================================================
require_once __DIR__ . '/db.php';
cors();
start_session();
$method = $_SERVER['REQUEST_METHOD'];
// ── GET ────────────────────────────────────────────────────────
if ($method === 'GET') {
// Batch: all ratings for a single team (member of the team or admin).
// /api/community_ratings?team_ratings=1&group_id=N
if (isset($_GET['team_ratings'])) {
$gid = (int)($_GET['group_id'] ?? 0);
if (!$gid) json_error('Missing group_id');
$is_admin = !empty($_SESSION['is_admin']);
$user = $_SESSION['oauth_user'] ?? null;
// Members of this team or admin only
if (!$is_admin) {
if (!$user) json_error('Not logged in', 401);
$stmt = db()->prepare("SELECT 1 FROM rater_group_members WHERE group_id=:gid AND user_id=:uid");
$stmt->execute([':gid' => $gid, ':uid' => $user['id']]);
if (!$stmt->fetchColumn()) json_error('Not a member of this team', 403);
}
$stmt = db()->prepare("
SELECT streamer_id, statistiky, grafika, alerty, vychytavky,
nahled, nastaveni, odlisnost, notes, updated_at
FROM community_ratings
WHERE group_id = :gid
");
$stmt->execute([':gid' => $gid]);
// Return as map: { streamer_id: rating }
$out = [];
foreach ($stmt->fetchAll() as $r) {
$out[(int)$r['streamer_id']] = $r;
}
json_out($out);
}
// My group's rating for a specific streamer.
// Optional &group_id=N to disambiguate when user is in multiple teams.
if (isset($_GET['my_rating'])) {
$sid = (int)($_GET['my_rating'] ?? 0);
$gid = isset($_GET['group_id']) ? (int)$_GET['group_id'] : 0;
$user = $_SESSION['oauth_user'] ?? null;
if (!$user) json_out(null);
$sql = "
SELECT cr.*, g.name AS group_name
FROM community_ratings cr
JOIN rater_groups g ON g.id = cr.group_id
JOIN rater_group_members m ON m.group_id = g.id
WHERE m.user_id = :uid AND cr.streamer_id = :sid
";
$params = [':uid' => $user['id'], ':sid' => $sid];
if ($gid) {
$sql .= " AND cr.group_id = :gid";
$params[':gid'] = $gid;
}
$sql .= " LIMIT 1";
$stmt = db()->prepare($sql);
$stmt->execute($params);
json_out($stmt->fetch() ?: null);
}
// All community ratings for a streamer — public, anonymous
$sid = (int)($_GET['streamer_id'] ?? 0);
if (!$sid) json_error('Missing streamer_id');
$stmt = db()->prepare("
SELECT cr.id, cr.group_id, g.name AS group_name,
cr.statistiky, cr.grafika, cr.alerty, cr.vychytavky,
cr.nahled, cr.nastaveni, cr.odlisnost, cr.notes, cr.updated_at
FROM community_ratings cr
JOIN rater_groups g ON g.id = cr.group_id
WHERE cr.streamer_id = :sid
ORDER BY cr.updated_at DESC
");
$stmt->execute([':sid' => $sid]);
$ratings = $stmt->fetchAll();
// Calculate averages
$avg = null;
$keymap = ['s'=>'statistiky','g'=>'grafika','a'=>'alerty','v'=>'vychytavky','n'=>'nahled','ns'=>'nastaveni','o'=>'odlisnost'];
if ($ratings) {
$keys = ['statistiky','grafika','alerty','vychytavky','nahled','nastaveni','odlisnost'];
$avg = [];
foreach ($keys as $k) {
$avg[$k] = round(array_sum(array_column($ratings, $k)) / count($ratings), 1);
}
// Also expose compact keys for frontend
foreach ($keymap as $short => $long) $avg[$short] = $avg[$long];
$avg['total'] = round(array_sum(array_intersect_key($avg, array_flip($keys))), 1);
$avg['count'] = count($ratings);
}
// Add compact keys to each rating row too
foreach ($ratings as &$r) {
foreach ($keymap as $short => $long) $r[$short] = (int)$r[$long];
}
unset($r);
json_out(['ratings' => $ratings, 'avg' => $avg]);
}
// ── PUT — submit or update group rating ───────────────────────
if ($method === 'PUT') {
$sid = (int)($_GET['streamer_id'] ?? 0);
if (!$sid) json_error('Missing streamer_id');
$is_admin = !empty($_SESSION['is_admin']);
$user = $_SESSION['oauth_user'] ?? null;
if (!$is_admin && !$user) json_error('Not logged in', 401);
// Check streamer not locked
$stmt = db()->prepare("SELECT community_locked FROM streamers WHERE id=:id");
$stmt->execute([':id' => $sid]);
$row = $stmt->fetch();
if (!$row) json_error('Streamer not found', 404);
if ($row['community_locked'] && !$is_admin) json_error('Community ratings are locked for this streamer', 403);
$body = body();
// Determine group_id
if (isset($body['group_id'])) {
$group_id = (int)$body['group_id'];
// Members must be in this group; admin can use any group
if (!$is_admin) {
$stmt = db()->prepare("
SELECT 1 FROM rater_group_members
WHERE group_id = :gid AND user_id = :uid
");
$stmt->execute([':gid' => $group_id, ':uid' => $user['id']]);
if (!$stmt->fetchColumn()) json_error('You are not a member of this team', 403);
}
} elseif ($user) {
// Default: pick the user's first group
$stmt = db()->prepare("
SELECT group_id FROM rater_group_members WHERE user_id=:uid LIMIT 1
");
$stmt->execute([':uid' => $user['id']]);
$row = $stmt->fetch();
if (!$row) json_error('You are not assigned to any rater group', 403);
$group_id = (int)$row['group_id'];
} else {
json_error('Cannot determine group', 400);
}
// Block self-rating: a team representing a streamer cannot rate that streamer
$stmt = db()->prepare("SELECT streamer_id FROM rater_groups WHERE id = :gid");
$stmt->execute([':gid' => $group_id]);
$linked_sid = $stmt->fetchColumn();
if ($linked_sid && (int)$linked_sid === $sid) {
json_error('A team cannot rate its own streamer', 403);
}
$clamp = fn($v) => max(0, min(10, (int)$v));
$r = $body['r'] ?? [];
db()->prepare("
INSERT INTO community_ratings
(group_id, streamer_id, statistiky, grafika, alerty, vychytavky,
nahled, nastaveni, odlisnost, notes, updated_by, updated_at)
VALUES
(:gid, :sid, :s, :g, :a, :v, :n, :ns, :o, :notes, :uid, NOW())
ON CONFLICT (group_id, streamer_id) DO UPDATE SET
statistiky = EXCLUDED.statistiky,
grafika = EXCLUDED.grafika,
alerty = EXCLUDED.alerty,
vychytavky = EXCLUDED.vychytavky,
nahled = EXCLUDED.nahled,
nastaveni = EXCLUDED.nastaveni,
odlisnost = EXCLUDED.odlisnost,
notes = EXCLUDED.notes,
updated_by = EXCLUDED.updated_by,
updated_at = NOW()
")->execute([
':gid' => $group_id,
':sid' => $sid,
':s' => $clamp($r['s'] ?? 0),
':g' => $clamp($r['g'] ?? 0),
':a' => $clamp($r['a'] ?? 0),
':v' => $clamp($r['v'] ?? 0),
':n' => $clamp($r['n'] ?? 0),
':ns' => $clamp($r['ns'] ?? 0),
':o' => $clamp($r['o'] ?? 0),
':notes' => substr(trim($body['notes'] ?? ''), 0, 1000),
':uid' => $user ? $user['id'] : null,
]);
json_out(['ok' => true]);
}
// ── DELETE — admin only ────────────────────────────────────────
if ($method === 'DELETE') {
require_admin();
// Wipe all ratings for a single streamer (used by reset)
if (isset($_GET['wipe_streamer'])) {
$sid = (int)$_GET['wipe_streamer'];
if (!$sid) json_error('Missing streamer id');
$stmt = db()->prepare("DELETE FROM community_ratings WHERE streamer_id = :sid");
$stmt->execute([':sid' => $sid]);
json_out(['ok' => true, 'deleted' => $stmt->rowCount()]);
}
$id = (int)($_GET['id'] ?? 0);
if (!$id) json_error('Missing id');
db()->prepare("DELETE FROM community_ratings WHERE id=:id")->execute([':id' => $id]);
json_out(['ok' => true]);
}
json_error('Method not allowed', 405);