Files
3proxyUI/server/lib/snapshot.ts

65 lines
1.9 KiB
TypeScript

import type { ProxyUserRecord } from '../../src/shared/contracts';
import { deriveDashboardSnapshot, render3proxyConfig, type ObservedRuntimeState, type RuntimePaths, type RuntimeSnapshot } from './config';
import type { StateStore } from './store';
import { readObservedTraffic } from './traffic';
export async function getDashboardSnapshot(
store: StateStore,
runtime: { getSnapshot(): RuntimeSnapshot },
runtimePaths: RuntimePaths,
) {
const state = await store.read();
const previewConfig = render3proxyConfig(state, runtimePaths);
const traffic = await readObservedTraffic(runtimePaths, state.userRecords);
const observedUsers = deriveObservedUsers(state.userRecords, traffic.userBytesByName, traffic.recentUsers);
const observed: ObservedRuntimeState = {
totalBytes: traffic.totalBytes,
liveConnections: traffic.liveConnections,
activeUsers: traffic.activeUsers,
daily: traffic.daily,
userRecords: observedUsers,
};
return deriveDashboardSnapshot(state, runtime.getSnapshot(), observed, previewConfig);
}
function deriveObservedUsers(
users: ProxyUserRecord[],
userBytesByName: Map<string, number>,
recentUsers: Set<string>,
): ProxyUserRecord[] {
return users.map((user) => {
const usedBytes = userBytesByName.get(user.username) ?? 0;
if (user.paused) {
return {
...user,
usedBytes,
status: 'idle',
};
}
if (user.quotaBytes !== null && usedBytes >= user.quotaBytes) {
return {
...user,
usedBytes,
status: 'fail',
};
}
if (user.quotaBytes !== null && user.quotaBytes > 0 && usedBytes / user.quotaBytes >= 0.8) {
return {
...user,
usedBytes,
status: recentUsers.has(user.username) ? 'live' : 'warn',
};
}
return {
...user,
usedBytes,
status: recentUsers.has(user.username) ? 'live' : 'idle',
};
});
}