diff --git a/server/package-lock.json b/server/package-lock.json index dadc9d8..1453c80 100644 --- a/server/package-lock.json +++ b/server/package-lock.json @@ -936,9 +936,9 @@ } }, "ajv": { - "version": "6.6.1", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.6.1.tgz", - "integrity": "sha512-ZoJjft5B+EJBjUyu9C9Hc0OZyPZSSlOF+plzouTrg6UlA8f+e/n8NIgBFG/9tppJtpPWfthHakK7juJdNDODww==", + "version": "6.10.2", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.2.tgz", + "integrity": "sha512-TXtUUEYHuaTEbLZWIKUr5pmBuhDLy+8KYtPYdcV8qC+pOZL+NKqYwvWSRrVXHn+ZmRRAu8vJTAznH7Oag6RVRw==", "requires": { "fast-deep-equal": "^2.0.1", "fast-json-stable-stringify": "^2.0.0", @@ -1375,9 +1375,9 @@ "dev": true }, "combined-stream": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.7.tgz", - "integrity": "sha512-brWl9y6vOB1xYPZcpZde3N9zDByXTosAeMDo4p1wzo6UMOX4vumB+TP1RZ76sfE6Md68Q0NJSrE/gbezd4Ul+w==", + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", "requires": { "delayed-stream": "~1.0.0" } @@ -1406,11 +1406,6 @@ "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", "dev": true }, - "connect-history-api-fallback": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/connect-history-api-fallback/-/connect-history-api-fallback-1.6.0.tgz", - "integrity": "sha512-e54B99q/OUoH64zYYRf3HBP5z24G38h5D3qXu23JGRoigpX5Ss4r9ZnDk3g0Z8uQC2x2lPaJ+UlWBc1ZWBWdLg==" - }, "content-disposition": { "version": "0.5.3", "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz", @@ -2042,12 +2037,14 @@ "balanced-match": { "version": "1.0.0", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "brace-expansion": { "version": "1.1.11", "bundled": true, "dev": true, + "optional": true, "requires": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -2062,17 +2059,20 @@ "code-point-at": { "version": "1.1.0", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "concat-map": { "version": "0.0.1", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "console-control-strings": { "version": "1.1.0", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "core-util-is": { "version": "1.0.2", @@ -2189,7 +2189,8 @@ "inherits": { "version": "2.0.3", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "ini": { "version": "1.3.5", @@ -2201,6 +2202,7 @@ "version": "1.0.0", "bundled": true, "dev": true, + "optional": true, "requires": { "number-is-nan": "^1.0.0" } @@ -2215,6 +2217,7 @@ "version": "3.0.4", "bundled": true, "dev": true, + "optional": true, "requires": { "brace-expansion": "^1.1.7" } @@ -2222,12 +2225,14 @@ "minimist": { "version": "0.0.8", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "minipass": { "version": "2.3.5", "bundled": true, "dev": true, + "optional": true, "requires": { "safe-buffer": "^5.1.2", "yallist": "^3.0.0" @@ -2246,6 +2251,7 @@ "version": "0.5.1", "bundled": true, "dev": true, + "optional": true, "requires": { "minimist": "0.0.8" } @@ -2326,7 +2332,8 @@ "number-is-nan": { "version": "1.0.1", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "object-assign": { "version": "4.1.1", @@ -2338,6 +2345,7 @@ "version": "1.4.0", "bundled": true, "dev": true, + "optional": true, "requires": { "wrappy": "1" } @@ -2459,6 +2467,7 @@ "version": "1.0.2", "bundled": true, "dev": true, + "optional": true, "requires": { "code-point-at": "^1.0.0", "is-fullwidth-code-point": "^1.0.0", @@ -3161,16 +3170,16 @@ "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==" }, "mime-db": { - "version": "1.37.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.37.0.tgz", - "integrity": "sha512-R3C4db6bgQhlIhPU48fUtdVmKnflq+hRdad7IyKhtFj06VPNVdk2RhiYL3UjQIlso8L+YxAtFkobT0VK+S/ybg==" + "version": "1.40.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.40.0.tgz", + "integrity": "sha512-jYdeOMPy9vnxEqFRRo6ZvTZ8d9oPb+k18PKoYNYUe2stVEBPPwsln/qWzdbmaIvnhZ9v2P+CuecK+fpUfsV2mA==" }, "mime-types": { - "version": "2.1.21", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.21.tgz", - "integrity": "sha512-3iL6DbwpyLzjR3xHSFNFeb9Nz/M8WDkX33t1GFQnFOllWk8pOrh/LSrB5OXlnlW5P9LH73X6loW/eogc+F5lJg==", + "version": "2.1.24", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.24.tgz", + "integrity": "sha512-WaFHS3MCl5fapm3oLxU4eYDw77IQM2ACcxQ9RIxfaC3ooc6PFuBMGZZsYpvoXS5D5QTWPieo1jjLdAm3TBP3cQ==", "requires": { - "mime-db": "~1.37.0" + "mime-db": "1.40.0" } }, "mimic-response": { @@ -4229,9 +4238,9 @@ } }, "sshpk": { - "version": "1.15.2", - "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.15.2.tgz", - "integrity": "sha512-Ra/OXQtuh0/enyl4ETZAfTaeksa6BXks5ZcjpSUNrjBr0DvrJKX+1fsKDPpT9TBXgHAFsa4510aNVgI8g/+SzA==", + "version": "1.16.1", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz", + "integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==", "requires": { "asn1": "~0.2.3", "assert-plus": "^1.0.0", @@ -4549,9 +4558,9 @@ "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=" }, "uuid": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz", - "integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==" + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.3.tgz", + "integrity": "sha512-pW0No1RGHgzlpHJO1nsVrHKpOEIxkGg1xB+v0ZmdNH5OAeAwzAVrCnI2/6Mtx+Uys6iaylxa+D3g4j63IKKjSQ==" }, "v8flags": { "version": "3.1.3", diff --git a/server/package.json b/server/package.json index 069ee12..1c219d7 100644 --- a/server/package.json +++ b/server/package.json @@ -12,15 +12,12 @@ "license": "ISC", "dependencies": { "@babel/runtime": "^7.5.5", - "bluebird": "^3.5.5", "body-parser": "^1.19.0", - "connect-history-api-fallback": "^1.6.0", "cors": "^2.8.5", "dotenv": "^7.0.0", "express": "^4.17.1", "got": "^9.6.0", "request": "^2.88.0", - "request-promise": "^4.2.4", "response-time": "^2.3.2", "riot-ratelimiter": "^0.1.5" }, diff --git a/server/src/Jax/Endpoints/LeagueEndpoint.js b/server/src/Jax/Endpoints/LeagueEndpoint.js new file mode 100644 index 0000000..769014d --- /dev/null +++ b/server/src/Jax/Endpoints/LeagueEndpoint.js @@ -0,0 +1,18 @@ +import JaxRequest from '../JaxRequest' + +class LeagueEndpoint { + constructor(limiter, region) { + this.limiter = limiter + this.region = region + } + + summonerID(summonerID) { + return new JaxRequest( + `league/v4/entries/by-summoner/${summonerID}`, + this.limiter, + this.region + ).execute() + } +} + +export default LeagueEndpoint diff --git a/server/src/Jax/Endpoints/MatchEndpoint.js b/server/src/Jax/Endpoints/MatchEndpoint.js new file mode 100644 index 0000000..e850960 --- /dev/null +++ b/server/src/Jax/Endpoints/MatchEndpoint.js @@ -0,0 +1,20 @@ +import JaxRequest from '../JaxRequest' + +class MatchEndpoint { + constructor(limiter, region) { + this.limiter = limiter + this.region = region + + this.get = this.get.bind(this) + } + + get(matchID) { + return new JaxRequest( + `match/v4/matches/${matchID}`, + this.limiter, + this.region + ).execute() + } +} + +export default MatchEndpoint diff --git a/server/src/Jax/Endpoints/MatchlistEndpoint.js b/server/src/Jax/Endpoints/MatchlistEndpoint.js new file mode 100644 index 0000000..4c2afda --- /dev/null +++ b/server/src/Jax/Endpoints/MatchlistEndpoint.js @@ -0,0 +1,18 @@ +import JaxRequest from '../JaxRequest' + +class MatchlistEndpoint { + constructor(limiter, region) { + this.limiter = limiter + this.region = region + } + + accountID(accountID, beginIndex = 0) { + return new JaxRequest( + `match/v4/matchlists/by-account/${accountID}?beginIndex=${beginIndex}`, + this.limiter, + this.region + ).execute() + } +} + +export default MatchlistEndpoint diff --git a/server/src/Jax/Jax.js b/server/src/Jax/Jax.js index 6a05469..fd16c0f 100644 --- a/server/src/Jax/Jax.js +++ b/server/src/Jax/Jax.js @@ -1,5 +1,10 @@ import RiotRateLimiter from 'riot-ratelimiter' +import { STRATEGY } from 'riot-ratelimiter/dist/RateLimiter' + +import LeagueEndpoint from './Endpoints/LeagueEndpoint' +import MatchEndpoint from './Endpoints/MatchEndpoint' +import MatchlistEndpoint from './Endpoints/MatchlistEndpoint' import SummonerEndpoint from './Endpoints/SummonerEndpoint' import DDragonVersionEndpoint from './Endpoints/DDragonEndpoints/DDragonVersionEndpoint' @@ -9,9 +14,15 @@ class Jax { constructor(key = process.env.API_KEY, region = 'euw1') { return (async () => { this.key = key - this.limiter = new RiotRateLimiter() + const limiterOptions = { + strategy: STRATEGY.BURST + } + this.limiter = new RiotRateLimiter(limiterOptions) this.region = region + this.League = new LeagueEndpoint(this.limiter, this.region) + this.Match = new MatchEndpoint(this.limiter, this.region) + this.Matchlist = new MatchlistEndpoint(this.limiter, this.region) this.Summoner = new SummonerEndpoint(this.limiter, this.region) this.version = (await new DDragonVersionEndpoint().list())[0] diff --git a/server/src/server.js b/server/src/server.js index 71a2bde..848eaa8 100644 --- a/server/src/server.js +++ b/server/src/server.js @@ -1,24 +1,10 @@ require('dotenv').config({ path: __dirname + '/./../.env' }) const express = require('express') -const request = require('request'); -const bodyParser = require('body-parser'); -const rp = require('request-promise'); -const Promise = require("bluebird"); +const bodyParser = require('body-parser') const responseTime = require('response-time') -const cors = require('cors'); +const cors = require('cors') const app = express() -import { Jax } from "./Jax"; - -/* Global Variables */ -const data = { - key: process.env.API_KEY, - region: 'euw1', - summonerID: '', - accountID: '', - username: '', - JSONMatches: [], - finalJSON: {} -} +import { Jax } from "./Jax" /* Set Port */ app.set('port', (process.env.PORT || 5000)) @@ -30,16 +16,16 @@ app.use(cors({ 'https://leaguestats-gg.netlify.com', 'https://leaguestats.valentinkaelin.ch/' ] -})); +})) /* To retrieve data of post request */ -app.use(bodyParser.json()); // to support JSON-encoded bodies +app.use(bodyParser.json()) // to support JSON-encoded bodies app.use(bodyParser.urlencoded({ // to support URL-encoded bodies extended: true -})); +})) // Create a middleware that adds a X-Response-Time header to responses -app.use(responseTime()); +app.use(responseTime()) // Setup Jax let jax @@ -51,19 +37,39 @@ app.listen(app.get('port'), async () => { }) // Send data of a summoner -app.post('/api', function (req, res) { - console.log('API Request'); - console.log(req.body.summoner); - console.log(req.body.region); +app.post('/api', async function (req, res) { + console.log('API Request') + console.log(req.body.summoner, req.body.region) console.time('all') - data.region = req.body.region; - data.username = req.body.summoner; - data.finalJSON = {}; - // getAccountInfos(res); - jax.regionName = data.region - getAccountInfosNew(res) -}); + const finalJSON = {} + jax.regionName = req.body.region + + try { + const account = await jax.Summoner.summonerName(req.body.summoner) + finalJSON.account = account + + const ranked = await jax.League.summonerID(account.id) + const soloQ = ranked.filter(e => e.queueType === 'RANKED_SOLO_5x5') + finalJSON.soloQ = soloQ.length ? soloQ[0] : null; + + console.time('getMatches') + const { matches } = await jax.Matchlist.accountID(account.accountId) + const gameIds = matches.slice(0, 10).map(({ gameId }) => gameId) + const requests = gameIds.map(jax.Match.get) + const results = await Promise.all(requests) + finalJSON.matchesDetails = results + finalJSON.allMatches = matches + + res.send(finalJSON) + console.timeEnd('getMatches') + console.timeEnd('all') + } catch (error) { + console.log('username not found') + console.log(error) + res.send(null) + } +}) /* Get static file from Riot API */ app.post('/ddragon', async function (req, res) { @@ -72,87 +78,3 @@ app.post('/ddragon', async function (req, res) { const result = await jax.DDragon[endpoint].list() res.send(result) }) - -/* Get account infos of an username - Refactor with the Jax Wrapper */ -async function getAccountInfosNew(res) { - try { - const account = await jax.Summoner.summonerName(data.username) - data.summonerID = account.id - data.accountID = account.accountId - data.finalJSON.account = account - getRanked(res) - } catch (error) { - console.log('username not found') - console.log(error) - res.send(null) - } -} - -// Get account infos of an username - Old version -const getAccountInfos = function (res) { - request(`https://${data.region}.api.riotgames.com/lol/summoner/v4/summoners/by-name/${encodeURIComponent(data.username)}?api_key=${data.key}`, function (error, response, body) { - if (!error && response.statusCode == 200) { - let JSONBody = JSON.parse(body); - data.summonerID = JSONBody.id; - data.accountID = JSONBody.accountId; - data.finalJSON.account = JSONBody - getRanked(res); - } - else { - console.log(response.statusCode); - console.log('username not found'); - res.send(null); - } - }); -} - -// Get data of rankeds stats -const getRanked = function (res) { - request(`https://${data.region}.api.riotgames.com/lol/league/v4/entries/by-summoner/${data.summonerID}?api_key=${data.key}`, function (error, response, body) { - if (!error && response.statusCode == 200) { - const JSONBody = JSON.parse(body).filter(e => e.queueType === 'RANKED_SOLO_5x5'); - if (JSONBody.length === 1) { - data.finalJSON.soloQ = JSONBody[0]; - } else { - console.log('empty rank stats'); - data.finalJSON.soloQ = null; - } - getMatches(res); - } - }) -} - -// Get 100 matches basic infos and 10 matches details of an accountID -const getMatches = function (res) { - console.time('getMatches'); - - request(`https://${data.region}.api.riotgames.com/lol/match/v4/matchlists/by-account/${data.accountID}?endIndex=100&api_key=${data.key}`, function (error, response, body) { - if (!error && response.statusCode == 200) { - const allMatches = JSON.parse(body) - data.JSONMatches = allMatches.matches.slice(0, 10) - const matchsId = data.JSONMatches.map(x => x.gameId) - - Promise.map(matchsId, function (id) { - return getMatch('match/v4/matches/' + id); - }).then(() => { - console.timeEnd('getMatches'); - console.log('Finished - Data sent to front'); - data.finalJSON.matchesDetails = data.JSONMatches - data.finalJSON.allMatches = allMatches.matches - res.send(data.finalJSON); - console.timeEnd('all') - }).catch(err => { - console.log('Error Promise'); - console.log(err); - }); - } - }); -} - -// Get data of one match -const getMatch = async function (urlApi) { - //console.log(urlApi); - return rp({ url: `https://${data.region}.api.riotgames.com/lol/${urlApi}?api_key=${data.key}`, json: true }).then(function (obj) { - data.JSONMatches = data.JSONMatches.map((match) => match.gameId === obj.gameId ? obj : match); - }); -}