UNPKG

athom-cli

Version:

Command-line interface for Homey Apps

228 lines (188 loc) 5.59 kB
'use strict'; const os = require('os'); const config = require('../../config.js'); const Log = require('../..').Log; const Settings = require('../..').Settings; const AthomCloudAPI = require('athom-api').AthomCloudAPI; const inquirer = require('inquirer'); const colors = require('colors'); const _ = require('underscore'); const fetch = require('node-fetch'); class AthomApi { constructor() { this._api = null; this._user = null; this._homeys = null; this._activeHomey = null; } async _initApi() { if( this._api ) return this._api; let token = await Settings.get('athomToken'); if( token === null ) token = await this.login(); this._api = new AthomCloudAPI({ token, clientId: config.athomApiClientId, clientSecret: config.athomApiClientSecret, }); this._api.on('token', token => { Settings.set('athomToken', token); }) } async login() { Log(colors.bold('To log in with your Athom Account, please visit', colors.underline.cyan(config.athomApiLoginUrl))); let answers = await inquirer.prompt([ { 'type': 'input', 'name': 'token', 'message': 'Paste the Account Token:', } ]); try { let token = answers.token; token = new Buffer(token, 'base64').toString(); token = JSON.parse(token); await Settings.set('athomToken', token); let profile = await this.getProfile(); Log(colors.green(`✓ You are now logged in as ${profile.firstname} ${profile.lastname}`)); return token; } catch( err ) { Log(colors.red('Invalid Account Token, please try again')); await Settings.unset('athomToken'); } } async logout() { Log(colors.green('✓ You are now logged out')); await Settings.unset('athomToken'); await this.unsetActiveHomey(); } async getProfile() { await this._initApi(); return this._api.getAuthenticatedUser(); } async getHomey( homeyId, { cache = false } = {}) { let homeys = await this.getHomeys(); for( let i = 0; i < homeys.length; i++ ) { let homey = homeys[i]; if( homey._id === homeyId ) return homey; } throw new Error('Invalid Homey'); } async getHomeys({ cache = true, local = true, } = {}) { if( cache && this._homeys ) return this._homeys; await this._initApi(); this._user = this._user || await this._api.getAuthenticatedUser(); this._homeys = await this._user.getHomeys(); // find USB connected Homeys if( local ) { let ifaces = os.networkInterfaces(); let candidates = []; for( let ifaceId in ifaces ) { let adapters = ifaces[ifaceId]; for( let i = 0; i < adapters.length; i++ ) { let adapter = adapters[i]; try { let ip = adapter.address.split('.'); if( ip[0] !== '10' ) continue; ip[3] = '1'; ip = ip.join('.'); let res = await fetch(`http://${ip}/api/manager/webserver/ping`, { timeout: 1000, }) if( !res.ok ) continue; let homeyId = res.headers.get('x-homey-id'); if( !homeyId ) continue; let homey = _.findWhere(this._homeys, { id: homeyId }) if( homey ) { homey.usb = ip; } } catch( err ) {} } } } return this._homeys; } async getActiveHomey() { if( this._activeHomey ) return this._activeHomey; let activeHomey = await Settings.get('activeHomey'); if( activeHomey === null ) { activeHomey = await this.selectActiveHomey(); } this._activeHomey = this.getHomey( activeHomey.id ).then(async homey => { let homeyApi = await homey.authenticate() homeyApi.name = homey.name; if( homey.usb ) { homeyApi.baseUrl = Promise.resolve(`http://${homey.usb}:80`); } return homeyApi; }); return this._activeHomey; } async setActiveHomey({ id, name }) { return Settings.set('activeHomey', { id, name }); } async unsetActiveHomey() { return Settings.unset('activeHomey'); } async selectActiveHomey({ id, name, filter = { online: true, local: true, } } = {}) { let homeys = await this.getHomeys(); let activeHomey; if( typeof id === 'string' ) { activeHomey = _.findWhere(homeys, { _id: id }); } else if( typeof name === 'string' ) { activeHomey = _.findWhere(homeys, { name }); } else { let answers = await inquirer.prompt([ { type: 'list', name: 'homey', message: 'Choose an active Homey:', choices: homeys .filter(homey => { if( filter.online && homey.state && homey.state.indexOf('online') !== 0 ) return false; return true; }) .map(homey => { let state = this.getFormattedState( homey ); return { value: { name: homey.name, id: homey._id, }, name: homey.name + ( state ? ` (${state})` : '' ) } }) } ]); activeHomey = answers.homey; } if( !activeHomey ) throw new Error('No Homey found'); let result = await this.setActiveHomey( activeHomey ); Log(`You have selected \`${activeHomey.name}\` as your active Homey.`); return result; } async unselectActiveHomey() { await this.unsetActiveHomey(); Log(`You have unselected your active Homey.`); } getFormattedState( homey ) { let state = homey.state || ''; state = state.split('_')[0]; if( state === 'online' ) state = colors.green(state); if( state === 'offline' ) state = colors.red(state); if( state === 'rebooting' ) state = colors.yellow(state); if( state === 'updating' ) state = colors.magenta(state); return state; } } module.exports = AthomApi;