Starting with Vue

This commit is contained in:
Valentin Kaelin 2019-03-30 23:55:48 +01:00
commit cc630f002b
30 changed files with 29127 additions and 0 deletions

3
client/.browserslistrc Normal file
View file

@ -0,0 +1,3 @@
> 1%
last 2 versions
not ie <= 8

17
client/.eslintrc.js Normal file
View file

@ -0,0 +1,17 @@
module.exports = {
root: true,
env: {
node: true
},
'extends': [
'plugin:vue/essential',
'eslint:recommended'
],
rules: {
'no-console': process.env.NODE_ENV === 'production' ? 'error' : 'off',
'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off'
},
parserOptions: {
parser: 'babel-eslint'
}
}

21
client/.gitignore vendored Normal file
View file

@ -0,0 +1,21 @@
.DS_Store
node_modules
/dist
# local env files
.env.local
.env.*.local
# Log files
npm-debug.log*
yarn-debug.log*
yarn-error.log*
# Editor directories and files
.idea
.vscode
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw*

29
client/README.md Normal file
View file

@ -0,0 +1,29 @@
# riot-vue
## Project setup
```
npm install
```
### Compiles and hot-reloads for development
```
npm run serve
```
### Compiles and minifies for production
```
npm run build
```
### Run your tests
```
npm run test
```
### Lints and fixes files
```
npm run lint
```
### Customize configuration
See [Configuration Reference](https://cli.vuejs.org/config/).

5
client/babel.config.js Normal file
View file

@ -0,0 +1,5 @@
module.exports = {
presets: [
'@vue/app'
]
}

11544
client/package-lock.json generated Normal file

File diff suppressed because it is too large Load diff

28
client/package.json Normal file
View file

@ -0,0 +1,28 @@
{
"name": "riot-vue",
"version": "0.1.0",
"private": true,
"scripts": {
"serve": "vue-cli-service serve",
"build": "vue-cli-service build",
"lint": "vue-cli-service lint"
},
"dependencies": {
"axios": "^0.18.0",
"vue": "^2.6.6",
"vue-axios": "^2.1.4",
"vue-router": "^3.0.2"
},
"devDependencies": {
"@fullhuman/postcss-purgecss": "^1.1.0",
"@vue/cli-plugin-babel": "^3.5.0",
"@vue/cli-plugin-eslint": "^3.5.0",
"@vue/cli-service": "^3.5.0",
"babel-eslint": "^10.0.1",
"eslint": "^5.8.0",
"eslint-plugin-vue": "^5.0.0",
"purgecss": "^1.1.0",
"tailwindcss": "^1.0.0-beta.3",
"vue-template-compiler": "^2.5.21"
}
}

20
client/postcss.config.js Normal file
View file

@ -0,0 +1,20 @@
const tailwindcss = require("tailwindcss");
const autoprefixer = require("autoprefixer");
const purgecss = require("@fullhuman/postcss-purgecss");
module.exports = {
plugins: [
tailwindcss("./tailwind.config.js"),
autoprefixer({
add: true,
grid: true
}),
//Only add purgecss in production
process.env.NODE_ENV === "production"? purgecss({
content: [
"./src/**/*.html",
"./src/**/*.vue"
]
}): ""
]
};

BIN
client/public/favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

17
client/public/index.html Normal file
View file

@ -0,0 +1,17 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
<title>riot-vue</title>
</head>
<body>
<noscript>
<strong>We're sorry but riot-vue doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
</noscript>
<div id="app"></div>
<!-- built files will be auto injected -->
</body>
</html>

36
client/src/App.vue Normal file
View file

@ -0,0 +1,36 @@
<template>
<div id="app">
<div class="nav">
<router-link to="/">Accueil</router-link> |
<router-link :to="`/summoner/${summoner}`">
{{ linkText }}
</router-link>
</div>
<router-view/>
</div>
</template>
<style>
#app {
font-family: 'Avenir', Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
</style>
<script>
export default {
data() {
return {
linkText: 'Test link',
summoner: 'Kalane'
}
},
}
</script>

View file

@ -0,0 +1,3 @@
@tailwind base;
@tailwind components;
@tailwind utilities;

BIN
client/src/assets/logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.7 KiB

View file

@ -0,0 +1,151 @@
<template>
<li class="match">
<div class="content-container">
<div class="first">
<img :src="`https://cdn.valentinkaelin.ch/riot/champions/${data.champ}.png`" class="champion-icon" alt="example design">
<span class="level">{{ data.level }}</span>
<div class="summonerSpells">
<img class="spell-icon" src="https://cdn.valentinkaelin.ch/riot/spells/SummonerFlash.png" alt="Flash">
<img class="spell-icon" src="https://cdn.valentinkaelin.ch/riot/spells/SummonerDot.png" alt="Ignite">
</div>
<span class="champion-name">{{ data.champ }}</span>
</div>
<div class="second">
<div class="map">{{ data.map }}</div>
<div class="gamemode">{{ data.gamemode }}</div>
</div>
<div class="third">
<div
v-for="(item, index) in data.items" :key="index"
:style="{background: getItemLink(item)}" class="item"
>
</div>
</div>
<div class="fourth">
<div class="score">{{ data.kills }}/{{ data.deaths }}/{{ data.assists }}</div>
<div class="gold-farm">
<div class="gold">{{ data.gold }}</div>
<div class="farm">{{ data.minions }}</div>
</div>
<div class="duration-date">
<div class="duration">{{ data.time }}</div>
<div class="date">{{ data.date }}</div>
</div>
</div>
</div>
</li>
</template>
<script>
import itemsJSON from '@/data/item.json'
export default {
props: {
data: Object
},
methods: {
getItemLink(id) {
if(id !== 0) {
const itemImage = itemsJSON.data[id].image;
return `url('https://cdn.valentinkaelin.ch/riot/${itemImage.sprite}') -${itemImage.x}px -${itemImage.y}px`;
}
return "url('https://cdn.valentinkaelin.ch/riot/items/0.png') 0% 0% / cover";
}
}
}
</script>
<style scoped>
/* --- MATCHES --- */
.match {
background: #fff;
padding: 10px 0;
border-bottom: 1px solid #dae1e7;
}
.match .content-container {
display: flex;
flex-wrap: wrap;
padding: 16px;
}
.match.win .content-container {
border-left: 10px solid #51d88a;
}
.match.lose .content-container {
border-left: 10px solid #ef5753;
}
/* First col */
.match .first {
position: relative;
display: flex;
flex-direction: row;
align-items: center;
flex: 1 0 0;
}
.champion-icon {
width: 48px;
height: 48px;
display: block;
margin: 0 2px 0 0;
}
.match .level {
position: absolute;
bottom: 0;
left: 0;
color: #fff;
font-weight: bold;
}
.match .summonerSpells {
margin: 0 8px 0 0;
}
.spell-icon {
width: 23px;
height: 23px;
display: block;
}
.match .spell-icon:first-child {
margin: 0 0 2px 0;
}
/* Second col */
.match .second {
flex: 1 0 0;
text-align: left;
}
/* Third col */
.match .third {
flex: 1 0 0;
display: flex;
}
.third .item {
width: 48px;
height: 48px;
margin: 0 2px 0 0;
}
/* Fourth col */
.match .fourth {
flex: 1 0 0;
display: flex;
justify-content: space-around;
align-items: center;
}
</style>

15
client/src/data/data.js Normal file
View file

@ -0,0 +1,15 @@
// import json from '@/data/item.json'
// export default {
// data() {
// return {
// myJson: json
// }
// }
// }
export const championsId = { 266: "Aatrox", 103: "Ahri", 84: "Akali", 12: "Alistar", 32: "Amumu", 34: "Anivia", 1: "Annie", 22: "Ashe", 136: "AurelionSol", 268: "Azir", 432: "Bard", 53: "Blitzcrank", 63: "Brand", 201: "Braum", 51: "Caitlyn", 164: "Camille", 69: "Cassiopeia", 31: "Chogath", 42: "Corki", 122: "Darius", 131: "Diana", 119: "Draven", 36: "DrMundo", 245: "Ekko", 60: "Elise", 28: "Evelynn", 81: "Ezreal", 9: "Fiddlesticks", 114: "Fiora", 105: "Fizz", 3: "Galio", 41: "Gangplank", 86: "Garen", 150: "Gnar", 79: "Gragas", 104: "Graves", 120: "Hecarim", 74: "Heimerdinger", 420: "Illaoi", 39: "Irelia", 427: "Ivern", 40: "Janna", 59: "JarvanIV", 24: "Jax", 126: "Jayce", 202: "Jhin", 222: "Jinx", 145: "Kaisa", 429: "Kalista", 43: "Karma", 30: "Karthus", 38: "Kassadin", 55: "Katarina", 10: "Kayle", 141: "Kayn", 85: "Kennen", 121: "Khazix", 203: "Kindred", 240: "Kled", 96: "KogMaw", 7: "Leblanc", 64: "LeeSin", 89: "Leona", 127: "Lissandra", 236: "Lucian", 117: "Lulu", 99: "Lux", 54: "Malphite", 90: "Malzahar", 57: "Maokai", 11: "MasterYi", 21: "MissFortune", 62: "MonkeyKing", 82: "Mordekaiser", 25: "Morgana", 267: "Nami", 75: "Nasus", 111: "Nautilus", 76: "Nidalee", 56: "Nocturne", 20: "Nunu", 2: "Olaf", 61: "Orianna", 516: "Ornn", 80: "Pantheon", 78: "Poppy", 555: "Pyke", 133: "Quinn", 497: "Rakan", 33: "Rammus", 421: "RekSai", 58: "Renekton", 107: "Rengar", 92: "Riven", 68: "Rumble", 13: "Ryze", 113: "Sejuani", 35: "Shaco", 98: "Shen", 102: "Shyvana", 27: "Singed", 14: "Sion", 15: "Sivir", 72: "Skarner", 37: "Sona", 16: "Soraka", 50: "Swain", 134: "Syndra", 223: "TahmKench", 163: "Taliyah", 91: "Talon", 44: "Taric", 17: "Teemo", 412: "Thresh", 18: "Tristana", 48: "Trundle", 23: "Tryndamere", 4: "TwistedFate", 29: "Twitch", 77: "Udyr", 6: "Urgot", 110: "Varus", 67: "Vayne", 45: "Veigar", 161: "Velkoz", 254: "Vi", 112: "Viktor", 8: "Vladimir", 106: "Volibear", 19: "Warwick", 498: "Xayah", 101: "Xerath", 5: "XinZhao", 157: "Yasuo", 83: "Yorick", 154: "Zac", 238: "Zed", 115: "Ziggs", 26: "Zilean", 142: "Zoe", 143: "Zyra" };
export const maps = { 10: "The Twisted Treeline", 11: "Summoner's Rift", 12: "Howling Abyss" };
export const gameModes = { 76: 'URF', 100: 'ARAM', 400: 'Normal (Draft)', 420: 'Ranked (Solo)', 430: 'Normal (Blind)', 440: 'Ranked (Flex)', 460: '3v3 Blind', 470: '3v3 Ranked (Flex)', 800: '3v3 Co-op vs. AI (Intermediate)', 810: '3v3 Co-op vs. AI (Intro)', 820: '3v3 Co-op vs. AI (Beginner)', 830: 'Co-op vs. AI (Intro)', 840: 'Co-op vs. AI (Beginner)', 850: 'Co-op vs. AI (Intermediate)' }

15177
client/src/data/item.json Normal file

File diff suppressed because it is too large Load diff

18
client/src/main.js Normal file
View file

@ -0,0 +1,18 @@
import Vue from 'vue'
import axios from 'axios'
import VueAxios from 'vue-axios'
import '@/assets/css/tailwind.css'
import App from './App.vue'
import router from './router'
Vue.config.productionTip = false
Vue.use(VueAxios, axios)
new Vue({
router,
render: h => h(App),
}).$mount('#app')

54
client/src/router.js Normal file
View file

@ -0,0 +1,54 @@
import Vue from 'vue'
import Router from 'vue-router'
import Home from '@/views/Home.vue'
import Summoner from '@/views/Summoner.vue'
//import Cats from './views/Cats.vue'
//import Dogs from './views/Dogs.vue'
//import Pet from './views/Pet.vue'
Vue.use(Router)
export default new Router({
mode: 'history',
base: process.env.BASE_URL,
routes: [
{
path: '/',
name: 'home',
component: Home
},
{
path: '/summoner/:name',
name: 'summoner',
component: Summoner
}
/*{
path: '/cats',
name: 'cats',
component: Cats
},
{
path: '/dogs',
name: 'dogs',
component: Dogs
},
{
path: '/pets/:species/:id',
name: 'pet',
component: Pet
}*/
]
})

26
client/src/views/Home.vue Normal file
View file

@ -0,0 +1,26 @@
<template>
<div>
<h1>Home page test</h1>
<form @submit.prevent="redirect">
<input type="text" placeholder="Entre un pseudo." class="bg-gray-300 p-2 rounded-l outline-none focus:bg-gray-400" v-model="search">
<button class="bg-teal-500 p-2 text-white rounded-r hover:bg-teal-400" type="submit">Rechercher</button>
</form>
</div>
</template>
<script>
export default {
data() {
return {
search: ""
};
},
methods: {
redirect() {
this.$router.push("/summoner/" + this.search)
}
}
};
</script>

View file

@ -0,0 +1,331 @@
<template>
<div>
<button class="debug"></button>
<div class="search">
<div class="container mx-auto">
<form class="flex items-center mb-6" id="changeName" method="get" action="summoners">
<input type="search" class="hadow appearance-none border rounded w-full py-2 px-3 text-grey-darker leading-tight focus:outline-none focus:shadow-outline mr-1" id="name" name="username" placeholder="Pseudo du Joueur">
<button type="submit" class="bg-white hover:bg-grey-lightest text-grey-darkest font-semibold py-2 px-4 mr-1 border border-grey-light rounded shadow">Chercher</button>
<button id="refresh" class="bg-white hover:bg-grey-lightest text-grey-darkest font-semibold py-2 px-4 border border-grey-light rounded shadow">
<i class="fas fa-sync"></i>
</button>
</form>
</div>
</div>
<div class="container mx-auto pb-16">
<div class="player shadow-md" v-if="localInfos.name">
<div class="player__pp" :style="{background: `url(https://cdn.valentinkaelin.ch/riot/profileicon/${localInfos.profileIconId}.png) center/cover`}"></div>
<h1 class="player__name">{{ localInfos.name }}</h1>
<h3 class="player__level">{{ localInfos.level }}</h3>
<h3 class="player__rank">{{ localInfos.rank }}</h3>
<div class="player__rank-img" :style="{background: `url(${localInfos.rankImgLink}) center/cover`}"></div>
<h3 class="player__ratio">{{ localInfos.rankedWins ? localInfos.rankedWins + ' wins / ' + localInfos.rankedLosses + ' losses' : "Joueur non classé" }}</h3>
<ul class="list-matches--debug">
<Match
v-for="(match, index) in localInfos.matches" :key="index"
:data="localInfos.matches[index]"
/>
</ul>
</div>
<div v-else>
<p>Loading player's information...</p>
</div>
</div>
</div>
</template>
<script>
import Match from '@/components/Match.vue';
import { championsId, maps, gameModes } from "@/data/data.js";
export default {
components: {
Match
},
data() {
return {
localInfos: {},
nameChosen: this.$route.params.name
};
},
methods: {
createObject(JSONData) {
//console.log('--- ALL INFOS ---')
//console.log(JSONData);
const userStats = JSONData[0];
const rankedStats = JSONData[1];
const soloQStats = rankedStats !== null ? (rankedStats.queueType == 'RANKED_SOLO_5x5' ? rankedStats : JSONData[2]) : false;
const matches = JSONData[3].matches;
const matchesInfos = [];
// Loop on all matches
for (let i = 0; i < matches.length; i++) {
const currentMatch = matches[i];
let participantId;
for (let i = 0; i < currentMatch.participantIdentities.length; i++) {
if (currentMatch.participantIdentities[i].player.accountId === userStats.accountId)
participantId = currentMatch.participantIdentities[i].participantId;
}
const teamId = currentMatch.participants[participantId - 1].teamId;
let win = false;
for (let i = 0; i < currentMatch.teams.length; i++) {
if (currentMatch.teams[i].teamId === teamId) {
if (currentMatch.teams[i].win === 'Win')
win = true;
}
}
const map = maps[currentMatch.mapId];
let mode = gameModes[currentMatch.queueId];
if (!mode)
mode = 'Undefined gamemode';
const champion = championsId[currentMatch.participants[participantId - 1].championId];
const role = currentMatch.participants[participantId - 1].timeline.lane;
const timeAgo = this.timeDifference(currentMatch.gameCreation);
const time = this.secToTime(currentMatch.gameDuration);
const kills = currentMatch.participants[participantId - 1].stats.kills;
const deaths = currentMatch.participants[participantId - 1].stats.deaths;
const assists = currentMatch.participants[participantId - 1].stats.assists;
const level = currentMatch.participants[participantId - 1].stats.champLevel;
const items = [];
for (let i = 0; i < 6; i++) {
const currentItem = 'item' + i;
items.push(currentMatch.participants[participantId - 1].stats[currentItem]);
}
const gold = (currentMatch.participants[participantId - 1].stats.goldEarned / 1000).toFixed(1) + 'k';
const minions = currentMatch.participants[participantId - 1].stats.totalMinionsKilled + currentMatch.participants[participantId - 1].stats.neutralMinionsKilled;
matchesInfos.push({
result: win,
map: map,
gamemode: mode,
champ: champion,
role: role,
date: timeAgo,
time: time,
kills: kills,
deaths: deaths,
assists: assists,
level: level,
items: items,
gold: gold,
minions: minions
});
}
console.log(matchesInfos);
this.localInfos = {
accountId: userStats.accountId,
matches: matchesInfos,
profileIconId: userStats.profileIconId,
name: userStats.name,
level: userStats.summonerLevel,
rank: soloQStats ? soloQStats.tier + ' ' + soloQStats.rank : 'Joueur non classé',
rankImgLink: this.getRankImg(soloQStats),
rankedWins: soloQStats ? soloQStats.wins : undefined,
rankedLosses: soloQStats ? soloQStats.losses : undefined
}
this.nameChosen = userStats.name;
console.log('====== Saved infos ======');
console.log(this.localInfos);
localStorage[this.nameChosen] = JSON.stringify(this.localInfos);
//displayContent(localStorage[this.nameChosen]);
},
getRankImg(soloQStats) {
if (!soloQStats) {
return "https://cdn.valentinkaelin.ch/riot/tier-icons/provisional.png";
}
if (soloQStats.tier != "MASTER" && soloQStats.tier != "CHALLENGER") {
return ("https://cdn.valentinkaelin.ch/riot/tier-icons/" + soloQStats.tier.toLowerCase() + "_" + soloQStats.rank.toLowerCase() + ".png");
}
return ("https://cdn.valentinkaelin.ch/riot/tier-icons/" + soloQStats.tier.toLowerCase() + ".png");
},
secToTime(sec) {
var min = Math.floor(sec / 60);
var newSec = sec - min * 60;
return min + ":" + (newSec < 10 ? "0" + newSec : newSec);
},
timeDifference(previous) {
var current = new Date();
var msPerMinute = 60 * 1000;
var msPerHour = msPerMinute * 60;
var msPerDay = msPerHour * 24;
var msPerWeek = msPerDay * 7;
var elapsed = current - previous;
if (elapsed < msPerMinute) {
return Math.round(elapsed / 1000) + 's';
} else if (elapsed < msPerHour) {
return Math.round(elapsed / msPerMinute) + 'm';
} else if (elapsed < msPerDay) {
return Math.round(elapsed / msPerHour) + 'h';
} else if (elapsed < msPerWeek) {
return Math.round(elapsed / msPerDay) + 'j';
} else {
var oldDate = new Date(previous);
var day = oldDate.getDate() < 10 ? '0' + oldDate.getDate() : oldDate.getDate();
var month = oldDate.getMonth() < 9 ? '0' + (oldDate.getMonth() + 1) : (oldDate.getMonth() + 1);
return day + '.' + month + '.' + oldDate.getFullYear().toString().substr(-2);
}
}
},
mounted: function () {
const summoner = this.$route.params.name;
this.axios({
method: "POST",
url: "http://localhost:5000/api",
headers: {
"Content-Type": "application/json"
},
data: {
summoner
}
})
.then(response => {
return response.data;
})
.then(jsonData => {
console.log(jsonData);
this.createObject(jsonData);
})
.catch(err => {
console.log(err);
});
}
};
</script>
<style scoped>
.debug {
position: absolute;
right: 0;
top: 0;
width: 40px;
height: 40px;
border: none;
z-index: 9999999999;
}
.debug:hover {
background: #ef5753;
}
.search {
background: #4dc0b5;
}
.search .container {
display: flex;
align-items: center;
justify-content: space-around;
padding: 32px 0;
}
#refresh {
display: none;
}
.player {
text-align: center;
margin: 16px auto 0;
border: 1px solid #ebebeb;
padding: 16px;
background: #fff;
}
.player__pp {
width: 75px;
height: 75px;
background: #ebebeb;
margin: 0 auto;
}
.player__rank-img {
width: 75px;
height: 75px;
background: #ebebeb;
margin: 0 auto;
}
.list-matches {
list-style-type: none;
padding: 0;
}
/* #######LOADER####### */
.loader--overlay {
position: absolute;
z-index: 9997;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.8);
display: none;
}
.loader-container {
position: absolute;
z-index: 9998;
width: 100%;
height: 100vh;
}
.LoaderBalls {
width: 90px;
display: flex;
justify-content: space-between;
align-items: center;
position: absolute;
z-index: 9999;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
}
.LoaderBalls__item {
width: 20px;
height: 20px;
border-radius: 50%;
background: #00f1ca;
}
.LoaderBalls__item:nth-child(1) {
animation: bouncing 0.4s alternate infinite
cubic-bezier(0.6, 0.05, 0.15, 0.95);
}
.LoaderBalls__item:nth-child(2) {
animation: bouncing 0.4s 0.1s alternate infinite
cubic-bezier(0.6, 0.05, 0.15, 0.95) backwards;
}
.LoaderBalls__item:nth-child(3) {
animation: bouncing 0.4s 0.2s alternate infinite
cubic-bezier(0.6, 0.05, 0.15, 0.95) backwards;
}
@keyframes bouncing {
0% {
transform: translate3d(0, 10px, 0) scale(1.2, 0.85);
}
100% {
transform: translate3d(0, -20px, 0) scale(0.9, 1.1);
}
}
</style>

