false, 'ERROR' => 'method_not_allowed'], 405); } $agentAddress = requireAgentAuth(); $id = (int)($_GET['ID'] ?? 0); $token = trim($_GET['Token'] ?? ''); if ($id <= 0 && empty($token)) { jsonResponse(['OK' => false, 'ERROR' => 'id_or_token_required'], 400); } if ($id > 0) { $row = queryOne("SELECT * FROM Hub_InviteLinks WHERE ID = ?", [$id]); } else { $row = queryOne("SELECT * FROM Hub_InviteLinks WHERE Token = ?", [$token]); } if (!$row) { jsonResponse(['OK' => false, 'ERROR' => 'invite_not_found'], 404); } // Get visitor count $vcRow = queryOne( "SELECT COUNT(*) AS cnt FROM Hub_Visitors WHERE InviteLinkID = ?", [(int)$row['ID']] ); // Compute status $computedStatus = 'active'; if ($row['IsRevoked']) { $computedStatus = 'revoked'; } elseif ($row['ExpiresAt'] && strtotime($row['ExpiresAt']) <= time()) { $computedStatus = 'expired'; } elseif ($row['MaxUses'] > 0 && $row['UseCount'] >= $row['MaxUses']) { $computedStatus = 'exhausted'; } // Get visitors using this link $visitors = queryTimed( "SELECT ID, DisplayName, CreatedAt, LastActiveAt FROM Hub_Visitors WHERE InviteLinkID = ? ORDER BY CreatedAt DESC", [(int)$row['ID']] ); $visitorList = []; foreach ($visitors as $v) { $visitorList[] = [ 'ID' => (int)$v['ID'], 'DisplayName' => $v['DisplayName'], 'CreatedAt' => toISO8601($v['CreatedAt']), 'LastActiveAt' => toISO8601($v['LastActiveAt']), ]; } jsonResponse([ 'OK' => true, 'Link' => [ 'ID' => (int)$row['ID'], 'Token' => $row['Token'], 'Label' => $row['Label'], 'AllowedChannels' => json_decode($row['AllowedChannels'], true), 'HostAddress' => $row['HostAddress'], 'ExpiresAt' => $row['ExpiresAt'] ? toISO8601($row['ExpiresAt']) : null, 'MaxUses' => (int)$row['MaxUses'], 'UseCount' => (int)$row['UseCount'], 'VisitorCount' => (int)($vcRow['cnt'] ?? 0), 'Status' => $computedStatus, 'CreatedBy' => $row['CreatedBy'], 'CreatedAt' => toISO8601($row['CreatedAt']), 'Visitors' => $visitorList, ], ]);