const snekfetch = require('snekfetch');
const Package = require('../package.json');
const Util = require('./util/Util');
const Player = require('./Player');
const Match = require('./matches/Match');
const Status = require('./Status');
const Season = require('./Season');
const Tournament = require('./Tournament');
const PlayerSeason = require('./playerseason/PlayerSeason');
/**
* The main hub for interacting with the pubg api, and starting point for any api instance
* @class Client
* @param {string} key PUBG app api token
* @param {string} [defaultShard='pc-oc'] Default shard to use if none provided in methods
*/
class Client {
constructor(key, defaultShard = 'pc-oc') {
if (!key) {
throw new Error('No API key passed.');
}
/**
* The api key passed into the client
* @type {string}
*/
this.key = key;
/**
* The default shard for the client if none provided
*/
this.defaultShard = defaultShard;
}
/**
* Get player by the given id or name
* @param {Object} args Specify what player to get
* * {id: ['id1', 'id2']}
* * {id: 'id'}
* * {name: 'name'}
* * {name: ['name1', 'name2']}
* @param {string} [shard=this.defaultShard] The server shard to send the request to
* @returns {Promise<Array<Player>>|Promise<Player>}
* @memberof Client
*/
getPlayer(args, shard = this.defaultShard) {
if (typeof args !== 'object' || typeof shard !== 'string') throw new Error('Requires (object, !string)');
if (args.id) {
return this._baseRequest({ endpoint: Array.isArray(args.id) ? 'players' : `players/${args.id}`, shard, query: Array.isArray(args.id) ? { 'filter[playerIds]': args.id.join(',') } : {} })
.then(players => Array.isArray(players.data) ? players.data.length === 1 ? new Player(players.data[0], this) : players.data.map(p => new Player(p, this)) : new Player(players.data, this))
.catch(e => Promise.reject(e.body.errors));
}
if (args.name) {
return this._baseRequest({ endpoint: 'players', shard, query: { 'filter[playerNames]': Array.isArray(args.name) ? args.name.join(',') : args.name } })
.then(players => Array.isArray(players.data) ? players.data.length === 1 ? new Player(players.data[0], this) : players.data.map(p => new Player(p, this)) : new Player(players.data, this))
.catch(e => Promise.reject(e.body.errors));
}
return Promise.reject(new Error('Invalid use of <Client>.getPlayer()'));
}
/**
* Get an array of all seasons of the shard
* @param {string} [shard=this.defaultShard] The server shard to send the request to
* @returns {Promise<Array<Season>>}
* @memberof Client
*/
getSeasons(shard = this.defaultShard) {
return this._baseRequest({ endpoint: 'seasons', shard })
.then(seasons => seasons.data.map(s => new Season(s, this)));
}
/**
* Get a player season object
* @param {(string|Player)} player The player of the player season
* @param {(string|Season)} season The season of the player season
* @param {string} [shard=player.attributes.shardId|this.defaultShard] The server shard to send the request to
* @returns {Promise<PlayerSeason>}
* @memberof Client
*/
getPlayerSeason(player, season, shard) {
return this._baseRequest({ endpoint: `players/${player instanceof Player ? player.id : player}/seasons/${season instanceof Season ? season.id : season}`, shard: player instanceof Player ? player.attributes.shardId : shard || this.defaultShard })
.then(ps => new PlayerSeason(ps.data));
}
/**
* Get a match from a match id
* @param {string} id Id of the match to get
* @param {string} [shard=this.defaultShard] The server shard to send the request to
* @returns {Promise<Match>}
* @memberof Client
*/
getMatch(id, shard = this.defaultShard) {
if (typeof id !== 'string' || typeof shard !== 'string') throw new Error('Requires (string, !string)');
return this._baseRequest({ endpoint: `matches/${id}`, shard })
.then(match => new Match(match.data, this, match.included))
.catch(e => Promise.reject(e.body.errors));
}
/**
* Gets the status of the api
* @returns {Promise<Status>}
* @memberof Client
*/
getStatus() {
return this._baseRequest({ endpoint: 'status' })
.then(status => new Status(status.data))
.catch(e => Promise.reject(e.body.errors));
}
/**
* Gets a list of all tournaments
* @returns {Promise<Array<Tournament>>}
* @memberof Client
*/
getTournaments() {
return this._baseRequest({ endpoint: 'tournaments' })
.then(tournaments => tournaments.data.map(t => new Tournament(t, this)))
.catch(e => Promise.reject(e));
}
/**
* Gets the tournament with the matching id
* @param {string} id Tournament ID
* @returns {Promise<Tournament>}
* @memberof Client
*/
getTournament(id) {
return this._baseRequest({ endpoint: `tournaments/${id}` })
.then(tournament => new Tournament(tournament.data))
.catch(e => Promise.reject(e.body.errors));
}
/**
* Gets a list of all past matches from the api
* @param {Date} [createdAt] The starting search date for the matches
* @param {string} [shard=this.defaultShard] The server shard to send the request to
* @returns {Promise<Array<Match>>}
* @memberof Client
*/
getSamples(createdAt, shard = this.defaultShard) {
return this._baseRequest({ endpoint: 'samples', shard, query: createdAt instanceof Date ? { 'filter[createdAt]': createdAt.toISOString() } : {} })
.then(samples => samples.data.relationships.matches.data.map(m => new Match(m.id, this)))
.catch(e => Promise.reject(e.body.errors));
}
/**
* Fetches telemetry data object
* @param {string} url URL of the telemetry object
* @returns {Promise<Object>}
* @memberof Client
*/
getTelemetry(url) {
if (!url || typeof url !== 'string') throw new Error('Requires (string)');
return this._baseRequest({ url });
}
/**
* Carries out a basic http request to the api
* @private
* @param {Object} options Object describing request
* @param {string} options.endpoint Endpoint to hit of the api
* @param {string} options.shard The server shard to send the request to
* @param {Object} [options.query={}] Snekfetch options
* @returns {Promise<Object>}
* @memberof Client
*/
_baseRequest(options = {}) {
const url = options.url || Util.constructURL(options.endpoint, options.shard);
if (!url) throw new Error('Invalid shard');
return snekfetch.get(url)
.set(this._headers)
.query(options.query || {})
.then(r => r.body);
}
get _headers() {
return {
'User-Agent': `pubg.js v${Package.version} (${Package.homepage})`,
accept: 'application/json',
Authorization: `Bearer ${this.key}`,
};
}
}
module.exports = Client;