fix(statistics): preserve private account history safely

This commit is contained in:
Sucukdeluxe
2026-08-21 08:37:04 +02:00
parent 4de4f4a0be
commit dc3d9dfc10
6 changed files with 97 additions and 14 deletions
+1 -1
View File
@@ -1092,7 +1092,7 @@ export class AppController {
exportedAt: new Date().toISOString(),
session: this.manager.getSession(),
history: loadHistoryForRetention(this.storagePaths, this.settings.historyRetentionMode, this.historyLimits()),
statistics: this.manager.getStats().statistics!,
statistics: this.manager.getStatisticsLedgerForBackup(),
remoteDiagnostics
});
const encrypted = encryptBackup(JSON.stringify(payloadObj), passphrase);
+13 -4
View File
@@ -85,6 +85,7 @@ import {
addStatisticsOutcomeInPlace,
createStatisticsLedger,
loadStatisticsLedger,
normalizeStatisticsLedger,
projectStatisticsLedger,
saveStatisticsLedger,
seedStatisticsDayProviderBytes
@@ -2624,7 +2625,7 @@ export class DownloadManager extends EventEmitter {
};
}
public getStats(now = nowMs()): DownloadStats {
public getStats(now = nowMs()): DownloadStats {
const itemCount = this.itemCount;
if (this.statsCache && this.session.running && itemCount >= 500 && now - this.statsCacheAt < 1500) {
return this.statsCache;
@@ -2649,8 +2650,12 @@ export class DownloadManager extends EventEmitter {
};
this.statsCache = stats;
this.statsCacheAt = now;
return stats;
}
return stats;
}
public getStatisticsLedgerForBackup(now = nowMs()): StatisticsLedger {
return normalizeStatisticsLedger(this.statisticsLedger, now);
}
public getLiveTotalRuntimeMs(now = nowMs()): number {
return Math.max(0, this.runtimePersistedTotalMs + Math.max(0, now - this.runtimePersistedAt));
@@ -8234,12 +8239,16 @@ export class DownloadManager extends EventEmitter {
}
const recordedAt = nowMs();
const effectiveProvider = resolveMegaDebridProvider(this.settings, provider) || provider;
const accountStatus = providerAccountId ? this.settings.debridAccountStatuses[providerAccountId] : undefined;
const statisticsAccountLabel = accountStatus?.username?.trim()
|| accountStatus?.email?.trim()
|| providerAccountLabel;
addStatisticsBytesInPlace(this.statisticsLedger, effectiveProvider, byteDelta, recordedAt);
this.rollingAccountStatistics.record(
effectiveProvider,
byteDelta,
providerAccountId,
providerAccountLabel,
statisticsAccountLabel,
recordedAt
);
this.statisticsDirty = true;
+17 -3
View File
@@ -164,9 +164,23 @@ export function buildRedactedSettingsPayload(settings: AppSettings): Record<stri
};
}
export function buildStatsPayload(snapshot: UiSnapshot): Record<string, unknown> {
return {
session: snapshot.stats,
export function buildStatsPayload(snapshot: UiSnapshot): Record<string, unknown> {
const rolling24Hours = snapshot.stats.rolling24Hours;
return {
session: {
...snapshot.stats,
...(rolling24Hours ? {
rolling24Hours: {
from: rolling24Hours.from,
to: rolling24Hours.to,
downloadedBytes: rolling24Hours.downloadedBytes,
accounts: rolling24Hours.accounts.map((account) => ({
provider: account.provider,
bytes: account.bytes
}))
}
} : {})
},
totals: {
totalPackages: Object.keys(snapshot.session.packages).length,
totalItems: Object.keys(snapshot.session.items).length,