270 lines
10 KiB
PHP
270 lines
10 KiB
PHP
<?php
|
|
// ============================================================
|
|
// api/streamers.php
|
|
//
|
|
// GET /api/streamers — public list (evaluated only)
|
|
// GET /api/streamers?all=1 — full list (admin or mod)
|
|
// POST /api/streamers — suggest a streamer (public)
|
|
// POST /api/streamers?admin=1 — add streamer (admin only)
|
|
// PUT /api/streamers?id=N — update streamer + rating (admin or mod)
|
|
// DELETE /api/streamers?id=N — delete streamer (admin only)
|
|
// ============================================================
|
|
|
|
require_once __DIR__ . '/db.php';
|
|
|
|
cors();
|
|
|
|
$method = $_SERVER['REQUEST_METHOD'];
|
|
|
|
// ------------------------------------------------------------------
|
|
// GET — fetch streamers
|
|
// ------------------------------------------------------------------
|
|
if ($method === 'GET') {
|
|
start_session();
|
|
$is_admin = !empty($_SESSION['is_admin']);
|
|
$is_mod = is_moderator();
|
|
|
|
// Detect if logged-in OAuth user is a member of any rater team
|
|
$is_team_member = false;
|
|
if (!$is_admin && !$is_mod && !empty($_SESSION['oauth_user']['id'])) {
|
|
$stmt = db()->prepare("SELECT 1 FROM rater_group_members WHERE user_id = :uid LIMIT 1");
|
|
$stmt->execute([':uid' => $_SESSION['oauth_user']['id']]);
|
|
$is_team_member = (bool)$stmt->fetchColumn();
|
|
}
|
|
|
|
// 'all=1' is admin/mod request for unfiltered list (with notes etc.)
|
|
$all = isset($_GET['all']) && ($is_admin || $is_mod);
|
|
// Team members must see all streamers (even unevaluated) so they can rate them
|
|
$see_unevaluated = $all || $is_team_member;
|
|
|
|
if ($all) {
|
|
$sql = "
|
|
SELECT s.*,
|
|
r.statistiky, r.grafika, r.alerty, r.vychytavky,
|
|
r.nahled, r.nastaveni, r.odlisnost, r.reward, r.notes,
|
|
g.id AS team_id, g.name AS team_name
|
|
FROM streamers s
|
|
LEFT JOIN ratings r ON r.streamer_id = s.id
|
|
LEFT JOIN rater_groups g ON g.streamer_id = s.id
|
|
ORDER BY s.evaluated DESC, s.name ASC
|
|
";
|
|
} elseif ($see_unevaluated) {
|
|
// Team member: all streamers, but no admin-only fields like notes
|
|
$sql = "
|
|
SELECT s.id, s.name, s.platform, s.kick_name, s.status,
|
|
s.game, s.title, s.evaluated, s.community_locked,
|
|
r.statistiky, r.grafika, r.alerty, r.vychytavky,
|
|
r.nahled, r.nastaveni, r.odlisnost, r.reward,
|
|
g.id AS team_id, g.name AS team_name
|
|
FROM streamers s
|
|
LEFT JOIN ratings r ON r.streamer_id = s.id
|
|
LEFT JOIN rater_groups g ON g.streamer_id = s.id
|
|
ORDER BY s.evaluated DESC, s.name ASC
|
|
";
|
|
} else {
|
|
$sql = "
|
|
SELECT s.id, s.name, s.platform, s.kick_name, s.status,
|
|
s.game, s.title, s.evaluated, s.community_locked,
|
|
r.statistiky, r.grafika, r.alerty, r.vychytavky,
|
|
r.nahled, r.nastaveni, r.odlisnost, r.reward,
|
|
g.id AS team_id, g.name AS team_name
|
|
FROM streamers s
|
|
INNER JOIN ratings r ON r.streamer_id = s.id
|
|
LEFT JOIN rater_groups g ON g.streamer_id = s.id
|
|
WHERE s.evaluated = true
|
|
ORDER BY (r.statistiky + r.grafika + r.alerty + r.vychytavky +
|
|
r.nahled + r.nastaveni + r.odlisnost) DESC
|
|
";
|
|
}
|
|
|
|
$rows = db()->query($sql)->fetchAll();
|
|
|
|
// Reshape: nest ratings under 'r' key to match frontend format
|
|
$out = array_map(function($row) {
|
|
$s = [
|
|
'id' => $row['id'],
|
|
'name' => $row['name'],
|
|
'platform' => $row['platform'],
|
|
'kick' => $row['kick_name'] ?? '',
|
|
'status' => $row['status'],
|
|
'game' => $row['game'] ?? '',
|
|
'title' => $row['title'] ?? '',
|
|
'evaluated' => (bool)$row['evaluated'],
|
|
'community_locked' => (bool)($row['community_locked'] ?? false),
|
|
'added_by' => $row['added_by'] ?? 'admin',
|
|
'r' => [
|
|
's' => (int)($row['statistiky'] ?? 0),
|
|
'g' => (int)($row['grafika'] ?? 0),
|
|
'a' => (int)($row['alerty'] ?? 0),
|
|
'v' => (int)($row['vychytavky'] ?? 0),
|
|
'n' => (int)($row['nahled'] ?? 0),
|
|
'ns' => (int)($row['nastaveni'] ?? 0),
|
|
'o' => (int)($row['odlisnost'] ?? 0),
|
|
],
|
|
'reward' => (int)($row['reward'] ?? 0),
|
|
'team_id' => isset($row['team_id']) ? (int)$row['team_id'] : null,
|
|
'team_name' => $row['team_name'] ?? null,
|
|
];
|
|
if (isset($row['notes'])) {
|
|
$s['notes'] = $row['notes'];
|
|
}
|
|
return $s;
|
|
}, $rows);
|
|
|
|
json_out($out);
|
|
}
|
|
|
|
// ------------------------------------------------------------------
|
|
// POST — add streamer (suggestion from public, or admin add)
|
|
// ------------------------------------------------------------------
|
|
if ($method === 'POST') {
|
|
$body = body();
|
|
$is_admin_add = isset($_GET['admin']);
|
|
|
|
if ($is_admin_add) {
|
|
session_start();
|
|
if (empty($_SESSION['is_admin'])) json_error('Unauthorized', 401);
|
|
}
|
|
|
|
$name = sanitize_name($body['name'] ?? '');
|
|
if (strlen($name) < 2) json_error('Invalid streamer name');
|
|
|
|
$platform = in_array($body['platform'] ?? '', ['twitch','kick']) ? $body['platform'] : 'twitch';
|
|
$kick_name = sanitize_name($body['kick_name'] ?? '');
|
|
$submitter = substr(trim($body['submitter'] ?? ''), 0, 60);
|
|
$added_by = $is_admin_add ? 'admin' : 'viewer';
|
|
|
|
try {
|
|
$stmt = db()->prepare("
|
|
INSERT INTO streamers (name, platform, kick_name, added_by, submitter)
|
|
VALUES (:name, :platform, :kick_name, :added_by, :submitter)
|
|
RETURNING id
|
|
");
|
|
$stmt->execute([
|
|
':name' => $name,
|
|
':platform' => $platform,
|
|
':kick_name' => $kick_name,
|
|
':added_by' => $added_by,
|
|
':submitter' => $submitter,
|
|
]);
|
|
$row = $stmt->fetch();
|
|
json_out(['ok' => true, 'id' => $row['id']], 201);
|
|
} catch (PDOException $e) {
|
|
if (str_contains($e->getMessage(), 'unique')) {
|
|
json_error('Streamer already exists', 409);
|
|
}
|
|
json_error('DB error', 500);
|
|
}
|
|
}
|
|
|
|
// ------------------------------------------------------------------
|
|
// PUT — update streamer + rating (admin or mod)
|
|
// ------------------------------------------------------------------
|
|
if ($method === 'PUT') {
|
|
require_mod();
|
|
|
|
$id = (int)($_GET['id'] ?? 0);
|
|
if (!$id) json_error('Missing id');
|
|
|
|
$is_admin = !empty($_SESSION['is_admin']);
|
|
$body = body();
|
|
|
|
// Lock/unlock community ratings — admin only
|
|
if (isset($_GET['lock'])) {
|
|
if (!$is_admin) json_error('Admin only', 403);
|
|
$locked = !empty($body['community_locked']) ? 'true' : 'false';
|
|
db()->prepare("UPDATE streamers SET community_locked=:l WHERE id=:id")
|
|
->execute([':l' => $locked, ':id' => $id]);
|
|
json_out(['ok' => true]);
|
|
}
|
|
|
|
// Clamp rating values 0-10
|
|
$clamp = fn($v) => max(0, min(10, (int)$v));
|
|
$r = $body['r'] ?? [];
|
|
$stats = $clamp($r['s'] ?? 0);
|
|
$graf = $clamp($r['g'] ?? 0);
|
|
$alert = $clamp($r['a'] ?? 0);
|
|
$vych = $clamp($r['v'] ?? 0);
|
|
$nahl = $clamp($r['n'] ?? 0);
|
|
$nast = $clamp($r['ns'] ?? 0);
|
|
$odl = $clamp($r['o'] ?? 0);
|
|
$notes = substr(trim($body['notes'] ?? ''), 0, 2000);
|
|
$evaluated = ($stats + $graf + $alert + $vych + $nahl + $nast + $odl) > 0;
|
|
|
|
// Reward — admin can override manually, mods get auto-calculated
|
|
$reward = $is_admin
|
|
? max(0, min(130, (int)($body['reward'] ?? 0)))
|
|
: ($evaluated ? (int)round(30 + (($stats+$graf+$alert+$vych+$nahl+$nast+$odl) / 70) * 100) : 0);
|
|
|
|
$db = db();
|
|
|
|
// Moderators can only update ratings, not streamer metadata (status/game/title)
|
|
if ($is_admin) {
|
|
$kick = sanitize_name($body['kick'] ?? '');
|
|
$status = in_array($body['status'] ?? '', ['live','offline']) ? $body['status'] : 'offline';
|
|
$game = substr(trim($body['game'] ?? ''), 0, 100);
|
|
$title = substr(trim($body['title'] ?? ''), 0, 200);
|
|
|
|
$db->prepare("
|
|
UPDATE streamers
|
|
SET kick_name=:kick, status=:status, game=:game, title=:title, evaluated=:evaluated
|
|
WHERE id=:id
|
|
")->execute([
|
|
':kick'=>$kick, ':status'=>$status, ':game'=>$game,
|
|
':title'=>$title, ':evaluated'=>$evaluated?'true':'false', ':id'=>$id,
|
|
]);
|
|
} else {
|
|
// Mod: only update evaluated flag
|
|
$db->prepare("UPDATE streamers SET evaluated=:evaluated WHERE id=:id")
|
|
->execute([':evaluated'=>$evaluated?'true':'false', ':id'=>$id]);
|
|
}
|
|
|
|
// Upsert rating row
|
|
$db->prepare("
|
|
INSERT INTO ratings
|
|
(streamer_id, statistiky, grafika, alerty, vychytavky,
|
|
nahled, nastaveni, odlisnost, reward, notes)
|
|
VALUES
|
|
(:sid, :s, :g, :a, :v, :n, :ns, :o, :reward, :notes)
|
|
ON CONFLICT (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,
|
|
reward = EXCLUDED.reward,
|
|
notes = EXCLUDED.notes,
|
|
updated_at = NOW()
|
|
")->execute([
|
|
':sid' => $id,
|
|
':s' => $stats,
|
|
':g' => $graf,
|
|
':a' => $alert,
|
|
':v' => $vych,
|
|
':n' => $nahl,
|
|
':ns' => $nast,
|
|
':o' => $odl,
|
|
':reward' => $reward,
|
|
':notes' => $notes,
|
|
]);
|
|
|
|
json_out(['ok' => true]);
|
|
}
|
|
|
|
// ------------------------------------------------------------------
|
|
// DELETE — remove streamer (admin only)
|
|
// ------------------------------------------------------------------
|
|
if ($method === 'DELETE') {
|
|
require_admin();
|
|
|
|
$id = (int)($_GET['id'] ?? 0);
|
|
if (!$id) json_error('Missing id');
|
|
|
|
db()->prepare("DELETE FROM streamers WHERE id = :id")->execute([':id' => $id]);
|
|
json_out(['ok' => true]);
|
|
}
|
|
|
|
json_error('Method not allowed', 405);
|