diff --git a/README.md b/README.md index 6383a29..7a696ed 100644 --- a/README.md +++ b/README.md @@ -2,28 +2,7 @@ ---- -Always up to date documentation for the League of Legends client API. - -### Post v8.14 requirements -Since League of Legends v8.14 RIOT hid some developer functionality behind a flag. To make Rift Explorer work with newer versions of the game you need to manually enable the *swagger endpoint* by hand. - -To enable *swagger* you need to add the `enable_swagger: true` at the start of the `system.yaml` file before starting the LCU client. - -![Swagger explainer](assets/swagger.png?raw=true) - -The file can be found here based on your OS - -- **Windows** - - `C:\Riot Games\League of Legends\RADS\projects\league_client\releases\\deploy\system.yaml` - -- **MacOS** - - `/Applications/League of Legends.app/Contents/LoL/RADS/projects/league_client/releases//deploy/system.yaml` - -Some regions may have a different directory structure but the general gist is the same. - -**This file will need to be updated everytime there's a new LCU version.** +Always up to date documentation for the League Client API. ### Prebuilt diff --git a/app.js b/app.js index d3601f9..5538846 100644 --- a/app.js +++ b/app.js @@ -1,45 +1,103 @@ const electron = require('electron'); const LCUConnector = require('lcu-connector'); +const fs = require('fs-extra'); +const path = require('path'); +const yaml = require('yaml'); +const { getLCUPathFromProcess } = require('./util'); -const connector = new LCUConnector(''); +const connector = new LCUConnector(); const { app } = electron; const { BrowserWindow } = electron; const root = __dirname + '/app'; -let mainWindow = null; - app.commandLine.appendSwitch('--ignore-certificate-errors'); app.on('ready', () => { + let mainWindow = null; + let windowLoaded = false; + let LCUData = null; + let swaggerDisabled = true; mainWindow = new BrowserWindow({ center: true, height: 720, show: false, - title: 'Rift Explorer', - width: 1280 + width: 1280, + title: 'Rift Explorer' }); + // Check if dev env FIXME + // mainWindow.openDevTools(); + // Remove default menu mainWindow.setMenu(null); mainWindow.loadURL('file://' + root + '/index.html'); - // Check if dev env FIXME - // mainWindow.openDevTools(); - // Avoid white page on load. mainWindow.webContents.on('did-finish-load', () => { - connector.on('connect', async (data) => { - mainWindow.webContents.send('lcu-load', data); - }); + windowLoaded = true; - connector.start(); mainWindow.show(); + + if (!LCUData) { + return; + } + + mainWindow.webContents.send(swaggerDisabled ? 'swagger-disabled' : 'swagger-enabled'); + mainWindow.webContents.send('lcu-load', LCUData); }); mainWindow.on('closed', () => { mainWindow = null; }); + + connector.on('connect', async (data) => { + // During multiple restarts of the client the backend server is not instantly + // ready to serve requests so we delay a bit + setTimeout(async () => { + LCUData = data; + + try { + const LCUPath = await getLCUPathFromProcess(); + const systemFile = path.join(LCUPath, 'system.yaml'); + + // File doesn't exist, do nothing + if (!(await fs.pathExists(systemFile))) { + throw new Error('system.yaml not found'); + } + + const file = await fs.readFile(systemFile, 'utf8'); + const fileParsed = yaml.parse(file); + + swaggerDisabled = !fileParsed.enable_swagger; + mainWindow.webContents.send(swaggerDisabled ? 'swagger-disabled' : 'swagger-enabled'); + + if (!fileParsed.enable_swagger) { + fileParsed.enable_swagger = true; + const stringifiedFile = yaml.stringify(fileParsed); + + // Rito's file is prefixed with --- newline + await fs.outputFile(systemFile, `---\n${stringifiedFile}`); + } + + } catch (error) { + console.error(error); + // No error handling for now + } + + mainWindow.webContents.send('lcu-load', LCUData); + }, 5000); + }); + + connector.on('disconnect', () => { + LCUData = null; + + if (windowLoaded) { + mainWindow.webContents.send('lcu-unload'); + } + }); + + connector.start(); }); app.on('window-all-closed', () => { diff --git a/app/css/style.css b/app/css/style.css index 81e5220..158876d 100644 --- a/app/css/style.css +++ b/app/css/style.css @@ -4,6 +4,14 @@ html { color: hsla(0, 0%, 0%, 0.87); } +.swagger-section .logo { + width: 54px; + height: 54px; + display: block; + float: left; + margin: -6px 12px 0 0; +} + .swagger-section .github { width: 24px; height: 24px; @@ -55,6 +63,10 @@ html { text-shadow: rgba(0, 0, 0, 0.15) 0 0 1px; } +.swagger-section .swagger-ui-wrap .info_title { + padding-bottom: 0; +} + @media (max-width: 960px) { .swagger-section #swagger-ui-container { margin: 24px auto; diff --git a/app/fonts/DroidSans-Bold.ttf b/app/fonts/DroidSans-Bold.ttf index 942bbf5..036c4d1 100644 Binary files a/app/fonts/DroidSans-Bold.ttf and b/app/fonts/DroidSans-Bold.ttf differ diff --git a/app/fonts/DroidSans.ttf b/app/fonts/DroidSans.ttf index efd1f8b..e517a0c 100644 Binary files a/app/fonts/DroidSans.ttf and b/app/fonts/DroidSans.ttf differ diff --git a/app/images/logo.png b/app/images/logo.png new file mode 100644 index 0000000..7563e8c Binary files /dev/null and b/app/images/logo.png differ diff --git a/app/index.html b/app/index.html index 3670372..81d4a4e 100644 --- a/app/index.html +++ b/app/index.html @@ -1,81 +1,137 @@ - - - - Rift Explorer - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + +
Waiting for League to start...
+
+ + - + function _handleGithubLink(event) { + shell.openExternal('https://github.com/pupix/rift-explorer'); + } - -
Waiting for League to start...
-
- + function _handleDiscordLink(event) { + shell.openExternal('https://discord.gg/hPtrMcx'); + } + + diff --git a/app/swagger-ui.js b/app/swagger-ui.js index 63cd916..41b787f 100644 --- a/app/swagger-ui.js +++ b/app/swagger-ui.js @@ -295,7 +295,7 @@ Handlebars.registerHelper('renderTextParam', function(param) { }); this["Handlebars"]["templates"]["main"] = Handlebars.template({"1":function(depth0,helpers,partials,data) { - var stack1, lambda=this.lambda, escapeExpression=this.escapeExpression, buffer = "
" + var stack1, lambda=this.lambda, escapeExpression=this.escapeExpression, buffer = "
" + escapeExpression(lambda(((stack1 = (depth0 != null ? depth0.info : depth0)) != null ? stack1.title : stack1), depth0)) + "
\n
"; stack1 = lambda(((stack1 = (depth0 != null ? depth0.info : depth0)) != null ? stack1.description : stack1), depth0); @@ -361,7 +361,7 @@ this["Handlebars"]["templates"]["main"] = Handlebars.template({"1":function(dept + "
"; },"14":function(depth0,helpers,partials,data) { var stack1, lambda=this.lambda, escapeExpression=this.escapeExpression; - return " , api version: " + return "version: " + escapeExpression(lambda(((stack1 = (depth0 != null ? depth0.info : depth0)) != null ? stack1.version : stack1), depth0)) + "\n "; },"16":function(depth0,helpers,partials,data) { @@ -379,9 +379,7 @@ this["Handlebars"]["templates"]["main"] = Handlebars.template({"1":function(dept var stack1, helper, functionType="function", helperMissing=helpers.helperMissing, escapeExpression=this.escapeExpression, buffer = "
\n"; stack1 = helpers['if'].call(depth0, (depth0 != null ? depth0.info : depth0), {"name":"if","hash":{},"fn":this.program(1, data),"inverse":this.noop,"data":data}); if (stack1 != null) { buffer += stack1; } - buffer += "
\n
\n
    \n\n
    \n

    [ base url: " - + escapeExpression(((helper = (helper = helpers.basePath || (depth0 != null ? depth0.basePath : depth0)) != null ? helper : helperMissing),(typeof helper === functionType ? helper.call(depth0, {"name":"basePath","hash":{},"data":data}) : helper))) - + "\n"; + buffer += "

    \n
    \n
      \n\n
      \n

      ["; stack1 = helpers['if'].call(depth0, ((stack1 = (depth0 != null ? depth0.info : depth0)) != null ? stack1.version : stack1), {"name":"if","hash":{},"fn":this.program(14, data),"inverse":this.noop,"data":data}); if (stack1 != null) { buffer += stack1; } buffer += "]\n"; @@ -1355,11 +1353,12 @@ SwaggerClient.prototype.buildFromSpec = function (response) { this.basePath = response.basePath || ''; this.consumes = response.consumes; this.host = response.host || ''; - this.info = response.info || {}; + this.info = RE.info; this.produces = response.produces; this.schemes = response.schemes || []; this.securityDefinitions = response.securityDefinitions; - this.title = response.title || ''; + this.title = RE.info.title; + this.version = RE.version; if (response.externalDocs) { this.externalDocs = response.externalDocs; diff --git a/assets/screenshot.png b/assets/screenshot.png index 7c160ad..e442146 100644 Binary files a/assets/screenshot.png and b/assets/screenshot.png differ diff --git a/assets/swagger.png b/assets/swagger.png deleted file mode 100644 index 9c9967a..0000000 Binary files a/assets/swagger.png and /dev/null differ diff --git a/package.json b/package.json index ccfe600..7ae83da 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "rift-explorer", - "version": "3.0.0", - "description": "Explore the API of the League of Legends client", + "version": "4.0.0", + "description": "Always up to date documentation for the League Client API", "main": "app.js", "scripts": { "start": "electron app", @@ -10,10 +10,12 @@ "author": "Robert Manolea ", "license": "MIT", "dependencies": { - "lcu-connector": "^1.0.0", + "fs-extra": "^7.0.1", + "lcu-connector": "^2.0.0", + "mixin-deep": "^2.0.0", "request": "^2.87.0", "request-promise": "^4.2.2", - "mixin-deep": "^2.0.0" + "yaml": "^1.2.1" }, "devDependencies": { "electron": "^1.7.11", diff --git a/util.js b/util.js new file mode 100644 index 0000000..a4a36de --- /dev/null +++ b/util.js @@ -0,0 +1,28 @@ +const cp = require('child_process'); +const path = require('path'); +const IS_WIN = process.platform === 'win32'; + +module.exports.getLCUPathFromProcess = () => { + return new Promise(resolve => { + const command = IS_WIN ? + `WMIC PROCESS WHERE name='LeagueClientUx.exe' GET ExecutablePath` : + `ps x -o comm= | grep 'LeagueClientUx'`; + + cp.exec(command, (err, stdout, stderr) => { + if (err || !stdout || stderr) { + resolve(); + return; + } + + let normalizedPath = path.normalize(stdout); + + // On MAC we need to go up a few levels to reach `deploy` + // This script also assumes that only Riot Games managed regions are provided + // Hasn't been tested on Garena + normalizedPath = IS_WIN ? normalizedPath.split(/\n|\n\r/)[1] : path.join(normalizedPath, '../../../'); + normalizedPath = path.dirname(normalizedPath); + + resolve(normalizedPath); + }); + }); +}; \ No newline at end of file diff --git a/yarn.lock b/yarn.lock index 4383512..a854a27 100644 --- a/yarn.lock +++ b/yarn.lock @@ -792,6 +792,15 @@ fs-extra@^5.0.0: jsonfile "^4.0.0" universalify "^0.1.0" +fs-extra@^7.0.1: + version "7.0.1" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-7.0.1.tgz#4f189c44aa123b895f722804f55ea23eadc348e9" + integrity sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw== + dependencies: + graceful-fs "^4.1.2" + jsonfile "^4.0.0" + universalify "^0.1.0" + fs.realpath@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" @@ -1263,9 +1272,10 @@ lcid@^1.0.0: dependencies: invert-kv "^1.0.0" -lcu-connector@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/lcu-connector/-/lcu-connector-1.0.1.tgz#42c053b34283bd0594d369c7340f4b8d0ff927b5" +lcu-connector@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/lcu-connector/-/lcu-connector-2.0.0.tgz#f78414cb479a86621154e70d323042418a3376b7" + integrity sha512-PbSeic0vbzOKau47mMm3TyM1YWaO3Njmc7GAXpGqGoRxrxPjab4CMKR7XPEm6zpZf18BOXxwo0fOXbJi5lGz3A== dependencies: chokidar "1.7.0" fs-extra "4.0.3" @@ -2347,6 +2357,11 @@ yallist@^2.1.2: version "2.1.2" resolved "https://registry.yarnpkg.com/yallist/-/yallist-2.1.2.tgz#1c11f9218f076089a47dd512f93c6699a6a81d52" +yaml@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/yaml/-/yaml-1.2.1.tgz#7057ee224c96e7dcd591a83a871ad89d3df1c6ed" + integrity sha512-LuOeoZc6LYguU9H/XCbrPfuDpCGJVf+o/r9uLCGnsHiHk/8Cr7IVeXOilO8yK0XA8QJPlX22KVofINt8xhdwqg== + yargs-parser@^8.1.0: version "8.1.0" resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-8.1.0.tgz#f1376a33b6629a5d063782944da732631e966950"