iobroker.backitup
Version:
ioBroker.backitup allows you to backup and restore your ioBroker installation and other systems, such as databases, Zigbee, scripts and many more.
1,007 lines (897 loc) • 107 kB
JavaScript
/* jshint -W097 */
/* jshint strict: false */
/* jslint node: true */
'use strict';
const fs = require('node:fs');
const path = require('node:path');
const utils = require('@iobroker/adapter-core'); // Get common adapter utils
const schedule = require('node-schedule');
const tools = require('./lib/tools');
const executeScripts = require('./lib/execute');
const systemCheck = require('./lib/systemCheck');
const TokenRefresher = require('./lib/tokenRefresher');
const adapterName = require('./package.json').name.split('.').pop();
let adapter;
let timerOutput;
let timerOutput2;
let timerUmount1;
let timerUmount2;
let timerMain;
let slaveTimeOut;
let waitToSlaveBackup;
let dlServer;
let ulServer;
let http;
let https;
let systemLang = 'de'; // system language
const backupConfig = {};
const backupTimeSchedules = []; // Array for Backup Times
let taskRunning = false;
let dropBoxTokenRefresher = null;
const bashDir = path.join(utils.getAbsoluteDefaultDataDir(), adapterName).replace(/\\/g, '/');
/**
* Decrypt the password/value with given key
*
* @param key - Secret key
* @param value - value to decrypt
* @returns
*/
function decrypt(key, value) {
let result = '';
for (let i = 0; i < value.length; i++) {
result += String.fromCharCode(key[i % key.length].charCodeAt(0) ^ value.charCodeAt(i));
}
return result;
}
async function updateAccessTokens(config) {
if (dropBoxTokenRefresher) {
try {
const accessToken = await dropBoxTokenRefresher.getAccessToken();
Object.keys(config).forEach((key) => {
if (config[key] && typeof config[key] === 'object') {
if (config[key].dropbox) {
config[key].dropbox.accessToken = accessToken;
} else {
Object.keys(config[key]).forEach((subKey) => {
if (config[key][subKey] && config[key][subKey].dropbox) {
config[key][subKey].dropbox.accessToken = accessToken;
}
});
}
}
});
} catch (e) {
adapter.log.error(`Cannot get access tokens for DropBox: ${e}`);
}
}
}
async function startBackup(config, cb) {
if (taskRunning) {
return setTimeout(startBackup, 10000, config, cb);
}
// await updateAccessTokens(config);
taskRunning = true;
try {
executeScripts(adapter, config, err => {
taskRunning = false;
cb && cb(err);
});
adapter.log.debug('Backup has started ...');
} catch (e) {
adapter.log.warn(`Backup error: ${e.stack}`);
adapter.log.warn(`Backup error: ${e} ... please check your config and and try again!!`);
}
}
function startAdapter(options) {
options = options || {};
Object.assign(options, { name: adapterName });
adapter = new utils.Adapter(options);
adapter.on('stateChange', async (id, state) => {
dropBoxTokenRefresher?.onStateChange(id, state);
if (id === `${adapter.namespace}.info.dropboxTokens`) {
await updateAccessTokens(backupConfig);
adapter.log.debug('Config Update for Dropbox Token');
}
if (state && (state.val === true || state.val === 'true') && !state.ack) {
if (id === `${adapter.namespace}.oneClick.iobroker` ||
id === `${adapter.namespace}.oneClick.ccu`
) {
const sysCheck = await systemCheck.storageSizeCheck(adapter, adapterName, adapter.log);
const type = id.split('.').pop();
if ((sysCheck && sysCheck.ready && sysCheck.ready === true) || adapter.config.cifsEnabled === true) {
let config;
try {
config = JSON.parse(JSON.stringify(backupConfig[type]));
config.enabled = true;
config.deleteBackupAfter = 0; // do not delete files by custom backup
} catch (e) {
adapter.log.warn(`backup error: ${e.stack}`);
adapter.log.warn(`backup error: ${e} ... please check your config and try again!!`);
}
startBackup(config, err => {
if (err) {
adapter.log.error(`[${type}] ${err}`);
} else {
adapter.log.debug(`[${type}] exec: done`);
}
timerOutput = setTimeout(() => {
return adapter.getState('output.line', (err, state) => {
if (state && state.val === '[EXIT] 0') {
adapter.setState(`history.${type}Success`, true, true);
adapter.setState(`history.${type}LastTime`, tools.getTimeString(systemLang), true);
if (adapter.config.onedriveEnabled && adapter.config.hostType === 'Single') {
renewOnedriveToken();
}
} else {
adapter.setState(`history.${type}LastTime`, `error: ${tools.getTimeString(systemLang)}`, true);
adapter.setState(`history.${type}Success`, false, true);
}
});
}, 500);
adapter.setState(`oneClick.${type}`, false, true);
if (adapter.config.slaveInstance && type === 'iobroker' && adapter.config.hostType === 'Master') {
adapter.log.debug('Slave backup from BackItUp-Master is started ...');
startSlaveBackup(adapter.config.slaveInstance[0], null);
}
});
} else {
adapter.log.error(`A local backup is currently not possible. The storage space is currently only ${sysCheck && sysCheck.diskFree ? sysCheck.diskFree : null} MB`);
systemCheck.systemMessage(adapter, tools._('A local backup is currently not possible. Please check your System!', systemLang));
adapter.setState(`oneClick.${type}`, false, true);
adapter.setState('output.line', `[EXIT] ${tools._('A local backup is currently not possible. Please check your System!', systemLang)}`, true);
}
}
}
});
adapter.on('ready', async () => {
try {
await main(adapter);
} catch (e) {
//ignore errors
}
});
// is called when adapter shuts down - callback has to be called under any circumstances!
adapter.on('unload', (callback) => {
try {
dropBoxTokenRefresher?.destroy();
adapter.log.info('cleaned everything up...');
timerOutput2 && clearTimeout(timerOutput2);
timerOutput && clearTimeout(timerOutput);
timerUmount1 && clearTimeout(timerUmount1);
timerUmount2 && clearTimeout(timerUmount2);
timerMain && clearTimeout(timerMain);
slaveTimeOut && clearTimeout(slaveTimeOut);
waitToSlaveBackup && clearTimeout(waitToSlaveBackup);
if (dlServer) {
try {
dlServer.closeAllConnections();
} catch (e) {
adapter.log.debug(`Download server Connections could not be closed: ${e}`);
}
try {
dlServer.close();
} catch (e) {
adapter.log.debug(`Download server Connections could not be closed: ${e}`);
}
}
if (ulServer) {
try {
ulServer.closeAllConnections();
} catch (e) {
adapter.log.debug(`Upload server connections could not be closed: ${e}`);
}
try {
ulServer.close();
} catch (e) {
adapter.log.debug(`Upload server connections could not be closed: ${e}`);
}
}
} catch (e) {
console.log(`Cannot unload: ${e}`);
}
callback();
});
adapter.on('message', async obj => {
if (obj) {
switch (obj.command) {
case 'list':
try {
const list = require('./lib/list');
adapter.log.debug(`Reading backup list...`);
await updateAccessTokens(backupConfig);
list(obj.message, backupConfig, adapter.log, res => {
adapter.log.debug(`Backup list was read: ${JSON.stringify(res)}`);
obj.callback && adapter.sendTo(obj.from, obj.command, res, obj.callback);
});
} catch (e) {
adapter.log.debug('Backup list cannot be read ...');
}
break;
case 'authGoogleDrive':
const GoogleDrive = require('./lib/googleDriveLib');
if (obj.callback) {
const google = new GoogleDrive();
google.getAuthorizeUrl()
.then(url =>
adapter.sendTo(obj.from, obj.command, { url }, obj.callback));
}
break;
case 'authDropbox':
if (obj.callback) {
TokenRefresher.getAuthUrl('https://oauth2.iobroker.in/dropbox')
.then(url => adapter.sendTo(obj.from, obj.command, { url }, obj.callback))
}
break;
case 'authOnedrive':
const Onedrive = require('./lib/oneDriveLib');
if (obj.message && obj.message.code) {
const onedrive = new Onedrive();
onedrive.getRefreshToken(obj.message.code, adapter.log)
.then(json => adapter.sendTo(obj.from, obj.command, { done: true, json }, obj.callback))
.catch(err => adapter.sendTo(obj.from, obj.command, { error: err }, obj.callback));
} else if (obj.callback) {
const onedrive = new Onedrive();
onedrive.getAuthorizeUrl(adapter.log)
.then(url => adapter.sendTo(obj.from, obj.command, { url: url }, obj.callback))
.catch(err => adapter.sendTo(obj.from, obj.command, { error: err }, obj.callback));
}
break;
case 'restore':
if (obj.message) {
if (obj.message.stopIOB) {
await getCerts(obj.from);
}
adapter.log.info(`DATA: ${JSON.stringify(obj.message)}`);
await updateAccessTokens(backupConfig);
const _restore = require('./lib/restore');
_restore.restore(
adapter,
backupConfig,
obj.message.type,
obj.message.fileName,
obj.message.currentTheme,
obj.message.currentProtocol,
bashDir,
adapter.log,
res => obj.callback && adapter.sendTo(obj.from, obj.command, res, obj.callback),
);
} else if (obj.callback) {
obj.callback({ error: 'Invalid parameters' });
}
break;
case 'uploadFile':
if (obj.message && obj.message.protocol) {
if (ulServer && ulServer._connectionKey && ulServer.listening) {
adapter.log.debug(`Upload server is running on Port ${ulServer.address().port}...`);
} else {
if (obj.message.protocol === 'https:') {
await getCerts(obj.from);
}
try {
ulFileServer(obj.message.protocol);
} catch (e) {
adapter.log.debug('Upload server cannot started');
}
}
try {
adapter.sendTo(obj.from, obj.command, { listenPort: ulServer.address().port }, obj.callback);
} catch (e) {
adapter.sendTo(obj.from, obj.command, { e }, obj.callback);
}
} else if (obj.callback) {
obj.callback({ error: 'Invalid parameters' });
}
break;
case 'getFile':
if (obj.message && obj.message.type && obj.message.fileName && obj.message.protocol) {
if (dlServer && dlServer._connectionKey && dlServer.listening) {
adapter.log.debug(`Download server is running on port ${dlServer.address().port}...`);
} else {
if (obj.message.protocol === 'https:') {
await getCerts(obj.from);
}
try {
dlFileServer(obj.message.protocol);
} catch (e) {
adapter.log.debug('Downloadserver cannot started');
}
}
const fileName = obj.message.fileName.split('/').pop();
if (obj.message.type !== 'local') {
const backupDir = path.join(tools.getIobDir(), 'backups');
const toSaveName = path.join(backupDir, fileName);
const _getFile = require('./lib/restore');
await updateAccessTokens(backupConfig);
_getFile.getFile(backupConfig, obj.message.type, obj.message.fileName, toSaveName, adapter.log, err => {
if (!err && fs.existsSync(toSaveName)) {
try {
adapter.sendTo(obj.from, obj.command, { fileName: fileName, listenPort: dlServer.address().port }, obj.callback);
} catch (error) {
adapter.sendTo(obj.from, obj.command, { error }, obj.callback);
}
} else {
adapter.log.warn(`File ${toSaveName} not found`);
}
});
} else if (fs.existsSync(obj.message.fileName)) {
try {
adapter.sendTo(obj.from, obj.command, { fileName: fileName, listenPort: dlServer.address().port }, obj.callback);
} catch (error) {
adapter.sendTo(obj.from, obj.command, { error }, obj.callback);
}
}
} else if (obj.callback) {
obj.callback({ error: 'Invalid parameters' });
}
break;
case 'serverClose':
if (obj.message && obj.message.downloadFinish && !obj.message.uploadFinish) {
adapter.log.debug('Download finished...');
adapter.sendTo(obj.from, obj.command, { serverClose: true }, obj.callback);
} else if (obj.message && obj.message.uploadFinish && !obj.message.downloadFinish) {
adapter.log.debug('Upload finished...');
adapter.sendTo(obj.from, obj.command, { serverClose: true }, obj.callback);
} else if (obj.callback) {
obj.callback({ error: 'Invalid parameters' });
}
break;
case 'getTelegramUser':
if (obj && obj.message) {
const inst = obj.message.config.instance ? obj.message.config.instance : adapter.config.telegramInstance;
adapter.getForeignState(`${inst}.communicate.users`, (err, state) => {
err && adapter.log.error(err);
if (state && state.val) {
try {
adapter.sendTo(obj.from, obj.command, state.val, obj.callback);
} catch (err) {
err && adapter.log.error(err);
adapter.log.error('Cannot parse stored user IDs from Telegram!');
}
}
});
}
break;
case 'getSystemInfo':
if (obj) {
let systemInfo = process.platform;;
let dbInfo = false;
if (fs.existsSync('/opt/scripts/.docker_config/.thisisdocker')) { // Docker Image Support >= 5.2.0
systemInfo = 'docker';
if (fs.existsSync('/opt/scripts/.docker_config/.backitup')) {
dbInfo = true;
}
} else {
const isWin = process.platform.startsWith('win');
if (isWin) {
systemInfo = 'win';
}
}
try {
adapter.sendTo(obj.from, obj.command, { systemOS: systemInfo, dockerDB: dbInfo, backupDir: path.join(tools.getIobDir(), 'backups') }, obj.callback);
} catch (err) {
err && adapter.log.error(err);
}
}
break;
case 'getFileSystemInfo':
if (obj) {
const sysCheck = await systemCheck.storageSizeCheck(adapter, adapterName, adapter.log);
if (sysCheck) {
try {
adapter.sendTo(obj.from, obj.command, sysCheck, obj.callback);
} catch (err) {
err && adapter.log.error(err);
}
}
}
break;
case 'testWebDAV':
if (obj.message) {
const { createClient } = await import('webdav');
const agent = new (require('node:https').Agent)({ rejectUnauthorized: Boolean(obj.message.config.signedCertificates) });
const client = createClient(
obj.message.config.host,
{
username: obj.message.config.username,
password: obj.message.config.password,
maxBodyLength: Infinity,
httpsAgent: agent
});
client
.getDirectoryContents('')
.then(contents => obj.callback && adapter.sendTo(obj.from, obj.command, contents, obj.callback))
.catch(err => adapter.sendTo(obj.from, obj.command, { error: JSON.stringify(err.message) }, obj.callback));
}
break;
case 'slaveBackup':
if (obj?.message) {
if (adapter.config.hostType === 'Slave') {
adapter.log.debug('Slave Backup started ...');
const type = 'iobroker';
let config;
try {
config = JSON.parse(JSON.stringify(backupConfig[type]));
config.enabled = true;
config.deleteBackupAfter = obj.message.config.deleteAfter ? obj.message.config.deleteAfter : 0; // do delete files with specification from Master
} catch (e) {
adapter.log.warn(`backup error: ${e} ... please check your config and try again!!`);
}
startBackup(config, err => {
if (err) {
adapter.log.error(`[${type}] ${err}`);
} else {
adapter.log.debug(`[${type}] exec: done`);
}
timerOutput = setTimeout(() =>
adapter.getState('output.line', (err, state) => {
if (state && state.val === '[EXIT] 0') {
adapter.setState(`history.${type}Success`, true, true);
adapter.setState(`history.${type}LastTime`, tools.getTimeString(systemLang), true);
try {
adapter.sendTo(obj.from, obj.command, state.val, obj.callback);
} catch (err) {
err && adapter.log.error(err);
adapter.log.error('slave Backup not finish!');
}
if (adapter.config.onedriveEnabled) {
renewOnedriveToken();
}
} else {
adapter.setState(`history.${type}LastTime`, `error: ${tools.getTimeString(systemLang)}`, true);
adapter.setState(`history.${type}Success`, false, true);
if (state && state.val) {
try {
adapter.sendTo(obj.from, obj.command, state.val, obj.callback);
} catch (err) {
err && adapter.log.error(err);
adapter.log.error('slave Backup not finish!');
}
}
}
}), 500);
adapter.setState(`oneClick.${type}`, false, true);
});
} else {
adapter.log.warn('Your BackItUp Instance is not configured as a slave');
adapter.sendTo(obj.from, obj.command, 'not configured as a slave', obj.callback);
}
}
break;
case 'slaveInstance':
if (obj && obj.command === 'slaveInstance' && obj.message && obj.message.instance) {
let resultInstances = [];
const instances = await adapter.getObjectViewAsync('system', 'instance', {
startkey: `system.adapter.${obj.message.instance}.`,
endkey: `system.adapter.${obj.message.instance}.\u9999`,
}).catch((err) => adapter.log.error(err));
if (instances && instances.rows && instances.rows.length != 0) {
instances.rows.forEach(async (row) => {
if (row.id.replace('system.adapter.', '') != adapter.namespace) {
resultInstances.push({
label: row.id.replace('system.adapter.', ''),
value: row.id.replace('system.adapter.', ''),
});
}
});
}
adapter.sendTo(obj.from, obj.command, resultInstances, obj.callback);
}
break;
case 'getLog':
const logName = path.join(bashDir, `${adapter.namespace}.log`).replace(/\\/g, '/');
if (fs.existsSync(logName) && (obj?.message.backupName || obj?.message.timestamp)) {
const data = fs.readFileSync(logName, 'utf8');
const backupLog = JSON.parse(data);
const backupName = obj?.message.backupName ? obj.message.backupName : null;
const timestamp = obj?.message.timestamp;
let found = false;
backupLog.forEach((item, index) => {
if (item.hasOwnProperty(timestamp)) {
found = true;
adapter.log.debug(`Printing logs of previous backup`);
adapter.sendTo(obj.from, obj.command, item[timestamp], obj.callback);
} else if (backupName !== null && item.hasOwnProperty(backupName)) {
found = true;
adapter.log.debug(`Printing logs of previous backup`);
adapter.sendTo(obj.from, obj.command, item[backupName], obj.callback);
} else if ((backupLog.length - 1) == index && !found) {
adapter.log.debug(`No Backuplogs found`);
adapter.sendTo(obj.from, obj.command, tools._('No log is available for this backup', systemLang), obj.callback);
}
});
}
break;
}
}
});
return adapter;
}
async function checkStates() {
// Fill empty data points with default values
const historyState = await adapter.getStateAsync('history.html');
if (!historyState || historyState.val === null) {
await adapter.setStateAsync('history.html', { val: `<span class="backup-type-total">${tools._('No backups yet', systemLang)}</span>`, ack: true });
}
const iobrokerLastTime = await adapter.getStateAsync('history.iobrokerLastTime');
if (!iobrokerLastTime || iobrokerLastTime.val === null) {
await adapter.setStateAsync('history.iobrokerLastTime', { val: tools._('No backups yet', systemLang), ack: true });
}
const ccuLastTime = await adapter.getStateAsync('history.ccuLastTime');
if (!ccuLastTime || ccuLastTime.val === null) {
await adapter.setStateAsync('history.ccuLastTime', { val: tools._('No backups yet', systemLang), ack: true });
}
const iobrokerState = await adapter.getStateAsync('oneClick.iobroker');
if (!iobrokerState || iobrokerState.val === null || iobrokerState.val === true) {
await adapter.setStateAsync('oneClick.iobroker', { val: false, ack: true });
}
const ccuState = await adapter.getStateAsync('oneClick.ccu');
if (!ccuState || ccuState.val === null || ccuState.val === true) {
await adapter.setStateAsync('oneClick.ccu', { val: false, ack: true });
}
const ccuSuccess = await adapter.getStateAsync('history.ccuSuccess');
if (!ccuSuccess || ccuSuccess.val === null) {
await adapter.setStateAsync('history.ccuSuccess', { val: false, ack: true });
}
const iobrokerSuccess = await adapter.getStateAsync('history.iobrokerSuccess');
if (!iobrokerSuccess || iobrokerSuccess.val === null) {
await adapter.setStateAsync('history.iobrokerSuccess', { val: false, ack: true });
}
const jsonState = await adapter.getStateAsync('history.json');
if (!jsonState || jsonState.val === null) {
await adapter.setStateAsync('history.json', { val: '[]', ack: true });
}
}
// function to create Backup schedules (Backup time)
function createBackupSchedule() {
for (const type in backupConfig) {
if (!backupConfig.hasOwnProperty(type)) {
continue;
}
const config = backupConfig[type];
if (config.enabled === true || config.enabled === 'true') {
let time = config.ownCron ? config.cronjob : config.time.split(':');
const backupInfo = config.ownCron ? `with Cronjob "${config.cronjob}"` : `at ${config.time} every ${config.everyXDays} day(s)`;
adapter.log.info(`[${type}] backup will be activated ${backupInfo}`);
if (backupTimeSchedules[type]) {
backupTimeSchedules[type].cancel();
}
const cron = config.ownCron ? time : `10 ${time[1]} ${time[0]} */${config.everyXDays} * * `;
backupTimeSchedules[type] = schedule.scheduleJob(cron, async () => {
const sysCheck = await systemCheck.storageSizeCheck(adapter, adapterName, adapter.log);
if ((sysCheck && sysCheck.ready && sysCheck.ready === true) || adapter.config.cifsEnabled === true) {
adapter.setState(`oneClick.${type}`, true, true);
startBackup(backupConfig[type], err => {
if (err) {
adapter.log.error(`[${type}] ${err}`);
} else {
adapter.log.debug(`[${type}] exec: done`);
}
timerOutput2 = setTimeout(() =>
adapter.getState('output.line', (err, state) => {
if (state && state.val === '[EXIT] 0') {
adapter.setState(`history.${type}Success`, true, true);
adapter.setState(`history.${type}LastTime`, tools.getTimeString(systemLang), true);
if (adapter.config.onedriveEnabled && adapter.config.hostType === 'Single') {
renewOnedriveToken();
}
} else {
adapter.setState(`history.${type}LastTime`, `error: ${tools.getTimeString(systemLang)}`, true);
adapter.setState(`history.${type}Success`, false, true);
}
}), 500);
nextBackup(false, type);
adapter.setState(`oneClick.${type}`, false, true);
if (adapter.config.slaveInstance && type === 'iobroker' && adapter.config.hostType === 'Master') {
adapter.log.debug('Slave backup from BackItUp-Master is started ...');
startSlaveBackup(adapter.config.slaveInstance[0], null);
}
});
} else {
adapter.log.error(`A local backup is currently not possible. The storage space is currently only ${sysCheck && sysCheck.diskFree ? sysCheck.diskFree : null} MB`);
systemCheck.systemMessage(adapter, tools._('A local backup is currently not possible. Please check your System!', systemLang));
}
});
if (config.debugging) {
adapter.log.debug(`[${type}] ${cron}`);
}
} else if (backupTimeSchedules[type]) {
adapter.log.info(`[${type}] backup deactivated`);
backupTimeSchedules[type].cancel();
backupTimeSchedules[type] = null;
}
}
}
async function initConfig(secret) {
return new Promise(async (resolve) => {
// compatibility
if (adapter.config.cifsMount === 'CIFS') {
adapter.config.cifsMount = '';
}
if (adapter.config.redisEnabled === undefined) {
adapter.config.redisEnabled = adapter.config.backupRedis
}
let ioPath;
try {
// ioPath = `${ioCommon.tools.getControllerDir()}/iobroker.js`; Todo: Error by iob Backup (no such file or directory, uv_cwd)
// ioPath = require.resolve('iobroker.js-controller/iobroker.js');
ioPath = path.resolve(__dirname, '../iobroker.js-controller/iobroker.js');
} catch (e) {
adapter.log.error(`Unable to read iobroker path: +${e}`);
}
decryptEvents(secret);
const telegram = {
enabled: adapter.config.notificationEnabled,
notificationsType: adapter.config.notificationsType,
type: 'message',
instance: adapter.config.telegramInstance,
SilentNotice: adapter.config.telegramSilentNotice,
NoticeType: adapter.config.telegramNoticeType,
User: adapter.config.telegramUser,
onlyError: adapter.config.telegramOnlyError,
telegramWaiting: adapter.config.telegramWaitToSend * 1000,
hostName: adapter.config.minimalNameSuffix ? adapter.config.minimalNameSuffix.replace(/[.;, ]/g, '_') : '',
ignoreErrors: adapter.config.ignoreErrors,
systemLang
};
const whatsapp = {
enabled: adapter.config.notificationEnabled,
notificationsType: adapter.config.notificationsType,
type: 'message',
instance: adapter.config.whatsappInstance,
NoticeType: adapter.config.whatsappNoticeType,
onlyError: adapter.config.whatsappOnlyError,
whatsappWaiting: adapter.config.whatsappWaitToSend * 1000,
hostName: adapter.config.minimalNameSuffix ? adapter.config.minimalNameSuffix.replace(/[.;, ]/g, '_') : '',
ignoreErrors: adapter.config.ignoreErrors,
systemLang
};
const gotify = {
enabled: adapter.config.notificationEnabled,
notificationsType: adapter.config.notificationsType,
type: 'message',
instance: adapter.config.gotifyInstance,
NoticeType: adapter.config.gotifyNoticeType,
onlyError: adapter.config.gotifyOnlyError,
gotifyWaiting: adapter.config.gotifyWaitToSend * 1000,
hostName: adapter.config.minimalNameSuffix ? adapter.config.minimalNameSuffix.replace(/[.;, ]/g, '_') : '',
ignoreErrors: adapter.config.ignoreErrors,
systemLang
};
const signal = {
enabled: adapter.config.notificationEnabled,
notificationsType: adapter.config.notificationsType,
type: 'message',
instance: adapter.config.signalInstance,
NoticeType: adapter.config.signalNoticeType,
onlyError: adapter.config.signalOnlyError,
signalWaiting: adapter.config.signalWaitToSend * 1000,
hostName: adapter.config.minimalNameSuffix ? adapter.config.minimalNameSuffix.replace(/[.;, ]/g, '_') : '',
ignoreErrors: adapter.config.ignoreErrors,
systemLang
};
const matrix = {
enabled: adapter.config.notificationEnabled,
notificationsType: adapter.config.notificationsType,
type: 'message',
instance: adapter.config.matrixInstance,
NoticeType: adapter.config.matrixNoticeType,
onlyError: adapter.config.matrixOnlyError,
matrixWaiting: adapter.config.matrixWaitToSend * 1000,
hostName: adapter.config.minimalNameSuffix ? adapter.config.minimalNameSuffix.replace(/[.;, ]/g, '_') : '',
ignoreErrors: adapter.config.ignoreErrors,
systemLang
};
const discord = {
enabled: adapter.config.notificationEnabled,
notificationsType: adapter.config.notificationsType,
type: 'message',
instance: adapter.config.discordInstance,
NoticeType: adapter.config.discordNoticeType,
target: adapter.config.discordTarget,
onlyError: adapter.config.discordOnlyError,
discordWaiting: adapter.config.discordWaitToSend * 1000,
hostName: adapter.config.minimalNameSuffix ? adapter.config.minimalNameSuffix.replace(/[.;, ]/g, '_') : '',
ignoreErrors: adapter.config.ignoreErrors,
systemLang
};
const pushover = {
enabled: adapter.config.notificationEnabled,
notificationsType: adapter.config.notificationsType,
type: 'message',
instance: adapter.config.pushoverInstance,
SilentNotice: adapter.config.pushoverSilentNotice,
NoticeType: adapter.config.pushoverNoticeType,
deviceID: adapter.config.pushoverDeviceID,
onlyError: adapter.config.pushoverOnlyError,
pushoverWaiting: adapter.config.pushoverWaitToSend * 1000,
hostName: adapter.config.minimalNameSuffix ? adapter.config.minimalNameSuffix.replace(/[.;, ]/g, '_') : '',
ignoreErrors: adapter.config.ignoreErrors,
systemLang
};
const email = {
enabled: adapter.config.notificationEnabled,
notificationsType: adapter.config.notificationsType,
type: 'message',
instance: adapter.config.emailInstance,
NoticeType: adapter.config.emailNoticeType,
emailReceiver: adapter.config.emailReceiver,
emailSender: adapter.config.emailSender,
onlyError: adapter.config.emailOnlyError,
emailWaiting: adapter.config.emailWaitToSend * 1000,
hostName: adapter.config.minimalNameSuffix ? adapter.config.minimalNameSuffix.replace(/[.;, ]/g, '_') : '',
ignoreErrors: adapter.config.ignoreErrors,
systemLang
};
const notification = {
type: 'message',
ignoreErrors: adapter.config.ignoreErrors,
bashDir: bashDir,
entriesNumber: adapter.config.historyEntriesNumber,
systemLang
};
const historyHTML = {
enabled: true,
type: 'message',
entriesNumber: adapter.config.historyEntriesNumber,
ignoreErrors: adapter.config.ignoreErrors,
systemLang
};
const historyJSON = {
enabled: true,
type: 'message',
entriesNumber: adapter.config.historyEntriesNumber,
ignoreErrors: adapter.config.ignoreErrors,
systemLang
};
const ftp = {
enabled: adapter.config.ftpEnabled,
type: 'storage',
source: adapter.config.restoreSource,
host: adapter.config.ftpHost, // ftp-host
debugging: adapter.config.debugLevel,
deleteOldBackup: adapter.config.ftpDeleteOldBackup, // Delete old Backups from FTP
ftpDeleteAfter: adapter.config.ftpDeleteAfter,
advancedDelete: adapter.config.advancedDelete,
ownDir: adapter.config.ftpOwnDir,
bkpType: adapter.config.restoreType,
dir: (adapter.config.ftpOwnDir === true) ? null : adapter.config.ftpDir, // directory on FTP server
dirMinimal: adapter.config.ftpMinimalDir,
user: adapter.config.ftpUser, // username for FTP Server
pass: adapter.config.ftpPassword || '', // password for FTP Server
port: adapter.config.ftpPort || 21, // FTP port
secure: adapter.config.ftpSecure || false, // secure FTP connection
signedCertificates: adapter.config.ftpSignedCertificates || true,
ignoreErrors: adapter.config.ignoreErrors
};
let accessToken = '';
if (adapter.config.dropboxEnabled) {
dropBoxTokenRefresher = new TokenRefresher(adapter, 'info.dropboxTokens', 'https://oauth2.iobroker.in/dropbox');
try {
accessToken = await dropBoxTokenRefresher.getAccessToken();
} catch (e) {
adapter.log.error(`No DropBox token found: ${e}`);
}
}
const dropbox = {
enabled: adapter.config.dropboxEnabled,
type: 'storage',
source: adapter.config.restoreSource,
debugging: adapter.config.debugLevel,
deleteOldBackup: adapter.config.dropboxDeleteOldBackup, // Delete old Backups from Dropbox
dropboxDeleteAfter: adapter.config.dropboxDeleteAfter,
advancedDelete: adapter.config.advancedDelete,
accessToken: adapter.config.dropboxTokenType === 'custom' ? adapter.config.dropboxAccessToken : accessToken,
dropboxAccessJson: adapter.config.dropboxAccessJson,
dropboxTokenType: adapter.config.dropboxTokenType,
ownDir: adapter.config.dropboxOwnDir,
bkpType: adapter.config.restoreType,
dir: (adapter.config.dropboxOwnDir === true) ? null : adapter.config.dropboxDir,
dirMinimal: adapter.config.dropboxMinimalDir,
ignoreErrors: adapter.config.ignoreErrors,
};
const onedrive = {
enabled: adapter.config.onedriveEnabled,
type: 'storage',
source: adapter.config.restoreSource,
debugging: adapter.config.debugLevel,
deleteOldBackup: adapter.config.onedriveDeleteOldBackup, // Delete old Backups from Onedrive
onedriveDeleteAfter: adapter.config.onedriveDeleteAfter,
advancedDelete: adapter.config.advancedDelete,
onedriveAccessJson: adapter.config.onedriveAccessJson,
ownDir: adapter.config.onedriveOwnDir,
bkpType: adapter.config.restoreType,
dir: (adapter.config.onedriveOwnDir === true) ? null : adapter.config.onedriveDir,
dirMinimal: adapter.config.onedriveMinimalDir,
ignoreErrors: adapter.config.ignoreErrors
};
const webdav = {
enabled: adapter.config.webdavEnabled,
type: 'storage',
source: adapter.config.restoreSource,
debugging: adapter.config.debugLevel,
deleteOldBackup: adapter.config.webdavDeleteOldBackup, // Delete old Backups from webdav
webdavDeleteAfter: adapter.config.webdavDeleteAfter,
advancedDelete: adapter.config.advancedDelete,
username: adapter.config.webdavUsername,
pass: adapter.config.webdavPassword || '', // webdav password
url: adapter.config.webdavURL,
ownDir: adapter.config.webdavOwnDir,
bkpType: adapter.config.restoreType,
dir: (adapter.config.webdavOwnDir === true) ? null : adapter.config.webdavDir,
dirMinimal: adapter.config.webdavMinimalDir,
signedCertificates: adapter.config.webdavSignedCertificates,
ignoreErrors: adapter.config.ignoreErrors
};
const googledrive = {
enabled: adapter.config.googledriveEnabled,
type: 'storage',
source: adapter.config.restoreSource,
debugging: adapter.config.debugLevel,
deleteOldBackup: adapter.config.googledriveDeleteOldBackup, // Delete old Backups from google drive
googledriveDeleteAfter: adapter.config.googledriveDeleteAfter,
advancedDelete: adapter.config.advancedDelete,
accessJson: adapter.config.googledriveAccessTokens || adapter.config.googledriveAccessJson,
newToken: !!adapter.config.googledriveAccessTokens,
ownDir: adapter.config.googledriveOwnDir,
bkpType: adapter.config.restoreType,
dir: (adapter.config.googledriveOwnDir === true) ? null : adapter.config.googledriveDir,
dirMinimal: adapter.config.googledriveMinimalDir,
ignoreErrors: adapter.config.ignoreErrors
};
const cifs = {
enabled: adapter.config.cifsEnabled,
mountType: adapter.config.connectType,
type: 'storage',
source: adapter.config.restoreSource,
mount: adapter.config.cifsMount,
debugging: adapter.config.debugLevel,
fileDir: bashDir,
wakeOnLAN: adapter.config.wakeOnLAN,
macAd: adapter.config.macAd,
wolTime: adapter.config.wolWait,
wolPort: adapter.config.wolPort || 9,
wolExtra: adapter.config.wolExtra,
smb: adapter.config.smbType,
sudo: adapter.config.sudoMount,
cifsDomain: adapter.config.cifsDomain,
clientInodes: adapter.config.noserverino,
cacheLoose: adapter.config.cacheLoose,
deleteOldBackup: adapter.config.cifsDeleteOldBackup, //Delete old Backups from Network Disk
ownDir: adapter.config.cifsOwnDir,
bkpType: adapter.config.restoreType,
dir: (adapter.config.cifsOwnDir === true) ? null : adapter.config.cifsDir, // specify if CIFS mount should be used
dirMinimal: adapter.config.cifsMinimalDir,
user: adapter.config.cifsUser, // specify if CIFS mount should be used
pass: adapter.config.cifsPassword || '', // password for NAS Server
expertMount: adapter.config.expertMount,
ignoreErrors: adapter.config.ignoreErrors
};
// Configurations for standard-IoBroker backup
backupConfig.iobroker = {
name: 'iobroker',
type: 'creator',
workDir: ioPath,
enabled: adapter.config.minimalEnabled,
time: adapter.config.minimalTime,
cronjob: adapter.config.iobrokerCronJob,
ownCron: adapter.config.iobrokerCron,
debugging: adapter.config.debugLevel,
slaveBackup: adapter.config.hostType,
everyXDays: adapter.config.minimalEveryXDays,
nameSuffix: adapter.config.minimalNameSuffix.replace(/[.;, ]/g, '_'), // names addition, appended to the file name
deleteBackupAfter: adapter.config.minimalDeleteAfter, // delete old backup files after x days
ftp: Object.assign({}, ftp, (adapter.config.ftpOwnDir === true) ? { dir: adapter.config.ftpMinimalDir } : {}),
cifs: Object.assign({}, cifs, (adapter.config.cifsOwnDir === true) ? { dir: adapter.config.cifsMinimalDir } : {}),
dropbox: Object.assign({}, dropbox, (adapter.config.dropboxOwnDir === true) ? { dir: adapter.config.dropboxMinimalDir } : {}),
onedrive: Object.assign({}, onedrive, (adapter.config.onedriveOwnDir === true) ? { dir: adapter.config.onedriveMinimalDir } : {}),
webdav: Object.assign({}, webdav, (adapter.config.webdavOwnDir === true) ? { dir: adapter.config.webdavMinimalDir } : {}),
googledrive: Object.assign({}, googledrive, (adapter.config.googledriveOwnDir === true) ? { dir: adapter.config.googledriveMinimalDir } : {}),
ignoreErrors: adapter.config.ignoreErrors,
mysql: {
enabled: adapter.config.mySqlEnabled === undefined ? true : adapter.config.mySqlEnabled,
type: 'creator',
ftp: Object.assign({}, ftp, (adapter.config.ftpOwnDir === true) ? { dir: adapter.config.ftpMinimalDir } : {}),
cifs: Object.assign({}, cifs, (adapter.config.cifsOwnDir === true) ? { dir: adapter.config.cifsMinimalDir } : {}),
dropbox: Object.assign({}, dropbox, (adapter.config.dropboxOwnDir === true) ? { dir: adapter.config.dropboxMinimalDir } : {}),
onedrive: Object.assign({}, onedrive, (adapter.config.onedriveOwnDir === true) ? { dir: adapter.config.onedriveMinimalDir } : {}),
webdav: Object.assign({}, webdav, (adapter.config.webdavOwnDir === true) ? { dir: adapter.config.webdavMi