From 2c09f733a298a992fe2471c7c0781eda072fa3e0 Mon Sep 17 00:00:00 2001 From: Joostlek Date: Wed, 29 Nov 2023 22:25:07 +0100 Subject: [PATCH] Add playback state --- src/spotifyaio/models.py | 125 ++++++++++++++++++++++++- tests/__snapshots__/test_playback.ambr | 72 +++++++++++++- 2 files changed, 195 insertions(+), 2 deletions(-) diff --git a/src/spotifyaio/models.py b/src/spotifyaio/models.py index ea10741..cab3ead 100644 --- a/src/spotifyaio/models.py +++ b/src/spotifyaio/models.py @@ -1,10 +1,21 @@ """Models for Spotify.""" +from __future__ import annotations + from dataclasses import dataclass, field +from enum import StrEnum from mashumaro import field_options from mashumaro.mixins.orjson import DataClassORJSONMixin +class DeviceType(StrEnum): + """Device type.""" + + COMPUTER = "Computer" + SMARTPHONE = "Smartphone" + SPEAKER = "Speaker" + + @dataclass class Device(DataClassORJSONMixin): """Device model.""" @@ -14,12 +25,124 @@ class Device(DataClassORJSONMixin): is_private_session: bool name: str supports_volume: bool - device_type: str = field(metadata=field_options(alias="type")) + device_type: DeviceType = field(metadata=field_options(alias="type")) volume_percent: int +class RepeatMode(StrEnum): + """Repeat mode.""" + + OFF = "off" + TRACK = "track" + CONTEXT = "context" + + +class ContextType(StrEnum): + """Context type.""" + + ALBUM = "album" + ARTIST = "artist" + PLAYLIST = "playlist" + COLLECTION = "collection" + SHOW = "show" + + +@dataclass +class Context(DataClassORJSONMixin): + """Context model.""" + + external_urls: dict[str, str] + href: str + context_type: ContextType = field(metadata=field_options(alias="type")) + uri: str + + +class AlbumType(StrEnum): + """Album type.""" + + ALBUM = "album" + SINGLE = "single" + COMPILATION = "compilation" + + +@dataclass +class Image(DataClassORJSONMixin): + """Image model.""" + + height: int + width: int + url: str + + +class ReleaseDatePrecision(StrEnum): + """Release date precision.""" + + YEAR = "year" + MONTH = "month" + DAY = "day" + + +@dataclass +class SimplifiedArtist(DataClassORJSONMixin): + """Simplified artist model.""" + + artist_id: str = field(metadata=field_options(alias="id")) + name: str + uri: str + + +@dataclass +class Album(DataClassORJSONMixin): + """Album model.""" + + album_type: AlbumType + total_tracks: int + album_id: str = field(metadata=field_options(alias="id")) + images: list[Image] + name: str + release_date: str + release_date_precision: ReleaseDatePrecision + uri: str + artists: list[SimplifiedArtist] + + +@dataclass +class Artist(DataClassORJSONMixin): + """Artist model.""" + + artist_id: str = field(metadata=field_options(alias="id")) + name: str + uri: str + + +@dataclass +class Track(DataClassORJSONMixin): + """Track model.""" + + track_id: str = field(metadata=field_options(alias="id")) + album: Album + artists: list[Artist] + disc_number: int + duration_ms: int + explicit: bool + external_ids: dict[str, str] + external_urls: dict[str, str] + href: str + is_local: bool + track_number: int + object_type: str = field(metadata=field_options(alias="type")) + uri: str + + @dataclass class PlaybackState(DataClassORJSONMixin): """Playback state model.""" device: Device + shuffle: bool = field(metadata=field_options(alias="shuffle_state")) + repeat_mode: RepeatMode = field(metadata=field_options(alias="repeat_state")) + context: Context | None + progress_ms: int | None + is_playing: bool + item: Track | None + currently_playing_type: str | None diff --git a/tests/__snapshots__/test_playback.ambr b/tests/__snapshots__/test_playback.ambr index 3a86840..b6a3518 100644 --- a/tests/__snapshots__/test_playback.ambr +++ b/tests/__snapshots__/test_playback.ambr @@ -1,14 +1,84 @@ # serializer version: 1 # name: test_get_devices dict({ + 'context': dict({ + 'context_type': , + 'external_urls': dict({ + 'spotify': 'https://open.spotify.com/collection/tracks', + }), + 'href': 'https://api.spotify.com/v1/me/tracks', + 'uri': 'spotify:user:1112264649:collection', + }), + 'currently_playing_type': 'track', 'device': dict({ 'device_id': '21dac6b0e0a1f181870fdc9749b2656466557687', - 'device_type': 'Computer', + 'device_type': , 'is_active': True, 'is_private_session': False, 'name': 'DESKTOP-BKC5SIK', 'supports_volume': True, 'volume_percent': 69, }), + 'is_playing': True, + 'item': dict({ + 'album': dict({ + 'album_id': '1iasbpTobDPa5BmsK0Rz1f', + 'album_type': , + 'artists': list([ + dict({ + 'artist_id': '6cmp7ut7okJAgJOSaMAVf3', + 'name': 'Machinae Supremacy', + 'uri': 'spotify:artist:6cmp7ut7okJAgJOSaMAVf3', + }), + ]), + 'images': list([ + dict({ + 'height': 640, + 'url': 'https://i.scdn.co/image/ab67616d0000b273326db007f167499d23171722', + 'width': 640, + }), + dict({ + 'height': 300, + 'url': 'https://i.scdn.co/image/ab67616d00001e02326db007f167499d23171722', + 'width': 300, + }), + dict({ + 'height': 64, + 'url': 'https://i.scdn.co/image/ab67616d00004851326db007f167499d23171722', + 'width': 64, + }), + ]), + 'name': 'WARRIORS, Pt. 1 (Final Stage)', + 'release_date': '2023-10-20', + 'release_date_precision': , + 'total_tracks': 1, + 'uri': 'spotify:album:1iasbpTobDPa5BmsK0Rz1f', + }), + 'artists': list([ + dict({ + 'artist_id': '6cmp7ut7okJAgJOSaMAVf3', + 'name': 'Machinae Supremacy', + 'uri': 'spotify:artist:6cmp7ut7okJAgJOSaMAVf3', + }), + ]), + 'disc_number': 1, + 'duration_ms': 268525, + 'explicit': False, + 'external_ids': dict({ + 'isrc': 'QZTB52388870', + }), + 'external_urls': dict({ + 'spotify': 'https://open.spotify.com/track/1FyXbzOlq3dkxaB6iRsETv', + }), + 'href': 'https://api.spotify.com/v1/tracks/1FyXbzOlq3dkxaB6iRsETv', + 'is_local': False, + 'object_type': 'track', + 'track_id': '1FyXbzOlq3dkxaB6iRsETv', + 'track_number': 1, + 'uri': 'spotify:track:1FyXbzOlq3dkxaB6iRsETv', + }), + 'progress_ms': 225564, + 'repeat_mode': , + 'shuffle': False, }) # ---