Metadata-Version: 2.4
Name: pyfeuxdeforet-fr
Version: 0.3.0
Summary: Async Python client for the feuxdeforet.fr unofficial API
Author-email: Julien <jul-fls@users.noreply.github.com>
License-Expression: Apache-2.0
Project-URL: Homepage, https://github.com/jul-fls/pyfeuxdeforet-fr
Project-URL: Issues, https://github.com/jul-fls/pyfeuxdeforet-fr/issues
Project-URL: Repository, https://github.com/jul-fls/pyfeuxdeforet-fr
Classifier: Development Status :: 3 - Alpha
Classifier: Framework :: AsyncIO
Classifier: Intended Audience :: Developers
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Typing :: Typed
Requires-Python: >=3.12
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: aiohttp>=3.9
Dynamic: license-file

# pyfeuxdeforet-fr

[![CI](https://github.com/jul-fls/pyfeuxdeforet-fr/actions/workflows/ci.yml/badge.svg)](https://github.com/jul-fls/pyfeuxdeforet-fr/actions/workflows/ci.yml)
[![PyPI](https://img.shields.io/pypi/v/pyfeuxdeforet-fr.svg)](https://pypi.org/project/pyfeuxdeforet-fr/)

`pyfeuxdeforet-fr` is an unofficial async Python client for JSON data exposed by [feuxdeforet.fr](https://feuxdeforet.fr).

The package is intentionally small and close to the site payloads. It is meant to provide reusable transport and typed convenience models for future projects, including a possible Home Assistant / HACS integration, without baking Home Assistant entity decisions into the library.

## Features

- Async API client built for `aiohttp`.
- Fetch French regions and departments from `/api/regions`.
- Fetch national counters and vigilance/risk totals from `/api/stats`.
- Fetch homepage news summaries from `/api/home`.
- Fetch raw cartography GeoJSON from `/fdf/cartographie/geojson`.
- Bootstraps the cartography proxy from `/cartes/feux/`, including its dynamic nonce and cookies.
- Normalizes `Point`, `MultiPoint`, `Polygon`, `MultiPolygon`, and `GeometryCollection` feature geometries.
- Raw payload helpers are available for integrations that need fields not yet modeled.
- Typed package (`py.typed`) for downstream users.

## Installation

```bash
pip install pyfeuxdeforet-fr
```

## Quick start

```python
import asyncio

from aiohttp import ClientSession
from pyfeuxdeforet_fr import FeuxDeForetClient


async def main() -> None:
    async with ClientSession() as session:
        client = FeuxDeForetClient(session=session)

        regions = await client.get_regions()
        stats = await client.get_stats()
        home = await client.get_home()
        geojson = await client.get_geojson(
            last_update="2026-07-05T00:11:12+02:00",
        )

        print(f"Regions: {len(regions or [])}")
        print(f"Stats: {stats}")
        print(f"Latest article: {home.articles[0].title if home and home.articles else None}")
        print(f"GeoJSON type: {geojson.get('type') if geojson else None}")


asyncio.run(main())
```

## API overview

### `FeuxDeForetClient(session, base_url="https://feuxdeforet.fr")`

Create a client using an injected `aiohttp.ClientSession`.

The caller owns the session lifecycle. This keeps the library suitable for applications that already manage connection pooling, such as Home Assistant.

### `get_regions()` / `get_regions_payload()`

Return normalized `Region` objects, or the raw `/api/regions` payload.

Each `Region` contains `Department` entries from the source `depts` field.

### `get_stats()` / `get_stats_payload()`

Return normalized `Stats`, or the raw `/api/stats` payload.

Known fields include published fire counts over several periods and aggregated risk-zone counters.

### `get_home()` / `get_home_payload()`

Return normalized homepage article summaries, or the raw `/api/home` payload.

The raw payload is also kept on `HomeData.raw` because the homepage response may grow with sections that are not yet modeled.

### `get_geojson(scope="web", last_update=None, nonce=None, headers=None)`

Return the raw cartography GeoJSON payload.

By default, each call first loads `/cartes/feux/`, extracts
`window.fdfBridge.proxyNonce`, retains any response cookies, then reproduces the
frontend proxy request with:

```http
X-FDF-Nonce: <dynamic proxyNonce>
Referer: https://feuxdeforet.fr/cartes/feux/
```

`last_update` accepts either a `datetime` or an already formatted string. A
manual nonce and extra headers remain available for diagnostics. The legacy
`nonce="0"` value now enables automatic discovery instead of sending zero.
The automatic proxy context is cached for 30 minutes, retried on transient HTML
failures, and refreshed once when the GeoJSON proxy rejects a request.

### `extract_feature_geometries(feature)`

Return a `GeoJsonGeometry` containing the first usable `(longitude, latitude)`
point and every normalized polygon carried by a feature. This keeps complex
`GeometryCollection` fires usable by map clients while preserving their
perimeters for consumers that can render GeoJSON polygons.

## Known limitations

- This is an unofficial client and is not affiliated with feuxdeforet.fr.
- The API is not publicly documented and may change without notice.
- The HTML bootstrap format is private frontend behavior and may change without notice.
- Most endpoints are intentionally exposed through raw helpers as well as typed models.

## Development

For contributors:

```bash
python -m pip install -r requirements_dev.txt
pytest -q --cov
mypy pyfeuxdeforet_fr
python -m build
```

## Demo script

Run the full feature demo with:

```bash
python examples/demo.py
```

It exercises raw payload helpers, normalized models, and the GeoJSON endpoint. The GeoJSON call accepts overrides while reverse engineering continues:

```bash
python examples/demo.py --last-update "2026-07-05T00:11:12+02:00"
```

## License

Apache-2.0
