Metadata-Version: 2.4
Name: steampy-api
Version: 0.2.0
Summary: Python-обёртка для Steam Web API
Home-page: https://github.com/your_name/steampy
Author: your_name
Classifier: Programming Language :: Python :: 3
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Requires-Python: >=3.10
Description-Content-Type: text/markdown
Requires-Dist: requests>=2.28.0
Provides-Extra: async
Requires-Dist: aiohttp>=3.9.0; extra == "async"
Dynamic: author
Dynamic: classifier
Dynamic: description
Dynamic: description-content-type
Dynamic: home-page
Dynamic: provides-extra
Dynamic: requires-dist
Dynamic: requires-python
Dynamic: summary

# steampy

Писал это для себя — хотел сделать бота который показывает статистику друзей в CS2, полез в официальную документацию Steam и чуть не сошёл с ума. Там надо руками собирать URL, разбираться в каком interface/method/version, парсить вложенный JSON... В общем написал обёртку, чтобы больше к этому не возвращаться.

```python
from steampy import SteamClient

steam = SteamClient(api_key="...")

user = steam.user.get_profile("76561198000000000")
print(user.nickname)

games = steam.games.get_owned("76561198000000000")
print(f"игр в библиотеке: {len(games)}")
print(games[0].name, games[0].playtime_hours, "ч")  # топ по времени уже отсортирован
```

## Установка

```bash
pip install steampy-api
```

Для async-версии нужен ещё `aiohttp`:

```bash
pip install "steampy-api[async]"
```

## API-ключ

