Skip to content
This repository was archived by the owner on May 11, 2021. It is now read-only.

Clear up region-specific code. #271

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Clear up region-specific code. Some relics still remain. All regions …
…now just "any"
  • Loading branch information
relaera committed Jan 21, 2019
commit 5085479231107475ce20caacb3f3f2dbb172b672
45 changes: 13 additions & 32 deletions api.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ Regions and platforms can be overridden with URL parameters.

### Regions (V3)

In V3, all regions are automatically checked. Data is returned for any regions the user is in. The other regions return
`null`. See V3 results below.
Blizzard has somewhat recently changed regions such that there are no region-specific statistics anymore. All region-
specific endpoints automatically redirect to remove the region, and region data ends up resulting in duplicate data.

### Platforms

Expand All @@ -21,15 +21,15 @@ You can override the platform with `?platform=<pc|xbl|psn>`. This defaults to `p

The default output is standard JSON, but you can prettify it with `?format=json_pretty` to have it
in a more readable format. (The other option is installing a browser plugin, such as
[JSONView](https://jsonview.com/).
[JSONView](https://jsonview.com/)).

#### Field formatting

Field names inside the inner dict will correspond to all of the cards shown inside the
[PlayOverwatch](https://playoverwatch.com/en-us/career/pc/eu/Downy-2877) pages corresponding to
[PlayOverwatch](https://playoverwatch.com/en-us/career/pc/Downy-2877) pages corresponding to
the users, with a slight formatting tweak:

- All nonalphanumeric characters are removed
- All non-alphanumeric characters are removed
- All spaces are replaced with underscores
- The entire fields are lowercase

Expand Down Expand Up @@ -62,15 +62,11 @@ Unless otherwise specified, time fields are always in ***hours***.
"api_ver": 3,
"route": "/api/v3/u/Dad-12262/blob"
},
"kr": null,
"eu": null,
"us": {
"any": {
"stats": {},
"heroes": {},
"achievements": {}
},
"any": null

}
}
```

Expand Down Expand Up @@ -99,14 +95,11 @@ Each of these will have several other keys:

```json
{

"_request": {
"api_ver": 3,
"route": "/api/v3/u/Dad-12262/stats"
},
"kr": null,
"eu": null,
"us": {
"any": {
"stats": {
"competitive": {
"overall_stats": {
Expand Down Expand Up @@ -264,9 +257,7 @@ Each of these will have several other keys:
}
},
"achievements": { }
},
"any": null

}
}
```

Expand All @@ -283,14 +274,11 @@ This is a mapping of category -> hash which is another mapping of achievement ->

```json
{

"_request": {
"api_ver": 3,
"route": "/api/v3/u/Dad-12262/achievements"
},
"kr": null,
"eu": null,
"us": {
"any": {
"stats": { },
"heroes": {
"stats": {
Expand Down Expand Up @@ -377,9 +365,7 @@ This is a mapping of category -> hash which is another mapping of achievement ->
"double_cap": true
}
}
},
"any": null

}
}
```

Expand All @@ -405,14 +391,11 @@ The `heroes` key will contain two subkeys, inside the respective `quickplay` and

```json
{

"_request": {
"api_ver": 3,
"route": "/api/v3/u/Dad-12262/heroes"
},
"kr": null,
"eu": null,
"us": {
"any": {
"stats": { },
"heroes": {
"stats": {
Expand Down Expand Up @@ -561,8 +544,6 @@ The `heroes` key will contain two subkeys, inside the respective `quickplay` and
}
},
"achievements": { }
},
"any": null

}
}
```
70 changes: 15 additions & 55 deletions owapi/blizz_interface.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,10 @@
from owapi import util

B_BASE_URL = "https://playoverwatch.com/en-us/"
B_PAGE_URL = B_BASE_URL + "career/{platform}{region}/{btag}"
B_PAGE_URL = B_BASE_URL + "career/{platform}/{btag}"
B_HEROES_URL = B_BASE_URL + "heroes"
B_HERO_URL = B_HEROES_URL + "/{hero}"

