parsec-client
Version:
Client for Parsec Gaming API
200 lines (162 loc) • 5.01 kB
JavaScript
const fs = require('fs')
const path = require('path')
const needle = require('needle')
const WebSocketClient = require('websocket').client
const appDataDir = process.env.APPDATA || (process.platform == 'darwin' ? process.env.HOME + '/Library/Preferences' : process.env.HOME + '/.local/share')
// Get the list of visible servers and all the info about them that we need
function serverGet() {
return new Promise((resolve, reject) => {
needle.get('https://kessel-api.parsecgaming.com/hosts', { headers: { 'Authorization': 'Bearer ' + session } }, (err, resp, body) => {
if (!err && (body || {}).data) {
resolve(body.data)
} else {
console.log(err)
console.log(resp.headers)
console.log(body)
reject(err || Error('Server Get: Unknown Error Occured'))
}
})
})
}
// Perform Daemon commands
let conn
function connectWS() {
return new Promise((resolve, reject) => {
if (conn) {
resolve()
return
}
const client = new WebSocketClient({ closeTimeout: 30000 })
client.on('connectFailed', error => {
console.log('WebSocket Connection Error: ' + error.toString())
})
client.on('connect', connection => {
console.log('WebSocket Client Connected')
connection.on('error', error => {
console.log('WebSocket Connection Error: ' + error.toString())
})
connection.on('close', () => {
console.log('WebSocket Connection Closed')
conn = false
})
conn = connection
resolve()
})
client.connect('ws://127.0.0.1:5309/', null, 'https://parsecgaming.com')
})
}
function command(args) {
return new Promise((resolve, reject) => {
connectWS().then(() => {
function handleMsg(message) {
if (message.type === 'utf8') {
console.log("Received: '" + message.utf8Data + "'")
conn.removeListener('message', handleMsg)
resolve(message.utf8Data) // we consider any first reply as successful
}
}
conn.on('message', handleMsg)
console.log("Sending: '" + JSON.stringify(args) + "'")
conn.sendUTF(JSON.stringify(args))
})
})
}
function connectServer(serverHost) {
console.log('Fetching Servers')
serverGet().then(hosts => {
let host
if (!(hosts || []).length) {
console.error('Parsec server list is empty')
return
}
// select server by predefined id
hosts.some(srv => {
if (srv.name == serverHost) {
host = srv
return true
}
})
if (!host) {
console.error('Server could not be found')
console.log('Server options are:')
console.log(hosts)
return
}
// Do the server-ey connect-ey work
const appClient = {
'session_id': session,
'x-function': 'app_client',
// 'server_build': host['build'] + '',
'peer_id': host['peer_id'] + ''
}
console.log('CMD.app_client')
command(appClient).then(() => {
console.log('Done')
})
})
}
const headers = {
'content-type': 'application/json',
origin: 'https://ui.parsecgaming.com',
referer: 'https://ui.parsecgaming.com/login',
'sec-fetch-mode': 'cors',
'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.90 Safari/537.36'
}
let session
const sessionExpire = 172800000
module.exports = {
start: (opts = {}) => {
let errors = 0
if (!opts.email) {
console.error('No email set in start options')
errors++
}
if (!opts.password) {
console.error('No password set in start options')
errors++
}
if (!opts.host) {
console.error('No host set in start options')
errors++
}
if (errors) {
console.error(errors + ' errors occured, stopping')
return
}
console.log('Logging in')
const sessionFile = path.join(appDataDir, 'parsec_session.private')
function getSession() {
needle.post('https://api.parsecgaming.com/v1/auth', { email: opts.email, password: opts.password, expiration_type: 'long' }, { json: true, headers }, (err, resp, body) => {
if (!err && body && body.session_id) {
console.log('loggin data:')
console.log(body)
session = body.session_id
console.log('Writing Session ID from File')
fs.writeFileSync(sessionFile, session)
connectServer(opts.host)
} else {
console.log('Could Not Get Session ID from Server')
console.log(resp.headers)
console.log(body)
console.error(err || Error('Start Session: Unknown Error'))
}
})
}
if (fs.existsSync(sessionFile)) {
const stats = fs.statSync(sessionFile)
const mtime = new Date(stats.mtime).getTime()
if (Date.now() - mtime > sessionExpire) {
getSession()
} else {
console.log('Retrieving Session ID from File')
session = fs.readFileSync(sessionFile).toString()
connectServer(opts.host)
}
} else {
getSession()
}
},
stop: () => {
command({'x-function': 'app_client_cancel'}).then(() => {})
}
}