Compare commits

..

6 Commits

13 changed files with 510 additions and 396 deletions

View File

@ -35,6 +35,7 @@ Auto backup can be configured via the web interface.
- __Restore__ : Upload backed-up snapshot to Home assistant.
- __Auto Stop__ : This addon can stop addons before backup and restart them after backup
- __Web UI__ : All the configuration is based on an easy-to-use web interface, no yaml needed.
- __Home Assistant State Entities__ : This addon create 2 entite in HA : `binary_sensor.nextcloud_backup_error` and `sensor.nextcloud_backup_status`
> __Info:__
> Auto Clean is executed after every upload and every day at 00h30

View File

@ -17,6 +17,7 @@ Easily backup your Home Assistant snapshots to Nextcloud.
- __Auto Stop__ : This addon can stop addons before backup and restart them after backup
- __Restore__ : Upload backed-up snapshot to Home assistant.
- __Web UI__ : All the configuration is based on an easy-to-use web interface, no yaml needed.
- __Home Assistant State Entities__ : This addon create 2 entite in HA : `binary_sensor.nextcloud_backup_error` and `sensor.nextcloud_backup_status`
[Click here for the full documentation][docs]

View File

@ -1 +1 @@
9.2.1
10.0.2

View File

@ -42,6 +42,8 @@ You can now configure the automatic backup.
If enabled, you can specify how much Local Snapshot and Nextcloud Backup you want to keep before deleting the older one.
> __Info:__
> Auto Clean is executed after every upload and every day at 00h30
## Home Assitant Os Configuration
**Note**: _Remember to restart the add-on when the configuration is changed._

View File

@ -18,6 +18,8 @@ Easily backup your Home Assistant snapshots to Nextcloud.
- __Auto Stop__ : This addon can stop addons before backup and restart them after backup
- __Restore__ : Upload backed-up snapshot to Home assistant.
- __Web UI__ : All the configuration is based on an easy-to-use web interface, no yaml needed.
- __Home Assistant State Entities__ : This addon create 2 entite in HA : `binary_sensor.nextcloud_backup_error` and `sensor.nextcloud_backup_status`
[Click here for the full documentation][docs]

View File

