GithubHelp home page GithubHelp logo

martinsileno / pubg-typescript-api Goto Github PK

View Code? Open in Web Editor NEW
11.0 4.0 9.0 119 KB

TypeScript wrapper on official PUBG API.

License: MIT License

TypeScript 100.00%
pubg pubg-api playerunknowns-battlegrounds pubg-typescript-api typescript-wrapper

pubg-typescript-api's Introduction

PUBG TypeScript API

Join the chat at https://gitter.im/pubg-typescript-api/Lobby npm version

Table of contents

About

Unofficial TypeScript wrapper on the official PUBG API.

Main features:

  • Simple to use
  • Maps API resources to easier-to-use "Models" (i.e. Player, Match, Participant, etc.)
  • Telemetry parsing
  • OOP design
  • Fully typed
  • Helps you win chicken dinners

Changelog

See releases tab on github.

Getting started

First, obtain an API key from PUBG Official API.

Then install the package with NPM:

npm install --save pubg-typescript-api

Usage example: player last match

As an example, let's make a command line utility to display some quick stats on a player's last match.

Import the module and define API_KEY with your own API key obtained from the official website. Obviously the required classes depend on what you're doing, but in this case we need these

import { Match, PlatformRegion, Player, PubgAPI } from 'pubg-typescript-api';

const API_KEY = 'YOUR_API_KEY_HERE';

First, instantiate the PubgAPI object, responsible for making requests to the API authenticated with your API key

const api = new PubgAPI(API_KEY, PlatformRegion.PC_EU);

here we used the Platform and Region PC_EU, but you're obviously free to change it to whatever you need. The possible values can be found in the PlatformRegion enum.

This object must be given to all methods that retrieve data from the API. For example, let's find the player corresponding to the username "martinsileno"

const players = await Player.filterByName(api, ['martinsileno']);
const player = players[0];
console.log(`Found player "${player.name}" with ID: ${player.id}`);

here we're awaiting on the Promise returned by filterByName, a function that returns a (promise of a) list of Players with the given names.

Now that we have our player's data, let's find stats on his/her last played match

const lastMatchId = player.matchIds[0];
const match = await Match.get(api, lastMatchId);
console.log(`Last played match on ${match.dateCreated} and lasted ${Math.round(match.duration / 60)} minutes, with ID: ${match.id}`);

