false, 'error' => 'invalid_json'], 400); } $sessionId = trim((string) ($body['session_id'] ?? $sessionId)); } if ($sessionId === '') { json_out(['ok' => false, 'error' => 'missing_session_id'], 400); } $session = LiveCastRepository::sessionById($sessionId); if ($session === null) { json_out(['ok' => false, 'error' => 'not_found'], 404); } $platform = strtolower((string) ($session['platform'] ?? '')); $status = strtolower((string) ($session['status'] ?? '')); $isPublic = str_starts_with($platform, 'education') || in_array($status, ['intent', 'live'], true); if (!$isPublic) { Auth::check(); } if ($method === 'GET') { $action = trim((string) ($_GET['action'] ?? 'poll')); if ($action === 'latest') { $latest = LiveCastSignalingRepository::latest( $sessionId, $msgType !== '' ? $msgType : 'offer', $fromRole !== '' ? $fromRole : null ); json_out(['ok' => true, 'message' => $latest]); } $messages = LiveCastSignalingRepository::poll( $sessionId, $sinceId, $msgType !== '' ? $msgType : null, $fromRole !== '' ? $fromRole : null ); $lastId = $sinceId; foreach ($messages as $m) { $lastId = max($lastId, (int) ($m['id'] ?? 0)); } json_out(['ok' => true, 'messages' => $messages, 'since_id' => $lastId]); } if ($method !== 'POST') { json_out(['ok' => false, 'error' => 'method_not_allowed'], 405); } $action = trim((string) ($body['action'] ?? 'post')); if ($action !== 'post') { json_out(['ok' => false, 'error' => 'unknown_action'], 400); } $peerRole = trim((string) ($body['peer_role'] ?? 'caster')); $type = trim((string) ($body['msg_type'] ?? '')); $payload = $body['payload'] ?? null; if (!is_array($payload)) { $payload = ['sdp' => (string) ($body['sdp'] ?? ''), 'type' => (string) ($body['type'] ?? '')]; } if ($type === '') { json_out(['ok' => false, 'error' => 'missing_msg_type'], 400); } $id = LiveCastSignalingRepository::post($sessionId, $peerRole, $type, $payload); json_out(['ok' => true, 'id' => $id]);