Metadata-Version: 2.4
Name: steam-fetcher
Version: 0.1.1
Summary: Typed Python client for Steam Store and Web API
Project-URL: Homepage, https://github.com/cop1cat/steam-fetcher
Project-URL: Repository, https://github.com/cop1cat/steam-fetcher
Project-URL: Issues, https://github.com/cop1cat/steam-fetcher/issues
Project-URL: Changelog, https://github.com/cop1cat/steam-fetcher/blob/main/CHANGELOG.md
Author: cop1cat
License: MIT
License-File: LICENSE
Keywords: api,async,pydantic,steam
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Typing :: Typed
Requires-Python: >=3.12
Requires-Dist: httpx>=0.27.0
Requires-Dist: pydantic>=2.0.0
Requires-Dist: tenacity>=8.0.0
Provides-Extra: all
Requires-Dist: aiolimiter>=1.1.0; extra == 'all'
Requires-Dist: polars>=0.20.0; extra == 'all'
Requires-Dist: sqlalchemy>=2.0.0; extra == 'all'
Requires-Dist: typer>=0.12.0; extra == 'all'
Provides-Extra: async
Requires-Dist: aiolimiter>=1.1.0; extra == 'async'
Provides-Extra: cli
Requires-Dist: typer>=0.12.0; extra == 'cli'
Provides-Extra: dev
Requires-Dist: aiolimiter>=1.1.0; extra == 'dev'
Requires-Dist: mkdocs-material>=9.0.0; extra == 'dev'
Requires-Dist: mkdocs-static-i18n>=1.0.0; extra == 'dev'
Requires-Dist: mypy>=1.19.1; extra == 'dev'
Requires-Dist: pre-commit>=4.5.1; extra == 'dev'
Requires-Dist: pytest-asyncio>=0.23.0; extra == 'dev'
Requires-Dist: pytest-cov>=5.0.0; extra == 'dev'
Requires-Dist: pytest>=8.0.0; extra == 'dev'
Requires-Dist: respx>=0.21.0; extra == 'dev'
Requires-Dist: ruff>=0.15.4; extra == 'dev'
Requires-Dist: typer>=0.12.0; extra == 'dev'
Provides-Extra: docs
Requires-Dist: mkdocs-material>=9.0.0; extra == 'docs'
Requires-Dist: mkdocs-static-i18n>=1.0.0; extra == 'docs'
Provides-Extra: parquet
Requires-Dist: polars>=0.20.0; extra == 'parquet'
Provides-Extra: sql
Requires-Dist: sqlalchemy>=2.0.0; extra == 'sql'
Provides-Extra: tests
Requires-Dist: pytest-asyncio>=0.23.0; extra == 'tests'
Requires-Dist: pytest-cov>=5.0.0; extra == 'tests'
Requires-Dist: pytest>=8.0.0; extra == 'tests'
Requires-Dist: respx>=0.21.0; extra == 'tests'
Requires-Dist: typer>=0.12.0; extra == 'tests'
Description-Content-Type: text/markdown

# steam-fetcher

<p align="center">
  <a href="https://pypi.org/project/steam-fetcher/"><img src="https://img.shields.io/pypi/v/steam-fetcher" alt="PyPI"></a>
  <a href="https://pypi.org/project/steam-fetcher/"><img src="https://img.shields.io/pypi/pyversions/steam-fetcher" alt="Python"></a>
  <a href="https://github.com/cop1cat/steam-fetcher/blob/main/LICENSE"><img src="https://img.shields.io/github/license/cop1cat/steam-fetcher" alt="License"></a>
</p>

Typed Python client for the Steam Store API, Steam Web API, and SteamSpy API.

## Features

- **Sync & async clients** with identical API
- **Pydantic v2 models** for all responses
- **Rate limiting** — sync (threading) and async (aiolimiter)
- **Retry logic** with exponential backoff (only on 5xx errors)
- **Exporters** — JSON, CSV, Parquet, SQL
- **CLI** via typer
- **API key safety** via `SecretStr`

## Installation

```bash
pip install steam-fetcher
```

Optional extras:

```bash
pip install steam-fetcher[async]     # async client
pip install steam-fetcher[parquet]   # Parquet export (polars)
pip install steam-fetcher[sql]       # SQL export (SQLAlchemy)
pip install steam-fetcher[cli]       # CLI (typer)
pip install steam-fetcher[all]       # everything
```

