diff --git a/nextcloud_backup/rootfs/opt/nextcloud_backup/app.js b/nextcloud_backup/rootfs/opt/nextcloud_backup/app.js index 9737c72..cb9c8e0 100644 --- a/nextcloud_backup/rootfs/opt/nextcloud_backup/app.js +++ b/nextcloud_backup/rootfs/opt/nextcloud_backup/app.js @@ -71,7 +71,8 @@ webdav.confIsValid().then( newlog.error("... " + err); } ); - +const settingTool = require('./tools/settingsTools') +settingTool.check(settingTool.getSettings(), true); const cronTools = require("./tools/cronTools"); cronTools.startCron(); diff --git a/nextcloud_backup/rootfs/opt/nextcloud_backup/routes/api.js b/nextcloud_backup/rootfs/opt/nextcloud_backup/routes/api.js index 1ba43c0..ff58228 100644 --- a/nextcloud_backup/rootfs/opt/nextcloud_backup/routes/api.js +++ b/nextcloud_backup/rootfs/opt/nextcloud_backup/routes/api.js @@ -130,18 +130,24 @@ router.post("/new-backup", function (req, res, next) { res.send(); return; } - let name = "Manual-" + moment().format("YYYY-MM-DD_HH-mm"); hassioApiTools - .createNewBackup(name) - .then((id) => { + .getVersion() + .then((version) => { + let name = settingsTools.getFormatedName(true, version); hassioApiTools - .downloadSnapshot(id) - .then(() => { - webdav.uploadFile(id, webdav.getConf().back_dir + pathTools.manual + name + ".tar"); + .createNewBackup(name) + .then((id) => { + hassioApiTools + .downloadSnapshot(id) + .then(() => { + webdav.uploadFile(id, webdav.getConf().back_dir + pathTools.manual + name + ".tar"); + }) + .catch(() => {}); }) .catch(() => {}); }) .catch(() => {}); + res.status(201); res.send(); }); @@ -151,7 +157,7 @@ router.get("/backup-settings", function (req, res, next) { }); router.post("/backup-settings", function (req, res, next) { - if (cronTools.checkConfig(req.body)) { + if (settingsTools.check(req.body)) { settingsTools.setSettings(req.body); cronTools.startCron(); res.send(); diff --git a/nextcloud_backup/rootfs/opt/nextcloud_backup/tools/cronTools.js b/nextcloud_backup/rootfs/opt/nextcloud_backup/tools/cronTools.js index 13ba178..21d6179 100644 --- a/nextcloud_backup/rootfs/opt/nextcloud_backup/tools/cronTools.js +++ b/nextcloud_backup/rootfs/opt/nextcloud_backup/tools/cronTools.js @@ -13,28 +13,6 @@ const CronJob = require("cron").CronJob; const moment = require("moment"); const logger = require("../config/winston"); -function checkConfig(conf) { - if (conf.cron_base != null) { - if (conf.cron_base === "1" || conf.cron_base === "2" || conf.cron_base === "3") { - if (conf.cron_hour != null && conf.cron_hour.match(/\d\d:\d\d/)) { - if (conf.cron_base === "1") return true; - } else return false; - } - - if (conf.cron_base === "2") { - return conf.cron_weekday != null && conf.cron_weekday >= 0 && conf.cron_weekday <= 6; - } - - if (conf.cron_base === "3") { - return conf.cron_month_day != null && conf.cron_month_day >= 1 && conf.cron_month_day <= 28; - } - - if (conf.cron_base === "0") return true; - } else return false; - - return false; -} - function startCron() { let cronContainer = new Singleton().getInstance(); cronContainer.init(); @@ -64,7 +42,7 @@ class CronContainer { this.cronJob.stop(); this.cronJob = null; } - if (!checkConfig(settingsTools.getSettings())) { + if (!settingsTools.check_cron(settingsTools.getSettings())) { logger.warn("No Cron settings available."); return; } @@ -110,15 +88,19 @@ class CronContainer { logger.debug("Cron triggered !"); let status = statusTools.getStatus(); if (status.status === "creating" || status.status === "upload" || status.status === "download") return; - - let name = "Auto-" + moment().format("YYYY-MM-DD_HH-mm"); hassioApiTools - .createNewBackup(name) - .then((id) => { + .getVersion() + .then((version) => { + let name = settingsTools.getFormatedName(false, version) hassioApiTools - .downloadSnapshot(id) - .then(() => { - webdav.uploadFile(id, webdav.getConf().back_dir + pathTools.auto + name + ".tar"); + .createNewBackup(name) + .then((id) => { + hassioApiTools + .downloadSnapshot(id) + .then(() => { + webdav.uploadFile(id, webdav.getConf().back_dir + pathTools.auto + name + ".tar"); + }) + .catch(() => {}); }) .catch(() => {}); }) @@ -149,6 +131,5 @@ class Singleton { } } -exports.checkConfig = checkConfig; exports.startCron = startCron; exports.updatetNextDate = updatetNextDate; diff --git a/nextcloud_backup/rootfs/opt/nextcloud_backup/tools/hassioApiTools.js b/nextcloud_backup/rootfs/opt/nextcloud_backup/tools/hassioApiTools.js index 3e2d40a..9d6a639 100644 --- a/nextcloud_backup/rootfs/opt/nextcloud_backup/tools/hassioApiTools.js +++ b/nextcloud_backup/rootfs/opt/nextcloud_backup/tools/hassioApiTools.js @@ -13,6 +13,40 @@ const logger = require("../config/winston"); const create_snap_timeout = 90 * 60 * 1000; + + +function getVersion() { + return new Promise((resolve, reject) => { + let token = process.env.HASSIO_TOKEN; + let status = statusTools.getStatus(); + let option = { + headers: { "X-HASSIO-KEY": token }, + responseType: "json", + }; + + got("http://hassio/core/info", option) + .then((result) => { + if (status.error_code === 1) { + status.status = "idle"; + status.message = null; + status.error_code = null; + statusTools.setStatus(status); + } + let version = result.body.data.version; + resolve(version); + }) + .catch((error) => { + status.status = "error"; + status.message = "Fail to fetch HA Version (" + error.message + ")"; + status.error_code = 1; + statusTools.setStatus(status); + logger.error(status.message); + reject(error.message); + }); + }); +} + + function getSnapshots() { return new Promise((resolve, reject) => { let token = process.env.HASSIO_TOKEN; @@ -267,6 +301,7 @@ function uploadSnapshot(path) { }); } +exports.getVersion = getVersion; exports.getSnapshots = getSnapshots; exports.downloadSnapshot = downloadSnapshot; exports.createNewBackup = createNewBackup; diff --git a/nextcloud_backup/rootfs/opt/nextcloud_backup/tools/settingsTools.js b/nextcloud_backup/rootfs/opt/nextcloud_backup/tools/settingsTools.js index 134ab9b..624bc7c 100644 --- a/nextcloud_backup/rootfs/opt/nextcloud_backup/tools/settingsTools.js +++ b/nextcloud_backup/rootfs/opt/nextcloud_backup/tools/settingsTools.js @@ -1,7 +1,117 @@ const fs = require("fs"); +const logger = require("../config/winston"); +const moment = require('moment') const settingsPath = "/data/backup_conf.json"; +function check_cron(conf){ + if (conf.cron_base != null) { + if (conf.cron_base === "1" || conf.cron_base === "2" || conf.cron_base === "3") { + if (conf.cron_hour != null && conf.cron_hour.match(/\d\d:\d\d/)) { + if (conf.cron_base === "1") return true; + } else return false; + } + + if (conf.cron_base === "2") { + return conf.cron_weekday != null && conf.cron_weekday >= 0 && conf.cron_weekday <= 6; + } + + if (conf.cron_base === "3") { + return conf.cron_month_day != null && conf.cron_month_day >= 1 && conf.cron_month_day <= 28; + } + + if (conf.cron_base === "0") return true; + } else return false; + + return false; +} + + +function check(conf, fallback = false){ + if(!check_cron(conf)){ + if(fallback){ + logger.warn("Bad value for cron settings, fallback to default ") + conf.cron_base = "0"; + conf.cron_hour = "00:00", + conf.cron_weekday = "0", + conf.cron_month_day = "1" + } + else { + logger.error("Bad value for cron settings") + return false; + } + } + if(conf.name_template == null){ + if(fallback){ + logger.warn("Bad value for 'name_template', fallback to default ") + conf.name_template = "{type}-{ha_version}-{date}_{hour}" + } + else { + logger.error("Bad value for 'name_template'") + return false; + } + } + if(conf.auto_clean_local_keep == null || !/^\d+$/.test(conf.auto_clean_local_keep)){ + + if(fallback){ + logger.warn("Bad value for 'auto_clean_local_keep', fallback to 5 ") + conf.auto_clean_local_keep = "5" + } + else { + logger.error("Bad value for 'auto_clean_local_keep'") + return false; + } + } + if(conf.auto_clean_backup_keep == null || !/^\d+$/.test(conf.auto_clean_backup_keep)){ + if(fallback){ + logger.warn("Bad value for 'auto_clean_backup_keep', fallback to 5 ") + conf.auto_clean_backup_keep = "5" + } + else { + logger.error("Bad value for 'auto_clean_backup_keep'") + return false; + } + } + if(conf.auto_clean_local == null){ + if(fallback){ + logger.warn("Bad value for 'auto_clean_local', fallback to false ") + conf.auto_clean_local = "false" + } + else { + logger.error("Bad value for 'auto_clean_local'") + return false; + } + } + if(conf.auto_clean_backup == null){ + if(fallback){ + logger.warn("Bad value for 'auto_clean_backup', fallback to false ") + conf.auto_clean_backup = "false" + } + else { + logger.error("Bad value for 'auto_clean_backup'") + return false; + } + } + if(fallback){ + setSettings(conf); + } + return true + +} + +function getFormatedName(is_manual, ha_version){ + let setting = getSettings(); + let template = setting.name_template; + template = template.replace('{type_low}', is_manual ? 'manual' : 'auto'); + template = template.replace('{type}', is_manual ? 'Manual' : 'Auto'); + template = template.replace('{ha_version}', ha_version); + let mmt = moment() + template = template.replace('{hour_12}', mmt.format('hh:mmA')); + template = template.replace('{hour}', mmt.format('HH:mm')); + template = template.replace('{date}', mmt.format('YYYY-MM-DD')); + return template +} + function getSettings() { if (!fs.existsSync(settingsPath)) { return {}; @@ -17,3 +127,6 @@ function setSettings(settings) { exports.getSettings = getSettings; exports.setSettings = setSettings; +exports.check = check; +exports.check_cron = check_cron; +exports.getFormatedName = getFormatedName; diff --git a/nextcloud_backup/rootfs/opt/nextcloud_backup/views/index.ejs b/nextcloud_backup/rootfs/opt/nextcloud_backup/views/index.ejs index b6ea4d6..5429201 100644 --- a/nextcloud_backup/rootfs/opt/nextcloud_backup/views/index.ejs +++ b/nextcloud_backup/rootfs/opt/nextcloud_backup/views/index.ejs @@ -598,6 +598,9 @@ changeSelect('#cron-drop-settings', data.cron_base); $('#cron-drop-settings').change(updateDropVisibility); + $('#name-template').val(data.name_template); + $('#name-template + label').removeClass("active"); + $('#name-template + label').addClass("active"); let timepicker = document.querySelector('#timepicker'); $('#timepicker').val(data.cron_hour); @@ -668,9 +671,11 @@ let auto_clean_backup = $("#auto_clean_backup").is(':checked'); let auto_clean_local_keep = $("#local-snap-keep").val(); let auto_clean_backup_keep = $("#backup-snap-keep").val(); + let name_template = $('#name-template').val(); loadingModal.open(); $.post('./api/backup-settings', { + name_template: name_template, cron_base: cron_base, cron_hour: cron_hour, cron_weekday: cron_weekday, diff --git a/nextcloud_backup/rootfs/opt/nextcloud_backup/views/modals/backup-settings-modal.ejs b/nextcloud_backup/rootfs/opt/nextcloud_backup/views/modals/backup-settings-modal.ejs index 98ad4a9..4644767 100644 --- a/nextcloud_backup/rootfs/opt/nextcloud_backup/views/modals/backup-settings-modal.ejs +++ b/nextcloud_backup/rootfs/opt/nextcloud_backup/views/modals/backup-settings-modal.ejs @@ -9,6 +9,15 @@
+
+
+ + + You can find all available variables here +
+
+