mirror of
https://github.com/Sebclem/hassio-nextcloud-backup.git
synced 2024-11-22 09:12:58 +01:00
✏️ Some code clean...
This commit is contained in:
parent
f34154a4f1
commit
d85c04755e
@ -1,8 +1,7 @@
|
|||||||
const appRoot = require("app-root-path");
|
|
||||||
const winston = require("winston");
|
const winston = require("winston");
|
||||||
|
|
||||||
const logger = winston.createLogger({
|
const logger = winston.createLogger({
|
||||||
level: process.env.LOG_LEVEL || 'info' ,
|
level: process.env.LOG_LEVEL || 'info',
|
||||||
format: winston.format.combine(
|
format: winston.format.combine(
|
||||||
winston.format.timestamp({
|
winston.format.timestamp({
|
||||||
format: "YYYY-MM-DD HH:mm:ss",
|
format: "YYYY-MM-DD HH:mm:ss",
|
||||||
|
@ -1,16 +1,12 @@
|
|||||||
const settingsTools = require("./settingsTools");
|
const CronJob = require("cron").CronJob;
|
||||||
|
|
||||||
|
const settingsTools = require("./settingsTools");
|
||||||
const WebdavTools = require("./webdavTools");
|
const WebdavTools = require("./webdavTools");
|
||||||
const webdav = new WebdavTools().getInstance();
|
const webdav = new WebdavTools().getInstance();
|
||||||
|
|
||||||
const hassioApiTools = require("./hassioApiTools");
|
const hassioApiTools = require("./hassioApiTools");
|
||||||
|
|
||||||
const statusTools = require("./status");
|
const statusTools = require("./status");
|
||||||
|
|
||||||
const pathTools = require("./pathTools");
|
const pathTools = require("./pathTools");
|
||||||
|
|
||||||
const CronJob = require("cron").CronJob;
|
|
||||||
const moment = require("moment");
|
|
||||||
const logger = require("../config/winston");
|
const logger = require("../config/winston");
|
||||||
|
|
||||||
function startCron() {
|
function startCron() {
|
||||||
@ -100,21 +96,26 @@ class CronContainer {
|
|||||||
.then(() => {
|
.then(() => {
|
||||||
webdav.uploadFile(id, webdav.getConf().back_dir + pathTools.auto + name + ".tar");
|
webdav.uploadFile(id, webdav.getConf().back_dir + pathTools.auto + name + ".tar");
|
||||||
})
|
})
|
||||||
.catch(() => {});
|
.catch(() => {
|
||||||
|
});
|
||||||
})
|
})
|
||||||
.catch(() => {});
|
.catch(() => {
|
||||||
|
});
|
||||||
})
|
})
|
||||||
.catch(() => {});
|
.catch(() => {
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
_clean() {
|
_clean() {
|
||||||
let autoCleanlocal = settingsTools.getSettings().auto_clean_local;
|
let autoCleanlocal = settingsTools.getSettings().auto_clean_local;
|
||||||
if (autoCleanlocal != null && autoCleanlocal === "true") {
|
if (autoCleanlocal != null && autoCleanlocal === "true") {
|
||||||
hassioApiTools.clean().catch(() => {});
|
hassioApiTools.clean().catch(() => {
|
||||||
|
});
|
||||||
}
|
}
|
||||||
let autoCleanCloud = settingsTools.getSettings().auto_clean_backup;
|
let autoCleanCloud = settingsTools.getSettings().auto_clean_backup;
|
||||||
if (autoCleanCloud != null && autoCleanCloud === "true") {
|
if (autoCleanCloud != null && autoCleanCloud === "true") {
|
||||||
webdav.clean().catch(() => {});
|
webdav.clean().catch(() => {
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -14,7 +14,6 @@ const logger = require("../config/winston");
|
|||||||
const create_snap_timeout = 90 * 60 * 1000;
|
const create_snap_timeout = 90 * 60 * 1000;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
function getVersion() {
|
function getVersion() {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
let token = process.env.HASSIO_TOKEN;
|
let token = process.env.HASSIO_TOKEN;
|
||||||
@ -23,26 +22,26 @@ function getVersion() {
|
|||||||
headers: { "X-HASSIO-KEY": token },
|
headers: { "X-HASSIO-KEY": token },
|
||||||
responseType: "json",
|
responseType: "json",
|
||||||
};
|
};
|
||||||
|
|
||||||
got("http://hassio/core/info", option)
|
got("http://hassio/core/info", option)
|
||||||
.then((result) => {
|
.then((result) => {
|
||||||
if (status.error_code === 1) {
|
if (status.error_code === 1) {
|
||||||
status.status = "idle";
|
status.status = "idle";
|
||||||
status.message = null;
|
status.message = null;
|
||||||
status.error_code = 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);
|
statusTools.setStatus(status);
|
||||||
}
|
logger.error(status.message);
|
||||||
let version = result.body.data.version;
|
reject(error.message);
|
||||||
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);
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -54,61 +53,63 @@ function getAddonList() {
|
|||||||
headers: { "X-HASSIO-KEY": token },
|
headers: { "X-HASSIO-KEY": token },
|
||||||
responseType: "json",
|
responseType: "json",
|
||||||
};
|
};
|
||||||
|
|
||||||
got("http://hassio/addons", option)
|
got("http://hassio/addons", option)
|
||||||
.then((result) => {
|
.then((result) => {
|
||||||
if (status.error_code === 1) {
|
if (status.error_code === 1) {
|
||||||
status.status = "idle";
|
status.status = "idle";
|
||||||
status.message = null;
|
status.message = null;
|
||||||
status.error_code = null;
|
status.error_code = null;
|
||||||
|
statusTools.setStatus(status);
|
||||||
|
}
|
||||||
|
let addons = result.body.data.addons;
|
||||||
|
let installed = [];
|
||||||
|
for (let index in addons) {
|
||||||
|
let current = addons[index];
|
||||||
|
if (current.installed === true) {
|
||||||
|
installed.push({ slug: current.slug, name: current.name })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
installed.sort((a, b) => {
|
||||||
|
let textA = a.name.toUpperCase();
|
||||||
|
let textB = b.name.toUpperCase();
|
||||||
|
return (textA < textB) ? -1 : (textA > textB) ? 1 : 0;
|
||||||
|
});
|
||||||
|
resolve(installed);
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
status.status = "error";
|
||||||
|
status.message = "Fail to fetch addons list (" + error.message + ")";
|
||||||
|
status.error_code = 1;
|
||||||
statusTools.setStatus(status);
|
statusTools.setStatus(status);
|
||||||
}
|
logger.error(status.message);
|
||||||
let addons = result.body.data.addons;
|
reject(error.message);
|
||||||
let instaled = [];
|
|
||||||
for(let index in addons){
|
|
||||||
let current = addons[index];
|
|
||||||
if(current.installed == true){
|
|
||||||
instaled.push({slug:current.slug, name: current.name})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
instaled.sort((a,b)=>{
|
|
||||||
var textA = a.name.toUpperCase();
|
|
||||||
var textB = b.name.toUpperCase();
|
|
||||||
return (textA < textB) ? -1 : (textA > textB) ? 1 : 0;
|
|
||||||
});
|
});
|
||||||
resolve(instaled);
|
|
||||||
})
|
|
||||||
.catch((error) => {
|
|
||||||
status.status = "error";
|
|
||||||
status.message = "Fail to fetch addons list (" + error.message + ")";
|
|
||||||
status.error_code = 1;
|
|
||||||
statusTools.setStatus(status);
|
|
||||||
logger.error(status.message);
|
|
||||||
reject(error.message);
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function getAddonToBackup(){
|
function getAddonToBackup() {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
let excluded_addon = settingsTools.getSettings().exclude_addon;
|
let excluded_addon = settingsTools.getSettings().exclude_addon;
|
||||||
getAddonList().then((all_addon)=>{
|
getAddonList()
|
||||||
let slugs = [];
|
.then((all_addon) => {
|
||||||
for(let i in all_addon){
|
let slugs = [];
|
||||||
if(!excluded_addon.includes(all_addon[i].slug))
|
for (let i in all_addon) {
|
||||||
slugs.push(all_addon[i].slug)
|
if (!excluded_addon.includes(all_addon[i].slug))
|
||||||
}
|
slugs.push(all_addon[i].slug)
|
||||||
resolve(slugs)
|
}
|
||||||
}).catch(()=>reject());
|
resolve(slugs)
|
||||||
});
|
})
|
||||||
|
.catch(() => reject());
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function getFolderList(){
|
function getFolderList() {
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
name: "Homme Assistant configuration",
|
name: "Homme Assistant configuration",
|
||||||
slug: "homeassistant"
|
slug: "homeassistant"
|
||||||
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "SSL",
|
name: "SSL",
|
||||||
@ -125,16 +126,16 @@ function getFolderList(){
|
|||||||
{
|
{
|
||||||
name: "Local add-ons",
|
name: "Local add-ons",
|
||||||
slug: "addons/local"
|
slug: "addons/local"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
function getFolderToBackup(){
|
function getFolderToBackup() {
|
||||||
let excluded_folder = settingsTools.getSettings().exclude_folder;
|
let excluded_folder = settingsTools.getSettings().exclude_folder;
|
||||||
let all_folder = getFolderList()
|
let all_folder = getFolderList()
|
||||||
let slugs = [];
|
let slugs = [];
|
||||||
for(let i in all_folder){
|
for (let i in all_folder) {
|
||||||
if(!excluded_folder.includes(all_folder[i].slug))
|
if (!excluded_folder.includes(all_folder[i].slug))
|
||||||
slugs.push(all_folder[i].slug)
|
slugs.push(all_folder[i].slug)
|
||||||
}
|
}
|
||||||
return slugs;
|
return slugs;
|
||||||
@ -148,26 +149,26 @@ function getSnapshots() {
|
|||||||
headers: { "X-HASSIO-KEY": token },
|
headers: { "X-HASSIO-KEY": token },
|
||||||
responseType: "json",
|
responseType: "json",
|
||||||
};
|
};
|
||||||
|
|
||||||
got("http://hassio/snapshots", option)
|
got("http://hassio/snapshots", option)
|
||||||
.then((result) => {
|
.then((result) => {
|
||||||
if (status.error_code === 1) {
|
if (status.error_code === 1) {
|
||||||
status.status = "idle";
|
status.status = "idle";
|
||||||
status.message = null;
|
status.message = null;
|
||||||
status.error_code = null;
|
status.error_code = null;
|
||||||
|
statusTools.setStatus(status);
|
||||||
|
}
|
||||||
|
let snaps = result.body.data.snapshots;
|
||||||
|
resolve(snaps);
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
status.status = "error";
|
||||||
|
status.message = "Fail to fetch Hassio snapshots (" + error.message + ")";
|
||||||
|
status.error_code = 1;
|
||||||
statusTools.setStatus(status);
|
statusTools.setStatus(status);
|
||||||
}
|
logger.error(status.message);
|
||||||
let snaps = result.body.data.snapshots;
|
reject(error.message);
|
||||||
resolve(snaps);
|
});
|
||||||
})
|
|
||||||
.catch((error) => {
|
|
||||||
status.status = "error";
|
|
||||||
status.message = "Fail to fetch Hassio snapshots (" + error.message + ")";
|
|
||||||
status.error_code = 1;
|
|
||||||
statusTools.setStatus(status);
|
|
||||||
logger.error(status.message);
|
|
||||||
reject(error.message);
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -180,74 +181,71 @@ function downloadSnapshot(id) {
|
|||||||
let token = process.env.HASSIO_TOKEN;
|
let token = process.env.HASSIO_TOKEN;
|
||||||
let status = statusTools.getStatus();
|
let status = statusTools.getStatus();
|
||||||
checkSnap(id)
|
checkSnap(id)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
status.status = "download";
|
status.status = "download";
|
||||||
status.progress = 0;
|
status.progress = 0;
|
||||||
statusTools.setStatus(status);
|
|
||||||
let option = {
|
|
||||||
headers: { "X-HASSIO-KEY": token },
|
|
||||||
};
|
|
||||||
|
|
||||||
pipeline(
|
|
||||||
got.stream.get(`http://hassio/snapshots/${id}/download`, option).on("downloadProgress", (e) => {
|
|
||||||
let percent = Math.round(e.percent * 100) / 100;
|
|
||||||
if (status.progress != percent) {
|
|
||||||
status.progress = percent;
|
|
||||||
statusTools.setStatus(status);
|
|
||||||
}
|
|
||||||
}),
|
|
||||||
stream
|
|
||||||
)
|
|
||||||
.then((res) => {
|
|
||||||
logger.info("Download success !");
|
|
||||||
status.progress = 1;
|
|
||||||
statusTools.setStatus(status);
|
statusTools.setStatus(status);
|
||||||
logger.debug("Snapshot dl size : " + fs.statSync(tmp_file).size / 1024 / 1024);
|
let option = {
|
||||||
resolve();
|
headers: { "X-HASSIO-KEY": token },
|
||||||
|
};
|
||||||
|
|
||||||
|
pipeline(
|
||||||
|
got.stream.get(`http://hassio/snapshots/${id}/download`, option)
|
||||||
|
.on("downloadProgress", (e) => {
|
||||||
|
let percent = Math.round(e.percent * 100) / 100;
|
||||||
|
if (status.progress !== percent) {
|
||||||
|
status.progress = percent;
|
||||||
|
statusTools.setStatus(status);
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
stream
|
||||||
|
)
|
||||||
|
.then((res) => {
|
||||||
|
logger.info("Download success !");
|
||||||
|
status.progress = 1;
|
||||||
|
statusTools.setStatus(status);
|
||||||
|
logger.debug("Snapshot dl size : " + fs.statSync(tmp_file).size / 1024 / 1024);
|
||||||
|
resolve();
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
fs.unlinkSync(tmp_file);
|
||||||
|
status.status = "error";
|
||||||
|
status.message = "Fail to download Hassio snapshot (" + err.message + ")";
|
||||||
|
status.error_code = 7;
|
||||||
|
statusTools.setStatus(status);
|
||||||
|
logger.error(status.message);
|
||||||
|
reject(err.message);
|
||||||
|
});
|
||||||
})
|
})
|
||||||
.catch((err) => {
|
.catch((err) => {
|
||||||
fs.unlinkSync(tmp_file);
|
|
||||||
status.status = "error";
|
status.status = "error";
|
||||||
status.message = "Fail to download Hassio snapshot (" + err.message + ")";
|
status.message = "Fail to download Hassio snapshot. Not found ?";
|
||||||
status.error_code = 7;
|
status.error_code = 7;
|
||||||
statusTools.setStatus(status);
|
statusTools.setStatus(status);
|
||||||
logger.error(status.message);
|
logger.error(status.message);
|
||||||
reject(err.message);
|
reject();
|
||||||
});
|
});
|
||||||
})
|
|
||||||
.catch((err) => {
|
|
||||||
status.status = "error";
|
|
||||||
status.message = "Fail to download Hassio snapshot. Not found ?";
|
|
||||||
status.error_code = 7;
|
|
||||||
statusTools.setStatus(status);
|
|
||||||
logger.error(status.message);
|
|
||||||
reject();
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function dellSnap(id) {
|
function dellSnap(id) {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
checkSnap(id)
|
checkSnap(id)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
let token = process.env.HASSIO_TOKEN;
|
let token = process.env.HASSIO_TOKEN;
|
||||||
|
|
||||||
let option = {
|
let option = {
|
||||||
headers: { "X-HASSIO-KEY": token },
|
headers: { "X-HASSIO-KEY": token },
|
||||||
responseType: "json",
|
responseType: "json",
|
||||||
};
|
};
|
||||||
|
|
||||||
got.post(`http://hassio/snapshots/${id}/remove`, option)
|
got.post(`http://hassio/snapshots/${id}/remove`, option)
|
||||||
.then((result) => {
|
.then(() => resolve())
|
||||||
resolve();
|
.catch(() => reject());
|
||||||
})
|
})
|
||||||
.catch((error) => {
|
.catch(() => {
|
||||||
reject();
|
reject();
|
||||||
});
|
});
|
||||||
})
|
|
||||||
.catch(() => {
|
|
||||||
reject();
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -258,15 +256,13 @@ function checkSnap(id) {
|
|||||||
headers: { "X-HASSIO-KEY": token },
|
headers: { "X-HASSIO-KEY": token },
|
||||||
responseType: "json",
|
responseType: "json",
|
||||||
};
|
};
|
||||||
|
|
||||||
got(`http://hassio/snapshots/${id}/info`, option)
|
got(`http://hassio/snapshots/${id}/info`, option)
|
||||||
.then((result) => {
|
.then((result) => {
|
||||||
logger.debug(`Snapshot size: ${result.body.data.size}`);
|
logger.debug(`Snapshot size: ${result.body.data.size}`);
|
||||||
resolve();
|
resolve();
|
||||||
})
|
})
|
||||||
.catch((error) => {
|
.catch(() => reject());
|
||||||
reject();
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -278,35 +274,35 @@ function createNewBackup(name) {
|
|||||||
statusTools.setStatus(status);
|
statusTools.setStatus(status);
|
||||||
logger.info("Creating new snapshot...");
|
logger.info("Creating new snapshot...");
|
||||||
let token = process.env.HASSIO_TOKEN;
|
let token = process.env.HASSIO_TOKEN;
|
||||||
getAddonToBackup().then((addons)=>{
|
getAddonToBackup().then((addons) => {
|
||||||
let folders = getFolderToBackup();
|
let folders = getFolderToBackup();
|
||||||
let option = {
|
let option = {
|
||||||
headers: { "X-HASSIO-KEY": token },
|
headers: { "X-HASSIO-KEY": token },
|
||||||
responseType: "json",
|
responseType: "json",
|
||||||
timeout: create_snap_timeout,
|
timeout: create_snap_timeout,
|
||||||
json: {
|
json: {
|
||||||
name: name,
|
name: name,
|
||||||
addons: addons,
|
addons: addons,
|
||||||
folders: folders
|
folders: folders
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
got.post(`http://hassio/snapshots/new/partial`, option)
|
got.post(`http://hassio/snapshots/new/partial`, option)
|
||||||
.then((result) => {
|
.then((result) => {
|
||||||
logger.info(`Snapshot created with id ${result.body.data.slug}`);
|
logger.info(`Snapshot created with id ${result.body.data.slug}`);
|
||||||
resolve(result.body.data.slug);
|
resolve(result.body.data.slug);
|
||||||
})
|
})
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
status.status = "error";
|
status.status = "error";
|
||||||
status.message = "Can't create new snapshot (" + error.message + ")";
|
status.message = "Can't create new snapshot (" + error.message + ")";
|
||||||
status.error_code = 5;
|
status.error_code = 5;
|
||||||
statusTools.setStatus(status);
|
statusTools.setStatus(status);
|
||||||
logger.error(status.message);
|
logger.error(status.message);
|
||||||
reject(status.message);
|
reject(status.message);
|
||||||
});
|
});
|
||||||
|
|
||||||
}).catch(reject);
|
}).catch(reject);
|
||||||
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -315,25 +311,26 @@ function clean() {
|
|||||||
if (limit == null) limit = 5;
|
if (limit == null) limit = 5;
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
getSnapshots()
|
getSnapshots()
|
||||||
.then(async (snaps) => {
|
.then(async (snaps) => {
|
||||||
if (snaps.length < limit) {
|
if (snaps.length < limit) {
|
||||||
|
resolve();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
snaps.sort((a, b) => {
|
||||||
|
if (moment(a.date).isBefore(moment(b.date))) return 1;
|
||||||
|
else
|
||||||
|
return -1;
|
||||||
|
});
|
||||||
|
let toDel = snaps.slice(limit);
|
||||||
|
for (let i in toDel) {
|
||||||
|
await dellSnap(toDel[i].slug);
|
||||||
|
}
|
||||||
|
logger.info("Local clean done.");
|
||||||
resolve();
|
resolve();
|
||||||
return;
|
})
|
||||||
}
|
.catch(() => {
|
||||||
snaps.sort((a, b) => {
|
reject();
|
||||||
if (moment(a.date).isBefore(moment(b.date))) return 1;
|
|
||||||
else return -1;
|
|
||||||
});
|
});
|
||||||
let toDel = snaps.slice(limit);
|
|
||||||
for (let i in toDel) {
|
|
||||||
await dellSnap(toDel[i].slug);
|
|
||||||
}
|
|
||||||
logger.info("Local clean done.");
|
|
||||||
resolve();
|
|
||||||
})
|
|
||||||
.catch(() => {
|
|
||||||
reject();
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -348,58 +345,58 @@ function uploadSnapshot(path) {
|
|||||||
logger.info("Uploading backup...");
|
logger.info("Uploading backup...");
|
||||||
let stream = fs.createReadStream(path);
|
let stream = fs.createReadStream(path);
|
||||||
let token = process.env.HASSIO_TOKEN;
|
let token = process.env.HASSIO_TOKEN;
|
||||||
|
|
||||||
let form = new FormData();
|
let form = new FormData();
|
||||||
form.append("file", stream);
|
form.append("file", stream);
|
||||||
|
|
||||||
let options = {
|
let options = {
|
||||||
body: form,
|
body: form,
|
||||||
username: this.username,
|
username: this.username,
|
||||||
password: this.password,
|
password: this.password,
|
||||||
headers: { "X-HASSIO-KEY": token },
|
headers: { "X-HASSIO-KEY": token },
|
||||||
};
|
};
|
||||||
|
|
||||||
got.stream
|
got.stream
|
||||||
.post(`http://hassio/snapshots/new/upload`, options)
|
.post(`http://hassio/snapshots/new/upload`, options)
|
||||||
.on("uploadProgress", (e) => {
|
.on("uploadProgress", (e) => {
|
||||||
let percent = e.percent;
|
let percent = e.percent;
|
||||||
if (status.progress != percent) {
|
if (status.progress !== percent) {
|
||||||
status.progress = percent;
|
status.progress = percent;
|
||||||
statusTools.setStatus(status);
|
statusTools.setStatus(status);
|
||||||
}
|
}
|
||||||
if (percent >= 1) {
|
if (percent >= 1) {
|
||||||
logger.info("Upload done...");
|
logger.info("Upload done...");
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.on("response", (res) => {
|
.on("response", (res) => {
|
||||||
if (res.statusCode != 200) {
|
if (res.statusCode !== 200) {
|
||||||
|
status.status = "error";
|
||||||
|
status.error_code = 4;
|
||||||
|
status.message = `Fail to upload backup to home assitant (Status code: ${res.statusCode})!`;
|
||||||
|
statusTools.setStatus(status);
|
||||||
|
logger.error(status.message);
|
||||||
|
fs.unlinkSync(path);
|
||||||
|
reject(status.message);
|
||||||
|
} else {
|
||||||
|
logger.info(`...Upload finish ! (status: ${res.statusCode})`);
|
||||||
|
status.status = "idle";
|
||||||
|
status.progress = -1;
|
||||||
|
status.message = null;
|
||||||
|
status.error_code = null;
|
||||||
|
statusTools.setStatus(status);
|
||||||
|
fs.unlinkSync(path);
|
||||||
|
resolve();
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.on("error", (err) => {
|
||||||
|
fs.unlinkSync(path);
|
||||||
status.status = "error";
|
status.status = "error";
|
||||||
status.error_code = 4;
|
status.error_code = 4;
|
||||||
status.message = `Fail to upload backup to home assitant (Status code: ${res.statusCode})!`;
|
status.message = `Fail to upload backup to home assitant (${err}) !`;
|
||||||
statusTools.setStatus(status);
|
statusTools.setStatus(status);
|
||||||
logger.error(status.message);
|
logger.error(status.message);
|
||||||
fs.unlinkSync(path);
|
|
||||||
reject(status.message);
|
reject(status.message);
|
||||||
} else {
|
});
|
||||||
logger.info(`...Upload finish ! (status: ${res.statusCode})`);
|
|
||||||
status.status = "idle";
|
|
||||||
status.progress = -1;
|
|
||||||
status.message = null;
|
|
||||||
status.error_code = null;
|
|
||||||
statusTools.setStatus(status);
|
|
||||||
fs.unlinkSync(path);
|
|
||||||
resolve();
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.on("error", (err) => {
|
|
||||||
fs.unlinkSync(path);
|
|
||||||
status.status = "error";
|
|
||||||
status.error_code = 4;
|
|
||||||
status.message = `Fail to upload backup to home assitant (${err}) !`;
|
|
||||||
statusTools.setStatus(status);
|
|
||||||
logger.error(status.message);
|
|
||||||
reject(status.message);
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
let default_root = "/Hassio Backup/";
|
let default_root = "/Hassio Backup/";
|
||||||
exports.default_root = default_root;
|
exports.default_root = default_root;
|
||||||
exports.manual = "Manual/";
|
exports.manual = "Manual/";
|
||||||
exports.auto = "Auto/";
|
exports.auto = "Auto/";
|
||||||
|
@ -4,135 +4,127 @@ const moment = require('moment')
|
|||||||
|
|
||||||
const settingsPath = "/data/backup_conf.json";
|
const settingsPath = "/data/backup_conf.json";
|
||||||
|
|
||||||
function check_cron(conf){
|
function check_cron(conf) {
|
||||||
if (conf.cron_base != null) {
|
if (conf.cron_base != null) {
|
||||||
if (conf.cron_base === "1" || conf.cron_base === "2" || conf.cron_base === "3") {
|
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_hour != null && conf.cron_hour.match(/\d\d:\d\d/)) {
|
||||||
if (conf.cron_base === "1") return true;
|
if (conf.cron_base === "1") return true;
|
||||||
} else return false;
|
} else return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (conf.cron_base === "2") {
|
if (conf.cron_base === "2") {
|
||||||
return conf.cron_weekday != null && conf.cron_weekday >= 0 && conf.cron_weekday <= 6;
|
return conf.cron_weekday != null && conf.cron_weekday >= 0 && conf.cron_weekday <= 6;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (conf.cron_base === "3") {
|
if (conf.cron_base === "3") {
|
||||||
return conf.cron_month_day != null && conf.cron_month_day >= 1 && conf.cron_month_day <= 28;
|
return conf.cron_month_day != null && conf.cron_month_day >= 1 && conf.cron_month_day <= 28;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (conf.cron_base === "0") return true;
|
if (conf.cron_base === "0") return true;
|
||||||
} else return false;
|
} else return false;
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function check(conf, fallback = false){
|
function check(conf, fallback = false) {
|
||||||
let needSave = false;
|
let needSave = false;
|
||||||
if(!check_cron(conf)){
|
if (!check_cron(conf)) {
|
||||||
if(fallback){
|
if (fallback) {
|
||||||
logger.warn("Bad value for cron settings, fallback to default ")
|
logger.warn("Bad value for cron settings, fallback to default ")
|
||||||
conf.cron_base = "0";
|
conf.cron_base = "0";
|
||||||
conf.cron_hour = "00:00",
|
conf.cron_hour = "00:00",
|
||||||
conf.cron_weekday = "0",
|
conf.cron_weekday = "0",
|
||||||
conf.cron_month_day = "1"
|
conf.cron_month_day = "1"
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
logger.error("Bad value for cron settings")
|
logger.error("Bad value for cron settings")
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(conf.name_template == null){
|
if (conf.name_template == null) {
|
||||||
if(fallback){
|
if (fallback) {
|
||||||
logger.warn("Bad value for 'name_template', fallback to default ")
|
logger.warn("Bad value for 'name_template', fallback to default ")
|
||||||
conf.name_template = "{type}-{ha_version}-{date}_{hour}"
|
conf.name_template = "{type}-{ha_version}-{date}_{hour}"
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
logger.error("Bad value for 'name_template'")
|
logger.error("Bad value for 'name_template'")
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(conf.auto_clean_local_keep == null || !/^\d+$/.test(conf.auto_clean_local_keep)){
|
if (conf.auto_clean_local_keep == null || !/^\d+$/.test(conf.auto_clean_local_keep)) {
|
||||||
|
|
||||||
if(fallback){
|
if (fallback) {
|
||||||
logger.warn("Bad value for 'auto_clean_local_keep', fallback to 5 ")
|
logger.warn("Bad value for 'auto_clean_local_keep', fallback to 5 ")
|
||||||
conf.auto_clean_local_keep = "5"
|
conf.auto_clean_local_keep = "5"
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
logger.error("Bad value for 'auto_clean_local_keep'")
|
logger.error("Bad value for 'auto_clean_local_keep'")
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(conf.auto_clean_backup_keep == null || !/^\d+$/.test(conf.auto_clean_backup_keep)){
|
if (conf.auto_clean_backup_keep == null || !/^\d+$/.test(conf.auto_clean_backup_keep)) {
|
||||||
if(fallback){
|
if (fallback) {
|
||||||
logger.warn("Bad value for 'auto_clean_backup_keep', fallback to 5 ")
|
logger.warn("Bad value for 'auto_clean_backup_keep', fallback to 5 ")
|
||||||
conf.auto_clean_backup_keep = "5"
|
conf.auto_clean_backup_keep = "5"
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
logger.error("Bad value for 'auto_clean_backup_keep'")
|
logger.error("Bad value for 'auto_clean_backup_keep'")
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(conf.auto_clean_local == null){
|
if (conf.auto_clean_local == null) {
|
||||||
if(fallback){
|
if (fallback) {
|
||||||
logger.warn("Bad value for 'auto_clean_local', fallback to false ")
|
logger.warn("Bad value for 'auto_clean_local', fallback to false ")
|
||||||
conf.auto_clean_local = "false"
|
conf.auto_clean_local = "false"
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
logger.error("Bad value for 'auto_clean_local'")
|
logger.error("Bad value for 'auto_clean_local'")
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(conf.auto_clean_backup == null){
|
if (conf.auto_clean_backup == null) {
|
||||||
if(fallback){
|
if (fallback) {
|
||||||
logger.warn("Bad value for 'auto_clean_backup', fallback to false ")
|
logger.warn("Bad value for 'auto_clean_backup', fallback to false ")
|
||||||
conf.auto_clean_backup = "false"
|
conf.auto_clean_backup = "false"
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
logger.error("Bad value for 'auto_clean_backup'")
|
logger.error("Bad value for 'auto_clean_backup'")
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(conf.exclude_addon == null){
|
if (conf.exclude_addon == null) {
|
||||||
if(fallback){
|
if (fallback) {
|
||||||
logger.warn("Bad value for 'exclude_addon', fallback to [] ")
|
logger.warn("Bad value for 'exclude_addon', fallback to [] ")
|
||||||
conf.exclude_addon = []
|
conf.exclude_addon = []
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
logger.error("Bad value for 'exclude_addon'")
|
logger.error("Bad value for 'exclude_addon'")
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(conf.exclude_folder == null){
|
if (conf.exclude_folder == null) {
|
||||||
if(fallback){
|
if (fallback) {
|
||||||
logger.warn("Bad value for 'exclude_folder', fallback to [] ")
|
logger.warn("Bad value for 'exclude_folder', fallback to [] ")
|
||||||
conf.exclude_folder = []
|
conf.exclude_folder = []
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
logger.error("Bad value for 'exclude_folder'")
|
logger.error("Bad value for 'exclude_folder'")
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!Array.isArray(conf.exclude_folder)){
|
if (!Array.isArray(conf.exclude_folder)) {
|
||||||
logger.debug("exclude_folder is not array (Empty value), reset...");
|
logger.debug("exclude_folder is not array (Empty value), reset...");
|
||||||
conf.exclude_folder = []
|
conf.exclude_folder = []
|
||||||
needSave = true;
|
needSave = true;
|
||||||
}
|
}
|
||||||
if(!Array.isArray(conf.exclude_addon)){
|
if (!Array.isArray(conf.exclude_addon)) {
|
||||||
logger.debug("exclude_addon is not array (Empty value), reset...");
|
logger.debug("exclude_addon is not array (Empty value), reset...");
|
||||||
conf.exclude_addon = []
|
conf.exclude_addon = []
|
||||||
needSave = true;
|
needSave = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(fallback || needSave){
|
if (fallback || needSave) {
|
||||||
setSettings(conf);
|
setSettings(conf);
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function getFormatedName(is_manual, ha_version){
|
function getFormatedName(is_manual, ha_version) {
|
||||||
let setting = getSettings();
|
let setting = getSettings();
|
||||||
let template = setting.name_template;
|
let template = setting.name_template;
|
||||||
template = template.replace('{type_low}', is_manual ? 'manual' : 'auto');
|
template = template.replace('{type_low}', is_manual ? 'manual' : 'auto');
|
||||||
@ -142,7 +134,7 @@ function getFormatedName(is_manual, ha_version){
|
|||||||
template = template.replace('{hour_12}', mmt.format('hhmmA'));
|
template = template.replace('{hour_12}', mmt.format('hhmmA'));
|
||||||
template = template.replace('{hour}', mmt.format('HHmm'));
|
template = template.replace('{hour}', mmt.format('HHmm'));
|
||||||
template = template.replace('{date}', mmt.format('YYYY-MM-DD'));
|
template = template.replace('{date}', mmt.format('YYYY-MM-DD'));
|
||||||
return template
|
return template
|
||||||
}
|
}
|
||||||
|
|
||||||
function getSettings() {
|
function getSettings() {
|
||||||
|
@ -36,7 +36,11 @@ class WebdavTools {
|
|||||||
this.password = password;
|
this.password = password;
|
||||||
let agent_option = ssl === "true" ? { rejectUnauthorized: accept_selfsigned_cert === "false" } : {};
|
let agent_option = ssl === "true" ? { rejectUnauthorized: accept_selfsigned_cert === "false" } : {};
|
||||||
try {
|
try {
|
||||||
this.client = createClient(this.baseUrl, { username: username, password: password, httpsAgent: new https.Agent(agent_option) });
|
this.client = createClient(this.baseUrl, {
|
||||||
|
username: username,
|
||||||
|
password: password,
|
||||||
|
httpsAgent: new https.Agent(agent_option)
|
||||||
|
});
|
||||||
|
|
||||||
this.client
|
this.client
|
||||||
.getDirectoryContents("/")
|
.getDirectoryContents("/")
|
||||||
@ -72,6 +76,7 @@ class WebdavTools {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async __createRoot() {
|
async __createRoot() {
|
||||||
let root_splited = this.getConf().back_dir.split("/").splice(1);
|
let root_splited = this.getConf().back_dir.split("/").splice(1);
|
||||||
let path = "/";
|
let path = "/";
|
||||||
@ -91,25 +96,25 @@ class WebdavTools {
|
|||||||
|
|
||||||
initFolder() {
|
initFolder() {
|
||||||
return new Promise((resolve) => {
|
return new Promise((resolve) => {
|
||||||
this.__createRoot()
|
this.__createRoot().catch((err) => {
|
||||||
.catch((err) => {
|
logger.error(err);
|
||||||
logger.error(err);
|
}).then(() => {
|
||||||
})
|
this.client.createDirectory(this.getConf().back_dir + pathTools.auto)
|
||||||
.then(() => {
|
.catch(() => {
|
||||||
this.client
|
})
|
||||||
.createDirectory(this.getConf().back_dir + pathTools.auto)
|
.then(() => {
|
||||||
.catch(() => {})
|
this.client
|
||||||
.then(() => {
|
.createDirectory(this.getConf().back_dir + pathTools.manual)
|
||||||
this.client
|
.catch(() => {
|
||||||
.createDirectory(this.getConf().back_dir + pathTools.manual)
|
})
|
||||||
.catch(() => {})
|
.then(() => {
|
||||||
.then(() => {
|
resolve();
|
||||||
resolve();
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if theh webdav config is valid, if yes, start init of webdav client
|
* Check if theh webdav config is valid, if yes, start init of webdav client
|
||||||
*/
|
*/
|
||||||
@ -177,7 +182,8 @@ class WebdavTools {
|
|||||||
if (fs.existsSync(configPath)) {
|
if (fs.existsSync(configPath)) {
|
||||||
let content = JSON.parse(fs.readFileSync(configPath));
|
let content = JSON.parse(fs.readFileSync(configPath));
|
||||||
return content;
|
return content;
|
||||||
} else return null;
|
} else
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
setConf(conf) {
|
setConf(conf) {
|
||||||
@ -194,7 +200,8 @@ class WebdavTools {
|
|||||||
.catch((err) => {
|
.catch((err) => {
|
||||||
reject(err);
|
reject(err);
|
||||||
});
|
});
|
||||||
} else this._startUpload(id, path);
|
} else
|
||||||
|
this._startUpload(id, path);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -237,7 +244,7 @@ class WebdavTools {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
.on("response", (res) => {
|
.on("response", (res) => {
|
||||||
if (res.statusCode != 201 && res.statusCode != 204) {
|
if (res.statusCode !== 201 && res.statusCode !== 204) {
|
||||||
status.status = "error";
|
status.status = "error";
|
||||||
status.error_code = 4;
|
status.error_code = 4;
|
||||||
status.message = `Fail to upload snapshot to nextcloud (Status code: ${res.statusCode})!`;
|
status.message = `Fail to upload snapshot to nextcloud (Status code: ${res.statusCode})!`;
|
||||||
@ -255,11 +262,11 @@ class WebdavTools {
|
|||||||
statusTools.setStatus(status);
|
statusTools.setStatus(status);
|
||||||
cleanTempFolder();
|
cleanTempFolder();
|
||||||
let autoCleanCloud = settingsTools.getSettings().auto_clean_backup;
|
let autoCleanCloud = settingsTools.getSettings().auto_clean_backup;
|
||||||
if (autoCleanCloud != null && autoCleanCloud == "true") {
|
if (autoCleanCloud != null && autoCleanCloud === "true") {
|
||||||
this.clean().catch();
|
this.clean().catch();
|
||||||
}
|
}
|
||||||
let autoCleanlocal = settingsTools.getSettings().auto_clean_local;
|
let autoCleanlocal = settingsTools.getSettings().auto_clean_local;
|
||||||
if (autoCleanlocal != null && autoCleanlocal == "true") {
|
if (autoCleanlocal != null && autoCleanlocal === "true") {
|
||||||
hassioApiTools.clean();
|
hassioApiTools.clean();
|
||||||
}
|
}
|
||||||
resolve();
|
resolve();
|
||||||
@ -296,6 +303,7 @@ class WebdavTools {
|
|||||||
.catch(() => reject());
|
.catch(() => reject());
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
_startDownload(path) {
|
_startDownload(path) {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
let status = statusTools.getStatus();
|
let status = statusTools.getStatus();
|
||||||
@ -321,32 +329,31 @@ class WebdavTools {
|
|||||||
logger.debug(`...URI: ${encodeURI(this.baseUrl.replace(this.host, 'host.hiden') + path)}`);
|
logger.debug(`...URI: ${encodeURI(this.baseUrl.replace(this.host, 'host.hiden') + path)}`);
|
||||||
logger.debug(`...rejectUnauthorized: ${options["https"]["rejectUnauthorized"]}`);
|
logger.debug(`...rejectUnauthorized: ${options["https"]["rejectUnauthorized"]}`);
|
||||||
pipeline(
|
pipeline(
|
||||||
got.stream.get(encodeURI(this.baseUrl + path), options).on("downloadProgress", (e) => {
|
got.stream.get(encodeURI(this.baseUrl + path), options)
|
||||||
let percent = Math.round(e.percent * 100) / 100;
|
.on("downloadProgress", (e) => {
|
||||||
if (status.progress != percent) {
|
let percent = Math.round(e.percent * 100) / 100;
|
||||||
status.progress = percent;
|
if (status.progress !== percent) {
|
||||||
statusTools.setStatus(status);
|
status.progress = percent;
|
||||||
}
|
statusTools.setStatus(status);
|
||||||
}),
|
}
|
||||||
|
}),
|
||||||
stream
|
stream
|
||||||
)
|
).then((res) => {
|
||||||
.then((res) => {
|
logger.info("Download success !");
|
||||||
logger.info("Download success !");
|
status.progress = 1;
|
||||||
status.progress = 1;
|
statusTools.setStatus(status);
|
||||||
statusTools.setStatus(status);
|
logger.debug("Backup dl size : " + fs.statSync(tmpFile).size / 1024 / 1024);
|
||||||
logger.debug("Backup dl size : " + fs.statSync(tmpFile).size / 1024 / 1024);
|
resolve(tmpFile);
|
||||||
resolve(tmpFile);
|
}).catch((err) => {
|
||||||
})
|
if (fs.existsSync(tmpFile)) fs.unlinkSync(tmpFile);
|
||||||
.catch((err) => {
|
status.status = "error";
|
||||||
if (fs.existsSync(tmpFile)) fs.unlinkSync(tmpFile);
|
status.message = "Fail to download Hassio snapshot (" + err.message + ")";
|
||||||
status.status = "error";
|
status.error_code = 7;
|
||||||
status.message = "Fail to download Hassio snapshot (" + err.message + ")";
|
statusTools.setStatus(status);
|
||||||
status.error_code = 7;
|
logger.error(status.message);
|
||||||
statusTools.setStatus(status);
|
logger.error(err.stack);
|
||||||
logger.error(status.message);
|
reject(err.message);
|
||||||
logger.error(err.stack);
|
});
|
||||||
reject(err.message);
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -358,12 +365,8 @@ class WebdavTools {
|
|||||||
}
|
}
|
||||||
this.client
|
this.client
|
||||||
.getDirectoryContents(path)
|
.getDirectoryContents(path)
|
||||||
.then((contents) => {
|
.then((contents) => resolve(contents))
|
||||||
resolve(contents);
|
.catch((error) => reject(error));
|
||||||
})
|
|
||||||
.catch((error) => {
|
|
||||||
reject(error);
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -378,8 +381,10 @@ class WebdavTools {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
contents.sort((a, b) => {
|
contents.sort((a, b) => {
|
||||||
if (moment(a.lastmod).isBefore(moment(b.lastmod))) return 1;
|
if (moment(a.lastmod).isBefore(moment(b.lastmod)))
|
||||||
else return -1;
|
return 1;
|
||||||
|
else
|
||||||
|
return -1;
|
||||||
});
|
});
|
||||||
|
|
||||||
let toDel = contents.slice(limit);
|
let toDel = contents.slice(limit);
|
||||||
@ -403,11 +408,13 @@ class WebdavTools {
|
|||||||
|
|
||||||
function cleanTempFolder() {
|
function cleanTempFolder() {
|
||||||
fs.readdir("./temp/", (err, files) => {
|
fs.readdir("./temp/", (err, files) => {
|
||||||
if (err) throw err;
|
if (err)
|
||||||
|
throw err;
|
||||||
|
|
||||||
for (const file of files) {
|
for (const file of files) {
|
||||||
fs.unlink(path.join("./temp/", file), (err) => {
|
fs.unlink(path.join("./temp/", file), (err) => {
|
||||||
if (err) throw err;
|
if (err)
|
||||||
|
throw err;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
Loading…
Reference in New Issue
Block a user