Идёшь на [steamcommunity.com/dev/apikey](https://steamcommunity.com/dev/apikey), вводишь любой домен (хоть `localhost`), получаешь ключ. Бесплатно.

---

## Что умеет

### Профили

```python
user = steam.user.get_profile("76561198000000000")
user.nickname    # имя
user.country     # "RU", "UA", "DE"...
user.is_public   # False если профиль закрыт
user.avatar_full # ссылка на аватарку

# если знаешь только ник из url типа steamcommunity.com/id/gaben
steam_id = steam.user.resolve_vanity_url("gaben")

# несколько профилей за один запрос, до 100
profiles = steam.user.get_profiles(["id1", "id2", "id3"])

# VAC-баны
bans = steam.user.get_bans("76561198000000000")
print(bans["VACBanned"])        # True/False
print(bans["NumberOfVACBans"])  # сколько раз
```

### Игры

```python
# библиотека, отсортирована по времени в игре
games = steam.games.get_owned("76561198000000000")
for g in games[:5]:
    print(g.name, "—", g.playtime_hours, "ч")

# только то, во что играл последние 2 недели
recent = steam.games.get_recent("76561198000000000")

# достижения. app_id 730 — это CS2
achievements = steam.games.get_achievements("76561198000000000", app_id=730)
done = [a for a in achievements if a.achieved]
print(f"{len(done)} из {len(achievements)}")

# статистика — убийства, смерти, матчи и т.д.
stats = steam.games.get_stats("76561198000000000", app_id=730)
print(stats["total_kills"])
print(stats["total_deaths"])
```

### Друзья

```python
friends = steam.friends.get_list("76561198000000000")

# get_list возвращает только id, профили грузи отдельно
ids = [f.steam_id for f in friends[:100]]
profiles = steam.user.get_profiles(ids)
```

### Маркет

```python
# для маркета ключ не нужен
item = steam.market.get_price(730, "AK-47 | Redline (Field-Tested)")
print(item.lowest_price)  # "1 234 ₽"
print(item.median_price)  # "1 300 ₽"
print(item.volume)        # сколько продали за сутки

# app_id игр которые чаще всего нужны:
# 730    CS2
# 570    Dota 2
# 440    TF2
# 252490 Rust
# 578080 PUBG
```

### Инвентарь

```python
# инвентарь CS2. для других игр меняй app_id
items = steam.inventory.get("76561198000000000", app_id=730)
print(f"предметов: {len(items)}")

for item in items[:5]:
    print(item.name, item.rarity)
    print(item.get_icon_url())   # ссылка на картинку
    print(item.tradable, item.marketable)

# только tradable
tradable = [i for i in items if i.tradable]

# app_id других игр:
# 570    Dota 2
# 440    TF2
# 252490 Rust
# 753    Steam (карточки, фоны, смайлики — context_id=6)
```

### Steam Store

```python
# подробная инфа об игре
game = steam.store.get_game(730)
print(game.name)             # Counter-Strike 2
print(game.genres)           # ["Экшены", "Бесплатно"]
print(game.metacritic_score) # 83
print(game.platforms)        # {"windows": True, "mac": False, "linux": True}

# цена и скидка
game = steam.store.get_game(1091500)  # Cyberpunk
print(game.price_original)   # 1999.0
print(game.price_final)      # 999.5
print(game.discount_percent) # 50
print(game.on_sale)          # True

# текущие акции (топ скидок)
sales = steam.store.get_sales()
for s in sales:
    print(f"{s.name} -{s.discount_percent}% ({s.price_final}₽)")

# поиск игры по названию
results = steam.store.search("half-life")
for r in results:
    print(r["name"], r["id"])
```

### Async (для ботов)

```python
import asyncio
from steampy import AsyncSteamClient

async def main():
    async with AsyncSteamClient(api_key="...") as steam:
        user = await steam.get_profile("76561198000000000")
        print(user.nickname)

        games = await steam.get_owned_games("76561198000000000")
        print(games[0].name, games[0].playtime_hours, "ч")

asyncio.run(main())
```

С aiogram:

```python
from steampy import AsyncSteamClient

steam = AsyncSteamClient(api_key="...")

@router.message(Command("profile"))
async def profile_cmd(message: Message):
    steam_id = message.text.split()[-1]
    user = await steam.get_profile(steam_id)
    await message.answer(f"{user.nickname} | {user.country}")

# при остановке бота
async def on_shutdown():
    await steam.close()
```

Несколько запросов параллельно через `asyncio.gather`:

```python
profile, friends, bans = await asyncio.gather(
    steam.get_profile(steam_id),
    steam.get_friends(steam_id),
    steam.get_bans(steam_id),
)
```

### Кэш

По умолчанию включён с TTL 5 минут — Steam не банит за повторные запросы и не тратишь лимиты на одни и те же данные.

```python
steam = SteamClient(api_key="...", cache_ttl=60)  # 1 минута
steam = SteamClient(api_key="...", cache_ttl=0)   # выключить кэш

# сбросить вручную
steam.clear_cache()
```

Работает одинаково для `SteamClient` и `AsyncSteamClient`.

---

## Ошибки

```python
from steampy.exceptions import SteamAPIError, SteamRateLimitError, SteamPrivateProfile

try:
    user = steam.user.get_profile("76561198000000000")
except SteamPrivateProfile:
    print("профиль закрыт")
except SteamRateLimitError:
    print("слишком много запросов, подожди")
except SteamAPIError as e:
    print(e)  # неверный ключ и прочее
except ValueError as e:
    print(e)  # пользователь не найден
```

| Исключение | Когда |
|---|---|
| `SteamAPIError` | базовый класс, неверный ключ, неожиданный ответ сервера |
| `SteamRateLimitError` | превышен лимит запросов (HTTP 429) |
| `SteamPrivateProfile` | профиль или инвентарь скрыт (HTTP 403) |
| `SteamUserNotFound` | пользователь не найден |
| `ValueError` | неверные входные данные |

---

## Что планирую добавить

- Пагинация для инвентаря (сейчас максимум 5000 предметов)
- Кэш для маркета и инвентаря (сейчас работает только для основного API)

## Если нашёл баг

Открывай issue, постараюсь ответить. PR тоже принимаю.

---

MIT