here we extract the latest match ID from player.matchIds (it's sorted from newest to oldest) and then using it as argument for Match.get, a function that returns a promise of a Match object. So by awaiting on that, we get our match data.

The last step before running our simple example is to get the player's stats in this Match.

const participant = match.getParticipantByName('martinsileno');
if (!participant) {
  console.error('Player not found in participants');
  return;
}
console.log(`${participant.name} placed #${participant.winPlace} out of ${match.participants.length} on ${match.map}`);
console.log('his stats: ');
console.log(`kills ${participant.kills}`);
console.log(`damage ${participant.damageDealt}`);
console.log(`assists ${participant.assists}`);
console.log(`headshot kills ${participant.headshotKills}`);
console.log(`total distance ${participant.totalDistance}m`);

to get a player's stats in a Match we use the method getParticipantByName, which returns the corresponding Participant object.

The Participant instances contain details on players in a Match, see the public getters in the class to find more.

And we're done, we can run our example to see if it works, the output should look like

$ node dist/main.js
Found player "martinsileno" with ID: account.a540a32a49784025939a975b45e86bfe
Last played match on Sun Apr 22 2018 00:33:20 GMT+0200 (W. Europe Daylight Time) and lasted 32 minutes, with ID: a6d8d8f7-a3c4-4b1c-9947-8df40c144283
martinsileno placed #1 out of 92 on Desert_Main
his stats:
kills 2
damage 376.501
assists 3
headshot kills 1
total distance 3915.62m

Usage example: player aggregate stats

Since May 1st and version 1.3 of this wrapper we finally have aggregate data on a player for each season.

Getting this data is very easy,

const api = new PubgAPI(API_KEY, PlatformRegion.PC_NA);
const result = await Player.filterByName(api, ['shroud']);
const shroud = result[0];
const seasonData = await PlayerSeason.get(api, shroud.id, 'division.bro.official.2018-04');
const soloStats = seasonData.squadFPPStats;
console.log(`Player [${shroud.name}] stats for season [${seasonData.seasonId}]:`);
console.log(`Kills ${soloStats.kills} / Assists ${soloStats.assists} / Knock-outs ${soloStats.dBNOs}`);
console.log(`Played ${soloStats.roundsPlayed} matches`);
console.log(`Won ${soloStats.wins} (${(100 * soloStats.wins / soloStats.roundsPlayed).toFixed(2)}%)`);
console.log(`top10s ${soloStats.top10s} (${(100 * soloStats.top10s / soloStats.roundsPlayed).toFixed(2)}%)`);

This results in

Player [shroud] stats for season [division.bro.official.2018-04]:
Kills 268 / Assists 50 / Knock-outs 200
Played 50 matches
Won 13 (26.00%)
top10s 20 (40.00%)

You can get the season names using the Season.list method,

const seasonsList = await Season.list(api);
seasonsList.forEach(s => console.log(s.id));

(I suggest you cache the result as it's not likely to change often)

Usage example: telemetry

This package includes an easy-to-use and complete telemetry parsing utility.

As an usage example we will get a list of player kills, care package landings and a list of player positions for a player.

You can do much more with telemetry data, please read the documentation in the wiki for more details.

Download telemetry data

The first thing to do when working with telemetry is to download the corresponding object

const api = new PubgAPI(API_KEY, PlatformRegion.PC_EU);
const telemetry = await match.getTelemetry(api);

List of kills in a match

telemetry.playerKillEvents.forEach(e => {
    console.log(`[${e.dateTime.toLocaleDateString()} ${e.dateTime.toLocaleTimeString()} kill] ${e.killer.name} -> ${e.victim.name} | ${e.damageCauserName} ${e.damageTypeCategory} @ ${e.distance / 100}m`);
});

example output:

...
[2018-4-28 19:16:28 kill] Ludosh -> martinsileno | PlayerMale_A_C Damage_Groggy @ 63.1690576171875m
[2018-4-28 19:16:28 kill] siperdekizurafa -> zaku6652 | PlayerMale_A_C Damage_Groggy @ 36.4665966796875m
[2018-4-28 19:16:28 kill] Ludosh -> Novanta | WeapHK416_C Damage_Gun @ 54.971845703125m
[2018-4-28 19:17:54 kill] Razzmatazzzzz -> WilliamTanz | WeapSCAR-L_C Damage_Gun @ 143.47111328125m
[2018-4-28 19:17:55 kill] Haspex -> LMNTRIXs | WeapAK47_C Damage_Gun @ 126.266767578125m
...

"damage groggy" means bleed out damage

Care package landings

telemetry.carePackageLandEvents.forEach(e => {
  const itemsString = e.itemPackage.items.map(item => item.itemId).join(', ');
  console.log(`[${e.dateTime.toLocaleDateString()} ${e.dateTime.toLocaleTimeString()} carePackage land] with ${itemsString}`);
});

example output:

[2018-4-28 19:04:55 carePackage land] with Item_Weapon_M24_C, Item_Ammo_762mm_C, Item_Ammo_762mm_C, Item_Attach_Weapon_Upper_CQBSS_C, Item_Attach_Weapon_Upper_PM2_01_C, Item_Back_C_01_Lv3_C, Item_Heal_MedKit_C
[2018-4-28 19:11:27 carePackage land] with Item_Weapon_M24_C, Item_Ammo_762mm_C, Item_Ammo_762mm_C, Item_Attach_Weapon_Upper_CQBSS_C, Item_Head_G_01_Lv3_C, Item_Heal_FirstAid_C
[2018-4-28 19:15:11 carePackage land] with Item_Weapon_Groza_C, Item_Ammo_762mm_C, Item_Ammo_762mm_C, Item_Ammo_762mm_C, Item_Attach_Weapon_Upper_CQBSS_C, Item_Armor_C_01_Lv3_C, Item_Heal_MedKit_C
[2018-4-28 19:24:19 carePackage land] with Item_Weapon_M249_C, Item_Ammo_556mm_C, Item_Ammo_556mm_C, Item_Head_G_01_Lv3_C, Item_Heal_MedKit_C, Item_Ghillie_02_C

Player positions in a match

const martinPositions = telemetry.playerPositionEvents.filter(e => e.character.name === 'martinsileno');
martinPositions.forEach(e => {
  const loc = e.character.location;
  console.log(`[${e.dateTime.toLocaleDateString()} ${e.dateTime.toLocaleTimeString()} position] (${loc.x}, ${loc.y}, ${loc.z})`);
});

example output:

...
[2018-4-28 19:12:44 position] (432451, 63057.02734375, 5437.40966796875)
[2018-4-28 19:12:54 position] (429667.1875, 61954.94921875, 4977.5)
[2018-4-28 19:13:04 position] (425153.90625, 65993.546875, 4900.1298828125)
[2018-4-28 19:13:14 position] (422108.46875, 71026.3671875, 5496.9599609375)
[2018-4-28 19:13:24 position] (419111.8125, 75035.40625, 5401.53759765625)
...

License

MIT

pubg-typescript-api's People

Contributors

gitter-badger avatar martinsileno avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

pubg-typescript-api's Issues

Cannot read property error during telemetry data parsing

During telemetry data parsing two TypeError: Cannot read property can occur.

It looks like it is possible that during the PlayerAttack event, event.vehicle object can be null:

Stack:

TypeError: Cannot read property 'vehicleType' of null
    at new Vehicle (http://localhost:4200/vendor.js:106095:37)
    at new PlayerAttack (http://localhost:4200/vendor.js:105288:25)
    at Telemetry.telemetryData.forEach.elem (http://localhost:4200/vendor.js:106207:51)
    at Array.forEach (<anonymous>)
    at new Telemetry (http://localhost:4200/vendor.js:106161:23)

Event object:

_D:"2018-08-05T16:28:49.010Z"
_T:"LogPlayerAttack"
attacker:Object {name: "SuperGaber", teamId: 1, health: 100, …}
attackId:1
attackType:"Weapon"
common:Object {isGame: 0}
vehicle:null <---
weapon:Object {itemId: "", stackCount: 374883072, category: "", …}
__proto__:Object {constructor: , __defineG...

The same situation can heppen in PlayerTakeDamage event. The event.attacker can be null.

Stack:

TypeError: Cannot read property 'name' of null
    at new Character (http://localhost:4200/vendor.js:105867:32)
    at new PlayerTakeDamage (http://localhost:4200/vendor.js:105577:26)
    at Telemetry.telemetryData.forEach.elem (http://localhost:4200/vendor.js:106233:55)
    at Array.forEach (<anonymous>)
    at new Telemetry (http://localhost:4200/vendor.js:106163:23)

Event object:

_D:"2018-08-05T16:31:11.795Z"
_T:"LogPlayerTakeDamage"
attacker:null <---
attackId:-1
common:Object {isGame: 0.10000000149011612}
damage:0
damageCauserName:"PlayerMale_A_C"
damageReason:"None"
damageTypeCategory:"Damage_Groggy"
victim:Object {name: "sergeach", teamId: 23, health: 0, …}
__proto__:Object {constructor: , __defineG

Checking of objects can help to parse whole telemetry object data:

pubg-typescript-api\entities\telemetry\events\playerAttack.js

        if (event.vehicle) {
            this._vehicle = new vehicle_1.Vehicle(event.vehicle);
        }

pubg-typescript-api\entities\telemetry\events\playerTakeDamage.js

        if (event.attacker) {
            this._attacker = new character_1.Character(event.attacker);
        } 

await on api call throwing error

I have the following function:

getPlayers: async (gamerTags: string[]) =>
await Player.filterByName(pubgApi, gamerTags);

Whenever I call it I get the following error: "ReferenceError: regeneratorRuntime is not defined".

It seems the api wrapper isn't able to handle the async/await. Is there something I should know?

Thanks.

Updating api for v6.0.0

PUBG API is updating their api to v6.0.0:

Task List

  • Add steam and kakao to PlatformRegion enum.
  • Add [PC] participant.attributes.stats.rankPoints
  • Add [PC] match.attributes.seasonState
  • Add [PC] LogMatchDefinition.SeasonState
  • Add new [PC] gameModeStats attributes: [bestRankPoints, dailyWins, rankPoints, swimDistance, weeklyWins.
  • No need to remove deprecated gameModeStats since Xbox and old-pc seasons still use them.
  • If needed - Update SeasonStats api call to handle new and old api format
  • If needed - Update matches endpoint to handle new api format
  • Push my commits to GitHub
  • Open a pull request

Major Updates

New Ranking

  • For XBOX the original rating properties (as is) will still be available.
  • For PC killPoints, winPoints, and their deltas will be deprecated for RankPoint.
  • Deprecated killPoints, killPointsDelta, winPoints, and winPointsDelta will be "0" for PC beginning on 10/3.

New Player Season-Stats and Matches:

Matches:

Old:  /shards/ {platform-region} /matches/{id}
New:  /shards/ {steam or kakao}  /matches/{id}
  • Matches will support both formats so you can use either format to get matches from previous/new season

Player's Season Stats:

PC (after  10/3)   - /shards/    {steam or kakao}   /players/{playerId}/seasons/{seasonId}
PC (before 10/3)   - /shards/ {pc or xbox}-{region} /players/{playerId}/seasons/{seasonId}
Xbox               - /shards/ {pc or xbox}-{region} /players/{playerId}/seasons/{seasonId}
  • New seasons will have to follow the new endpoint format
  • Does this means that we CANT use the new rank format for PC seasons before 10/3?
    • Waiting on confirmation for this...

Player by Id:

Remains the same    - https://api.pubg.com/shards/{region}/players/{id}

Source / Documentation

image

Error in Chrome - Refused to set unsafe header "Accept-Encoding"

In Chrome browser I'm getting Refused to set unsafe header "Accept-Encoding" error message every time when a request is processed. According to this StackOverflow question, the Accept-Encoding should not be part of the header. But I'm not sure, what it exactly does and what it can affects. Anyway if I remove the Accept-Encoding in constructor of PubgAPI class in pubg-typescript-api\api\base.js, it works fine and the error is not produced:

        /*if (useGzip) {
            headers['Accept-Encoding'] = 'gzip';
        }*/

Btw. great job, I like this wrapper.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.