Metadata-Version: 2.4
Name: dannykeane
Version: 0.1.0
Summary: Official Python SDK and CLI for the dannykeane.com public API: work history, GitHub contributions, live stats, and the Habbo NPC chat. Zero dependencies.
Keywords: dannykeane,danny keane,dannykeane.com,sdk,api-client,cli,openapi,portfolio
Author: Danny Keane
Author-email: Danny Keane <me@dannykeane.co.uk>
License-Expression: MIT
License-File: LICENSE
Classifier: Development Status :: 4 - Beta
Classifier: Environment :: Console
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.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Classifier: Typing :: Typed
Maintainer: Danny Keane
Maintainer-email: Danny Keane <me@dannykeane.co.uk>
Requires-Python: >=3.9
Project-URL: Homepage, https://dannykeane.com/developers
Project-URL: Documentation, https://dannykeane.com/developers
Project-URL: API reference, https://dannykeane.com/openapi.json
Description-Content-Type: text/markdown

# dannykeane

Official Python SDK and CLI for the [dannykeane.com](https://dannykeane.com) public API: Danny Keane's work history, GitHub contribution calendar, live visitor stats, and the Habbo room NPC chat.

Zero dependencies, standard library only. Python 3.9+, fully typed.

```sh
pip install dannykeane
```

## Usage

```python
from dannykeane import DannyKeane

dk = DannyKeane()
for role in dk.iter_work():
    print(role["company"], role["years"])
```

Every endpoint is public, so there is no API key. Pass `base_url` to point at a local or preview deploy.

| Method | API operation | Endpoint |
| --- | --- | --- |
| `list_work(limit=None, cursor=None)` | `listWork` | `GET /api/v1/work` |
| `iter_work(limit=None)` | `listWork`, every page | `GET /api/v1/work` |
| `get_stats()` | `getStats` | `GET /api/v1/stats` |
| `get_github_contributions()` | `getGithubContributions` | `GET /api/v1/github-contributions` |
| `npc_chat(message, npc_id, context=None)` | `npcChat` | `POST /api/v1/npc-chat` |
| `npc_chat_health()` | `npcChatHealth` | `GET /api/v1/npc-chat` |
| `run_batch(requests)` | `runBatch` | `POST /api/v1/batch` |

Results are the API's own JSON as `TypedDict`s. The full contract is the OpenAPI document at https://dannykeane.com/openapi.json.

### Pagination

`list_work` returns one page: `{"data": [...], "next_cursor": "..."}`, with `next_cursor` set to `None` on the last page. `iter_work` follows the cursors for you.

### Errors

Every non-2xx response raises `ApiError`, parsed from the API's ErrorResponse body:

```python
from dannykeane import ApiError, DannyKeane

try:
    DannyKeane().list_work(limit=50)
except ApiError as error:
    print(error.status, error.code, error.message, error.hint)
    # 400 invalid_parameter limit must be an integer from 1 to 20 ...
```

`error.body` holds the full parsed body. Network failures raise the standard library's `urllib.error.URLError`.

### Rate limits

On a 429 the client waits out `Retry-After` and retries, up to `max_retries` (default 2). A `Retry-After` longer than `max_retry_delay` (default 60 seconds) raises immediately instead, with the wait on `error.retry_after`. Set `max_retries=0` to handle every 429 yourself.

## CLI

The package installs a `dannykeane` command. Run it without installing:

```sh
pipx run dannykeane work --limit 5
```

| Command | Operation |
| --- | --- |
| `dannykeane work [--limit N] [--cursor TOKEN] [--all]` | `listWork`; `--all` walks every page and prints one array |
| `dannykeane stats` | `getStats` |
| `dannykeane github-contributions` | `getGithubContributions` |
| `dannykeane npc-chat [--npc-id ID] <message>` | `npcChat` |
| `dannykeane npc-chat-health` | `npcChatHealth` |
| `dannykeane batch <operationId>...` | `runBatch` |

The API's JSON goes to stdout, indented when stdout is a terminal (`--pretty` forces it). Failures go to stderr as one line of ErrorResponse JSON, with stdout empty. `--base-url` or `DANNYKEANE_BASE_URL` points it at another deploy.

Exit codes: `0` success, `1` the API returned an error, `2` usage error, `3` the API could not be reached.

The npm package [`dannykeane`](https://www.npmjs.com/package/dannykeane) ships the same client and CLI for TypeScript and Node.

## Links

- Developer docs: https://dannykeane.com/developers
- OpenAPI spec: https://dannykeane.com/openapi.json
- Contact: me@dannykeane.co.uk

## License

MIT
