mirror of
https://github.com/H4zeyaf/Breakallery.git
synced 2026-10-17 11:00:44 +02:00
140 lines
4.1 KiB
JavaScript
140 lines
4.1 KiB
JavaScript
const fs = require('fs');
|
|
const path = require('path');
|
|
const crypto = require('crypto');
|
|
const { sanitizeFolderName, THUMBNAILS_DIR } = require('./paths');
|
|
|
|
class AutoSyncManager {
|
|
constructor(ftpManager, scanner, config) {
|
|
this.ftp = ftpManager;
|
|
this.scanner = scanner;
|
|
this.config = config;
|
|
this.isRunning = false;
|
|
this.timer = null;
|
|
this.status = {
|
|
active: false,
|
|
lastSync: null,
|
|
currentProgress: null,
|
|
error: null,
|
|
syncedCount: 0,
|
|
};
|
|
}
|
|
|
|
start() {
|
|
if (!this.config.autoSync || !this.config.autoSync.enabled) return;
|
|
this.stop();
|
|
|
|
const intervalMs = Math.max(1, this.config.autoSync.intervalMinutes || 10) * 60 * 1000;
|
|
console.log(`[AutoSync] Background sync enabled (checking every ${this.config.autoSync.intervalMinutes} min).`);
|
|
|
|
// Initial run after 5 seconds
|
|
setTimeout(() => this.runSync(), 5000);
|
|
|
|
this.timer = setInterval(() => {
|
|
this.runSync();
|
|
}, intervalMs);
|
|
}
|
|
|
|
stop() {
|
|
if (this.timer) {
|
|
clearInterval(this.timer);
|
|
this.timer = null;
|
|
}
|
|
this.isRunning = false;
|
|
}
|
|
|
|
async runSync() {
|
|
if (this.isRunning) return;
|
|
|
|
this.isRunning = true;
|
|
this.status.active = true;
|
|
this.status.error = null;
|
|
|
|
try {
|
|
// 1. Check if PS5 is reachable
|
|
const online = await this.ftp.checkOnline(2000);
|
|
if (!online) {
|
|
this.status.error = 'PS5 is unreachable';
|
|
return;
|
|
}
|
|
|
|
// 2. Scan captures
|
|
const scanResult = await this.scanner.scan();
|
|
if (!scanResult.success) {
|
|
this.status.error = scanResult.error;
|
|
return;
|
|
}
|
|
|
|
const items = scanResult.library.items || [];
|
|
const downloadRoot = this.config.autoSync.downloadPath;
|
|
if (!fs.existsSync(downloadRoot)) {
|
|
fs.mkdirSync(downloadRoot, { recursive: true });
|
|
}
|
|
|
|
let downloadedThisRun = 0;
|
|
const totalToSync = items.filter((item) => {
|
|
if (item.type === 'photo' && !this.config.autoSync.syncPhotos) return false;
|
|
if (item.type === 'video' && !this.config.autoSync.syncVideos) return false;
|
|
|
|
const gameFolder = sanitizeFolderName(item.gameTitle || item.titleId);
|
|
const targetPath = path.join(downloadRoot, gameFolder, item.filename);
|
|
return !fs.existsSync(targetPath);
|
|
});
|
|
|
|
console.log(`[AutoSync] Found ${totalToSync.length} new items to download.`);
|
|
|
|
for (let i = 0; i < totalToSync.length; i++) {
|
|
const item = totalToSync[i];
|
|
const gameFolder = sanitizeFolderName(item.gameTitle || item.titleId);
|
|
const targetDir = path.join(downloadRoot, gameFolder);
|
|
const targetPath = path.join(targetDir, item.filename);
|
|
|
|
if (!fs.existsSync(targetDir)) {
|
|
fs.mkdirSync(targetDir, { recursive: true });
|
|
}
|
|
|
|
this.status.currentProgress = {
|
|
current: i + 1,
|
|
total: totalToSync.length,
|
|
filename: item.filename,
|
|
};
|
|
|
|
try {
|
|
await this.ftp.downloadFile(item.remotePath, targetPath);
|
|
downloadedThisRun++;
|
|
|
|
// Also cache thumbnail if not cached
|
|
const thumbKey = crypto.createHash('md5').update(item.remotePath).digest('hex') + '.thumb';
|
|
const thumbPath = path.join(THUMBNAILS_DIR, thumbKey);
|
|
if (!fs.existsSync(thumbPath)) {
|
|
if (item.type === 'photo') {
|
|
try { fs.copyFileSync(targetPath, thumbPath); } catch (e) {}
|
|
}
|
|
}
|
|
} catch (e) {
|
|
console.error(`[AutoSync] Failed to download ${item.remotePath}:`, e.message);
|
|
}
|
|
}
|
|
|
|
this.status.syncedCount += downloadedThisRun;
|
|
this.status.lastSync = new Date().toISOString();
|
|
console.log(`[AutoSync] Sync finished. Downloaded ${downloadedThisRun} items.`);
|
|
} catch (err) {
|
|
console.error('[AutoSync] Sync error:', err.message);
|
|
this.status.error = err.message;
|
|
} finally {
|
|
this.isRunning = false;
|
|
this.status.active = false;
|
|
this.status.currentProgress = null;
|
|
}
|
|
}
|
|
|
|
getStatus() {
|
|
return {
|
|
enabled: this.config.autoSync.enabled,
|
|
...this.status,
|
|
};
|
|
}
|
|
}
|
|
|
|
module.exports = AutoSyncManager;
|