218 lines
6.9 KiB
JavaScript
218 lines
6.9 KiB
JavaScript
'use strict'
|
||
|
||
const os = require('os')
|
||
const fs = require('fs')
|
||
const path = require('path')
|
||
const homedir = require('homedir')
|
||
const Store = require('./store')
|
||
const phantomloader = require('./phantomloader')
|
||
const webserver = require('./webserver')
|
||
const Cookies = require('./cookies')
|
||
const Headers = require('./headers')
|
||
const Login = require('./login')
|
||
const proxy = require('./proxy')
|
||
|
||
// file & directory names
|
||
const DATA_DIR = '.alexis'
|
||
const PHANTOMFILE = os.platform() === 'win32' ? 'phantomjs.exe' : 'phantomjs'
|
||
|
||
// computes the data directory
|
||
const getDataDir = () => path.join(homedir(), DATA_DIR)
|
||
// checks if the data directory exists
|
||
const checkDataDirExists = () => fs.existsSync(getDataDir())
|
||
// creates the data directory
|
||
const createDataDir = () => fs.mkdirSync(getDataDir())
|
||
// checks if the PhantomJS binary exists
|
||
const checkPhantomExist = () => fs.existsSync(path.join(getDataDir(), PHANTOMFILE))
|
||
// checks if the given options are valid
|
||
const validateOptions = (options, verbose) => {
|
||
let missing = [];
|
||
['httpPort', 'email', 'pass'].forEach(option => {
|
||
if (!options[option]) missing.push(option)
|
||
})
|
||
if (verbose && missing.length > 0) return missing.join(', ')
|
||
if (missing.length > 0) return false
|
||
return true
|
||
}
|
||
// validate options
|
||
const optionsAreValid = (options = {}, invalidOptionsCb) => {
|
||
if (!options.interval) options.interval = 10
|
||
options.interval = options.interval * 1000
|
||
if(!validateOptions(options)) {
|
||
invalidOptionsCb()
|
||
return false
|
||
}
|
||
return true
|
||
}
|
||
// checks if data dir exists and creates it if not
|
||
const doCreateUserdataDirectory = (data_dir, logger) => {
|
||
if (!checkDataDirExists()) {
|
||
logger.log('SETUP', `Creating data directory: ${data_dir}`)
|
||
createDataDir()
|
||
}
|
||
}
|
||
// checks if Phantom is installed, downloads it if not
|
||
const mountPhantom = async (data_dir, logger) => {
|
||
if (!checkPhantomExist()) {
|
||
phantom_mounted = false
|
||
const phantom_path_name = path.join(data_dir, PHANTOMFILE)
|
||
logger.log('SETUP', 'Downloading Phantom')
|
||
return await Phantom.download(phantom_path_name, data_dir)
|
||
}
|
||
return true
|
||
}
|
||
|
||
// Initializing flow
|
||
const run = async (logger, options, invalidOptionsCb) => {
|
||
// helper variable to determine if cookies exist
|
||
let cookies_exist = false
|
||
// helper variable to determine if cookies are valid
|
||
let cookies_valid = false
|
||
// helper variable to determine if login did work
|
||
let login_success = false
|
||
// init store
|
||
let store = null
|
||
// device data store
|
||
let device_data = null
|
||
// init PhantomJS downlaoder
|
||
const Phantom = phantomloader(logger)
|
||
// cache data dir location
|
||
const data_dir = getDataDir()
|
||
|
||
// validate options
|
||
if (!optionsAreValid(options, invalidOptionsCb)) return false
|
||
|
||
// set up redux store
|
||
logger.log('SETUP', 'Creating in-memory store')
|
||
store = Store()
|
||
|
||
// check if data dir exists, else create
|
||
doCreateUserdataDirectory(data_dir, logger)
|
||
|
||
// checks if Phantom is installed, downloads it if not
|
||
const phantom_mounted = await mountPhantom(data_dir, logger)
|
||
|
||
// check if phantom is mounted
|
||
if (phantom_mounted !== true) {
|
||
logger.log('ERROR', 'Error with mounting Phantom')
|
||
return false
|
||
}
|
||
|
||
// everythings okay
|
||
logger.log('SETUP', 'Dependency check successful')
|
||
|
||
// cookie check
|
||
if (Cookies.checkJsonCookiesExist(data_dir) && Cookies.checkJsonCookiesExist(data_dir)) {
|
||
logger.log('SETUP', 'Cookies exist, trying to reuse them')
|
||
// validate existing cookies
|
||
try {
|
||
cookies_valid = await Cookies.validateCookie(data_dir)
|
||
device_data = cookies_valid[1]
|
||
cookies_valid = cookies_valid[0]
|
||
} catch (e) {
|
||
cookies_valid = false
|
||
}
|
||
|
||
// set flasg & log cookie state
|
||
if (cookies_valid) {
|
||
cookies_exist = true
|
||
login_success = true
|
||
logger.log('SETUP', 'Cookies valid, connection could be established')
|
||
} else {
|
||
cookies_exist = false
|
||
logger.log('SETUP', 'Cookies invalid, connection could not be established')
|
||
}
|
||
}
|
||
|
||
// create a new set of cookies by logging in
|
||
if (!cookies_exist) {
|
||
logger.log('SETUP', 'No cookies found or invalid, logging in to create a fresh pair')
|
||
try {
|
||
login_success = await Login.fetchInitialCookies(
|
||
Cookies.getJsonCookiePath(data_dir),
|
||
Cookies.getRawCookiePath(data_dir),
|
||
Headers.ua,
|
||
options.email,
|
||
options.pass,
|
||
path.join(data_dir, PHANTOMFILE),
|
||
)
|
||
} catch (error) {
|
||
console.log(error)
|
||
if (error === 'captcha') {
|
||
logger.log('ERROR', 'Login failed, we got a captcha notice. Please change your public IP and try again.')
|
||
} else {
|
||
logger.log('ERROR', 'Login failed, please check your credentials')
|
||
}
|
||
login_success = false
|
||
return false
|
||
}
|
||
// Login should´ve been successful, lets validate
|
||
logger.log('SETUP', 'Login successful')
|
||
|
||
// cookie check
|
||
if (Cookies.checkJsonCookiesExist(getDataDir()) && Cookies.checkJsonCookiesExist(getDataDir())) {
|
||
// validate existing cookies
|
||
try {
|
||
cookies_valid = await Cookies.validateCookie(getDataDir())
|
||
device_data = cookies_valid[1]
|
||
cookies_valid = cookies_valid[0]
|
||
} catch (e) {
|
||
cookies_valid = false
|
||
}
|
||
|
||
// set flasg & log cookie state
|
||
if (cookies_valid) {
|
||
logger.log('SETUP', 'Cookies valid, connection could be established')
|
||
} else {
|
||
logger.log('SETUP', 'Cookies invalid, connection could not be established')
|
||
return false
|
||
}
|
||
}
|
||
}
|
||
|
||
// set up proxy dialer
|
||
const Proxy = await proxy(logger, data_dir, store)
|
||
|
||
// initial fetch of data
|
||
logger.log('SETUP', 'Fetching initial data')
|
||
const initial_data = await Proxy.fetchAll()
|
||
logger.log('SETUP', 'Fetch finished')
|
||
|
||
// start webserver
|
||
logger.log('SETUP', 'Starting webserver')
|
||
try {
|
||
await webserver(logger, options.httpPort, store, Proxy)
|
||
} catch (error) {
|
||
logger.log('ERROR', `Problem starting webserver: ${error}`)
|
||
return false
|
||
}
|
||
|
||
// set up scheduler to periodically fetch data
|
||
logger.log('SETUP', `Setting up scheduler with interval: ${options.interval}ms`)
|
||
|
||
// display data about the echo devices we found
|
||
logger.log('ECHO', `Found ${device_data.devices.length} Device(s) connected with this account`)
|
||
device_data.devices.forEach(device => {
|
||
logger.log('ECHO', `---------------------------------`)
|
||
logger.log('ECHO', `Name: ${device.accountName}`)
|
||
logger.log('ECHO', `Id: ${device.deviceAccountId}`)
|
||
logger.log('ECHO', `Type: ${device.deviceFamily}`)
|
||
logger.log('ECHO', `Active: ${device.online}`)
|
||
logger.log('ECHO', `Mac Address: ${device.macAddress}`)
|
||
})
|
||
logger.log('ECHO', `---------------------------------`)
|
||
|
||
// setup done, system is ready to use
|
||
logger.log('SETUP', 'Setup finished. Ready to use. Have Fun!')
|
||
return true
|
||
}
|
||
|
||
module.exports = (logger) => {
|
||
return {
|
||
getDataDir,
|
||
checkDataDirExists,
|
||
createDataDir,
|
||
checkPhantomExist,
|
||
run: run.bind(this, logger)
|
||
}
|
||
} |