11
client/tailwind.config.js Normal file
View file

@ -0,0 +1,11 @@
module.exports = {
theme: {
// Some useful comment
},
variants: {
// Some useful comment
},
plugins: [
// Some useful comment
]
}

3
server/.gitignore vendored Normal file
View file

@ -0,0 +1,3 @@
/node_modules
/Patch9.5
.env

52
server/home.html Normal file
View file

@ -0,0 +1,52 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Riot Api Node</title>
<link href="https://cdn.jsdelivr.net/npm/tailwindcss/dist/tailwind.min.css" rel="stylesheet">
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.6.3/css/all.css">
<!-- Custom CSS -->
<link rel="stylesheet" href="public/style.css">
</head>
<body class="font-sans bg-grey-lighter">
<div class="loader--overlay">
<div class="loader-container">
<div class="LoaderBalls">
<div class="LoaderBalls__item"></div>
<div class="LoaderBalls__item"></div>
<div class="LoaderBalls__item"></div>
</div>
</div>
</div>
<button class="debug"></button>
<div class="search">
<div class="container mx-auto">
<h2>Homepage</h2>
<form class="flex items-center" id="changeName" method="get" action="summoners">
<input type="search" class="hadow appearance-none border rounded w-full py-2 px-3 text-grey-darker leading-tight focus:outline-none focus:shadow-outline mr-1" id="name" name="username" placeholder="Pseudo du Joueur">
<button type="submit" class="bg-white hover:bg-grey-lightest text-grey-darkest font-semibold py-2 px-4 mr-1 border border-grey-light rounded shadow">
Chercher
</button>
<button id="refresh" class="bg-white hover:bg-grey-lightest text-grey-darkest font-semibold py-2 px-4 border border-grey-light rounded shadow">
<i class="fas fa-sync"></i>
</button>
</form>
</div>
</div>
<div class="flex items-center justify-center w-full" style="height: calc(100vh - 153px);">
<h1>Welcome on KLN's RIOT API Test</h1>
</div>
</body>
</html>

