mirror of
https://github.com/SillyTavern/SillyTavern.git
synced 2025-01-22 07:26:23 +01:00
Prevent duplicate settings auto-backups
This commit is contained in:
parent
1b6e816525
commit
f53c77b9d8
@ -3,7 +3,7 @@ const path = require('path');
|
||||
const express = require('express');
|
||||
const _ = require('lodash');
|
||||
const writeFileAtomicSync = require('write-file-atomic').sync;
|
||||
const { PUBLIC_DIRECTORIES, SETTINGS_FILE } = require('../constants');
|
||||
const { SETTINGS_FILE } = require('../constants');
|
||||
const { getConfigValue, generateTimestamp, removeOldBackups } = require('../util');
|
||||
const { jsonParser } = require('../express-common');
|
||||
const { getAllUserHandles, getUserDirectories } = require('../users');
|
||||
@ -27,12 +27,12 @@ const AUTOSAVE_FUNCTIONS = new Map();
|
||||
*/
|
||||
function triggerAutoSave(handle) {
|
||||
if (!AUTOSAVE_FUNCTIONS.has(handle)) {
|
||||
const throttledAutoSave = _.throttle(() => backupUserSettings(handle), AUTOSAVE_INTERVAL);
|
||||
const throttledAutoSave = _.throttle(() => backupUserSettings(handle, true), AUTOSAVE_INTERVAL);
|
||||
AUTOSAVE_FUNCTIONS.set(handle, throttledAutoSave);
|
||||
}
|
||||
|
||||
const functionToCall = AUTOSAVE_FUNCTIONS.get(handle);
|
||||
if (functionToCall) {
|
||||
if (functionToCall && typeof functionToCall === 'function') {
|
||||
functionToCall();
|
||||
}
|
||||
}
|
||||
@ -113,7 +113,7 @@ async function backupSettings() {
|
||||
const userHandles = await getAllUserHandles();
|
||||
|
||||
for (const handle of userHandles) {
|
||||
backupUserSettings(handle);
|
||||
backupUserSettings(handle, true);
|
||||
}
|
||||
} catch (err) {
|
||||
console.log('Could not backup settings file', err);
|
||||
@ -123,13 +123,18 @@ async function backupSettings() {
|
||||
/**
|
||||
* Makes a backup of the user's settings file.
|
||||
* @param {string} handle User handle
|
||||
* @param {boolean} preventDuplicates Prevent duplicate backups
|
||||
* @returns {void}
|
||||
*/
|
||||
function backupUserSettings(handle) {
|
||||
function backupUserSettings(handle, preventDuplicates) {
|
||||
const userDirectories = getUserDirectories(handle);
|
||||
const backupFile = path.join(userDirectories.backups, `${getFilePrefix(handle)}${generateTimestamp()}.json`);
|
||||
const sourceFile = path.join(userDirectories.root, SETTINGS_FILE);
|
||||
|
||||
if (preventDuplicates && isDuplicateBackup(handle, sourceFile)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!fs.existsSync(sourceFile)) {
|
||||
return;
|
||||
}
|
||||
@ -138,6 +143,52 @@ function backupUserSettings(handle) {
|
||||
removeOldBackups(userDirectories.backups, `settings_${handle}`);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the backup would be a duplicate.
|
||||
* @param {string} handle User handle
|
||||
* @param {string} sourceFile Source file path
|
||||
* @returns {boolean} True if the backup is a duplicate
|
||||
*/
|
||||
function isDuplicateBackup(handle, sourceFile) {
|
||||
const latestBackup = getLatestBackup(handle);
|
||||
if (!latestBackup) {
|
||||
return false;
|
||||
}
|
||||
return areFilesEqual(latestBackup, sourceFile);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the two files are equal.
|
||||
* @param {string} file1 File path
|
||||
* @param {string} file2 File path
|
||||
*/
|
||||
function areFilesEqual(file1, file2) {
|
||||
if (!fs.existsSync(file1) || !fs.existsSync(file2)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const content1 = fs.readFileSync(file1);
|
||||
const content2 = fs.readFileSync(file2);
|
||||
return content1.toString() === content2.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the latest backup file for a user.
|
||||
* @param {string} handle User handle
|
||||
* @returns {string|null} Latest backup file. Null if no backup exists.
|
||||
*/
|
||||
function getLatestBackup(handle) {
|
||||
const userDirectories = getUserDirectories(handle);
|
||||
const backupFiles = fs.readdirSync(userDirectories.backups)
|
||||
.filter(x => x.startsWith(getFilePrefix(handle)))
|
||||
.map(x => ({ name: x, ctime: fs.statSync(path.join(userDirectories.backups, x)).ctimeMs }));
|
||||
const latestBackup = backupFiles.sort((a, b) => b.ctime - a.ctime)[0]?.name;
|
||||
if (!latestBackup) {
|
||||
return null;
|
||||
}
|
||||
return path.join(userDirectories.backups, latestBackup);
|
||||
}
|
||||
|
||||
const router = express.Router();
|
||||
|
||||
router.post('/save', jsonParser, function (request, response) {
|
||||
@ -265,7 +316,7 @@ router.post('/load-snapshot', jsonParser, async (request, response) => {
|
||||
|
||||
router.post('/make-snapshot', jsonParser, async (request, response) => {
|
||||
try {
|
||||
backupUserSettings(request.user.profile.handle);
|
||||
backupUserSettings(request.user.profile.handle, false);
|
||||
response.sendStatus(204);
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
|
Loading…
Reference in New Issue
Block a user