diff --git a/package.json b/package.json index c276fb0..d3c0a35 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "Lytical", "author": "downthecrop", "description": "Lytical is an open source League of Legends statistics and profile analytics tool for all regions including Garena and WeGame", - "version": "1.2.7", + "version": "1.2.8", "repository": "https://github.com/LyticalApp/Lytical/", "private": true, "scripts": { diff --git a/public/all.css b/public/all.css index f5939a0..13bd727 100644 --- a/public/all.css +++ b/public/all.css @@ -11,7 +11,7 @@ --lobby-victory-background: rgba(92, 215, 228, 0.5); --lobby-defeat-background: rgb(186, 75, 69, 0.5); --minicard-text: #9a96a4; - --minicard-background: #020202; + --minicard-background: #060606; --minicard-since-background: #5d4e73; --error-background: #e84057; --role-icon-size: 12px; diff --git a/src/background.js b/src/background.js index 49f8963..0641888 100644 --- a/src/background.js +++ b/src/background.js @@ -24,6 +24,10 @@ protocol.registerSchemesAsPrivileged([ let win; const puuidStore = {}; +const asyncReply = 'asynchronous-reply'; + +const MATCH_HISTORY_V1 = '/lol-match-history/v1/products/lol/'; +const RANKED_STATS_V1 = '/lol-ranked/v1/ranked-stats/'; async function createWindow() { // Create the browser window. @@ -32,10 +36,6 @@ async function createWindow() { width: 1200, height: 650, webPreferences: { - // Use pluginOptions.nodeIntegration, leave this alone - // eslint-disable-next-line max-len - // See nklayman.github.io/vue-cli-plugin-electron-builder/guide/security.html#node-integration - // for more info nodeIntegration: true, contextIsolation: false, }, @@ -78,7 +78,7 @@ app.on('activate', () => { // This method will be called when Electron has finished // initialization and is ready to create browser windows. -// Some APIs can only be used after this event occurs. +// Some APIs can only be used after this e occurs. app.on('ready', async () => { if (isDevelopment && !process.env.IS_TEST) { // Install Vue Devtools @@ -127,30 +127,8 @@ function createReply(dataD, id) { reply.reply_type = id; return reply; } -/** -const WebSocket = require('ws'); -function connectToWebsocket() { - // Connect to websocket - process.env.NODE_TLS_REJECT_UNAUTHORIZED = 0; - lcu.getLCUAuth().then((auth) => { - const ws = new WebSocket(`wss://riot:${auth.password}@127.0.0.1:${auth.port}/`, 'wamp'); - ws.on('open', () => { - // Subsribe to [Ingame, Lobby, Matchmaking] events - ws.send('[5, "OnJsonApiEvent_lol-gameflow_v1_session"]'); - }); - ws.on('error', (err) => { - console.log(err); - }); - - ws.on('message', (msg) => { - console.log(JSON.parse(msg)); - }); - }); -} -*/ - -function errorHandler(errorCode, event) { +function errorHandler(errorCode, e, req) { console.log('ERRORCODE: ', errorCode); switch (String(errorCode)) { case '400': @@ -158,23 +136,27 @@ function errorHandler(errorCode, event) { // GOOD REQUEST. BAD RESPONSE // e.g. checking lobby status when // no lobby exists. Just do nothing.. - event.reply('asynchronous-reply', { reply_type: 'lcu-reconnected' }); + e.reply(asyncReply, { reply_type: 'lcu-reconnected' }); break; } - case '403': case 'ECONNREFUSED': + case '403': case '0': default: { + if (req.id === 'liveclientdata-playerlist') { + // Allow polling for live game can refuse connection + break; + } // Unhadled Error.. lcu.setAuth(null); - event.reply('asynchronous-reply', { reply_type: 'lcu-disonnceted' }); + e.reply(asyncReply, { reply_type: 'lcu-disonnceted' }); break; } } } // Used to get PUUID for many differet requests. -function getSummonerByName(name, auth) { +async function getSummonerByName(name, auth) { const summonerName = encodeURI(name.replace(/\s/g, '')); if (puuidStore[name]) { return new Promise((resolve) => { @@ -192,7 +174,7 @@ function getSummonerByName(name, auth) { }); } -function getSummonerById(id, auth) { +async function getSummonerById(id, auth) { if (puuidStore[id]) { return new Promise((resolve) => { resolve(puuidStore[id]); @@ -209,7 +191,15 @@ function getSummonerById(id, auth) { }); } -function getSummonerCurrent(auth) { +const clearProfile = (e) => { + e.reply(asyncReply, createReply({}, 'clear-profile')); +}; + +const reqURL = async (auth, url) => JSON.parse( + await request.requestURL(auth, url), +); + +async function getSummonerCurrent(auth) { if (puuidStore['summoner.current']) { return new Promise((resolve) => { resolve(puuidStore['summoner.current']); @@ -226,247 +216,164 @@ function getSummonerCurrent(auth) { }); } -ipcMain.on('asynchronous-message', (event, req) => { +ipcMain.on('asynchronous-message', (e, req) => { console.log('NEW REQUEST: ', req); // ipc required requests for debug/versioning - if (req.id === 'openDevTools') { - win.webContents.openDevTools(); - return; - } - if (req.id === 'getVersion') { - event.reply('asynchronous-reply', { reply_type: 'appVersion', version: app.getVersion() }); - return; - } - if (req.id === 'scaleUp') { - win.webContents.setZoomFactor(win.webContents.getZoomFactor() + 0.1); - return; - } - if (req.id === 'scaleDown') { - win.webContents.setZoomFactor(win.webContents.getZoomFactor() - 0.1); - return; - } - if (req.id === 'getRunLevel') { - event.reply('asynchronous-reply', { reply_type: 'runLevel', isAdmin: lcu.getRunLevel() }); - return; + switch (req.id) { + case 'openDevTools': { + win.webContents.openDevTools(); + return; + } + case 'getVersion': { + e.reply(asyncReply, { reply_type: 'appVersion', version: app.getVersion() }); + return; + } + case 'scaleUp': { + win.webContents.setZoomFactor(win.webContents.getZoomFactor() + 0.1); + return; + } + case 'scaleDown': { + win.webContents.setZoomFactor(win.webContents.getZoomFactor() - 0.1); + return; + } + case 'getRunLevel': { + e.reply(asyncReply, { reply_type: 'runLevel', isAdmin: lcu.getRunLevel() }); + return; + } + default: { + break; + } } // LCU related Requests - lcu.getLCUAuth().then((auth) => { - switch (req.id) { - case 'liveclientdata-playerlist': { - const url = '/liveclientdata/playerlist'; - const config = { - protocol: 'https', - port: 2999, - }; - request.requestURL(config, url).then((data) => { - event.reply( - 'asynchronous-reply', - createReply(data, req.id), + // eslint-disable-next-line func-names + lcu.getLCUAuth().then(async (auth) => { + try { + switch (req.id) { + case 'liveclientdata-playerlist': { + const config = { + protocol: 'https', + port: 2999, + }; + e.reply( + asyncReply, + createReply(await request.requestURL(config, '/liveclientdata/playerlist'), req.id), ); - }).catch((error) => { - if (String(error) !== 'ECONNREFUSED') { - console.log(error); - } - }); - break; - } - case 'lol-lobby-playercard': { - let rankedData = null; - getSummonerById(req.summonerId, auth) - .then((summoner) => { - request.requestURL( - auth, - `/lol-ranked/v1/ranked-stats/${summoner.puuid}`, - ).then((rankedD) => { - rankedData = JSON.parse(rankedD); - rankedData.username = summoner.displayName; - request.requestURL( - auth, - `/lol-match-history/v1/products/lol/${summoner.puuid}/matches?begIndex=0&endIndex=9`, - ).then( - (matchHistory) => { - rankedData.teamId = req.teamId; - rankedData.position = req.pos.toUpperCase(); - rankedData.matchHistory = JSON.parse(matchHistory); - event.reply( - 'asynchronous-reply', - createReply(rankedData, req.id), - ); - }, - ); - }); - }).catch((error) => errorHandler(error, event)); - break; - } - case 'lol-match-playercard': { - let rankedData = null; - getSummonerByName(req.summonerName, auth) - .then((summoner) => { - request.requestURL( - auth, - `/lol-ranked/v1/ranked-stats/${summoner.puuid}`, - ).then((rankedD) => { - rankedData = JSON.parse(rankedD); - rankedData.username = summoner.displayName; - request.requestURL( - auth, - `/lol-match-history/v1/products/lol/${summoner.puuid}/matches?begIndex=0&endIndex=9`, - ).then( - (matchHistory) => { - rankedData.teamId = req.teamId; - rankedData.championId = req.championId; - rankedData.position = req.position.toUpperCase(); - rankedData.matchHistory = JSON.parse(matchHistory); - event.reply( - 'asynchronous-reply', - createReply(rankedData, req.id), - ); - }, - ); - }); - }).catch((error) => errorHandler(error, event)); - break; - } - case 'lol-champ-select': { - request.requestURL( - auth, - '/lol-champ-select/v1/session', - ).then((data) => { - event.reply('asynchronous-reply', createReply(data, req.id)); - }).catch((error) => errorHandler(error, event)); - break; - } - case 'lol-match-history-current': { - request.requestURL( - auth, - // eslint-disable-next-line max-len - `/lol-match-history/v1/products/lol/current-summoner/matches?begIndex=${req.begIndex}&endIndex=${req.endIndex}`, - ).then((data) => { - event.reply('asynchronous-reply', createReply(data, req.id)); - }).catch((error) => errorHandler(error, event)); - break; - } - case 'lol-match-history': { - getSummonerByName(req.user, auth) - .then((summoner) => { - request.requestURL( - auth, - // eslint-disable-next-line max-len - `/lol-match-history/v1/products/lol/${summoner.puuid}/matches?begIndex=${req.begIndex}&endIndex=${req.endIndex}`, - ).then( - (matchHistory) => { - event.reply( - 'asynchronous-reply', - createReply(matchHistory, req.id), - ); - }, - ); - }).catch((error) => errorHandler(error, event)); - break; - } - case 'lol-match-details': { - request.requestURL( - auth, - `/lol-match-history/v1/games/${req.gameId}`, - ).then((data) => { - event.reply('asynchronous-reply', createReply(data, req.id)); - }).catch((error) => errorHandler(error, event)); - break; - } - case 'lol-ranked-stats-current': { - event.reply('asynchronous-reply', createReply({}, 'clear-profile')); - getSummonerCurrent(auth).then((summoner) => { - request.requestURL( + break; + } + case 'lol-lobby-playercard': { + const summoner = await getSummonerById(req.summonerId, auth); + const response = await reqURL(auth, `${RANKED_STATS_V1}${summoner.puuid}`); + response.matchHistory = await reqURL( auth, - '/lol-ranked/v1/current-ranked-stats', - ).then((rankedD) => { - const rankData = JSON.parse(rankedD); - rankData.summonerData = summoner; - rankData.username = summoner.displayName; - event.reply('asynchronous-reply', createReply(rankData, req.id)); - }); - }).catch((error) => errorHandler(error, event)); - break; - } - case 'lol-ranked-stats': { - event.reply('asynchronous-reply', createReply({}, 'clear-profile')); - getSummonerByName(req.user, auth) - .then((summoner) => { - request.requestURL( - auth, - `/lol-ranked/v1/ranked-stats/${summoner.puuid}`, - ).then( - (rankedD) => { - const rankData = JSON.parse(rankedD); - rankData.summonerData = summoner; - rankData.username = summoner.displayName; - event.reply('asynchronous-reply', createReply(rankData, req.id)); - }, - ); - }).catch((error) => errorHandler(error, event)); - break; - } - case 'lol-ranked-stats-match-details': { - getSummonerByName(req.user, auth) - .then((summoner) => { - request.requestURL( - auth, - `/lol-ranked/v1/ranked-stats/${summoner.puuid}`, - ).then( - (rankedD) => { - const rankData = JSON.parse(rankedD); - rankData.summonerData = summoner; - rankData.username = summoner.displayName; - rankData.index = req.index; - rankData.gameId = req.gameId; - event.reply('asynchronous-reply', createReply(rankData, req.id)); - }, - ); - }).catch((error) => errorHandler(error, event)); - break; - } - case 'lol-full-ranked-history-current': { - getSummonerCurrent(auth) - .then((summoner) => { - request.requestURL( + `${MATCH_HISTORY_V1}${summoner.puuid}/matches?begIndex=0&endIndex=9`, + ); + response.username = summoner.displayName; + response.teamId = req.teamId; + response.position = req.pos.toUpperCase(); + e.reply(asyncReply, createReply(response, req.id)); + break; + } + case 'lol-match-playercard': { + const summoner = await getSummonerByName(req.summonerName, auth); + const response = await reqURL(auth, `${RANKED_STATS_V1}${summoner.puuid}`); + + response.matchHistory = await reqURL( + auth, + `${MATCH_HISTORY_V1}${summoner.puuid}/matches?begIndex=0&endIndex=9`, + ); + + response.username = summoner.displayName; + response.teamId = req.teamId; + response.championId = req.championId; + response.position = req.position.toUpperCase(); + e.reply(asyncReply, createReply(response, req.id)); + break; + } + case 'lol-champ-select': { + e.reply(asyncReply, createReply(await reqURL(auth, '/lol-champ-select/v1/session'), req.id)); + break; + } + case 'lol-match-history-current': { + e.reply( + asyncReply, + createReply(await reqURL( auth, - // This is capped at 200 Games internally. If the player refreshes late into the season we - // Could iterate backwards with an older start index but I don't really care.. - // Timing: Takes 2345.318800000474ms - `/lol-match-history/v1/products/lol/${summoner.puuid}/matches?begIndex=0&endIndex=200`, - ).then( - (matchHistory) => { - event.reply( - 'asynchronous-reply', - createReply(matchHistory, req.id), - ); - }, - ); - }).catch((error) => errorHandler(error, event)); - break; - } - case 'lol-full-ranked-history': { - getSummonerByName(req.user, auth) - .then((summoner) => { - request.requestURL( + `${MATCH_HISTORY_V1}current-summoner/matches?begIndex=${req.begIndex}&endIndex=${req.endIndex}`, + ), req.id), + ); + break; + } + case 'lol-match-history': { + const summoner = await getSummonerByName(req.user, auth); + e.reply( + asyncReply, + createReply(await reqURL( auth, - `/lol-match-history/v1/products/lol/${summoner.puuid}/matches?begIndex=0&endIndex=200`, - ).then( - (matchHistory) => { - event.reply( - 'asynchronous-reply', - createReply(matchHistory, req.id), - ); - }, - ); - }).catch((error) => errorHandler(error, event)); - break; - } - default: { - event.reply('asynchronous-reply', createReply(null, req.id)); + `${MATCH_HISTORY_V1}${summoner.puuid}/matches?begIndex=${req.begIndex}&endIndex=${req.endIndex}`, + ), req.id), + ); + break; + } + case 'lol-match-details': { + e.reply(asyncReply, createReply(await reqURL(auth, `/lol-match-history/v1/games/${req.gameId}`), req.id)); + break; + } + case 'lol-ranked-stats-current': { + clearProfile(e); + const summoner = await getSummonerCurrent(auth); + const response = await reqURL(auth, '/lol-ranked/v1/current-ranked-stats'); + response.summonerData = summoner; + response.username = summoner.displayName; + e.reply(asyncReply, createReply(response, req.id)); + break; + } + case 'lol-ranked-stats': { + const summoner = await getSummonerByName(req.user, auth); + const response = await reqURL(auth, `${RANKED_STATS_V1}${summoner.puuid}`); + response.summonerData = summoner; + response.username = summoner.displayName; + e.reply(asyncReply, createReply(response, req.id)); + break; + } + case 'lol-ranked-stats-match-details': { + const summoner = await getSummonerByName(req.user, auth); + const response = await reqURL(auth, `${RANKED_STATS_V1}${summoner.puuid}`); + response.summonerData = summoner; + response.username = summoner.displayName; + response.index = req.index; + response.gameId = req.gameId; + e.reply(asyncReply, createReply(response, req.id)); + break; + } + case 'lol-full-ranked-history-current': { + const summoner = await getSummonerCurrent(auth); + const matchHistory = await reqURL( + auth, + `${MATCH_HISTORY_V1}${summoner.puuid}/matches?begIndex=0&endIndex=200`, + ); + e.reply(asyncReply, createReply(matchHistory, req.id)); + break; + } + case 'lol-full-ranked-history': { + const summoner = await getSummonerByName(req.user, auth); + const matchHistory = await request.requestURL( + auth, + `${MATCH_HISTORY_V1}${summoner.puuid}/matches?begIndex=0&endIndex=200`, + ); + e.reply( + asyncReply, + createReply(matchHistory, req.id), + ); + break; + } + default: { + e.reply(asyncReply, createReply(null, req.id)); + } } + } catch (error) { + errorHandler(error, e, req); } }); }); diff --git a/src/res/request.js b/src/res/request.js index da8209a..a454ede 100644 --- a/src/res/request.js +++ b/src/res/request.js @@ -4,8 +4,7 @@ const badStatusCodes = [400, 403, 404]; exports.requestURL = async (auth, path, postData = null) => new Promise((resolve, reject) => { if (auth == null) { - // eslint-disable-next-line prefer-promise-reject-errors - reject('0'); + reject(new Error('NULLAUTH')); } const options = {