diff --git a/lib/config-store.js b/lib/config-store.js index 67d35e9..da5474b 100644 --- a/lib/config-store.js +++ b/lib/config-store.js @@ -82,10 +82,24 @@ class ConfigStore { } catch {} } + _readAndParse(filePath) { + const raw = fs.readFileSync(filePath, 'utf-8'); + if (!raw || raw.trim().length < 2) return null; + return JSON.parse(raw); + } + load() { try { - const raw = fs.readFileSync(this.filePath, 'utf-8'); - const data = JSON.parse(raw); + let data = null; + // Try main config + try { data = this._readAndParse(this.filePath); } catch {} + // Fallback to backup if main is empty/corrupt + if (!data) { + const backupPath = this.filePath + '.bak'; + try { data = this._readAndParse(backupPath); } catch {} + } + if (!data) return JSON.parse(JSON.stringify(DEFAULTS)); + // Merge with defaults so new hosters are always present const hosters = { ...DEFAULTS.hosters }; for (const [name, val] of Object.entries(data.hosters || {})) { @@ -116,12 +130,7 @@ class ConfigStore { if (config.hosters) current.hosters = config.hosters; if (config.hosterSettings) current.hosterSettings = config.hosterSettings; if (config.globalSettings) current.globalSettings = config.globalSettings; - const data = JSON.stringify(current, null, 2); - return new Promise((resolve, reject) => { - fs.writeFile(this.filePath, data, 'utf-8', (err) => { - if (err) reject(err); else resolve(); - }); - }); + return this._atomicWrite(JSON.stringify(current, null, 2)); } loadHistory() { @@ -129,29 +138,39 @@ class ConfigStore { return config.history || []; } + _atomicWrite(data) { + return new Promise((resolve, reject) => { + const tmpPath = this.filePath + '.tmp'; + const backupPath = this.filePath + '.bak'; + fs.writeFile(tmpPath, data, 'utf-8', (err) => { + if (err) return reject(err); + try { + if (fs.existsSync(this.filePath)) { + const existing = fs.readFileSync(this.filePath, 'utf-8'); + if (existing && existing.trim().length > 2) { + fs.writeFileSync(backupPath, existing, 'utf-8'); + } + } + fs.renameSync(tmpPath, this.filePath); + } catch (e) { return reject(e); } + resolve(); + }); + }); + } + appendHistory(entry) { const config = this.load(); config.history.push(entry); if (config.history.length > MAX_HISTORY) { config.history = config.history.slice(-MAX_HISTORY); } - const data = JSON.stringify(config, null, 2); - return new Promise((resolve, reject) => { - fs.writeFile(this.filePath, data, 'utf-8', (err) => { - if (err) reject(err); else resolve(); - }); - }); + return this._atomicWrite(JSON.stringify(config, null, 2)); } clearHistory() { const config = this.load(); config.history = []; - const data = JSON.stringify(config, null, 2); - return new Promise((resolve, reject) => { - fs.writeFile(this.filePath, data, 'utf-8', (err) => { - if (err) reject(err); else resolve(); - }); - }); + return this._atomicWrite(JSON.stringify(config, null, 2)); } } diff --git a/package.json b/package.json index 30d0392..6206156 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "multi-hoster-uploader", - "version": "1.6.7", + "version": "1.6.8", "description": "Upload files to doodstream, voe, vidmoly, byse simultaneously", "main": "main.js", "scripts": {