Metadata-Version: 2.4
Name: nu-private-api
Version: 0.1.0
Summary: Read-only Python client for discovering and parsing public NU.nl articles.
Author: 11philip22
License-Expression: MIT
Project-URL: Repository, https://github.com/11philip22/nu-private-api
Keywords: nu.nl,news,api,client
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Programming Language :: Python :: 3.10
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: httpx>=0.28
Dynamic: license-file

<div align="center">

# nu-private-api

Read-only Python client for discovering and parsing public NU.nl articles.

[![PyPI](https://img.shields.io/pypi/v/nu-private-api?style=flat-square&logo=pypi&logoColor=white)](https://pypi.org/project/nu-private-api/)
![Python](https://img.shields.io/badge/Python-%3E%3D3.10-3776ab?style=flat-square&logo=python&logoColor=white)
![License](https://img.shields.io/pypi/l/nu-private-api?style=flat-square)
[![Downloads](https://img.shields.io/pypi/dm/nu-private-api?style=flat-square)](https://pypi.org/project/nu-private-api/)

[Overview](#overview) • [Install](#install) • [Usage](#usage) • [API](#api) • [Project Layout](#project-layout)

</div>

## Overview

`nu-private-api` wraps the NU.nl web GraphQL endpoint used by the public site.
It currently does two things:

- read a NU.nl section/list page and return article URLs
- fetch a public article URL and return a small parsed article object

> [!WARNING]
> This is an unofficial client for NU.nl web endpoints. It intentionally fails
> loudly if NU.nl changes the article response shape.

## Install

Install from PyPI:

```powershell
pip install nu-private-api
```

Or from a checkout:

```powershell
pip install .
```

## Usage

```python
from nu_private_api import NuClient, SectionUrl

client = NuClient()

urls = client.section_by_url(SectionUrl.BINNENLAND)
article = client.article_by_url(urls[0])

print(article.title)
print(article.author)
print(article.body)
```

Raw section URLs work too:

```python
urls = client.section_by_url("https://www.nu.nl/binnenland")
```

You can also pass your own configured `httpx.Client`:

```python
import httpx
from nu_private_api import NuClient

http = httpx.Client(timeout=10)
client = NuClient(client=http)
```

## API

### `NuClient.section_by_url(url)`

Fetches a NU.nl section/list URL and returns de-duped absolute article URLs.

```python
urls = client.section_by_url(SectionUrl.ECONOMIE)
```

`url` can be either a `SectionUrl` enum value or a string URL.

### `NuClient.article_by_url(url)`

Fetches and parses a public article URL.

```python
article = client.article_by_url(urls[0])
```

Returns an `Article` dataclass:

```python
Article(
    url="...",
    title="...",
    description="...",
    published_at="...",
    modified_at="...",
    author="...",
    body="...",
)
```

## Python Shell Smoke Test

```powershell
python
```

```python
from nu_private_api import NuClient, SectionUrl

client = NuClient()
urls = client.section_by_url(SectionUrl.BINNENLAND)
article = client.article_by_url(urls[0])

assert urls
assert article.title
assert article.description
assert article.published_at
assert article.author
assert article.body
```

## Project Layout

```text
nu_private_api/
  __init__.py      public exports
  client.py        HTTP client and parsers
  sections.py      generated NU.nl section URL enum

docs/apis/         captured API notes
scripts/           capture and replay helpers
artifacts/         captured request data
```

## Notes

- Public article reads do not require cookies or login.
- `article_by_url()` follows the currently observed NU.nl article shape:
  base64 JSON-LD schema, `screenMetadata`, and article text blocks.
- The client is intentionally small. Add packaging, tests, and broader parsing
  only when the library needs them.
