function normalize(value) { return String(value ?? "") .trim() .toLowerCase(); } function userKeys(user) { return [user.jellyfin_id, user.username, user.display_name] .map(normalize) .filter(Boolean); } function sessionMatchesUser(user, session) { const sessionUser = normalize(session.user); if (!sessionUser) { return false; } return userKeys(user).some((key) => key === sessionUser); } function buildActivitySummary(sessions) { const activeSessions = sessions.filter((session) => { const state = String(session.state || "") .trim() .toLowerCase(); return state === "playing" || state === "paused"; }); const idleSessions = sessions.filter((session) => { const state = String(session.state || "") .trim() .toLowerCase(); return state === "idle"; }); const primarySession = activeSessions[0] || sessions[0] || null; const hasPlaying = activeSessions.some((session) => { const state = String(session.state || "") .trim() .toLowerCase(); return state === "playing"; }); const hasPaused = activeSessions.some((session) => { const state = String(session.state || "") .trim() .toLowerCase(); return state === "paused"; }); const label = !sessions.length ? "No sessions" : hasPlaying ? "Playing" : hasPaused ? "Paused" : "Idle"; const summary = sessions.length === 0 ? "No live sessions" : [ `${sessions.length} session${sessions.length === 1 ? "" : "s"}`, activeSessions.length ? `${activeSessions.length} active` : null, idleSessions.length ? `${idleSessions.length} idle` : null, ] .filter(Boolean) .join(" ยท "); return { sessions, active_count: activeSessions.length, idle_count: idleSessions.length, label, summary, primary_session: primarySession, }; } export function mergeUsersWithActivity(users, sessions) { return users.map((user) => { const matchingSessions = sessions.filter((session) => sessionMatchesUser(user, session), ); const activity = buildActivitySummary(matchingSessions); return { ...user, activity, activity_label: activity.label, activity_summary: activity.summary, activity_count: activity.sessions.length, activity_active_count: activity.active_count, activity_idle_count: activity.idle_count, }; }); } export function resolveUserSelection(users, identifier) { const needle = normalize(identifier); if (!needle) { return null; } return ( users.find((user) => userKeys(user).some((key) => key === needle)) || null ); }