Metadata-Version: 2.4
Name: blizzardapi3
Version: 4.0.0
Summary: A modern Python wrapper for the Blizzard API with sync and async support
Author-email: lostcol0ny <c098os0k@4wrd.cc>
License-Expression: MIT
Project-URL: Homepage, https://github.com/lostcol0ny/blizzardapi3
Project-URL: Documentation, https://github.com/lostcol0ny/blizzardapi3#readme
Project-URL: Repository, https://github.com/lostcol0ny/blizzardapi3
Project-URL: Issues, https://github.com/lostcol0ny/blizzardapi3/issues
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Operating System :: OS Independent
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Requires-Python: >=3.11
Description-Content-Type: text/markdown
Requires-Dist: httpx<1.0.0,>=0.27.0
Provides-Extra: dev
Requires-Dist: pytest<10.0.0,>=8.2.2; extra == "dev"
Requires-Dist: pytest-mock<4.0.0,>=3.14.0; extra == "dev"
Requires-Dist: pytest-asyncio<2.0.0,>=0.23.5; extra == "dev"
Requires-Dist: black<26.0.0,>=24.4.2; extra == "dev"
Requires-Dist: ruff<1.0.0,>=0.3.0; extra == "dev"
Provides-Extra: examples
Requires-Dist: python-dotenv<2.0.0,>=1.0.0; extra == "examples"

# BlizzardAPI v3

A modern, config-driven Python wrapper for the Blizzard API with full async support, type safety via Pydantic, and comprehensive error handling.

## Table of Contents

