const fs = require('fs'); const path = require('path'); const HOSTER_SETTINGS_DEFAULTS = { retries: 3, maxSpeedKbs: 0, // 0 = unlimited parallelCount: 2, // 1-100 restartBelowKbs: 0, // 0 = off timeIntervalSec: 0, // delay between jobs maxSizeMb: 0 // 0 = unlimited }; const DEFAULTS = { hosters: { 'doodstream.com': { enabled: true, apiKey: '', username: '', password: '' }, 'voe.sx': { enabled: true, apiKey: '' }, 'vidmoly.me': { enabled: true, authType: 'login', username: '', password: '' }, 'byse.sx': { enabled: true, apiKey: '' } }, hosterSettings: { 'doodstream.com': { ...HOSTER_SETTINGS_DEFAULTS }, 'voe.sx': { ...HOSTER_SETTINGS_DEFAULTS }, 'vidmoly.me': { ...HOSTER_SETTINGS_DEFAULTS }, 'byse.sx': { ...HOSTER_SETTINGS_DEFAULTS } }, globalSettings: { alwaysOnTop: false, shutdownAfterFinish: 'nothing', // nothing | sleep | shutdown | restart logFilePath: '', resumeQueueOnLaunch: true, parallelUploadCount: 0, // 0 = use per-hoster limits only scaleParallelUploads: false, removeFromQueueOnDone: false, globalMaxSpeedKbs: 0, // 0 = unlimited global speed pendingQueue: null, scramble: { active: false, prefix: '', suffix: '', chars: 'both', // 'letters' | 'numbers' | 'both' length: 0 // 0 = same as original basename length } }, history: [] }; const MAX_HISTORY = 100; class ConfigStore { constructor(app) { const dir = app && app.isPackaged ? app.getPath('userData') : path.join(__dirname, '..'); this.filePath = path.join(dir, 'electron-config.json'); // Migrate config from old location if current doesn't exist if (!fs.existsSync(this.filePath) && app && app.isPackaged) { this._migrateFromOldPath(app); } } _migrateFromOldPath(app) { try { const appDataDir = path.dirname(app.getPath('userData')); // Check alternate folder names that may have been used const candidates = ['multi-hoster-uploader', 'Multi-Hoster-Upload']; for (const name of candidates) { const oldPath = path.join(appDataDir, name, 'electron-config.json'); if (oldPath !== this.filePath && fs.existsSync(oldPath)) { fs.mkdirSync(path.dirname(this.filePath), { recursive: true }); fs.copyFileSync(oldPath, this.filePath); return; } } // Also check next to the executable (portable mode previous location) const exeDir = path.dirname(app.getPath('exe')); const portablePath = path.join(exeDir, 'electron-config.json'); if (portablePath !== this.filePath && fs.existsSync(portablePath)) { fs.mkdirSync(path.dirname(this.filePath), { recursive: true }); fs.copyFileSync(portablePath, this.filePath); } } catch {} } load() { try { const raw = fs.readFileSync(this.filePath, 'utf-8'); const data = JSON.parse(raw); // Merge with defaults so new hosters are always present const hosters = { ...DEFAULTS.hosters }; for (const [name, val] of Object.entries(data.hosters || {})) { if (hosters[name]) { hosters[name] = { ...hosters[name], ...val }; } } // Merge hoster settings with defaults const hosterSettings = {}; for (const name of Object.keys(DEFAULTS.hosterSettings)) { hosterSettings[name] = { ...HOSTER_SETTINGS_DEFAULTS, ...(data.hosterSettings && data.hosterSettings[name] || {}) }; } const globalSettings = { ...DEFAULTS.globalSettings, ...(data.globalSettings || {}) }; return { hosters, hosterSettings, globalSettings, history: data.history || [] }; } catch { return JSON.parse(JSON.stringify(DEFAULTS)); } } save(config) { const current = this.load(); 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(); }); }); } loadHistory() { const config = this.load(); return config.history || []; } 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(); }); }); } 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(); }); }); } } module.exports = ConfigStore;