721
server/package-lock.json generated Normal file
View file

@ -0,0 +1,721 @@
{
"name": "riotapi",
"version": "1.0.0",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
"accepts": {
"version": "1.3.5",
"resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.5.tgz",
"integrity": "sha1-63d99gEXI6OxTopywIBcjoZ0a9I=",
"requires": {
"mime-types": "~2.1.18",
"negotiator": "0.6.1"
}
},
"ajv": {
"version": "6.6.1",
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.6.1.tgz",
"integrity": "sha512-ZoJjft5B+EJBjUyu9C9Hc0OZyPZSSlOF+plzouTrg6UlA8f+e/n8NIgBFG/9tppJtpPWfthHakK7juJdNDODww==",
"requires": {
"fast-deep-equal": "^2.0.1",
"fast-json-stable-stringify": "^2.0.0",
"json-schema-traverse": "^0.4.1",
"uri-js": "^4.2.2"
}
},
"array-flatten": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz",
"integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI="
},
"asn1": {
"version": "0.2.4",
"resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz",
"integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==",
"requires": {
"safer-buffer": "~2.1.0"
}
},
"assert-plus": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz",
"integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU="
},
"asynckit": {
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
"integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k="
},
"aws-sign2": {
"version": "0.7.0",
"resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz",
"integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg="
},
"aws4": {
"version": "1.8.0",
"resolved": "https://registry.npmjs.org/aws4/-/aws4-1.8.0.tgz",
"integrity": "sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ=="
},
"bcrypt-pbkdf": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz",
"integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=",
"requires": {
"tweetnacl": "^0.14.3"
}
},
"bluebird": {
"version": "3.5.3",
"resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.3.tgz",
"integrity": "sha512-/qKPUQlaW1OyR51WeCPBvRnAlnZFUJkCSG5HzGnuIqhgyJtF+T94lFnn33eiazjRm2LAHVy2guNnaq48X9SJuw=="
},
"body-parser": {
"version": "1.18.3",
"resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.18.3.tgz",
"integrity": "sha1-WykhmP/dVTs6DyDe0FkrlWlVyLQ=",
"requires": {
"bytes": "3.0.0",
"content-type": "~1.0.4",
"debug": "2.6.9",
"depd": "~1.1.2",
"http-errors": "~1.6.3",
"iconv-lite": "0.4.23",
"on-finished": "~2.3.0",
"qs": "6.5.2",
"raw-body": "2.3.3",
"type-is": "~1.6.16"
}
},
"bytes": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz",
"integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg="
},
"caseless": {
"version": "0.12.0",
"resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz",
"integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw="
},
"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==",
"requires": {
"delayed-stream": "~1.0.0"
}
},
"content-disposition": {
"version": "0.5.2",
"resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.2.tgz",
"integrity": "sha1-DPaLud318r55YcOoUXjLhdunjLQ="
},
"content-type": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz",
"integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA=="
},
"cookie": {
"version": "0.3.1",
"resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz",
"integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s="
},
"cookie-signature": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz",
"integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw="
},
"core-util-is": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
"integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac="
},
"cors": {
"version": "2.8.5",
"resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz",
"integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==",
"requires": {
"object-assign": "^4",
"vary": "^1"
}
},
"dashdash": {
"version": "1.14.1",
"resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz",
"integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=",
"requires": {
"assert-plus": "^1.0.0"
}
},
"debug": {
"version": "2.6.9",
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
"integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
"requires": {
"ms": "2.0.0"
}
},
"delayed-stream": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
"integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk="
},
"depd": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz",
"integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak="
},
"destroy": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz",
"integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA="
},
"dotenv": {
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/dotenv/-/dotenv-7.0.0.tgz",
"integrity": "sha512-M3NhsLbV1i6HuGzBUH8vXrtxOk+tWmzWKDMbAVSUp3Zsjm7ywFeuwrUXhmhQyRK1q5B5GGy7hcXPbj3bnfZg2g=="
},
"ecc-jsbn": {
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz",
"integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=",
"requires": {
"jsbn": "~0.1.0",
"safer-buffer": "^2.1.0"
}
},
"ee-first": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
"integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0="
},
"encodeurl": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz",
"integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k="
},
"escape-html": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
"integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg="
},
"etag": {
"version": "1.8.1",
"resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz",
"integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc="
},
"express": {
"version": "4.16.4",
"resolved": "https://registry.npmjs.org/express/-/express-4.16.4.tgz",
"integrity": "sha512-j12Uuyb4FMrd/qQAm6uCHAkPtO8FDTRJZBDd5D2KOL2eLaz1yUNdUB/NOIyq0iU4q4cFarsUCrnFDPBcnksuOg==",
"requires": {
"accepts": "~1.3.5",
"array-flatten": "1.1.1",
"body-parser": "1.18.3",
"content-disposition": "0.5.2",
"content-type": "~1.0.4",
"cookie": "0.3.1",
"cookie-signature": "1.0.6",
"debug": "2.6.9",
"depd": "~1.1.2",
"encodeurl": "~1.0.2",
"escape-html": "~1.0.3",
"etag": "~1.8.1",
"finalhandler": "1.1.1",
"fresh": "0.5.2",
"merge-descriptors": "1.0.1",
"methods": "~1.1.2",
"on-finished": "~2.3.0",
"parseurl": "~1.3.2",
"path-to-regexp": "0.1.7",
"proxy-addr": "~2.0.4",
"qs": "6.5.2",
"range-parser": "~1.2.0",
"safe-buffer": "5.1.2",
"send": "0.16.2",
"serve-static": "1.13.2",
"setprototypeof": "1.1.0",
"statuses": "~1.4.0",
"type-is": "~1.6.16",
"utils-merge": "1.0.1",
"vary": "~1.1.2"
}
},
"extend": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz",
"integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g=="
},
"extsprintf": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz",
"integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU="
},
"fast-deep-equal": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz",
"integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk="
},
"fast-json-stable-stringify": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz",
"integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I="
},
"finalhandler": {
"version": "1.1.1",
"resolved": "http://registry.npmjs.org/finalhandler/-/finalhandler-1.1.1.tgz",
"integrity": "sha512-Y1GUDo39ez4aHAw7MysnUD5JzYX+WaIj8I57kO3aEPT1fFRL4sr7mjei97FgnwhAyyzRYmQZaTHb2+9uZ1dPtg==",
"requires": {
"debug": "2.6.9",
"encodeurl": "~1.0.2",
"escape-html": "~1.0.3",
"on-finished": "~2.3.0",
"parseurl": "~1.3.2",
"statuses": "~1.4.0",
"unpipe": "~1.0.0"
}
},
"forever-agent": {
"version": "0.6.1",
"resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz",
"integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE="
},
"form-data": {
"version": "2.3.3",
"resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz",
"integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==",
"requires": {
"asynckit": "^0.4.0",
"combined-stream": "^1.0.6",
"mime-types": "^2.1.12"
}
},
"forwarded": {
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz",
"integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ="
},
"fresh": {
"version": "0.5.2",
"resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz",
"integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac="
},
"getpass": {
"version": "0.1.7",
"resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz",
"integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=",
"requires": {
"assert-plus": "^1.0.0"
}
},
"har-schema": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz",
"integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI="
},
"har-validator": {
"version": "5.1.3",
"resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.3.tgz",
"integrity": "sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g==",
"requires": {
"ajv": "^6.5.5",
"har-schema": "^2.0.0"
}
},
"http-errors": {
"version": "1.6.3",
"resolved": "http://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz",
"integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=",
"requires": {
"depd": "~1.1.2",
"inherits": "2.0.3",
"setprototypeof": "1.1.0",
"statuses": ">= 1.4.0 < 2"
}
},
"http-signature": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz",
"integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=",
"requires": {
"assert-plus": "^1.0.0",
"jsprim": "^1.2.2",
"sshpk": "^1.7.0"
}
},
"iconv-lite": {
"version": "0.4.23",
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.23.tgz",
"integrity": "sha512-neyTUVFtahjf0mB3dZT77u+8O0QB89jFdnBkd5P1JgYPbPaia3gXXOVL2fq8VyU2gMMD7SaN7QukTB/pmXYvDA==",
"requires": {
"safer-buffer": ">= 2.1.2 < 3"
}
},
"inherits": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
"integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4="
},
"ipaddr.js": {
"version": "1.8.0",
"resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.8.0.tgz",
"integrity": "sha1-6qM9bd16zo9/b+DJygRA5wZzix4="
},
"is-typedarray": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz",
"integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo="
},
"isstream": {
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz",
"integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo="
},
"jsbn": {
"version": "0.1.1",
"resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz",
"integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM="
},
"json-schema": {
"version": "0.2.3",
"resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz",
"integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM="
},
"json-schema-traverse": {
"version": "0.4.1",
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
"integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg=="
},
"json-stringify-safe": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz",
"integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus="
},
"jsprim": {
"version": "1.4.1",
"resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz",
"integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=",
"requires": {
"assert-plus": "1.0.0",
"extsprintf": "1.3.0",
"json-schema": "0.2.3",
"verror": "1.10.0"
}
},
"lodash": {
"version": "4.17.11",
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz",
"integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg=="
},
"media-typer": {
"version": "0.3.0",
"resolved": "http://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
"integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g="
},
"merge-descriptors": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz",
"integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E="
},
"methods": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz",
"integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4="
},
"mime": {
"version": "1.4.1",
"resolved": "https://registry.npmjs.org/mime/-/mime-1.4.1.tgz",
"integrity": "sha512-KI1+qOZu5DcW6wayYHSzR/tXKCDC5Om4s1z2QJjDULzLcmf3DvzS7oluY4HCTrc+9FiKmWUgeNLg7W3uIQvxtQ=="
},
"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=="
},
"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==",
"requires": {
"mime-db": "~1.37.0"
}
},
"ms": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
"integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
},
"negotiator": {
"version": "0.6.1",
"resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.1.tgz",
"integrity": "sha1-KzJxhOiZIQEXeyhWP7XnECrNDKk="
},
"oauth-sign": {
"version": "0.9.0",
"resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz",
"integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ=="
},
"object-assign": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
"integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM="
},
"on-finished": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz",
"integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=",
"requires": {
"ee-first": "1.1.1"
}
},
"parseurl": {
"version": "1.3.2",
"resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.2.tgz",
"integrity": "sha1-/CidTtiZMRlGDBViUyYs3I3mW/M="
},
"path-to-regexp": {
"version": "0.1.7",
"resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz",
"integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w="
},
"performance-now": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz",
"integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns="
},
"proxy-addr": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.4.tgz",
"integrity": "sha512-5erio2h9jp5CHGwcybmxmVqHmnCBZeewlfJ0pex+UW7Qny7OOZXTtH56TGNyBizkgiOwhJtMKrVzDTeKcySZwA==",
"requires": {
"forwarded": "~0.1.2",
"ipaddr.js": "1.8.0"
}
},
"psl": {
"version": "1.1.29",
"resolved": "https://registry.npmjs.org/psl/-/psl-1.1.29.tgz",
"integrity": "sha512-AeUmQ0oLN02flVHXWh9sSJF7mcdFq0ppid/JkErufc3hGIV/AMa8Fo9VgDo/cT2jFdOWoFvHp90qqBH54W+gjQ=="
},
"punycode": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz",
"integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A=="
},
"qs": {
"version": "6.5.2",
"resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz",
"integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA=="
},
"range-parser": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.0.tgz",
"integrity": "sha1-9JvmtIeJTdxA3MlKMi9hEJLgDV4="
},
"raw-body": {
"version": "2.3.3",
"resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.3.3.tgz",
"integrity": "sha512-9esiElv1BrZoI3rCDuOuKCBRbuApGGaDPQfjSflGxdy4oyzqghxu6klEkkVIvBje+FF0BX9coEv8KqW6X/7njw==",
"requires": {
"bytes": "3.0.0",
"http-errors": "1.6.3",
"iconv-lite": "0.4.23",
"unpipe": "1.0.0"
}
},
"request": {
"version": "2.88.0",
"resolved": "https://registry.npmjs.org/request/-/request-2.88.0.tgz",
"integrity": "sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg==",
"requires": {
"aws-sign2": "~0.7.0",
"aws4": "^1.8.0",
"caseless": "~0.12.0",
"combined-stream": "~1.0.6",
"extend": "~3.0.2",
"forever-agent": "~0.6.1",
"form-data": "~2.3.2",
"har-validator": "~5.1.0",
"http-signature": "~1.2.0",
"is-typedarray": "~1.0.0",
"isstream": "~0.1.2",
"json-stringify-safe": "~5.0.1",
"mime-types": "~2.1.19",
"oauth-sign": "~0.9.0",
"performance-now": "^2.1.0",
"qs": "~6.5.2",
"safe-buffer": "^5.1.2",
"tough-cookie": "~2.4.3",
"tunnel-agent": "^0.6.0",
"uuid": "^3.3.2"
}
},
"request-promise": {
"version": "4.2.2",
"resolved": "https://registry.npmjs.org/request-promise/-/request-promise-4.2.2.tgz",
"integrity": "sha1-0epG1lSm7k+O5qT+oQGMIpEZBLQ=",
"requires": {
"bluebird": "^3.5.0",
"request-promise-core": "1.1.1",
"stealthy-require": "^1.1.0",
"tough-cookie": ">=2.3.3"
}
},
"request-promise-core": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/request-promise-core/-/request-promise-core-1.1.1.tgz",
"integrity": "sha1-Pu4AssWqgyOc+wTFcA2jb4HNCLY=",
"requires": {
"lodash": "^4.13.1"
}
},
"safe-buffer": {
"version": "5.1.2",
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
},
"safer-buffer": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
},
"send": {
"version": "0.16.2",
"resolved": "https://registry.npmjs.org/send/-/send-0.16.2.tgz",
"integrity": "sha512-E64YFPUssFHEFBvpbbjr44NCLtI1AohxQ8ZSiJjQLskAdKuriYEP6VyGEsRDH8ScozGpkaX1BGvhanqCwkcEZw==",
"requires": {
"debug": "2.6.9",
"depd": "~1.1.2",
"destroy": "~1.0.4",
"encodeurl": "~1.0.2",
"escape-html": "~1.0.3",
"etag": "~1.8.1",
"fresh": "0.5.2",
"http-errors": "~1.6.2",
"mime": "1.4.1",
"ms": "2.0.0",
"on-finished": "~2.3.0",
"range-parser": "~1.2.0",
"statuses": "~1.4.0"
}
},
"serve-static": {
"version": "1.13.2",
"resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.13.2.tgz",
"integrity": "sha512-p/tdJrO4U387R9oMjb1oj7qSMaMfmOyd4j9hOFoxZe2baQszgHcSWjuya/CiT5kgZZKRudHNOA0pYXOl8rQ5nw==",
"requires": {
"encodeurl": "~1.0.2",
"escape-html": "~1.0.3",
"parseurl": "~1.3.2",
"send": "0.16.2"
}
},
"setprototypeof": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz",
"integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ=="
},
"sshpk": {
"version": "1.15.2",
"resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.15.2.tgz",
"integrity": "sha512-Ra/OXQtuh0/enyl4ETZAfTaeksa6BXks5ZcjpSUNrjBr0DvrJKX+1fsKDPpT9TBXgHAFsa4510aNVgI8g/+SzA==",
"requires": {
"asn1": "~0.2.3",
"assert-plus": "^1.0.0",
"bcrypt-pbkdf": "^1.0.0",
"dashdash": "^1.12.0",
"ecc-jsbn": "~0.1.1",
"getpass": "^0.1.1",
"jsbn": "~0.1.0",
"safer-buffer": "^2.0.2",
"tweetnacl": "~0.14.0"
}
},
"statuses": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/statuses/-/statuses-1.4.0.tgz",
"integrity": "sha512-zhSCtt8v2NDrRlPQpCNtw/heZLtfUDqxBM1udqikb/Hbk52LK4nQSwr10u77iopCW5LsyHpuXS0GnEc48mLeew=="
},
"stealthy-require": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/stealthy-require/-/stealthy-require-1.1.1.tgz",
"integrity": "sha1-NbCYdbT/SfJqd35QmzCQoyJr8ks="
},
"tough-cookie": {
"version": "2.4.3",
"resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.4.3.tgz",
"integrity": "sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ==",
"requires": {
"psl": "^1.1.24",
"punycode": "^1.4.1"
},
"dependencies": {
"punycode": {
"version": "1.4.1",
"resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz",
"integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4="
}
}
},
"tunnel-agent": {
"version": "0.6.0",
"resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz",
"integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=",
"requires": {
"safe-buffer": "^5.0.1"
}
},
"tweetnacl": {
"version": "0.14.5",
"resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz",
"integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q="
},
"type-is": {
"version": "1.6.16",
"resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.16.tgz",
"integrity": "sha512-HRkVv/5qY2G6I8iab9cI7v1bOIdhm94dVjQCPFElW9W+3GeDOSHmy2EBYe4VTApuzolPcmgFTN3ftVJRKR2J9Q==",
"requires": {
"media-typer": "0.3.0",
"mime-types": "~2.1.18"
}
},
"unpipe": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
"integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw="
},
"uri-js": {
"version": "4.2.2",
"resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz",
"integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==",
"requires": {
"punycode": "^2.1.0"
}
},
"utils-merge": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz",
"integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM="
},
"uuid": {
"version": "3.3.2",
"resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz",
"integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA=="
},
"vary": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
"integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw="
},
"verror": {
"version": "1.10.0",
"resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz",
"integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=",
"requires": {
"assert-plus": "^1.0.0",
"core-util-is": "1.0.2",
"extsprintf": "^1.2.0"
}
}
}
}