# The currently available specific regions.
AVAILABLE_REGIONS = ["/eu", "/us", "/kr"]

logger = logging.getLogger("OWAPI")


Expand Down Expand Up @@ -73,15 +70,11 @@ def _parse_page_lxml(content: str) -> etree._Element:


async def get_user_page(ctx: HTTPRequestContext, battletag: str, platform: str = "pc",
region: str = "us",
cache_time=300, cache_404=False) -> etree._Element:
"""
Downloads the BZ page for a user, and parses it.
"""
if platform != "pc":
region = ""
built_url = B_PAGE_URL.format(
region=region, btag=battletag.replace("#", "-"), platform=platform)
built_url = B_PAGE_URL.format(btag=battletag.replace("#", "-"), platform=platform)
page_body = await get_page_body(ctx, built_url, cache_time=cache_time, cache_404=cache_404)

if not page_body:
Expand All @@ -106,81 +99,48 @@ async def fetch_all_user_pages(ctx: HTTPRequestContext, battletag: str, *,
"""
Fetches all user pages for a specified user.

Returns a dictionary in the format of `{region: etree._Element | None}`.
Returns a dictionary in the format of `{"any": etree._Element | None}`.
"""
if platform != "pc":
coro = get_user_page(ctx, battletag, region="", platform=platform, cache_404=True)
coro = get_user_page(ctx, battletag, platform=platform, cache_404=True)
result = await coro
if isinstance(result, etree._Element):
return {"any": result,
"eu": None, "us": None, "kr": None}
return {"any": result}
else:
# Raise a 404.
raise NotFound()

futures = []
for region in AVAILABLE_REGIONS:
# Add the get_user_page coroutine.
coro = get_user_page(ctx, battletag, region=region, platform=platform, cache_404=True)
futures.append(coro)
coro = get_user_page(ctx, battletag, platform=platform, cache_404=True)
futures.append(coro)

# Gather all the futures to download paralellely.
# Gather all the futures to download in parallel.
results = await asyncio.gather(*futures, return_exceptions=True)
d = {"any": None}
user_data = {"any": None}
error = None
for region, result in zip(AVAILABLE_REGIONS, results):
# Remove the `/` from the front of the region.
# This is used internally to make building the URL to get simpler.
region = region[1:]
for key, result in zip(["any"], results):
# Make sure it's either a None or an element.
if isinstance(result, etree._Element):
d[region] = result
user_data[key] = result
elif isinstance(result, Exception):
logger.error("Failed to fetch user page!\n{}".format(
''.join(traceback.format_exception(type(result), result, result.__traceback__))
))
error = result
d[region] = None
user_data[key] = None
else:
d[region] = None
user_data[key] = None

# Check if we should raise or return.
if not any(d[i[1:]] is not None for i in AVAILABLE_REGIONS):
if user_data["any"] is None:
if error is not None:
e = InternalServerError()
e.__cause__ = error
e.__context__ = error
raise e
raise NotFound()

return d


async def region_helper_v2(ctx: HTTPRequestContext, battletag: str, platform="pc", region=None,
extra=""):
"""
Downloads the correct page for a user in the right region.

This will return either (etree._Element, region) or (None, None).
"""
if region is None:
reg_l = ["/eu", "/us", "/kr"]
else:
if not region.startswith("/"):
# ugh
region = "/" + region
reg_l = [region]

for reg in reg_l:
# Get the user page.
page = await get_user_page(ctx, battletag, platform=platform, region=reg)
# Check if the page was returned successfully.
# If it was, return it.
if page is not None:
return page, reg[1:]
else:
# Since we continued without returning, give back the None, None.
return None, None
return user_data


async def get_hero_data(ctx: HTTPRequestContext, hero: str):
Expand Down