Last active
January 4, 2019 00:52
-
-
Save iczero/48f985c9e2f2c14bb3a487132d5a098f to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const repl = require('repl'); | |
const LeagueClientAPI = require('./lol-client-api'); | |
const http = require('http'); | |
const util = require('util'); | |
// set this to the path to LeagueClient.exe (example for linux) | |
const LEAGUE_EXE_PATH = process.env.HOME + '/Games/league-of-legends/drive_c/Riot Games/League of Legends/LeagueClient.exe'; | |
// options for util.inspect when formatting responses | |
const INSPECT_OPTS = { | |
depth: Infinity, | |
colors: true | |
}; | |
let api = new LeagueClientAPI(LEAGUE_EXE_PATH); | |
api | |
.on('connect', () => console.log('Found lockfile')) | |
.on('disconnect', () => console.log('Lockfile removed')) | |
.on('wsConnect', () => console.log('WebSocket events connected')) | |
.on('wsDisconnect', () => console.log('WebSocket events disconnected')) | |
.on('event', ev => { | |
console.log(`===== Event: ${ev.eventType} ${ev.uri}`); | |
console.log(util.inspect(ev.data, INSPECT_OPTS)); | |
console.log(''); | |
}) | |
.on('error', err => console.error(err)); | |
let replServer = repl.start({ | |
breakEvalOnSigint: true | |
}); | |
replServer.on('exit', () => process.exit(0)); | |
replServer.context.api = api; | |
let request = function replDoRequest(method, endpoint, options) { | |
api.doRequest( | |
method, | |
endpoint, | |
Object.assign({}, { | |
transform(body, response) { | |
return { response, body }; | |
}, | |
simple: false | |
}, options) | |
) | |
.then(result => { | |
console.log(`===== Response: ${method} ${endpoint}`); | |
let res = result.response; | |
console.log(`HTTP/${res.httpVersion} ${res.statusCode} ${res.statusMessage || ''}`); | |
for (let [header, content] of Object.entries(res.headers)) { | |
console.log(`${header}: ${content}`); | |
} | |
console.log(''); | |
console.log(util.inspect(result.body, INSPECT_OPTS)); | |
console.log(''); | |
}); | |
}; | |
for (let method of http.METHODS) { | |
request[method.toLowerCase()] = Function.prototype.bind.call(request, null, method); | |
} | |
replServer.context.request = request; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const LCUConnector = require('lcu-connector'); | |
const WebSocket = require('ws'); | |
const EventEmitter = require('events'); | |
const request = require('request-promise'); | |
const messageTypes = { | |
WELCOME: 0, | |
PREFIX: 1, | |
CALL: 2, | |
CALLRESULT: 3, | |
CALLERROR: 4, | |
SUBSCRIBE: 5, | |
UNSUBSCRIBE: 6, | |
PUBLISH: 7, | |
EVENT: 8 | |
}; | |
/** Represents an API client for the League of Legneds client API */ | |
class LeagueClientAPI extends EventEmitter { | |
/** | |
* The constructor | |
* @param {String} exePath Path to LeagueClient.exe | |
*/ | |
constructor(exePath) { | |
super(); | |
this.exePath = exePath; | |
this.connector = new LCUConnector(exePath); | |
this.connectionData = null; | |
this.wsConnection = null; | |
this._init(); | |
} | |
/** | |
* Initializes async stuff | |
*/ | |
_init() { | |
this.connector.start(); | |
this.connector.on('connect', this._onLockfileExists.bind(this)); | |
this.connector.on('disconnect', this._onLockfileGone.bind(this)); | |
} | |
/** | |
* Called internally when lcu-connector finds a lockfile | |
* @param {Object} data | |
*/ | |
_onLockfileExists(data) { | |
this.emit('connect'); | |
this.connectionData = data; | |
this.urlPrefix = `${data.protocol}://127.0.0.1:${data.port}`; | |
this.connectWs(data); | |
} | |
/** | |
* Called internally when the lockfile is deleted | |
*/ | |
_onLockfileGone() { | |
this.connectionData = null; | |
this.urlPrefix = null; | |
this.emit('disconnect'); | |
} | |
/** | |
* Attempt to connect to the websocket server | |
* @param {Object} data Connection data | |
*/ | |
connectWs(data) { | |
if (!this.connectionData) return; | |
this.wsConnection = new WebSocket(`ws${data.protocol === 'https' ? 's' : ''}://127.0.0.1:${data.port}`, { | |
headers: { | |
'Authorization': 'Basic ' + | |
Buffer.from('riot:' + data.password).toString('base64') | |
}, | |
rejectUnauthorized: false | |
}); | |
this.wsConnection | |
.on('open', () => { | |
this.emit('wsConnect'); | |
// subscribe to events | |
this.wsConnection.send(JSON.stringify([5, 'OnJsonApiEvent'])); | |
}) | |
.on('close', code => { | |
this.emit('wsDisconnect', code); | |
this.wsConnection = null; | |
}) | |
.on('error', err => { | |
// because the server isn't up yet | |
this.emit('wsError', err); | |
// retry | |
setTimeout(() => this.connectWs(data), 1000); | |
}) | |
.on('message', this._handleWsMessage.bind(this)); | |
} | |
/** | |
* Handles a websocket message | |
* @param {Object} message | |
*/ | |
_handleWsMessage(message) { | |
try { | |
message = JSON.parse(message); | |
} catch (err) { | |
// the first message sent is an empty string | |
} | |
let [type, ...data] = message; | |
if (!type) return; | |
switch (type) { | |
// TODO: deal with other types | |
case messageTypes.EVENT: { | |
let event = data[1]; | |
this.emit('event', event); | |
this.emit('event-' + event.uri, event.eventType, event.data); | |
break; | |
} | |
} | |
} | |
/** | |
* Make an API request | |
* @param {String} method HTTP method | |
* @param {String} endpoint API endpoint | |
* @param {Object} options Additional options to request() | |
* @return {Object} The result of the request | |
*/ | |
async doRequest(method, endpoint, options) { | |
return await request({ | |
method, | |
url: this.urlPrefix + endpoint, | |
json: true, | |
headers: { | |
'Accept': 'application/json' | |
}, | |
auth: { | |
user: 'riot', | |
pass: this.connectionData.password | |
}, | |
rejectUnauthorized: false, | |
...options | |
}); | |
} | |
} | |
LeagueClientAPI.messageTypes = messageTypes; | |
module.exports = LeagueClientAPI; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment