diff --git a/example.js b/example.js index 83128bd..236b223 100644 --- a/example.js +++ b/example.js @@ -1,8 +1,11 @@ const ShiftRequest = require('./index') let s = new ShiftRequest() +// with promises s.login().then(() => { return s.divisionStandings(4702) -}).then((standings) => { +}).then(async (standings) => { console.log(standings.teams) + // with async/await + console.log((await s.gameGoals(166658, 'home')).home_goals) }) diff --git a/index.js b/index.js index f39c7a4..7299af0 100644 --- a/index.js +++ b/index.js @@ -43,7 +43,7 @@ class Request { } } -module.exports = class ShiftRequest extends Request { +module.exports = class ShiftStats extends Request { constructor(apiKey) { super() this.apiKey = apiKey || 'YXBpLnNoaWZ0c3RhdHMuY29tLDE5YjhhZGIwNDVjZjAxMzJhM2E5N2VmZDQ1YTRj' @@ -80,6 +80,15 @@ module.exports = class ShiftRequest extends Request { 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 @@ -87,7 +96,127 @@ module.exports = class ShiftRequest extends Request { }) } + 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}}) + 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 }) } } diff --git a/package.json b/package.json index 3db6dd3..1cf3b93 100644 --- a/package.json +++ b/package.json @@ -1,17 +1,33 @@ { "name": "node-digitalshift", "description": "Library for talking with DigitalShift network sites (HockeyShift, BasketballShift, etc.)", - "version": "0.0.1", + "version": "1.0.0", "main": "index.js", "license": "MIT", "repository": "https://github.com/parnic/node-digitalshift.git", - "main": "index.js", "keywords": [ "digitalshift", "sports", + "stats", "hockey", - "hockeyshift" + "hockeyshift", + "basketball", + "basketballshift", + "soccer", + "soccershift", + "lacrosse", + "lacrosseshift", + "football", + "footballshift", + "baseball", + "baseballshift" ], - "dependencies": { + "devDependencies": { + "chai": "^4.1.2", + "chai-as-promised-compat": "^7.0.3", + "mocha": "^5.1.1" + }, + "scripts": { + "test": "mocha test/**.spec.js" } } diff --git a/test/shift.spec.js b/test/shift.spec.js new file mode 100644 index 0000000..d83509a --- /dev/null +++ b/test/shift.spec.js @@ -0,0 +1,297 @@ +'use strict' + +const ShiftStats = require('../index') + +const chai = require('chai') +let expect = chai.expect + +const chaiAsPromised = require("chai-as-promised-compat") +chai.use(chaiAsPromised) + +describe('ShiftStats', () => { + describe('bad api key', () => { + it('throws an error', () => { + let s = new ShiftStats('a') + expect(s.login()).to.be.rejected + }) + }) + + describe('with valid api key', function() { + this.timeout(0) + + let s = new ShiftStats() + before(async () => { + await s.login() + }) + + context('teamSearch', () => { + let teamSearch + before(async () => { + teamSearch = await s.teamSearch('hockey', 'bears') + }) + + it('returns some teams', () => { + expect(teamSearch).to.have.property('teams') + expect(teamSearch.teams).to.be.an('array') + }) + + it('finds the right team', () => { + let bears = teamSearch.teams.find(team => team.id == 18827) + expect(bears).to.have.property('id') + }) + }) + + context('teamSchedule', () => { + let teamSchedule + before(async () => { + teamSchedule = await s.teamSchedule(18827) + }) + + it('returns a schedule', () => { + expect(teamSchedule).to.have.property('games') + }) + }) + + context('teamPlayersList', () => { + let ret + before(async () => { + ret = await s.teamPlayersList(18827) + }) + + it('returns players', () => { + expect(ret).to.have.property('players') + }) + }) + + context('divisionGamesList', () => { + let ret + before(async () => { + ret = await s.divisionGamesList(3057) + }) + + it('returns a list of games', () => { + expect(ret).to.have.property('games') + }) + }) + + context('seasonDivisionsList', () => { + let ret + before(async () => { + ret = await s.seasonDivisionsList(741) + }) + + it('returns a list of divisions', () => { + expect(ret).to.have.property('divisions') + }) + }) + + context('seasonSuspensions', () => { + let ret + before(async () => { + ret = await s.seasonSuspensions(741, false) + }) + + it('returns a list of suspensions', () => { + expect(ret).to.have.property('suspensions') + }) + }) + + context('leagues', () => { + let ret + before(async () => { + ret = await s.leagues() + }) + + it('returns a list of leagues', () => { + expect(ret).to.have.property('leagues') + }) + }) + + context('league', () => { + let ret + before(async () => { + ret = await s.league(3) + }) + + it('returns a league', () => { + expect(ret).to.have.property('league') + }) + }) + + context('leagueSeasons', () => { + let ret + before(async () => { + ret = await s.leagueSeasons(3) + }) + + it('returns a list of seasons', () => { + expect(ret).to.have.property('seasons') + }) + }) + + context('leagueSeasons', () => { + let ret + before(async () => { + ret = await s.leagueSuspensions(3, true) + }) + + it('returns a list of suspensions', () => { + expect(ret).to.have.property('suspensions') + }) + }) + + context('teamsInDivision', () => { + let ret + before(async () => { + ret = await s.teamsInDivision('XPL', 317, true) + }) + + it('returns a list of teams', () => { + expect(ret).to.have.property('teams') + }) + }) + + context('teamGames', () => { + let ret + before(async () => { + ret = await s.teamGames(1, true, true) + }) + + it('returns a list of games', () => { + expect(ret).to.have.property('games') + }) + }) + + context('teamGamesForStatus', () => { + let ret + before(async () => { + ret = await s.teamGamesForStatus(1, 'Final,In Progress') + }) + + it('returns a list of games', () => { + expect(ret).to.have.property('games') + }) + }) + + context('teamPractices', () => { + let ret + before(async () => { + ret = await s.teamPractices(18827, true, true) + }) + + it('returns a list of practices', () => { + expect(ret).to.have.property('practices') + }) + }) + + context('teamSuspensions', () => { + let ret + before(async () => { + ret = await s.teamSuspensions(18827, false) + }) + + it('returns a list of suspensions', () => { + expect(ret).to.have.property('suspensions') + }) + }) + + context('game', () => { + let ret + before(async () => { + ret = await s.game(128740) + }) + + it('returns game info', () => { + expect(ret).to.have.property('game') + }) + }) + + context('gameGoals', () => { + let ret + before(async () => { + ret = await s.gameGoals(128740, 'away') + }) + + it('returns a list of away goals', () => { + expect(ret).to.have.property('away_goals') + }) + }) + + context('gameGoalies', () => { + let ret + before(async () => { + ret = await s.gameGoalies(128740, 'away') + }) + + it('returns a list of away goalies', () => { + expect(ret).to.have.property('away_goalies') + }) + }) + + context('gamePenalties', () => { + let ret + before(async () => { + ret = await s.gamePenalties(128740, 'away') + }) + + it('returns a list of away penalties', () => { + expect(ret).to.have.property('away_penalties') + }) + }) + + context('gameRoster', () => { + let ret + before(async () => { + ret = await s.gameRoster(128740, 'away') + }) + + it('returns an away roster', () => { + expect(ret).to.have.property('away_roster') + }) + }) + + context('divisionStandings', () => { + let ret + before(async () => { + ret = await s.divisionStandings(3057, 'Regular Season') + }) + + it('returns ranked list of teams', () => { + expect(ret).to.have.property('teams') + }) + }) + + context('divisionTeams', () => { + let ret + before(async () => { + ret = await s.divisionTeams(3057) + }) + + it('returns a list of teams', () => { + expect(ret).to.have.property('teams') + }) + }) + + context('divisionLeaders', () => { + let ret + before(async () => { + ret = await s.divisionLeaders(3057, 'Regular Season', 5, ['points', 'goals', 'assists']) + }) + + it('returns a list of leaders', () => { + expect(ret).to.have.property('leaders') + }) + }) + + context('divisionSuspensions', () => { + let ret + before(async () => { + ret = await s.divisionSuspensions(3057, false) + }) + + it('returns a list of suspensions', () => { + expect(ret).to.have.property('suspensions') + }) + }) + }) +})