Neuer `sync`-Subcommand: authentifiziert über den Personal-Access-Token gegen GET /api/sync/ + GET /books/<id>/data/, entschlüsselt Metadaten und Buchbytes lokal mit AES-256-GCM (diora_tui/crypto.py, kompatibel zu static/js/app.js' encryptBytes/decryptBytes) und legt EPUBs als normale Dateien in der Library ab — PDFs werden übersprungen. Zugangsdaten (Server-URL, Token, Base64-Key) landen auf Wunsch in ~/.config/diora-tui/config.json (0600), sonst interaktive Abfrage pro Lauf. Lesefortschritt wird bewusst noch nicht synced: der Server verankert Position als "blockIndex:innerFraction" in der Absatz-Nummerierung des Web-Readers, die nicht 1:1 auf das Kapitel-basierte scroll_fraction dieser TUI abbildet — ein naiver Abgleich würde falsche Positionen liefern. Getestet: AES-GCM-Rundreise + Falsch-Schlüssel-Ablehnung, vollständiger sync-Lauf gegen einen echten Dev-Server (Token/Key-Abfrage, Download, Entschlüsselung, Dedup bei erneutem Lauf, Fehlerfälle bei falschem Token/Key, --save inkl. 0600-Datei und Wiederverwendung ohne Prompt).
74 lines
3.4 KiB
Markdown
74 lines
3.4 KiB
Markdown
# diora-tui
|
|
|
|
Lokaler EPUB-Reader im Terminal — die erste Stufe einer TUI-Version von diora.
|
|
|
|
Läuft komplett offline gegen eine lokale Bibliothek aus `.epub`-Dateien und merkt sich
|
|
den Lesefortschritt pro Buch (`progress.json` im plattformüblichen Datenverzeichnis,
|
|
z.B. `~/.local/share/diora-tui/` unter Linux, via `platformdirs`). Der Fortschritt wird
|
|
— genau wie im Web-Reader von diora (siehe `books/models.py`, `save_progress`) — nur
|
|
vorwärts überschrieben ("furthest wins"), damit ein älterer/gestaffelter Lauf nie eine
|
|
bereits weiter gelesene Position zurücksetzt.
|
|
|
|
`diora-tui sync` kann Bücher jetzt vom diora-Server holen und lokal entschlüsseln (siehe
|
|
unten) — Lesefortschritt bleibt aber weiterhin rein lokal, siehe **Grenzen** unten.
|
|
|
|
## Setup
|
|
|
|
```bash
|
|
cd tui
|
|
pip install -e .
|
|
```
|
|
|
|
## Nutzung
|
|
|
|
```bash
|
|
diora-tui --library ~/Books # Standard: ~/Books
|
|
```
|
|
|
|
Tastenkürzel:
|
|
|
|
- `↑`/`k`, `↓`/`j` — zeilenweise scrollen
|
|
- `n` / `]` — nächstes Kapitel, `p` / `[` — vorheriges Kapitel
|
|
- `Enter` — markiertes Buch aus der Bibliothek öffnen
|
|
- `Escape` / `q` — zurück zur Bibliothek (im Reader) bzw. beenden (in der Bibliothek)
|
|
|
|
## Bücher vom Server holen (`diora-tui sync`)
|
|
|
|
```bash
|
|
diora-tui sync # nutzt gespeicherte Zugangsdaten, sonst interaktive Abfrage
|
|
diora-tui sync --server https://diora.creamfresh.xyz --save # einmalig einrichten + speichern
|
|
```
|
|
|
|
Lädt alle EPUBs des Accounts über `GET /api/sync/` + `GET /books/<id>/data/` herunter,
|
|
entschlüsselt sie lokal (AES-256-GCM, kompatibel zu `static/js/app.js`) und legt sie als
|
|
normale `.epub`-Dateien in `--library` ab (Dateiname `<id> - <Titel>.epub`) — von da an
|
|
funktionieren sie wie jedes andere lokale Buch. Bereits heruntergeladene Bücher werden
|
|
beim nächsten Lauf übersprungen (kein erneuter Download).
|
|
|
|
Dafür nötig, beim ersten Lauf abgefragt (danach optional lokal gespeichert unter
|
|
`~/.config/diora-tui/config.json`, `chmod 600`):
|
|
|
|
- **Server-URL** — z.B. `https://diora.creamfresh.xyz`.
|
|
- **API-Token** — diora → Einstellungen (`/accounts/settings/`) → "Personal Access Token".
|
|
- **Verschlüsselungs-Key (Base64)** — der AES-Schlüssel, mit dem deine Bücher im Browser
|
|
verschlüsselt wurden. Der Export-Button dafür ist im UI aktuell nicht verdrahtet
|
|
(`exportEncKey()` in `app.js` existiert, hat aber keinen sichtbaren Button); bis das
|
|
nachgezogen ist, in der Browser-Devtools-Konsole auf der diora-Seite ausführen:
|
|
```js
|
|
await exportEncKey()
|
|
```
|
|
Das kopiert den Key ins Clipboard — von dort ins `sync`-Prompt einfügen.
|
|
|
|
Der Key/Token wird genauso vertrauensvoll behandelt wie im Web-Client (dort liegt der
|
|
Schlüssel unverschlüsselt in `localStorage`): lokal als Klartext in einer 0600-Datei.
|
|
|
|
## Grenzen der aktuellen Version
|
|
|
|
- Nur EPUB, kein PDF — `sync` lädt PDFs im Account gar nicht erst herunter (übersprungen,
|
|
wird gemeldet), da der Reader sie ohnehin nicht darstellen kann.
|
|
- Text wird pro Kapitel als Fließtext ohne Bild-/Layout-Rendering dargestellt.
|
|
- Lesefortschritt bleibt rein lokal — `sync` holt nur Bücher, keinen Fortschritt. Der
|
|
Web-Reader verankert Position als `"blockIndex:innerFraction"` in seiner eigenen, über
|
|
das ganze Buch laufenden Absatz-Nummerierung; diese TUI zählt Position dagegen pro
|
|
Kapitel. Ohne eine echte Übersetzung zwischen beiden Schemata würde ein naiver Abgleich
|
|
falsche Positionen liefern — deshalb bewusst (noch) nicht gebaut.
|