20
server/package.json Normal file
View file

@ -0,0 +1,20 @@
{
"name": "riotapi",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "kalane",
"license": "ISC",
"dependencies": {
"bluebird": "^3.5.3",
"body-parser": "^1.18.3",
"cors": "^2.8.5",
"dotenv": "^7.0.0",
"express": "^4.16.4",
"request": "^2.88.0",
"request-promise": "^4.2.2"
}
}

View file

@ -0,0 +1,55 @@
/**
* Return the relative time betweeen a chosen moment and the current time
* @param previous : time we want to get difference
*/
function timeDifference(previous) {
var current = new Date();
var msPerMinute = 60 * 1000;
var msPerHour = msPerMinute * 60;
var msPerDay = msPerHour * 24;
var msPerWeek = msPerDay * 7;
var elapsed = current - previous;
if (elapsed < msPerMinute) {
return Math.round(elapsed / 1000) + 's';
} else if (elapsed < msPerHour) {
return Math.round(elapsed / msPerMinute) + 'm';
} else if (elapsed < msPerDay) {
return Math.round(elapsed / msPerHour) + 'h';
} else if (elapsed < msPerWeek) {
return Math.round(elapsed / msPerDay) + 'j';
} else {
var oldDate = new Date(previous);
var day = oldDate.getDate() < 10 ? '0' + oldDate.getDate() : oldDate.getDate();
var month = oldDate.getMonth() < 9 ? '0' + (oldDate.getMonth() + 1) : (oldDate.getMonth() + 1);
return day + '.' + month + '.' + oldDate.getFullYear().toString().substr(-2);
}
}
/**
* Return time in a formatted way
* @param sec : time in seconds to convert
*/
function secToTime(sec) {
var min = Math.floor(sec / 60);
var newSec = sec - min * 60;
return min + ':' + (newSec < 10 ? '0' + newSec : newSec); //
}
/**
* Return the link of the rank image
* @param soloQStats : stats in soloQ of the player
*/
function getRankImg(soloQStats) {
if (!soloQStats) {
return 'https://cdn.valentinkaelin.ch/riot/tier-icons/provisional.png';
}
if (soloQStats.tier != 'MASTER' && soloQStats.tier != 'CHALLENGER') {
return 'https://cdn.valentinkaelin.ch/riot/tier-icons/' + soloQStats.tier.toLowerCase() + '_' + soloQStats.rank.toLowerCase() + '.png';
} else {
return 'https://cdn.valentinkaelin.ch/riot/tier-icons/' + soloQStats.tier.toLowerCase() + '.png';
}
}