@ -37,18 +37,18 @@
}
},
"node_modules/@fortawesome/fontawesome-free": {
"version": "5.15.3",
"resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-free/-/fontawesome-free-5.15.3.tgz",
"integrity": "sha512-rFnSUN/QOtnOAgqFRooTA3H57JLDm0QEG/jPdk+tLQNL/eWd+Aok8g3qCI+Q1xuDPWpGW/i9JySpJVsq8Q0s9w==",
"version": "5.15.4",
"resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-free/-/fontawesome-free-5.15.4.tgz",
"integrity": "sha512-eYm8vijH/hpzr/6/1CJ/V/Eb1xQFW2nnUKArb3z+yUWv7HTwj6M7SP957oMjfZjAHU6qpoNc2wQvIxBLWYa/Jg==",
"hasInstallScript": true,
"engines": {
"node": ">=6"
}
},
"node_modules/@popperjs/core": {
"version": "2.9.2",
"resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.9.2.tgz",
"integrity": "sha512-VZMYa7+fXHdwIq1TDhSXoVmSPEGM/aa+6Aiq3nVVJ9bXr24zScr+NlKFKC3iPljA7ho/GAZr+d2jOf5GIRC30Q==",
"version": "2.10.1",
"resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.10.1.tgz",
"integrity": "sha512-HnUhk1Sy9IuKrxEMdIRCxpIqPw6BFsbYSEUO9p/hNw5sMld/+3OLMWQP80F8/db9qsv3qUjs7ZR5bS/R+iinXw==",
"peer": true,
"funding": {
"type": "opencollective",
@ -67,9 +67,9 @@
}
},
"node_modules/@szmarczak/http-timer": {
"version": "4.0.5",
"resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-4.0.5.tgz",
"integrity": "sha512-PyRA9sm1Yayuj5OIoJ1hGt2YISX45w9WcFbh6ddT0Z/0yaFxOtGLInr4jUfU1EAFVs0Yfyfev4RNwBlUaHdlDQ==",
"version": "4.0.6",
"resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-4.0.6.tgz",
"integrity": "sha512-4BAffykYOgO+5nzBWYwE3W90sBgLJoUPRWWcL8wlyiM8IB8ipJz3UMJ9KXQd1RKQXpKp8Tutn80HZtWsu2u76w==",
"dependencies": {
"defer-to-connect": "^2.0.0"
},
@ -102,9 +102,9 @@
}
},
"node_modules/@types/node": {
"version": "16.0.1",
"resolved": "https://registry.npmjs.org/@types/node/-/node-16.0.1.tgz",
"integrity": "sha512-hBOx4SUlEPKwRi6PrXuTGw1z6lz0fjsibcWCM378YxsSu/6+C30L6CR49zIBKHiwNWCYIcOLjg4OHKZaFeLAug=="
"version": "16.7.13",
"resolved": "https://registry.npmjs.org/@types/node/-/node-16.7.13.tgz",
"integrity": "sha512-pLUPDn+YG3FYEt/pHI74HmnJOWzeR+tOIQzUx93pi9M7D8OE7PSLr97HboXwk5F+JS+TLtWuzCOW97AHjmOXXA=="
},
"node_modules/@types/responselike": {
"version": "1.0.0",
@ -161,11 +161,11 @@
"integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k="
},
"node_modules/axios": {
"version": "0.21.1",
"resolved": "https://registry.npmjs.org/axios/-/axios-0.21.1.tgz",
"integrity": "sha512-dKQiRHxGD9PPRIUNIWvZhPTPpl1rf/OxTYKsqKUDjBwYylTvV7SjSHJb9ratfyzM6wCdLCOYLzs73qpg5c4iGA==",
"version": "0.21.4",
"resolved": "https://registry.npmjs.org/axios/-/axios-0.21.4.tgz",
"integrity": "sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg==",
"dependencies": {
"follow-redirects": "^1.10.0"
"follow-redirects": "^1.14.0"
}
},
"node_modules/balanced-match": {
@ -243,15 +243,15 @@
"integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
},
"node_modules/bootstrap": {
"version": "5.0.2",
"resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-5.0.2.tgz",
"integrity": "sha512-1Ge963tyEQWJJ+8qtXFU6wgmAVj9gweEjibUdbmcCEYsn38tVwRk8107rk2vzt6cfQcRr3SlZ8aQBqaD8aqf+Q==",
"version": "5.1.0",
"resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-5.1.0.tgz",
"integrity": "sha512-bs74WNI9BgBo3cEovmdMHikSKoXnDgA6VQjJ7TyTotU6L7d41ZyCEEelPwkYEzsG/Zjv3ie9IE3EMAje0W9Xew==",
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/bootstrap"
},
"peerDependencies": {
"@popperjs/core": "^2.9.2"
"@popperjs/core": "^2.9.3"
}
},
"node_modules/brace-expansion": {
@ -348,9 +348,9 @@
"integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU="
},
"node_modules/color-string": {
"version": "1.5.5",
"resolved": "https://registry.npmjs.org/color-string/-/color-string-1.5.5.tgz",
"integrity": "sha512-jgIoum0OfQfq9Whcfc2z/VhCNcmQjWbey6qBX0vqt7YICflUmBCh9E9CiQD5GSJ+Uehixm3NUwHVhqUAWRivZg==",
"version": "1.6.0",
"resolved": "https://registry.npmjs.org/color-string/-/color-string-1.6.0.tgz",
"integrity": "sha512-c/hGS+kRWJutUBEngKKmk4iH3sD59MBkoxVapS/0wgpCz2u7XsNloxknyvBhzwEs1IbV36D9PwqLPJ2DTu3vMA==",
"dependencies": {
"color-name": "^1.0.0",
"simple-swizzle": "^0.2.2"
@ -434,9 +434,9 @@
"integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw="
},
"node_modules/core-util-is": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
"integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac="
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz",
"integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ=="
},
"node_modules/cron": {
"version": "1.8.2",
@ -639,9 +639,9 @@
"integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
},
"node_modules/fast-safe-stringify": {
"version": "2.0.7",
"resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.0.7.tgz",
"integrity": "sha512-Utm6CdzT+6xsDk2m8S6uL8VHxNwI6Jub+e9NYTcAms28T84pTa25GJQV9j0CY0N1rM8hK4x6grpF2BQf+2qwVA=="
"version": "2.0.8",
"resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.0.8.tgz",
"integrity": "sha512-lXatBjf3WPjmWD6DpIZxkeSsCOwqI0maYMpgDlx8g4U2qi4lbjA9oH/HD2a87G+KfsUmo5WbJFmqBZlPxtptag=="
},
"node_modules/fast-xml-parser": {
"version": "3.19.0",
@ -704,9 +704,9 @@
"integrity": "sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw=="
},
"node_modules/follow-redirects": {
"version": "1.14.1",
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.1.tgz",
"integrity": "sha512-HWqDgT7ZEkqRzBvc2s64vSZ/hfOceEol3ac/7tKwzuvEyWx3/4UegXh5oBOIotkGsObyk3xznnSRVADBgWSQVg==",
"version": "1.14.3",
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.3.tgz",
"integrity": "sha512-3MkHxknWMUtb23apkgz/83fDoe+y+qr0TdgacGIA7bew+QLBo3vdgEN2xEsuXNivpFy4CyDhBBZnNZOtalmenw==",
"funding": [
{
"type": "individual",
@ -882,11 +882,14 @@
"integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w=="
},
"node_modules/is-stream": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.0.tgz",
"integrity": "sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw==",
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz",
"integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==",
"engines": {
"node": ">=8"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/isarray": {
@ -1002,19 +1005,19 @@
}
},
"node_modules/mime-db": {
"version": "1.48.0",
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.48.0.tgz",
"integrity": "sha512-FM3QwxV+TnZYQ2aRqhlKBMHxk10lTbMt3bBkMAp54ddrNeVSfcQYOOKuGuy3Ddrm38I04If834fOUSq1yzslJQ==",
"version": "1.49.0",
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.49.0.tgz",
"integrity": "sha512-CIc8j9URtOVApSFCQIF+VBkX1RwXp/oMMOrqdyXSBXq5RWNEsRfyj1kiRnQgmNXmHxPoFIxOroKA3zcU9P+nAA==",
"engines": {
"node": ">= 0.6"
}
},
"node_modules/mime-types": {
"version": "2.1.31",
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.31.tgz",
"integrity": "sha512-XGZnNzm3QvgKxa8dpzyhFTHmpP3l5YNusmne07VUOXxou9CqUqYa/HBy124RqtVh/O2pECas/MOcsDgpilPOPg==",
"version": "2.1.32",
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.32.tgz",
"integrity": "sha512-hJGaVS4G4c9TSMYh2n6SQAGrC4RnfU+daP8G7cSCmaqNjiOoUY0VHCMS42pxnQmVF1GWwFhbHWn3RIxCqTmZ9A==",
"dependencies": {
"mime-db": "1.48.0"
"mime-db": "1.49.0"
},
"engines": {
"node": ">= 0.6"
@ -1295,9 +1298,9 @@
"integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8="
},
"node_modules/resolve-alpn": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/resolve-alpn/-/resolve-alpn-1.1.2.tgz",
"integrity": "sha512-8OyfzhAtA32LVUsJSke3auIyINcwdh5l3cvYKdKO0nvsYSKuiLfTM5i78PJswFPT8y6cPW+L1v6/hE95chcpDA=="
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/resolve-alpn/-/resolve-alpn-1.2.1.tgz",
"integrity": "sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g=="
},
"node_modules/responselike": {
"version": "2.0.0",
@ -1498,9 +1501,9 @@
"integrity": "sha512-jk1+QP6ZJqyOiuEI9AEWQfju/nB2Pw466kbA0LEZljHwKeMgd9WrAEgEGxjPDD2+TNbbb37rTyhEfrCXfuKXnA=="
},
"node_modules/url-parse": {
"version": "1.5.1",
"resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.1.tgz",
"integrity": "sha512-HOfCOUJt7iSYzEx/UqgtwKRMC6EU91NFhsCHMv9oM03VJcVo2Qrp8T8kI9D7amFf1cu+/3CEhgb3rF9zL7k85Q==",
"version": "1.5.3",
"resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.3.tgz",
"integrity": "sha512-IIORyIQD9rvj0A4CLWsHkBBJuNqWpFQe224b6j9t/ABmquIS0qDU2pY6kl6AuOrL5OkCXHMCFNe1jBcuAggjvQ==",
"dependencies": {
"querystringify": "^2.1.1",
"requires-port": "^1.0.0"
@ -1528,9 +1531,9 @@
}
},
"node_modules/webdav": {
"version": "4.6.0",
"resolved": "https://registry.npmjs.org/webdav/-/webdav-4.6.0.tgz",
"integrity": "sha512-amL/NeZ73xe8cNC+uqAF3mOC/j5dNoNWlZswYCd7DKxhnZM7dViAVSv6gdCYeGAETjPEZVubcKDDRwGKz9ShQQ==",
"version": "4.7.0",
"resolved": "https://registry.npmjs.org/webdav/-/webdav-4.7.0.tgz",
"integrity": "sha512-R1WZl/JeFPAmSEn1EPCmxSdPY8IxS/P0qnxAzBeRqEewpxVJ/UiCMJwXHLpyVsKYA1PIb1dYv+UTQsbNaQnLBw==",
"dependencies": {
"axios": "^0.21.1",
"base-64": "^1.0.0",
@ -1543,7 +1546,7 @@
"nested-property": "^4.0.0",
"path-posix": "^1.0.0",
"url-join": "^4.0.1",
"url-parse": "^1.5.1"
"url-parse": "^1.5.3"
}
},
"node_modules/winston": {
@ -1600,9 +1603,9 @@
}
},
"node_modules/winston/node_modules/async": {
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/async/-/async-3.2.0.tgz",
"integrity": "sha512-TR2mEZFVOj2pLStYxLht7TyfuRzaydfpxr3k9RpHIzMgw7A64dzsdqCxH1WJyQdoe8T10nDXd9wnEigmiuHIZw=="
"version": "3.2.1",
"resolved": "https://registry.npmjs.org/async/-/async-3.2.1.tgz",
"integrity": "sha512-XdD5lRO/87udXCMC9meWdYiR+Nq6ZjUfXidViUZGu2F1MO4T3XwZ1et0hb2++BgLfhyJwy44BGB/yx80ABx8hg=="
},
"node_modules/wrappy": {
"version": "1.0.2",
@ -1622,14 +1625,14 @@
}
},
"@fortawesome/fontawesome-free": {
"version": "5.15.3",
"resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-free/-/fontawesome-free-5.15.3.tgz",
"integrity": "sha512-rFnSUN/QOtnOAgqFRooTA3H57JLDm0QEG/jPdk+tLQNL/eWd+Aok8g3qCI+Q1xuDPWpGW/i9JySpJVsq8Q0s9w=="
"version": "5.15.4",
"resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-free/-/fontawesome-free-5.15.4.tgz",
"integrity": "sha512-eYm8vijH/hpzr/6/1CJ/V/Eb1xQFW2nnUKArb3z+yUWv7HTwj6M7SP957oMjfZjAHU6qpoNc2wQvIxBLWYa/Jg=="
},
"@popperjs/core": {
"version": "2.9.2",
"resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.9.2.tgz",
"integrity": "sha512-VZMYa7+fXHdwIq1TDhSXoVmSPEGM/aa+6Aiq3nVVJ9bXr24zScr+NlKFKC3iPljA7ho/GAZr+d2jOf5GIRC30Q==",
"version": "2.10.1",
"resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.10.1.tgz",
"integrity": "sha512-HnUhk1Sy9IuKrxEMdIRCxpIqPw6BFsbYSEUO9p/hNw5sMld/+3OLMWQP80F8/db9qsv3qUjs7ZR5bS/R+iinXw==",
"peer": true
},
"@sindresorhus/is": {
@ -1638,9 +1641,9 @@
"integrity": "sha512-Qm9hBEBu18wt1PO2flE7LPb30BHMQt1eQgbV76YntdNk73XZGpn3izvGTYxbGgzXKgbCjiia0uxTd3aTNQrY/g=="
},
"@szmarczak/http-timer": {
"version": "4.0.5",
"resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-4.0.5.tgz",
"integrity": "sha512-PyRA9sm1Yayuj5OIoJ1hGt2YISX45w9WcFbh6ddT0Z/0yaFxOtGLInr4jUfU1EAFVs0Yfyfev4RNwBlUaHdlDQ==",
"version": "4.0.6",
"resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-4.0.6.tgz",
"integrity": "sha512-4BAffykYOgO+5nzBWYwE3W90sBgLJoUPRWWcL8wlyiM8IB8ipJz3UMJ9KXQd1RKQXpKp8Tutn80HZtWsu2u76w==",
"requires": {
"defer-to-connect": "^2.0.0"
}
@ -1670,9 +1673,9 @@
}
},
"@types/node": {
"version": "16.0.1",
"resolved": "https://registry.npmjs.org/@types/node/-/node-16.0.1.tgz",
"integrity": "sha512-hBOx4SUlEPKwRi6PrXuTGw1z6lz0fjsibcWCM378YxsSu/6+C30L6CR49zIBKHiwNWCYIcOLjg4OHKZaFeLAug=="
"version": "16.7.13",
"resolved": "https://registry.npmjs.org/@types/node/-/node-16.7.13.tgz",
"integrity": "sha512-pLUPDn+YG3FYEt/pHI74HmnJOWzeR+tOIQzUx93pi9M7D8OE7PSLr97HboXwk5F+JS+TLtWuzCOW97AHjmOXXA=="
},
"@types/responselike": {
"version": "1.0.0",
@ -1720,11 +1723,11 @@
"integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k="
},
"axios": {
"version": "0.21.1",
"resolved": "https://registry.npmjs.org/axios/-/axios-0.21.1.tgz",
"integrity": "sha512-dKQiRHxGD9PPRIUNIWvZhPTPpl1rf/OxTYKsqKUDjBwYylTvV7SjSHJb9ratfyzM6wCdLCOYLzs73qpg5c4iGA==",
"version": "0.21.4",
"resolved": "https://registry.npmjs.org/axios/-/axios-0.21.4.tgz",
"integrity": "sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg==",
"requires": {
"follow-redirects": "^1.10.0"
"follow-redirects": "^1.14.0"
}
},
"balanced-match": {
@ -1795,9 +1798,9 @@
}
},
"bootstrap": {
"version": "5.0.2",
"resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-5.0.2.tgz",
"integrity": "sha512-1Ge963tyEQWJJ+8qtXFU6wgmAVj9gweEjibUdbmcCEYsn38tVwRk8107rk2vzt6cfQcRr3SlZ8aQBqaD8aqf+Q==",
"version": "5.1.0",
"resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-5.1.0.tgz",
"integrity": "sha512-bs74WNI9BgBo3cEovmdMHikSKoXnDgA6VQjJ7TyTotU6L7d41ZyCEEelPwkYEzsG/Zjv3ie9IE3EMAje0W9Xew==",
"requires": {}
},
"brace-expansion": {
@ -1879,9 +1882,9 @@
"integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU="
},
"color-string": {
"version": "1.5.5",
"resolved": "https://registry.npmjs.org/color-string/-/color-string-1.5.5.tgz",
"integrity": "sha512-jgIoum0OfQfq9Whcfc2z/VhCNcmQjWbey6qBX0vqt7YICflUmBCh9E9CiQD5GSJ+Uehixm3NUwHVhqUAWRivZg==",
"version": "1.6.0",
"resolved": "https://registry.npmjs.org/color-string/-/color-string-1.6.0.tgz",
"integrity": "sha512-c/hGS+kRWJutUBEngKKmk4iH3sD59MBkoxVapS/0wgpCz2u7XsNloxknyvBhzwEs1IbV36D9PwqLPJ2DTu3vMA==",
"requires": {
"color-name": "^1.0.0",
"simple-swizzle": "^0.2.2"
@ -1947,9 +1950,9 @@
"integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw="
},
"core-util-is": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
"integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac="
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz",
"integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ=="
},
"cron": {
"version": "1.8.2",
@ -2106,9 +2109,9 @@
}
},
"fast-safe-stringify": {
"version": "2.0.7",
"resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.0.7.tgz",
"integrity": "sha512-Utm6CdzT+6xsDk2m8S6uL8VHxNwI6Jub+e9NYTcAms28T84pTa25GJQV9j0CY0N1rM8hK4x6grpF2BQf+2qwVA=="
"version": "2.0.8",
"resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.0.8.tgz",
"integrity": "sha512-lXatBjf3WPjmWD6DpIZxkeSsCOwqI0maYMpgDlx8g4U2qi4lbjA9oH/HD2a87G+KfsUmo5WbJFmqBZlPxtptag=="
},
"fast-xml-parser": {
"version": "3.19.0",
@ -2163,9 +2166,9 @@
"integrity": "sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw=="
},
"follow-redirects": {
"version": "1.14.1",
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.1.tgz",
"integrity": "sha512-HWqDgT7ZEkqRzBvc2s64vSZ/hfOceEol3ac/7tKwzuvEyWx3/4UegXh5oBOIotkGsObyk3xznnSRVADBgWSQVg=="
"version": "1.14.3",
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.3.tgz",
"integrity": "sha512-3MkHxknWMUtb23apkgz/83fDoe+y+qr0TdgacGIA7bew+QLBo3vdgEN2xEsuXNivpFy4CyDhBBZnNZOtalmenw=="
},
"form-data": {
"version": "4.0.0",
@ -2290,9 +2293,9 @@
"integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w=="
},
"is-stream": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.0.tgz",
"integrity": "sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw=="
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz",
"integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg=="
},
"isarray": {
"version": "1.0.0",
@ -2386,16 +2389,16 @@
"integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg=="
},
"mime-db": {
"version": "1.48.0",
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.48.0.tgz",
"integrity": "sha512-FM3QwxV+TnZYQ2aRqhlKBMHxk10lTbMt3bBkMAp54ddrNeVSfcQYOOKuGuy3Ddrm38I04If834fOUSq1yzslJQ=="
"version": "1.49.0",
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.49.0.tgz",
"integrity": "sha512-CIc8j9URtOVApSFCQIF+VBkX1RwXp/oMMOrqdyXSBXq5RWNEsRfyj1kiRnQgmNXmHxPoFIxOroKA3zcU9P+nAA=="
},
"mime-types": {
"version": "2.1.31",
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.31.tgz",
"integrity": "sha512-XGZnNzm3QvgKxa8dpzyhFTHmpP3l5YNusmne07VUOXxou9CqUqYa/HBy124RqtVh/O2pECas/MOcsDgpilPOPg==",
"version": "2.1.32",
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.32.tgz",
"integrity": "sha512-hJGaVS4G4c9TSMYh2n6SQAGrC4RnfU+daP8G7cSCmaqNjiOoUY0VHCMS42pxnQmVF1GWwFhbHWn3RIxCqTmZ9A==",
"requires": {
"mime-db": "1.48.0"
"mime-db": "1.49.0"
}
},
"mimic-response": {
@ -2614,9 +2617,9 @@
"integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8="
},
"resolve-alpn": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/resolve-alpn/-/resolve-alpn-1.1.2.tgz",
"integrity": "sha512-8OyfzhAtA32LVUsJSke3auIyINcwdh5l3cvYKdKO0nvsYSKuiLfTM5i78PJswFPT8y6cPW+L1v6/hE95chcpDA=="
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/resolve-alpn/-/resolve-alpn-1.2.1.tgz",
"integrity": "sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g=="
},
"responselike": {
"version": "2.0.0",
@ -2782,9 +2785,9 @@
"integrity": "sha512-jk1+QP6ZJqyOiuEI9AEWQfju/nB2Pw466kbA0LEZljHwKeMgd9WrAEgEGxjPDD2+TNbbb37rTyhEfrCXfuKXnA=="
},
"url-parse": {
"version": "1.5.1",
"resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.1.tgz",
"integrity": "sha512-HOfCOUJt7iSYzEx/UqgtwKRMC6EU91NFhsCHMv9oM03VJcVo2Qrp8T8kI9D7amFf1cu+/3CEhgb3rF9zL7k85Q==",
"version": "1.5.3",
"resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.3.tgz",
"integrity": "sha512-IIORyIQD9rvj0A4CLWsHkBBJuNqWpFQe224b6j9t/ABmquIS0qDU2pY6kl6AuOrL5OkCXHMCFNe1jBcuAggjvQ==",
"requires": {
"querystringify": "^2.1.1",
"requires-port": "^1.0.0"
@ -2806,9 +2809,9 @@
"integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw="
},
"webdav": {
"version": "4.6.0",
"resolved": "https://registry.npmjs.org/webdav/-/webdav-4.6.0.tgz",
"integrity": "sha512-amL/NeZ73xe8cNC+uqAF3mOC/j5dNoNWlZswYCd7DKxhnZM7dViAVSv6gdCYeGAETjPEZVubcKDDRwGKz9ShQQ==",
"version": "4.7.0",
"resolved": "https://registry.npmjs.org/webdav/-/webdav-4.7.0.tgz",
"integrity": "sha512-R1WZl/JeFPAmSEn1EPCmxSdPY8IxS/P0qnxAzBeRqEewpxVJ/UiCMJwXHLpyVsKYA1PIb1dYv+UTQsbNaQnLBw==",
"requires": {
"axios": "^0.21.1",
"base-64": "^1.0.0",
@ -2821,7 +2824,7 @@
"nested-property": "^4.0.0",
"path-posix": "^1.0.0",
"url-join": "^4.0.1",
"url-parse": "^1.5.1"
"url-parse": "^1.5.3"
}
},
"winston": {
@ -2841,9 +2844,9 @@
},
"dependencies": {
"async": {
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/async/-/async-3.2.0.tgz",
"integrity": "sha512-TR2mEZFVOj2pLStYxLht7TyfuRzaydfpxr3k9RpHIzMgw7A64dzsdqCxH1WJyQdoe8T10nDXd9wnEigmiuHIZw=="
"version": "3.2.1",
"resolved": "https://registry.npmjs.org/async/-/async-3.2.1.tgz",
"integrity": "sha512-XdD5lRO/87udXCMC9meWdYiR+Nq6ZjUfXidViUZGu2F1MO4T3XwZ1et0hb2++BgLfhyJwy44BGB/yx80ABx8hg=="
}
}
},

