mirror of
https://github.com/gesellix/Bose-SoundTouch.git
synced 2026-08-19 00:56:16 +00:00
feat: improve Bose SoundTouch parity, Spotify integration, and data reliability (#138)
feat: improve Bose SoundTouch parity, Spotify integration, and data
reliability
- Update XML marshaling for ServicePreset and ServiceRecent to match
Bose parity requirements.
- Add support for adding music sources via
`/streaming/account/{account}/source`.
- Implement HandleBoseAccountToken for Spotify OAuth code exchange and
token persistence.
- Implement atomic file writes in the datastore to prevent data
corruption.
- Add startup logic to initialize default sources for existing devices.
- Expand test coverage with new parity regression and Spotify
integration tests.
---------
Co-authored-by: Junie <junie@jetbrains.com>
Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
This commit is contained in:
@@ -0,0 +1,34 @@
|
||||
### PUT /streaming/account/{{accountId}}/device/{{deviceId}}/preset/6
|
||||
PUT {{host}}/streaming/account/{{accountId}}/device/{{deviceId}}/preset/6
|
||||
Host: streaming.bose.com
|
||||
User-Agent: Bose_Lisa/27.0.6
|
||||
Accept: application/vnd.bose.streaming-v1.2+xml
|
||||
Authorization: Bearer {{token}}
|
||||
Content-Type: application/vnd.bose.streaming-v1.2+xml
|
||||
|
||||
<?xml version="1.0" encoding="UTF-8" ?><preset buttonNumber="6"><sourceid>TUNEIN</sourceid><name>SMOOTH JAZZ</name><username>SMOOTH JAZZ</username><location>/v1/playback/station/s166521</location><contentItemType>stationurl</contentItemType><containerArt>https://cdn-profiles.tunein.com/s166521/images/logod.png?t=638398103700000000</containerArt></preset>
|
||||
|
||||
> {%
|
||||
client.test("Response is 200 OK", function() {
|
||||
client.assert(response.status === 200, "Response status is not 200");
|
||||
});
|
||||
|
||||
client.test("Response body is a preset", function() {
|
||||
const doc = response.body;
|
||||
const preset = doc.getElementsByTagName("preset")[0];
|
||||
|
||||
client.assert(preset.getAttribute("buttonNumber") === "6", "Response body does not contain buttonNumber=\"6\"");
|
||||
client.assert(doc.getElementsByTagName("name")[0].textContent === "SMOOTH JAZZ", "Response body does not contain <name>SMOOTH JAZZ</name>");
|
||||
client.assert(doc.getElementsByTagName("location")[0].textContent === "/v1/playback/station/s166521", "Response body does not contain <location>/v1/playback/station/s166521</location>");
|
||||
client.assert(doc.getElementsByTagName("contentItemType")[0].textContent === "stationurl", "Response body does not contain <contentItemType>stationurl</contentItemType>");
|
||||
|
||||
const source = doc.getElementsByTagName("source")[0];
|
||||
client.assert(source.getAttribute("id") !== null && source.getAttribute("id") !== "", "Response body does not contain a non-empty source id");
|
||||
client.assert(source.getAttribute("type") === "Audio", "Response body does not contain source type=\"Audio\"");
|
||||
client.assert(source.getAttribute("displayName") === null, "Response body should NOT contain displayName attribute in source");
|
||||
client.assert(doc.getElementsByTagName("sourceproviderid")[0].textContent === "25", "Response body does not contain <sourceproviderid>25</sourceproviderid>");
|
||||
client.assert(doc.getElementsByTagName("sourcename")[0].textContent === "", "Response body does not contain <sourcename></sourcename>");
|
||||
client.assert(source.getElementsByTagName("username")[0].textContent === "", "Response body does not contain empty <username> in source, found: " + source.getElementsByTagName("username")[0].textContent);
|
||||
client.assert(doc.getElementsByTagName("username")[1].textContent === "SMOOTH JAZZ", "Response body does not contain <username>SMOOTH JAZZ</username> in preset, found: " + doc.getElementsByTagName("username")[1].textContent);
|
||||
});
|
||||
%}
|
||||
Reference in New Issue
Block a user