diff --git a/.dockerignore b/.dockerignore index c09fb4d2a..e91e3fe3e 100644 --- a/.dockerignore +++ b/.dockerignore @@ -3,4 +3,5 @@ node_modules npm-debug.log readme* Start.bat -/dist \ No newline at end of file +/dist +/backups/ diff --git a/.gitignore b/.gitignore index adbad52f1..8f73d2edd 100644 --- a/.gitignore +++ b/.gitignore @@ -20,3 +20,4 @@ whitelist.txt secrets.json /dist poe_device.json +/backups/ diff --git a/.npmignore b/.npmignore index 225d3c058..896c9b028 100644 --- a/.npmignore +++ b/.npmignore @@ -5,3 +5,4 @@ node_modules/ secrets.json /dist poe_device.json +/backups/ diff --git a/server.js b/server.js index ee1f0ff41..dcf6f8dcd 100644 --- a/server.js +++ b/server.js @@ -256,6 +256,7 @@ const directories = { extensions: 'public/scripts/extensions', instruct: 'public/instruct', context: 'public/context', + backups: 'backups/', }; // CSRF Protection // @@ -3335,6 +3336,7 @@ const setupTasks = async function () { console.log(`SillyTavern ${version.pkgVersion}` + (version.gitBranch ? ` '${version.gitBranch}' (${version.gitRevision})` : '')); + backupSettings(); migrateSecrets(); ensurePublicDirectoriesExist(); await ensureThumbnailCache(); @@ -3426,6 +3428,41 @@ async function convertWebp() { } } +function backupSettings() { + const MAX_BACKUPS = 25; + + function generateTimestamp() { + const now = new Date(); + const year = now.getFullYear(); + const month = String(now.getMonth() + 1).padStart(2, '0'); + const day = String(now.getDate()).padStart(2, '0'); + const hours = String(now.getHours()).padStart(2, '0'); + const minutes = String(now.getMinutes()).padStart(2, '0'); + const seconds = String(now.getSeconds()).padStart(2, '0'); + + return `${year}${month}${day}-${hours}${minutes}${seconds}`; + } + + try { + if (!fs.existsSync(directories.backups)) { + fs.mkdirSync(directories.backups); + } + + const backupFile = path.join(directories.backups, `settings_${generateTimestamp()}.json`); + fs.copyFileSync(SETTINGS_FILE, backupFile); + + let files = fs.readdirSync(directories.backups); + if (files.length > MAX_BACKUPS) { + files = files.map(f => path.join(directories.backups, f)); + files.sort((a, b) => fs.statSync(a).mtimeMs - fs.statSync(b).mtimeMs); + + fs.rmSync(files[0]); + } + } catch (err) { + console.log('Could not backup settings file', err); + } +} + function ensurePublicDirectoriesExist() { for (const dir of Object.values(directories)) { if (!fs.existsSync(dir)) {