215
server/public/style.css Normal file
View file

@ -0,0 +1,215 @@
html {
height: 100%;
}
body {
background: #F1F5F8;
position: relative;
min-height: 100%;
}
.debug {
position: absolute;
right: 0;
top: 0;
width: 40px;
height: 40px;
border: none;
z-index: 9999999999;
}
.debug:hover {
background: #EF5753;
}
.search {
background: #4DC0B5;
}
.search .container {
display: flex;
align-items: center;
justify-content: space-around;
padding: 32px 0;
}
#refresh {
display: none;
}
.player {
text-align: center;
margin: 16px auto 0;
border: 1px solid #ebebeb;
padding: 16px;
background: #fff;
}
.player__pp {
width: 75px;
height: 75px;
background: #ebebeb;
margin: 0 auto;
}
.player__rank-img {
width: 75px;
height: 75px;
background: #ebebeb;
margin: 0 auto;
}
/* --- MATCHES --- */
.list-matches {
list-style-type: none;
padding: 0;
}
.match {
background: #fff;
padding: 10px 0;
border-bottom: 1px solid #DAE1E7;
}
.match .content-container {
display: flex;
flex-wrap: wrap;
padding: 16px;
}
.match.win .content-container {
border-left: 10px solid #51D88A;
}
.match.lose .content-container {
border-left: 10px solid #EF5753;
}
/* First col */
.match .first {
position: relative;
display: flex;
flex-direction: row;
align-items: center;
flex: 1 0 0;
}
.champion-icon {
width: 48px;
height: 48px;
display: block;
margin: 0 2px 0 0;
}
.match .level {
position: absolute;
bottom: 0;
left: 0;
color: #fff;
font-weight: bold;
}
.match .summonerSpells {
margin: 0 8px 0 0;
}
.spell-icon {
width: 23px;
height: 23px;
display: block;
}
.match .spell-icon:first-child {
margin: 0 0 2px 0;
}
/* Second col */
.match .second {
flex: 1 0 0;
text-align: left;
}
/* Third col */
.match .third {
flex: 1 0 0;
display: flex;
}
.third .item {
width: 48px;
height: 48px;
margin: 0 2px 0 0;
}
/* Fourth col */
.match .fourth {
flex: 1 0 0;
display: flex;
justify-content: space-around;
align-items: center;
}
/* #######LOADER####### */
.loader--overlay {
position: absolute;
z-index: 9997;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.8);
display: none;
}
.loader-container {
position: absolute;
z-index: 9998;
width: 100%;
height: 100vh;
}
.LoaderBalls {
width: 90px;
display: flex;
justify-content: space-between;
align-items: center;
position: absolute;
z-index: 9999;
left: 50%;
top: 50%;
transform: translate(-50%,-50%);
}
.LoaderBalls__item {
width: 20px;
height: 20px;
border-radius: 50%;
background: #00f1ca;
}
.LoaderBalls__item:nth-child(1) {
animation: bouncing 0.4s alternate infinite cubic-bezier(0.6, 0.05, 0.15, 0.95);
}
.LoaderBalls__item:nth-child(2) {
animation: bouncing 0.4s 0.1s alternate infinite cubic-bezier(0.6, 0.05, 0.15, 0.95) backwards;
}
.LoaderBalls__item:nth-child(3) {
animation: bouncing 0.4s 0.2s alternate infinite cubic-bezier(0.6, 0.05, 0.15, 0.95) backwards;
}
@keyframes bouncing {
0% {
transform: translate3d(0, 10px, 0) scale(1.2, 0.85);
}
100% {
transform: translate3d(0, -20px, 0) scale(0.9, 1.1);
}
}

