-const express = require("express")
const fs = require("fs")
const request = require("request-promise-native")
+const sleep = require("util").promisify(setTimeout)
+const low = require("lowdb")
+const FileAsync = require("lowdb/adapters/FileAsync")
+
+const express = require("express")
const app = express()
const port = 3000
-const sleep = require('util').promisify(setTimeout)
const patch = "8.24.1";
-const key = "RGAPI-c6cae96a-c4b0-4842-9017-ddd736f3f628";
+const key = "RGAPI-dce1850a-0954-4b1e-8072-77a26739f076";
+
let appRateLimit1;
let appRateLimit120;
let appRateLimitCount1;
let appRateLimitCount120;
+// Express routing
+// ---------------
let rules = [
["/lol", "index.html"],
["/lol/script.js", "script.js"],
res.sendFile(__dirname + "/html/" + file);
});
}
+// ---------------
+// Riot API request
+// ----------------
const regions = {
"BR": "br1.api.riotgames.com",
"EUNE": "eun1.api.riotgames.com",
"TR": "tr1.api.riotgames.com",
"RU": "ru.api.riotgames.com",
"PBE": "pbe1.api.riotgames.com",
-};
+};
async function riotRequest(region, url, params, retries) {
if (retries < 1) throw "Error too many tries";
+
let req = "https://" + regions[region] + url + "?api_key=" + key;
for (p in params) {
req += "&" + p + "=" + params[p];
}
+
try {
+ console.log("[Info] request: " + req);
let result = await request({uri: req, resolveWithFullResponse: true, json: true});
+
let appRateLimit = result.headers["x-app-rate-limit"];
let appRateLimitCount = result.headers["x-app-rate-limit-count"];
appRateLimit1 = appRateLimit.split(",")[0].split(":")[0];
appRateLimit120 = appRateLimit.split(",")[1].split(":")[0];
appRateLimitCount1 = appRateLimitCount.split(",")[0].split(":")[0];
appRateLimitCount120 = appRateLimitCount.split(",")[1].split(":")[0];
+
let delay1 = 1000 / (appRateLimit1 - 1);
let delay120 = 120000 / (appRateLimit120 - 1);
await sleep(Math.max(delay1, delay120));
- console.log(Math.max(delay1, delay120));
- return result.body;
+
+ if (typeof result.body == "object") return result.body;
+ return JSON.parse(result.body);
} catch (err) {
- console.log(err.message);
+ console.log("[Error] riotRequest: " + err.message);
return await riotRequest(region, url, params, retries - 1);
}
}
+// ----------------
+
+// User functionality
+// ------------------
+let users = {};
+let nameLookup = {};
-async function getAllMatches(region, accountId) {
- let matches = [];
+async function loadUserDb(region, accountId) {
+ if (!users[region]) users[region] = {};
+ if (users[region][accountId]) return;
+ let adapter = new FileAsync(region + "/" + accountId + ".json");
+ let db = await low(adapter);
+ await db.defaults({ games: [], gameSummaries: [], account: {} })
+ .write();
+ users[region][accountId] = db;
+}
+
+async function loadUserInfo(region, summonerName) {
+ if (!nameLookup[region]) nameLookup[region] = {};
+ if (nameLookup[region][summonerName]) return;
+ let user = await riotRequest(region, "/lol/summoner/v4/summoners/by-name/" + summonerName, {}, 5);
+ let accountId = user.accountId;
+ await loadUserDb(region, accountId);
+ users[region][accountId].set("account", user);
+ nameLookup[region][summonerName] = accountId;
+}
+
+async function loadGameSummaries(region, accountId) {
let totalGames;
- let bI = 0, eI = 99;
+ let bI = 0, eI = 100;
+ loop1:
do {
- let m = await riotRequest(region, "/lol/match/v4/matchlists/by-account/" + accountId, { beginIndex: bI, endIndex: eI }, 5);
- console.log(m);
- totalGames = m.totalGames;
- matches = matches.concat(m.matches);
- console.log("Added games " + bI + " to " + eI + ", " + matches.length + " of " + totalGames);
- bI = eI + 1;
+ let matchlist = await riotRequest(region, "/lol/match/v4/matchlists/by-account/" + accountId, { beginIndex: bI, endIndex: eI }, 5);
+ totalGames = matchlist.totalGames;
+ for (m in matchlist.matches) {
+ let match = matchlist.matches[m];
+ if (users[region][accountId].get("gameSummaries").find({ gameId: match.gameId }).value()) {
+ break loop1;
+ }
+ users[region][accountId].get("gameSummaries").push(match).write();
+ }
+ bI = eI;
eI += 100;
} while (bI <= totalGames);
-
- return matches;
+ users[region][accountId].write();
+ users[region][accountId].set("gameSummaries",
+ users[region][accountId].get("gameSummaries").sortBy("timestamp").sortedUniqBy((x) => x.gameId).value()).write();
}
+app.get("/lol/matches", async (req, res) => {
+ let region = req.query.region;
+ let summoner = req.query.summoner;
+ console.log("[Info] getting game summaries for " + summoner + " from " + region);
+ try {
+ await loadUserInfo(region, summoner);
+ let accountId = nameLookup[region][summoner];
+ await loadGameSummaries(region, accountId);
+ let matches = users[region][accountId].get("gameSummaries").value();
+ console.log(matches.length);
+ res.send(JSON.stringify(matches));
+ } catch (err) {
+ console.log("[Error] GET /lol/matches: " + err);
+ res.send("error");
+ }
+});
+// ------------------
+
// Static Data
// -----------
-let champions = null;
+let champions;
let champLookup = {};
-function getChampions(cb) {
+function loadChampions() {
request("http://ddragon.leagueoflegends.com/cdn/" + patch + "/data/en_US/champion.json", (err, res, body) => {
+ if (err) console.log("[Error] loadChampions: " + err);
champions = JSON.parse(body).data;
for (c in champions) {
champLookup[champions[c].key] = c;
}
- cb();
});
}
+
app.get("/lol/champions", (req, res) => {
- if (champions == null)
- getChampions(() => {
- res.send(JSON.stringify(Object.keys(champions)));
- });
- else
- res.send(JSON.stringify(Object.keys(champions)));
+ res.send(JSON.stringify(Object.keys(champions)));
});
+
app.get("/lol/champlookup", (req, res) => {
- if (champions == null)
- getChampions(() => {
- res.send(JSON.stringify(champLookup));
- });
- else
- res.send(JSON.stringify(champLookup));
-});
-let users = {};
-if (fs.existsSync("users.js")) {
- fs.readFile("users.js", (err, data) => {
- users = JSON.parse(data);
- });
-}
-app.get("/lol/matches", async (req, res) => {
- let region = req.query.region;
- let summoner = req.query.summoner;
- let regionUrl = regions[region];
- try {
- let data = await riotRequest(region, "/lol/summoner/v4/summoners/by-name/" + summoner, {}, 5);
- let accountId = data.accountId;
- if (users[accountId]) {
- res.send(JSON.stringify(users[accountId]));
- return;
- }
- let matches = await getAllMatches(region, accountId);
- users[accountId] = matches;
- fs.writeFile("users.js", JSON.stringify(users), (err) => {
- if (err) console.log("Error writing file: " + err);
- });
- res.send(JSON.stringify(matches));
- } catch (err) {
- console.log(err);
- }
+ res.send(JSON.stringify(champLookup));
});
-
// -----------
+loadChampions();
app.listen(port, () => {
console.log("Listening on port %d", port)
});