GithubHelp home page GithubHelp logo

ramonsaraiva / pubg-python Goto Github PK

View Code? Open in Web Editor NEW
129.0 14.0 49.0 8.16 MB

A python wrapper for the PUBG developer API

License: MIT License

Python 99.87% Dockerfile 0.13%
pubg playerunknowns-battlegrounds api-client api-wrapper wrapper pubg-python

pubg-python's Introduction

pubg-python

pypi wheel

A python wrapper for the PUBG Developer API

PUBG Developer API Official Documentation

Installation

To install the wrapper, simply use pip

pip install pubg-python

or pipenv

pipenv install pubg-python

Usage

Specifying a shard

The PUBG API shards data by platform and region, and therefore requires a shard to be specified in the URL for most requests.

from pubg_python import PUBG, Shard

api = PUBG('<api-key>', Shard.PC_NA)

A list of shards can be found here and the wrapper constants here

Samples

A sample of matches can be retrieved as a starting point

sample = api.samples().get()
for match in sample.matches:
    print(match.id)

Samples can also be filtered by a creation date

sample = api.samples().filter(created_at_start='2018-01-01T00:00:00Z').get()
for match in sample.matches:
    print(match.id)

Players

Retrieving a single player

player = api.players().get('account.3654e255b77b409e87b10dcb086ab00d')

for match in player.matches:
    match_data = api.matches().get(match.id)

Retrieving a list of players filtering by names

players = api.players().filter(player_names=['Name1', 'Name2'])

for player in players:
    player_id = player.id

Retrieving a list of players filtering by ids

players = api.players().filter(player_ids=['account.3654e255b77b409e87b10dcb086ab00d'])

for player in players:
    player_name = player.name

Matches

Retrieving a single match

match = api.matches().get('276f5bcb-a831-4e8c-a610-d2073692069e')

Retrieving a list of matches filtering by ids

Still unavailable in the API

match_ids = [
    '276f5bcb-a831-4e8c-a610-d2073692069e',
    'fasf9082-21de-dkle-13ke-qlamd13nab3a',
]
matches = api.matches().filter(match_ids=match_ids)
for match in matches:
    print(match)

Telemetry

Processing a match Telemetry data

match = api.matches().get('276f5bcb-a831-4e8c-a610-d2073692069e')
asset = match.assets[0]
telemetry = api.telemetry(asset.url)

print(len(telemetry.events))
>> 16871

Filtering specific events in a telemetry object

Sometimes you're interested in a set of very specific events, so there is a helper function to filter those for you:

match = api.matches().get('276f5bcb-a831-4e8c-a610-d2073692069e')
asset = match.assets[0]
telemetry = api.telemetry(asset.url)

player_kill_events = telemetry.events_from_type('LogPlayerKill')
player_position_events = telemetry.events_from_type('LogPlayerPosition')

Loading a local Telemetry file

If you want to load a previously downloaded telemetry file, there is a helper method to create a Telemetry object from it:

from pubg_python import Telemetry

telemetry = Telemetry.from_json('telemetry.json', shard='pc')

shard defaults to pc but you need to specify if you're loading a xbox telemetry file.

Tournaments

Retrieving a single tournament

tournament = api.tournaments().get('na-ppc')

Retrieving a list of tournaments

tournaments = api.tournaments()
for tournament in tournaments:
    print(tournament)

Seasons

Retrieving the list of seasons

seasons = api.seasons()

Retrieving seasons information for a list of players

players_seasons = api.seasons(
    season_id='division.bro.official.2018-09', game_mode='solo'
).filter(player_ids=['epickitten'])

It's also possible to retrieve lifetime stats, instead of a season_id:

players_seasons = api.seasons(
    season_id='lifetime', game_mode='solo'
).filter(player_ids=['epickitten'])

Retrieving season data for a specific player

season_data = api.seasons(
    'division.bro.official.2018-09' , player_id='epickitten').get()

It's also possible to retrieve lifetime stats, instead of a season_id:

season_data = api.seasons(
    'lifetime' , player_id='epickitten').get()

Weapon Mastery

Retrieving a weapon mastery data

players = api.players().filter(player_names=['epickitten'])[0]
player = players[0]
wm = api.weapon_mastery(player.id).get()
print(wm.weapon_summaries)

Leaderboards

Retrieving a leaderboard

# Leaderboards stats are only available for PC players
api.shard = Shard.STEAM
solo_leaderboard = api.leaderboards(game_mode='solo').page(0).get()
solo_fpp_leaderboard = api.leaderboards(game_mode='solo-fpp').page(0).get()
duo_leaderboard = api.leaderboards(game_mode='duo').page(0).get()
duo_fpp_leaderboard = api.leaderboards(game_mode='duo-fpp').page(0).get()
squad_leaderboard = api.leaderboards(game_mode='squad').page(0).get()
squad_fpp_leaderboard = api.leaderboards(game_mode='squad-fpp').page(0).get()