323
server/public/summoner.js Normal file
View file

@ -0,0 +1,323 @@
const req = new XMLHttpRequest();
const url = '/api';
const localInfos = {};
let nameChosen = '';
let itemsJSON;
// Get username from param
const fullUrl = new URL(window.location.href);
const searchParams = new URLSearchParams(fullUrl.search);
nameChosen = searchParams.get('username');
/**
* Get the JSON file of all the items
*/
async function getItemsJSON() {
return fetch('public/item.json').then(resp => resp.json()).then(json => { return json });
}
/**
* Main function of the program
*/
async function main() {
req.addEventListener('load', onLoad);
req.addEventListener('error', onError);
itemsJSON = await getItemsJSON();
//console.log(itemsJSON);
/* Check on the load of the page if the content is already cached */
if (localStorage[nameChosen]) {
console.log('cached on page load');
document.querySelector('#refresh').style.display = 'block';
displayContent(localStorage[nameChosen]);
} else {
console.log('not cached on page load');
req.open('POST', url, true);
document.querySelector('.loader--overlay').style.display = 'block';
req.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
req.send('playerName=' + nameChosen);
}
/* Debug button to reset localstorage */
document.querySelector('.debug').addEventListener('click', () => {
console.log('CLEAR LOCALSTORAGE');
localStorage.clear();
});
/* Refresh button */
const refreshBtn = document.querySelector('#refresh');
refreshBtn.addEventListener('click', (e) => {
e.preventDefault();
document.querySelector('.loader--overlay').style.display = 'block';
req.open('POST', url, true);
req.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
req.send('playerName=' + nameChosen);
})
}
// Call main function
main();
function onLoad() {
document.querySelector('.loader--overlay').style.display = 'none';
const response = this.responseText;
// If username isn't found
if (!response) {
document.querySelector('#refresh').style.display = 'none';
displayPlayerNotFound('Joueur introuvable');
return;
}
document.querySelector('#refresh').style.display = 'block';
createObject(JSON.parse(response));
}
function onError() {
console.log('error receiving async AJAX call');
}
/**
* Create an object in LocalStorage with the data we need to display
* @param JSONData : big JSON with all the data of the request to the server
*/
function createObject(JSONData) {
console.log('--- ALL INFOS ---')
console.log(JSONData);
const userStats = JSONData[0];
const rankedStats = JSONData[1];
const soloQStats = rankedStats !== null ? (rankedStats.queueType == 'RANKED_SOLO_5x5' ? rankedStats : JSONData[2]) : false;
const matches = JSONData[3].matches;
const matchesInfos = [];
// Loop on all matches
for (let i = 0; i < matches.length; i++) {
const currentMatch = matches[i];
let participantId;
for (let i = 0; i < currentMatch.participantIdentities.length; i++) {
if (currentMatch.participantIdentities[i].player.accountId === userStats.accountId)
participantId = currentMatch.participantIdentities[i].participantId;
}
const teamId = currentMatch.participants[participantId - 1].teamId;
let win = false;
for (let i = 0; i < currentMatch.teams.length; i++) {
if (currentMatch.teams[i].teamId === teamId) {
if (currentMatch.teams[i].win === 'Win')
win = true;
}
}
const map = maps[currentMatch.mapId];
let mode = gameModes[currentMatch.queueId];
if (!mode)
mode = 'Undefined gamemode';
const champion = currentMatch.participants[participantId - 1].championId;
const role = currentMatch.participants[participantId - 1].timeline.lane;
const timeAgo = timeDifference(currentMatch.gameCreation);
const time = secToTime(currentMatch.gameDuration);
const kills = currentMatch.participants[participantId - 1].stats.kills;
const deaths = currentMatch.participants[participantId - 1].stats.deaths;
const assists = currentMatch.participants[participantId - 1].stats.assists;
const level = currentMatch.participants[participantId - 1].stats.champLevel;
const items = [];
for (let i = 0; i < 6; i++) {
const currentItem = 'item' + i;
items.push(currentMatch.participants[participantId - 1].stats[currentItem]);
}
const gold = (currentMatch.participants[participantId - 1].stats.goldEarned / 1000).toFixed(1) + 'k';
const minions = currentMatch.participants[participantId - 1].stats.totalMinionsKilled + currentMatch.participants[participantId - 1].stats.neutralMinionsKilled;
matchesInfos.push({
result: win,
map: map,
gamemode: mode,
champ: champion,
role: role,
date: timeAgo,
time: time,
kills: kills,
deaths: deaths,
assists: assists,
level: level,
items: items,
gold: gold,
minions: minions
});
}
console.log(matchesInfos);
localInfos.accountId = userStats.accountId;
localInfos.matches = matchesInfos;
localInfos.profileIconId = userStats.profileIconId;
localInfos.name = userStats.name;
localInfos.level = userStats.summonerLevel;
localInfos.rank = soloQStats ? soloQStats.tier + ' ' + soloQStats.rank : 'Joueur non classé';
localInfos.rankImgLink = getRankImg(soloQStats);
localInfos.rankedWins = soloQStats ? soloQStats.wins : undefined;
localInfos.rankedLosses = soloQStats ? soloQStats.losses : undefined;
nameChosen = userStats.name;
console.log('====== Saved infos ======');
console.log(localInfos);
localStorage[nameChosen] = JSON.stringify(localInfos);
displayContent(localStorage[nameChosen]);
}
/**
* Display on the page all the dynamic content
* @param stringData : Stringify object with all datas
*/
function displayContent(stringData) {
const data = JSON.parse(stringData);
document.querySelector('.player__pp').style.background = 'url(https://cdn.valentinkaelin.ch/riot/profileicon/' + data.profileIconId + '.png) center/cover';
document.querySelector('.player__name').innerHTML = data.name;
document.querySelector('.player__level').innerHTML = data.level;
document.querySelector('.player__rank').innerHTML = data.rank;
document.querySelector('.player__rank-img').style.background = 'url(' + data.rankImgLink + ') center/cover';
document.querySelector('.player__ratio').innerHTML = data.rankedWins ? data.rankedWins + ' wins / ' + data.rankedLosses + ' losses' : "Joueur non classé";
const playerContainer = document.querySelector('.player');
const oldList = document.querySelector('.list-matches');
if (oldList)
oldList.parentNode.removeChild(oldList);
const matchesList = document.createElement('ul');
matchesList.className = 'list-matches';
playerContainer.appendChild(matchesList);
/* Loop on all matches */
data.matches.forEach(e => {
const li = createHTMLOneMatch(e);
matchesList.appendChild(li);
});
}
/**
* Return the HTML of one match
* @param e : Infos in JSON of the match
*/
function createHTMLOneMatch(e) {
const li = document.createElement('li');
li.className = e.result ? 'match win' : 'match lose';
const container = document.createElement('div');
container.className = 'content-container';
/* First col (champion/summoners) */
const first = document.createElement('div');
first.className = 'first';
const imgChamp = document.createElement('img');
const championName = championsId[e.champ];
imgChamp.setAttribute('src', 'https://cdn.valentinkaelin.ch/riot/champions/' + championName + '.png');
imgChamp.className = 'champion-icon';
const level = document.createElement('span');
level.className = 'level';
level.innerText = e.level;
const summonerSpells = document.createElement('div');
summonerSpells.className = 'summonerSpells';
const firstSpell = document.createElement('img');
firstSpell.setAttribute('src', 'https://cdn.valentinkaelin.ch/riot/spells/SummonerFlash.png');
firstSpell.className = 'spell-icon';
summonerSpells.appendChild(firstSpell);
const secondSpell = document.createElement('img');
secondSpell.setAttribute('src', 'https://cdn.valentinkaelin.ch/riot/spells/SummonerDot.png');
secondSpell.className = 'spell-icon';
summonerSpells.appendChild(secondSpell);
const name = document.createElement('span');
name.className = 'champion-name';
name.innerText = championName;
first.appendChild(imgChamp);
first.appendChild(level);
first.appendChild(summonerSpells);
first.appendChild(name);
/* Second col (gamemode) */
const second = document.createElement('div');
second.className = 'second';
const map = document.createElement('div');
map.className = 'map';
map.innerText = e.map;
const gamemode = document.createElement('div');
gamemode.className = 'gamemode';
gamemode.innerText = e.gamemode;
second.appendChild(map);
second.appendChild(gamemode);
/* Third col (items) */
const third = document.createElement('div');
third.className = 'third';
e.items.forEach(e => {
const img = document.createElement('div');
img.className = 'item ' + e;
if(e !== 0) {
const itemImage = itemsJSON.data[e].image;
img.style.background = `url('https://cdn.valentinkaelin.ch/riot/${itemImage.sprite}') -${itemImage.x}px -${itemImage.y}px`;
} else {
img.style.background = "url('https://cdn.valentinkaelin.ch/riot/items/0.png') 0% 0% / cover";
}
third.appendChild(img);
});
/* Fourth col (stats) */
const fourth = document.createElement('div');
fourth.className = 'fourth';
const score = document.createElement('div');
score.className = 'score';
score.innerText = e.kills + '/' + e.deaths + '/' + e.assists;
const goldFarm = document.createElement('div');
goldFarm.className = 'gold-farm';
const gold = document.createElement('div');
gold.className = 'gold';
gold.innerText = e.gold;
const farm = document.createElement('div');
farm.className = 'farm';
farm.innerText = e.minions;
goldFarm.appendChild(gold);
goldFarm.appendChild(farm);
const durationDate = document.createElement('div');
durationDate.className = 'duration-date';
const duration = document.createElement('div');
duration.className = 'duration';
duration.innerText = e.time;
const date = document.createElement('div');
date.className = 'date';
date.innerText = e.date;
durationDate.appendChild(duration);
durationDate.appendChild(date);
fourth.appendChild(score);
fourth.appendChild(goldFarm);
fourth.appendChild(durationDate);
/* End */
container.appendChild(first);
container.appendChild(second);
container.appendChild(third);
container.appendChild(fourth);
li.appendChild(container);
return li;
}
/**
* Display the information that the player has not be found
* @param text : String to display - error message
*/
function displayPlayerNotFound(text) {
document.querySelector('.player').innerHTML = `<h3>${text}</h3>`
}

