Previously, an accidentally empty tonie folder combined with pruning
(the default) would delete every existing chapter on the tonie. Now:
- syncer.BuildPlan detects an empty local folder and returns a
Plan{Skipped: true, SkipReason: ...} instead of computing a diff
- syncer.ApplyPlan is a no-op for a skipped plan (defense in depth)
- Plan.NeedsChanges() reports false for skipped plans
- cmd/toni-sync sync prints "Skipped: <reason>" for such folders and
moves on, regardless of --no-prune
- Added a test covering the skip behavior end-to-end (BuildPlan +
ApplyPlan no-op)
- README documents the safety behavior
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
173 lines
5.2 KiB
Markdown
173 lines
5.2 KiB
Markdown
# toni-sync
|
|
|
|
Ein CLI-Tool zur Verwaltung von Kreativ-Tonies: Es synchronisiert lokale
|
|
Audio-Ordner (z. B. exportierte Deezer-Playlists) automatisch zu den
|
|
passenden Kreativ-Tonies über die inoffizielle TonieCloud-API. Geschrieben
|
|
in Go, kompiliert zu einer einzigen statischen Binary - keine Laufzeit-
|
|
Abhängigkeiten (kein Python/pip nötig).
|
|
|
|
> **Hinweis:** toni-sync lädt selbst keine Musik von Deezer herunter. Das
|
|
> Herunterladen/Umgehen von DRM-geschützten Streams verstößt gegen die
|
|
> Nutzungsbedingungen von Deezer und ggf. gegen Urheberrecht. Lege deine
|
|
> bereits legal exportierten Audiodateien einfach in die passenden
|
|
> lokalen Ordner - toni-sync kümmert sich nur um den Abgleich mit der
|
|
> TonieCloud.
|
|
|
|
## Keine Config-Datei - die Ordnerstruktur *ist* die Konfiguration
|
|
|
|
Statt einer separaten Config-Datei wird das Mapping Playlist ↔ Kreativ-Tonie
|
|
direkt über die Ordnerstruktur abgebildet:
|
|
|
|
```
|
|
<root>/
|
|
<household_id>/
|
|
<freier_name> [id=<tonie_id>]/
|
|
01 - Track.mp3
|
|
02 - Track.mp3
|
|
```
|
|
|
|
- `<household_id>`: die Household-ID deines TonieCloud-Accounts
|
|
- `<freier_name> [id=<tonie_id>]`: frei wählbarer Name + Tonie-ID in eckigen
|
|
Klammern - der Name dient nur der Lesbarkeit, für das Mapping zählt allein
|
|
die ID
|
|
- Die alphabetische Dateireihenfolge innerhalb eines Tonie-Ordners bestimmt
|
|
die Kapitelreihenfolge auf dem Tonie
|
|
|
|
## Installation
|
|
|
|
Benötigt wird nur eine Go-Toolchain (>= 1.21) zum Bauen - danach ist das
|
|
Ergebnis eine einzelne Binary ohne weitere Abhängigkeiten:
|
|
|
|
```bash
|
|
go build -o toni-sync ./cmd/toni-sync
|
|
./toni-sync --help
|
|
```
|
|
|
|
Oder direkt installieren (landet in `$(go env GOPATH)/bin`):
|
|
|
|
```bash
|
|
go install ./cmd/toni-sync
|
|
```
|
|
|
|
## Anmeldedaten
|
|
|
|
toni-sync benötigt deine TonieCloud-Zugangsdaten (dieselben wie in der
|
|
Tonies-App). Sie werden **nicht** gespeichert, sondern bei jedem Aufruf
|
|
über Umgebungsvariablen oder interaktiven Prompt abgefragt:
|
|
|
|
```bash
|
|
export TONI_SYNC_USERNAME="you@example.com"
|
|
export TONI_SYNC_PASSWORD="********"
|
|
```
|
|
|
|
Alternativ: `--username`/`--password` Flags bei `tonies list`, `init` und `sync`.
|
|
|
|
## Nutzung
|
|
|
|
### 1. Library-Ordner automatisch anlegen
|
|
|
|
```bash
|
|
toni-sync init --root ~/Musik/tonies
|
|
```
|
|
|
|
Legt für jede Household und jeden Kreativ-Tonie deines Accounts den
|
|
passenden Ordner an, z. B.:
|
|
|
|
```
|
|
[created] /home/you/Musik/tonies/abcd-1234/Peppa Wutz [id=ef01-5678]
|
|
[created] /home/you/Musik/tonies/abcd-1234/Gute-Nacht-Geschichten [id=9876-4321]
|
|
Library ready at /home/you/Musik/tonies
|
|
```
|
|
|
|
Bereits vorhandene Ordner (anhand der Tonie-ID erkannt, auch bei geändertem
|
|
Namen) werden nicht angefasst - deine Audiodateien bleiben unberührt.
|
|
|
|
Alternativ manuell: einfach die Ordner nach obigem Schema selbst anlegen.
|
|
|
|
### 2. Root-Ordner festlegen
|
|
|
|
Der Library-Root wird wie folgt bestimmt (erste zutreffende Option):
|
|
|
|
1. `--root PATH` Flag
|
|
2. Umgebungsvariable `TONI_SYNC_ROOT`
|
|
3. aktuelles Arbeitsverzeichnis
|
|
|
|
### 3. Audiodateien einsortieren & synchronisieren
|
|
|
|
Lege deine (legal exportierten) Audiodateien in den passenden Tonie-Ordner.
|
|
Die Kapitelreihenfolge wird wie folgt bestimmt:
|
|
|
|
- **Mit Playlist:** Liegt genau eine `.m3u`/`.m3u8`-Datei im Tonie-Ordner,
|
|
bestimmt deren Zeilenreihenfolge die Kapitelreihenfolge (Kommentare/`#`-Zeilen
|
|
und Leerzeilen werden ignoriert, Pfade relativ zum Ordner). Dateien, die
|
|
lokal existieren aber nicht in der Playlist stehen, werden trotzdem
|
|
synchronisiert und ans Ende angehängt (nichts geht verloren). Einträge in
|
|
der Playlist ohne passende Datei werden ignoriert. Liegen mehrere Playlist-
|
|
Dateien im selben Ordner, bricht `sync` mit einem Fehler ab (Reihenfolge
|
|
wäre sonst mehrdeutig).
|
|
- **Ohne Playlist:** alphabetische Dateireihenfolge, z. B. `01 - Track.mp3`,
|
|
`02 - Track.mp3`, ...
|
|
|
|
Beispiel `playlist.m3u`:
|
|
|
|
```
|
|
#EXTM3U
|
|
02 - Second Track.mp3
|
|
01 - First Track.mp3
|
|
03 - Third Track.mp3
|
|
```
|
|
|
|
```bash
|
|
# alle gefundenen Tonies synchronisieren
|
|
toni-sync sync --root ~/Musik/tonies
|
|
|
|
# nur Tonies syncen, deren Household-ID/Tonie-ID/Name den Filter enthalten
|
|
toni-sync sync peppa --root ~/Musik/tonies
|
|
|
|
# nur anzeigen, was sich ändern würde
|
|
toni-sync sync --root ~/Musik/tonies --dry-run
|
|
```
|
|
|
|
`sync` lädt neue Dateien hoch, entfernt Kapitel, die lokal nicht mehr
|
|
existieren (abschaltbar via `--no-prune`), und sortiert die Kapitel passend
|
|
zur lokalen Reihenfolge (Playlist-Datei falls vorhanden, sonst alphabetisch).
|
|
|
|
**Leere Tonie-Ordner werden übersprungen** - so verhindert toni-sync, dass
|
|
ein versehentlich leerer Ordner (z. B. noch nicht befüllt) beim Sync alle
|
|
vorhandenen Kapitel auf dem Tonie löscht.
|
|
|
|
### Household-/Tonie-IDs nachschlagen
|
|
|
|
Falls du die Struktur lieber manuell pflegen willst:
|
|
|
|
```bash
|
|
toni-sync tonies list
|
|
```
|
|
|
|
```
|
|
Household: Familie Müller [id=abcd-1234]
|
|
- Peppa Wutz [id=ef01-5678] (12 chapters, 3600s)
|
|
- Gute-Nacht-Geschichten [id=9876-4321] (0 chapters, 0s)
|
|
```
|
|
|
|
## Unterstützte Audioformate
|
|
|
|
`.mp3`, `.m4a`, `.aac`, `.ogg`, `.flac`, `.wav`
|
|
|
|
## Projektstruktur
|
|
|
|
```
|
|
cmd/toni-sync/ CLI-Einstiegspunkt (Cobra-Kommandos: tonies, init, sync)
|
|
internal/tonieapi/ Eigener, minimaler TonieCloud-API-Client
|
|
internal/library/ Erkennung & Scaffolding der Ordnerstruktur (Household/Tonie)
|
|
internal/syncer/ Diff-/Apply-Logik zwischen lokalem Ordner und Tonie
|
|
```
|
|
|
|
## Entwicklung / Tests
|
|
|
|
```bash
|
|
go build ./...
|
|
go vet ./...
|
|
go test ./...
|
|
```
|