Metadata-Version: 2.4
Name: nyora
Version: 0.3.0
Summary: Python SDK and terminal UI (nyora-cli/TUI) for operating Nyora manga sources.
Project-URL: Homepage, https://nyora.app
Project-URL: Documentation, https://nyora.app/docs/python/
Project-URL: Repository, https://github.com/hasan72341/Nyora
Project-URL: Issues, https://github.com/hasan72341/Nyora/issues
Author: Md Hasan Raza
License: GPL-3.0-only
Keywords: manga,nyora,sdk,tui
Classifier: Development Status :: 3 - Alpha
Classifier: Environment :: Console
Classifier: Intended Audience :: Developers
Classifier: Intended Audience :: End Users/Desktop
Classifier: License :: OSI Approved :: GNU General Public License v3 (GPLv3)
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
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: Topic :: Internet :: WWW/HTTP
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Requires-Python: >=3.10
Requires-Dist: httpx>=0.27.0
Requires-Dist: platformdirs>=4.2.0
Requires-Dist: quickjs>=1.19.4
Requires-Dist: rich>=13.7.0
Requires-Dist: selectolax>=0.4.10
Requires-Dist: textual>=0.86.0
Requires-Dist: typing-extensions>=4.12.0
Provides-Extra: dev
Requires-Dist: build>=1.2.0; extra == 'dev'
Requires-Dist: mypy>=1.11.0; extra == 'dev'
Requires-Dist: pytest>=8.2.0; extra == 'dev'
Requires-Dist: ruff>=0.6.0; extra == 'dev'
Requires-Dist: twine>=5.1.0; extra == 'dev'
Provides-Extra: docs
Requires-Dist: furo>=2024.5; extra == 'docs'
Requires-Dist: linkify-it-py>=2.0; extra == 'docs'
Requires-Dist: myst-parser>=3.0; extra == 'docs'
Requires-Dist: sphinx-autodoc-typehints>=2.0; extra == 'docs'
Requires-Dist: sphinx-copybutton>=0.5; extra == 'docs'
Requires-Dist: sphinx>=7.3; extra == 'docs'
Provides-Extra: tui
Requires-Dist: rich>=13.7.0; extra == 'tui'
Requires-Dist: textual>=0.86.0; extra == 'tui'
Description-Content-Type: text/markdown

<div align="center">

<img src="https://nyora.pages.dev/icon.png" width="120" alt="Nyora" />

# Nyora — Python

### Read like the world can wait.

The official Python package for **Nyora** — script your library, search 1000+ manga sources, and fetch chapters and pages straight from Python. Pure Python: no JVM, no desktop app, no Node.js, no Java. Just `pip install`.

<p>
  <img alt="Python" src="https://img.shields.io/badge/Python-3776AB?style=for-the-badge&logo=python&logoColor=white" />
  <a href="https://pypi.org/project/nyora/"><img alt="PyPI version" src="https://img.shields.io/pypi/v/nyora?style=for-the-badge&logo=pypi&logoColor=white" /></a>
  <a href="https://pypi.org/project/nyora/"><img alt="Python versions" src="https://img.shields.io/pypi/pyversions/nyora?style=for-the-badge&logo=python&logoColor=white" /></a>
</p>

<p>
  <a href="https://www.gnu.org/licenses/gpl-3.0"><img alt="License: GPL v3" src="https://img.shields.io/badge/License-GPLv3-blue.svg?style=for-the-badge" /></a>
  <a href="https://github.com/Hasan72341/nyora-python/stargazers"><img alt="Stars" src="https://img.shields.io/github/stars/Hasan72341/nyora-python?style=for-the-badge&logo=github&logoColor=white" /></a>
  <a href="https://github.com/Hasan72341/nyora-python/pulls"><img alt="PRs welcome" src="https://img.shields.io/badge/PRs-welcome-FF4655?style=for-the-badge&logo=github&logoColor=white" /></a>
</p>

