mirror of
https://github.com/gesellix/Bose-SoundTouch.git
synced 2026-08-18 08:36:13 +00:00
The speaker decodes /streaming/account/.../full into a protobuf message where recents>recent>source>sourceproviderid is a required field. A laut.fm recent (location "/custom/v1/playback/...") POSTed against an account with no Sources.xml fell into classifyLearnedSource's default branch, which wrote sourceKey type="INVALID" with no providerid. That entry then re-appeared in /full with an empty <sourceproviderid> element, which the post-marshal strip-empty step deleted entirely — aborting the speaker's account sync with "MargePB.account.devices.device[N].recents.recent[K].source.sourceproviderid" missing and forcing a 60-second retry loop. Three changes, each defended by the new regression test: * classifyLearnedSource recognises LocalInternetRadio via sourceProviderID == 11 and via the /custom/v1/playback/ URL pattern, and stops writing the "INVALID" sentinel that locked sources out of every read-side repair path. * mapToFullResponseSource falls back to the canonical SourceProviderID keyed by source ID (10002/10003/10004/10005) so already-poisoned data on disk still renders a non-empty providerid at /full time, with no manual data scrub required. * AccountFullToXML no longer strips empty <sourceproviderid> elements. The strip-empty was added for parity with upstream's standalone <sources> block, but it's wrong inside recents/preset source blocks where the field is protobuf-required. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>