]> gitweb.ps.run Git - lolstats/blobdiff - index.js
data
[lolstats] / index.js
index 2fe7fc35b9cd54cde109bd18507ca5fee2f3f42a..b8ddb223fc7529fad5f120455e9818fd4f793007 100644 (file)
--- a/index.js
+++ b/index.js
@@ -1,17 +1,22 @@
-const express = require("express")
 const fs = require("fs")
 const request = require("request-promise-native")
 const fs = require("fs")
 const request = require("request-promise-native")
+const low = require("lowdb")
+const FileAsync = require("lowdb/adapters/FileAsync")
+
+const express = require("express")
 const app = express()
 const port = 3000
 const app = express()
 const port = 3000
-const sleep = require('util').promisify(setTimeout)
 
 const patch = "8.24.1";
 
 const patch = "8.24.1";
-const key = "RGAPI-c6cae96a-c4b0-4842-9017-ddd736f3f628";
-let appRateLimit1;
-let appRateLimit120;
+const key = "RGAPI-dce1850a-0954-4b1e-8072-77a26739f076";
+
+let appRateLimit1 = 10;
+let appRateLimit120 = 100;
 let appRateLimitCount1;
 let appRateLimitCount120;
 
 let appRateLimitCount1;
 let appRateLimitCount120;
 
+// Express routing
+// ---------------
 let rules = [
   ["/lol", "index.html"],
   ["/lol/script.js", "script.js"],
 let rules = [
   ["/lol", "index.html"],
   ["/lol/script.js", "script.js"],
@@ -25,7 +30,10 @@ for (i in rules) {
     res.sendFile(__dirname + "/html/" + file);
   });
 }
     res.sendFile(__dirname + "/html/" + file);
   });
 }
+// ---------------
 
 
+// Riot API request
+// ----------------
 const regions = {
   "BR": "br1.api.riotgames.com",
   "EUNE": "eun1.api.riotgames.com",
 const regions = {
   "BR": "br1.api.riotgames.com",
   "EUNE": "eun1.api.riotgames.com",
@@ -39,110 +47,142 @@ const regions = {
   "TR": "tr1.api.riotgames.com",
   "RU": "ru.api.riotgames.com",
   "PBE": "pbe1.api.riotgames.com",
   "TR": "tr1.api.riotgames.com",
   "RU": "ru.api.riotgames.com",
   "PBE": "pbe1.api.riotgames.com",
-}; 
+};
+
+let requests = [];
+
+async function executeRequest() {
+  if (requests.length > 0) {
+    let req = requests.shift();
+    if (req.retries < 1) req.rej();
+    else {
+      try {
+        console.log("[Info] request: " + req.url);
+        let result = await request({uri: req.url, 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];
+
+        if (typeof result.body == "object") req.res(result.body);
+        else req.res(JSON.parse(result.body));
+      } catch (err) {
+        console.log("[Error] riotRequest: " + err.message);
+        req.retries--;
+        requests.push(req);
+      }
+    }
+  }
+  let delay1 = 1000 / (appRateLimit1 - 1);
+  let delay120 = 120000 / (appRateLimit120 - 1);
+  setTimeout(executeRequest, Math.max(delay1, delay120));
+}
+executeRequest();
 
 async function riotRequest(region, url, params, retries) {
 
 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];
   }
   let req = "https://" + regions[region] + url + "?api_key=" + key;
   for (p in params) {
     req += "&" + p + "=" + params[p];
   }
-  try {
-    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;
-  } catch (err) {
-    console.log(err.message);
-    return await riotRequest(region, url, params, retries - 1);
-  }
+  return new Promise((resolve, reject) => {
+    requests.push({ url: req, retries: 5, res: resolve, rej: reject });
+  });
+}
+// ----------------
+
+// User functionality
+// ------------------
+let users = {};
+let nameLookup = {};
+
+async function loadUserDb(region, accountId) {
+  if (!users[region]) users[region] = {};
+  if (users[region][accountId]) return;
+  let adapter = new FileAsync("data/" + 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 getAllMatches(region, accountId) {
-  let matches = [];
+async function loadGameSummaries(region, accountId) {
   let totalGames;
   let totalGames;
-  let bI = 0, eI = 99;
+  let bI = 0, eI = 100;
 
 
+  loop1:
   do {
   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);
     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
 // -----------
 // Static Data
 // -----------
-let champions = null;
+let champions;
 let champLookup = {};
 let champLookup = {};
-function getChampions(cb) {
+function loadChampions() {
   request("http://ddragon.leagueoflegends.com/cdn/" + patch + "/data/en_US/champion.json", (err, res, body) => {
   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;
     }
     champions = JSON.parse(body).data;
     for (c in champions) {
       champLookup[champions[c].key] = c;
     }
-    cb();
   });
 }
   });
 }
+
 app.get("/lol/champions", (req, res) => {
 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) => {
 app.get("/lol/champlookup", (req, res) => {
-  if (champions == null)
-    getChampions(() => {
-      res.send(JSON.stringify(champLookup));
-    });
-  else
-    res.send(JSON.stringify(champLookup));
+  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);
-  }
-});
-
 // -----------
 
 // -----------
 
+loadChampions();
 app.listen(port, () => {
   console.log("Listening on port %d", port)
 });
 app.listen(port, () => {
   console.log("Listening on port %d", port)
 });