mirror of
https://github.com/Tzahi12345/YoutubeDL-Material.git
synced 2026-04-14 15:31:29 +03:00
Added ability to backup remote DB
Added ability to restore DB
This commit is contained in:
@@ -1924,6 +1924,45 @@ app.post('/api/updateTaskSchedule', optionalJwt, async (req, res) => {
|
||||
res.send({success: true});
|
||||
});
|
||||
|
||||
app.post('/api/updateTaskData', optionalJwt, async (req, res) => {
|
||||
const task_key = req.body.task_key;
|
||||
const new_data = req.body.new_data;
|
||||
|
||||
const success = await db_api.updateRecord('tasks', {key: task_key}, {data: new_data});
|
||||
|
||||
res.send({success: success});
|
||||
});
|
||||
|
||||
app.post('/api/getDBBackups', optionalJwt, async (req, res) => {
|
||||
const backup_dir = path.join('appdata', 'db_backup');
|
||||
const db_backups = [];
|
||||
|
||||
const candidate_backups = await utils.recFindByExt(backup_dir, 'bak', null, [], false);
|
||||
for (let i = 0; i < candidate_backups.length; i++) {
|
||||
const candidate_backup = candidate_backups[i];
|
||||
|
||||
// must have specific format
|
||||
if (candidate_backup.split('.').length - 1 !== 4) continue;
|
||||
|
||||
const candidate_backup_path = candidate_backup;
|
||||
const stats = fs.statSync(candidate_backup_path);
|
||||
|
||||
db_backups.push({ name: path.basename(candidate_backup), timestamp: parseInt(candidate_backup.split('.')[2]), size: stats.size, source: candidate_backup.includes('local') ? 'local' : 'remote' });
|
||||
}
|
||||
|
||||
db_backups.sort((a,b) => b.timestamp - a.timestamp);
|
||||
|
||||
res.send({db_backups: db_backups});
|
||||
});
|
||||
|
||||
app.post('/api/restoreDBBackup', optionalJwt, async (req, res) => {
|
||||
const file_name = req.body.file_name;
|
||||
|
||||
const success = await db_api.restoreDB(file_name);
|
||||
|
||||
res.send({success: success});
|
||||
});
|
||||
|
||||
// logs management
|
||||
|
||||
app.post('/api/logs', optionalJwt, async function(req, res) {
|
||||
|
||||
@@ -987,6 +987,52 @@ const createDownloadsRecords = (downloads) => {
|
||||
return new_downloads;
|
||||
}
|
||||
|
||||
exports.backupDB = async () => {
|
||||
const backup_dir = path.join('appdata', 'db_backup');
|
||||
fs.ensureDirSync(backup_dir);
|
||||
const backup_file_name = `${using_local_db ? 'local' : 'remote'}_db.json.${Date.now()/1000}.bak`;
|
||||
const path_to_backups = path.join(backup_dir, backup_file_name);
|
||||
|
||||
logger.verbose(`Backing up ${using_local_db ? 'local' : 'remote'} DB to ${path_to_backups}`);
|
||||
|
||||
const table_to_records = {};
|
||||
for (let i = 0; i < tables_list.length; i++) {
|
||||
const table = tables_list[i];
|
||||
table_to_records[table] = await exports.getRecords(table);
|
||||
}
|
||||
|
||||
fs.writeJsonSync(path_to_backups, table_to_records);
|
||||
|
||||
return backup_file_name;
|
||||
}
|
||||
|
||||
exports.restoreDB = async (file_name) => {
|
||||
const path_to_backup = path.join('appdata', 'db_backup', file_name);
|
||||
|
||||
logger.debug('Reading database backup file.');
|
||||
const table_to_records = fs.readJSONSync(path_to_backup);
|
||||
|
||||
if (!table_to_records) {
|
||||
logger.error(`Failed to restore DB! Backup file '${path_to_backup}' could not be read.`);
|
||||
return false;
|
||||
}
|
||||
|
||||
logger.debug('Clearing database.');
|
||||
await exports.removeAllRecords();
|
||||
|
||||
logger.debug('Database cleared! Beginning restore.');
|
||||
let success = true;
|
||||
for (let i = 0; i < tables_list.length; i++) {
|
||||
const table = tables_list[i];
|
||||
if (!table_to_records[table] || table_to_records[table].length === 0) continue;
|
||||
success &= await exports.bulkInsertRecordsIntoTable(table, table_to_records[table]);
|
||||
}
|
||||
|
||||
logger.debug('Restore finished!');
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
exports.transferDB = async (local_to_remote) => {
|
||||
const table_to_records = {};
|
||||
for (let i = 0; i < tables_list.length; i++) {
|
||||
@@ -996,9 +1042,8 @@ exports.transferDB = async (local_to_remote) => {
|
||||
|
||||
using_local_db = !local_to_remote;
|
||||
if (local_to_remote) {
|
||||
// backup local DB
|
||||
logger.debug('Backup up Local DB...');
|
||||
await fs.copyFile('appdata/local_db.json', `appdata/local_db.json.${Date.now()/1000}.bak`);
|
||||
logger.debug('Backup up DB...');
|
||||
await exports.backupDB();
|
||||
const db_connected = await exports.connectToDB(5, true);
|
||||
if (!db_connected) {
|
||||
logger.error('Failed to transfer database - could not connect to MongoDB. Verify that your connection URL is valid.');
|
||||
|
||||
@@ -7,8 +7,8 @@ const scheduler = require('node-schedule');
|
||||
|
||||
const TASKS = {
|
||||
backup_local_db: {
|
||||
run: utils.backupLocalDB,
|
||||
title: 'Backup Local DB',
|
||||
run: db_api.backupDB,
|
||||
title: 'Backup DB',
|
||||
job: null
|
||||
},
|
||||
missing_files_check: {
|
||||
@@ -81,7 +81,8 @@ const setupTasks = async () => {
|
||||
confirming: false,
|
||||
data: null,
|
||||
error: null,
|
||||
schedule: null
|
||||
schedule: null,
|
||||
options: {}
|
||||
});
|
||||
} else {
|
||||
// reset task if necessary
|
||||
|
||||
@@ -70,6 +70,17 @@ describe('Database', async function() {
|
||||
const success = await db_api.getRecord('test', {test: 'test'});
|
||||
assert(success);
|
||||
});
|
||||
|
||||
it('Restore db', async function() {
|
||||
const db_stats = await db_api.getDBStats();
|
||||
|
||||
const file_name = await db_api.backupDB();
|
||||
await db_api.restoreDB(file_name);
|
||||
|
||||
const new_db_stats = await db_api.getDBStats();
|
||||
|
||||
assert(JSON.stringify(db_stats), JSON.stringify(new_db_stats));
|
||||
});
|
||||
});
|
||||
|
||||
describe('Export', function() {
|
||||
@@ -393,7 +404,7 @@ describe('Tasks', function() {
|
||||
|
||||
await tasks_api.initialize();
|
||||
});
|
||||
it('Backup local db', async function() {
|
||||
it('Backup db', async function() {
|
||||
const backups_original = await utils.recFindByExt('appdata', 'bak');
|
||||
const original_length = backups_original.length;
|
||||
await tasks_api.executeTask('backup_local_db');
|
||||
|
||||
@@ -266,13 +266,7 @@ function getCurrentDownloader() {
|
||||
return details_json['downloader'];
|
||||
}
|
||||
|
||||
async function backupLocalDB() {
|
||||
const path_to_backups = path.join('appdata', 'db_backup');
|
||||
fs.ensureDir(path_to_backups);
|
||||
await fs.copyFile('appdata/local_db.json', path.join(path_to_backups, `local_db.json.${Date.now()/1000}.bak`));
|
||||
}
|
||||
|
||||
async function recFindByExt(base,ext,files,result)
|
||||
async function recFindByExt(base, ext, files, result, recursive = true)
|
||||
{
|
||||
files = files || (await fs.readdir(base))
|
||||
result = result || []
|
||||
@@ -281,6 +275,7 @@ async function recFindByExt(base,ext,files,result)
|
||||
var newbase = path.join(base,file)
|
||||
if ( (await fs.stat(newbase)).isDirectory() )
|
||||
{
|
||||
if (!recursive) continue;
|
||||
result = await recFindByExt(newbase,ext,await fs.readdir(newbase),result)
|
||||
}
|
||||
else
|
||||
@@ -396,7 +391,6 @@ module.exports = {
|
||||
getMatchingCategoryFiles: getMatchingCategoryFiles,
|
||||
addUIDsToCategory: addUIDsToCategory,
|
||||
getCurrentDownloader: getCurrentDownloader,
|
||||
backupLocalDB: backupLocalDB,
|
||||
recFindByExt: recFindByExt,
|
||||
removeFileExtension: removeFileExtension,
|
||||
formatDateString: formatDateString,
|
||||
|
||||
Reference in New Issue
Block a user