From e05453e0efcee854567f510056276287bd5abae1 Mon Sep 17 00:00:00 2001 From: Eric Munson Date: Fri, 20 Feb 2026 18:22:20 -0500 Subject: [PATCH] OpenSubsonic: Use server provided version tag if present (#3200) --- .../providers/opensubsonic/parsers.py | 14 +- .../__snapshots__/test_parsers.ambr | 749 ++++++++++++++++-- .../fixtures/albums/no-version.album.json | 72 ++ .../fixtures/albums/no-version.info.json | 7 + .../fixtures/albums/spec.album.json | 1 + .../fixtures/tracks/no-version.album.json | 74 ++ .../fixtures/tracks/no-version.track.json | 108 +++ 7 files changed, 946 insertions(+), 79 deletions(-) create mode 100644 tests/providers/opensubsonic/fixtures/albums/no-version.album.json create mode 100644 tests/providers/opensubsonic/fixtures/albums/no-version.info.json create mode 100644 tests/providers/opensubsonic/fixtures/tracks/no-version.album.json create mode 100644 tests/providers/opensubsonic/fixtures/tracks/no-version.track.json diff --git a/music_assistant/providers/opensubsonic/parsers.py b/music_assistant/providers/opensubsonic/parsers.py index 50123406..56ee89af 100644 --- a/music_assistant/providers/opensubsonic/parsers.py +++ b/music_assistant/providers/opensubsonic/parsers.py @@ -109,7 +109,12 @@ def parse_track( for c in sonic_song.contributors: metadata.performers.add(c.artist.name) - name, version = parse_title_and_version(sonic_song.title) + if isinstance(album, Album) and album.version: + name = sonic_song.title + version = album.version + else: + name, version = parse_title_and_version(sonic_song.title) + track = Track( item_id=sonic_song.id, provider=instance_id, @@ -316,7 +321,12 @@ def parse_album( if sonic_album.moods: metadata.mood = sonic_album.moods[0] - name, version = parse_title_and_version(sonic_album.name) + if sonic_album.version: + name = sonic_album.name + version = sonic_album.version + else: + name, version = parse_title_and_version(sonic_album.name) + album = Album( item_id=sonic_album.id, provider=SUBSONIC_DOMAIN, diff --git a/tests/providers/opensubsonic/__snapshots__/test_parsers.ambr b/tests/providers/opensubsonic/__snapshots__/test_parsers.ambr index a94896c5..0acfe2af 100644 --- a/tests/providers/opensubsonic/__snapshots__/test_parsers.ambr +++ b/tests/providers/opensubsonic/__snapshots__/test_parsers.ambr @@ -281,7 +281,7 @@ 'year': 2007, }) # --- -# name: test_parse_albums[spec.album] +# name: test_parse_albums[no-version.album] dict({ 'album_type': 'unknown', 'artists': list([ @@ -408,7 +408,7 @@ 'year': 2007, }) # --- -# name: test_parse_albums[spec.album].1 +# name: test_parse_albums[no-version.album].1 dict({ 'album_type': 'unknown', 'artists': list([ @@ -541,35 +541,83 @@ 'year': 2007, }) # --- -# name: test_parse_artists[no-sort-name.artist] +# name: test_parse_albums[spec.album] dict({ + 'album_type': 'unknown', + 'artists': list([ + dict({ + 'available': True, + 'external_ids': list([ + ]), + 'image': None, + 'is_playable': True, + 'item_id': '91c3901ac465b9efc439e4be4270c2b6', + 'media_type': 'artist', + 'name': 'pornophonique', + 'provider': 'xx-instance-id-xx', + 'sort_name': 'pornophonique', + 'translation_key': None, + 'uri': 'xx-instance-id-xx://artist/91c3901ac465b9efc439e4be4270c2b6', + 'version': '', + 'year': None, + }), + dict({ + 'available': True, + 'external_ids': list([ + ]), + 'image': None, + 'is_playable': True, + 'item_id': 'ar-1', + 'media_type': 'artist', + 'name': 'Artist 1', + 'provider': 'xx-instance-id-xx', + 'sort_name': 'artist 1', + 'translation_key': None, + 'uri': 'xx-instance-id-xx://artist/ar-1', + 'version': '', + 'year': None, + }), + dict({ + 'available': True, + 'external_ids': list([ + ]), + 'image': None, + 'is_playable': True, + 'item_id': 'ar-2', + 'media_type': 'artist', + 'name': 'Artist 2', + 'provider': 'xx-instance-id-xx', + 'sort_name': 'artist 2', + 'translation_key': None, + 'uri': 'xx-instance-id-xx://artist/ar-2', + 'version': '', + 'year': None, + }), + ]), 'date_added': None, 'external_ids': list([ list([ - 'musicbrainz_artistid', + 'musicbrainz_albumid', '189002e7-3285-4e2e-92a3-7f6c30d407a2', ]), ]), 'favorite': True, 'is_playable': True, - 'item_id': '37ec820ca7193e17040c98f7da7c4b51', - 'media_type': 'artist', + 'item_id': 'ad0f112b6dcf83de5e9cae85d07f0d35', + 'media_type': 'album', 'metadata': dict({ 'chapters': None, 'copyright': None, 'description': None, 'explicit': None, - 'genres': None, + 'genres': list([ + 'East coast', + 'Hip-Hop', + ]), 'grouping': None, 'images': list([ dict({ - 'path': 'https://demo.org/image.jpg', - 'provider': 'xx-instance-id-xx', - 'remotely_accessible': True, - 'type': 'thumb', - }), - dict({ - 'path': 'ar-37ec820ca7193e17040c98f7da7c4b51_0', + 'path': 'al-ad0f112b6dcf83de5e9cae85d07f0d35_640a93a8', 'provider': 'xx-instance-id-xx', 'remotely_accessible': False, 'type': 'thumb', @@ -581,7 +629,7 @@ 'links': None, 'lrc_lyrics': None, 'lyrics': None, - 'mood': None, + 'mood': 'slow', 'performers': None, 'popularity': None, 'preview': None, @@ -589,7 +637,7 @@ 'review': None, 'style': None, }), - 'name': '2 Mello', + 'name': '8-bit lagerfeuer', 'position': None, 'provider': 'opensubsonic', 'provider_mappings': list([ @@ -607,53 +655,102 @@ 'details': None, 'in_library': None, 'is_unique': None, - 'item_id': '37ec820ca7193e17040c98f7da7c4b51', + 'item_id': 'ad0f112b6dcf83de5e9cae85d07f0d35', 'provider_domain': 'opensubsonic', 'provider_instance': 'xx-instance-id-xx', 'url': None, }), ]), - 'sort_name': '2 mello', + 'sort_name': 'lagerfeuer (8-bit)', 'translation_key': None, - 'uri': 'opensubsonic://artist/37ec820ca7193e17040c98f7da7c4b51', - 'version': '', + 'uri': 'opensubsonic://album/ad0f112b6dcf83de5e9cae85d07f0d35', + 'version': 'Deluxe Edition', + 'year': 2007, }) # --- -# name: test_parse_artists[no-sort-name.artist].1 +# name: test_parse_albums[spec.album].1 dict({ + 'album_type': 'unknown', + 'artists': list([ + dict({ + 'available': True, + 'external_ids': list([ + ]), + 'image': None, + 'is_playable': True, + 'item_id': '91c3901ac465b9efc439e4be4270c2b6', + 'media_type': 'artist', + 'name': 'pornophonique', + 'provider': 'xx-instance-id-xx', + 'sort_name': 'pornophonique', + 'translation_key': None, + 'uri': 'xx-instance-id-xx://artist/91c3901ac465b9efc439e4be4270c2b6', + 'version': '', + 'year': None, + }), + dict({ + 'available': True, + 'external_ids': list([ + ]), + 'image': None, + 'is_playable': True, + 'item_id': 'ar-1', + 'media_type': 'artist', + 'name': 'Artist 1', + 'provider': 'xx-instance-id-xx', + 'sort_name': 'artist 1', + 'translation_key': None, + 'uri': 'xx-instance-id-xx://artist/ar-1', + 'version': '', + 'year': None, + }), + dict({ + 'available': True, + 'external_ids': list([ + ]), + 'image': None, + 'is_playable': True, + 'item_id': 'ar-2', + 'media_type': 'artist', + 'name': 'Artist 2', + 'provider': 'xx-instance-id-xx', + 'sort_name': 'artist 2', + 'translation_key': None, + 'uri': 'xx-instance-id-xx://artist/ar-2', + 'version': '', + 'year': None, + }), + ]), 'date_added': None, 'external_ids': list([ list([ - 'musicbrainz_artistid', + 'musicbrainz_albumid', '189002e7-3285-4e2e-92a3-7f6c30d407a2', ]), ]), 'favorite': True, 'is_playable': True, - 'item_id': '37ec820ca7193e17040c98f7da7c4b51', - 'media_type': 'artist', + 'item_id': 'ad0f112b6dcf83de5e9cae85d07f0d35', + 'media_type': 'album', 'metadata': dict({ 'chapters': None, 'copyright': None, - 'description': 'Empty biography', + 'description': 'Download the full release here (creative commons). These cripsy beats are ripe with thumping funk and techno influences, sample wizardry and daring shuffles. Composed with the help of unique sound plugins which were especially programmed to measure Comfort Fit’s needs and wishes, we think the chances aren’t bad that you’ll fall for the unique sound signature, bounce and elegance of this unusual Hip Hop production. Ltj bukem / Good looking Rec., UK: "Really love this music." Velanche / XLR8R, UK: "Awesome job he\'s done... overall production is dope." Kwesi / BBE Music, UK: "Wooooooowwwww... WHAT THE FUCK! THIS IS WHAT', 'explicit': None, - 'genres': None, + 'genres': list([ + 'East coast', + 'Hip-Hop', + ]), 'grouping': None, 'images': list([ dict({ - 'path': 'https://demo.org/image.jpg', - 'provider': 'xx-instance-id-xx', - 'remotely_accessible': True, - 'type': 'thumb', - }), - dict({ - 'path': 'ar-37ec820ca7193e17040c98f7da7c4b51_0', + 'path': 'al-ad0f112b6dcf83de5e9cae85d07f0d35_640a93a8', 'provider': 'xx-instance-id-xx', 'remotely_accessible': False, 'type': 'thumb', }), dict({ - 'path': 'http://localhost:8989/play/art/f20070e8e11611cc53542a38801d60fa/artist/2/thumb34.jpg', + 'path': 'http://localhost:8989/play/art/0f8c3cbd6b0b22c3b5402141351ac812/album/21/thumb34.jpg', 'provider': 'xx-instance-id-xx', 'remotely_accessible': True, 'type': 'thumb', @@ -665,7 +762,7 @@ 'links': None, 'lrc_lyrics': None, 'lyrics': None, - 'mood': None, + 'mood': 'slow', 'performers': None, 'popularity': None, 'preview': None, @@ -673,7 +770,7 @@ 'review': None, 'style': None, }), - 'name': '2 Mello', + 'name': '8-bit lagerfeuer', 'position': None, 'provider': 'opensubsonic', 'provider_mappings': list([ @@ -691,19 +788,20 @@ 'details': None, 'in_library': None, 'is_unique': None, - 'item_id': '37ec820ca7193e17040c98f7da7c4b51', + 'item_id': 'ad0f112b6dcf83de5e9cae85d07f0d35', 'provider_domain': 'opensubsonic', 'provider_instance': 'xx-instance-id-xx', 'url': None, }), ]), - 'sort_name': '2 mello', + 'sort_name': 'lagerfeuer (8-bit)', 'translation_key': None, - 'uri': 'opensubsonic://artist/37ec820ca7193e17040c98f7da7c4b51', - 'version': '', + 'uri': 'opensubsonic://album/ad0f112b6dcf83de5e9cae85d07f0d35', + 'version': 'Deluxe Edition', + 'year': 2007, }) # --- -# name: test_parse_artists[spec-artistid3.artist] +# name: test_parse_artists[no-sort-name.artist] dict({ 'date_added': None, 'external_ids': list([ @@ -775,13 +873,13 @@ 'url': None, }), ]), - 'sort_name': 'Mello (2)', + 'sort_name': '2 mello', 'translation_key': None, 'uri': 'opensubsonic://artist/37ec820ca7193e17040c98f7da7c4b51', 'version': '', }) # --- -# name: test_parse_artists[spec-artistid3.artist].1 +# name: test_parse_artists[no-sort-name.artist].1 dict({ 'date_added': None, 'external_ids': list([ @@ -859,20 +957,24 @@ 'url': None, }), ]), - 'sort_name': 'Mello (2)', + 'sort_name': '2 mello', 'translation_key': None, 'uri': 'opensubsonic://artist/37ec820ca7193e17040c98f7da7c4b51', 'version': '', }) # --- -# name: test_parse_artists[spec-sample.artist] +# name: test_parse_artists[spec-artistid3.artist] dict({ 'date_added': None, 'external_ids': list([ + list([ + 'musicbrainz_artistid', + '189002e7-3285-4e2e-92a3-7f6c30d407a2', + ]), ]), 'favorite': True, 'is_playable': True, - 'item_id': '100000002', + 'item_id': '37ec820ca7193e17040c98f7da7c4b51', 'media_type': 'artist', 'metadata': dict({ 'chapters': None, @@ -883,7 +985,13 @@ 'grouping': None, 'images': list([ dict({ - 'path': 'ar-100000002', + 'path': 'https://demo.org/image.jpg', + 'provider': 'xx-instance-id-xx', + 'remotely_accessible': True, + 'type': 'thumb', + }), + dict({ + 'path': 'ar-37ec820ca7193e17040c98f7da7c4b51_0', 'provider': 'xx-instance-id-xx', 'remotely_accessible': False, 'type': 'thumb', @@ -903,7 +1011,7 @@ 'review': None, 'style': None, }), - 'name': 'Synthetic', + 'name': '2 Mello', 'position': None, 'provider': 'opensubsonic', 'provider_mappings': list([ @@ -921,26 +1029,30 @@ 'details': None, 'in_library': None, 'is_unique': None, - 'item_id': '100000002', + 'item_id': '37ec820ca7193e17040c98f7da7c4b51', 'provider_domain': 'opensubsonic', 'provider_instance': 'xx-instance-id-xx', 'url': None, }), ]), - 'sort_name': 'synthetic', + 'sort_name': 'Mello (2)', 'translation_key': None, - 'uri': 'opensubsonic://artist/100000002', + 'uri': 'opensubsonic://artist/37ec820ca7193e17040c98f7da7c4b51', 'version': '', }) # --- -# name: test_parse_artists[spec-sample.artist].1 +# name: test_parse_artists[spec-artistid3.artist].1 dict({ 'date_added': None, 'external_ids': list([ + list([ + 'musicbrainz_artistid', + '189002e7-3285-4e2e-92a3-7f6c30d407a2', + ]), ]), 'favorite': True, 'is_playable': True, - 'item_id': '100000002', + 'item_id': '37ec820ca7193e17040c98f7da7c4b51', 'media_type': 'artist', 'metadata': dict({ 'chapters': None, @@ -951,7 +1063,13 @@ 'grouping': None, 'images': list([ dict({ - 'path': 'ar-100000002', + 'path': 'https://demo.org/image.jpg', + 'provider': 'xx-instance-id-xx', + 'remotely_accessible': True, + 'type': 'thumb', + }), + dict({ + 'path': 'ar-37ec820ca7193e17040c98f7da7c4b51_0', 'provider': 'xx-instance-id-xx', 'remotely_accessible': False, 'type': 'thumb', @@ -977,7 +1095,7 @@ 'review': None, 'style': None, }), - 'name': 'Synthetic', + 'name': '2 Mello', 'position': None, 'provider': 'opensubsonic', 'provider_mappings': list([ @@ -995,39 +1113,37 @@ 'details': None, 'in_library': None, 'is_unique': None, - 'item_id': '100000002', + 'item_id': '37ec820ca7193e17040c98f7da7c4b51', 'provider_domain': 'opensubsonic', 'provider_instance': 'xx-instance-id-xx', 'url': None, }), ]), - 'sort_name': 'synthetic', + 'sort_name': 'Mello (2)', 'translation_key': None, - 'uri': 'opensubsonic://artist/100000002', + 'uri': 'opensubsonic://artist/37ec820ca7193e17040c98f7da7c4b51', 'version': '', }) # --- -# name: test_parse_episode[gonic-sample.episode] +# name: test_parse_artists[spec-sample.artist] dict({ 'date_added': None, - 'duration': 1878, 'external_ids': list([ ]), - 'favorite': False, - 'fully_played': None, + 'favorite': True, 'is_playable': True, - 'item_id': 'pd-5$!$pe-1860', - 'media_type': 'podcast_episode', + 'item_id': '100000002', + 'media_type': 'artist', 'metadata': dict({ 'chapters': None, 'copyright': None, - 'description': 'The history of The History of Rome...Why the Western Empire Fell when it did...Some thoughts on the future...Thank you, goodnight.', + 'description': None, 'explicit': None, 'genres': None, 'grouping': None, 'images': list([ dict({ - 'path': 'pd-5', + 'path': 'ar-100000002', 'provider': 'xx-instance-id-xx', 'remotely_accessible': False, 'type': 'thumb', @@ -1043,20 +1159,164 @@ 'performers': None, 'popularity': None, 'preview': None, - 'release_date': '2012-05-06T18:18:38+00:00', + 'release_date': None, 'review': None, 'style': None, }), - 'name': '179- The End', - 'podcast': dict({ - 'date_added': None, - 'external_ids': list([ - ]), - 'favorite': False, - 'is_playable': True, - 'item_id': 'pd-5', - 'media_type': 'podcast', - 'metadata': dict({ + 'name': 'Synthetic', + 'position': None, + 'provider': 'opensubsonic', + 'provider_mappings': list([ + dict({ + 'audio_format': dict({ + 'bit_depth': 16, + 'bit_rate': 0, + 'channels': 2, + 'codec_type': '?', + 'content_type': '?', + 'output_format_str': '?', + 'sample_rate': 44100, + }), + 'available': True, + 'details': None, + 'in_library': None, + 'is_unique': None, + 'item_id': '100000002', + 'provider_domain': 'opensubsonic', + 'provider_instance': 'xx-instance-id-xx', + 'url': None, + }), + ]), + 'sort_name': 'synthetic', + 'translation_key': None, + 'uri': 'opensubsonic://artist/100000002', + 'version': '', + }) +# --- +# name: test_parse_artists[spec-sample.artist].1 + dict({ + 'date_added': None, + 'external_ids': list([ + ]), + 'favorite': True, + 'is_playable': True, + 'item_id': '100000002', + 'media_type': 'artist', + 'metadata': dict({ + 'chapters': None, + 'copyright': None, + 'description': 'Empty biography', + 'explicit': None, + 'genres': None, + 'grouping': None, + 'images': list([ + dict({ + 'path': 'ar-100000002', + 'provider': 'xx-instance-id-xx', + 'remotely_accessible': False, + 'type': 'thumb', + }), + dict({ + 'path': 'http://localhost:8989/play/art/f20070e8e11611cc53542a38801d60fa/artist/2/thumb34.jpg', + 'provider': 'xx-instance-id-xx', + 'remotely_accessible': True, + 'type': 'thumb', + }), + ]), + 'label': None, + 'languages': None, + 'last_refresh': None, + 'links': None, + 'lrc_lyrics': None, + 'lyrics': None, + 'mood': None, + 'performers': None, + 'popularity': None, + 'preview': None, + 'release_date': None, + 'review': None, + 'style': None, + }), + 'name': 'Synthetic', + 'position': None, + 'provider': 'opensubsonic', + 'provider_mappings': list([ + dict({ + 'audio_format': dict({ + 'bit_depth': 16, + 'bit_rate': 0, + 'channels': 2, + 'codec_type': '?', + 'content_type': '?', + 'output_format_str': '?', + 'sample_rate': 44100, + }), + 'available': True, + 'details': None, + 'in_library': None, + 'is_unique': None, + 'item_id': '100000002', + 'provider_domain': 'opensubsonic', + 'provider_instance': 'xx-instance-id-xx', + 'url': None, + }), + ]), + 'sort_name': 'synthetic', + 'translation_key': None, + 'uri': 'opensubsonic://artist/100000002', + 'version': '', + }) +# --- +# name: test_parse_episode[gonic-sample.episode] + dict({ + 'date_added': None, + 'duration': 1878, + 'external_ids': list([ + ]), + 'favorite': False, + 'fully_played': None, + 'is_playable': True, + 'item_id': 'pd-5$!$pe-1860', + 'media_type': 'podcast_episode', + 'metadata': dict({ + 'chapters': None, + 'copyright': None, + 'description': 'The history of The History of Rome...Why the Western Empire Fell when it did...Some thoughts on the future...Thank you, goodnight.', + 'explicit': None, + 'genres': None, + 'grouping': None, + 'images': list([ + dict({ + 'path': 'pd-5', + 'provider': 'xx-instance-id-xx', + 'remotely_accessible': False, + 'type': 'thumb', + }), + ]), + 'label': None, + 'languages': None, + 'last_refresh': None, + 'links': None, + 'lrc_lyrics': None, + 'lyrics': None, + 'mood': None, + 'performers': None, + 'popularity': None, + 'preview': None, + 'release_date': '2012-05-06T18:18:38+00:00', + 'review': None, + 'style': None, + }), + 'name': '179- The End', + 'podcast': dict({ + 'date_added': None, + 'external_ids': list([ + ]), + 'favorite': False, + 'is_playable': True, + 'item_id': 'pd-5', + 'media_type': 'podcast', + 'metadata': dict({ 'chapters': None, 'copyright': None, 'description': 'A weekly podcast tracing the rise, decline and fall of the Roman Empire. Now complete!', @@ -2350,6 +2610,341 @@ 'version': '', }) # --- +# name: test_parse_track[no-version.track] + dict({ + 'album': dict({ + 'available': True, + 'external_ids': list([ + ]), + 'image': None, + 'is_playable': True, + 'item_id': 'e8a0685e3f3ec6f251649af2b58b8617', + 'media_type': 'album', + 'name': 'Live at The Casbah - 2005-04-29', + 'provider': 'xx-instance-id-xx', + 'sort_name': 'live at the casbah - 2005-04-29', + 'translation_key': None, + 'uri': 'xx-instance-id-xx://album/e8a0685e3f3ec6f251649af2b58b8617', + 'version': '', + 'year': None, + }), + 'artists': list([ + dict({ + 'available': True, + 'external_ids': list([ + ]), + 'image': None, + 'is_playable': True, + 'item_id': '97e0398acf63f9fb930d7d4ce209a52b', + 'media_type': 'artist', + 'name': 'The New Deal', + 'provider': 'xx-instance-id-xx', + 'sort_name': 'new deal, the', + 'translation_key': None, + 'uri': 'xx-instance-id-xx://artist/97e0398acf63f9fb930d7d4ce209a52b', + 'version': '', + 'year': None, + }), + dict({ + 'available': True, + 'external_ids': list([ + ]), + 'image': None, + 'is_playable': True, + 'item_id': 'ar-1', + 'media_type': 'artist', + 'name': 'Artist 1', + 'provider': 'xx-instance-id-xx', + 'sort_name': 'artist 1', + 'translation_key': None, + 'uri': 'xx-instance-id-xx://artist/ar-1', + 'version': '', + 'year': None, + }), + dict({ + 'available': True, + 'external_ids': list([ + ]), + 'image': None, + 'is_playable': True, + 'item_id': 'ar-2', + 'media_type': 'artist', + 'name': 'Artist 2', + 'provider': 'xx-instance-id-xx', + 'sort_name': 'artist 2', + 'translation_key': None, + 'uri': 'xx-instance-id-xx://artist/ar-2', + 'version': '', + 'year': None, + }), + ]), + 'date_added': None, + 'disc_number': 1, + 'duration': 178, + 'external_ids': list([ + list([ + 'musicbrainz_recordingid', + '189002e7-3285-4e2e-92a3-7f6c30d407a2', + ]), + ]), + 'favorite': True, + 'is_playable': True, + 'item_id': '082f435a363c32c57d5edb6a678a28d4', + 'last_played': 0, + 'media_type': 'track', + 'metadata': dict({ + 'chapters': None, + 'copyright': None, + 'description': None, + 'explicit': True, + 'genres': list([ + 'East coast', + 'Hip-Hop', + ]), + 'grouping': None, + 'images': None, + 'label': None, + 'languages': None, + 'last_refresh': None, + 'links': None, + 'lrc_lyrics': None, + 'lyrics': None, + 'mood': 'slow', + 'performers': list([ + 'Artist 3', + 'Artist 4', + 'Artist 5', + ]), + 'popularity': None, + 'preview': None, + 'release_date': None, + 'review': None, + 'style': None, + }), + 'name': '"polar expedition"', + 'position': None, + 'provider': 'xx-instance-id-xx', + 'provider_mappings': list([ + dict({ + 'audio_format': dict({ + 'bit_depth': 16, + 'bit_rate': 880, + 'channels': 2, + 'codec_type': '?', + 'content_type': 'flac', + 'output_format_str': 'flac', + 'sample_rate': 44100, + }), + 'available': True, + 'details': None, + 'in_library': None, + 'is_unique': None, + 'item_id': '082f435a363c32c57d5edb6a678a28d4', + 'provider_domain': 'opensubsonic', + 'provider_instance': 'xx-instance-id-xx', + 'url': None, + }), + ]), + 'sort_name': 'Polar expedition', + 'track_number': 4, + 'translation_key': None, + 'uri': 'xx-instance-id-xx://track/082f435a363c32c57d5edb6a678a28d4', + 'version': '', + }) +# --- +# name: test_parse_track[no-version.track].1 + dict({ + 'album': dict({ + 'artist': 'pornophonique', + 'artistId': '97e0398acf63f9fb930d7d4ce209a52b', + 'artists': list([ + dict({ + 'id': 'ar-1', + 'name': 'Artist 1', + }), + dict({ + 'id': 'ar-2', + 'name': 'Artist 2', + }), + ]), + 'coverArt': 'al-ad0f112b6dcf83de5e9cae85d07f0d35_640a93a8', + 'created': '2023-03-10T02:19:35.784818075Z', + 'discTitles': list([ + dict({ + 'disc': 0, + 'title': 'Disc 0 title', + }), + dict({ + 'disc': 2, + 'title': 'Disc 1 title', + }), + ]), + 'displayArtist': 'Artist 1 feat. Artist 2', + 'duration': 1954, + 'explicitStatus': 'explicit', + 'genre': 'Hip-Hop', + 'genres': list([ + dict({ + 'name': 'Hip-Hop', + }), + dict({ + 'name': 'East coast', + }), + ]), + 'id': 'e8a0685e3f3ec6f251649af2b58b8617', + 'isCompilation': False, + 'moods': list([ + 'slow', + 'cool', + ]), + 'musicBrainzId': '189002e7-3285-4e2e-92a3-7f6c30d407a2', + 'name': 'Live at The Casbah - 2005-04-29', + 'originalReleaseDate': dict({ + 'day': 10, + 'month': 3, + 'year': 2001, + }), + 'playCount': 97, + 'played': '2023-03-28T00:45:13Z', + 'releaseDate': dict({ + 'day': 10, + 'month': 3, + 'year': 2001, + }), + 'releaseTypes': list([ + 'Album', + 'Remixes', + ]), + 'songCount': 8, + 'sortName': 'lagerfeuer (8-bit)', + 'starred': '2023-03-22T01:51:06Z', + 'userRating': 4, + 'year': 2007, + }), + 'artists': list([ + dict({ + 'available': True, + 'external_ids': list([ + ]), + 'image': None, + 'is_playable': True, + 'item_id': '97e0398acf63f9fb930d7d4ce209a52b', + 'media_type': 'artist', + 'name': 'The New Deal', + 'provider': 'xx-instance-id-xx', + 'sort_name': 'new deal, the', + 'translation_key': None, + 'uri': 'xx-instance-id-xx://artist/97e0398acf63f9fb930d7d4ce209a52b', + 'version': '', + 'year': None, + }), + dict({ + 'available': True, + 'external_ids': list([ + ]), + 'image': None, + 'is_playable': True, + 'item_id': 'ar-1', + 'media_type': 'artist', + 'name': 'Artist 1', + 'provider': 'xx-instance-id-xx', + 'sort_name': 'artist 1', + 'translation_key': None, + 'uri': 'xx-instance-id-xx://artist/ar-1', + 'version': '', + 'year': None, + }), + dict({ + 'available': True, + 'external_ids': list([ + ]), + 'image': None, + 'is_playable': True, + 'item_id': 'ar-2', + 'media_type': 'artist', + 'name': 'Artist 2', + 'provider': 'xx-instance-id-xx', + 'sort_name': 'artist 2', + 'translation_key': None, + 'uri': 'xx-instance-id-xx://artist/ar-2', + 'version': '', + 'year': None, + }), + ]), + 'date_added': None, + 'disc_number': 1, + 'duration': 178, + 'external_ids': list([ + list([ + 'musicbrainz_recordingid', + '189002e7-3285-4e2e-92a3-7f6c30d407a2', + ]), + ]), + 'favorite': True, + 'is_playable': True, + 'item_id': '082f435a363c32c57d5edb6a678a28d4', + 'last_played': 0, + 'media_type': 'track', + 'metadata': dict({ + 'chapters': None, + 'copyright': None, + 'description': None, + 'explicit': True, + 'genres': list([ + 'East coast', + 'Hip-Hop', + ]), + 'grouping': None, + 'images': None, + 'label': None, + 'languages': None, + 'last_refresh': None, + 'links': None, + 'lrc_lyrics': None, + 'lyrics': None, + 'mood': 'slow', + 'performers': list([ + 'Artist 3', + 'Artist 4', + 'Artist 5', + ]), + 'popularity': None, + 'preview': None, + 'release_date': None, + 'review': None, + 'style': None, + }), + 'name': '"polar expedition"', + 'position': None, + 'provider': 'xx-instance-id-xx', + 'provider_mappings': list([ + dict({ + 'audio_format': dict({ + 'bit_depth': 16, + 'bit_rate': 880, + 'channels': 2, + 'codec_type': '?', + 'content_type': 'flac', + 'output_format_str': 'flac', + 'sample_rate': 44100, + }), + 'available': True, + 'details': None, + 'in_library': None, + 'is_unique': None, + 'item_id': '082f435a363c32c57d5edb6a678a28d4', + 'provider_domain': 'opensubsonic', + 'provider_instance': 'xx-instance-id-xx', + 'url': None, + }), + ]), + 'sort_name': 'Polar expedition', + 'track_number': 4, + 'translation_key': None, + 'uri': 'xx-instance-id-xx://track/082f435a363c32c57d5edb6a678a28d4', + 'version': '', + }) +# --- # name: test_parse_track[spec-child.track] dict({ 'album': dict({ diff --git a/tests/providers/opensubsonic/fixtures/albums/no-version.album.json b/tests/providers/opensubsonic/fixtures/albums/no-version.album.json new file mode 100644 index 00000000..986dbb9e --- /dev/null +++ b/tests/providers/opensubsonic/fixtures/albums/no-version.album.json @@ -0,0 +1,72 @@ +{ + "id": "ad0f112b6dcf83de5e9cae85d07f0d35", + "name": "8-bit lagerfeuer", + "artist": "pornophonique", + "year": 2007, + "coverArt": "al-ad0f112b6dcf83de5e9cae85d07f0d35_640a93a8", + "starred": "2023-03-22T01:51:06Z", + "duration": 1954, + "playCount": 97, + "genre": "Hip-Hop", + "created": "2023-03-10T02:19:35.784818075Z", + "artistId": "91c3901ac465b9efc439e4be4270c2b6", + "songCount": 8, + "played": "2023-03-28T00:45:13Z", + "userRating": 4, + "recordLabels": [ + { + "name": "Sony" + } + ], + "musicBrainzId": "189002e7-3285-4e2e-92a3-7f6c30d407a2", + "genres": [ + { + "name": "Hip-Hop" + }, + { + "name": "East coast" + } + ], + "artists": [ + { + "id": "ar-1", + "name": "Artist 1" + }, + { + "id": "ar-2", + "name": "Artist 2" + } + ], + "displayArtist": "Artist 1 feat. Artist 2", + "releaseTypes": [ + "Album", + "Remixes" + ], + "moods": [ + "slow", + "cool" + ], + "sortName": "lagerfeuer (8-bit)", + "originalReleaseDate": { + "year": 2001, + "month": 3, + "day": 10 + }, + "releaseDate": { + "year": 2001, + "month": 3, + "day": 10 + }, + "isCompilation": false, + "explicitStatus": "explicit", + "discTitles": [ + { + "disc": 0, + "title": "Disc 0 title" + }, + { + "disc": 2, + "title": "Disc 1 title" + } + ] +} diff --git a/tests/providers/opensubsonic/fixtures/albums/no-version.info.json b/tests/providers/opensubsonic/fixtures/albums/no-version.info.json new file mode 100644 index 00000000..b971e1be --- /dev/null +++ b/tests/providers/opensubsonic/fixtures/albums/no-version.info.json @@ -0,0 +1,7 @@ +{ + "notes": "Download the full release here (creative commons). These cripsy beats are ripe with thumping funk and techno influences, sample wizardry and daring shuffles. Composed with the help of unique sound plugins which were especially programmed to measure Comfort Fit’s needs and wishes, we think the chances aren’t bad that you’ll fall for the unique sound signature, bounce and elegance of this unusual Hip Hop production. Ltj bukem / Good looking Rec., UK: \"Really love this music.\" Velanche / XLR8R, UK: \"Awesome job he's done... overall production is dope.\" Kwesi / BBE Music, UK: \"Wooooooowwwww... WHAT THE FUCK! THIS IS WHAT", + "musicBrainzId": "6e1d48f7-717c-416e-af35-5d2454a13af2", + "smallImageUrl": "http://localhost:8989/play/art/0f8c3cbd6b0b22c3b5402141351ac812/album/21/thumb34.jpg", + "mediumImageUrl": "http://localhost:8989/play/art/41b16680dc1b3aaf5dfba24ddb6a1712/album/21/thumb64.jpg", + "largeImageUrl": "http://localhost:8989/play/art/e6fd8d4e0d35c4436e56991892bfb27b/album/21/thumb174.jpg" +} diff --git a/tests/providers/opensubsonic/fixtures/albums/spec.album.json b/tests/providers/opensubsonic/fixtures/albums/spec.album.json index 986dbb9e..f9562802 100644 --- a/tests/providers/opensubsonic/fixtures/albums/spec.album.json +++ b/tests/providers/opensubsonic/fixtures/albums/spec.album.json @@ -1,6 +1,7 @@ { "id": "ad0f112b6dcf83de5e9cae85d07f0d35", "name": "8-bit lagerfeuer", + "version": "Deluxe Edition", "artist": "pornophonique", "year": 2007, "coverArt": "al-ad0f112b6dcf83de5e9cae85d07f0d35_640a93a8", diff --git a/tests/providers/opensubsonic/fixtures/tracks/no-version.album.json b/tests/providers/opensubsonic/fixtures/tracks/no-version.album.json new file mode 100644 index 00000000..9ce43634 --- /dev/null +++ b/tests/providers/opensubsonic/fixtures/tracks/no-version.album.json @@ -0,0 +1,74 @@ + + +{ + "id": "e8a0685e3f3ec6f251649af2b58b8617", + "name": "Live at The Casbah - 2005-04-29", + "artist": "pornophonique", + "year": 2007, + "coverArt": "al-ad0f112b6dcf83de5e9cae85d07f0d35_640a93a8", + "starred": "2023-03-22T01:51:06Z", + "duration": 1954, + "playCount": 97, + "genre": "Hip-Hop", + "created": "2023-03-10T02:19:35.784818075Z", + "artistId": "97e0398acf63f9fb930d7d4ce209a52b", + "songCount": 8, + "played": "2023-03-28T00:45:13Z", + "userRating": 4, + "recordLabels": [ + { + "name": "Sony" + } + ], + "musicBrainzId": "189002e7-3285-4e2e-92a3-7f6c30d407a2", + "genres": [ + { + "name": "Hip-Hop" + }, + { + "name": "East coast" + } + ], + "artists": [ + { + "id": "ar-1", + "name": "Artist 1" + }, + { + "id": "ar-2", + "name": "Artist 2" + } + ], + "displayArtist": "Artist 1 feat. Artist 2", + "releaseTypes": [ + "Album", + "Remixes" + ], + "moods": [ + "slow", + "cool" + ], + "sortName": "lagerfeuer (8-bit)", + "originalReleaseDate": { + "year": 2001, + "month": 3, + "day": 10 + }, + "releaseDate": { + "year": 2001, + "month": 3, + "day": 10 + }, + "isCompilation": false, + "explicitStatus": "explicit", + "discTitles": [ + { + "disc": 0, + "title": "Disc 0 title" + }, + { + "disc": 2, + "title": "Disc 1 title" + } + ] +} diff --git a/tests/providers/opensubsonic/fixtures/tracks/no-version.track.json b/tests/providers/opensubsonic/fixtures/tracks/no-version.track.json new file mode 100644 index 00000000..acaae276 --- /dev/null +++ b/tests/providers/opensubsonic/fixtures/tracks/no-version.track.json @@ -0,0 +1,108 @@ +{ + "id": "082f435a363c32c57d5edb6a678a28d4", + "parent": "e8a0685e3f3ec6f251649af2b58b8617", + "isDir": false, + "title": "\"polar expedition\"", + "album": "Live at The Casbah - 2005-04-29", + "artist": "The New Deal", + "track": 4, + "year": 2005, + "coverArt": "mf-082f435a363c32c57d5edb6a678a28d4_6410b3ce", + "size": 19866778, + "contentType": "audio/flac", + "suffix": "flac", + "starred": "2023-03-27T09:45:27Z", + "duration": 178, + "bitRate": 880, + "bitDepth": 16, + "samplingRate": 44100, + "channelCount": 2, + "path": "The New Deal/Live at The Casbah - 2005-04-29/04 - \"polar expedition\".flac", + "playCount": 8, + "played": "2023-03-26T22:27:46Z", + "discNumber": 1, + "created": "2023-03-14T17:51:22.112827504Z", + "albumId": "e8a0685e3f3ec6f251649af2b58b8617", + "artistId": "97e0398acf63f9fb930d7d4ce209a52b", + "type": "music", + "mediaType": "song", + "isVideo": false, + "bpm": 134, + "comment": "This is a song comment", + "sortName": "Polar expedition", + "musicBrainzId": "189002e7-3285-4e2e-92a3-7f6c30d407a2", + "genres": [ + { + "name": "Hip-Hop" + }, + { + "name": "East coast" + } + ], + "artists": [ + { + "id": "ar-1", + "name": "Artist 1" + }, + { + "id": "ar-2", + "name": "Artist 2" + } + ], + "displayArtist": "Artist 1 feat. Artist 2", + "albumArtists": [ + { + "id": "ar-6", + "name": "Artist 6" + }, + { + "id": "ar-7", + "name": "Artist 7" + } + ], + "displayAlbumArtist": "Artist 6 & Artist 7", + "contributors": [ + { + "role": "composer", + "artist": { + "id": "ar-3", + "name": "Artist 3" + } + }, + { + "role": "composer", + "artist": { + "id": "ar-4", + "name": "Artist 4" + } + }, + { + "role": "lyricist", + "artist": { + "id": "ar-5", + "name": "Artist 5" + } + }, + { + "role": "performer", + "subRole": "Bass", + "artist": { + "id": "ar-5", + "name": "Artist 5" + } + } + ], + "displayComposer": "Artist 3, Artist 4", + "moods": [ + "slow", + "cool" + ], + "explicitStatus": "explicit", + "replayGain": { + "trackGain": 0.1, + "albumGain": 1.1, + "trackPeak": 9.2, + "albumPeak": 9, + "baseGain": 0 + } +} -- 2.34.1