View File

@ -7,51 +7,48 @@ const default_toast_timeout = 10000;
let loadingModal;
let nextcloud_setting_modal;
let backup_setting_modal;
document.addEventListener('DOMContentLoaded', function () {
document.addEventListener("DOMContentLoaded", function () {
$.ajaxSetup({ traditional: true });
updateLocalSnaps();
update_status();
loadingModal = new bootstrap.Modal(document.getElementById('loading-modal'), {
loadingModal = new bootstrap.Modal(document.getElementById("loading-modal"), {
keyboard: false,
backdrop: 'static'
backdrop: "static",
});
nextcloud_setting_modal = new bootstrap.Modal(document.getElementById('modal-settings-nextcloud'));
backup_setting_modal = new bootstrap.Modal(document.getElementById('modal-settings-backup'));
nextcloud_setting_modal = new bootstrap.Modal(document.getElementById("modal-settings-nextcloud"));
backup_setting_modal = new bootstrap.Modal(document.getElementById("modal-settings-backup"));
setInterval(update_status, 500);
setInterval(updateLocalSnaps, 5000);
listeners();
});
function updateDynamicListeners() {
$('.local-snap-listener').click(function () {
let id = this.getAttribute('data-id');
$(".local-snap-listener").on("click", function () {
let id = this.getAttribute("data-id");
console.log(id);
});
let manual_back_list = $('.manual-back-list');
manual_back_list.unbind();
manual_back_list.click(function () {
let id = this.getAttribute('data-id');
let name = this.getAttribute('data-name');
let manual_back_list = $(".manual-back-list");
manual_back_list.off();
manual_back_list.on("click", function () {
let id = this.getAttribute("data-id");
let name = this.getAttribute("data-name");
manualBackup(id, name);
})
$('.restore').click(function () {
let to_restore = this.getAttribute('data-id');
console.log(to_restore)
restore(to_restore)
})
});
$(".restore").click(function () {
let to_restore = this.getAttribute("data-id");
console.log(to_restore);
restore(to_restore);
});
}
function updateLocalSnaps() {
let needUpdate = false;
$.get('./api/formated-local-snap', (data) => {
if (JSON.stringify(data) === last_local_snap)
return;
$.get("./api/formated-local-snap", (data) => {
if (JSON.stringify(data) === last_local_snap) return;
last_local_snap = JSON.stringify(data);
needUpdate = true;
let local_snaps = $('#local_snaps');
let local_snaps = $("#local_snaps");
local_snaps.empty();
local_snaps.html(data);
}).always(() => {
@ -61,15 +58,13 @@ function updateLocalSnaps() {
function updateManuBackup(prevUpdate) {
let needUpdate = false;
$.get('./api/formated-backup-manual', (data) => {
if (JSON.stringify(data) === last_manu_back)
return;
$.get("./api/formated-backup-manual", (data) => {
if (JSON.stringify(data) === last_manu_back) return;
last_manu_back = JSON.stringify(data);
needUpdate = true;
let manual_backups = $('#manual_backups')
let manual_backups = $("#manual_backups");
manual_backups.empty();
manual_backups.html(data);
}).always(() => {
updateAutoBackup(prevUpdate || needUpdate);
});
@ -77,157 +72,145 @@ function updateManuBackup(prevUpdate) {
function updateAutoBackup(prevUpdate) {
let needUpdate = false;
$.get('./api/formated-backup-auto', (data) => {
if (JSON.stringify(data) === last_auto_back)
return;
$.get("./api/formated-backup-auto", (data) => {
if (JSON.stringify(data) === last_auto_back) return;
needUpdate = true;
last_auto_back = JSON.stringify(data);
let auto_backups = $('#auto_backups')
let auto_backups = $("#auto_backups");
auto_backups.empty();
auto_backups.html(data);
}).always(() => {
if (prevUpdate || needUpdate)
updateDynamicListeners();
if (prevUpdate || needUpdate) updateDynamicListeners();
});
}
function update_status() {
$.get('./api/status', (data) => {
$.get("./api/status", (data) => {
if (JSON.stringify(data) !== last_status) {
last_status = JSON.stringify(data);
let buttons = $('#btn-backup-now, #btn-clean-now');
let buttons = $("#btn-backup-now, #btn-clean-now");
switch (data.status) {
case "error":
printStatus('Error', data.message);
printStatus("Error", data.message);
buttons.removeClass("disabled");
break;
case "idle":
printStatus('Idle', "Waiting for next backup.");
printStatus("Idle", "Waiting for next backup.");
buttons.removeClass("disabled");
break;
case "download":
printStatusWithBar('Downloading Snapshot', data.progress);
printStatusWithBar("Downloading Snapshot", data.progress);
buttons.addClass("disabled");
break;
case "download-b":
printStatusWithBar('Downloading Backup', data.progress);
printStatusWithBar("Downloading Backup", data.progress);
buttons.addClass("disabled");
break;
case "upload":
printStatusWithBar('Uploading Snapshot', data.progress);
printStatusWithBar("Uploading Snapshot", data.progress);
buttons.addClass("disabled");
break;
case "upload-b":
printStatusWithBar('Uploading Snapshot', data.progress);
printStatusWithBar("Uploading Snapshot", data.progress);
buttons.addClass("disabled");
break;
case "creating":
printStatusWithBar('Creating Snapshot', data.progress);
printStatusWithBar("Creating Snapshot", data.progress);
buttons.addClass("disabled");
break;
case "stopping":
printStatusWithBar('Stopping addons', data.progress);
printStatusWithBar("Stopping addons", data.progress);
buttons.addClass("disabled");
break;
case "starting":
printStatusWithBar('Starting addons', data.progress);
printStatusWithBar("Starting addons", data.progress);
buttons.addClass("disabled");
break;
}
if (data.last_backup != null) {
let last_back_status = $('#last_back_status');
if (last_back_status.html() !== data.last_backup)
last_back_status.html(data.last_backup);
let last_back_status = $("#last_back_status");
if (last_back_status.html() !== data.last_backup) last_back_status.html(data.last_backup);
}
if (data.next_backup != null) {
let next_back_status = $('#next_back_status');
if (next_back_status.html() !== data.next_backup)
next_back_status.html(data.next_backup);
let next_back_status = $("#next_back_status");
if (next_back_status.html() !== data.next_backup) next_back_status.html(data.next_backup);
}
}
});
}
function printStatus(status, secondLine) {
let status_jq = $('#status');
let status_jq = $("#status");
status_jq.empty();
status_jq.html(status);
let status_s_l_jq = $('#status-second-line');
let status_s_l_jq = $("#status-second-line");
status_s_l_jq.empty();
status_s_l_jq.removeClass('text-center');
status_s_l_jq.removeClass("text-center");
status_s_l_jq.html(secondLine);
$('#progress').addClass("invisible");
$("#progress").addClass("invisible");
}
function printStatusWithBar(status, progress) {
let status_jq = $('#status')
let status_jq = $("#status");
status_jq.empty();
status_jq.html(status);
let secondLine = $('#status-second-line')
let secondLine = $("#status-second-line");
secondLine.empty();
secondLine.html(progress === -1 ? "Waiting..." : (Math.round(progress * 100) + "%"));
secondLine.html(progress === -1 ? "Waiting..." : Math.round(progress * 100) + "%");
secondLine.addClass("text-center");
let progressDiv = $('#progress');
let progressDiv = $("#progress");
progressDiv.removeClass("invisible");
if (progress === -1) {
progressDiv.children().css('width', "100%");
progressDiv.children().addClass('progress-bar-striped progress-bar-animated');
progressDiv.children().css("width", "100%");
progressDiv.children().addClass("progress-bar-striped progress-bar-animated");
} else {
progressDiv.children().removeClass('progress-bar-striped progress-bar-animated');
progressDiv.children().css('width', (progress * 100) + "%");
progressDiv.children().removeClass("progress-bar-striped progress-bar-animated");
progressDiv.children().css("width", progress * 100 + "%");
}
}
function listeners() {
$('#btn-backup-now').click(backupNow);
$('#btn-clean-now').click(cleanNow);
$("#btn-backup-now").on("click", backupNow);
$("#btn-clean-now").on("click", cleanNow);
$('#trigger-backup-settings').click(getBackupSettings);
$('#password_protected').change(function () {
if (!$(this).is(':checked')) {
$('#password_protect_value').parent().parent().addClass('d-none');
$("#trigger-backup-settings").on("click", getBackupSettings);
$("#password_protected").on("change", function () {
if (!$(this).is(":checked")) {
$("#password_protect_value").parent().parent().addClass("d-none");
} else {
$('#password_protect_value').parent().parent().removeClass('d-none');
}
})
$('#cron-drop-settings').change(updateDropVisibility);
$('#save-backup-settings').click(sendBackupSettings);
$('#auto_clean_local').change(function () {
if (!$(this).is(':checked')) {
$('#local-snap-keep').parent().parent().addClass("d-none");
} else {
$('#local-snap-keep').parent().parent().removeClass("d-none");
$("#password_protect_value").parent().parent().removeClass("d-none");
}
});
$('#auto_clean_backup').change(function () {
if (!$(this).is(':checked')) {
$('#backup-snap-keep').parent().parent().addClass("d-none");
$("#cron-drop-settings").on("change", updateDropVisibility);
$("#save-backup-settings").click(sendBackupSettings);
$("#auto_clean_local").on("change", function () {
if (!$(this).is(":checked")) {
$("#local-snap-keep").parent().parent().addClass("d-none");
} else {
$('#backup-snap-keep').parent().parent().removeClass("d-none");
$("#local-snap-keep").parent().parent().removeClass("d-none");
}
});
$("#auto_clean_backup").on("change", function () {
if (!$(this).is(":checked")) {
$("#backup-snap-keep").parent().parent().addClass("d-none");
} else {
$("#backup-snap-keep").parent().parent().removeClass("d-none");
}
});
$('#trigger-nextcloud-settings').click(getNextcloudSettings);
$('#save-nextcloud-settings').click(sendNextcloudSettings);
$('#ssl').change(function () {
let div = $('#self_signed').parent().parent();
if ($('#ssl').is(':checked'))
div.removeClass("invisible")
else
div.addClass("invisible");
$("#trigger-nextcloud-settings").click(getNextcloudSettings);
$("#save-nextcloud-settings").click(sendNextcloudSettings);
$("#ssl").on("change", function () {
let div = $("#self_signed").parent().parent();
if ($("#ssl").is(":checked")) div.removeClass("invisible");
else div.addClass("invisible");
});
}
function restore(id) {
loadingModal.show();
$.post('./api/restore', { path: id })
$.post("./api/restore", { path: id })
.done(() => {
console.log("Restore cmd send !");
create_toast("success", "Command sent !", default_toast_timeout);
@ -236,49 +219,48 @@ function restore(id) {
console.log(error);
create_toast("error", "Can't send command !", default_toast_timeout);
})
.always(() => loadingModal.hide())
.always(() => loadingModal.hide());
}
function sendNextcloudSettings() {
loadingModal.show();
nextcloud_setting_modal.hide();
let ssl = $('#ssl').is(':checked')
let self_signed = $('#self_signed').is(':checked')
let hostname = $('#hostname').val();
let username = $('#username').val();
let password = $('#password').val();
let back_dir = $('#back-dir').val();
$.post('./api/nextcloud-settings', {
let ssl = $("#ssl").is(":checked");
let self_signed = $("#self_signed").is(":checked");
let hostname = $("#hostname").val();
let username = $("#username").val();
let password = $("#password").val();
let back_dir = $("#back-dir").val();
$.post("./api/nextcloud-settings", {
ssl: ssl,
host: hostname,
username: username,
password: password,
back_dir: back_dir,
self_signed: self_signed
self_signed: self_signed,
})
.done(() => {
console.log('Saved');
$('#nextcloud_settings_message').parent().addClass("d-none");
console.log("Saved");
$("#nextcloud_settings_message").parent().addClass("d-none");
create_toast("success", "Nextcloud settings saved !", default_toast_timeout);
0
0;
})
.fail((data) => {
let nextcloud_settings_message = $('#nextcloud_settings_message')
let nextcloud_settings_message = $("#nextcloud_settings_message");
if (data.status === 406) {
console.log(data.responseJSON.message);
nextcloud_settings_message.html(data.responseJSON.message);
} else {
nextcloud_settings_message.html("Invalid Settings.");
}
nextcloud_settings_message.parent().removeClass("d-none");
nextcloud_setting_modal.show();
create_toast("error", "Invalid Nextcloud settings !", default_toast_timeout);
console.log('Fail');
}).always(() => {
loadingModal.hide();
console.log("Fail");
})
.always(() => {
loadingModal.hide();
});
}
function manualBackup(id, name) {
@ -290,40 +272,40 @@ function manualBackup(id, name) {
.fail((error) => {
console.log(error);
create_toast("error", "Can't send command !", default_toast_timeout);
})
});
}
function getNextcloudSettings() {
loadingModal.show();
$.get('./api/nextcloud-settings', (data) => {
$('#ssl').prop("checked", data.ssl === "true");
let sef_signed_jq = $('#self_signed')
$.get("./api/nextcloud-settings", (data) => {
$("#ssl").prop("checked", data.ssl === "true");
let sef_signed_jq = $("#self_signed");
if (data.ssl === "true") {
let div = sef_signed_jq.parent().parent();
div.removeClass("invisible");
}
sef_signed_jq.prop('checked', data.self_signed === "true")
$('#hostname').val(data.host);
$('#username').val(data.username);
$('#password').val(data.password);
$('#back-dir').val(data.back_dir);
nextcloud_setting_modal.show();
}).fail((error) => {
if (error.status === 404)
sef_signed_jq.prop("checked", data.self_signed === "true");
$("#hostname").val(data.host);
$("#username").val(data.username);
$("#password").val(data.password);
$("#back-dir").val(data.back_dir);
nextcloud_setting_modal.show();
})
.fail((error) => {
if (error.status === 404) nextcloud_setting_modal.show();
else {
console.log(error);
create_toast("error", "Failed to fetch Nextcloud config !", default_toast_timeout);
}
}).always(() => {
})
.always(() => {
loadingModal.hide();
});
}
function backupNow() {
loadingModal.show();
$.post('./api/new-backup')
$.post("./api/new-backup")
.done(() => {
create_toast("success", "Command sent !", default_toast_timeout);
})
@ -333,12 +315,12 @@ function backupNow() {
})
.always(() => {
loadingModal.hide();
})
});
}
function cleanNow() {
loadingModal.show();
$.post('./api/clean-now')
$.post("./api/clean-now")
.done(() => {
create_toast("success", "Command sent !", default_toast_timeout);
})
@ -348,141 +330,158 @@ function cleanNow() {
})
.always(() => {
loadingModal.hide();
})
});
}
function getBackupSettings() {
loadingModal.show();
$.get('./api/backup-settings', (data) => {
$.get("./api/backup-settings", (data) => {
if (JSON.stringify(data) === "{}") {
data = {
settings: {
cron_base: "0",
cron_hour: "00:00",
cron_weekday: "0",
cron_month_day: "1",
cron_custom: "5 4 * * *",
auto_clean_local: false,
auto_clean_local_keep: 5,
auto_clean_backup: false,
auto_clean_backup_keep: 5,
}
};
}
if (data.settings.cron_custom == null || data.settings.cron_custom == "") {
data.settings.cron_custom = "5 4 * * *";
}
$('#cron-drop-settings').val(data.settings.cron_base);
$('#name-template').val(data.settings.name_template);
$("#cron-drop-settings").val(data.settings.cron_base);
$("#name-template").val(data.settings.name_template);
$("#timepicker").val(data.settings.cron_hour);
$("#cron-drop-day-month-read").val(data.settings.cron_month_day);
$("#cron-drop-day-month").val(data.settings.cron_month_day);
$("#cron-drop-custom").val(data.settings.cron_custom);
$('#timepicker').val(data.settings.cron_hour);
$('#cron-drop-day-month-read').val(data.settings.cron_month_day);
$('#cron-drop-day-month').val(data.settings.cron_month_day);
$('#auto_clean_local').prop('checked', data.settings.auto_clean_local === "true");
let local_snap_keep = $('#local-snap-keep');
if (data.settings.auto_clean_local === "true")
local_snap_keep.parent().parent().removeClass("d-none");
else
local_snap_keep.parent().parent().addClass("d-none");
$("#auto_clean_local").prop("checked", data.settings.auto_clean_local === "true");
let local_snap_keep = $("#local-snap-keep");
if (data.settings.auto_clean_local === "true") local_snap_keep.parent().parent().removeClass("d-none");
else local_snap_keep.parent().parent().addClass("d-none");
local_snap_keep.val(data.settings.auto_clean_local_keep);
$('#auto_clean_backup').prop('checked', data.settings.auto_clean_backup === "true");
let backup_snap_keep = $('#backup-snap-keep');
if (data.settings.auto_clean_backup === "true")
backup_snap_keep.parent().parent().removeClass("d-none");
else
backup_snap_keep.parent().parent().addClass("d-none");
$("#auto_clean_backup").prop("checked", data.settings.auto_clean_backup === "true");
let backup_snap_keep = $("#backup-snap-keep");
if (data.settings.auto_clean_backup === "true") backup_snap_keep.parent().parent().removeClass("d-none");
else backup_snap_keep.parent().parent().addClass("d-none");
backup_snap_keep.val(data.settings.auto_clean_backup_keep);
$('#cron-drop-day').val(data.settings.cron_weekday);
let folder_html = ""
$("#cron-drop-day").val(data.settings.cron_weekday);
let folder_html = "";
for (let thisFolder of data.folders) {
let exclude = data.settings.exclude_folder.includes(thisFolder.slug);
folder_html += `<li class="list-group-item"><div class="form-check"><input class="form-check-input folders-box" type="checkbox" id="${thisFolder.slug}" ${exclude ? "" : "checked"}><label class="form-label mb-0" for="${thisFolder.slug}">${thisFolder.name}</label></div></li>`
folder_html += `<li class="list-group-item"><div class="form-check"><input class="form-check-input folders-box" type="checkbox" id="${
thisFolder.slug
}" ${exclude ? "" : "checked"}><label class="form-label mb-0" for="${thisFolder.slug}">${thisFolder.name}</label></div></li>`;
}
$("#folders-div").html(folder_html);
let addons_html = ""
let addons_html = "";
for (let thisAddon of data.addonList) {
let exclude = data.settings.exclude_addon.includes(thisAddon.slug);
addons_html += `<li class="list-group-item"><div class="form-check"><input class="form-check-input addons-box" type="checkbox" id="${thisAddon.slug}" ${exclude ? "" : "checked"}><label class="form-label mb-0" for="${thisAddon.slug}">${thisAddon.name}</label></div></li>`
addons_html += `<li class="list-group-item"><div class="form-check"><input class="form-check-input addons-box" type="checkbox" id="${
thisAddon.slug
}" ${exclude ? "" : "checked"}><label class="form-label mb-0" for="${thisAddon.slug}">${thisAddon.name}</label></div></li>`;
}
$("#addons-div").html(addons_html);
let addons_stop_html = ""
let addons_stop_html = "";
for (let thisAddon of data.addonList) {
if (thisAddon.slug !== "229cc4d7_nextcloud_backup"){
if (thisAddon.slug !== "229cc4d7_nextcloud_backup") {
let on = data.settings.auto_stop_addon.includes(thisAddon.slug);
addons_stop_html += `<li class="list-group-item"><div class="form-check"><input class="form-check-input stop-addons-box" type="checkbox" id="${thisAddon.slug}" ${on ? "checked" : ""}><label class="form-label mb-0" for="${thisAddon.slug}">${thisAddon.name}</label></div></li>`
addons_stop_html += `<li class="list-group-item"><div class="form-check"><input class="form-check-input stop-addons-box" type="checkbox" id="${
thisAddon.slug
}" ${on ? "checked" : ""}><label class="form-label mb-0" for="${thisAddon.slug}">${thisAddon.name}</label></div></li>`;
}
}
$("#auto-stop-addons-div").html(addons_stop_html);
updateDropVisibility();
backup_setting_modal.show();
}).fail((error) => {
})
.fail((error) => {
console.log(error);
create_toast("error", "Failed to fetch Nextcloud config !", default_toast_timeout);
}).always(() => {
})
.always(() => {
loadingModal.hide();
});
}
function updateDropVisibility() {
let cronBase = $("#cron-drop-settings").val();
let timepicker = $('#timepicker');
let cron_drop_day = $('#cron-drop-day');
let cron_drop_day_mount = $('#cron-drop-day-month');
let timepicker = $("#timepicker");
let cron_drop_day = $("#cron-drop-day");
let cron_drop_day_mount = $("#cron-drop-day-month");
let cron_drop_custom = $("#cron-drop-custom");
switch (cronBase) {
case "4":
timepicker.parent().parent().addClass("d-none");
cron_drop_day.parent().parent().addClass("d-none");
cron_drop_day_mount.parent().parent().addClass("d-none");
cron_drop_custom.parent().parent().removeClass("d-none");
break;
case "3":
timepicker.parent().parent().removeClass("d-none");
cron_drop_day.parent().parent().addClass("d-none");
cron_drop_day_mount.parent().parent().removeClass("d-none");
cron_drop_custom.parent().parent().addClass("d-none");
break;
case "2":
timepicker.parent().parent().removeClass("d-none");
cron_drop_day.parent().parent().removeClass("d-none");
cron_drop_day_mount.parent().parent().addClass("d-none");
cron_drop_custom.parent().parent().addClass("d-none");
break;
case "1":
timepicker.parent().parent().removeClass("d-none");
cron_drop_day.parent().parent().addClass("d-none");
cron_drop_day_mount.parent().parent().addClass("d-none");
cron_drop_custom.parent().parent().addClass("d-none");
break;
case "0":
timepicker.parent().parent().addClass("d-none");
cron_drop_day.parent().parent().addClass("d-none");
cron_drop_day_mount.parent().parent().addClass("d-none");
cron_drop_custom.parent().parent().addClass("d-none");
break;
}
}
function sendBackupSettings() {
let cron_month_day = $('#cron-drop-day-month').val();
let cron_weekday = $('#cron-drop-day').val();
let cron_hour = $('#timepicker').val();
let cron_base = $('#cron-drop-settings').val();
let auto_clean_local = $("#auto_clean_local").is(':checked');
let auto_clean_backup = $("#auto_clean_backup").is(':checked');
let cron_month_day = $("#cron-drop-day-month").val();
let cron_weekday = $("#cron-drop-day").val();
let cron_hour = $("#timepicker").val();
let cron_custom = $("#cron-drop-custom").val();
let cron_base = $("#cron-drop-settings").val();
let auto_clean_local = $("#auto_clean_local").is(":checked");
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();
let excluded_folders_nodes = document.querySelectorAll('.folders-box:not(:checked)');
let name_template = $("#name-template").val();
let excluded_folders_nodes = document.querySelectorAll(".folders-box:not(:checked)");
let exclude_folder = [""];
let password_protected = $('#password_protected').is(':checked');
let password_protect_value = $('#password_protect_value').val();
let password_protected = $("#password_protected").is(":checked");
let password_protect_value = $("#password_protect_value").val();
for (let i of excluded_folders_nodes) {
exclude_folder.push(i.id);
}
let excluded_addons_nodes = document.querySelectorAll('.addons-box:not(:checked)');
let excluded_addons_nodes = document.querySelectorAll(".addons-box:not(:checked)");
let exclude_addon = [""];
for (let i of excluded_addons_nodes) {
exclude_addon.push(i.id);
}
let stop_addons_nodes = document.querySelectorAll('.stop-addons-box:checked');
let stop_addons_nodes = document.querySelectorAll(".stop-addons-box:checked");
let stop_addon = [""];
for (let i of stop_addons_nodes) {
stop_addon.push(i.id);
@ -490,13 +489,13 @@ function sendBackupSettings() {
loadingModal.show();
backup_setting_modal.hide();
$.post('./api/backup-settings',
{
$.post("./api/backup-settings", {
name_template: name_template,
cron_base: cron_base,
cron_hour: cron_hour,
cron_weekday: cron_weekday,
cron_month_day: cron_month_day,
cron_custom: cron_custom,
auto_clean_local: auto_clean_local,
auto_clean_local_keep: auto_clean_local_keep,
auto_clean_backup: auto_clean_backup,
@ -505,14 +504,14 @@ function sendBackupSettings() {
exclude_folder: exclude_folder,
auto_stop_addon: stop_addon,
password_protected: password_protected,
password_protect_value: password_protect_value
password_protect_value: password_protect_value,
})
.done(() => {
create_toast("success", "Backup settings saved !", default_toast_timeout);
})
.fail(() => {
create_toast("error", "Can't save backup settings !", default_toast_timeout);
.fail((data) => {
debugger
create_toast("error", `Can't save backup settings ! <br> Error: ${data.responseText}`, default_toast_timeout);
backup_setting_modal.show();
})
.always(() => {

View File

@ -188,13 +188,14 @@ router.get("/backup-settings", function (req, res, next) {
});
router.post("/backup-settings", function (req, res, next) {
if (settingsTools.check(req.body)) {
let [result, message] = settingsTools.check(req.body)
if (result) {
settingsTools.setSettings(req.body);
cronTools.startCron();
res.send();
} else {
res.status(400);
res.send();
res.send(message);
}
});

View File

@ -64,6 +64,10 @@ class CronContainer {
cronStr = "" + splited[1] + " " + splited[0] + " " + settings.cron_month_day + " * *";
break;
}
case "4": {
cronStr = settings.cron_custom;
break;
}
}
logger.info("Starting Cron...");
this.cronJob = new CronJob(cronStr, this._createBackup, null, false, Intl.DateTimeFormat().resolvedOptions().timeZone);

View File

@ -457,7 +457,7 @@ function startAddons() {
let promises = [];
let token = process.env.HASSIO_TOKEN;
let option = {
headers: { "X-HASSIO-KEY": token },
headers: { "Authorization": `Bearer ${token}` },
responseType: "json",
};
let addons_slug = settingsTools.getSettings().auto_stop_addon
@ -494,6 +494,76 @@ function startAddons() {
}));
}
function publish_state(state){
let data_error_sensor = {
state: state.status == "error" ? "on" : "off",
attributes: {
friendly_name: "Nexcloud Backup Error",
device_class: "problem",
error_code: state.error_code,
message: state.message,
icon: state.status == "error" ? "mdi:cloud-alert" : "mdi:cloud-check"
},
}
let token = process.env.HASSIO_TOKEN;
let option = {
headers: { "Authorization": `Bearer ${token}` },
responseType: "json",
json: data_error_sensor
};
got.post(`http://hassio/core/api/states/binary_sensor.nextcloud_backup_error`, option)
.then((result) => {
logger.debug('Home assistant sensor updated (error status)');
})
.catch((error) => {
logger.error(error);
});
let icon = ""
switch(state.status){
case "error":
icon = "mdi:cloud-alert";
break;
case "download":
case "download-b":
icon = "mdi:cloud-download";
break;
case "upload":
case "upload-b":
icon = "mdi:cloud-upload";
break;
case "idle":
icon = "mdi:cloud-check";
break;
default:
icon = "mdi:cloud-sync";
break;
}
let data_state_sensor = {
state: state.status,
attributes: {
friendly_name: "Nexcloud Backup Status",
error_code: state.error_code,
message: state.message,
icon: icon,
last_backup: state.last_backup == null ? "" : new Date(state.last_backup).toISOString(),
next_backup: state.next_backup == null ? "" : new Date(state.next_backup).toISOString()
},
}
option.json = data_state_sensor
got.post(`http://hassio/core/api/states/sensor.nextcloud_backup_status`, option)
.then((result) => {
logger.debug('Home assistant sensor updated (status)');
})
.catch((error) => {
logger.error(error);
});
}
exports.getVersion = getVersion;
exports.getAddonList = getAddonList;
exports.getFolderList = getFolderList;
@ -504,3 +574,4 @@ exports.uploadSnapshot = uploadSnapshot;
exports.stopAddons = stopAddons;
exports.startAddons = startAddons;
exports.clean = clean;
exports.publish_state = publish_state;

View File

@ -1,6 +1,7 @@
const fs = require("fs");
const logger = require("../config/winston");
const moment = require('moment')
const moment = require("moment");
const CronJob = require("cron").CronJob;
const settingsPath = "/data/backup_conf.json";
@ -20,149 +21,158 @@ function check_cron(conf) {
return conf.cron_month_day != null && conf.cron_month_day >= 1 && conf.cron_month_day <= 28;
}
if (conf.cron_base === "4") {
if (conf.cron_custom != null) {
try {
new CronJob(conf.cron_custom, () => {});
return true;
} catch(e) {
return false;
}
}else return false;
}
if (conf.cron_base === "0") return true;
} else return false;
return false;
}
function check(conf, fallback = false) {
let needSave = false;
if (!check_cron(conf)) {
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_hour = "00:00",
conf.cron_weekday = "0",
conf.cron_month_day = "1"
conf.cron_hour = "00:00";
conf.cron_weekday = "0";
conf.cron_month_day = "1";
conf.cron_custom = "5 4 * * *";
} else {
logger.error("Bad value for cron settings")
return false;
logger.error("Bad value for cron settings");
return [false, "Bad cron settings"];
}
}
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}"
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;
logger.error("Bad value for 'name_template'");
return [false, "Bad value for 'name_template'"];
}
}
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"
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;
logger.error("Bad value for 'auto_clean_local_keep'");
return [false, "Bad value for 'auto_clean_local_keep'"];
}
}
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"
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;
logger.error("Bad value for 'auto_clean_backup_keep'");
return [false, "Bad value for 'auto_clean_backup_keep'"];
}
}
if (conf.auto_clean_local == null) {
if (fallback) {
logger.warn("Bad value for 'auto_clean_local', fallback to false ")
conf.auto_clean_local = "false"
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;
logger.error("Bad value for 'auto_clean_local'");
return [false, "Bad value for 'auto_clean_local'"];
}
}
if (conf.auto_clean_backup == null) {
if (fallback) {
logger.warn("Bad value for 'auto_clean_backup', fallback to false ")
conf.auto_clean_backup = "false"
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;
logger.error("Bad value for 'auto_clean_backup'");
return [false, "Bad value for 'auto_clean_backup'"];
}
}
if (conf.exclude_addon == null) {
if (fallback) {
logger.warn("Bad value for 'exclude_addon', fallback to [] ")
conf.exclude_addon = []
logger.warn("Bad value for 'exclude_addon', fallback to [] ");
conf.exclude_addon = [];
} else {
logger.error("Bad value for 'exclude_addon'")
return false;
logger.error("Bad value for 'exclude_addon'");
return [false, "Bad value for 'exclude_addon'"];
}
}
if (conf.exclude_folder == null) {
if (fallback) {
logger.warn("Bad value for 'exclude_folder', fallback to [] ")
conf.exclude_folder = []
logger.warn("Bad value for 'exclude_folder', fallback to [] ");
conf.exclude_folder = [];
} else {
logger.error("Bad value for 'exclude_folder'")
return false;
logger.error("Bad value for 'exclude_folder'");
return [false, "Bad value for 'exclude_folder'"];
}
}
if (conf.auto_stop_addon == null) {
if (fallback) {
logger.warn("Bad value for 'auto_stop_addon', fallback to [] ")
conf.auto_stop_addon = []
logger.warn("Bad value for 'auto_stop_addon', fallback to [] ");
conf.auto_stop_addon = [];
} else {
logger.error("Bad value for 'auto_stop_addon'")
return false;
logger.error("Bad value for 'auto_stop_addon'");
return [false, "Bad value for 'auto_stop_addon'"];
}
}
if (!Array.isArray(conf.exclude_folder)) {
logger.debug("exclude_folder is not array (Empty value), reset...");
conf.exclude_folder = []
conf.exclude_folder = [];
needSave = true;
}
if (!Array.isArray(conf.exclude_addon)) {
logger.debug("exclude_addon is not array (Empty value), reset...");
conf.exclude_addon = []
conf.exclude_addon = [];
needSave = true;
}
if(conf.password_protected == null){
if (conf.password_protected == null) {
if (fallback) {
logger.warn("Bad value for 'password_protected', fallback to false ");
conf.password_protected = 'false';
conf.password_protected = "false";
} else {
logger.error("Bad value for 'password_protect_value'");
return false;
return [false, "Bad value for 'password_protect_value'"];
}
}
if(conf.password_protect_value == null){
if (conf.password_protect_value == null) {
if (fallback) {
logger.warn("Bad value for 'password_protect_value', fallback to '' ");
conf.password_protect_value = '';
conf.password_protect_value = "";
} else {
logger.error("Bad value for 'password_protect_value'");
return false;
return [false, "Bad value for 'password_protect_value'"];
}
}
if (fallback || needSave) {
setSettings(conf);
}
return true
return [true, null];
}
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('hhmmA'));
template = template.replace('{hour}', mmt.format('HHmm'));
template = template.replace('{date}', mmt.format('YYYY-MM-DD'));
return 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("hhmmA"));
template = template.replace("{hour}", mmt.format("HHmm"));
template = template.replace("{date}", mmt.format("YYYY-MM-DD"));
return template;
}
function getSettings() {

View File

@ -1,4 +1,5 @@
const fs = require("fs");
const hassioApiTools = require("./hassioApiTools");
const statusPath = "/data/status.json";
@ -33,11 +34,14 @@ function setStatus(state) {
let old_state_str = fs.readFileSync(statusPath).toString();
if(old_state_str !== JSON.stringify(state)){
fs.writeFileSync(statusPath, JSON.stringify(state));
hassioApiTools.publish_state(state);
}
}else{
fs.writeFileSync(statusPath, JSON.stringify(state));
hassioApiTools.publish_state(state);
}
}
exports.init = init;

View File

@ -88,6 +88,7 @@
<option value="1">Daily</option>
<option value="2">Weekly</option>
<option value="3">Monthly</option>
<option value="4">Custom</option>
</select>
</div>
</div>
@ -120,6 +121,21 @@
<input type="number" class="form-control" id="cron-drop-day-month" min="1" max="28">
</div>
</div>
<div class="row d-none mt-2">
<div class="col-12 col-lg-10 offset-lg-1">
<label for="cron-drop-custom" class="form-label">Custom Cron Pattern</label>
<input type="text" class="form-control" id="cron-drop-custom">
<span id="help-cron-custom"" class="form-text">
Only '*', ranges (1-3,5), steps (*/2) are allowed.
<a target="_blank"
href="https://crontab.guru/">
Generator
</a>
</span>
</div>
</div>
<div class="row my-3">
<div class="col-12 text-center border-secondary border"></div>
</div>