/** * Communication Admin API Route - Stats Proxy * * Proxies requests to Matrix/Jitsi admin endpoints * Aggregates statistics from both services */ import { NextRequest, NextResponse } from 'next/server' // Service URLs const CONSENT_SERVICE_URL = process.env.CONSENT_SERVICE_URL || 'http://localhost:8081' const MATRIX_ADMIN_URL = process.env.MATRIX_ADMIN_URL || 'http://localhost:8448' const JITSI_URL = process.env.JITSI_URL || 'http://localhost:8443' // Matrix Admin Token (for Synapse Admin API) const MATRIX_ADMIN_TOKEN = process.env.MATRIX_ADMIN_TOKEN || '' interface MatrixStats { total_users: number active_users: number total_rooms: number active_rooms: number messages_today: number messages_this_week: number status: 'online' | 'offline' | 'degraded' } interface JitsiStats { active_meetings: number total_participants: number meetings_today: number average_duration_minutes: number peak_concurrent_users: number total_minutes_today: number status: 'online' | 'offline' | 'degraded' } async function fetchMatrixStats(): Promise { try { // Try to get stats from consent service first const consentResponse = await fetch(`${CONSENT_SERVICE_URL}/api/v1/communication/admin/stats`, { headers: { 'Content-Type': 'application/json', }, }) if (consentResponse.ok) { const data = await consentResponse.json() return { total_users: data.matrix?.total_users || 0, active_users: data.matrix?.active_users || 0, total_rooms: data.matrix?.total_rooms || 0, active_rooms: data.matrix?.active_rooms || 0, messages_today: data.matrix?.messages_today || 0, messages_this_week: data.matrix?.messages_this_week || 0, status: 'online' } } // Fallback: Try direct Matrix Admin API if (MATRIX_ADMIN_TOKEN) { const response = await fetch(`${MATRIX_ADMIN_URL}/_synapse/admin/v1/statistics/users/media`, { headers: { 'Authorization': `Bearer ${MATRIX_ADMIN_TOKEN}`, }, }) if (response.ok) { return { total_users: 0, active_users: 0, total_rooms: 0, active_rooms: 0, messages_today: 0, messages_this_week: 0, status: 'online' } } } // Check if Matrix is at least reachable const healthCheck = await fetch(`${MATRIX_ADMIN_URL}/_matrix/client/versions`, { signal: AbortSignal.timeout(5000) }) return { total_users: 0, active_users: 0, total_rooms: 0, active_rooms: 0, messages_today: 0, messages_this_week: 0, status: healthCheck.ok ? 'degraded' : 'offline' } } catch (error) { console.error('Matrix stats fetch error:', error) return { total_users: 0, active_users: 0, total_rooms: 0, active_rooms: 0, messages_today: 0, messages_this_week: 0, status: 'offline' } } } async function fetchJitsiStats(): Promise { try { // Try to get stats from consent service const consentResponse = await fetch(`${CONSENT_SERVICE_URL}/api/v1/communication/admin/stats`, { headers: { 'Content-Type': 'application/json', }, }) if (consentResponse.ok) { const data = await consentResponse.json() return { active_meetings: data.jitsi?.active_meetings || 0, total_participants: data.jitsi?.total_participants || 0, meetings_today: data.jitsi?.meetings_today || 0, average_duration_minutes: data.jitsi?.average_duration_minutes || 0, peak_concurrent_users: data.jitsi?.peak_concurrent_users || 0, total_minutes_today: data.jitsi?.total_minutes_today || 0, status: 'online' } } // Check if Jitsi is at least reachable const healthCheck = await fetch(`${JITSI_URL}/http-bind`, { method: 'HEAD', signal: AbortSignal.timeout(5000) }) return { active_meetings: 0, total_participants: 0, meetings_today: 0, average_duration_minutes: 0, peak_concurrent_users: 0, total_minutes_today: 0, status: healthCheck.ok ? 'degraded' : 'offline' } } catch (error) { console.error('Jitsi stats fetch error:', error) return { active_meetings: 0, total_participants: 0, meetings_today: 0, average_duration_minutes: 0, peak_concurrent_users: 0, total_minutes_today: 0, status: 'offline' } } } export async function GET(request: NextRequest) { try { // Fetch stats from both services in parallel const [matrixStats, jitsiStats] = await Promise.all([ fetchMatrixStats(), fetchJitsiStats() ]) // Try to get active meetings and rooms from consent service let activeMeetings: unknown[] = [] let recentRooms: unknown[] = [] try { const consentResponse = await fetch(`${CONSENT_SERVICE_URL}/api/v1/communication/admin/stats`) if (consentResponse.ok) { const data = await consentResponse.json() activeMeetings = data.active_meetings || [] recentRooms = data.recent_rooms || [] } } catch { // Ignore errors, use empty arrays } return NextResponse.json({ matrix: matrixStats, jitsi: jitsiStats, active_meetings: activeMeetings, recent_rooms: recentRooms, last_updated: new Date().toISOString() }) } catch (error) { console.error('Communication stats error:', error) return NextResponse.json( { error: 'Fehler beim Abrufen der Statistiken', matrix: { status: 'offline', total_users: 0, active_users: 0, total_rooms: 0, active_rooms: 0, messages_today: 0, messages_this_week: 0 }, jitsi: { status: 'offline', active_meetings: 0, total_participants: 0, meetings_today: 0, average_duration_minutes: 0, peak_concurrent_users: 0, total_minutes_today: 0 }, active_meetings: [], recent_rooms: [], last_updated: new Date().toISOString() }, { status: 503 } ) } }