238 lines
6.5 KiB
JavaScript
238 lines
6.5 KiB
JavaScript
'use strict';
|
|
|
|
const http = require('http');
|
|
const querystring = require('querystring');
|
|
const zlib = require('zlib');
|
|
|
|
class Request {
|
|
_request(options) {
|
|
return new Promise((resolve, reject) => {
|
|
http.get(options, (response) => {
|
|
const { statusCode } = response;
|
|
const contentType = response.headers['content-type'];
|
|
|
|
let error;
|
|
if (statusCode !== 200) {
|
|
error = new Error(`Request Failed.\nStatus Code: ${statusCode}`);
|
|
} else if (!/^application\/json/.test(contentType)) {
|
|
error = new Error(`Invalid content-type.\nExpected application/json but received ${contentType}`);
|
|
}
|
|
if (error) {
|
|
response.resume();
|
|
reject(error);
|
|
return;
|
|
}
|
|
|
|
let rawData = '';
|
|
|
|
const gunzip = zlib.createGunzip();
|
|
gunzip.on('data', (chunk) => {
|
|
rawData += chunk;
|
|
}).on('end', () => {
|
|
try {
|
|
const parsedData = JSON.parse(rawData);
|
|
resolve(parsedData);
|
|
} catch (e) {
|
|
reject(e);
|
|
}
|
|
});
|
|
|
|
response.pipe(gunzip);
|
|
}).on('error', (e) => {
|
|
reject(e);
|
|
});
|
|
});
|
|
}
|
|
}
|
|
|
|
module.exports = class ShiftStats extends Request {
|
|
constructor(apiKey) {
|
|
super();
|
|
this.apiKey = apiKey || 'YXBpLnNoaWZ0c3RhdHMuY29tLDE5YjhhZGIwNDVjZjAxMzJhM2E5N2VmZDQ1YTRj';
|
|
}
|
|
|
|
_request(options) {
|
|
return super._request({
|
|
hostname: 'api.shiftstats.com',
|
|
path: this._url(options.url, options.query),
|
|
headers: options.headers || this._headers(),
|
|
});
|
|
}
|
|
|
|
_basicHeaders() {
|
|
return {
|
|
Accept: 'application/json',
|
|
'Content-Type': 'application/json',
|
|
'X-Requested-With': 'com.digitalshift.hockeyshift',
|
|
'Accept-Language': 'en-US',
|
|
'Accept-Encoding': 'gzip,deflate',
|
|
Connection: 'keep-alive',
|
|
};
|
|
}
|
|
|
|
_headers() {
|
|
if (typeof this.headersWithTicket === 'undefined') {
|
|
this.headersWithTicket = Object.assign({
|
|
Authorization: `StatsAuth ticket="${this.ticketHash}"`,
|
|
}, this._basicHeaders());
|
|
}
|
|
|
|
return this.headersWithTicket;
|
|
}
|
|
|
|
_url(path, query) {
|
|
return `/${path}?${querystring.stringify(query)}`;
|
|
}
|
|
|
|
_gameSubpath(gameId, path, only) {
|
|
if (only === 'home') {
|
|
path = `home_${path}`;
|
|
} else if (only === 'away') {
|
|
path = `away_${path}`;
|
|
}
|
|
return this._request({ url: `game/${gameId}/${path}` });
|
|
}
|
|
|
|
login() {
|
|
return this._request({ url: 'login', query: {key: this.apiKey}, headers: this._basicHeaders() }).then((json) => {
|
|
this.ticketHash = json.ticket.hash;
|
|
return json;
|
|
});
|
|
}
|
|
|
|
leagues() {
|
|
return this._request({ url: 'leagues' });
|
|
}
|
|
|
|
league(leagueId) {
|
|
return this._request({ url: `league/${leagueId}` });
|
|
}
|
|
|
|
leagueSeasons(leagueId) {
|
|
return this._request({ url: `league/${leagueId}/seasons` });
|
|
}
|
|
|
|
leagueSuspensions(leagueId, onlyActive = true) {
|
|
let query = {};
|
|
if (onlyActive) {
|
|
query.status = 'active';
|
|
}
|
|
return this._request({ url: `league/${leagueId}/suspensions`, query: query });
|
|
}
|
|
|
|
teamSearch(sport, name) {
|
|
return this._request({ url: 'teams', query: {name: name, not_ended: true, sport: sport.toLowerCase()} });
|
|
}
|
|
|
|
teamSchedule(teamId) {
|
|
return this._request({ url: `team/${teamId}/games`, query: {future: true, today: true, past: true} });
|
|
}
|
|
|
|
teamPlayersList(teamId) {
|
|
return this._request({ url: `team/${teamId}/players`, query: {status: 'active'} });
|
|
}
|
|
|
|
teamsInDivision(divisionName, leagueId, currentSeason = true) {
|
|
return this._request({ url: 'teams', query: {
|
|
division: divisionName,
|
|
league_id: leagueId,
|
|
not_ended: currentSeason,
|
|
} });
|
|
}
|
|
|
|
teamGames(teamId, includeFuture = true, includeToday = true) {
|
|
return this._request({ url: `team/${teamId}/games`, query: {future: includeFuture, today: includeToday} });
|
|
}
|
|
|
|
teamGamesForStatus(teamId, status = 'Final,In Progress,Forfeit') {
|
|
return this._request({ url: `team/${teamId}/games`, query: {status: status} });
|
|
}
|
|
|
|
teamPractices(teamId, includeFuture = true, includeToday = true) {
|
|
return this._request({ url: `team/${teamId}/practices`, query: {future: includeFuture, today: includeToday} });
|
|
}
|
|
|
|
teamSuspensions(teamId, onlyActive = true) {
|
|
let query = {};
|
|
if (onlyActive) {
|
|
query.status = 'active';
|
|
}
|
|
return this._request({ url: `team/${teamId}/suspensions`, query: query });
|
|
}
|
|
|
|
game(gameId) {
|
|
return this._request({ url: `game/${gameId}` });
|
|
}
|
|
|
|
// only is 'home' or 'away', optional
|
|
gameGoals(gameId, only = null) {
|
|
return this._gameSubpath(gameId, 'goals', only);
|
|
}
|
|
|
|
// only is 'home' or 'away', optional
|
|
gameGoalies(gameId, only = null) {
|
|
return this._gameSubpath(gameId, 'goalies', only);
|
|
}
|
|
|
|
// only is 'home' or 'away', optional
|
|
gamePenalties(gameId, only = null) {
|
|
return this._gameSubpath(gameId, 'penalties', only);
|
|
}
|
|
|
|
// only is 'home' or 'away', optional
|
|
gameRoster(gameId, only = null) {
|
|
return this._gameSubpath(gameId, 'roster', only);
|
|
}
|
|
|
|
divisionGamesList(divisionId) {
|
|
return this._request({ url: `division/${divisionId}/games` });
|
|
}
|
|
|
|
// type is 'Regular Season', 'Playoffs', or 'Exhibition', required
|
|
divisionStandings(divisionId, type = 'Regular Season') {
|
|
return this._request({ url: `division/${divisionId}/standings`, query: {type: type} });
|
|
}
|
|
|
|
divisionTeams(divisionId) {
|
|
return this._request({ url: `division/${divisionId}/teams` });
|
|
}
|
|
|
|
// type is 'Regular Season', 'Playoffs', or 'Exhibition', required
|
|
// limit, required
|
|
// metrics, required
|
|
divisionLeaders(divisionId, type = 'Regular Season', limit = 20, metrics = [
|
|
'points', 'goals', 'assists', 'goals_against_average', 'save_percentage',
|
|
'wins', 'shutouts', 'number_first_stars', 'number_stars',
|
|
]) {
|
|
return this._request({ url: `division/${divisionId}/leaders`, query: {
|
|
limit: limit,
|
|
metrics: metrics.join(','),
|
|
type: type,
|
|
} });
|
|
}
|
|
|
|
divisionSuspensions(divisionId, onlyActive = true) {
|
|
let query = {};
|
|
if (onlyActive) {
|
|
query.status = 'active';
|
|
}
|
|
return this._request({ url: `division/${divisionId}/suspensions`, query: query });
|
|
}
|
|
|
|
season(seasonId) {
|
|
return this._request({ url: `season/${seasonId}` });
|
|
}
|
|
|
|
seasonDivisionsList(seasonId) {
|
|
return this._request({ url: `season/${seasonId}/divisions` });
|
|
}
|
|
|
|
seasonSuspensions(seasonId, onlyActive = true) {
|
|
let query = {};
|
|
if (onlyActive) {
|
|
query.status = 'active';
|
|
}
|
|
return this._request({ url: `season/${seasonId}/suspensions`, query: query });
|
|
}
|
|
};
|