page is always required, even when querying the first leaderboard page.

Playing around with data

An example of how you can manipulate the data: The domain is all specified here

players = api.players().filter(player_names=['epickitten'])
player = players[0]

player.matches
>> [<Match bd6aae34-be05-4094-981c-083285c7e861>, <Match 276f5bcb-a831-4e8c-a610-d2073692069e>, ..]

match = api.matches().get(player.matches[0].id)

match.game_mode
>> 'solo'

match.duration
>> 1899

match.rosters
>> [<Roster d542eaee-cd02-4f4e-ad7f-ed5ea71a17cf>, <Roster e9f0962a-ebd4-4d86-b134-95783b713800>, ..]

roster = match.rosters[0]

roster.participants
>> [<Participant 7cc76d1b-a80e-4997-8eb8-d4b3c1ed4f44>]

participant = roster.participans[0]

participant.name
>> 'urdaddyYO'

participant.damage_dealt
>> 291.08

participant.kills
>> 2

participant.ride_distance
>> 3204.53467

participant.walk_distance
>> 2262.81714

participant.time_survived
>> 1367

participant.player_id
>> account.edb9910f1e9c4f3b9addb87d9329b57c

player = api.players().get(participant.player_id)

player
>> account.edb9910f1e9c4f3b9addb87d9329b57c

player.matches
>> [<Match b3dcd7e8-2270-4fdd-8389-af77acf2d6c2>, <Match 2ebb1a9c-ab5e-4264-971f-df77a00918a9>, ..]

Ratelimits

Each application has a limited amount of requests allowed per minute. The ratelimit is managed through HTTP headers (X-Ratelimit-Limit, X-Ratelimit-Reset, etc..). In order to facilitate heavy tasks, it is possible to retrieve those values from the RateLimitError. The values available in the exception instance are rl_limit (integer) and rl_reset (datetime).

An example snippet that would use this information in favor of processing something big:

api = PUBG('my-super-secret-key', Shard.STEAM)

while True:
    try:
        print('Processing samples...')
        api.samples().get()
    except RateLimitError as error:
        sleep_seconds = (error.rl_reset - datetime.now()).total_seconds()
        if sleep_seconds > 0:
            print('Reached my limit! sleeping for {}'.format(sleep_seconds))
            time.sleep(sleep_seconds)

Limits and Offsets

Currently disabled from the official API

Offsetting 5 matches and limitting by 10

matches = api.matches().limit(10).offset(5)

Sorting

Currently disabled from the official API

sort defaults to ascending, you can use ascending=False for a descending sort

matches = api.matches().limit(10).sort('createdAt')
matches = api.matches().limit(10).sort('createdAt', ascending=False)

Filtering

Some endpoints allow you to apply filters, for example, filtering players by names:

players = api.players().filter(player_names=['Name1', 'Name2'])

Or filtering players by ids:

players = api.players().filter(player_ids=['account.3654e255b77b409e87b10dcb086ab00d'])

Pagination

Use next() for the next page and prev() for the previous one:

matches = api.matches()
next_matches = matches.next()
previous_matches = matches.prev()

Changelog

CHANGELOG.md

pubg-python's People

Contributors

adamgeraldy avatar dandyrilla avatar divomen avatar dzen avatar faiare avatar gintsmurans avatar glmn avatar haza avatar hireyes avatar hurani avatar hyeom avatar jandaluz1 avatar jgrinaveckis avatar junhan-z avatar kenanwarren avatar koyah avatar oricul avatar ramonsaraiva avatar rico0821 avatar tetraquark avatar tilo-k avatar vgustov avatar wookienz avatar xcodinas avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

pubg-python's Issues

RateLimitError Auto-Handling

Firstly, thank you for your great work! In practice, I find myself scratching my head when I'm constantly getting RateLimitError when I'm collecting data for my friends, due to the 5 request/min limitation. Therefore, I'm suggesting a feature which wraps around the requests using some structure like the following:

cont = False
while not cont:
    try:
        # make the request
        
       cont = True
   except pubg_python.exceptions.RateLimitError:
        time.sleep(60)

This has the disadvantage of making the return time of the call very unpredictable. However, we could warn the users about it and let them choose which to use.

Passing unexpected response_headers to __init()__

Error in exceptions.py after PR #77
TypeError: __init__() got an unexpected keyword argument 'response_headers'

This error triggers in every APIError exceptions except RateLimitError due to passing response_headers to __init__()