<p>
  <a href="https://nyora.app/docs/python/"><img alt="Documentation" src="https://img.shields.io/badge/Docs-nyora.app%2Fdocs%2Fpython-0ae448?style=for-the-badge&logo=readthedocs&logoColor=white" /></a>
  <a href="https://pypi.org/project/nyora/"><img alt="Install from PyPI" src="https://img.shields.io/badge/Install-pip_install_nyora-3776AB?style=for-the-badge&logo=pypi&logoColor=white" /></a>
  <a href="https://nyora.pages.dev"><img alt="Website" src="https://img.shields.io/badge/Website-nyora.app-FF4655?style=for-the-badge&logo=githubpages&logoColor=white" /></a>
</p>

</div>

---

## About

Nyora is a fast, free, ad-free, open-source manga reader that runs on **every** platform — with whole-page AI translation, 1000+ sources, offline downloads, and free cloud sync across all your devices. `nyora` brings that same source-and-parser engine to Python: a pip-installable library, a command-line tool (`nyora-cli`), and a terminal reader (TUI).

It runs the full Nyora parser bundle in-process through Python-installed dependencies — pure Python, end to end, with nothing to compile and no companion app to launch.

📖 **Full documentation: [nyora.app/docs/python](https://nyora.app/docs/python/)**

```bash
pip3 install nyora
```

This single install gives you **both** things below — a Python library you import, and the `nyora-cli` command-line tool. They are documented as clearly separate surfaces.

---

## Python library (`pip install nyora`)

`import nyora` to drive Nyora's source/parser engine from your own code. Open a `Nyora()` client, find a source, search it, fetch details, and resolve page image URLs — all with a clean, typed API. No JVM helper, no desktop app, no Node.js, no Java.

```python
from nyora import Nyora

with Nyora() as client:
    source = client.sources.find("mangadex")          # resolve by id or fuzzy name
    page = client.manga.popular(source.id)            # SearchPage of entries
    entry = page.entries[0]

    details = client.manga.details(source.id, entry.url, title=entry.title)
    pages = client.manga.pages(source.id, details.chapters[0].url)

    for p in pages:
        print(p.url)
```

The client exposes two typed namespaces:

- **`client.sources`** — `list()` the full bundled catalogue, or `find(...)` a source by **id** or fuzzy **name** (e.g. `"asura"`).
- **`client.manga`** — `popular(...)`, `latest(...)`, `search(...)`, `details(...)`, and `pages(...)`.

For concurrent fan-out across many sources, use the async client, which exposes the same namespaces:

```python
import asyncio
from nyora import AsyncNyora

async def main():
    async with AsyncNyora() as client:
        source = await client.sources.find("asura")
        results = await client.manga.search(source.id, "Solo Leveling")
        print(results.entries[0].title)

asyncio.run(main())
```

You can also attach to an already-running Nyora helper (the desktop helper, another app, or `nyora-cli serve`) over its REST contract instead of running the engine in-process:

```python
from nyora import NyoraHelper

with NyoraHelper.attach("http://127.0.0.1:54123") as client:
    print(client.health())
```

The parser bundle and source catalogue update **over the air**, so new and fixed sources arrive without upgrading the package:

```python
from nyora import Nyora

with Nyora() as client:
    available, installed, latest = client.check_update()
    if available:
        result = client.update()        # sha256-verified, atomic
        print("updated to OTA version", result.version)
```

→ Library guide: **[nyora.app/docs/python/guide/library](https://nyora.app/docs/python/guide/library.html)** · API reference: **[/reference/api](https://nyora.app/docs/python/reference/api.html)**

---

## Command line (`nyora-cli`)

Installing the package adds the **`nyora-cli`** command (also aliased as `nyora`). It drives the same pure-Python engine as the library.

> **Running bare `nyora-cli` with no subcommand launches the terminal reader (TUI).** Pass a subcommand to run a one-shot command instead.

```bash
nyora-cli                                    # no subcommand -> launches the TUI
nyora-cli sources --search asura             # one-shot subcommand
nyora-cli search -s asura "Solo Leveling"
```

### Subcommands

| Command | Description |
|---|---|
| `sources [--search Q]` | List the source catalogue, or fuzzy-find sources by name |
| `search -s SRC [-p PAGE] QUERY` | Search a source for a query |
| `popular -s SRC [-p PAGE]` | Browse a source's popular titles |
| `latest -s SRC [-p PAGE]` | Browse a source's latest updates |
| `details -s SRC URL` | Fetch manga details and the full chapter list |
| `pages -s SRC CHAPTER_URL [--branch B]` | Resolve page image URLs for a chapter |
| `download -s SRC CHAPTER_URL [-o DIR]` | Download every page image of a chapter to `DIR` |
| `update [--force]` | Self-update the parser bundle over the air (OTA) |
| `serve [--host H] [--port P]` | Run the pure-Python REST helper |
| `version` | Print the package and installed OTA version |

`-s/--source` accepts a source **id** or a fuzzy **name** (e.g. `asura`). Add the global `--json` flag to any subcommand to emit raw JSON instead of a pretty table — ideal for piping into `jq` or wiring into scripts:

```bash
nyora-cli --json popular -s mangadex -p 1
```

### Terminal reader (TUI)

Run bare `nyora-cli` (or `nyora-tui`) to open the full terminal reader, built on [Textual](https://github.com/Textualize/textual): pick a source, browse popular/latest/search, open a title, and page through a chapter — all without leaving the shell. It is non-TTY safe: in a non-interactive shell it prints a friendly notice and exits cleanly.

```bash
nyora-cli        # launches the TUI
nyora-tui        # also launches the TUI
```

### Pure-Python REST helper

`nyora-cli serve` starts a small stdlib HTTP server that exposes the engine over the same camelCase REST contract the desktop helper uses, so any other Nyora app (or `NyoraHelper.attach(...)`) can connect:

```bash
nyora-cli serve --host 127.0.0.1 --port 0
# -> http://127.0.0.1:54123
```

It binds the requested host/port (port `0` picks a free port), prints the base URL, and writes a `helper.port` file so other Nyora processes can auto-discover it. Endpoints include `/health`, `/sources`, `/sources/popular`, `/sources/latest`, `/sources/search`, `/manga/details`, and `/manga/pages`.

→ CLI guide: **[/guide/cli](https://nyora.app/docs/python/guide/cli.html)** · TUI guide: **[/guide/tui](https://nyora.app/docs/python/guide/tui.html)** · Server guide: **[/guide/server](https://nyora.app/docs/python/guide/server.html)**

---

## Installation

### From PyPI (recommended)

```bash
pip3 install nyora
```

This installs the `nyora` Python library **and** the `nyora-cli` command (aliased as `nyora`), including the Textual-based terminal reader and the REST helper. It is pure Python with only Python-installed dependencies — no JVM helper, desktop app, Node.js, or Java to install.

| Install | Command | Adds |
|---|---|---|
| Default | `pip3 install nyora` | Library + `nyora-cli` + TUI + REST helper |
| Docs tooling | `pip3 install "nyora[docs]"` | Sphinx + Furo to build these docs |
| Dev tooling | `pip3 install "nyora[dev]"` | Build, test, lint, and publish tooling |

### Requirements

- **Python 3.10 or newer** (tested through 3.14).
- A network connection for source requests and OTA parser-bundle updates.

### Troubleshooting

- **`nyora-cli: command not found`** — ensure your Python `Scripts`/`bin` directory is on your `PATH`, or invoke it as `python -m nyora`.
- **Stale or missing sources** — run `nyora-cli update` (or `--force`), then `nyora-cli version` to confirm the installed OTA version.
- **Permission errors writing the cache** — the OTA bundle is written into the user cache directory; make sure that location is writable for your user.

---

## What it can and cannot do

| Capability | Supported | Notes |
|---|---|---|
| List the full source catalogue | Yes | `client.sources.list()` / `nyora-cli sources` |
| Resolve a source by id or fuzzy name | Yes | `client.sources.find(...)` |
| Popular / latest / search browsing | Yes | `client.manga.popular` · `.latest` · `.search` |
| Manga details + full chapter list | Yes | `client.manga.details(...)` |
| Resolve page image URLs | Yes | `client.manga.pages(...)` |
| Download a chapter's pages to disk | Yes | `nyora-cli download` |
| Synchronous **and** async clients | Yes | `Nyora` and `AsyncNyora` |
| Run as a REST helper / attach to one | Yes | `nyora-cli serve` · `NyoraHelper.attach(...)` |
| OTA self-update of sources | Yes | sha256-verified, atomic writes |
| Pure Python — no JVM / Node.js / Java | Yes | Runs the parser bundle in-process |
| Host the consumer reading UI | No | Use the platform apps for a full reader |
| Bundled OCR / image translation pipeline | No | Translation lives in the consumer apps; the library gives you the page URLs to build on |
| Bypass a source's own access controls | No | It parses publicly accessible providers only |

---

## Build from source

For local development in this repository, the project is managed with [`uv`](https://github.com/astral-sh/uv).

```bash
uv sync --extra dev --extra docs
uv run python -c "from nyora import Nyora, Manga, Source; print(Nyora, Manga, Source)"
```

`uv sync` resolves and installs all dependencies into a managed virtual environment, and the `uv run` smoke test confirms the core symbols import cleanly. Requires Python 3.10+.

Build the documentation locally with:

```bash
bash scripts/build-docs.sh
```

### Packaging

```bash
uv lock
uv build
uv run twine check dist/*
```

The parser bundle and source catalogue are force-included into the wheel, so a fresh install can run the engine immediately and update over the air from there.

---

## Nyora on every platform

The Nyora reader is everywhere your screens are — and your library, history, bookmarks, and progress sync for free across all of them.

| Platform | Repo | Get it |
|---|---|---|
| Python | [nyora-python](https://github.com/Hasan72341/nyora-python) **(you are here)** | [`pip3 install nyora`](https://pypi.org/project/nyora/) |
| Android | [nyora-android](https://github.com/Hasan72341/nyora-android) | [APK](https://github.com/Hasan72341/nyora-android/releases/latest) |
| macOS | [nyora-mac](https://github.com/Hasan72341/nyora-mac) | [.dmg / brew](https://github.com/Hasan72341/nyora-mac/releases/latest) |
| Windows | [nyora-windows](https://github.com/Hasan72341/nyora-windows) | [.exe (x64/ARM64)](https://github.com/Hasan72341/nyora-windows/releases/latest) |
| Linux | [nyora-linux](https://github.com/Hasan72341/nyora-linux) | [deb · rpm · curl](https://github.com/Hasan72341/nyora-linux/releases/latest) |
| iOS / iPadOS | [nyora-ios](https://github.com/Hasan72341/nyora-ios) | [sideload IPA](https://github.com/Hasan72341/nyora-ios/releases/latest) |
| Web | [nyora-web](https://github.com/Hasan72341/nyora-web) | [nyoraweb.pages.dev](https://nyoraweb.pages.dev) |

---

## Privacy & open source

Nyora is 100% free, ad-free, and contains no tracking. `nyora` is fully auditable open-source code: there are no analytics, no telemetry, and no accounts. The only network calls it makes are to the sources you ask for and to fetch the sha256-verified OTA parser bundle. Licensed under **GPL-3.0-only**.

## Acknowledgements

Nyora's source and parser engine builds on the work of the open-source manga community. `nyora` is developed and maintained by **Md Hasan Raza** — [GitHub](https://github.com/Hasan72341) · hasanraza96@outlook.com.

## License

Licensed under **GPL-3.0-only**. See the project metadata in `pyproject.toml` for details.

---

> Nyora is not affiliated with any of the manga sources it can access.
