mirror of
https://github.com/Sebclem/hassio-nextcloud-backup.git
synced 2024-11-25 02:22:58 +01:00
Compare commits
No commits in common. "f7d4992bf1762458dd80a31c9827cab0c95d76ab" and "0fa020d0ab1547790975cdf3bf92cebe671f2a6b" have entirely different histories.
f7d4992bf1
...
0fa020d0ab
2
.github/workflows/build_addon.yml
vendored
2
.github/workflows/build_addon.yml
vendored
@ -76,7 +76,7 @@ jobs:
|
|||||||
uses: docker/login-action@v1
|
uses: docker/login-action@v1
|
||||||
with:
|
with:
|
||||||
registry: ghcr.io
|
registry: ghcr.io
|
||||||
username: ${{ github.actor }}
|
username: ${{ github.repository_owner }}
|
||||||
password: ${{ secrets.GITHUB_TOKEN }}
|
password: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
- name: Build and push ${{matrix.arch}}
|
- name: Build and push ${{matrix.arch}}
|
||||||
|
@ -1,26 +1,11 @@
|
|||||||
import createError from "http-errors";
|
const createError = require("http-errors");
|
||||||
import express from "express";
|
const express = require("express");
|
||||||
import path from "path";
|
const path = require("path");
|
||||||
import cookieParser from "cookie-parser";
|
const cookieParser = require("cookie-parser");
|
||||||
import logger from "morgan";
|
const logger = require("morgan");
|
||||||
import { fileURLToPath } from 'url';
|
|
||||||
import { dirname } from 'path';
|
|
||||||
import fs from "fs"
|
|
||||||
import newlog from "./config/winston.js"
|
|
||||||
import * as statusTools from "./tools/status.js"
|
|
||||||
import * as hassioApiTools from "./tools/hassioApiTools.js"
|
|
||||||
import webdav from "./tools/webdavTools.js"
|
|
||||||
import * as settingsTools from "./tools/settingsTools.js"
|
|
||||||
import cronTools from "./tools/cronTools.js"
|
|
||||||
|
|
||||||
import indexRouter from "./routes/index.js"
|
const indexRouter = require("./routes/index");
|
||||||
import apiRouter from "./routes/api.js"
|
const apiRouter = require("./routes/api");
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const __filename = fileURLToPath(import.meta.url);
|
|
||||||
const __dirname = dirname(__filename);
|
|
||||||
|
|
||||||
const app = express();
|
const app = express();
|
||||||
// view engine setup
|
// view engine setup
|
||||||
@ -86,15 +71,17 @@ app.use(function (err, req, res, next) {
|
|||||||
----------------------------------------------------------
|
----------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
const fs = require("fs");
|
||||||
|
const newlog = require("./config/winston");
|
||||||
|
|
||||||
newlog.info(`Log level: ${ process.env.LOG_LEVEL }`);
|
newlog.info(`Log level: ${ process.env.LOG_LEVEL }`);
|
||||||
newlog.info(`Backup timeout: ${ parseInt(process.env.CREATE_BACKUP_TIMEOUT) || ( 90 * 60 * 1000 ) }`)
|
newlog.info(`Backup timeout: ${ parseInt(process.env.CREATE_BACKUP_TIMEOUT) || ( 90 * 60 * 1000 ) }`)
|
||||||
|
|
||||||
if (!fs.existsSync("/data")) fs.mkdirSync("/data");
|
if (!fs.existsSync("/data")) fs.mkdirSync("/data");
|
||||||
|
const statusTools = require("./tools/status");
|
||||||
statusTools.init();
|
statusTools.init();
|
||||||
newlog.info("Satus : \x1b[32mGo !\x1b[0m");
|
newlog.info("Satus : \x1b[32mGo !\x1b[0m");
|
||||||
|
const hassioApiTools = require("./tools/hassioApiTools");
|
||||||
hassioApiTools.getSnapshots().then(
|
hassioApiTools.getSnapshots().then(
|
||||||
() => {
|
() => {
|
||||||
newlog.info("Hassio API : \x1b[32mGo !\x1b[0m");
|
newlog.info("Hassio API : \x1b[32mGo !\x1b[0m");
|
||||||
@ -105,6 +92,8 @@ hassioApiTools.getSnapshots().then(
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const WebdavTools = require("./tools/webdavTools");
|
||||||
|
const webdav = new WebdavTools().getInstance();
|
||||||
webdav.confIsValid().then(
|
webdav.confIsValid().then(
|
||||||
() => {
|
() => {
|
||||||
newlog.info("Nextcloud connection : \x1b[32mGo !\x1b[0m");
|
newlog.info("Nextcloud connection : \x1b[32mGo !\x1b[0m");
|
||||||
@ -114,9 +103,11 @@ webdav.confIsValid().then(
|
|||||||
newlog.error("... " + err);
|
newlog.error("... " + err);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
const settingTool = require('./tools/settingsTools')
|
||||||
settingsTools.check(settingsTools.getSettings(), true);
|
settingTool.check(settingTool.getSettings(), true);
|
||||||
cronTools.init();
|
const cronTools = require("./tools/cronTools");
|
||||||
|
cronTools.startCron();
|
||||||
|
|
||||||
|
|
||||||
export default app;
|
|
||||||
|
module.exports = app;
|
||||||
|
@ -4,11 +4,9 @@
|
|||||||
* Module dependencies.
|
* Module dependencies.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import app from "../app.js"
|
var app = require('../app');
|
||||||
import http from "http"
|
var debug = require('debug')('nexcloud-backup:server');
|
||||||
import _debug from 'debug';
|
var http = require('http');
|
||||||
const debug = _debug('nexcloud-backup:server');
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get port from environment and store in Express.
|
* Get port from environment and store in Express.
|
@ -1,4 +1,4 @@
|
|||||||
import winston from "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',
|
||||||
@ -24,5 +24,4 @@ const logger = winston.createLogger({
|
|||||||
],
|
],
|
||||||
});
|
});
|
||||||
|
|
||||||
|
module.exports = logger;
|
||||||
export default logger;
|
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -2,24 +2,23 @@
|
|||||||
"name": "nexcloud-backup",
|
"name": "nexcloud-backup",
|
||||||
"version": "0.8.0",
|
"version": "0.8.0",
|
||||||
"private": true,
|
"private": true,
|
||||||
"type": "module",
|
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"start": "node ./bin/www.js "
|
"start": "node ./bin/www "
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@fortawesome/fontawesome-free": "^6.1.1",
|
"@fortawesome/fontawesome-free": "^6.0.0",
|
||||||
"app-root-path": "^3.0.0",
|
"app-root-path": "^3.0.0",
|
||||||
"bootstrap": "^5.0.1",
|
"bootstrap": "^5.0.1",
|
||||||
"cookie-parser": "^1.4.6",
|
"cookie-parser": "^1.4.6",
|
||||||
"cron": "^1.8.2",
|
"cron": "^1.8.2",
|
||||||
"debug": "~4.3.4",
|
"debug": "~4.3.3",
|
||||||
"ejs": "~3.1.7",
|
"ejs": "~3.1.6",
|
||||||
"express": "~4.18.1",
|
"express": "~4.17.2",
|
||||||
"form-data": "^4.0.0",
|
"form-data": "^4.0.0",
|
||||||
"got": "12.0.4",
|
"got": "^11.8.2",
|
||||||
"http-errors": "~2.0.0",
|
"http-errors": "~2.0.0",
|
||||||
"jquery": "^3.6.0",
|
"jquery": "^3.6.0",
|
||||||
"moment": "^2.29.3",
|
"moment": "^2.29.1",
|
||||||
"morgan": "~1.10.0",
|
"morgan": "~1.10.0",
|
||||||
"webdav": "^4.8.0",
|
"webdav": "^4.8.0",
|
||||||
"winston": "^3.6.0"
|
"winston": "^3.6.0"
|
||||||
|
@ -29,15 +29,13 @@ function updateDynamicListeners() {
|
|||||||
console.log(id);
|
console.log(id);
|
||||||
});
|
});
|
||||||
let manual_back_list = $(".manual-back-list");
|
let manual_back_list = $(".manual-back-list");
|
||||||
manual_back_list.unbind();
|
manual_back_list.off();
|
||||||
manual_back_list.on("click", function () {
|
manual_back_list.on("click", function () {
|
||||||
let id = this.getAttribute("data-id");
|
let id = this.getAttribute("data-id");
|
||||||
let name = this.getAttribute("data-name");
|
let name = this.getAttribute("data-name");
|
||||||
manualBackup(id, name);
|
manualBackup(id, name);
|
||||||
});
|
});
|
||||||
let restore_btn = $(".restore");
|
$(".restore").click(function () {
|
||||||
restore_btn.unbind();
|
|
||||||
restore_btn.click(function () {
|
|
||||||
let to_restore = this.getAttribute("data-id");
|
let to_restore = this.getAttribute("data-id");
|
||||||
console.log(to_restore);
|
console.log(to_restore);
|
||||||
restore(to_restore);
|
restore(to_restore);
|
||||||
@ -245,6 +243,7 @@ function sendNextcloudSettings() {
|
|||||||
console.log("Saved");
|
console.log("Saved");
|
||||||
$("#nextcloud_settings_message").parent().addClass("d-none");
|
$("#nextcloud_settings_message").parent().addClass("d-none");
|
||||||
create_toast("success", "Nextcloud settings saved !", default_toast_timeout);
|
create_toast("success", "Nextcloud settings saved !", default_toast_timeout);
|
||||||
|
0;
|
||||||
})
|
})
|
||||||
.fail((data) => {
|
.fail((data) => {
|
||||||
let nextcloud_settings_message = $("#nextcloud_settings_message");
|
let nextcloud_settings_message = $("#nextcloud_settings_message");
|
||||||
|
@ -1,18 +1,20 @@
|
|||||||
import express from 'express';
|
const express = require("express");
|
||||||
import moment from "moment";
|
const router = express.Router();
|
||||||
import * as statusTools from "../tools/status.js"
|
const moment = require("moment");
|
||||||
import webdav from "../tools/webdavTools.js"
|
const statusTools = require("../tools/status");
|
||||||
import * as settingsTools from "../tools/settingsTools.js"
|
const WebdavTools = require("../tools/webdavTools");
|
||||||
import * as pathTools from "../tools/pathTools.js"
|
const webdav = new WebdavTools().getInstance();
|
||||||
import * as hassioApiTools from "../tools/hassioApiTools.js"
|
const settingsTools = require("../tools/settingsTools");
|
||||||
import { humanFileSize } from "../tools/toolbox.js";
|
const pathTools = require("../tools/pathTools");
|
||||||
import cronTools from "../tools/cronTools.js"
|
const hassioApiTools = require("../tools/hassioApiTools");
|
||||||
import logger from "../config/winston.js"
|
const humanFileSize = require("../tools/toolbox").humanFileSize;
|
||||||
|
|
||||||
var router = express.Router();
|
const cronTools = require("../tools/cronTools");
|
||||||
|
|
||||||
|
const logger = require("../config/winston");
|
||||||
|
|
||||||
router.get("/status", (req, res, next) => {
|
router.get("/status", (req, res, next) => {
|
||||||
cronTools.updateNextDate();
|
cronTools.updatetNextDate();
|
||||||
let status = statusTools.getStatus();
|
let status = statusTools.getStatus();
|
||||||
res.json(status);
|
res.json(status);
|
||||||
});
|
});
|
||||||
@ -128,15 +130,9 @@ router.post("/manual-backup", function (req, res, next) {
|
|||||||
hassioApiTools
|
hassioApiTools
|
||||||
.downloadSnapshot(id)
|
.downloadSnapshot(id)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
webdav.uploadFile(id, webdav.getConf().back_dir + pathTools.manual + name + ".tar").then(()=>{
|
webdav.uploadFile(id, webdav.getConf().back_dir + pathTools.manual + name + ".tar").catch();
|
||||||
res.status(201);
|
res.status(201);
|
||||||
res.send();
|
res.send();
|
||||||
}).catch(()=>{
|
|
||||||
res.status(500);
|
|
||||||
res.send();
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
})
|
})
|
||||||
.catch(() => {
|
.catch(() => {
|
||||||
res.status(500);
|
res.status(500);
|
||||||
@ -165,10 +161,10 @@ router.post("/new-backup", function (req, res, next) {
|
|||||||
.then(() => {
|
.then(() => {
|
||||||
hassioApiTools.startAddons().catch(() => {
|
hassioApiTools.startAddons().catch(() => {
|
||||||
})
|
})
|
||||||
}).catch(()=>{});
|
});
|
||||||
}).catch(()=>{});
|
});
|
||||||
}).catch(()=>{});
|
});
|
||||||
}).catch(()=>{});
|
});
|
||||||
})
|
})
|
||||||
.catch(() => {
|
.catch(() => {
|
||||||
hassioApiTools.startAddons().catch(() => {
|
hassioApiTools.startAddons().catch(() => {
|
||||||
@ -195,7 +191,7 @@ router.post("/backup-settings", function (req, res, next) {
|
|||||||
let [result, message] = settingsTools.check(req.body)
|
let [result, message] = settingsTools.check(req.body)
|
||||||
if (result) {
|
if (result) {
|
||||||
settingsTools.setSettings(req.body);
|
settingsTools.setSettings(req.body);
|
||||||
cronTools.init();
|
cronTools.startCron();
|
||||||
res.send();
|
res.send();
|
||||||
} else {
|
} else {
|
||||||
res.status(400);
|
res.status(400);
|
||||||
@ -229,5 +225,5 @@ router.post("/restore", function (req, res, next) {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
export default router;
|
module.exports = router;
|
||||||
|
|
@ -1,9 +1,9 @@
|
|||||||
import express from 'express';
|
const express = require("express");
|
||||||
var router = express.Router();
|
const router = express.Router();
|
||||||
|
|
||||||
/* GET home page. */
|
/* GET home page. */
|
||||||
router.get("/", function (req, res, next) {
|
router.get("/", function (req, res, next) {
|
||||||
res.render("index");
|
res.render("index");
|
||||||
});
|
});
|
||||||
|
|
||||||
export default router;
|
module.exports = router;
|
||||||
|
@ -1,13 +1,23 @@
|
|||||||
import { CronJob } from "cron"
|
const CronJob = require("cron").CronJob;
|
||||||
import * as settingsTools from "./settingsTools.js"
|
|
||||||
import * as hassioApiTools from "./hassioApiTools.js"
|
|
||||||
import * as statusTools from "./status.js"
|
|
||||||
import * as pathTools from "./pathTools.js"
|
|
||||||
import webdav from "./webdavTools.js"
|
|
||||||
|
|
||||||
|
const settingsTools = require("./settingsTools");
|
||||||
|
const WebdavTools = require("./webdavTools");
|
||||||
|
const webdav = new WebdavTools().getInstance();
|
||||||
|
const hassioApiTools = require("./hassioApiTools");
|
||||||
|
const statusTools = require("./status");
|
||||||
|
const pathTools = require("./pathTools");
|
||||||
|
|
||||||
import logger from "../config/winston.js"
|
const logger = require("../config/winston");
|
||||||
|
|
||||||
|
function startCron() {
|
||||||
|
let cronContainer = new Singleton().getInstance();
|
||||||
|
cronContainer.init();
|
||||||
|
}
|
||||||
|
|
||||||
|
function updatetNextDate() {
|
||||||
|
let cronContainer = new Singleton().getInstance();
|
||||||
|
cronContainer.updateNextDate();
|
||||||
|
}
|
||||||
|
|
||||||
class CronContainer {
|
class CronContainer {
|
||||||
constructor() {
|
constructor() {
|
||||||
@ -116,6 +126,17 @@ class CronContainer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const INSTANCE = new CronContainer();
|
class Singleton {
|
||||||
export default INSTANCE;
|
constructor() {
|
||||||
|
if (!Singleton.instance) {
|
||||||
|
Singleton.instance = new CronContainer();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
getInstance() {
|
||||||
|
return Singleton.instance;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
exports.startCron = startCron;
|
||||||
|
exports.updatetNextDate = updatetNextDate;
|
||||||
|
@ -1,24 +1,23 @@
|
|||||||
import fs from "fs"
|
const fs = require("fs");
|
||||||
import moment from "moment";
|
|
||||||
import stream from "stream"
|
|
||||||
import { promisify } from "util";
|
|
||||||
import got from "got";
|
|
||||||
import FormData from "form-data";
|
|
||||||
import * as statusTools from "../tools/status.js"
|
|
||||||
import * as settingsTools from "../tools/settingsTools.js"
|
|
||||||
|
|
||||||
import logger from "../config/winston.js"
|
const moment = require("moment");
|
||||||
|
const stream = require("stream");
|
||||||
|
const { promisify } = require("util");
|
||||||
|
|
||||||
const pipeline = promisify(stream.pipeline);
|
const pipeline = promisify(stream.pipeline);
|
||||||
|
const got = require("got");
|
||||||
|
const FormData = require("form-data");
|
||||||
|
const statusTools = require("./status");
|
||||||
|
const settingsTools = require("./settingsTools");
|
||||||
|
const logger = require("../config/winston");
|
||||||
|
|
||||||
const token = process.env.SUPERVISOR_TOKEN;
|
// Default timout to 90min
|
||||||
|
const create_snap_timeout = parseInt(process.env.CREATE_BACKUP_TIMEOUT) || ( 90 * 60 * 1000 );
|
||||||
// Default timeout to 90min
|
|
||||||
const create_snap_timeout = parseInt(process.env.CREATE_BACKUP_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 status = statusTools.getStatus();
|
let status = statusTools.getStatus();
|
||||||
let option = {
|
let option = {
|
||||||
headers: { "Authorization": `Bearer ${token}` },
|
headers: { "Authorization": `Bearer ${token}` },
|
||||||
@ -37,14 +36,19 @@ function getVersion() {
|
|||||||
resolve(version);
|
resolve(version);
|
||||||
})
|
})
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
statusTools.setError(`Fail to fetch HA Version (${error.message})`, 1);
|
status.status = "error";
|
||||||
reject(`Fail to fetch HA Version (${error.message})`);
|
status.message = "Fail to fetch HA Version (" + error.message + ")";
|
||||||
|
status.error_code = 1;
|
||||||
|
statusTools.setStatus(status);
|
||||||
|
logger.error(status.message);
|
||||||
|
reject(error.message);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function getAddonList() {
|
function getAddonList() {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
|
let token = process.env.HASSIO_TOKEN;
|
||||||
let status = statusTools.getStatus();
|
let status = statusTools.getStatus();
|
||||||
let option = {
|
let option = {
|
||||||
headers: { "Authorization": `Bearer ${token}` },
|
headers: { "Authorization": `Bearer ${token}` },
|
||||||
@ -74,8 +78,12 @@ function getAddonList() {
|
|||||||
resolve(installed);
|
resolve(installed);
|
||||||
})
|
})
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
statusTools.setError(`Fail to fetch addons list (${error.message})`, 1);
|
status.status = "error";
|
||||||
reject(`Fail to fetch addons list (${error.message})`);
|
status.message = "Fail to fetch addons list (" + error.message + ")";
|
||||||
|
status.error_code = 1;
|
||||||
|
statusTools.setStatus(status);
|
||||||
|
logger.error(status.message);
|
||||||
|
reject(error.message);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -138,6 +146,7 @@ function getFolderToBackup() {
|
|||||||
|
|
||||||
function getSnapshots() {
|
function getSnapshots() {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
|
let token = process.env.HASSIO_TOKEN;
|
||||||
let status = statusTools.getStatus();
|
let status = statusTools.getStatus();
|
||||||
let option = {
|
let option = {
|
||||||
headers: { "Authorization": `Bearer ${token}` },
|
headers: { "Authorization": `Bearer ${token}` },
|
||||||
@ -156,8 +165,12 @@ function getSnapshots() {
|
|||||||
resolve(snaps);
|
resolve(snaps);
|
||||||
})
|
})
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
statusTools.setError(`Fail to fetch Hassio backups (${error.message})`, 1);
|
status.status = "error";
|
||||||
reject(`Fail to fetch Hassio backups (${error.message})`);
|
status.message = "Fail to fetch Hassio snapshots (" + error.message + ")";
|
||||||
|
status.error_code = 1;
|
||||||
|
statusTools.setStatus(status);
|
||||||
|
logger.error(status.message);
|
||||||
|
reject(error.message);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -168,6 +181,7 @@ function downloadSnapshot(id) {
|
|||||||
if (!fs.existsSync("./temp/")) fs.mkdirSync("./temp/");
|
if (!fs.existsSync("./temp/")) fs.mkdirSync("./temp/");
|
||||||
let tmp_file = `./temp/${id}.tar`;
|
let tmp_file = `./temp/${id}.tar`;
|
||||||
let stream = fs.createWriteStream(tmp_file);
|
let stream = fs.createWriteStream(tmp_file);
|
||||||
|
let token = process.env.HASSIO_TOKEN;
|
||||||
let status = statusTools.getStatus();
|
let status = statusTools.getStatus();
|
||||||
checkSnap(id)
|
checkSnap(id)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
@ -189,21 +203,29 @@ function downloadSnapshot(id) {
|
|||||||
}),
|
}),
|
||||||
stream
|
stream
|
||||||
)
|
)
|
||||||
.then(() => {
|
.then((res) => {
|
||||||
logger.info("Download success !");
|
logger.info("Download success !");
|
||||||
status.progress = 1;
|
status.progress = 1;
|
||||||
statusTools.setStatus(status);
|
statusTools.setStatus(status);
|
||||||
logger.debug("Snapshot dl size : " + fs.statSync(tmp_file).size / 1024 / 1024);
|
logger.debug("Snapshot dl size : " + fs.statSync(tmp_file).size / 1024 / 1024);
|
||||||
resolve();
|
resolve();
|
||||||
})
|
})
|
||||||
.catch((error) => {
|
.catch((err) => {
|
||||||
fs.unlinkSync(tmp_file);
|
fs.unlinkSync(tmp_file);
|
||||||
statusTools.setError(`Fail to download Hassio backup (${error.message})`, 7);
|
status.status = "error";
|
||||||
reject(`Fail to download Hassio backup (${error.message})`);
|
status.message = "Fail to download Hassio snapshot (" + err.message + ")";
|
||||||
|
status.error_code = 7;
|
||||||
|
statusTools.setStatus(status);
|
||||||
|
logger.error(status.message);
|
||||||
|
reject(err.message);
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
.catch(() => {
|
.catch((err) => {
|
||||||
statusTools.setError("Fail to download Hassio backup. Not found ?", 7);
|
status.status = "error";
|
||||||
|
status.message = "Fail to download Hassio snapshot. Not found ?";
|
||||||
|
status.error_code = 7;
|
||||||
|
statusTools.setStatus(status);
|
||||||
|
logger.error(status.message);
|
||||||
reject();
|
reject();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -213,6 +235,8 @@ 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 option = {
|
let option = {
|
||||||
headers: { "Authorization": `Bearer ${token}` },
|
headers: { "Authorization": `Bearer ${token}` },
|
||||||
responseType: "json",
|
responseType: "json",
|
||||||
@ -233,6 +257,7 @@ function dellSnap(id) {
|
|||||||
|
|
||||||
function checkSnap(id) {
|
function checkSnap(id) {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
|
let token = process.env.HASSIO_TOKEN;
|
||||||
let option = {
|
let option = {
|
||||||
headers: { "Authorization": `Bearer ${token}` },
|
headers: { "Authorization": `Bearer ${token}` },
|
||||||
responseType: "json",
|
responseType: "json",
|
||||||
@ -254,23 +279,20 @@ function createNewBackup(name) {
|
|||||||
status.progress = -1;
|
status.progress = -1;
|
||||||
statusTools.setStatus(status);
|
statusTools.setStatus(status);
|
||||||
logger.info("Creating new snapshot...");
|
logger.info("Creating new snapshot...");
|
||||||
|
let token = process.env.HASSIO_TOKEN;
|
||||||
getAddonToBackup().then((addons) => {
|
getAddonToBackup().then((addons) => {
|
||||||
let folders = getFolderToBackup();
|
let folders = getFolderToBackup();
|
||||||
let option = {
|
let option = {
|
||||||
headers: { "Authorization": `Bearer ${token}` },
|
headers: { "Authorization": `Bearer ${token}` },
|
||||||
responseType: "json",
|
responseType: "json",
|
||||||
timeout: {
|
timeout: create_snap_timeout,
|
||||||
response: create_snap_timeout
|
|
||||||
},
|
|
||||||
json: {
|
json: {
|
||||||
name: name,
|
name: name,
|
||||||
addons: addons,
|
addons: addons,
|
||||||
folders: folders
|
folders: folders
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
let password_protected = settingsTools.getSettings().password_protected;
|
if (settingsTools.getSettings().password_protected === "true") {
|
||||||
logger.debug(`Is password protected ? ${password_protected}`)
|
|
||||||
if ( password_protected === "true") {
|
|
||||||
option.json.password = settingsTools.getSettings().password_protect_value
|
option.json.password = settingsTools.getSettings().password_protect_value
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -280,8 +302,12 @@ function createNewBackup(name) {
|
|||||||
resolve(result.body.data.slug);
|
resolve(result.body.data.slug);
|
||||||
})
|
})
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
statusTools.setError(`Can't create new snapshot (${error.message})`, 5);
|
status.status = "error";
|
||||||
reject(`Can't create new snapshot (${error.message})`);
|
status.message = "Can't create new snapshot (" + error.message + ")";
|
||||||
|
status.error_code = 5;
|
||||||
|
statusTools.setStatus(status);
|
||||||
|
logger.error(status.message);
|
||||||
|
reject(status.message);
|
||||||
});
|
});
|
||||||
|
|
||||||
}).catch(reject);
|
}).catch(reject);
|
||||||
@ -311,9 +337,8 @@ function clean() {
|
|||||||
logger.info("Local clean done.");
|
logger.info("Local clean done.");
|
||||||
resolve();
|
resolve();
|
||||||
})
|
})
|
||||||
.catch((e) => {
|
.catch(() => {
|
||||||
statusTools.setError(`Fail to clean backups (${e}) !`, 6);
|
reject();
|
||||||
reject(`Fail to clean backups (${e}) !`);
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -328,11 +353,15 @@ function uploadSnapshot(path) {
|
|||||||
statusTools.setStatus(status);
|
statusTools.setStatus(status);
|
||||||
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 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,
|
||||||
|
password: this.password,
|
||||||
headers: { "Authorization": `Bearer ${token}` },
|
headers: { "Authorization": `Bearer ${token}` },
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -370,15 +399,19 @@ function uploadSnapshot(path) {
|
|||||||
})
|
})
|
||||||
.on("error", (err) => {
|
.on("error", (err) => {
|
||||||
fs.unlinkSync(path);
|
fs.unlinkSync(path);
|
||||||
statusTools.setError(`Fail to upload backup to home assistant (${err}) !`, 4);
|
status.status = "error";
|
||||||
reject(`Fail to upload backup to home assistant (${err}) !`);
|
status.error_code = 4;
|
||||||
|
status.message = `Fail to upload backup to home assistant (${err}) !`;
|
||||||
|
statusTools.setStatus(status);
|
||||||
|
logger.error(status.message);
|
||||||
|
reject(status.message);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function stopAddons() {
|
function stopAddons() {
|
||||||
return new Promise(((resolve, reject) => {
|
return new Promise(((resolve, reject) => {
|
||||||
logger.info('Stopping addons...');
|
logger.info('Stopping addons...')
|
||||||
let status = statusTools.getStatus();
|
let status = statusTools.getStatus();
|
||||||
status.status = "stopping";
|
status.status = "stopping";
|
||||||
status.progress = -1;
|
status.progress = -1;
|
||||||
@ -386,6 +419,7 @@ function stopAddons() {
|
|||||||
status.error_code = null;
|
status.error_code = null;
|
||||||
statusTools.setStatus(status);
|
statusTools.setStatus(status);
|
||||||
let promises = [];
|
let promises = [];
|
||||||
|
let token = process.env.HASSIO_TOKEN;
|
||||||
let option = {
|
let option = {
|
||||||
headers: { "Authorization": `Bearer ${token}` },
|
headers: { "Authorization": `Bearer ${token}` },
|
||||||
responseType: "json",
|
responseType: "json",
|
||||||
@ -393,7 +427,7 @@ function stopAddons() {
|
|||||||
let addons_slug = settingsTools.getSettings().auto_stop_addon
|
let addons_slug = settingsTools.getSettings().auto_stop_addon
|
||||||
for (let addon of addons_slug) {
|
for (let addon of addons_slug) {
|
||||||
if (addon !== "") {
|
if (addon !== "") {
|
||||||
logger.debug(`... Stopping addon ${addon}`);
|
logger.debug(`... Stopping addon ${addon}`)
|
||||||
promises.push(got.post(`http://hassio/addons/${addon}/stop`, option));
|
promises.push(got.post(`http://hassio/addons/${addon}/stop`, option));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -405,11 +439,14 @@ function stopAddons() {
|
|||||||
error = val.reason;
|
error = val.reason;
|
||||||
|
|
||||||
if (error) {
|
if (error) {
|
||||||
statusTools.setError(`Fail to stop addons(${error}) !`, 8);
|
status.status = "error";
|
||||||
|
status.error_code = 8;
|
||||||
|
status.message = `Fail to stop addons(${error}) !`;
|
||||||
|
statusTools.setStatus(status);
|
||||||
logger.error(status.message);
|
logger.error(status.message);
|
||||||
reject(status.message);
|
reject(status.message);
|
||||||
} else {
|
} else {
|
||||||
logger.info('... Ok');
|
logger.info('... Ok')
|
||||||
resolve();
|
resolve();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -426,6 +463,7 @@ function startAddons() {
|
|||||||
status.error_code = null;
|
status.error_code = null;
|
||||||
statusTools.setStatus(status);
|
statusTools.setStatus(status);
|
||||||
let promises = [];
|
let promises = [];
|
||||||
|
let token = process.env.HASSIO_TOKEN;
|
||||||
let option = {
|
let option = {
|
||||||
headers: { "Authorization": `Bearer ${token}` },
|
headers: { "Authorization": `Bearer ${token}` },
|
||||||
responseType: "json",
|
responseType: "json",
|
||||||
@ -444,7 +482,12 @@ function startAddons() {
|
|||||||
error = val.reason;
|
error = val.reason;
|
||||||
|
|
||||||
if (error) {
|
if (error) {
|
||||||
statusTools.setError(`Fail to start addons (${error}) !`, 9)
|
let status = statusTools.getStatus();
|
||||||
|
status.status = "error";
|
||||||
|
status.error_code = 9;
|
||||||
|
status.message = `Fail to start addons (${error}) !`;
|
||||||
|
statusTools.setStatus(status);
|
||||||
|
logger.error(status.message);
|
||||||
reject(status.message);
|
reject(status.message);
|
||||||
} else {
|
} else {
|
||||||
logger.info('... Ok')
|
logger.info('... Ok')
|
||||||
@ -459,7 +502,7 @@ function startAddons() {
|
|||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
function publish_state(state) {
|
function publish_state(state){
|
||||||
|
|
||||||
// let data_error_sensor = {
|
// let data_error_sensor = {
|
||||||
// state: state.status == "error" ? "on" : "off",
|
// state: state.status == "error" ? "on" : "off",
|
||||||
@ -473,6 +516,7 @@ function publish_state(state) {
|
|||||||
// }
|
// }
|
||||||
|
|
||||||
|
|
||||||
|
// let token = process.env.HASSIO_TOKEN;
|
||||||
// let option = {
|
// let option = {
|
||||||
// headers: { "Authorization": `Bearer ${token}` },
|
// headers: { "Authorization": `Bearer ${token}` },
|
||||||
// responseType: "json",
|
// responseType: "json",
|
||||||
@ -528,16 +572,14 @@ function publish_state(state) {
|
|||||||
// });
|
// });
|
||||||
}
|
}
|
||||||
|
|
||||||
export {
|
exports.getVersion = getVersion;
|
||||||
getVersion,
|
exports.getAddonList = getAddonList;
|
||||||
getAddonList,
|
exports.getFolderList = getFolderList;
|
||||||
getFolderList,
|
exports.getSnapshots = getSnapshots;
|
||||||
getSnapshots,
|
exports.downloadSnapshot = downloadSnapshot;
|
||||||
downloadSnapshot,
|
exports.createNewBackup = createNewBackup;
|
||||||
createNewBackup,
|
exports.uploadSnapshot = uploadSnapshot;
|
||||||
uploadSnapshot,
|
exports.stopAddons = stopAddons;
|
||||||
stopAddons,
|
exports.startAddons = startAddons;
|
||||||
startAddons,
|
exports.clean = clean;
|
||||||
clean,
|
exports.publish_state = publish_state;
|
||||||
publish_state
|
|
||||||
}
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
const default_root = "/Hassio Backup/";
|
let default_root = "/Hassio Backup/";
|
||||||
export { default_root };
|
exports.default_root = default_root;
|
||||||
export const manual = "Manual/";
|
exports.manual = "Manual/";
|
||||||
export const auto = "Auto/";
|
exports.auto = "Auto/";
|
||||||
|
@ -1,8 +1,7 @@
|
|||||||
import fs from "fs"
|
const fs = require("fs");
|
||||||
import moment from "moment";
|
const logger = require("../config/winston");
|
||||||
import { CronJob } from "cron";
|
const moment = require("moment");
|
||||||
|
const CronJob = require("cron").CronJob;
|
||||||
import logger from "../config/winston.js"
|
|
||||||
|
|
||||||
const settingsPath = "/data/backup_conf.json";
|
const settingsPath = "/data/backup_conf.json";
|
||||||
|
|
||||||
@ -25,7 +24,6 @@ function check_cron(conf) {
|
|||||||
if (conf.cron_base === "4") {
|
if (conf.cron_base === "4") {
|
||||||
if (conf.cron_custom != null) {
|
if (conf.cron_custom != null) {
|
||||||
try {
|
try {
|
||||||
// TODO Need to be destroy
|
|
||||||
new CronJob(conf.cron_custom, () => {});
|
new CronJob(conf.cron_custom, () => {});
|
||||||
return true;
|
return true;
|
||||||
} catch(e) {
|
} catch(e) {
|
||||||
@ -189,4 +187,8 @@ function setSettings(settings) {
|
|||||||
fs.writeFileSync(settingsPath, JSON.stringify(settings));
|
fs.writeFileSync(settingsPath, JSON.stringify(settings));
|
||||||
}
|
}
|
||||||
|
|
||||||
export { getSettings, setSettings, check, check_cron, getFormatedName };
|
exports.getSettings = getSettings;
|
||||||
|
exports.setSettings = setSettings;
|
||||||
|
exports.check = check;
|
||||||
|
exports.check_cron = check_cron;
|
||||||
|
exports.getFormatedName = getFormatedName;
|
||||||
|
@ -1,38 +1,49 @@
|
|||||||
import * as hassioApiTools from "./hassioApiTools.js";
|
const fs = require("fs");
|
||||||
import logger from "../config/winston.js"
|
const hassioApiTools = require("./hassioApiTools");
|
||||||
|
|
||||||
|
const statusPath = "/data/status.json";
|
||||||
|
|
||||||
let status = {
|
let baseStatus = {
|
||||||
status: "idle",
|
status: "idle",
|
||||||
last_backup: null,
|
last_backup: null,
|
||||||
next_backup: null,
|
next_backup: null,
|
||||||
};
|
};
|
||||||
|
|
||||||
export function init() {
|
function init() {
|
||||||
if (status.status !== "idle") {
|
if (!fs.existsSync(statusPath)) {
|
||||||
status.status = "idle";
|
fs.writeFileSync(statusPath, JSON.stringify(baseStatus));
|
||||||
status.message = null;
|
} else {
|
||||||
|
let content = getStatus();
|
||||||
|
if (content.status !== "idle") {
|
||||||
|
content.status = "idle";
|
||||||
|
content.message = null;
|
||||||
|
setStatus(content);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getStatus() {
|
function getStatus() {
|
||||||
return status;
|
if (!fs.existsSync(statusPath)) {
|
||||||
|
fs.writeFileSync(statusPath, JSON.stringify(baseStatus));
|
||||||
|
}
|
||||||
|
return JSON.parse(fs.readFileSync(statusPath).toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
export function setStatus(new_state) {
|
function setStatus(state) {
|
||||||
let old_state_str = JSON.stringify(status);
|
if (fs.existsSync(statusPath)) {
|
||||||
if(old_state_str !== JSON.stringify(new_state)){
|
let old_state_str = fs.readFileSync(statusPath).toString();
|
||||||
status = new_state;
|
if(old_state_str !== JSON.stringify(state)){
|
||||||
hassioApiTools.publish_state(status);
|
fs.writeFileSync(statusPath, JSON.stringify(state));
|
||||||
|
hassioApiTools.publish_state(state);
|
||||||
}
|
}
|
||||||
|
}else{
|
||||||
|
fs.writeFileSync(statusPath, JSON.stringify(state));
|
||||||
|
hassioApiTools.publish_state(state);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function setError(message, error_code){
|
exports.init = init;
|
||||||
// Check if we don't have another error stored
|
exports.getStatus = getStatus;
|
||||||
if (status.status != "error") {
|
exports.setStatus = setStatus;
|
||||||
status.status = "error"
|
|
||||||
status.message = message
|
|
||||||
status.error_code = error_code;
|
|
||||||
}
|
|
||||||
logger.error(message);
|
|
||||||
}
|
|
||||||
|
@ -18,4 +18,4 @@ function humanFileSize(bytes, si = false, dp = 1) {
|
|||||||
return bytes.toFixed(dp) + " " + units[u];
|
return bytes.toFixed(dp) + " " + units[u];
|
||||||
}
|
}
|
||||||
|
|
||||||
export { humanFileSize } ;
|
exports.humanFileSize = humanFileSize;
|
||||||
|
@ -1,21 +1,20 @@
|
|||||||
import { createClient } from "webdav";
|
const { createClient } = require("webdav");
|
||||||
import fs from "fs"
|
const fs = require("fs");
|
||||||
import moment from "moment";
|
const moment = require("moment");
|
||||||
import https from "https"
|
const https = require("https");
|
||||||
import path from "path";
|
|
||||||
import got from "got";
|
|
||||||
import stream from "stream";
|
|
||||||
import { promisify } from "util";
|
|
||||||
|
|
||||||
import * as statusTools from "../tools/status.js"
|
|
||||||
import * as settingsTools from "../tools/settingsTools.js"
|
|
||||||
import * as pathTools from "../tools/pathTools.js"
|
|
||||||
import * as hassioApiTools from "../tools/hassioApiTools.js"
|
|
||||||
import logger from "../config/winston.js"
|
|
||||||
|
|
||||||
|
const statusTools = require("./status");
|
||||||
const endpoint = "/remote.php/webdav";
|
const endpoint = "/remote.php/webdav";
|
||||||
const configPath = "/data/webdav_conf.json";
|
const configPath = "/data/webdav_conf.json";
|
||||||
|
const path = require("path");
|
||||||
|
const settingsTools = require("./settingsTools");
|
||||||
|
const pathTools = require("./pathTools");
|
||||||
|
const hassioApiTools = require("./hassioApiTools");
|
||||||
|
const logger = require("../config/winston");
|
||||||
|
|
||||||
|
const got = require("got");
|
||||||
|
const stream = require("stream");
|
||||||
|
const { promisify } = require("util");
|
||||||
const pipeline = promisify(stream.pipeline);
|
const pipeline = promisify(stream.pipeline);
|
||||||
|
|
||||||
class WebdavTools {
|
class WebdavTools {
|
||||||
@ -70,7 +69,12 @@ class WebdavTools {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
__cant_connect_status(err){
|
__cant_connect_status(err){
|
||||||
statusTools.setError(`Can't connect to Nextcloud (${err})`, 3);
|
let status = statusTools.getStatus();
|
||||||
|
status.status = "error";
|
||||||
|
status.error_code = 3;
|
||||||
|
status.message = "Can't connect to Nextcloud (" + err + ") !";
|
||||||
|
statusTools.setStatus(status);
|
||||||
|
logger.error("Can't connect to Nextcloud (" + err + ") !");
|
||||||
}
|
}
|
||||||
|
|
||||||
async __createRoot() {
|
async __createRoot() {
|
||||||
@ -423,5 +427,16 @@ function cleanTempFolder() {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const INSTANCE = new WebdavTools();
|
class Singleton {
|
||||||
export default INSTANCE;
|
constructor() {
|
||||||
|
if (!Singleton.instance) {
|
||||||
|
Singleton.instance = new WebdavTools();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
getInstance() {
|
||||||
|
return Singleton.instance;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = Singleton;
|
||||||
|
Loading…
Reference in New Issue
Block a user