You can reproduce it even with invalid API Key. It will crash with first error instead of raising an UnauthorizedError

ReadMe Telemetry Issue

The code as follows in the ReadMe under the Telemetry section does not work...

`match = api.matches().get('276f5bcb-a831-4e8c-a610-d2073692069e')
asset = match.assets[0]
telemetry = api.telemetry(asset.url)

Traceback (most recent call last):

File "", line 3, in
telemetry = api.telemetry(asset.url)

AttributeError: 'PUBG' object has no attribute 'telemetry'`

I'm sure the telemetry info is there since I see code written for it in the package, but it looks like the PUBG object doesnt have a "telemetry" method to call.

I'm sure I'm not the only one who has had this problem, what is the simplest way to access Telemetry data?

pubg_python.exceptions.NotFoundError: The specified resource was not found

from pubg_python import PUBG, Shard

api_key = "..."
api = PUBG(api_key, Shard.PC_EU)

players = api.players().filter(player_names=['epickitten'])
player = players[0]

The following results in:

Traceback (most recent call last):
  File "pubg.py", line 7, in <module>
    player = players[0]
  File "/usr/lib/python3.7/site-packages/pubg_python-0.4.1-py3.7.egg/pubg_python/decorators.py", line 23, in wrapper
  File "/usr/lib/python3.7/site-packages/pubg_python-0.4.1-py3.7.egg/pubg_python/querysets.py", line 45, in fetch
  File "/usr/lib/python3.7/site-packages/pubg_python-0.4.1-py3.7.egg/pubg_python/clients.py", line 32, in request
pubg_python.exceptions.NotFoundError: The specified resource was not found

And I have no idea why. None of the player-filter searches works.
(python setup.py install from the latest branch. Python3.7 as the errors suggest)

KeyError

match = api.matches().get('2586b033-3831-43b3-a87f-dc31781e5901')
asset = match.assets[0]
telemetry = api.telemetry(asset.url)

KeyError: 'LogItemPickupFromCarepackage'

Usage of api.players().filter()

Hi !

I'm testing around with your wrapper.
Right now, I am trying to retrieve some user data.
Using api.players().get() I can get a response from the API, everything seems good.

Using api.players().filter(), the query does not seems to be fired and I do not get any data from the API.

Here is my code

api = PUBG('<key>', <shard>)
# accound ID and player name are mine :-)
player = api.players().get('account.d70754df232c42b2b63dc0525c99acfb')
players = api.players().filter(player_names=['Hazadess'])

And the debug output
capture_36789f

Do I miss something ?
Thanks !

Issues with code in the read me

Under "Playing around with data"

The line

players = api.players().filter(players_names['epickitten'])

Should be player_names not players_names.

players = api.players().filter(player_names['epickitten'])

I would be more than happy to make fixes. Can I upload my own fixes to the repo?

Support for local telemetry files

I downloaded a few thousand telemetry files without using pubg-python, but then I wanted to use pubg-python to process them handily. So I added the following code into base.py:

11   import json

55    def telemetryStatic(self, telemetryJson):
56        data = json.loads(open(telemetryJson,"r").read())
57        return Telemetry(data, telemetryJson)

Now, this really doesn't follow the rest of the library's style, so I haven't submitted a pull request. But it allows me to do this, which is valuable to me:

static = "telemetry-files/c8228bc5-4f28-11e8-9fbb-0a5864768b15-telemetry.json"
telemetry =  api.telemetryStatic(static)

From there, I can work with the file as if I'd requested it through the API. This saves requests and guards against PUBG deleting historical replays. I thought this might be useful to people trying to solve the same problem, or as inspiration for a future feature (e.g. a function to cache the JSON file when we API request it).

Key Error

Code:
from pubg_python import PUBG, Shard
import config

api = PUBG(config.api_key, Shard.PC_AS)
sample = api.samples().get()
match = api.matches().get('8648bf56-82a2-4377-a2a7-de65c03ec8df')
asset = match.assets[0]
telemetry = api.telemetry(asset.url)
print(len(telemetry.events))

Error:

telemetry = api.telemetry(asset.url)
File "/home/wookienz/Projects/Coding/nemesis/lib64/python3.6/site-packages/pubg_python-0.3.2-py3.6.egg/pubg_python/base.py", line 52, in telemetry
File "/home/wookienz/Projects/Coding/nemesis/lib64/python3.6/site-packages/pubg_python-0.3.2-py3.6.egg/pubg_python/domain/telemetry/base.py", line 13, in init
File "/home/wookienz/Projects/Coding/nemesis/lib64/python3.6/site-packages/pubg_python-0.3.2-py3.6.egg/pubg_python/domain/telemetry/base.py", line 13, in
File "/home/wookienz/Projects/Coding/nemesis/lib64/python3.6/site-packages/pubg_python-0.3.2-py3.6.egg/pubg_python/domain/telemetry/events.py", line 18, in instance
File "/home/wookienz/Projects/Coding/nemesis/lib64/python3.6/site-packages/pubg_python-0.3.2-py3.6.egg/pubg_python/domain/telemetry/events.py", line 8, in init
File "/home/wookienz/Projects/Coding/nemesis/lib64/python3.6/site-packages/pubg_python-0.3.2-py3.6.egg/pubg_python/domain/telemetry/events.py", line 179, in from_dict
File "/home/wookienz/Projects/Coding/nemesis/lib64/python3.6/site-packages/pubg_python-0.3.2-py3.6.egg/pubg_python/domain/telemetry/events.py", line 13, in from_dict
File "/home/wookienz/Projects/Coding/nemesis/lib64/python3.6/site-packages/pubg_python-0.3.2-py3.6.egg/pubg_python/domain/telemetry/data.py", line 11, in getitem
KeyError: '_V'

The request appears to fire correctly. However it errors while trying to store data in the following function:

class TelemetryData(collections.MutableMapping):

def __getitem__(self, key):
    value = self.store[self.__keytransform__(key)]
    if isinstance(value, dict):
        return self.__class__(value)
    return value

Specifically just after trying to insert: '2018-06-30T23:27:10.5366766Z'

FYI.

redundant "Accept-Encoding" header

In RequestMixin, I see you're adding the Accept-Encoding: gzip header.
requests adds an Accept-Encoding: gzip, deflate header for you automatically, so there shouldn't be a need to do this manually.

See the docs here

Could pubg-python add a new Telemetry events?

I want to get a telemetry events. so I tried to run this "telemetry = api.telemetry(asset.url)" code.
but I recieve a KeyError: 'LogHeal'.
So Could pubg-python update for pubg API V7.8.0?

Add new exception for wrong player_names

There are IGN restrictions that i found in PUBG official forum - link

  • Player nicknames must start with a letter.
  • Player nicknames must contain between 4 to 16 characters.
  • Use only letters (a-z, A-Z), digits (0-9), dashes (-), and underscores (_).

To prevent extra API requests with wrong player_names filter in players endpoint we can add new exception WrongIGNError for PC shards

New telemetry exceptions

@ramonsaraiva
In official PUBG API discord server i've found that there is undocumented 403 status code if telemetry was not found on servers or no longer available. Should i make a new exception (ex. OldTelemetryError) or just return NotFoundError for 403 status code?

Examples:
https://telemetry-cdn.playbattlegrounds.com/bluehole-pubg/steam/2019/08/28/21/18/5a9cc5e2-c9d9-11e9-8db7-0a586468ab66-telemetry.json
https://telemetry-cdn.playbattlegrounds.com/bluehole-pubg/steam/2019/08/30/18/00/0fb4b2b6-cb50-11e9-a981-0a5864687231-telemetry.json

P.S. Should we limit telemetry URL only for official PUBG host telemetry-cdn.playbattlegrounds.com otherwise TelemetryURLError?

events_from_type could return ordered dictionaries

All events include a timestamp. In my limited testing, the events come out sorted anyways. If we order the events and put them into a dictionary, subsequent operations on the resulting ordered dictionary will be much faster, some will be O(1) rather than O(n).

This would be an improvement, in my opinion. If there is concern about backwards compatibility (which there should be) we could simply have it as an optional flag such as .events_from_type(event, ordered_dict = False)

I'd be happy to take a look at implementing this if there is interest/agreement.

Api did not return my account

i am trying to return information about my account

from pubg_python import PUBG, Shard

api = PUBG(mykey, Shard.PC_RU)
print(api)
players = api.players().filter(player_names=['Serjlife'])
player = players[0]
print(player.id)
print(player.matches)

and got the following error :

pubg_python.exceptions.NotFoundError: The specified resource was not found

Support multiple concurrent filters

Where the existing implementation is:

squad_matches = api.matches().filter('gameMode', 'squad')
solo_matches = api.matches().filter('gameMode', 'solo')
after_2018 = api.matches().filter('createdAt-start', '2018-01-01T00:00:00Z')

I would suggest supporting an array of filters. For instance, if I want solo matches after 2018 I think this would be an efficient method:

solo_after_2018 = api.matches().filter(gameMode='solo', createdAt-start='2018-01-01T00:00:00Z')

Which would take advantage of **kwargs. Another option is

filter('gameMode=solo', 'createdAt-start=2018-01-01T00:00:00Z')

Either can be parsed as a series of calls to the existing filter method.

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.