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.
257 lines (231 loc) • 9.48 kB
JavaScript
;
const axios = require('axios');
const OAUTH_URL = 'https://dropboxauth.simateccloud.de/';
class dropbox {
getAuthorizeUrl(log) {
return new Promise(async (resolve, reject) => {
try {
const urlRequest = await axios({
method: 'get',
url: OAUTH_URL,
headers: {
'User-Agent': 'axios/1.6.5'
},
responseType: 'json'
}).catch(err => log.warn('getAuthorizeUrl Dropbox: ' + err));
if (urlRequest && urlRequest.data) {
const url = `${urlRequest.data.authURL}&client_id=${urlRequest.data.client_id}`;
resolve(url);
} else {
reject();
}
} catch (e) {
console.log('error getAuthorizeUrl Dropbox: ' + e);
reject();
}
});
}
getCodeChallage(log, dropboxCodeChallenge) {
return new Promise((resolve, reject) => {
if (dropboxCodeChallenge && dropboxCodeChallenge.length == 48) {
log.debug('Dropbox code verifier already exists');
resolve(dropboxCodeChallenge);
} else {
try {
let codeChallenge = '';
const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
for (var i = 0; i < 48; i++) {
codeChallenge += characters.charAt(Math.floor(Math.random() * characters.length));
}
if (codeChallenge) {
resolve(codeChallenge);
} else {
reject();
}
} catch (e) {
console.log('error getCodeChallage Dropbox: ' + e);
reject();
}
}
});
}
getRefreshToken(code, code_verifier, log) {
return new Promise(async (resolve, reject) => {
try {
const refreshToken = await axios('https://api.dropbox.com/1/oauth2/token', {
method: 'post',
params: {
code: code,
grant_type: 'authorization_code',
code_verifier: code_verifier,
client_id: await this.getClientID(log)
}
}).catch(err => log.warn('getRefreshToken Dropbox: ' + err));
if (refreshToken && refreshToken.data && refreshToken.data.refresh_token) {
resolve(refreshToken.data.refresh_token);
} else {
reject();
}
} catch (e) {
console.log('error getRefreshToken Dropbox: ' + e);
reject();
}
});
}
getClientID(log) {
return new Promise(async (resolve, reject) => {
try {
const urlRequest = await axios({
method: 'get',
url: OAUTH_URL,
headers: {
'User-Agent': 'axios/1.6.5'
},
responseType: 'json'
}).catch(err => log.warn('getClientID Dropbox: ' + err));
if (urlRequest && urlRequest.data && urlRequest.data.client_id) {
resolve(urlRequest.data.client_id)
} else {
reject();
}
} catch (e) {
console.log('error getClientID Dropbox: ' + e);
reject();
}
});
}
getToken(refreshToken, log) {
return new Promise(async (resolve, reject) => {
try {
const accessToken = await axios('https://api.dropbox.com/1/oauth2/token', {
method: 'post',
params: {
refresh_token: refreshToken,
grant_type: 'refresh_token',
client_id: await this.getClientID(log)
}
}).catch(err => log.warn('getToken Dropbox: ' + err));
if (accessToken && accessToken.data && accessToken.data.access_token) {
resolve(accessToken.data.access_token);
} else {
reject();
}
} catch (e) {
console.log('error getToken Dropbox: ' + e);
reject();
}
});
}
sessionUpload(dbx, fileName, dir, log) {
return new Promise(async (resolve, reject) => {
const fs = require('node:fs');
const path = require('node:path');
try {
const chunkLength = 1000000;
const fileSize = fs.statSync(fileName).size;
if (fileSize) {
const onlyFileName = fileName.split('/').pop();
const dbxPth = path.join(dir, onlyFileName).replace(/\\/g, '/');
const getNextChunkStream = (start, end) => fs.createReadStream(fileName, { start, end });
const append = async (sessionId, start, end) => {
if (start === fileSize) {
log.debug(`${Math.round((end / fileSize) * 100)}% uploaded from ${onlyFileName}...`);
resolve('done');
return await this.sessionFinish(sessionId, dbx, log, dbxPth, fileSize);
}
if (end > fileSize) {
end = fileSize - 1;
log.debug(`${Math.round((start / fileSize) * 100)}% uploaded from ${onlyFileName}...`);
return await this.sessionAppend(sessionId, dbx, getNextChunkStream, log, start, fileSize - 1)
.then(async () => {
log.debug(`${Math.round((end / fileSize) * 100)}% uploaded from ${onlyFileName}...`);
resolve('done');
return await this.sessionFinish(sessionId, dbx, log, dbxPth, fileSize);
});
}
log.debug(`${Math.round((start / fileSize) * 100)}% uploaded from ${onlyFileName}...`);
await this.sessionAppend(sessionId, dbx, getNextChunkStream, log, start, end)
.then(async () => {
append(sessionId, end + 1, end + chunkLength);
});
}
const sessionId = await this.sessionStart(dbx, log);
if (sessionId) {
append(sessionId, 0, chunkLength - 1);
}
} else {
reject('Error Session Upload');
}
} catch (err) {
reject(`Error Session Upload: ${JSON.stringify(err)}`);
}
});
}
sessionStart(dbx, log) {
return new Promise(async (resolve, reject) => {
dbx({
resource: 'files/upload_session/start',
parameters: {
close: false
},
}, async (err, result) => {
if (err) {
log.error('sessionStart error: ' + JSON.stringify(err));
reject(err);
}
if (result && result.session_id) {
resolve(result.session_id);
} else {
reject();
}
});
});
}
sessionAppend(sessionId, dbx, getNextChunkStream, log, start, end) {
return new Promise(async (resolve, reject) => {
dbx({
resource: 'files/upload_session/append_v2',
parameters: {
cursor: {
session_id: sessionId,
offset: start
},
close: false,
},
readStream: getNextChunkStream(start, end)
}, async (err) => {
if (err) {
log.error(); ('sessionAppend error: ' + JSON.stringify(err));
reject(err);
}
resolve();
});
});
}
sessionFinish(sessionId, dbx, log, dbxPth, fileSize) {
return new Promise(async (resolve, reject) => {
dbx({
resource: 'files/upload_session/finish',
parameters: {
cursor: {
session_id: sessionId,
offset: fileSize
},
commit: {
path: dbxPth,
mode: "add",
autorename: true,
mute: false
}
}
}, (err) => {
if (err) {
log.error('sessionFinish error: ' + JSON.stringify(err));
reject(err);
}
});
resolve();
});
}
}
module.exports = dropbox;