Refactor SplatNet API

This commit is contained in:
Unknown
2017-11-18 18:14:13 -08:00
committed by Matt Isenhower
parent 8bcb4a35fc
commit 1f19c3ba3c
4 changed files with 129 additions and 117 deletions

View File

@@ -7,98 +7,96 @@ const axios = require('axios');
const userAgent = process.env.SPLATNET_USER_AGENT;
const splatnetBaseUrl = 'https://app.splatoon2.nintendo.net';
function createApiClient(sessionId) {
return axios.create({
baseURL: `${splatnetBaseUrl}/api/`,
headers: {
'User-Agent': userAgent,
'Cookie': `iksm_session=${sessionId}`,
},
});
class SplatNet {
constructor(region = 'NA', language = 'en-US') {
this.region = region;
this.language = language;
}
getSessionId() {
switch (this.region) {
case 'NA': return process.env.NINTENDO_SESSION_ID_NA;
case 'EU': return process.env.NINTENDO_SESSION_ID_EU;
case 'JP': return process.env.NINTENDO_SESSION_ID_JP;
}
}
getClient() {
return axios.create({
baseURL: `${splatnetBaseUrl}/api/`,
headers: {
'User-Agent': userAgent,
'Cookie': `iksm_session=${this.getSessionId()}`,
'Accept-Language': this.language,
},
});
}
async getResponse(path) {
let response = await this.getClient().get(path);
return response.data;
}
getSchedules() {
return this.getResponse('schedules');
}
getCoopSchedules() {
return this.getResponse('coop_schedules');
}
getTimeline() {
return this.getResponse('timeline');
}
getActiveFestivals() {
return this.getResponse('festivals/active');
}
getPastFestivals() {
return this.getResponse('festivals/pasts');
}
async getCombinedFestivals() {
let active = await this.getActiveFestivals();
let past = await this.getPastFestivals();
return {
festivals: active.festivals.concat(past.festivals),
results: past.results,
};
}
getMerchandises() {
return this.getResponse('onlineshop/merchandises');
}
getLeagueMatchRanking(year, month, day, hour, type = 'T', region = 'ALL') {
// Hour should be in multiples of 2, e.g., 00, 02, 04, ..., 22.
// Type should be 'T' (team) or 'P' (pair).
// Region should be 'ALL', 'JP', 'US', or 'EU'.
// Make sure year is specified as two digits
year = year % 100;
// Make sure we have leading zeros
year = ('0' + year).substr(-2);
month = ('0' + month).substr(-2);
day = ('0' + day).substr(-2);
hour = ('0' + hour).substr(-2);
return this.getResponse(`league_match_ranking/${year}${month}${day}${hour}${type}/${region}`);
}
getResults(id = null, region = 'NA') {
let url = (id) ? `results/${id}` : 'results';
return this.getResponse(url);
}
async getImage(imagePath) {
let response = await axios.get(`${splatnetBaseUrl}${imagePath}`, { responseType: 'arraybuffer', headers: { 'User-Agent': userAgent } });
return response.data;
}
}
const api = {
NA: createApiClient(process.env.NINTENDO_SESSION_ID_NA),
EU: createApiClient(process.env.NINTENDO_SESSION_ID_EU),
JP: createApiClient(process.env.NINTENDO_SESSION_ID_JP),
}
async function getSchedules(region = 'NA') {
let response = await api[region].get('schedules');
return response.data;
}
async function getCoopSchedules(region = 'NA') {
let response = await api[region].get('coop_schedules');
return response.data;
}
async function getTimeline(region = 'NA') {
let response = await api[region].get('timeline');
return response.data;
}
async function getActiveFestivals(region = 'NA') {
let response = await api[region].get('festivals/active');
return response.data;
}
async function getPastFestivals(region = 'NA') {
let response = await api[region].get('festivals/pasts');
return response.data;
}
async function getCombinedFestivals(region = 'NA') {
let active = await getActiveFestivals(region);
let past = await getPastFestivals(region);
return {
festivals: active.festivals.concat(past.festivals),
results: past.results,
};
}
async function getMerchandises(region = 'NA') {
let response = await api[region].get('onlineshop/merchandises');
return response.data;
}
async function getLeagueMatchRanking(year, month, day, hour, type = 'T', region = 'ALL', apiRegion = 'NA') {
// Hour should be in multiples of 2, e.g., 00, 02, 04, ..., 22.
// Type should be 'T' (team) or 'P' (pair).
// Region should be 'ALL', 'JP', 'US', or 'EU'.
// Make sure year is specified as two digits
year = year % 100;
// Make sure we have leading zeros
year = ('0' + year).substr(-2);
month = ('0' + month).substr(-2);
day = ('0' + day).substr(-2);
hour = ('0' + hour).substr(-2);
let response = await api[apiRegion].get(`league_match_ranking/${year}${month}${day}${hour}${type}/${region}`);
return response.data;
}
async function getResults(id = null, region = 'NA') {
let url = (id) ? `results/${id}` : 'results';
let response = await api[region].get(url);
return response.data;
}
async function getImage(imagePath) {
let response = await axios.get(`${splatnetBaseUrl}${imagePath}`, { responseType: 'arraybuffer', headers: { 'User-Agent': userAgent } });
return response.data;
}
module.exports = {
getSchedules,
getCoopSchedules,
getTimeline,
getCombinedFestivals,
getMerchandises,
getLeagueMatchRanking,
getResults,
getImage,
}
module.exports = SplatNet;

View File

@@ -1,8 +1,8 @@
require('./bootstrap');
const splatnet = require('./splatnet');
const Updater = require('./updaters/Updater');
const OriginalGearImageUpdater = require('./updaters/OriginalGearImageUpdater');
const FestivalsUpdater = require('./updaters/FestivalsUpdater');
const updaters = [
// Original gear images
@@ -12,7 +12,7 @@ const updaters = [
new Updater({
name: 'Schedules',
filename: 'schedules.json',
request: () => splatnet.getSchedules(),
request: (splatnet) => splatnet.getSchedules(),
imagePaths: [
'$..stage_a.image',
'$..stage_b.image',
@@ -23,7 +23,7 @@ const updaters = [
new Updater({
name: 'Co-op Schedules',
filename: 'coop-schedules.json',
request: () => splatnet.getCoopSchedules(),
request: (splatnet) => splatnet.getCoopSchedules(),
imagePaths: [
'$..stage.image',
'$..weapons[*].image',
@@ -34,7 +34,7 @@ const updaters = [
new Updater({
name: 'Timeline',
filename: 'timeline.json',
request: () => splatnet.getTimeline(),
request: (splatnet) => splatnet.getTimeline(),
rootKeys: ['coop', 'weapon_availability'],
imagePaths: [
'$.coop..gear.image',
@@ -46,29 +46,13 @@ const updaters = [
}),
// Festivals
new Updater({
name: 'Festivals',
filename: 'festivals.json',
async request() {
return {
na: await splatnet.getCombinedFestivals('NA'),
eu: await splatnet.getCombinedFestivals('EU'),
jp: await splatnet.getCombinedFestivals('JP'),
};
},
imagePaths: [
'$..images.alpha',
'$..images.bravo',
'$..images.panel',
'$..special_stage.image',
],
}),
new FestivalsUpdater,
// Merchandises
new Updater({
name: 'Merchandises',
filename: 'merchandises.json',
request: () => splatnet.getMerchandises(),
request: (splatnet) => splatnet.getMerchandises(),
rootKeys: ['merchandises'],
imagePaths: [
'$..gear.image',

View File

@@ -0,0 +1,28 @@
const Updater = require('./Updater');
const SplatNet = require('../splatnet');
class FestivalsUpdater extends Updater {
constructor() {
super({
name: 'Festivals',
filename: 'festivals.json',
request: (splatnet) => splatnet.getCombinedFestivals(),
imagePaths: [
'$..images.alpha',
'$..images.bravo',
'$..images.panel',
'$..special_stage.image',
],
});
}
async getData() {
return {
na: await this.options.request(new SplatNet('NA')),
eu: await this.options.request(new SplatNet('EU')),
jp: await this.options.request(new SplatNet('JP')),
}
}
}
module.exports = FestivalsUpdater;

View File

@@ -2,7 +2,7 @@ const path = require('path');
const fs = require('fs');
const mkdirp = require('mkdirp');
const jsonpath = require('jsonpath');
const splatnet = require('../splatnet');
const SplatNet = require('../splatnet');
const raven = require('raven');
const dataPath = path.resolve('public/data');
@@ -36,7 +36,8 @@ class Updater {
}
getData() {
return this.options.request();
let splatnet = new SplatNet;
return this.options.request(splatnet);
}
async handleRequest(request) {
@@ -109,6 +110,7 @@ class Updater {
// Otherwise, download the image
try {
this.info(`Downloading image: ${imagePath}`);
let splatnet = new SplatNet;
let image = await this.handleRequest(splatnet.getImage(imagePath));
this.writeFile(localPath, image);
} catch (e) { }