Files
yunkong2.adapter_studio/main.js
2018-08-07 20:43:49 +08:00

776 lines
24 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

'use strict';
// you have to require the utils module and call adapter function
const utils = require(__dirname + '/lib/utils'); // Get common adapter utils
const exec = require('child_process').exec;
const execSync = require('child_process').execSync;
const os = require('os');
const fs = require('fs');
const request = require('request');
let plattform = os.platform();
// you have to call the adapter function and pass a options object
// name has to be set and has to be equal to adapters folder name and main file name excluding extension
// adapter will be restarted automatically every time as the configuration changed, e.g system.adapter.adapter_studio.0
const adapter = new utils.Adapter('adapter-studio');
// is called when adapter shuts down - callback has to be called under any circumstances!
adapter.on('unload', (callback) => {
try {
adapter.log.info('cleaned everything up...');
callback();
} catch (e) {
callback();
}
});
// is called if a subscribed object changes
adapter.on('objectChange', (id, obj) => {
// Warning, obj can be null if it was deleted
adapter.log.info('objectChange ' + id + ' ' + JSON.stringify(obj));
});
// is called if a subscribed state changes
adapter.on('stateChange', (id, state) => {
// Warning, state can be null if it was deleted
adapter.log.info('stateChange ' + id + ' ' + JSON.stringify(state));
// you can use the ack flag to detect if it is status (true) or command (false)
if (state && !state.ack) {
adapter.log.info('ack is not set!');
}
});
// Some message was sent to adapter instance over message box. Used by email, pushover, text2speech, ...
adapter.on('message', (obj) => {
adapter.log.info(JSON.stringify(obj));
if (typeof obj === 'object' && obj.message) {
if (obj.command === 'send') {
// e.g. send email or pushover or whatever
//adapter.log.debug('send command');
// Send response in callback if required
//if (obj.callback) adapter.sendTo(obj.from, obj.command, 'Message received', obj.callback);
if(obj.message === 'getAdapterList'){
getAdapters((res) => {
//adapter.log.info(`Callback ${res}`);
if (obj.callback) adapter.sendTo(obj.from, obj.command, res, obj.callback);
})
}
if(obj.message.command === 'getAdapterFiles'){
getAdapterFiles(obj.message.folder, (res) => {
if (obj.callback) adapter.sendTo(obj.from, obj.command, res, obj.callback);
});
}
if(obj.message.command === 'openFile'){
openFile(obj.message.file, (res) => {
if (obj.callback) adapter.sendTo(obj.from, obj.command, res, obj.callback);
});
}
if(obj.message.command === 'saveFile'){
saveFile(obj.message.file, obj.message.data, (res) => {
if (obj.callback) adapter.sendTo(obj.from, obj.command, res, obj.callback);
});
}
if(obj.message.command === 'uploadFiles'){
uploadFiles(obj.message.adapterName, (res) => {
if (obj.callback) adapter.sendTo(obj.from, obj.command, res, obj.callback);
});
}
if(obj.message.command === 'ssAdapter'){
ssAdapter(obj.message.adapterName, obj.message.cmd, (res) => {
if (obj.callback) adapter.sendTo(obj.from, obj.command, res, obj.callback);
});
}
if(obj.message.command === 'createAdapter'){
createAdapter(obj.message, (res) => {
if (obj.callback) adapter.sendTo(obj.from, obj.command, res, obj.callback);
});
}
if(obj.message.command === 'getRunningState'){
getRunningState(obj.message.adapterName, (res) => {
if (obj.callback) adapter.sendTo(obj.from, obj.command, res, obj.callback);
});
}
if(obj.message.command === 'npmPublish'){
npmPublish(obj.message.adapterName, (res) => {
if (obj.callback) adapter.sendTo(obj.from, obj.command, res, obj.callback);
});
}
if(obj.message.command === 'npmAddUser'){
npmAdduser(obj.message.user, obj.message.password, obj.message.email, (res) => {
if (obj.callback) adapter.sendTo(obj.from, obj.command, res, obj.callback);
});
}
if(obj.message.command === 'checkoutGithub'){
checkoutGithub(obj.message.link, (res) => {
if (obj.callback) adapter.sendTo(obj.from, obj.command, res, obj.callback);
});
}
if(obj.message.command === 'githubPublish'){
createNewGHRepo(obj.message.adapterName, (res) => {
if (obj.callback) adapter.sendTo(obj.from, obj.command, res, obj.callback);
});
}
}
}
});
// is called when databases are connected and adapter received configuration.
// start here!
adapter.on('ready', () => {
main();
});
function main() {
adapter.log.info(plattform);
adapter.log.info(__dirname);
createNewGHRepo('test', ()=>{});
}
let ready = true;
let s;
switch(plattform){
case 'win32':
s = '\\';
break;
case 'linux':
s = '/';
break;
}
function createAdapter(data, callback){
//adapter.log.info(JSON.stringify(data));
let newName = data.name;
newName = newName.replace(' ', '-');
newName = newName.toLowerCase();
let odir = __dirname;
let path = odir.replace('yunkong2.adapter-studio', `yunkong2.${newName}`);
let remove = ['.git'];
let addFiles = [];
let newFile = [];
if(data.widgets === false){
remove.push('widgets')
}
if(data.webpage === false){
remove.push('www')
}
if(data.adminv2 === false){
remove.push(`admin${s}index.html`);
}
if(data.license !== 'MIT'){
let folder = `${s}licenses${s}`;
remove.push('LICENSE');
switch(data.license){
case 'Apache 2.0':
addFiles.push(`${folder}Apache_2.0`);
break;
case 'CC-BY':
addFiles.push(`${folder}CC-BY`);
break;
case 'CC-BY-NC':
addFiles.push(`${folder}CC-BY-NC`);
break;
case 'CC-BY-NC-SA':
addFiles.push(`${folder}CC-BY-NC-SA`);
break;
case 'OFL-1.1':
addFiles.push(`${folder}OFL_1.1`);
break;
case 'EPL':
addFiles.push(`${folder}EPL`);
break;
case 'LGPL':
addFiles.push(`${folder}LGPL_v3`);
break;
case 'GPLv3':
addFiles.push(`${folder}GPLv3`);
break;
case 'GPLv2':
addFiles.push(`${folder}GPLv2`);
break;
}
newFile.push('LICENSE');
}
if(data.adminv2 === true){
addFiles.push('tab.html');
newFile.push(`admin${s}tab.html`);
}
if(data.tab === true){
addFiles.push('tab_m.html');
addFiles.push('tab.js');
newFile.push(`admin${s}tab_m.html`);
newFile.push(`admin${s}tab.js`);
}
let gclone = `git clone --depth=1 https://git.spacen.net/yunkong2/yunkong2.template.git ${path}`;
let child = exec(gclone);
child.stderr.pipe(process.stdout);
child.on('exit', () => {
//if (callback) callback(adapter);
for(let i = 0; i <= remove.length -1; i++){
let rm = new RemoveFaF(remove[i], path);
}
for(let i = 0; i <= addFiles.length -1; i++){
let rm = new AddTFiles(addFiles[i], path, newFile[i]);
}
fs.readFile(`${path}${s}io-package.json`, (err, output) => {
let json = JSON.parse(output);
if (err) throw err;
if(data.mode.toLowerCase() === 'schedule'){
json.common.schedule = data.cron
}
json.common.mode = data.mode.toLowerCase();
json.common.license = data.license;
json.common.enabled = data.enabled;
json.common.loglevel = data.logLevel;
json.common.type = data.type;
json.common.messagebox = data.messagebox;
if(data.tab === true){
json.common.materialize = true;
json.common.adminTab = {"name": newName};
}
//Keywords
let keywords = data.keywords;
keywords = keywords.split(', ');
json.common.keywords = keywords;
json.common.version = '0.0.1';
json.common.news = {"0.0.1": { "en": "initial version created with Adapter-Studio by Jey Cee", "de": "erste Version erstellt mit Adapter-Studio von Jey Cee", "ru": "начальная версия, созданная с помощью Adapter-Studio by Jey Cee", "pt": "versão inicial criada com o Adapter-Studio por Jey Cee", "nl": "eerste versie gemaakt met Adapter-Studio door Jey Cee", "fr": "Version initiale créée avec Adapter-Studio par Jey Cee", "it": "versione iniziale creata con Adapter-Studio di Jey Cee", "es": "versión inicial creada con Adapter-Studio por Jey Cee", "pl": "początkowa wersja stworzona za pomocą Adapter-Studio przez Jey Cee"}};
if(data.widgets === true){
json.restartAdapters = ["vis"];
}
//Adapter dependencies
if(data.depAdapters.length === 0){
}else {
let adapters = data.depAdapters;
adapters = adapters.split(', ');
let arr = {};
for (let i in adapters) {
let x = adapters[i].split(' ');
arr[x[0]] = `${x[1]}`;
}
//let jsonArr = `"dependencies": [${arr}]`;
json.common.dependencies = arr;
}
fs.writeFile(`${path}${s}io-package.json`, JSON.stringify(json, null, 4), (err) => {
if (err) throw err;
adapter.log.info('The file io-package.json has been saved!');
});
});
fs.readFile(`${path}${s}package.json`, (err, output) => {
let json = JSON.parse(output);
if (err) throw err;
json.license = data.license;
json.version = '0.0.1';
//Keywords
let keywords = data.keywords;
keywords = keywords.split(', ');
json.keywords = keywords;
//dependencies
if(data.dependencies.length > 0){
let dependencies = data.dependencies;
dependencies = dependencies.split(', ');
let arr = {};
for(let i in dependencies){
let x = dependencies[i].split(' ');
arr[x[0]] = `${x[1]}`;
}
if(arr.length === 0){
json.dependencies = '';
}else{
json.dependencies = arr;
}
}
json.scripts = {"gulp": "gulp"};
fs.writeFile(`${path}${s}package.json`, JSON.stringify(json, null, 4), (err) => {
let email = data.email;
let author = data.author;
adapter.log.info(`rename information: ${email}, ${author}`);
if (err) throw err;
adapter.log.info('The file package.json has been saved!');
installDependencies(path, (data)=>{
if(data === 'Error'){
callback('Error');
}else{
adapter.log.info(`rename information: ${email}, ${author}`);
rename(path, newName, email, author, () => {
let cmd = 'git add .';
const child = exec(cmd, {cwd: path});
child.stderr.pipe(process.stdout);
child.on('exit', (code) => {
if(code === 0){
callback('Error')
}else{
callback('Done')
}
child.stderr.on('data',(data) => {
adapter.log.info('stderr: ' + data.toString());
});
child.stdout.on('data',(data) => {
adapter.log.info('stdout: ' + data.toString());
});
});
});
}
});
});
});
});
}
function RemoveFaF(name, path){
ready = false;
let cmd;
switch(plattform){
case 'win32':
cmd = `del /Q /S /F ${name} & rd /S /Q ${name}`;
break;
case 'linux':
cmd = `rm -r ${name}`;
break;
}
const child = exec(cmd, {cwd: path});
child.stderr.pipe(process.stdout);
child.on('exit', () => {
});
}
function AddTFiles(file, path, newFile){
ready = false;
let cmd;
switch(plattform){
case 'win32':
cmd = `copy ${__dirname}\\templates\\${file} ${newFile}`;
break;
case 'linux':
cmd = `mv ${__dirname}/templates/${file} ${newFile}`;
break;
}
const child = exec(cmd, {cwd: path});
child.stderr.pipe(process.stdout);
child.on('exit', () => {
});
}
function cacheClean(path, callback){
let cmd = `npm cache clean --force`;
const child = exec(cmd, {cwd: path});
child.stderr.pipe(process.stdout);
child.on('exit', (code) => {
adapter.log.info(`Exit code cache clean: ${code}`);
callback('Done')
});
}
function installDependencies(path, callback){
cacheClean(path, (result)=>{
if(result === 'Done'){
let cmd = `npm install`;
const child = exec(cmd, {cwd: path});
child.stderr.pipe(process.stdout);
child.on('exit', (code) => {
adapter.log.info(`Exit code install dependencies: ${code}`);
if(code === 0){
let cmd = `npm install --only=dev`;
const child = exec(cmd, {cwd: path});
child.stderr.pipe(process.stdout);
child.on('exit', (code) => {
adapter.log.info(`Exit code install dev dependencies: ${code}`);
if(code === 0){
callback('Done');
}else{
callback('Error');
}
});
}else{
callback('Error');
}
});
}
})
}
function rename(path, name, email, author, callback){
let cmd = `npm install --global gulp-cli`;
const child = exec(cmd, {cwd: path});
child.stderr.pipe(process.stdout);
child.on('exit', (code) => {
let cmd = `npm run gulp -- rename --name ${name} --email ${email} --author "${author}"`;
const child = exec(cmd, {cwd: path});
child.stderr.pipe(process.stdout);
child.on('exit', (code) => {
if (code !== 0) {
callback('Error');
} else {
callback('Done');
}
});
child.stderr.on('data',(data) => {
adapter.log.info('stderr: ' + data.toString());
});
child.stdout.on('data',(data) => {
adapter.log.info('stdout: ' + data.toString());
});
});
child.stderr.on('data',(data) => {
adapter.log.info('stderr: ' + data.toString());
});
child.stdout.on('data',(data) => {
adapter.log.info('stdout: ' + data.toString());
});
}
function getAdapters(callback){
//adapter.log.debug('Get list of adapters');
let odir = __dirname;
let node_modules = odir.replace('yunkong2.adapter-studio', ``);
fs.readdir(node_modules,(err, files) =>{
let arrA = [];
for(let x in files){
const patt = new RegExp(/io(b|B)roker..*/g);
const patt2 = new RegExp(/.rar$/g);
let name = files[x].match(patt);
if(name !== null){
let nA = name[0].match(patt2);
if(nA === null) {
arrA.push(name[0]);
}
}
}
callback(arrA);
})
}
function getAdapterFiles(name, callback){
let odir = __dirname;
let folder;
const patt = new RegExp(/.io(b|B)roker\.\w*.\w*.\w*/g);
let test = name.match(patt);
if(test !== null){
if(plattform === 'win32'){
let patt2 = new RegExp('/', 'g');
name = name.replace(patt2, s);
}
folder = name;
}else{
folder = odir.replace('yunkong2.adapter-studio', `${s}${name}`);
}
fs.readdir(folder,(err, files) => {
if(err){adapter.log.error(err)}
let arrA = {};
for (let x in files) {
if(fs.lstatSync(`${folder}${s}${files[x]}`).isDirectory()){
arrA[x] = {"name": files[x], "type": "folder", "parent": folder};
}else{
arrA[x]= {"name": files[x], "type": "file", "parent": folder};
}
}
adapter.log.info('Read files');
callback(arrA);
});
}
function openFile(file, callback){
adapter.log.info('open file');
if(plattform === 'win32'){
let patt2 = new RegExp('/', 'g');
file = file.replace(patt2, s);
}
const patt = new RegExp('.png');
let res = patt.test(file);
fs.readFile(file, (err, output) => {
if(err){adapter.log.error(err)};
//adapter.log.debug(output);
if(!res){
callback(output)
}else{
let Buffer = require('buffer').Buffer;
let picture = Buffer.from(output).toString('base64');
callback(picture);
}
})
}
function saveFile(file, data, callback){
if(plattform === 'win32'){
let patt2 = new RegExp('/', 'g');
file = file.replace(patt2, s);
}
fs.writeFile(file, data, (err, output) => {
if (err) throw err;
adapter.log.info(`The file ${file} has been saved!`);
callback('Done');
})
}
function uploadFiles(adapterName, callback){
let odir = __dirname;
let baseDir = odir.match(/.*io(b|B)roker(\/|\\)/);
//baseDir = JSON.stringify(baseDir[0]);
exec(`yunkong2 upload ${adapterName}`, {cwd: baseDir[0]}, (error, stderr, stdout) => {
//adapter.log.info('stdout: ' + stdout);
//adapter.log.info('stderr: ' + stderr);
if (error !== null) {
adapter.log.error('exec error: ' + error);
}
callback('Done');
});
}
function ssAdapter(adapterName, cmd, callback){
let odir = __dirname;
let baseDir = odir.match(/.*io(b|B)roker(\/|\\)/);
//baseDir = JSON.stringify(baseDir[0]);
exec(`yunkong2 ${cmd} ${adapterName}`, {cwd: baseDir[0]}, (error, stderr, stdout) => {
//adapter.log.info('stdout: ' + stdout);
//adapter.log.info('stderr: ' + stderr);
if (error !== null) {
adapter.log.error('exec error: ' + error);
}else {
const patt = new RegExp(/Adapter .* (started|stopped|restarted)./gm);
if (patt.test(stderr)) {
callback('Done');
} else if (patt.test(stdout)) {
callback('Done');
} else {
ssAdapter(adapterName, 'restart', callback);
}
}
});
}
function getRunningState(adapterName, callback){
adapter.getForeignState(`system.adapter.${adapterName}.0.alive`, (err, state) => {
adapter.log.info(JSON.stringify(state));
if(err){
callback('Error')
}else if(state === null){
callback('false')
}else if(state !== null && state !== undefined){
callback(state.val)
}
})
}
function npmPublish(adapterName, callback){
let odir = __dirname;
let path = odir.replace('yunkong2.adapter-studio', `${adapterName}`);
let cmd = `npm publish`;
const child = exec(cmd, {cwd: path});
child.stderr.pipe(process.stdout);
child.on('exit', (code) => {
adapter.log.info(`Exit code npmPublish: ${code}`);
if(code === 4294963248){
callback('Login required')
}else if(code === 0){
callback('Done');
}else if(code > 0){
callback('Error')
}
});
child.stderr.on('data',(data) => {
adapter.log.info('stderr: ' + data.toString());
});
child.stdout.on('data',(data) => {
adapter.log.info('stdout: ' + data.toString());
});
}
function npmAdduser(user, password, email, callback){
let odir = __dirname;
let cmd = `npm adduser`;
const child = exec(cmd, {cwd: odir});
child.stderr.pipe(process.stdout);
child.on('exit', (code) => {
adapter.log.info(`Exit code npmPublish: ${code}`);
if (code === 0) {
callback('Done');
} else if (code > 0) {
callback('Error')
}
});
child.stdin.write(user + '\n' + password + '\n' +email + '\n');
//child.stdin.write(password + '\n');
//child.stdin.write(email + '\n');
child.stderr.on('data', (data) => {
adapter.log.info('stderr: ' + data.toString());
});
child.stdout.on('data', (data) => {
adapter.log.info('stdout: ' + data.toString());
switch(data.toString().trim()){
case 'Username:':
child.stdin.write(user + '\n');
break;
case 'Password:':
child.stdin.write(password + '\n');
break;
case 'Email: (this IS public)':
child.stdin.write(email + '\n');
break;
}
});
//child.stdin.end();
}
function createNewGHRepo(adapterName, callback){
let user = adapter.config.ghuser;
let pw = adapter.config.ghpw;
let options = {
url: `https://api.git.spacen.net/user/repos`,
method: 'POST',
headers: {
'Content-Type': 'application/json',
'User-Agent': `${user}`,
'Authorization': 'Basic ' + new Buffer(user + ':' + pw).toString('base64')
}
};
let req = request(options, function (error, res, body){
adapter.log.info('STATUS: ' + res.statusCode);
if(res.statusCode === 403){
callback('Forbidden');
}else if(res.statusCode === 200){
let b = JSON.parse(body);
adapter.log.info(JSON.stringify(b));
callback('Done');
}
});
let content = `{"name": adapterName, "has_wiki": false, "auto_init": false}`;
req.write(content);
}
function checkoutGithub(link, callback){
let odir = __dirname;
let path = odir.replace(`${s}yunkong2.adapter-studio`, ``);
let cmd = `git clone ${link}`;
const child = exec(cmd, {cwd: path});
child.stderr.pipe(process.stdout);
child.on('exit', (code) => {
adapter.log.info(`Exit code checkoutGithub: ${code}`);
if (code === 0) {
callback('Done');
} else if (code > 0) {
callback('Error')
}
});
child.stderr.on('data', (data) => {
adapter.log.info('stderr: ' + data.toString());
});
child.stdout.on('data', (data) => {
adapter.log.info('stdout: ' + data.toString());
});
}