124
server/server.js Normal file
View file

@ -0,0 +1,124 @@
require('dotenv').config()
const express = require('express')
const request = require('request');
const path = require('path');
const bodyParser = require('body-parser');
const rp = require('request-promise');
const Promise = require("bluebird");
const app = express()
// DEV
var cors = require('cors');
app.use(cors({origin: '*'}));
/* Global Variables */
const key = process.env.API_KEY;
let summonerID;
let accountID;
let username;
let JSONMatches;
let finalJSON = [];
/* Set Port */
app.set('port', (process.env.PORT || 5000))
/* To retrieve data of post request */
app.use(bodyParser.json()); // to support JSON-encoded bodies
app.use(bodyParser.urlencoded({ // to support URL-encoded bodies
extended: true
}));
// /* Homepage */
// app.get('/', function (request, response) {
// response.sendFile(path.join(__dirname, 'home.html'));
// });
// /* Summoners pages */
// app.get('/summoners', function (request, response) {
// response.sendFile(path.join(__dirname, 'summoner.html'));
// });
// /* Public assets folder */
// app.use('/public', express.static(__dirname + '/public'));
/* Launch app */
app.listen(app.get('port'), () => console.log(`RiotAPI app listening on port ${app.get('port')}!`))
// Send data of a summoner
app.post('/api', function (req, res) {
console.log('API Request');
console.log(req.body.summoner);
//console.log(req.body.playerName);
console.time('all')
username = req.body.summoner;
finalJSON = [];
getAccountInfos(res);
});
// Get account infos of an username
const getAccountInfos = function (res) {
request('https://euw1.api.riotgames.com/lol/summoner/v4/summoners/by-name/' + encodeURIComponent(username) + '?api_key=' + key, function (error, response, body) {
if (!error && response.statusCode == 200) {
let JSONBody = JSON.parse(body);
summonerID = JSONBody.id;
accountID = JSONBody.accountId;
finalJSON.push(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://euw1.api.riotgames.com/lol/league/v4/positions/by-summoner/' + summonerID + '?api_key=' + key, function (error, response, body) {
if (!error && response.statusCode == 200) {
let JSONBody = JSON.parse(body);
if (JSONBody.length > 0) {
finalJSON.push(...JSONBody);
if (JSONBody.length === 1) finalJSON.push(null);
} else {
console.log('empty rank stats')
finalJSON.push(null, null);
}
getMatches(res);
}
})
}
// Get 10 matches of an accountID
const getMatches = function (res) {
console.time('getMatches');
request('https://euw1.api.riotgames.com/lol/match/v4/matchlists/by-account/' + accountID + '?endIndex=10&api_key=' + key, function (error, response, body) {
if (!error && response.statusCode == 200) {
JSONMatches = JSON.parse(body);
const matchsId = JSONMatches.matches.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');
finalJSON.push(JSONMatches)
res.send(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://euw1.api.riotgames.com/lol/' + urlApi + '?api_key=' + key, json: true }).then(function (obj) {
JSONMatches.matches = JSONMatches.matches.map((match) => match.gameId === obj.gameId ? obj : match);
});
}

108
server/summoner.html Normal file
View file

@ -0,0 +1,108 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Riot Api Node</title>
<link href="https://cdn.jsdelivr.net/npm/tailwindcss/dist/tailwind.min.css" rel="stylesheet">
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.6.3/css/all.css">
<!-- Custom CSS -->
<link rel="stylesheet" href="public/style.css">
</head>
<body class="font-sans bg-grey-lighter">
<div class="loader--overlay">
<div class="loader-container">
<div class="LoaderBalls">
<div class="LoaderBalls__item"></div>
<div class="LoaderBalls__item"></div>
<div class="LoaderBalls__item"></div>
</div>
</div>
</div>
<button class="debug"></button>
<div class="search">
<div class="container mx-auto">
<form class="flex items-center mb-6" id="changeName" method="get" action="summoners">
<input type="search" class="hadow appearance-none border rounded w-full py-2 px-3 text-grey-darker leading-tight focus:outline-none focus:shadow-outline mr-1" id="name" name="username" placeholder="Pseudo du Joueur">
<button type="submit" class="bg-white hover:bg-grey-lightest text-grey-darkest font-semibold py-2 px-4 mr-1 border border-grey-light rounded shadow">
Chercher
</button>
<button id="refresh" class="bg-white hover:bg-grey-lightest text-grey-darkest font-semibold py-2 px-4 border border-grey-light rounded shadow">
<i class="fas fa-sync"></i>
</button>
</form>
</div>
</div>
<div class="container mx-auto pb-16">
<div class="player shadow-md">
<div class="player__pp"></div>
<h1 class="player__name">Default name</h1>
<h3 class="player__level">Default level</h3>
<h3 class="player__rank">Default division</h3>
<div class="player__rank-img"></div>
<h3 class="player__ratio">Default ratio</h3>
<!--<ul class="list-matches--debug">
<li class="match">
<div class="content-container">
<div class="first">
<img src="/public/img/champions/Vayne.png" class="champion-img" alt="example design">
<span class="level">17</span>
<div class="summonerSpells">
<img class="spell-icon" src="https://cdn.valentinkaelin.ch/riot/spells/SummonerFlash.png" alt="Flash">
<img class="spell-icon" src="https://cdn.valentinkaelin.ch/riot/spells/SummonerDot.png" alt="Ignite">
</div>
<span class="champion-name">Vayne</span>
</div>
<div class="second">
<div class="map">Summoner's Rift</div>
<div class="gamemode">Normal (Draft Mode)</div>
</div>
<div class="third">
<img src="https://cdn.valentinkaelin.ch/riot/items/3140.png" class="item" alt="example design">
<img src="https://cdn.valentinkaelin.ch/riot/items/3153.png" class="item" alt="example design">
<img src="https://cdn.valentinkaelin.ch/riot/items/3031.png" class="item" alt="example design">
<img src="https://cdn.valentinkaelin.ch/riot/items/3124.png" class="item" alt="example design">
<img src="https://cdn.valentinkaelin.ch/riot/items/3094.png" class="item" alt="example design">
<img src="https://cdn.valentinkaelin.ch/riot/items/3006.png" class="item" alt="example design">
<img src="https://cdn.valentinkaelin.ch/riot/items/3363.png" class="item" alt="example design">
</div>
<div class="fourth">
<div class="score">8/6/9</div>
<div class="gold-farm">
<div class="gold">16.2k</div>
<div class="farm">227</div>
</div>
<div class="duration-date">
<div class="duration">40:31</div>
<div class="date">1/12/2018</div>
</div>
</div>
</div>
</li>
</ul>-->
</div>
</div>
<script src="public/data.js"></script>
<script src="public/functions.js"></script>
<script src="public/summoner.js"></script>
</body>
</html>