Repository navigation
Free setup page: install addons and move a Nuvio account into ARVIO - #774
Conversation
|
This needs testing before I can merge. Also it is questionable if it is really needed. |
The web app is behind a subscription, but the Android and TV apps are not, so a user coming from Nuvio had no way to carry their setup over without paying for an interface they did not want. /migrate is a standalone page outside the subscribed shell. It reads a Nuvio account, installs addons by manifest URL, and copies profiles, addons and collections into an ARVIO account, which the free apps then sync. Nuvio keeps its data; nothing there is changed. - The public Nuvio cloud publishes /.well-known/nuvio, so the page needs no server address and no embedded key: it reads the publishable key at connect time, which also survives a key rotation. Self-hosters can name their own server behind a link. - Reading Nuvio needs no ARVIO account, so the connect step comes first and the result can be downloaded as JSON. Signing in to ARVIO is only required to write. - Row-level security can leave a direct table read empty, so collections and home catalog settings fall back to the sync_pull_* RPCs, and an account that exposes no profiles table still migrates as profile 1. - Profiles are matched by name and created when missing, so a multi-profile account arrives whole and a repeated import does not duplicate anything. A Nuvio PIN hash is not portable, so a copied profile starts unlocked. - Addon manifests are resolved one by one; an unreachable addon is reported in the summary instead of aborting the run. - Collections reuse the existing Nuvio collections parser. Plugins are counted and reported as staying behind, since the web app has no plugins. - The password is used once for the token exchange and never stored. - English by default, with a language picker saved per device.
e4de28f to
d34d443
Compare
|
Fair on both points — let me take the testing one first, because it is the blocker. Testing. You are right that this is unverified, and I have said so at the top of the description rather than letting it look finished. What I could test, I did: 15 unit tests (the Nuvio read, the RPC fallback, profile matching, addon de-duplication) and a full manual run of the flow in a browser against a stub Nuvio server, which is what the screenshots show. What I could not test is the only part that matters for merging: the real Whether it is needed. The case is about who it is for, not about the web app:
If the judgement is still that the migration half is not wanted, the addon/collection management half stands on its own and I am happy to split the PR so you can take only that. And if you would rather it lived somewhere other than |
|
Thanks for the contribution and the explanation. I can see the value in easier browser setup and moving from Nuvio, especially for TV users. I would like to keep exploring this, but a few things need fixing before merging:
TypeScript checks and all 770 web tests passed, but I reproduced the first two problems using the actual cloud helpers with a mocked backend. After fixing these, please add regression tests and verify a real disposable Nuvio-to-ARVIO import, including that existing account settings/IPTV remain intact and the imported content appears on Android/TV. The idea is useful; protecting existing account data is the main blocker here. |
|
Thanks for actually running it — these are real, and 1 and 2 are the kind of bug that would have cost someone their setup. Protecting existing account data being the blocker is the right call. Taking them in order: 1. 2. A failed read treated as an empty profile. My 3. Choices not recalculated after ARVIO sign-in. Right — connecting Nuvio first (which is the order I moved it to) means 4. The 1-6 fallback only building Profile 1. Correct, and it silently drops the other profiles' content. Fix: derive the profile ids from what the RPC calls actually returned (and from the addon/plugin rows) and build a profile for each, instead of assuming one. I will also separate the two cases you are pointing at: a read that failed is not an account that is empty, and only the genuinely empty case should fall back. 5. Disabled addons installed as enabled. Fix: carry Nuvio's Regression tests for all five, including one that asserts an unrelated settings field survives an import and one that asserts a failed read writes nothing at all. On verification: I can cover the above with tests against the real cloud helpers the way you did, but a true end-to-end run needs a disposable ARVIO account to write into, which I do not have — if you can point me at one (or run it once yourself after the fixes land), I will confirm settings and IPTV stay intact and that the imported rows show up on Android/TV before you look again. |
Review findings on ProdigyV21#774, all five: 1. The import wrote a whole settings object with no baseline, so the theme, the AI subtitle toggle and the saved AI key were reset to the page's defaults. It now reads the profile's current cloud settings, changes only `catalogs`, and passes those same settings as the `baseline`, so saveCloudSettings asserts nothing else. 2. A failed cloud read was swallowed and treated as an empty profile, which then wrote defaults over real catalogs and IPTV playlists. The failure now stops that profile's import, writes nothing for it, and is reported in the summary. Other profiles continue. 3. Connecting Nuvio before signing in to ARVIO left every profile set to "create new", because the plan was drawn up against an empty profile list. The plan is recalculated when profiles arrive, keeping any target the user already picked by hand. 4. When the profile table is unavailable the profile ids are recovered from whatever the other tables and the sync RPCs answered for, instead of building Profile 1 alone and dropping the rest. A read that failed is also distinguished from a table that is simply empty, and a failed read is surfaced as a warning. 5. An addon switched off in Nuvio is installed switched off. Tests: the two data-safety regressions run against the real cloud helpers with a stubbed backend, since that is the layer the damage happened in — one asserts unrelated settings and IPTV survive an import, one asserts a failed read writes nothing at all. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
All five are fixed and pushed (790db45). What changed, in the same order: 1. Unrelated global settings. The write no longer starts from the page's defaults. The import reads the profile's current cloud settings, changes 2. Failed read. 3. Choices after sign-in. 4. The 1-6 fallback. Profile ids are now recovered from every table that carries 5. Disabled addons. The enabled flag travels with the addon, so one switched off in Nuvio arrives switched off ( Tests
Both of the first two fail against the previous code and pass against this one; I checked by reverting each fix in turn. Also added: profile recovery from a failed End-to-end runI ran the whole flow in a browser against a stub Nuvio server, with the ARVIO backend stubbed at the network layer so the real
That is as far as I can take it without an account. A real disposable Nuvio-to-ARVIO run against |
Summary
A user moving from Nuvio has no way to carry their setup across: the web app sits behind the subscription, and the Android/TV apps — which are free — have no importer. This adds
/migrate, a standalone page outside the subscribed shell, so someone who only uses the free apps can still set their account up.The page does three things:
Everything written goes into the ARVIO cloud payload, which the free Android and TV apps already sync, so the result shows up on a TV without a web subscription. Nothing in Nuvio is modified; it is only read.
Connecting to Nuvio
The public Nuvio cloud publishes its client settings at
https://api.nuvio.tv/.well-known/nuvio, so the page asks only for the user's Nuvio email and password — no server address, and no Nuvio key is embedded in this repo: the publishable key is read at connect time, which also means a rotated key keeps working. Self-hosters can name their own server behind an "I host Nuvio myself" link. The password is used once for the token exchange and never stored; the access token lives in memory for the length of the import.Data is read from the documented tables —
profiles,addons,plugins,collections,home_catalog_settings. Because row-level security can leave a direct table read empty, collections and home catalog settings fall back to thesync_pull_*RPCs, and an account that exposes noprofilestable still migrates as profile 1.How it lands in ARVIO
parseCustomCollections, the same path the Nuvio collections import already uses.Interface is English by default, with a language picker saved per device that reuses the app's existing dictionaries.
Test plan
npx tsc --noEmittests/nuvio-migration.test.cjs— 15 tests: address forms, discovery parsing, sign-in error surfacing, grouping by profile, a missing table, the RPC fallback, colour/avatar conversion, name matching, addon de-duplication, row order.tests/nuvio-import-runner.test.cjs— 7 tests with the cloud layer stubbed: profile creation, skipped profiles writing nothing, no double-install, refusing to run without a session, a failed read skipping that profile, the write being limited tocatalogs, and a disabled addon staying disabled.tests/nuvio-import-safety.test.cjs— 3 tests against the real cloud helpers with a stubbed backend: an import leaves every settings field it does not own untouched (theme, AI subtitle key, IPTV playlists), a failed read writes nothing at all, and an account that cannot be read is never written to.npm test— 779 passing; onlyprovider JSON/XML/playlist text survives incorrect octet-stream MIME typesfails, and it fails the same way on a cleanmain(pre-existing, unrelated).https://api.nuvio.tv/.well-known/nuvioverified to returnbackend_urlandpublishable_key, which is what removes the server field.cloud.tsread/modify/write path executed: an account that started with an accent colour, AI subtitles with a saved key, an IPTV playlist and one catalog came out of the import with all of those unchanged, the imported collection rails added, and an addon that was off in Nuvio installed off.Notes for review
Review fixes (790db45)
All five findings from the review are addressed: the write is limited to
catalogsand carries the account's own settings as itsbaseline; a failed cloud read stops that profile and writes nothing instead of passing for an empty profile; the profile plan is recalculated once ARVIO profiles load, keeping manual picks; profile ids are recovered from every table and RPC that answered, and a failed read is distinguished from an empty one and surfaced; and an addon disabled in Nuvio is installed disabled.