- [Features](#features)
- [Installation](#installation)
- [Quick Start](#quick-start)
- [Accessing Response Headers](#accessing-response-headers)
- [Using Search Endpoints](#using-search-endpoints)
- [Error Handling](#error-handling)
- [Comprehensive Examples](#comprehensive-examples)
- [Supported Games](#supported-games)
- [Documentation](#documentation)
- [Development](#development)
- [Architecture](#architecture)

## Features

- 🚀 **Async/Await Support** - First-class async support with both sync and async methods
- 🔒 **Type Safety** - Full Pydantic models with IDE autocomplete
- 📝 **Config-Driven** - YAML-defined endpoints, easy to extend
- 🎯 **Better Errors** - Specific exception types with detailed context
- ⚡ **Efficient** - Single session management, proper resource cleanup
- 📊 **Response Headers** - Access HTTP headers for caching, rate limits, and metadata
- 🎮 **Complete Coverage** - Supports WoW, Diablo 3, Hearthstone, and StarCraft 2

## Installation

```bash
pip install blizzardapi3
```

> **Version stability:** BlizzardAPI v3 is under active development and is not yet considered stable. Breaking changes may land between minor versions as internal patterns are refined. For production use, pin to an exact version and review the [release notes](https://github.com/lostcol0ny/blizzardapi3/releases) before upgrading:
>
> ```bash
> pip install blizzardapi3==3.0.5
> ```

## Quick Start

### Synchronous Usage

```python
from blizzardapi3 import BlizzardAPI

# Use context manager for proper cleanup
with BlizzardAPI(client_id="your_id", client_secret="your_secret") as api:
    # Get WoW achievement
    achievement = api.wow.game_data.get_achievement(
        region="us",
        locale="en_US",
        achievement_id=6
    )
    print(achievement["name"]["en_US"])
```

### Asynchronous Usage

```python
import asyncio
from blizzardapi3 import BlizzardAPI

async def main():
    async with BlizzardAPI(client_id="your_id", client_secret="your_secret") as api:
        # Async methods end with _async
        achievement = await api.wow.game_data.get_achievement_async(
            region="us",
            locale="en_US",
            achievement_id=6
        )
        print(achievement["name"]["en_US"])

asyncio.run(main())
```

## Accessing Response Headers

All API responses include HTTP headers that provide useful metadata. The response object behaves like a dict for data access while also exposing headers:

```python
from blizzardapi3 import BlizzardAPI

with BlizzardAPI(client_id, client_secret) as api:
    result = api.wow.game_data.get_achievement(
        region="us",
        locale="en_US",
        achievement_id=6
    )

    # Access data (unchanged - full backwards compatibility)
    print(result["name"])
    print(result.get("points"))

    # Access response headers
    print(result.headers.get("Last-Modified"))
    print(result.headers.get("Cache-Control"))
    print(result.status_code)

    # List all headers
    for name, value in result.headers.items():
        print(f"{name}: {value}")
```

### Useful Headers

| Header | Description |
|--------|-------------|
| `Last-Modified` | When the data was last updated by Blizzard |
| `Cache-Control` | Caching policy (e.g., `max-age=86400` = 24 hours) |
| `Battlenet-Namespace` | The namespace/version of the data |
| `blizzard-token-expires` | When the OAuth token expires |

## Using Search Endpoints

BlizzardAPI v3 provides powerful search functionality for various game resources. Search methods accept flexible keyword arguments for filtering and pagination.

### Basic Search

```python
from blizzardapi3 import BlizzardAPI, Region, Locale

with BlizzardAPI(client_id, client_secret) as api:
    # Search for decor items containing "wall"
    results = api.wow.game_data.search_decor(
        region=Region.US,
        locale=Locale.EN_US,
        **{"name.en_US": "wall"}
    )

    print(f"Found {len(results['results'])} items")
    for item in results['results']:
        data = item['data']
        print(f"{data['name']['en_US']} (ID: {data['id']})")
```

### Pagination and Ordering

```python
with BlizzardAPI(client_id, client_secret) as api:
    # Get first page, ordered by ID
    results = api.wow.game_data.search_decor(
        region=Region.US,
        locale=Locale.EN_US,
        orderby="id",
        _page=1
    )

    print(f"Page {results['page']} of {results['pageCount']}")
    print(f"Results per page: {results['pageSize']}")
```

### Advanced Filtering

Search endpoints support locale-specific filtering using dot notation:

```python
with BlizzardAPI(client_id, client_secret) as api:
    # Search with multiple filters
    results = api.wow.game_data.search_decor(
        region=Region.US,
        locale=Locale.EN_US,
        **{
            "name.en_US": "mirror",
            "orderby": "id:desc",
            "_page": 1
        }
    )
```

### Available Search Methods

#### World of Warcraft Game Data

- `search_azerite_essence()` - Search azerite essences
- `search_covenant()` - Search covenants
- `search_creature()` - Search creatures
- `search_decor()` - Search housing decor items
- `search_item()` - Search items
- `search_media()` - Search media assets
- `search_mount()` - Search mounts
- `search_pet()` - Search battle pets
- `search_profession()` - Search professions
- `search_spell()` - Search spells

### Common Search Parameters

| Parameter       | Description              | Example              |
| --------------- | ------------------------ | -------------------- |
| `name.{locale}` | Filter by localized name | `name.en_US: "wall"` |
| `orderby`       | Sort results             | `"id"`, `"id:desc"`  |
| `_page`         | Page number (1-indexed)  | `1`, `2`, `3`        |

### Search Response Structure

```python
{
    "page": 1,
    "pageSize": 100,
    "maxPageSize": 100,
    "pageCount": 10,
    "results": [
        {
            "key": {"href": "..."},
            "data": {
                "id": 534,
                "name": {"en_US": "Plain Interior Wall"},
                # ... additional fields
            }
        }
    ]
}
```

## Error Handling

```python
from blizzardapi3 import BlizzardAPI
from blizzardapi3.exceptions import NotFoundError, RateLimitError

with BlizzardAPI(client_id, client_secret) as api:
    try:
        data = api.wow.game_data.get_achievement(
            region="us",
            locale="en_US",
            achievement_id=999999
        )
    except NotFoundError:
        print("Achievement not found")
    except RateLimitError as e:
        print(f"Rate limited. Retry after {e.retry_after} seconds")
```

## Comprehensive Examples

### Character Profile Information

```python
from blizzardapi3 import BlizzardAPI, Region, Locale

with BlizzardAPI(client_id, client_secret) as api:
    # Get character appearance
    appearance = api.wow.profile.get_character_appearance_summary(
        region=Region.US,
        locale=Locale.EN_US,
        realm_slug="illidan",
        character_name="beyloc"
    )

    print(f"Character: {appearance['character']['name']}")
    print(f"Race: {appearance['playable_race']['name']}")
    print(f"Class: {appearance['playable_class']['name']}")
    print(f"Spec: {appearance['active_spec']['name']}")

    # Get character equipment
    equipment = api.wow.profile.get_character_equipment_summary(
        region=Region.US,
        locale=Locale.EN_US,
        realm_slug="illidan",
        character_name="beyloc"
    )

    for item in equipment['equipped_items']:
        print(f"{item['slot']['name']}: {item['name']}")
```

### Building a Decor Browser

```python
from blizzardapi3 import BlizzardAPI, Region, Locale

def search_decor_by_name(api, search_term, page=1):
    """Search for decor items by name with pagination."""
    results = api.wow.game_data.search_decor(
        region=Region.US,
        locale=Locale.EN_US,
        **{
            "name.en_US": search_term,
            "orderby": "id",
            "_page": page
        }
    )

    items = []
    for result in results['results']:
        data = result['data']
        items.append({
            'id': data['id'],
            'name': data['name']['en_US'],
            'href': result['key']['href']
        })

    return {
        'items': items,
        'page': results['page'],
        'total_pages': results['pageCount'],
        'has_more': results['page'] < results['pageCount']
    }

with BlizzardAPI(client_id, client_secret) as api:
    # Search for walls
    result = search_decor_by_name(api, "wall", page=1)

    for item in result['items']:
        print(f"{item['name']} (ID: {item['id']})")

    if result['has_more']:
        print(f"\nShowing page {result['page']} of {result['total_pages']}")
```

### Item Search with Filtering

```python
with BlizzardAPI(client_id, client_secret) as api:
    # Search for epic quality items
    items = api.wow.game_data.search_item(
        region=Region.US,
        locale=Locale.EN_US,
        **{
            "name.en_US": "sword",
            "orderby": "id:desc",
            "_page": 1
        }
    )

    for result in items['results'][:10]:
        item = result['data']
        print(f"{item['name']['en_US']} (ID: {item['id']})")
```

### Async Batch Operations

```python
import asyncio
from blizzardapi3 import BlizzardAPI, Region, Locale

async def get_multiple_achievements(api, achievement_ids):
    """Fetch multiple achievements concurrently."""
    tasks = [
        api.wow.game_data.get_achievement_async(
            region=Region.US,
            locale=Locale.EN_US,
            achievement_id=aid
        )
        for aid in achievement_ids
    ]
    return await asyncio.gather(*tasks)

async def main():
    async with BlizzardAPI(client_id, client_secret) as api:
        achievement_ids = [6, 7, 8, 9, 10]
        achievements = await get_multiple_achievements(api, achievement_ids)

        for ach in achievements:
            print(f"{ach['name']} - {ach['points']} points")

asyncio.run(main())
```

### Guild Information

```python
with BlizzardAPI(client_id, client_secret) as api:
    # Get guild roster
    roster = api.wow.profile.get_guild_roster(
        region=Region.US,
        locale=Locale.EN_US,
        realm_slug="illidan",
        name_slug="your-guild-name"
    )

    for member in roster['members']:
        char = member['character']
        print(f"{char['name']} - Level {char['level']} {char.get('playable_class', {}).get('name', 'Unknown')}")
```

### Diablo 3 Examples

```python
from blizzardapi3 import BlizzardAPI, Region, Locale

with BlizzardAPI(client_id, client_secret) as api:
    # Get D3 season index
    seasons = api.d3.game_data.get_season_index(
        region=Region.US,
        locale=Locale.EN_US
    )
    print(f"Current season: {seasons['current_season']}")

    # Get a player's career profile
    profile = api.d3.community.get_career(
        region=Region.US,
        locale=Locale.EN_US,
        battle_tag="BattleTag-1234"
    )
    print(f"Paragon level: {profile['paragonLevel']}")

    # Get item type index
    item_types = api.d3.game_data.get_item_type_index(
        region=Region.US,
        locale=Locale.EN_US
    )
```

### Hearthstone Examples

```python
from blizzardapi3 import BlizzardAPI, Region, Locale

with BlizzardAPI(client_id, client_secret) as api:
    # Search for cards
    cards = api.hearthstone.game_data.search_cards(
        region=Region.US,
        locale=Locale.EN_US,
        **{"class": "mage", "manaCost": 3}
    )
    for card in cards['cards'][:5]:
        print(f"{card['name']} - {card['manaCost']} mana")

    # Get card backs
    card_backs = api.hearthstone.game_data.search_card_backs(
        region=Region.US,
        locale=Locale.EN_US
    )

    # Get metadata
    metadata = api.hearthstone.game_data.get_metadata(
        region=Region.US,
        locale=Locale.EN_US
    )
```

### StarCraft 2 Examples

```python
from blizzardapi3 import BlizzardAPI, Region, Locale

with BlizzardAPI(client_id, client_secret) as api:
    # Get league data
    league = api.sc2.game_data.get_league_data(
        region=Region.US,
        locale=Locale.EN_US,
        season_id=44,
        queue_id=201,
        team_type="0",
        league_id=6
    )

    # Get static profile data
    static = api.sc2.community.get_static_profile(
        region=Region.US,
        locale=Locale.EN_US,
        region_id=1
    )

    # Get grandmaster leaderboard
    gm_ladder = api.sc2.community.get_grandmaster_leaderboard(
        region=Region.US,
        locale=Locale.EN_US,
        region_id=1
    )
```

## Supported Games

- **World of Warcraft** - Game Data & Profile APIs (~290 endpoints)
  - Game Data: Achievements, Items, Mounts, Pets, Auctions, Housing/Decor, and more
  - Profile: Characters, Guilds, Mythic+, PvP, Collections, Equipment
- **Diablo 3** - Community & Game Data APIs (39 endpoints)
  - Game Data: Items, item types, seasons, eras
  - Community: Career profiles, heroes, items, followers
- **Hearthstone** - Game Data API (12 endpoints)
  - Cards, card backs, decks, metadata search
- **StarCraft 2** - Community & Game Data APIs (22 endpoints)
  - Game Data: League data
  - Community: Profiles, ladders, grandmaster leaderboards

**Total: 363 endpoints** (726 methods including async variants)

## Documentation

### Core Documentation

- **[Search Guide](docs/SEARCH_GUIDE.md)** - Comprehensive guide to using search endpoints with real-world examples
- **[Search Quick Reference](docs/SEARCH_QUICK_REFERENCE.md)** - Quick reference for all search methods and parameters
- **[OAuth Guide](docs/OAUTH_GUIDE.md)** - Complete guide to OAuth authorization code flow for user-specific endpoints

### Additional Resources

- [Blizzard API Official Documentation](https://develop.battle.net/documentation)
- [GitHub Repository](https://github.com/lostcol0ny/blizzardapi3)
- [Issue Tracker](https://github.com/lostcol0ny/blizzardapi3/issues)

## Development

```bash
# Clone the repository
git clone https://github.com/lostcol0ny/blizzardapi3.git
cd blizzardapi3

# Install development dependencies
pip install -e ".[dev]"

# Run tests
pytest

# Format code
black .
ruff check .

# Regenerate stub files for IDE autocomplete (after modifying YAML configs)
python scripts/generate_stubs.py
```

### IDE Autocomplete

BlizzardAPI uses `.pyi` stub files to provide full IDE autocomplete for all dynamically generated API methods. If you modify the YAML endpoint configurations, run the stub generator to update the type hints:

```bash
python scripts/generate_stubs.py
```

This generates stub files in `blizzardapi3/api/` for each game API.

## Architecture

BlizzardAPI v3 uses a config-driven architecture:

- **YAML Endpoint Definitions** - All API endpoints defined in YAML configs
- **Dynamic Method Generation** - Methods generated at runtime from configs
- **Pydantic Models** - Type-safe response models
- **Custom Exceptions** - Detailed error hierarchy
- **Single Session** - Efficient session management with proper cleanup
