A frontend-agnostic crate for moving a Qobuz account's favorites and playlists into another account, additively (contract qbz-nix-docs/specs/2026-09-02-account-migration-contract.md §9): - snapshot: capture the signed-in account (five favorite kinds with favorited_at, owned playlists with track ids in order, followed playlists) into users/<uid>/account_migration/snapshot-*.json; the same capture is the target's live state at migration time. - plan: the pure delta against the target and the ledger. Same-name playlists holding nothing foreign are the same playlist and get the missing tracks appended; anything foreign means a different playlist and a " (migrated)" copy. Favorites are written oldest first so the target's own stamps keep the chronology. - apply: one favorite per call with pacing and bounded retries, 50-track chunks, subscriptions re-followed; every success lands in the ledger before the next write, so a run resumes and a second run adds nothing. - local: copy the old profile directory row by row (library folders and scanned tracks on the fast path, playlist folders, settings keyed by qobuz_playlist_id remapped through the ledger, pinned items, orders, preferences, blacklist; media servers, scrobblers and listening history behind options). Never the favorites cache, the subscription clock, the session or the purchases. The writes are the ones the app already issues when a user hearts or creates a playlist; nothing touches subscriptions, purchases or account data. cc
21 lines
612 B
TOML
21 lines
612 B
TOML
[package]
|
|
name = "qbz-account-migration"
|
|
version = "0.1.0"
|
|
edition = "2021"
|
|
description = "Qobuz account migration for QBZ — snapshot one account's favorites and playlists, plan and apply them additively into another (headless, frontend-agnostic)"
|
|
authors = ["blitzkriegfc"]
|
|
|
|
[dependencies]
|
|
qbz-models = { path = "../qbz-models" }
|
|
qbz-qobuz = { path = "../qbz-qobuz" }
|
|
|
|
serde = { workspace = true }
|
|
serde_json = { workspace = true }
|
|
log = { workspace = true }
|
|
tokio = { workspace = true }
|
|
chrono = { workspace = true }
|
|
rusqlite = { version = "0.40", features = ["bundled"] }
|
|
|
|
[dev-dependencies]
|
|
tempfile = "3"
|