## Quick start

### Public API (no key required)

```python
from steam_fetcher import SteamClient

with SteamClient() as client:
    game = client.get_game(730)
    print(game.name)  # Counter-Strike 2

    players = client.get_player_count(730)
    print(players.player_count)  # 684339

    results = client.search("half-life")
    for entry in results.entries:
        print(f"{entry.name} — {entry.price}")

    reviews = client.get_reviews(730, num_per_page=5)
    print(f"{reviews.score_description}: {reviews.positive}/{reviews.total}")

    news = client.get_news(730, count=3)
    for item in news.items:
        print(item.title)
```

### Async

```python
import asyncio
from steam_fetcher import AsyncSteamClient

async def main():
    async with AsyncSteamClient() as client:
        games = await asyncio.gather(
            client.get_game(730),
            client.get_game(570),
            client.get_game(440),
        )
        for g in games:
            if g:
                print(g.name)

asyncio.run(main())
```

### Authenticated API (requires [Steam Web API key](https://steamcommunity.com/dev/apikey))

```python
from steam_fetcher import SteamAuthClient

with SteamAuthClient(api_key="YOUR_KEY") as client:
    profile = client.get_user_profile("76561198000000000")
    print(profile.username)

    library = client.get_user_library("76561198000000000")
    print(f"{library.game_count} games")

    friends = client.get_user_friends("76561198000000000")
    bans = client.get_user_bans(["76561198000000000"])
    badges = client.get_user_badges("76561198000000000")
    level = client.get_steam_level("76561198000000000")
    steam_id = client.resolve_vanity_url("gabelogannewell")

    schema = client.get_game_schema(730)
    app_list = client.get_app_list(max_results=100)
```

### Export

```python
from steam_fetcher.exporters import JsonExporter, CsvExporter

JsonExporter().export([game], "game.json")
CsvExporter().export([game], "game.csv")
```

### CLI

```bash
pip install steam-fetcher[cli]

steam-fetcher games details 730
steam-fetcher games search "portal" --format csv --output results.csv
steam-fetcher games players 730
steam-fetcher games news 730 --count 5
steam-fetcher users profile 76561198000000000 --api-key YOUR_KEY
steam-fetcher users friends 76561198000000000 --api-key YOUR_KEY
```

## Available methods

### Public (SteamClient / AsyncSteamClient)

| Method | Returns |
|--------|---------|
| `get_game(app_id, country, language)` | `GameDetails` |
| `get_player_count(app_id)` | `PlayerCount` |
| `get_reviews(app_id, language, review_filter, num_per_page, cursor)` | `ReviewSummary` |
| `search(query, country, language)` | `SearchResult` |
| `get_steamspy_details(app_id)` | `SteamSpyDetails` |
| `get_news(app_id, count, max_length)` | `AppNews` |
| `get_global_achievement_percentages(app_id)` | `GlobalAchievements` |

### Authenticated (SteamAuthClient / AsyncSteamAuthClient)

All public methods plus:

| Method | Returns |
|--------|---------|
| `get_user_profile(steam_id)` | `UserProfile` |
| `get_user_profiles(steam_ids)` | `list[UserProfile]` |
| `get_user_library(steam_id)` | `UserLibrary` |
| `get_user_achievements(steam_id, app_id)` | `GameAchievements` |
| `get_user_friends(steam_id)` | `FriendList` |
| `get_user_bans(steam_ids)` | `list[PlayerBan]` |
| `resolve_vanity_url(vanity_url)` | `str` |
| `get_recently_played(steam_id)` | `RecentlyPlayed` |
| `get_steam_level(steam_id)` | `int` |
| `get_user_badges(steam_id)` | `UserBadges` |
| `get_wishlist(steam_id)` | `list[WishlistItem]` |
| `get_user_stats(steam_id, app_id)` | `UserStats` |
| `get_game_schema(app_id)` | `GameSchema` |
| `get_app_list(last_appid, max_results)` | `AppList` |

## Documentation

Full docs: [cop1cat.github.io/steam-fetcher](https://cop1cat.github.io/steam-fetcher) (English + Русский)

## License

MIT
