Restyled by yapf

This commit is contained in:
Restyled.io
2021-05-22 01:27:30 +00:00
parent 9c47be20a5
commit 0fbe39722b
48 changed files with 1213 additions and 1198 deletions

View File

@@ -33,18 +33,15 @@ def client():
return return
if (args[0] == "p" or args[0] == "play") and len(args) == 2: if (args[0] == "p" or args[0] == "play") and len(args) == 2:
track_uri_search = re.search( track_uri_search = re.search(
r"^spotify:track:(?P<TrackID>[0-9a-zA-Z]{22})$", args[1] r"^spotify:track:(?P<TrackID>[0-9a-zA-Z]{22})$", args[1])
)
track_url_search = re.search( track_url_search = re.search(
r"^(https?://)?open.spotify.com/track/(?P<TrackID>[0-9a-zA-Z]{22})(\?si=.+?)?$", r"^(https?://)?open.spotify.com/track/(?P<TrackID>[0-9a-zA-Z]{22})(\?si=.+?)?$",
args[1], args[1],
) )
if track_uri_search is not None or track_url_search is not None: if track_uri_search is not None or track_url_search is not None:
track_id_str = ( track_id_str = (track_uri_search
track_uri_search if track_uri_search is not None else
if track_uri_search is not None track_url_search).group("TrackID")
else track_url_search
).group("TrackID")
play(track_id_str) play(track_id_str)
wait() wait()
if args[0] == "q" or args[0] == "quality": if args[0] == "q" or args[0] == "quality":
@@ -64,20 +61,22 @@ def client():
token = session.tokens().get("user-read-email") token = session.tokens().get("user-read-email")
resp = requests.get( resp = requests.get(
"https://api.spotify.com/v1/search", "https://api.spotify.com/v1/search",
{"limit": "5", "offset": "0", "q": cmd[2:], "type": "track"}, {
"limit": "5",
"offset": "0",
"q": cmd[2:],
"type": "track"
},
headers={"Authorization": "Bearer %s" % token}, headers={"Authorization": "Bearer %s" % token},
) )
i = 1 i = 1
tracks = resp.json()["tracks"]["items"] tracks = resp.json()["tracks"]["items"]
for track in tracks: for track in tracks:
print( print("%d, %s | %s" % (
"%d, %s | %s"
% (
i, i,
track["name"], track["name"],
",".join([artist["name"] for artist in track["artists"]]), ",".join([artist["name"] for artist in track["artists"]]),
) ))
)
i += 1 i += 1
position = -1 position = -1
while True: while True:
@@ -115,8 +114,7 @@ def login():
def play(track_id_str: str): def play(track_id_str: str):
track_id = TrackId.from_base62(track_id_str) track_id = TrackId.from_base62(track_id_str)
stream = session.content_feeder().load( stream = session.content_feeder().load(
track_id, VorbisOnlyAudioQuality(AudioQuality.VERY_HIGH), False, None track_id, VorbisOnlyAudioQuality(AudioQuality.VERY_HIGH), False, None)
)
ffplay = subprocess.Popen( ffplay = subprocess.Popen(
["ffplay", "-"], ["ffplay", "-"],
stdin=subprocess.PIPE, stdin=subprocess.PIPE,
@@ -131,13 +129,11 @@ def play(track_id_str: str):
def splash(): def splash():
print( print("=================================\n"
"=================================\n"
"| Librespot-Python Player |\n" "| Librespot-Python Player |\n"
"| |\n" "| |\n"
"| by kokarare1212 |\n" "| by kokarare1212 |\n"
"=================================\n\n\n" "=================================\n\n\n")
)
def main(): def main():

View File

@@ -24,7 +24,8 @@ class ZeroconfServer(Closeable):
__keys: DiffieHellman __keys: DiffieHellman
__inner: ZeroconfServer.Inner __inner: ZeroconfServer.Inner
def __init__(self, inner: ZeroconfServer.Inner, listen_port: int, listen_all: bool): def __init__(self, inner: ZeroconfServer.Inner, listen_port: int,
listen_all: bool):
self.__inner = inner self.__inner = inner
self.__keys = DiffieHellman() self.__keys = DiffieHellman()
@@ -78,15 +79,13 @@ class ZeroconfServer(Closeable):
self.conf = conf self.conf = conf
self.device_type = device_type self.device_type = device_type
self.device_name = device_name self.device_name = device_name
self.device_id = ( self.device_id = (device_id if device_id is not None else
device_id if device_id is not None else Utils.random_hex_string(40) Utils.random_hex_string(40))
)
class HttpRunner(Runnable, Closeable): class HttpRunner(Runnable, Closeable):
__sock: socket __sock: socket
__executorService: concurrent.futures.ThreadPoolExecutor = ( __executorService: concurrent.futures.ThreadPoolExecutor = (
concurrent.futures.ThreadPoolExecutor() concurrent.futures.ThreadPoolExecutor())
)
__shouldStop: bool = False __shouldStop: bool = False
def __init__(self, port: int): def __init__(self, port: int):

View File

@@ -22,7 +22,9 @@ class AbsChunkedInputStream(InputStream, HaltListener):
_decoded_length: int = 0 _decoded_length: int = 0
def __init__(self, retry_on_chunk_error: bool): def __init__(self, retry_on_chunk_error: bool):
self.retries: typing.Final[typing.List[int]] = [0 for _ in range(self.chunks())] self.retries: typing.Final[typing.List[int]] = [
0 for _ in range(self.chunks())
]
self.retry_on_chunk_error = retry_on_chunk_error self.retry_on_chunk_error = retry_on_chunk_error
def is_closed(self) -> bool: def is_closed(self) -> bool:
@@ -107,13 +109,10 @@ class AbsChunkedInputStream(InputStream, HaltListener):
self.request_chunk_from_stream(chunk) self.request_chunk_from_stream(chunk)
self.requested_chunks()[chunk] = True self.requested_chunks()[chunk] = True
for i in range( for i in range(chunk + 1,
chunk + 1, min(self.chunks() - 1, chunk + self.preload_ahead) + 1 min(self.chunks() - 1, chunk + self.preload_ahead) + 1):
): if (self.requested_chunks()[i]
if ( and self.retries[i] < self.preload_chunk_retries):
self.requested_chunks()[i]
and self.retries[i] < self.preload_chunk_retries
):
self.request_chunk_from_stream(i) self.request_chunk_from_stream(i)
self.requested_chunks()[chunk] = True self.requested_chunks()[chunk] = True
@@ -147,7 +146,10 @@ class AbsChunkedInputStream(InputStream, HaltListener):
self.check_availability(chunk, True, True) self.check_availability(chunk, True, True)
def read(self, b: bytearray = None, offset: int = None, length: int = None) -> int: def read(self,
b: bytearray = None,
offset: int = None,
length: int = None) -> int:
if b is None and offset is None and length is None: if b is None and offset is None and length is None:
return self.internal_read() return self.internal_read()
if not (b is not None and offset is not None and length is not None): if not (b is not None and offset is not None and length is not None):
@@ -157,9 +159,8 @@ class AbsChunkedInputStream(InputStream, HaltListener):
raise IOError("Stream is closed!") raise IOError("Stream is closed!")
if offset < 0 or length < 0 or length > len(b) - offset: if offset < 0 or length < 0 or length > len(b) - offset:
raise IndexError( raise IndexError("offset: {}, length: {}, buffer: {}".format(
"offset: {}, length: {}, buffer: {}".format(offset, length, len(b)) offset, length, len(b)))
)
elif length == 0: elif length == 0:
return 0 return 0
@@ -174,7 +175,8 @@ class AbsChunkedInputStream(InputStream, HaltListener):
self.check_availability(chunk, True, False) self.check_availability(chunk, True, False)
copy = min(len(self.buffer()[chunk]) - chunk_off, length - i) copy = min(len(self.buffer()[chunk]) - chunk_off, length - i)
b[offset + 0 : copy] = self.buffer()[chunk][chunk_off : chunk_off + copy] b[offset + 0:copy] = self.buffer()[chunk][chunk_off:chunk_off +
copy]
i += copy i += copy
self._pos += copy self._pos += copy
@@ -222,5 +224,4 @@ class AbsChunkedInputStream(InputStream, HaltListener):
@staticmethod @staticmethod
def from_stream_error(stream_error: int): def from_stream_error(stream_error: int):
return AbsChunkedInputStream.ChunkException( return AbsChunkedInputStream.ChunkException(
"Failed due to stream error, code: {}".format(stream_error) "Failed due to stream error, code: {}".format(stream_error))
)

View File

@@ -26,7 +26,10 @@ class AudioKeyManager(PacketsReceiver):
def __init__(self, session: Session): def __init__(self, session: Session):
self._session = session self._session = session
def get_audio_key(self, gid: bytes, file_id: bytes, retry: bool = True) -> bytes: def get_audio_key(self,
gid: bytes,
file_id: bytes,
retry: bool = True) -> bytes:
seq: int seq: int
with self._seqHolderLock: with self._seqHolderLock:
seq = self._seqHolder seq = self._seqHolder
@@ -49,9 +52,8 @@ class AudioKeyManager(PacketsReceiver):
return self.get_audio_key(gid, file_id, False) return self.get_audio_key(gid, file_id, False)
raise RuntimeError( raise RuntimeError(
"Failed fetching audio key! gid: {}, fileId: {}".format( "Failed fetching audio key! gid: {}, fileId: {}".format(
Utils.Utils.bytes_to_hex(gid), Utils.Utils.bytes_to_hex(file_id) Utils.Utils.bytes_to_hex(gid),
) Utils.Utils.bytes_to_hex(file_id)))
)
return key return key
@@ -61,7 +63,8 @@ class AudioKeyManager(PacketsReceiver):
callback = self._callbacks.get(seq) callback = self._callbacks.get(seq)
if callback is None: if callback is None:
self._LOGGER.warning("Couldn't find callback for seq: {}".format(seq)) self._LOGGER.warning(
"Couldn't find callback for seq: {}".format(seq))
return return
if packet.is_cmd(Packet.Type.aes_key): if packet.is_cmd(Packet.Type.aes_key):
@@ -73,9 +76,7 @@ class AudioKeyManager(PacketsReceiver):
else: else:
self._LOGGER.warning( self._LOGGER.warning(
"Couldn't handle packet, cmd: {}, length: {}".format( "Couldn't handle packet, cmd: {}, length: {}".format(
packet.cmd, len(packet.payload) packet.cmd, len(packet.payload)))
)
)
class Callback: class Callback:
def key(self, key: bytes) -> None: def key(self, key: bytes) -> None:
@@ -99,15 +100,15 @@ class AudioKeyManager(PacketsReceiver):
def error(self, code: int) -> None: def error(self, code: int) -> None:
self._audioKeyManager._LOGGER.fatal( self._audioKeyManager._LOGGER.fatal(
"Audio key error, code: {}".format(code) "Audio key error, code: {}".format(code))
)
with self.reference_lock: with self.reference_lock:
self.reference.put(None) self.reference.put(None)
self.reference_lock.notify_all() self.reference_lock.notify_all()
def wait_response(self) -> bytes: def wait_response(self) -> bytes:
with self.reference_lock: with self.reference_lock:
self.reference_lock.wait(AudioKeyManager._AUDIO_KEY_REQUEST_TIMEOUT) self.reference_lock.wait(
AudioKeyManager._AUDIO_KEY_REQUEST_TIMEOUT)
return self.reference.get(block=False) return self.reference.get(block=False)
class AesKeyException(IOError): class AesKeyException(IOError):

View File

@@ -20,8 +20,7 @@ class PlayableContentFeeder:
_LOGGER: logging = logging.getLogger(__name__) _LOGGER: logging = logging.getLogger(__name__)
STORAGE_RESOLVE_INTERACTIVE: str = "/storage-resolve/files/audio/interactive/{}" STORAGE_RESOLVE_INTERACTIVE: str = "/storage-resolve/files/audio/interactive/{}"
STORAGE_RESOLVE_INTERACTIVE_PREFETCH: str = ( STORAGE_RESOLVE_INTERACTIVE_PREFETCH: str = (
"/storage-resolve/files/audio/interactive_prefetch/{}" "/storage-resolve/files/audio/interactive_prefetch/{}")
)
session: Session session: Session
def __init__(self, session: Session): def __init__(self, session: Session):
@@ -45,20 +44,17 @@ class PlayableContentFeeder:
halt_listener: HaltListener, halt_listener: HaltListener,
): ):
if type(playable_id) is TrackId: if type(playable_id) is TrackId:
return self.load_track( return self.load_track(playable_id, audio_quality_picker, preload,
playable_id, audio_quality_picker, preload, halt_listener halt_listener)
)
def resolve_storage_interactive( def resolve_storage_interactive(
self, file_id: bytes, preload: bool self, file_id: bytes,
) -> StorageResolve.StorageResolveResponse: preload: bool) -> StorageResolve.StorageResolveResponse:
resp = self.session.api().send( resp = self.session.api().send(
"GET", "GET",
( (self.STORAGE_RESOLVE_INTERACTIVE_PREFETCH
self.STORAGE_RESOLVE_INTERACTIVE_PREFETCH if preload else self.STORAGE_RESOLVE_INTERACTIVE).format(
if preload Utils.bytes_to_hex(file_id)),
else self.STORAGE_RESOLVE_INTERACTIVE
).format(Utils.bytes_to_hex(file_id)),
None, None,
None, None,
) )
@@ -81,7 +77,8 @@ class PlayableContentFeeder:
halt_listener: HaltListener, halt_listener: HaltListener,
): ):
if type(track_id_or_track) is TrackId: if type(track_id_or_track) is TrackId:
original = self.session.api().get_metadata_4_track(track_id_or_track) original = self.session.api().get_metadata_4_track(
track_id_or_track)
track = self.pick_alternative_if_necessary(original) track = self.pick_alternative_if_necessary(original)
if track is None: if track is None:
raise raise
@@ -89,7 +86,8 @@ class PlayableContentFeeder:
track = track_id_or_track track = track_id_or_track
file = audio_quality_picker.get_file(track.file) file = audio_quality_picker.get_file(track.file)
if file is None: if file is None:
self._LOGGER.fatal("Couldn't find any suitable audio file, available") self._LOGGER.fatal(
"Couldn't find any suitable audio file, available")
raise raise
return self.load_stream(file, track, None, preload, halt_listener) return self.load_stream(file, track, None, preload, halt_listener)
@@ -108,12 +106,10 @@ class PlayableContentFeeder:
resp = self.resolve_storage_interactive(file.file_id, preload) resp = self.resolve_storage_interactive(file.file_id, preload)
if resp.result == StorageResolve.StorageResolveResponse.Result.CDN: if resp.result == StorageResolve.StorageResolveResponse.Result.CDN:
if track is not None: if track is not None:
return CdnFeedHelper.load_track( return CdnFeedHelper.load_track(self.session, track, file,
self.session, track, file, resp, preload, halt_lister resp, preload, halt_lister)
) return CdnFeedHelper.load_episode(self.session, episode, file,
return CdnFeedHelper.load_episode( resp, preload, halt_lister)
self.session, episode, file, resp, preload, halt_lister
)
elif resp.result == StorageResolve.StorageResolveResponse.Result.STORAGE: elif resp.result == StorageResolve.StorageResolveResponse.Result.STORAGE:
if track is None: if track is None:
# return StorageFeedHelper # return StorageFeedHelper
@@ -156,10 +152,10 @@ class PlayableContentFeeder:
preloaded_audio_key: bool preloaded_audio_key: bool
audio_key_time: int audio_key_time: int
def __init__( def __init__(self, file_id: bytes, preloaded_audio_key: bool,
self, file_id: bytes, preloaded_audio_key: bool, audio_key_time: int audio_key_time: int):
): self.file_id = None if file_id is None else Utils.bytes_to_hex(
self.file_id = None if file_id is None else Utils.bytes_to_hex(file_id) file_id)
self.preloaded_audio_key = preloaded_audio_key self.preloaded_audio_key = preloaded_audio_key
self.audio_key_time = audio_key_time self.audio_key_time = audio_key_time

View File

@@ -40,7 +40,8 @@ class CdnFeedHelper:
streamer = session.cdn().stream_file(file, key, url, halt_listener) streamer = session.cdn().stream_file(file, key, url, halt_listener)
input_stream = streamer.stream() input_stream = streamer.stream()
normalization_data = NormalizationData.NormalizationData.read(input_stream) normalization_data = NormalizationData.NormalizationData.read(
input_stream)
if input_stream.skip(0xA7) != 0xA7: if input_stream.skip(0xA7) != 0xA7:
raise IOError("Couldn't skip 0xa7 bytes!") raise IOError("Couldn't skip 0xa7 bytes!")
return PlayableContentFeeder.PlayableContentFeeder.LoadedStream( return PlayableContentFeeder.PlayableContentFeeder.LoadedStream(
@@ -48,13 +49,13 @@ class CdnFeedHelper:
streamer, streamer,
normalization_data, normalization_data,
PlayableContentFeeder.PlayableContentFeeder.Metrics( PlayableContentFeeder.PlayableContentFeeder.Metrics(
file.file_id, preload, -1 if preload else audio_key_time file.file_id, preload, -1 if preload else audio_key_time),
),
) )
@staticmethod @staticmethod
def load_episode_external( def load_episode_external(
session: Session, episode: Metadata.Episode, halt_listener: HaltListener session: Session, episode: Metadata.Episode,
halt_listener: HaltListener
) -> PlayableContentFeeder.PlayableContentFeeder.LoadedStream: ) -> PlayableContentFeeder.PlayableContentFeeder.LoadedStream:
resp = session.client().head(episode.external_url) resp = session.client().head(episode.external_url)
@@ -62,18 +63,17 @@ class CdnFeedHelper:
CdnFeedHelper._LOGGER.warning("Couldn't resolve redirect!") CdnFeedHelper._LOGGER.warning("Couldn't resolve redirect!")
url = resp.url url = resp.url
CdnFeedHelper._LOGGER.debug( CdnFeedHelper._LOGGER.debug("Fetched external url for {}: {}".format(
"Fetched external url for {}: {}".format( Utils.Utils.bytes_to_hex(episode.gid), url))
Utils.Utils.bytes_to_hex(episode.gid), url
)
)
streamer = session.cdn().stream_external_episode(episode, url, halt_listener) streamer = session.cdn().stream_external_episode(
episode, url, halt_listener)
return PlayableContentFeeder.PlayableContentFeeder.LoadedStream( return PlayableContentFeeder.PlayableContentFeeder.LoadedStream(
episode, episode,
streamer, streamer,
None, None,
PlayableContentFeeder.PlayableContentFeeder.Metrics(None, False, -1), PlayableContentFeeder.PlayableContentFeeder.Metrics(
None, False, -1),
) )
@staticmethod @staticmethod
@@ -102,6 +102,5 @@ class CdnFeedHelper:
streamer, streamer,
normalization_data, normalization_data,
PlayableContentFeeder.PlayableContentFeeder.Metrics( PlayableContentFeeder.PlayableContentFeeder.Metrics(
file.file_id, False, audio_key_time file.file_id, False, audio_key_time),
),
) )

View File

@@ -37,9 +37,9 @@ class CdnManager:
def get_head(self, file_id: bytes): def get_head(self, file_id: bytes):
resp = self._session.client().get( resp = self._session.client().get(
self._session.get_user_attribute( self._session.get_user_attribute(
"head-files-url", "https://heads-fa.spotify.com/head/{file_id}" "head-files-url",
).replace("{file_id}", Utils.bytes_to_hex(file_id)) "https://heads-fa.spotify.com/head/{file_id}").replace(
) "{file_id}", Utils.bytes_to_hex(file_id)))
if resp.status_code != 200: if resp.status_code != 200:
raise IOError("{}".format(resp.status_code)) raise IOError("{}".format(resp.status_code))
@@ -50,9 +50,9 @@ class CdnManager:
return body return body
def stream_external_episode( def stream_external_episode(self, episode: Metadata.Episode,
self, episode: Metadata.Episode, external_url: str, halt_listener: HaltListener external_url: str,
): halt_listener: HaltListener):
return CdnManager.Streamer( return CdnManager.Streamer(
self._session, self._session,
StreamId(episode), StreamId(episode),
@@ -84,8 +84,7 @@ class CdnManager:
resp = self._session.api().send( resp = self._session.api().send(
"GET", "GET",
"/storage-resolve/files/audio/interactive/{}".format( "/storage-resolve/files/audio/interactive/{}".format(
Utils.bytes_to_hex(file_id) Utils.bytes_to_hex(file_id)),
),
None, None,
None, None,
) )
@@ -101,13 +100,11 @@ class CdnManager:
proto.ParseFromString(body) proto.ParseFromString(body)
if proto.result == StorageResolve.StorageResolveResponse.Result.CDN: if proto.result == StorageResolve.StorageResolveResponse.Result.CDN:
url = random.choice(proto.cdnurl) url = random.choice(proto.cdnurl)
self._LOGGER.debug( self._LOGGER.debug("Fetched CDN url for {}: {}".format(
"Fetched CDN url for {}: {}".format(Utils.bytes_to_hex(file_id), url) Utils.bytes_to_hex(file_id), url))
)
return url return url
raise CdnManager.CdnException( raise CdnManager.CdnException(
"Could not retrieve CDN url! result: {}".format(proto.result) "Could not retrieve CDN url! result: {}".format(proto.result))
)
class CdnException(Exception): class CdnException(Exception):
pass pass
@@ -167,8 +164,7 @@ class CdnManager:
if expire_at is None: if expire_at is None:
self._expiration = -1 self._expiration = -1
self._cdnManager._LOGGER.warning( self._cdnManager._LOGGER.warning(
"Invalid __token__ in CDN url: {}".format(url) "Invalid __token__ in CDN url: {}".format(url))
)
return return
self._expiration = expire_at * 1000 self._expiration = expire_at * 1000
@@ -178,10 +174,8 @@ class CdnManager:
except ValueError: except ValueError:
self._expiration = -1 self._expiration = -1
self._cdnManager._LOGGER.warning( self._cdnManager._LOGGER.warning(
"Couldn't extract expiration, invalid parameter in CDN url: ".format( "Couldn't extract expiration, invalid parameter in CDN url: "
url .format(url))
)
)
return return
self._expiration = int(token_url.query[:i]) * 1000 self._expiration = int(token_url.query[:i]) * 1000
@@ -224,38 +218,39 @@ class CdnManager:
self._cdnUrl = cdn_url self._cdnUrl = cdn_url
self._haltListener = halt_listener self._haltListener = halt_listener
resp = self.request(range_start=0, range_end=ChannelManager.CHUNK_SIZE - 1) resp = self.request(range_start=0,
range_end=ChannelManager.CHUNK_SIZE - 1)
content_range = resp._headers.get("Content-Range") content_range = resp._headers.get("Content-Range")
if content_range is None: if content_range is None:
raise IOError("Missing Content-Range header!") raise IOError("Missing Content-Range header!")
split = Utils.split(content_range, "/") split = Utils.split(content_range, "/")
self._size = int(split[1]) self._size = int(split[1])
self._chunks = int(math.ceil(self._size / ChannelManager.CHUNK_SIZE)) self._chunks = int(
math.ceil(self._size / ChannelManager.CHUNK_SIZE))
first_chunk = resp._buffer first_chunk = resp._buffer
self._available = [False for _ in range(self._chunks)] self._available = [False for _ in range(self._chunks)]
self._requested = [False for _ in range(self._chunks)] self._requested = [False for _ in range(self._chunks)]
self._buffer = [bytearray() for _ in range(self._chunks)] self._buffer = [bytearray() for _ in range(self._chunks)]
self._internalStream = CdnManager.Streamer.InternalStream(self, False) self._internalStream = CdnManager.Streamer.InternalStream(
self, False)
self._requested[0] = True self._requested[0] = True
self.write_chunk(first_chunk, 0, False) self.write_chunk(first_chunk, 0, False)
def write_chunk(self, chunk: bytes, chunk_index: int, cached: bool) -> None: def write_chunk(self, chunk: bytes, chunk_index: int,
cached: bool) -> None:
if self._internalStream.is_closed(): if self._internalStream.is_closed():
return return
self._session._LOGGER.debug( self._session._LOGGER.debug(
"Chunk {}/{} completed, cached: {}, stream: {}".format( "Chunk {}/{} completed, cached: {}, stream: {}".format(
chunk_index + 1, self._chunks, cached, self.describe() chunk_index + 1, self._chunks, cached, self.describe()))
)
)
self._buffer[chunk_index] = self._audioDecrypt.decrypt_chunk( self._buffer[chunk_index] = self._audioDecrypt.decrypt_chunk(
chunk_index, chunk chunk_index, chunk)
)
self._internalStream.notify_chunk_available(chunk_index) self._internalStream.notify_chunk_available(chunk_index)
def stream(self) -> AbsChunkedInputStream: def stream(self) -> AbsChunkedInputStream:
@@ -266,7 +261,8 @@ class CdnManager:
def describe(self) -> str: def describe(self) -> str:
if self._streamId.is_episode(): if self._streamId.is_episode():
return "episode_gid: {}".format(self._streamId.get_episode_gid()) return "episode_gid: {}".format(
self._streamId.get_episode_gid())
return "file_id: {}".format(self._streamId.get_file_id()) return "file_id: {}".format(self._streamId.get_file_id())
def decrypt_time_ms(self) -> int: def decrypt_time_ms(self) -> int:
@@ -276,9 +272,10 @@ class CdnManager:
resp = self.request(index) resp = self.request(index)
self.write_chunk(resp._buffer, index, False) self.write_chunk(resp._buffer, index, False)
def request( def request(self,
self, chunk: int = None, range_start: int = None, range_end: int = None chunk: int = None,
) -> CdnManager.InternalResponse: range_start: int = None,
range_end: int = None) -> CdnManager.InternalResponse:
if chunk is None and range_start is None and range_end is None: if chunk is None and range_start is None and range_end is None:
raise TypeError() raise TypeError()
@@ -288,7 +285,9 @@ class CdnManager:
resp = self._session.client().get( resp = self._session.client().get(
self._cdnUrl._url, self._cdnUrl._url,
headers={"Range": "bytes={}-{}".format(range_start, range_end)}, headers={
"Range": "bytes={}-{}".format(range_start, range_end)
},
) )
if resp.status_code != 206: if resp.status_code != 206:
@@ -324,21 +323,16 @@ class CdnManager:
def request_chunk_from_stream(self, index: int) -> None: def request_chunk_from_stream(self, index: int) -> None:
self.streamer._executorService.submit( self.streamer._executorService.submit(
lambda: self.streamer.request_chunk(index) lambda: self.streamer.request_chunk(index))
)
def stream_read_halted(self, chunk: int, _time: int) -> None: def stream_read_halted(self, chunk: int, _time: int) -> None:
if self.streamer._haltListener is not None: if self.streamer._haltListener is not None:
self.streamer._executorService.submit( self.streamer._executorService.submit(
lambda: self.streamer._haltListener.stream_read_halted( lambda: self.streamer._haltListener.stream_read_halted(
chunk, _time chunk, _time))
)
)
def stream_read_resumed(self, chunk: int, _time: int) -> None: def stream_read_resumed(self, chunk: int, _time: int) -> None:
if self.streamer._haltListener is not None: if self.streamer._haltListener is not None:
self.streamer._executorService.submit( self.streamer._executorService.submit(
lambda: self.streamer._haltListener.stream_read_resumed( lambda: self.streamer._haltListener.
chunk, _time stream_read_resumed(chunk, _time))
)
)

View File

@@ -13,35 +13,28 @@ class AudioQuality(enum.Enum):
@staticmethod @staticmethod
def get_quality(audio_format: AudioFile.Format) -> AudioQuality: def get_quality(audio_format: AudioFile.Format) -> AudioQuality:
if ( if (audio_format == AudioFile.MP3_96
audio_format == AudioFile.MP3_96
or audio_format == AudioFile.OGG_VORBIS_96 or audio_format == AudioFile.OGG_VORBIS_96
or audio_format == AudioFile.AAC_24_NORM or audio_format == AudioFile.AAC_24_NORM):
):
return AudioQuality.NORMAL return AudioQuality.NORMAL
if ( if (audio_format == AudioFile.MP3_160
audio_format == AudioFile.MP3_160
or audio_format == AudioFile.MP3_160_ENC or audio_format == AudioFile.MP3_160_ENC
or audio_format == AudioFile.OGG_VORBIS_160 or audio_format == AudioFile.OGG_VORBIS_160
or audio_format == AudioFile.AAC_24 or audio_format == AudioFile.AAC_24):
):
return AudioQuality.HIGH return AudioQuality.HIGH
if ( if (audio_format == AudioFile.MP3_320
audio_format == AudioFile.MP3_320
or audio_format == AudioFile.MP3_256 or audio_format == AudioFile.MP3_256
or audio_format == AudioFile.OGG_VORBIS_320 or audio_format == AudioFile.OGG_VORBIS_320
or audio_format == AudioFile.AAC_48 or audio_format == AudioFile.AAC_48):
):
return AudioQuality.VERY_HIGH return AudioQuality.VERY_HIGH
raise RuntimeError("Unknown format: {}".format(format)) raise RuntimeError("Unknown format: {}".format(format))
def get_matches(self, files: typing.List[AudioFile]) -> typing.List[AudioFile]: def get_matches(self,
files: typing.List[AudioFile]) -> typing.List[AudioFile]:
file_list = [] file_list = []
for file in files: for file in files:
if ( if (hasattr(file, "format")
hasattr(file, "format") and AudioQuality.get_quality(file.format) == self):
and AudioQuality.get_quality(file.format) == self
):
file_list.append(file) file_list.append(file)
return file_list return file_list

View File

@@ -8,8 +8,7 @@ from librespot.audio.storage import ChannelManager
class AesAudioDecrypt(AudioDecrypt): class AesAudioDecrypt(AudioDecrypt):
audio_aes_iv = bytes( audio_aes_iv = bytes([
[
0x72, 0x72,
0xE0, 0xE0,
0x67, 0x67,
@@ -26,8 +25,7 @@ class AesAudioDecrypt(AudioDecrypt):
0x63, 0x63,
0x0D, 0x0D,
0x93, 0x93,
] ])
)
iv_int = int.from_bytes(audio_aes_iv, "big") iv_int = int.from_bytes(audio_aes_iv, "big")
iv_diff = 0x100 iv_diff = 0x100
cipher = None cipher = None
@@ -54,10 +52,8 @@ class AesAudioDecrypt(AudioDecrypt):
new_buffer += decrypted_buffer new_buffer += decrypted_buffer
if count != len(decrypted_buffer): if count != len(decrypted_buffer):
raise RuntimeError( raise RuntimeError(
"Couldn't process all data, actual: {}, expected: {}".format( "Couldn't process all data, actual: {}, expected: {}".
len(decrypted_buffer), count format(len(decrypted_buffer), count))
)
)
iv += self.iv_diff iv += self.iv_diff
@@ -67,8 +63,5 @@ class AesAudioDecrypt(AudioDecrypt):
return new_buffer return new_buffer
def decrypt_time_ms(self): def decrypt_time_ms(self):
return ( return (0 if self.decrypt_count == 0 else int(
0 (self.decrypt_total_time / self.decrypt_count) / 1000000))
if self.decrypt_count == 0
else int((self.decrypt_total_time / self.decrypt_count) / 1000000)
)

View File

@@ -7,5 +7,6 @@ if typing.TYPE_CHECKING:
class AudioQualityPicker: class AudioQualityPicker:
def get_file(self, files: typing.List[Metadata.AudioFile]) -> Metadata.AudioFile: def get_file(self,
files: typing.List[Metadata.AudioFile]) -> Metadata.AudioFile:
pass pass

View File

@@ -24,8 +24,7 @@ class ChannelManager(Closeable, PacketsReceiver.PacketsReceiver):
_seqHolder: int = 0 _seqHolder: int = 0
_seqHolderLock: threading.Condition = threading.Condition() _seqHolderLock: threading.Condition = threading.Condition()
_executorService: concurrent.futures.ThreadPoolExecutor = ( _executorService: concurrent.futures.ThreadPoolExecutor = (
concurrent.futures.ThreadPoolExecutor() concurrent.futures.ThreadPoolExecutor())
)
_session: Session = None _session: Session = None
def __init__(self, session: Session): def __init__(self, session: Session):
@@ -58,9 +57,7 @@ class ChannelManager(Closeable, PacketsReceiver.PacketsReceiver):
if channel is None: if channel is None:
self._LOGGER.warning( self._LOGGER.warning(
"Couldn't find channel, id: {}, received: {}".format( "Couldn't find channel, id: {}, received: {}".format(
chunk_id, len(packet.payload) chunk_id, len(packet.payload)))
)
)
return return
channel._add_to_queue(payload) channel._add_to_queue(payload)
@@ -70,18 +67,14 @@ class ChannelManager(Closeable, PacketsReceiver.PacketsReceiver):
if channel is None: if channel is None:
self._LOGGER.warning( self._LOGGER.warning(
"Dropping channel error, id: {}, code: {}".format( "Dropping channel error, id: {}, code: {}".format(
chunk_id, payload.read_short() chunk_id, payload.read_short()))
)
)
return return
channel.stream_error(payload.read_short()) channel.stream_error(payload.read_short())
else: else:
self._LOGGER.warning( self._LOGGER.warning(
"Couldn't handle packet, cmd: {}, payload: {}".format( "Couldn't handle packet, cmd: {}, payload: {}".format(
packet.cmd, Utils.Utils.bytes_to_hex(packet.payload) packet.cmd, Utils.Utils.bytes_to_hex(packet.payload)))
)
)
def close(self) -> None: def close(self) -> None:
self._executorService.shutdown() self._executorService.shutdown()
@@ -95,9 +88,8 @@ class ChannelManager(Closeable, PacketsReceiver.PacketsReceiver):
_buffer: BytesOutputStream = BytesOutputStream() _buffer: BytesOutputStream = BytesOutputStream()
_header: bool = True _header: bool = True
def __init__( def __init__(self, channel_manager: ChannelManager, file: AudioFile,
self, channel_manager: ChannelManager, file: AudioFile, chunk_index: int chunk_index: int):
):
self._channelManager = channel_manager self._channelManager = channel_manager
self._file = file self._file = file
self._chunkIndex = chunk_index self._chunkIndex = chunk_index
@@ -106,18 +98,17 @@ class ChannelManager(Closeable, PacketsReceiver.PacketsReceiver):
self._channelManager._seqHolder += 1 self._channelManager._seqHolder += 1
self._channelManager._executorService.submit( self._channelManager._executorService.submit(
lambda: ChannelManager.Channel.Handler(self) lambda: ChannelManager.Channel.Handler(self))
)
def _handle(self, payload: BytesInputStream) -> bool: def _handle(self, payload: BytesInputStream) -> bool:
if len(payload.buffer) == 0: if len(payload.buffer) == 0:
if not self._header: if not self._header:
self._file.write_chunk( self._file.write_chunk(bytearray(payload.buffer),
bytearray(payload.buffer), self._chunkIndex, False self._chunkIndex, False)
)
return True return True
self._channelManager._LOGGER.debug("Received empty chunk, skipping.") self._channelManager._LOGGER.debug(
"Received empty chunk, skipping.")
return False return False
if self._header: if self._header:
@@ -128,9 +119,8 @@ class ChannelManager(Closeable, PacketsReceiver.PacketsReceiver):
break break
header_id = payload.read_byte() header_id = payload.read_byte()
header_data = payload.read(length - 1) header_data = payload.read(length - 1)
self._file.write_header( self._file.write_header(int.from_bytes(header_id, "big"),
int.from_bytes(header_id, "big"), bytearray(header_data), False bytearray(header_data), False)
)
self._header = False self._header = False
else: else:
self._buffer.write(payload.read(len(payload.buffer))) self._buffer.write(payload.read(len(payload.buffer)))
@@ -151,12 +141,11 @@ class ChannelManager(Closeable, PacketsReceiver.PacketsReceiver):
def run(self) -> None: def run(self) -> None:
self._channel._channelManager._LOGGER.debug( self._channel._channelManager._LOGGER.debug(
"ChannelManager.Handler is starting" "ChannelManager.Handler is starting")
)
with self._channel._q.all_tasks_done: with self._channel._q.all_tasks_done:
self._channel._channelManager._channels.pop(self._channel.chunkId) self._channel._channelManager._channels.pop(
self._channel.chunkId)
self._channel._channelManager._LOGGER.debug( self._channel._channelManager._LOGGER.debug(
"ChannelManager.Handler is shutting down" "ChannelManager.Handler is shutting down")
)

View File

@@ -8,7 +8,8 @@ class ApResolver:
@staticmethod @staticmethod
def request(service_type: str): def request(service_type: str):
response = requests.get("{}?type={}".format(ApResolver.base_url, service_type)) response = requests.get("{}?type={}".format(ApResolver.base_url,
service_type))
return response.json() return response.json()
@staticmethod @staticmethod

View File

@@ -47,8 +47,7 @@ from librespot.Version import Version
class Session(Closeable, SubListener, DealerClient.MessageListener): class Session(Closeable, SubListener, DealerClient.MessageListener):
_LOGGER: logging = logging.getLogger(__name__) _LOGGER: logging = logging.getLogger(__name__)
_serverKey: bytes = bytes( _serverKey: bytes = bytes([
[
0xAC, 0xAC,
0xE0, 0xE0,
0x46, 0x46,
@@ -305,8 +304,7 @@ class Session(Closeable, SubListener, DealerClient.MessageListener):
0xE6, 0xE6,
0x55, 0x55,
0xBD, 0xBD,
] ])
)
_keys: DiffieHellman = None _keys: DiffieHellman = None
_inner: Session.Inner = None _inner: Session.Inner = None
_scheduler: sched.scheduler = sched.scheduler(time.time) _scheduler: sched.scheduler = sched.scheduler(time.time)
@@ -344,9 +342,8 @@ class Session(Closeable, SubListener, DealerClient.MessageListener):
self._conn = Session.ConnectionHolder.create(addr, inner.conf) self._conn = Session.ConnectionHolder.create(addr, inner.conf)
self._client = Session._create_client(self._inner.conf) self._client = Session._create_client(self._inner.conf)
self._LOGGER.info( self._LOGGER.info("Created new session! device_id: {}, ap: {}".format(
"Created new session! device_id: {}, ap: {}".format(inner.device_id, addr) inner.device_id, addr))
)
@staticmethod @staticmethod
def _create_client(conf: Session.Configuration) -> requests.Session: def _create_client(conf: Session.Configuration) -> requests.Session:
@@ -388,12 +385,12 @@ class Session(Closeable, SubListener, DealerClient.MessageListener):
client_hello = Keyexchange.ClientHello( client_hello = Keyexchange.ClientHello(
build_info=Version.standard_build_info(), build_info=Version.standard_build_info(),
cryptosuites_supported=[Keyexchange.Cryptosuite.CRYPTO_SUITE_SHANNON], cryptosuites_supported=[
Keyexchange.Cryptosuite.CRYPTO_SUITE_SHANNON
],
login_crypto_hello=Keyexchange.LoginCryptoHelloUnion( login_crypto_hello=Keyexchange.LoginCryptoHelloUnion(
diffie_hellman=Keyexchange.LoginCryptoDiffieHellmanHello( diffie_hellman=Keyexchange.LoginCryptoDiffieHellmanHello(
gc=self._keys.public_key_array(), server_keys_known=1 gc=self._keys.public_key_array(), server_keys_known=1), ),
),
),
client_nonce=nonce, client_nonce=nonce,
padding=bytes([0x1E]), padding=bytes([0x1E]),
) )
@@ -422,22 +419,21 @@ class Session(Closeable, SubListener, DealerClient.MessageListener):
ap_response_message.ParseFromString(buffer) ap_response_message.ParseFromString(buffer)
shared_key = Utils.to_byte_array( shared_key = Utils.to_byte_array(
self._keys.compute_shared_key( self._keys.compute_shared_key(
ap_response_message.challenge.login_crypto_challenge.diffie_hellman.gs ap_response_message.challenge.login_crypto_challenge.
) diffie_hellman.gs))
)
# Check gs_signature # Check gs_signature
rsa = RSA.construct((int.from_bytes(self._serverKey, "big"), 65537)) rsa = RSA.construct((int.from_bytes(self._serverKey, "big"), 65537))
pkcs1_v1_5 = PKCS1_v1_5.new(rsa) pkcs1_v1_5 = PKCS1_v1_5.new(rsa)
sha1 = SHA1.new() sha1 = SHA1.new()
sha1.update( sha1.update(ap_response_message.challenge.login_crypto_challenge.
ap_response_message.challenge.login_crypto_challenge.diffie_hellman.gs diffie_hellman.gs)
)
# noinspection PyTypeChecker # noinspection PyTypeChecker
if not pkcs1_v1_5.verify( if not pkcs1_v1_5.verify(
sha1, sha1,
ap_response_message.challenge.login_crypto_challenge.diffie_hellman.gs_signature, ap_response_message.challenge.login_crypto_challenge.
diffie_hellman.gs_signature,
): ):
raise RuntimeError("Failed signature check!") raise RuntimeError("Failed signature check!")
@@ -460,14 +456,13 @@ class Session(Closeable, SubListener, DealerClient.MessageListener):
client_response_plaintext = Keyexchange.ClientResponsePlaintext( client_response_plaintext = Keyexchange.ClientResponsePlaintext(
login_crypto_response=Keyexchange.LoginCryptoResponseUnion( login_crypto_response=Keyexchange.LoginCryptoResponseUnion(
diffie_hellman=Keyexchange.LoginCryptoDiffieHellmanResponse( diffie_hellman=Keyexchange.LoginCryptoDiffieHellmanResponse(
hmac=challenge hmac=challenge)),
)
),
pow_response=Keyexchange.PoWResponseUnion(), pow_response=Keyexchange.PoWResponseUnion(),
crypto_response=Keyexchange.CryptoResponseUnion(), crypto_response=Keyexchange.CryptoResponseUnion(),
) )
client_response_plaintext_bytes = client_response_plaintext.SerializeToString() client_response_plaintext_bytes = client_response_plaintext.SerializeToString(
)
length = 4 + len(client_response_plaintext_bytes) length = 4 + len(client_response_plaintext_bytes)
self._conn.write_int(length) self._conn.write_int(length)
self._conn.write(client_response_plaintext_bytes) self._conn.write(client_response_plaintext_bytes)
@@ -477,12 +472,10 @@ class Session(Closeable, SubListener, DealerClient.MessageListener):
self._conn.set_timeout(1) self._conn.set_timeout(1)
scrap = self._conn.read(4) scrap = self._conn.read(4)
if 4 == len(scrap): if 4 == len(scrap):
length = ( length = ((scrap[0] << 24)
(scrap[0] << 24)
| (scrap[1] << 16) | (scrap[1] << 16)
| (scrap[2] << 8) | (scrap[2] << 8)
| (scrap[3] & 0xFF) | (scrap[3] & 0xFF))
)
payload = self._conn.read(length - 4) payload = self._conn.read(length - 4)
failed = Keyexchange.APResponseMessage() failed = Keyexchange.APResponseMessage()
failed.ParseFromString(payload) failed.ParseFromString(payload)
@@ -499,7 +492,8 @@ class Session(Closeable, SubListener, DealerClient.MessageListener):
self._LOGGER.info("Connection successfully!") self._LOGGER.info("Connection successfully!")
def _authenticate(self, credentials: Authentication.LoginCredentials) -> None: def _authenticate(self,
credentials: Authentication.LoginCredentials) -> None:
self._authenticate_partial(credentials, False) self._authenticate_partial(credentials, False)
with self._authLock: with self._authLock:
@@ -509,7 +503,8 @@ class Session(Closeable, SubListener, DealerClient.MessageListener):
self._channelManager = ChannelManager(self) self._channelManager = ChannelManager(self)
self._api = ApiClient.ApiClient(self) self._api = ApiClient.ApiClient(self)
self._cdnManager = CdnManager(self) self._cdnManager = CdnManager(self)
self._contentFeeder = PlayableContentFeeder.PlayableContentFeeder(self) self._contentFeeder = PlayableContentFeeder.PlayableContentFeeder(
self)
self._cacheManager = CacheManager(self) self._cacheManager = CacheManager(self)
self._dealer = DealerClient(self) self._dealer = DealerClient(self)
self._search = SearchManager.SearchManager(self) self._search = SearchManager.SearchManager(self)
@@ -522,15 +517,15 @@ class Session(Closeable, SubListener, DealerClient.MessageListener):
# TimeProvider.init(self) # TimeProvider.init(self)
self._dealer.connect() self._dealer.connect()
self._LOGGER.info( self._LOGGER.info("Authenticated as {}!".format(
"Authenticated as {}!".format(self._apWelcome.canonical_username) self._apWelcome.canonical_username))
)
self.mercury().interested_in("spotify:user:attributes:update", self) self.mercury().interested_in("spotify:user:attributes:update", self)
self.dealer().add_message_listener(self, "hm://connect-state/v1/connect/logout") self.dealer().add_message_listener(
self, "hm://connect-state/v1/connect/logout")
def _authenticate_partial( def _authenticate_partial(self,
self, credentials: Authentication.LoginCredentials, remove_lock: bool credentials: Authentication.LoginCredentials,
) -> None: remove_lock: bool) -> None:
if self._cipherPair is None: if self._cipherPair is None:
raise RuntimeError("Connection not established!") raise RuntimeError("Connection not established!")
@@ -545,9 +540,8 @@ class Session(Closeable, SubListener, DealerClient.MessageListener):
version_string=Version.version_string(), version_string=Version.version_string(),
) )
self._send_unchecked( self._send_unchecked(Packet.Type.login,
Packet.Type.login, client_response_encrypted.SerializeToString() client_response_encrypted.SerializeToString())
)
packet = self._cipherPair.receive_encoded(self._conn) packet = self._cipherPair.receive_encoded(self._conn)
if packet.is_cmd(Packet.Type.ap_welcome): if packet.is_cmd(Packet.Type.ap_welcome):
@@ -563,7 +557,8 @@ class Session(Closeable, SubListener, DealerClient.MessageListener):
preferred_locale += bytes([0x00, 0x00, 0x10, 0x00, 0x02]) preferred_locale += bytes([0x00, 0x00, 0x10, 0x00, 0x02])
preferred_locale += "preferred-locale".encode() preferred_locale += "preferred-locale".encode()
preferred_locale += self._inner.preferred_locale.encode() preferred_locale += self._inner.preferred_locale.encode()
self._send_unchecked(Packet.Type.preferred_locale, preferred_locale) self._send_unchecked(Packet.Type.preferred_locale,
preferred_locale)
if remove_lock: if remove_lock:
with self._authLock: with self._authLock:
@@ -573,8 +568,7 @@ class Session(Closeable, SubListener, DealerClient.MessageListener):
if self._inner.conf.store_credentials: if self._inner.conf.store_credentials:
reusable = self._apWelcome.reusable_auth_credentials reusable = self._apWelcome.reusable_auth_credentials
reusable_type = Authentication.AuthenticationType.Name( reusable_type = Authentication.AuthenticationType.Name(
self._apWelcome.reusable_auth_credentials_type self._apWelcome.reusable_auth_credentials_type)
)
if self._inner.conf.stored_credentials_file is None: if self._inner.conf.stored_credentials_file is None:
raise TypeError() raise TypeError()
@@ -597,9 +591,8 @@ class Session(Closeable, SubListener, DealerClient.MessageListener):
raise RuntimeError("Unknown CMD 0x" + packet.cmd.hex()) raise RuntimeError("Unknown CMD 0x" + packet.cmd.hex())
def close(self) -> None: def close(self) -> None:
self._LOGGER.info( self._LOGGER.info("Closing session. device_id: {}".format(
"Closing session. device_id: {}".format(self._inner.device_id) self._inner.device_id))
)
self._closing = True self._closing = True
@@ -652,9 +645,11 @@ class Session(Closeable, SubListener, DealerClient.MessageListener):
listener.on_closed() listener.on_closed()
self._closeListeners: typing.List[Session.CloseListener] = [] self._closeListeners: typing.List[Session.CloseListener] = []
self._reconnectionListeners: typing.List[Session.ReconnectionListener] = [] self._reconnectionListeners: typing.List[
Session.ReconnectionListener] = []
self._LOGGER.info("Closed session. device_id: {}".format(self._inner.device_id)) self._LOGGER.info("Closed session. device_id: {}".format(
self._inner.device_id))
def _send_unchecked(self, cmd: bytes, payload: bytes) -> None: def _send_unchecked(self, cmd: bytes, payload: bytes) -> None:
self._cipherPair.send_encoded(self._conn, cmd, payload) self._cipherPair.send_encoded(self._conn, cmd, payload)
@@ -797,8 +792,7 @@ class Session(Closeable, SubListener, DealerClient.MessageListener):
self._receiver.stop() self._receiver.stop()
self._conn = Session.ConnectionHolder.create( self._conn = Session.ConnectionHolder.create(
ApResolver.get_random_accesspoint(), self._inner.conf ApResolver.get_random_accesspoint(), self._inner.conf)
)
self._connect() self._connect()
self._authenticate_partial( self._authenticate_partial(
Authentication.LoginCredentials( Authentication.LoginCredentials(
@@ -809,9 +803,8 @@ class Session(Closeable, SubListener, DealerClient.MessageListener):
True, True,
) )
self._LOGGER.info( self._LOGGER.info("Re-authenticated as {}!".format(
"Re-authenticated as {}!".format(self._apWelcome.canonical_username) self._apWelcome.canonical_username))
)
with self._reconnectionListenersLock: with self._reconnectionListenersLock:
for listener in self._reconnectionListeners: for listener in self._reconnectionListeners:
@@ -821,11 +814,13 @@ class Session(Closeable, SubListener, DealerClient.MessageListener):
if listener not in self._closeListeners: if listener not in self._closeListeners:
self._closeListeners.append(listener) self._closeListeners.append(listener)
def add_reconnection_listener(self, listener: ReconnectionListener) -> None: def add_reconnection_listener(self,
listener: ReconnectionListener) -> None:
if listener not in self._reconnectionListeners: if listener not in self._reconnectionListeners:
self._reconnectionListeners.append(listener) self._reconnectionListeners.append(listener)
def remove_reconnection_listener(self, listener: ReconnectionListener) -> None: def remove_reconnection_listener(self,
listener: ReconnectionListener) -> None:
self._reconnectionListeners.remove(listener) self._reconnectionListeners.remove(listener)
def _parse_product_info(self, data) -> None: def _parse_product_info(self, data) -> None:
@@ -842,14 +837,12 @@ class Session(Closeable, SubListener, DealerClient.MessageListener):
for i in range(len(product)): for i in range(len(product)):
self._userAttributes[product[i].tag] = product[i].text self._userAttributes[product[i].tag] = product[i].text
self._LOGGER.debug("Parsed product info: {}".format(self._userAttributes)) self._LOGGER.debug("Parsed product info: {}".format(
self._userAttributes))
def get_user_attribute(self, key: str, fallback: str = None) -> str: def get_user_attribute(self, key: str, fallback: str = None) -> str:
return ( return (self._userAttributes.get(key)
self._userAttributes.get(key) if self._userAttributes.get(key) is not None else fallback)
if self._userAttributes.get(key) is not None
else fallback
)
def event(self, resp: MercuryClient.Response) -> None: def event(self, resp: MercuryClient.Response) -> None:
if resp.uri == "spotify:user:attributes:update": if resp.uri == "spotify:user:attributes:update":
@@ -858,13 +851,11 @@ class Session(Closeable, SubListener, DealerClient.MessageListener):
for pair in attributes_update.pairs_list: for pair in attributes_update.pairs_list:
self._userAttributes[pair.key] = pair.value self._userAttributes[pair.key] = pair.value
self._LOGGER.info( self._LOGGER.info("Updated user attribute: {} -> {}".format(
"Updated user attribute: {} -> {}".format(pair.key, pair.value) pair.key, pair.value))
)
def on_message( def on_message(self, uri: str, headers: typing.Dict[str, str],
self, uri: str, headers: typing.Dict[str, str], payload: bytes payload: bytes) -> None:
) -> None:
if uri == "hm://connect-state/v1/connect/logout": if uri == "hm://connect-state/v1/connect/logout":
self.close() self.close()
@@ -898,9 +889,8 @@ class Session(Closeable, SubListener, DealerClient.MessageListener):
self.conf = conf self.conf = conf
self.device_type = device_type self.device_type = device_type
self.device_name = device_name self.device_name = device_name
self.device_id = ( self.device_id = (device_id if device_id is not None else
device_id if device_id is not None else Utils.random_hex_string(40) Utils.random_hex_string(40))
)
class AbsBuilder: class AbsBuilder:
conf = None conf = None
@@ -934,8 +924,7 @@ class Session(Closeable, SubListener, DealerClient.MessageListener):
return self return self
def set_device_type( def set_device_type(
self, device_type: Connect.DeviceType self, device_type: Connect.DeviceType) -> Session.AbsBuilder:
) -> Session.AbsBuilder:
self.device_type = device_type self.device_type = device_type
return self return self
@@ -945,7 +934,8 @@ class Session(Closeable, SubListener, DealerClient.MessageListener):
def stored(self): def stored(self):
pass pass
def stored_file(self, stored_credentials: str = None) -> Session.Builder: def stored_file(self,
stored_credentials: str = None) -> Session.Builder:
if stored_credentials is None: if stored_credentials is None:
stored_credentials = self.conf.stored_credentials_file stored_credentials = self.conf.stored_credentials_file
if os.path.isfile(stored_credentials): if os.path.isfile(stored_credentials):
@@ -957,7 +947,8 @@ class Session(Closeable, SubListener, DealerClient.MessageListener):
else: else:
try: try:
self.login_credentials = Authentication.LoginCredentials( self.login_credentials = Authentication.LoginCredentials(
typ=Authentication.AuthenticationType.Value(obj["type"]), typ=Authentication.AuthenticationType.Value(
obj["type"]),
username=obj["username"], username=obj["username"],
auth_data=base64.b64decode(obj["credentials"]), auth_data=base64.b64decode(obj["credentials"]),
) )
@@ -1061,64 +1052,66 @@ class Session(Closeable, SubListener, DealerClient.MessageListener):
# Stored credentials # Stored credentials
store_credentials: bool = True store_credentials: bool = True
stored_credentials_file: str = os.path.join(os.getcwd(), "credentials.json") stored_credentials_file: str = os.path.join(
os.getcwd(), "credentials.json")
# Fetching # Fetching
retry_on_chunk_error: bool = None retry_on_chunk_error: bool = None
def set_proxy_enabled( def set_proxy_enabled(
self, proxy_enabled: bool self,
) -> Session.Configuration.Builder: proxy_enabled: bool) -> Session.Configuration.Builder:
self.proxyEnabled = proxy_enabled self.proxyEnabled = proxy_enabled
return self return self
def set_proxy_type( def set_proxy_type(
self, proxy_type: Proxy.Type self,
) -> Session.Configuration.Builder: proxy_type: Proxy.Type) -> Session.Configuration.Builder:
self.proxyType = proxy_type self.proxyType = proxy_type
return self return self
def set_proxy_address( def set_proxy_address(
self, proxy_address: str self, proxy_address: str) -> Session.Configuration.Builder:
) -> Session.Configuration.Builder:
self.proxyAddress = proxy_address self.proxyAddress = proxy_address
return self return self
def set_proxy_auth(self, proxy_auth: bool) -> Session.Configuration.Builder: def set_proxy_auth(
self, proxy_auth: bool) -> Session.Configuration.Builder:
self.proxyAuth = proxy_auth self.proxyAuth = proxy_auth
return self return self
def set_proxy_username( def set_proxy_username(
self, proxy_username: str self,
) -> Session.Configuration.Builder: proxy_username: str) -> Session.Configuration.Builder:
self.proxyUsername = proxy_username self.proxyUsername = proxy_username
return self return self
def set_proxy_password( def set_proxy_password(
self, proxy_password: str self,
) -> Session.Configuration.Builder: proxy_password: str) -> Session.Configuration.Builder:
self.proxyPassword = proxy_password self.proxyPassword = proxy_password
return self return self
def set_cache_enabled( def set_cache_enabled(
self, cache_enabled: bool self,
) -> Session.Configuration.Builder: cache_enabled: bool) -> Session.Configuration.Builder:
self.cache_enabled = cache_enabled self.cache_enabled = cache_enabled
return self return self
def set_cache_dir(self, cache_dir: str) -> Session.Configuration.Builder: def set_cache_dir(self,
cache_dir: str) -> Session.Configuration.Builder:
self.cache_dir = cache_dir self.cache_dir = cache_dir
return self return self
def set_do_cache_clean_up( def set_do_cache_clean_up(
self, do_cache_clean_up: bool self,
) -> Session.Configuration.Builder: do_cache_clean_up: bool) -> Session.Configuration.Builder:
self.do_cache_clean_up = do_cache_clean_up self.do_cache_clean_up = do_cache_clean_up
return self return self
def set_store_credentials( def set_store_credentials(
self, store_credentials: bool self,
) -> Session.Configuration.Builder: store_credentials: bool) -> Session.Configuration.Builder:
self.store_credentials = store_credentials self.store_credentials = store_credentials
return self return self
@@ -1153,7 +1146,8 @@ class Session(Closeable, SubListener, DealerClient.MessageListener):
class SpotifyAuthenticationException(Exception): class SpotifyAuthenticationException(Exception):
def __init__(self, login_failed: Keyexchange.APLoginFailed): def __init__(self, login_failed: Keyexchange.APLoginFailed):
super().__init__(Keyexchange.ErrorCode.Name(login_failed.error_code)) super().__init__(
Keyexchange.ErrorCode.Name(login_failed.error_code))
class Accumulator: class Accumulator:
buffer: bytes = bytes() buffer: bytes = bytes()
@@ -1180,7 +1174,8 @@ class Session(Closeable, SubListener, DealerClient.MessageListener):
self.sock = sock self.sock = sock
@staticmethod @staticmethod
def create(addr: str, conf: Session.Configuration) -> Session.ConnectionHolder: def create(addr: str,
conf: Session.Configuration) -> Session.ConnectionHolder:
ap_addr = addr.split(":")[0] ap_addr = addr.split(":")[0]
ap_port = int(addr.split(":")[1]) ap_port = int(addr.split(":")[1])
if not conf.proxyEnabled or conf.proxyType is Proxy.Type.DIRECT: if not conf.proxyEnabled or conf.proxyType is Proxy.Type.DIRECT:
@@ -1192,9 +1187,11 @@ class Session(Closeable, SubListener, DealerClient.MessageListener):
sock = socket.socket() sock = socket.socket()
sock.connect((conf.proxyAddress, conf.proxyPort)) sock.connect((conf.proxyAddress, conf.proxyPort))
sock.send("CONNECT {}:{} HTTP/1.0\n".format(ap_addr, ap_port).encode()) sock.send("CONNECT {}:{} HTTP/1.0\n".format(ap_addr,
ap_port).encode())
if conf.proxyAuth: if conf.proxyAuth:
sock.send("Proxy-Authorization: {}\n".format(None).encode()) sock.send(
"Proxy-Authorization: {}\n".format(None).encode())
sock.send(b"\n") sock.send(b"\n")
@@ -1259,21 +1256,18 @@ class Session(Closeable, SubListener, DealerClient.MessageListener):
try: try:
# noinspection PyProtectedMember # noinspection PyProtectedMember
packet = self.session._cipherPair.receive_encoded( packet = self.session._cipherPair.receive_encoded(
self.session._conn self.session._conn)
)
cmd = Packet.Type.parse(packet.cmd) cmd = Packet.Type.parse(packet.cmd)
if cmd is None: if cmd is None:
self.session._LOGGER.info( self.session._LOGGER.info(
"Skipping unknown command cmd: 0x{}, payload: {}".format( "Skipping unknown command cmd: 0x{}, payload: {}".
Utils.bytes_to_hex(packet.cmd), packet.payload format(Utils.bytes_to_hex(packet.cmd),
) packet.payload))
)
continue continue
except RuntimeError as ex: except RuntimeError as ex:
if self.running: if self.running:
self.session._LOGGER.fatal( self.session._LOGGER.fatal(
"Failed reading packet! {}".format(ex) "Failed reading packet! {}".format(ex))
)
# noinspection PyProtectedMember # noinspection PyProtectedMember
self.session._reconnect() self.session._reconnect()
break break
@@ -1284,18 +1278,17 @@ class Session(Closeable, SubListener, DealerClient.MessageListener):
# noinspection PyProtectedMember # noinspection PyProtectedMember
if self.session._scheduledReconnect is not None: if self.session._scheduledReconnect is not None:
# noinspection PyProtectedMember # noinspection PyProtectedMember
self.session._scheduler.cancel(self.session._scheduledReconnect) self.session._scheduler.cancel(
self.session._scheduledReconnect)
def anonymous(): def anonymous():
self.session._LOGGER.warning( self.session._LOGGER.warning(
"Socket timed out. Reconnecting..." "Socket timed out. Reconnecting...")
)
self.session._reconnect() self.session._reconnect()
# noinspection PyProtectedMember # noinspection PyProtectedMember
self.session.scheduled_reconnect = self.session._scheduler.enter( self.session.scheduled_reconnect = self.session._scheduler.enter(
2 * 60 + 5, 1, anonymous 2 * 60 + 5, 1, anonymous)
)
self.session.send(Packet.Type.pong, packet.payload) self.session.send(Packet.Type.pong, packet.payload)
continue continue
if cmd == Packet.Type.pong_ack: if cmd == Packet.Type.pong_ack:
@@ -1303,8 +1296,8 @@ class Session(Closeable, SubListener, DealerClient.MessageListener):
if cmd == Packet.Type.country_code: if cmd == Packet.Type.country_code:
self.session.country_code = packet.payload.decode() self.session.country_code = packet.payload.decode()
self.session._LOGGER.info( self.session._LOGGER.info(
"Received country_code: {}".format(self.session.country_code) "Received country_code: {}".format(
) self.session.country_code))
continue continue
if cmd == Packet.Type.license_version: if cmd == Packet.Type.license_version:
license_version = BytesInputStream(packet.payload) license_version = BytesInputStream(packet.payload)
@@ -1313,40 +1306,33 @@ class Session(Closeable, SubListener, DealerClient.MessageListener):
buffer = license_version.read() buffer = license_version.read()
self.session._LOGGER.info( self.session._LOGGER.info(
"Received license_version: {}, {}".format( "Received license_version: {}, {}".format(
license_id, buffer.decode() license_id, buffer.decode()))
)
)
else: else:
self.session._LOGGER.info( self.session._LOGGER.info(
"Received license_version: {}".format(license_id) "Received license_version: {}".format(license_id))
)
continue continue
if cmd == Packet.Type.unknown_0x10: if cmd == Packet.Type.unknown_0x10:
self.session._LOGGER.debug( self.session._LOGGER.debug("Received 0x10: {}".format(
"Received 0x10: {}".format(Utils.bytes_to_hex(packet.payload)) Utils.bytes_to_hex(packet.payload)))
)
continue continue
if ( if (cmd == Packet.Type.mercury_sub
cmd == Packet.Type.mercury_sub
or cmd == Packet.Type.mercury_unsub or cmd == Packet.Type.mercury_unsub
or cmd == Packet.Type.mercury_event or cmd == Packet.Type.mercury_event
or cmd == Packet.Type.mercury_req or cmd == Packet.Type.mercury_req):
):
self.session.mercury().dispatch(packet) self.session.mercury().dispatch(packet)
continue continue
if cmd == Packet.Type.aes_key or cmd == Packet.Type.aes_key_error: if cmd == Packet.Type.aes_key or cmd == Packet.Type.aes_key_error:
self.session.audio_key().dispatch(packet) self.session.audio_key().dispatch(packet)
continue continue
if ( if (cmd == Packet.Type.channel_error
cmd == Packet.Type.channel_error or cmd == Packet.Type.stream_chunk_res):
or cmd == Packet.Type.stream_chunk_res
):
self.session.channel().dispatch(packet) self.session.channel().dispatch(packet)
continue continue
if cmd == Packet.Type.product_info: if cmd == Packet.Type.product_info:
# noinspection PyProtectedMember # noinspection PyProtectedMember
self.session._parse_product_info(packet.payload) self.session._parse_product_info(packet.payload)
continue continue
self.session._LOGGER.info("Skipping {}".format(Utils.bytes_to_hex(cmd))) self.session._LOGGER.info("Skipping {}".format(
Utils.bytes_to_hex(cmd)))
self.session._LOGGER.debug("Session.Receiver stopped") self.session._LOGGER.debug("Session.Receiver stopped")

View File

@@ -18,8 +18,7 @@ class TokenProvider:
self._session = session self._session = session
def find_token_with_all_scopes( def find_token_with_all_scopes(
self, scopes: typing.List[str] self, scopes: typing.List[str]) -> TokenProvider.StoredToken:
) -> TokenProvider.StoredToken:
for token in self._tokens: for token in self._tokens:
if token.has_scopes(scopes): if token.has_scopes(scopes):
return token return token
@@ -40,20 +39,16 @@ class TokenProvider:
return token return token
self._LOGGER.debug( self._LOGGER.debug(
"Token expired or not suitable, requesting again. scopes: {}, old_token: {}".format( "Token expired or not suitable, requesting again. scopes: {}, old_token: {}"
scopes, token .format(scopes, token))
)
)
resp = self._session.mercury().send_sync_json( resp = self._session.mercury().send_sync_json(
MercuryRequests.request_token(self._session.device_id(), ",".join(scopes)) MercuryRequests.request_token(self._session.device_id(),
) ",".join(scopes)))
token = TokenProvider.StoredToken(resp) token = TokenProvider.StoredToken(resp)
self._LOGGER.debug( self._LOGGER.debug(
"Updated token successfully! scopes: {}, new_token: {}".format( "Updated token successfully! scopes: {}, new_token: {}".format(
scopes, token scopes, token))
)
)
self._tokens.append(token) self._tokens.append(token)
return token return token
@@ -74,11 +69,9 @@ class TokenProvider:
self.scopes = obj["scope"] self.scopes = obj["scope"]
def expired(self) -> bool: def expired(self) -> bool:
return ( return (self.timestamp +
self.timestamp (self.expires_in - TokenProvider._TOKEN_EXPIRE_THRESHOLD) *
+ (self.expires_in - TokenProvider._TOKEN_EXPIRE_THRESHOLD) * 1000 1000 < TimeProvider.TimeProvider().current_time_millis())
< TimeProvider.TimeProvider().current_time_millis()
)
def has_scope(self, scope: str) -> bool: def has_scope(self, scope: str) -> bool:
for s in self.scopes: for s in self.scopes:

View File

@@ -4,8 +4,7 @@ from librespot.common.Utils import Utils
class DiffieHellman: class DiffieHellman:
prime_bytes: bytearray = bytes( prime_bytes: bytearray = bytes([
[
0xFF, 0xFF,
0xFF, 0xFF,
0xFF, 0xFF,
@@ -102,8 +101,7 @@ class DiffieHellman:
0xFF, 0xFF,
0xFF, 0xFF,
0xFF, 0xFF,
] ])
)
prime: int = int.from_bytes(prime_bytes, "big") prime: int = int.from_bytes(prime_bytes, "big")
private_key: int private_key: int
public_key: int public_key: int

View File

@@ -37,8 +37,7 @@ class ApiClient(Closeable):
if headers is not None: if headers is not None:
request.headers = headers request.headers = headers
request.headers["Authorization"] = "Bearer {}".format( request.headers["Authorization"] = "Bearer {}".format(
self._session.tokens().get("playlist-read") self._session.tokens().get("playlist-read"))
)
request.url = self._baseUrl + suffix request.url = self._baseUrl + suffix
return request return request
@@ -50,13 +49,11 @@ class ApiClient(Closeable):
body: typing.Union[None, bytes], body: typing.Union[None, bytes],
) -> requests.Response: ) -> requests.Response:
resp = self._session.client().send( resp = self._session.client().send(
self.build_request(method, suffix, headers, body) self.build_request(method, suffix, headers, body))
)
return resp return resp
def put_connect_state( def put_connect_state(self, connection_id: str,
self, connection_id: str, proto: Connect.PutStateRequest proto: Connect.PutStateRequest) -> None:
) -> None:
resp = self.send( resp = self.send(
"PUT", "PUT",
"/connect-state/v1/devices/{}".format(self._session.device_id()), "/connect-state/v1/devices/{}".format(self._session.device_id()),
@@ -69,21 +66,15 @@ class ApiClient(Closeable):
if resp.status_code == 413: if resp.status_code == 413:
self._LOGGER.warning( self._LOGGER.warning(
"PUT state payload is too large: {} bytes uncompressed.".format( "PUT state payload is too large: {} bytes uncompressed.".
len(proto.SerializeToString()) format(len(proto.SerializeToString())))
)
)
elif resp.status_code != 200: elif resp.status_code != 200:
self._LOGGER.warning( self._LOGGER.warning("PUT state returned {}. headers: {}".format(
"PUT state returned {}. headers: {}".format( resp.status_code, resp.headers))
resp.status_code, resp.headers
)
)
def get_metadata_4_track(self, track: TrackId) -> Metadata.Track: def get_metadata_4_track(self, track: TrackId) -> Metadata.Track:
resp = self.send( resp = self.send("GET", "/metadata/4/track/{}".format(track.hex_id()),
"GET", "/metadata/4/track/{}".format(track.hex_id()), None, None None, None)
)
ApiClient.StatusCodeException.check_status(resp) ApiClient.StatusCodeException.check_status(resp)
body = resp.content body = resp.content
@@ -94,9 +85,9 @@ class ApiClient(Closeable):
return proto return proto
def get_metadata_4_episode(self, episode: EpisodeId) -> Metadata.Episode: def get_metadata_4_episode(self, episode: EpisodeId) -> Metadata.Episode:
resp = self.send( resp = self.send("GET",
"GET", "/metadata/4/episode/{}".format(episode.hex_id()), None, None "/metadata/4/episode/{}".format(episode.hex_id()),
) None, None)
ApiClient.StatusCodeException.check_status(resp) ApiClient.StatusCodeException.check_status(resp)
body = resp.content body = resp.content
@@ -107,9 +98,8 @@ class ApiClient(Closeable):
return proto return proto
def get_metadata_4_album(self, album: AlbumId) -> Metadata.Album: def get_metadata_4_album(self, album: AlbumId) -> Metadata.Album:
resp = self.send( resp = self.send("GET", "/metadata/4/album/{}".format(album.hex_id()),
"GET", "/metadata/4/album/{}".format(album.hex_id()), None, None None, None)
)
ApiClient.StatusCodeException.check_status(resp) ApiClient.StatusCodeException.check_status(resp)
body = resp.content body = resp.content
@@ -120,9 +110,9 @@ class ApiClient(Closeable):
return proto return proto
def get_metadata_4_artist(self, artist: ArtistId) -> Metadata.Artist: def get_metadata_4_artist(self, artist: ArtistId) -> Metadata.Artist:
resp = self.send( resp = self.send("GET",
"GET", "/metadata/4/artist/{}".format(artist.hex_id()), None, None "/metadata/4/artist/{}".format(artist.hex_id()), None,
) None)
ApiClient.StatusCodeException.check_status(resp) ApiClient.StatusCodeException.check_status(resp)
body = resp.content body = resp.content
@@ -133,7 +123,8 @@ class ApiClient(Closeable):
return proto return proto
def get_metadata_4_show(self, show: ShowId) -> Metadata.Show: def get_metadata_4_show(self, show: ShowId) -> Metadata.Show:
resp = self.send("GET", "/metadata/4/show/{}".format(show.hex_id()), None, None) resp = self.send("GET", "/metadata/4/show/{}".format(show.hex_id()),
None, None)
ApiClient.StatusCodeException.check_status(resp) ApiClient.StatusCodeException.check_status(resp)
body = resp.content body = resp.content

View File

@@ -12,9 +12,11 @@ class DealerClient(Closeable):
def connect(self): def connect(self):
pass pass
def add_message_listener(self, listener: DealerClient.MessageListener, *uris: str): def add_message_listener(self, listener: DealerClient.MessageListener,
*uris: str):
pass pass
class MessageListener: class MessageListener:
def on_message(self, uri: str, headers: typing.Dict[str, str], payload: bytes): def on_message(self, uri: str, headers: typing.Dict[str, str],
payload: bytes):
pass pass

View File

@@ -45,12 +45,10 @@ class MercuryClient(PacketsReceiver.PacketsReceiver, Closeable):
sub = Pubsub.Subscription() sub = Pubsub.Subscription()
sub.ParseFromString(payload) sub.ParseFromString(payload)
self._subscriptions.append( self._subscriptions.append(
MercuryClient.InternalSubListener(sub.uri, listener, True) MercuryClient.InternalSubListener(sub.uri, listener, True))
)
else: else:
self._subscriptions.append( self._subscriptions.append(
MercuryClient.InternalSubListener(uri, listener, True) MercuryClient.InternalSubListener(uri, listener, True))
)
self._LOGGER.debug("Subscribed successfully to {}!".format(uri)) self._LOGGER.debug("Subscribed successfully to {}!".format(uri))
@@ -73,10 +71,8 @@ class MercuryClient(PacketsReceiver.PacketsReceiver, Closeable):
resp = callback.wait_response() resp = callback.wait_response()
if resp is None: if resp is None:
raise IOError( raise IOError(
"Request timeout out, {} passed, yet no response. seq: {}".format( "Request timeout out, {} passed, yet no response. seq: {}".
self._MERCURY_REQUEST_TIMEOUT, seq format(self._MERCURY_REQUEST_TIMEOUT, seq))
)
)
return resp return resp
except queue.Empty as e: except queue.Empty as e:
raise IOError(e) raise IOError(e)
@@ -97,9 +93,7 @@ class MercuryClient(PacketsReceiver.PacketsReceiver, Closeable):
self._LOGGER.debug( self._LOGGER.debug(
"Send Mercury request, seq: {}, uri: {}, method: {}".format( "Send Mercury request, seq: {}, uri: {}, method: {}".format(
seq, request.header.uri, request.header.method seq, request.header.uri, request.header.method))
)
)
buffer.write_short(4) buffer.write_short(4)
buffer.write_int(seq) buffer.write_int(seq)
@@ -143,9 +137,7 @@ class MercuryClient(PacketsReceiver.PacketsReceiver, Closeable):
self._LOGGER.debug( self._LOGGER.debug(
"Handling packet, cmd: 0x{}, seq: {}, flags: {}, parts: {}".format( "Handling packet, cmd: 0x{}, seq: {}, flags: {}, parts: {}".format(
Utils.bytes_to_hex(packet.cmd), seq, flags, parts Utils.bytes_to_hex(packet.cmd), seq, flags, parts))
)
)
for i in range(parts): for i in range(parts):
size = payload.read_short() size = payload.read_short()
@@ -173,39 +165,30 @@ class MercuryClient(PacketsReceiver.PacketsReceiver, Closeable):
if not dispatched: if not dispatched:
self._LOGGER.debug( self._LOGGER.debug(
"Couldn't dispatch Mercury event seq: {}, uri: {}, code: {}, payload: {}".format( "Couldn't dispatch Mercury event seq: {}, uri: {}, code: {}, payload: {}"
seq, header.uri, header.status_code, resp.payload .format(seq, header.uri, header.status_code, resp.payload))
) elif (packet.is_cmd(Packet.Type.mercury_req)
)
elif (
packet.is_cmd(Packet.Type.mercury_req)
or packet.is_cmd(Packet.Type.mercury_sub) or packet.is_cmd(Packet.Type.mercury_sub)
or packet.is_cmd(Packet.Type.mercury_sub) or packet.is_cmd(Packet.Type.mercury_sub)):
):
callback = self._callbacks.get(seq) callback = self._callbacks.get(seq)
self._callbacks.pop(seq) self._callbacks.pop(seq)
if callback is not None: if callback is not None:
callback.response(resp) callback.response(resp)
else: else:
self._LOGGER.warning( self._LOGGER.warning(
"Skipped Mercury response, seq: {}, uri: {}, code: {}".format( "Skipped Mercury response, seq: {}, uri: {}, code: {}".
seq, resp.uri, resp.status_code format(seq, resp.uri, resp.status_code))
)
)
with self._removeCallbackLock: with self._removeCallbackLock:
self._removeCallbackLock.notify_all() self._removeCallbackLock.notify_all()
else: else:
self._LOGGER.warning( self._LOGGER.warning(
"Couldn't handle packet, seq: {}, uri: {}, code: {}".format( "Couldn't handle packet, seq: {}, uri: {}, code: {}".format(
seq, header.uri, header.status_code seq, header.uri, header.status_code))
)
)
def interested_in(self, uri: str, listener: SubListener) -> None: def interested_in(self, uri: str, listener: SubListener) -> None:
self._subscriptions.append( self._subscriptions.append(
MercuryClient.InternalSubListener(uri, listener, False) MercuryClient.InternalSubListener(uri, listener, False))
)
def not_interested_in(self, listener: SubListener) -> None: def not_interested_in(self, listener: SubListener) -> None:
try: try:
@@ -240,7 +223,8 @@ class MercuryClient(PacketsReceiver.PacketsReceiver, Closeable):
self._reference.task_done() self._reference.task_done()
def wait_response(self) -> typing.Any: def wait_response(self) -> typing.Any:
return self._reference.get(timeout=MercuryClient._MERCURY_REQUEST_TIMEOUT) return self._reference.get(
timeout=MercuryClient._MERCURY_REQUEST_TIMEOUT)
# class PubSubException(MercuryClient.MercuryException): # class PubSubException(MercuryClient.MercuryException):
# pass # pass
@@ -273,7 +257,8 @@ class MercuryClient(PacketsReceiver.PacketsReceiver, Closeable):
payload: typing.List[bytes] payload: typing.List[bytes]
status_code: int status_code: int
def __init__(self, header: Mercury.Header, payload: typing.List[bytes]): def __init__(self, header: Mercury.Header,
payload: typing.List[bytes]):
self.uri = header.uri self.uri = header.uri
self.status_code = header.status_code self.status_code = header.status_code
self.payload = payload[1:] self.payload = payload[1:]

View File

@@ -13,35 +13,28 @@ class RawMercuryRequest:
@staticmethod @staticmethod
def sub(uri: str): def sub(uri: str):
return RawMercuryRequest.new_builder().set_uri(uri).set_method("SUB").build() return RawMercuryRequest.new_builder().set_uri(uri).set_method(
"SUB").build()
@staticmethod @staticmethod
def unsub(uri: str): def unsub(uri: str):
return RawMercuryRequest.new_builder().set_uri(uri).set_method("UNSUB").build() return RawMercuryRequest.new_builder().set_uri(uri).set_method(
"UNSUB").build()
@staticmethod @staticmethod
def get(uri: str): def get(uri: str):
return RawMercuryRequest.new_builder().set_uri(uri).set_method("GET").build() return RawMercuryRequest.new_builder().set_uri(uri).set_method(
"GET").build()
@staticmethod @staticmethod
def send(uri: str, part: bytes): def send(uri: str, part: bytes):
return ( return (RawMercuryRequest.new_builder().set_uri(uri).add_payload_part(
RawMercuryRequest.new_builder() part).set_method("SEND").build())
.set_uri(uri)
.add_payload_part(part)
.set_method("SEND")
.build()
)
@staticmethod @staticmethod
def post(uri: str, part: bytes): def post(uri: str, part: bytes):
return ( return (RawMercuryRequest.new_builder().set_uri(uri).set_method(
RawMercuryRequest.new_builder() "POST").add_payload_part(part).build())
.set_uri(uri)
.set_method("POST")
.add_payload_part(part)
.build()
)
@staticmethod @staticmethod
def new_builder(): def new_builder():
@@ -67,9 +60,10 @@ class RawMercuryRequest:
self.header_dict["method"] = method self.header_dict["method"] = method
return self return self
def add_user_field( def add_user_field(self,
self, field: Mercury.UserField = None, key: str = None, value: str = None field: Mercury.UserField = None,
): key: str = None,
value: str = None):
if field is None and (key is None or value is None): if field is None and (key is None or value is None):
return self return self
try: try:
@@ -80,8 +74,7 @@ class RawMercuryRequest:
self.header_dict["user_fields"].append(field) self.header_dict["user_fields"].append(field)
if key is not None and value is not None: if key is not None and value is not None:
self.header_dict["user_fields"].append( self.header_dict["user_fields"].append(
Mercury.UserField(key=key, value=value.encode()) Mercury.UserField(key=key, value=value.encode()))
)
return self return self
def add_payload_part(self, part: bytes): def add_payload_part(self, part: bytes):
@@ -92,4 +85,5 @@ class RawMercuryRequest:
return self.add_payload_part(msg) return self.add_payload_part(msg)
def build(self): def build(self):
return RawMercuryRequest(Mercury.Header(**self.header_dict), self.payload) return RawMercuryRequest(Mercury.Header(**self.header_dict),
self.payload)

View File

@@ -49,11 +49,9 @@ class PlayableId:
@staticmethod @staticmethod
def is_supported(uri: str): def is_supported(uri: str):
return ( return (not uri.startswith("spotify:local:")
not uri.startswith("spotify:local:")
and not uri == "spotify:delimiter" and not uri == "spotify:delimiter"
and not uri == "spotify:meta:delimiter" and not uri == "spotify:meta:delimiter")
)
@staticmethod @staticmethod
def should_play(track: ContextTrack): def should_play(track: ContextTrack):
@@ -98,7 +96,8 @@ class AlbumId(SpotifyId):
matcher = AlbumId._PATTERN.search(uri) matcher = AlbumId._PATTERN.search(uri)
if matcher is not None: if matcher is not None:
album_id = matcher.group(1) album_id = matcher.group(1)
return AlbumId(Utils.bytes_to_hex(AlbumId._BASE62.decode(album_id, 16))) return AlbumId(
Utils.bytes_to_hex(AlbumId._BASE62.decode(album_id, 16)))
raise TypeError("Not a Spotify album ID: {}.f".format(uri)) raise TypeError("Not a Spotify album ID: {}.f".format(uri))
@staticmethod @staticmethod
@@ -111,8 +110,7 @@ class AlbumId(SpotifyId):
def to_mercury_uri(self) -> str: def to_mercury_uri(self) -> str:
return "spotify:album:{}".format( return "spotify:album:{}".format(
AlbumId._BASE62.encode(Utils.hex_to_bytes(self._hexId)) AlbumId._BASE62.encode(Utils.hex_to_bytes(self._hexId)))
)
def hex_id(self) -> str: def hex_id(self) -> str:
return self._hexId return self._hexId
@@ -131,12 +129,14 @@ class ArtistId(SpotifyId):
matcher = ArtistId._PATTERN.search(uri) matcher = ArtistId._PATTERN.search(uri)
if matcher is not None: if matcher is not None:
artist_id = matcher.group(1) artist_id = matcher.group(1)
return ArtistId(Utils.bytes_to_hex(ArtistId._BASE62.decode(artist_id, 16))) return ArtistId(
Utils.bytes_to_hex(ArtistId._BASE62.decode(artist_id, 16)))
raise TypeError("Not a Spotify artist ID: {}".format(uri)) raise TypeError("Not a Spotify artist ID: {}".format(uri))
@staticmethod @staticmethod
def from_base62(base62: str) -> ArtistId: def from_base62(base62: str) -> ArtistId:
return ArtistId(Utils.bytes_to_hex(ArtistId._BASE62.decode(base62, 16))) return ArtistId(Utils.bytes_to_hex(ArtistId._BASE62.decode(base62,
16)))
@staticmethod @staticmethod
def from_hex(hex_str: str) -> ArtistId: def from_hex(hex_str: str) -> ArtistId:
@@ -147,8 +147,7 @@ class ArtistId(SpotifyId):
def to_spotify_uri(self) -> str: def to_spotify_uri(self) -> str:
return "spotify:artist:{}".format( return "spotify:artist:{}".format(
ArtistId._BASE62.encode(Utils.hex_to_bytes(self._hexId)) ArtistId._BASE62.encode(Utils.hex_to_bytes(self._hexId)))
)
def hex_id(self) -> str: def hex_id(self) -> str:
return self._hexId return self._hexId
@@ -167,13 +166,14 @@ class EpisodeId(SpotifyId, PlayableId):
if matcher is not None: if matcher is not None:
episode_id = matcher.group(1) episode_id = matcher.group(1)
return EpisodeId( return EpisodeId(
Utils.Utils.bytes_to_hex(PlayableId.BASE62.decode(episode_id, 16)) Utils.Utils.bytes_to_hex(
) PlayableId.BASE62.decode(episode_id, 16)))
TypeError("Not a Spotify episode ID: {}".format(uri)) TypeError("Not a Spotify episode ID: {}".format(uri))
@staticmethod @staticmethod
def from_base62(base62: str) -> EpisodeId: def from_base62(base62: str) -> EpisodeId:
return EpisodeId(Utils.Utils.bytes_to_hex(PlayableId.BASE62.decode(base62, 16))) return EpisodeId(
Utils.Utils.bytes_to_hex(PlayableId.BASE62.decode(base62, 16)))
@staticmethod @staticmethod
def from_hex(hex_str: str) -> EpisodeId: def from_hex(hex_str: str) -> EpisodeId:
@@ -184,8 +184,7 @@ class EpisodeId(SpotifyId, PlayableId):
def to_spotify_uri(self) -> str: def to_spotify_uri(self) -> str:
return "Spotify:episode:{}".format( return "Spotify:episode:{}".format(
PlayableId.BASE62.encode(Utils.Utils.hex_to_bytes(self._hexId)) PlayableId.BASE62.encode(Utils.Utils.hex_to_bytes(self._hexId)))
)
def hex_id(self) -> str: def hex_id(self) -> str:
return self._hexId return self._hexId
@@ -207,7 +206,8 @@ class ShowId(SpotifyId):
matcher = ShowId._PATTERN.search(uri) matcher = ShowId._PATTERN.search(uri)
if matcher is not None: if matcher is not None:
show_id = matcher.group(1) show_id = matcher.group(1)
return ShowId(Utils.bytes_to_hex(ShowId._BASE62.decode(show_id, 16))) return ShowId(
Utils.bytes_to_hex(ShowId._BASE62.decode(show_id, 16)))
raise TypeError("Not a Spotify show ID: {}".format(uri)) raise TypeError("Not a Spotify show ID: {}".format(uri))
@staticmethod @staticmethod
@@ -223,8 +223,7 @@ class ShowId(SpotifyId):
def to_spotify_uri(self) -> str: def to_spotify_uri(self) -> str:
return "spotify:show:{}".format( return "spotify:show:{}".format(
ShowId._BASE62.encode(Utils.hex_to_bytes(self._hexId)) ShowId._BASE62.encode(Utils.hex_to_bytes(self._hexId)))
)
def hex_id(self) -> str: def hex_id(self) -> str:
return self._hexId return self._hexId
@@ -242,12 +241,14 @@ class TrackId(PlayableId, SpotifyId):
search = TrackId.PATTERN.search(uri) search = TrackId.PATTERN.search(uri)
if search is not None: if search is not None:
track_id = search.group(1) track_id = search.group(1)
return TrackId(Utils.bytes_to_hex(PlayableId.BASE62.decode(track_id, 16))) return TrackId(
Utils.bytes_to_hex(PlayableId.BASE62.decode(track_id, 16)))
raise RuntimeError("Not a Spotify track ID: {}".format(uri)) raise RuntimeError("Not a Spotify track ID: {}".format(uri))
@staticmethod @staticmethod
def from_base62(base62: str) -> TrackId: def from_base62(base62: str) -> TrackId:
return TrackId(Utils.bytes_to_hex(PlayableId.BASE62.decode(base62, 16))) return TrackId(Utils.bytes_to_hex(PlayableId.BASE62.decode(base62,
16)))
@staticmethod @staticmethod
def from_hex(hex_str: str) -> TrackId: def from_hex(hex_str: str) -> TrackId:

View File

@@ -38,7 +38,8 @@ class Player(Closeable, PlayerSession.Listener, AudioSink.Listener):
self.__init_state() self.__init_state()
def __init_state(self): def __init_state(self):
self._state = StateWrapper.StateWrapper(self._session, self, self._conf) self._state = StateWrapper.StateWrapper(self._session, self,
self._conf)
class Anonymous(DeviceStateHandler.Listener): class Anonymous(DeviceStateHandler.Listener):
_player: Player = None _player: Player = None
@@ -54,7 +55,8 @@ class Player(Closeable, PlayerSession.Listener, AudioSink.Listener):
endpoint: DeviceStateHandler.Endpoint, endpoint: DeviceStateHandler.Endpoint,
data: DeviceStateHandler.CommandBody, data: DeviceStateHandler.CommandBody,
) -> None: ) -> None:
self._player._LOGGER.debug("Received command: {}".format(endpoint)) self._player._LOGGER.debug(
"Received command: {}".format(endpoint))
self._deviceStateListener = Anonymous(self) self._deviceStateListener = Anonymous(self)
self._state.add_listener(self._deviceStateListener) self._state.add_listener(self._deviceStateListener)

View File

@@ -51,15 +51,18 @@ class PlayerConfiguration:
def __init__(self): def __init__(self):
pass pass
def set_preferred_quality(self, preferred_quality: AudioQuality) -> __class__: def set_preferred_quality(
self, preferred_quality: AudioQuality) -> __class__:
self.preferred_quality = preferred_quality self.preferred_quality = preferred_quality
return self return self
def set_enable_normalisation(self, enable_normalisation: bool) -> __class__: def set_enable_normalisation(self,
enable_normalisation: bool) -> __class__:
self.enable_normalisation = enable_normalisation self.enable_normalisation = enable_normalisation
return self return self
def set_normalisation_pregain(self, normalisation_pregain: float) -> __class__: def set_normalisation_pregain(
self, normalisation_pregain: float) -> __class__:
self.normalisation_pregain = normalisation_pregain self.normalisation_pregain = normalisation_pregain
return self return self

View File

@@ -20,7 +20,8 @@ class StateWrapper(DeviceStateHandler.Listener, DealerClient.MessageListener):
_player: Player = None _player: Player = None
_device: DeviceStateHandler = None _device: DeviceStateHandler = None
def __init__(self, session: Session, player: Player, conf: PlayerConfiguration): def __init__(self, session: Session, player: Player,
conf: PlayerConfiguration):
self._session = session self._session = session
self._player = player self._player = player
self._device = DeviceStateHandler(session, self, conf) self._device = DeviceStateHandler(session, self, conf)
@@ -39,9 +40,9 @@ class StateWrapper(DeviceStateHandler.Listener, DealerClient.MessageListener):
playback_speed=1.0, playback_speed=1.0,
suppressions=Suppressions(), suppressions=Suppressions(),
context_restrictions=Restrictions(), context_restrictions=Restrictions(),
options=ContextPlayerOptions( options=ContextPlayerOptions(repeating_context=False,
repeating_context=False, shuffling_context=False, repeating_track=False shuffling_context=False,
), repeating_track=False),
position_as_of_timestamp=0, position_as_of_timestamp=0,
position=0, position=0,
is_playing=False, is_playing=False,
@@ -51,7 +52,9 @@ class StateWrapper(DeviceStateHandler.Listener, DealerClient.MessageListener):
self._device.add_listener(listener) self._device.add_listener(listener)
def ready(self) -> None: def ready(self) -> None:
self._device.update_state(Connect.PutStateReason.NEW_DEVICE, 0, self._state) self._device.update_state(Connect.PutStateReason.NEW_DEVICE, 0,
self._state)
def on_message(self, uri: str, headers: typing.Dict[str, str], payload: bytes): def on_message(self, uri: str, headers: typing.Dict[str, str],
payload: bytes):
pass pass

View File

@@ -19,26 +19,26 @@ class VorbisOnlyAudioQuality(AudioQualityPicker):
@staticmethod @staticmethod
def get_vorbis_file(files: typing.List[Metadata.AudioFile]): def get_vorbis_file(files: typing.List[Metadata.AudioFile]):
for file in files: for file in files:
if ( if (hasattr(file, "format") and SuperAudioFormat.get(file.format)
hasattr(file, "format") == SuperAudioFormat.VORBIS):
and SuperAudioFormat.get(file.format) == SuperAudioFormat.VORBIS
):
return file return file
return None return None
def get_file(self, files: typing.List[Metadata.AudioFile]): def get_file(self, files: typing.List[Metadata.AudioFile]):
matches: typing.List[Metadata.AudioFile] = self.preferred.get_matches(files) matches: typing.List[Metadata.AudioFile] = self.preferred.get_matches(
vorbis: Metadata.AudioFile = VorbisOnlyAudioQuality.get_vorbis_file(matches) files)
vorbis: Metadata.AudioFile = VorbisOnlyAudioQuality.get_vorbis_file(
matches)
if vorbis is None: if vorbis is None:
vorbis: Metadata.AudioFile = VorbisOnlyAudioQuality.get_vorbis_file(files) vorbis: Metadata.AudioFile = VorbisOnlyAudioQuality.get_vorbis_file(
files)
if vorbis is not None: if vorbis is not None:
self._LOGGER.warning( self._LOGGER.warning(
"Using {} because preferred {} couldn't be found.".format( "Using {} because preferred {} couldn't be found.".format(
vorbis.format, self.preferred vorbis.format, self.preferred))
)
)
else: else:
self._LOGGER.fatal("Couldn't find any Vorbis file, available: {}") self._LOGGER.fatal(
"Couldn't find any Vorbis file, available: {}")
return vorbis return vorbis

View File

@@ -22,8 +22,7 @@ class DeviceStateHandler:
_listeners: typing.List[DeviceStateHandler.Listener] = [] _listeners: typing.List[DeviceStateHandler.Listener] = []
_putState: Connect.PutStateRequest = None _putState: Connect.PutStateRequest = None
_putStateWorker: concurrent.futures.ThreadPoolExecutor = ( _putStateWorker: concurrent.futures.ThreadPoolExecutor = (
concurrent.futures.ThreadPoolExecutor() concurrent.futures.ThreadPoolExecutor())
)
_connectionId: str = None _connectionId: str = None
def __init__(self, session: Session, player, conf: PlayerConfiguration): def __init__(self, session: Session, player, conf: PlayerConfiguration):
@@ -36,9 +35,8 @@ class DeviceStateHandler:
if self._connectionId is None or self._connectionId != newer: if self._connectionId is None or self._connectionId != newer:
self._connectionId = newer self._connectionId = newer
self._LOGGER.debug( self._LOGGER.debug("Updated Spotify-Connection-Id: {}".format(
"Updated Spotify-Connection-Id: {}".format(self._connectionId) self._connectionId))
)
self._notify_ready() self._notify_ready()
def add_listener(self, listener: DeviceStateHandler.Listener): def add_listener(self, listener: DeviceStateHandler.Listener):
@@ -71,13 +69,11 @@ class DeviceStateHandler:
def _put_connect_state(self, req: Connect.PutStateRequest): def _put_connect_state(self, req: Connect.PutStateRequest):
self._session.api().put_connect_state(self._connectionId, req) self._session.api().put_connect_state(self._connectionId, req)
self._LOGGER.info( self._LOGGER.info("Put state. ts: {}, connId: {}, reason: {}".format(
"Put state. ts: {}, connId: {}, reason: {}".format(
req.client_side_timestamp, req.client_side_timestamp,
Utils.truncate_middle(self._connectionId, 10), Utils.truncate_middle(self._connectionId, 10),
req.put_state_reason, req.put_state_reason,
) ))
)
class Endpoint(enum.Enum): class Endpoint(enum.Enum):
Play: str = "play" Play: str = "play"

View File

@@ -12,14 +12,14 @@ from google.protobuf import symbol_database as _symbol_database
_sym_db = _symbol_database.Default() _sym_db = _symbol_database.Default()
DESCRIPTOR = _descriptor.FileDescriptor( DESCRIPTOR = _descriptor.FileDescriptor(
name="canvaz.proto", name="canvaz.proto",
package="com.spotify.canvazcache", package="com.spotify.canvazcache",
syntax="proto3", syntax="proto3",
serialized_options=b"\n\022com.spotify.canvazH\002", serialized_options=b"\n\022com.spotify.canvazH\002",
create_key=_descriptor._internal_create_key, create_key=_descriptor._internal_create_key,
serialized_pb=b'\n\x0c\x63\x61nvaz.proto\x12\x17\x63om.spotify.canvazcache\x1a\x11\x63\x61nvaz-meta.proto"3\n\x06\x41rtist\x12\x0b\n\x03uri\x18\x01 \x01(\t\x12\x0c\n\x04name\x18\x02 \x01(\t\x12\x0e\n\x06\x61vatar\x18\x03 \x01(\t"\xe1\x02\n\x14\x45ntityCanvazResponse\x12\x46\n\x08\x63\x61nvases\x18\x01 \x03(\x0b\x32\x34.com.spotify.canvazcache.EntityCanvazResponse.Canvaz\x12\x16\n\x0ettl_in_seconds\x18\x02 \x01(\x03\x1a\xe8\x01\n\x06\x43\x61nvaz\x12\n\n\x02id\x18\x01 \x01(\t\x12\x0b\n\x03url\x18\x02 \x01(\t\x12\x0f\n\x07\x66ile_id\x18\x03 \x01(\t\x12&\n\x04type\x18\x04 \x01(\x0e\x32\x18.com.spotify.canvaz.Type\x12\x12\n\nentity_uri\x18\x05 \x01(\t\x12/\n\x06\x61rtist\x18\x06 \x01(\x0b\x32\x1f.com.spotify.canvazcache.Artist\x12\x10\n\x08\x65xplicit\x18\x07 \x01(\x08\x12\x13\n\x0buploaded_by\x18\x08 \x01(\t\x12\x0c\n\x04\x65tag\x18\t \x01(\t\x12\x12\n\ncanvas_uri\x18\x0b \x01(\t"\x88\x01\n\x13\x45ntityCanvazRequest\x12\x45\n\x08\x65ntities\x18\x01 \x03(\x0b\x32\x33.com.spotify.canvazcache.EntityCanvazRequest.Entity\x1a*\n\x06\x45ntity\x12\x12\n\nentity_uri\x18\x01 \x01(\t\x12\x0c\n\x04\x65tag\x18\x02 \x01(\tB\x16\n\x12\x63om.spotify.canvazH\x02\x62\x06proto3', serialized_pb=
b'\n\x0c\x63\x61nvaz.proto\x12\x17\x63om.spotify.canvazcache\x1a\x11\x63\x61nvaz-meta.proto"3\n\x06\x41rtist\x12\x0b\n\x03uri\x18\x01 \x01(\t\x12\x0c\n\x04name\x18\x02 \x01(\t\x12\x0e\n\x06\x61vatar\x18\x03 \x01(\t"\xe1\x02\n\x14\x45ntityCanvazResponse\x12\x46\n\x08\x63\x61nvases\x18\x01 \x03(\x0b\x32\x34.com.spotify.canvazcache.EntityCanvazResponse.Canvaz\x12\x16\n\x0ettl_in_seconds\x18\x02 \x01(\x03\x1a\xe8\x01\n\x06\x43\x61nvaz\x12\n\n\x02id\x18\x01 \x01(\t\x12\x0b\n\x03url\x18\x02 \x01(\t\x12\x0f\n\x07\x66ile_id\x18\x03 \x01(\t\x12&\n\x04type\x18\x04 \x01(\x0e\x32\x18.com.spotify.canvaz.Type\x12\x12\n\nentity_uri\x18\x05 \x01(\t\x12/\n\x06\x61rtist\x18\x06 \x01(\x0b\x32\x1f.com.spotify.canvazcache.Artist\x12\x10\n\x08\x65xplicit\x18\x07 \x01(\x08\x12\x13\n\x0buploaded_by\x18\x08 \x01(\t\x12\x0c\n\x04\x65tag\x18\t \x01(\t\x12\x12\n\ncanvas_uri\x18\x0b \x01(\t"\x88\x01\n\x13\x45ntityCanvazRequest\x12\x45\n\x08\x65ntities\x18\x01 \x03(\x0b\x32\x33.com.spotify.canvazcache.EntityCanvazRequest.Entity\x1a*\n\x06\x45ntity\x12\x12\n\nentity_uri\x18\x01 \x01(\t\x12\x0c\n\x04\x65tag\x18\x02 \x01(\tB\x16\n\x12\x63om.spotify.canvazH\x02\x62\x06proto3',
dependencies=[ dependencies=[
canvaz__meta__pb2.DESCRIPTOR, canvaz__meta__pb2.DESCRIPTOR,
], ],
@@ -151,7 +151,8 @@ _ENTITYCANVAZRESPONSE_CANVAZ = _descriptor.Descriptor(
), ),
_descriptor.FieldDescriptor( _descriptor.FieldDescriptor(
name="file_id", name="file_id",
full_name="com.spotify.canvazcache.EntityCanvazResponse.Canvaz.file_id", full_name=
"com.spotify.canvazcache.EntityCanvazResponse.Canvaz.file_id",
index=2, index=2,
number=3, number=3,
type=9, type=9,
@@ -170,7 +171,8 @@ _ENTITYCANVAZRESPONSE_CANVAZ = _descriptor.Descriptor(
), ),
_descriptor.FieldDescriptor( _descriptor.FieldDescriptor(
name="type", name="type",
full_name="com.spotify.canvazcache.EntityCanvazResponse.Canvaz.type", full_name=
"com.spotify.canvazcache.EntityCanvazResponse.Canvaz.type",
index=3, index=3,
number=4, number=4,
type=14, type=14,
@@ -189,7 +191,8 @@ _ENTITYCANVAZRESPONSE_CANVAZ = _descriptor.Descriptor(
), ),
_descriptor.FieldDescriptor( _descriptor.FieldDescriptor(
name="entity_uri", name="entity_uri",
full_name="com.spotify.canvazcache.EntityCanvazResponse.Canvaz.entity_uri", full_name=
"com.spotify.canvazcache.EntityCanvazResponse.Canvaz.entity_uri",
index=4, index=4,
number=5, number=5,
type=9, type=9,
@@ -208,7 +211,8 @@ _ENTITYCANVAZRESPONSE_CANVAZ = _descriptor.Descriptor(
), ),
_descriptor.FieldDescriptor( _descriptor.FieldDescriptor(
name="artist", name="artist",
full_name="com.spotify.canvazcache.EntityCanvazResponse.Canvaz.artist", full_name=
"com.spotify.canvazcache.EntityCanvazResponse.Canvaz.artist",
index=5, index=5,
number=6, number=6,
type=11, type=11,
@@ -227,7 +231,8 @@ _ENTITYCANVAZRESPONSE_CANVAZ = _descriptor.Descriptor(
), ),
_descriptor.FieldDescriptor( _descriptor.FieldDescriptor(
name="explicit", name="explicit",
full_name="com.spotify.canvazcache.EntityCanvazResponse.Canvaz.explicit", full_name=
"com.spotify.canvazcache.EntityCanvazResponse.Canvaz.explicit",
index=6, index=6,
number=7, number=7,
type=8, type=8,
@@ -246,7 +251,8 @@ _ENTITYCANVAZRESPONSE_CANVAZ = _descriptor.Descriptor(
), ),
_descriptor.FieldDescriptor( _descriptor.FieldDescriptor(
name="uploaded_by", name="uploaded_by",
full_name="com.spotify.canvazcache.EntityCanvazResponse.Canvaz.uploaded_by", full_name=
"com.spotify.canvazcache.EntityCanvazResponse.Canvaz.uploaded_by",
index=7, index=7,
number=8, number=8,
type=9, type=9,
@@ -265,7 +271,8 @@ _ENTITYCANVAZRESPONSE_CANVAZ = _descriptor.Descriptor(
), ),
_descriptor.FieldDescriptor( _descriptor.FieldDescriptor(
name="etag", name="etag",
full_name="com.spotify.canvazcache.EntityCanvazResponse.Canvaz.etag", full_name=
"com.spotify.canvazcache.EntityCanvazResponse.Canvaz.etag",
index=8, index=8,
number=9, number=9,
type=9, type=9,
@@ -284,7 +291,8 @@ _ENTITYCANVAZRESPONSE_CANVAZ = _descriptor.Descriptor(
), ),
_descriptor.FieldDescriptor( _descriptor.FieldDescriptor(
name="canvas_uri", name="canvas_uri",
full_name="com.spotify.canvazcache.EntityCanvazResponse.Canvaz.canvas_uri", full_name=
"com.spotify.canvazcache.EntityCanvazResponse.Canvaz.canvas_uri",
index=9, index=9,
number=11, number=11,
type=9, type=9,
@@ -343,7 +351,8 @@ _ENTITYCANVAZRESPONSE = _descriptor.Descriptor(
), ),
_descriptor.FieldDescriptor( _descriptor.FieldDescriptor(
name="ttl_in_seconds", name="ttl_in_seconds",
full_name="com.spotify.canvazcache.EntityCanvazResponse.ttl_in_seconds", full_name=
"com.spotify.canvazcache.EntityCanvazResponse.ttl_in_seconds",
index=1, index=1,
number=2, number=2,
type=3, type=3,
@@ -385,7 +394,8 @@ _ENTITYCANVAZREQUEST_ENTITY = _descriptor.Descriptor(
fields=[ fields=[
_descriptor.FieldDescriptor( _descriptor.FieldDescriptor(
name="entity_uri", name="entity_uri",
full_name="com.spotify.canvazcache.EntityCanvazRequest.Entity.entity_uri", full_name=
"com.spotify.canvazcache.EntityCanvazRequest.Entity.entity_uri",
index=0, index=0,
number=1, number=1,
type=9, type=9,
@@ -476,18 +486,18 @@ _ENTITYCANVAZREQUEST = _descriptor.Descriptor(
serialized_end=606, serialized_end=606,
) )
_ENTITYCANVAZRESPONSE_CANVAZ.fields_by_name["type"].enum_type = canvaz__meta__pb2._TYPE _ENTITYCANVAZRESPONSE_CANVAZ.fields_by_name[
"type"].enum_type = canvaz__meta__pb2._TYPE
_ENTITYCANVAZRESPONSE_CANVAZ.fields_by_name["artist"].message_type = _ARTIST _ENTITYCANVAZRESPONSE_CANVAZ.fields_by_name["artist"].message_type = _ARTIST
_ENTITYCANVAZRESPONSE_CANVAZ.containing_type = _ENTITYCANVAZRESPONSE _ENTITYCANVAZRESPONSE_CANVAZ.containing_type = _ENTITYCANVAZRESPONSE
_ENTITYCANVAZRESPONSE.fields_by_name[ _ENTITYCANVAZRESPONSE.fields_by_name[
"canvases" "canvases"].message_type = _ENTITYCANVAZRESPONSE_CANVAZ
].message_type = _ENTITYCANVAZRESPONSE_CANVAZ
_ENTITYCANVAZREQUEST_ENTITY.containing_type = _ENTITYCANVAZREQUEST _ENTITYCANVAZREQUEST_ENTITY.containing_type = _ENTITYCANVAZREQUEST
_ENTITYCANVAZREQUEST.fields_by_name[ _ENTITYCANVAZREQUEST.fields_by_name[
"entities" "entities"].message_type = _ENTITYCANVAZREQUEST_ENTITY
].message_type = _ENTITYCANVAZREQUEST_ENTITY
DESCRIPTOR.message_types_by_name["Artist"] = _ARTIST DESCRIPTOR.message_types_by_name["Artist"] = _ARTIST
DESCRIPTOR.message_types_by_name["EntityCanvazResponse"] = _ENTITYCANVAZRESPONSE DESCRIPTOR.message_types_by_name[
"EntityCanvazResponse"] = _ENTITYCANVAZRESPONSE
DESCRIPTOR.message_types_by_name["EntityCanvazRequest"] = _ENTITYCANVAZREQUEST DESCRIPTOR.message_types_by_name["EntityCanvazRequest"] = _ENTITYCANVAZREQUEST
_sym_db.RegisterFileDescriptor(DESCRIPTOR) _sym_db.RegisterFileDescriptor(DESCRIPTOR)
@@ -506,7 +516,8 @@ EntityCanvazResponse = _reflection.GeneratedProtocolMessageType(
"EntityCanvazResponse", "EntityCanvazResponse",
(_message.Message, ), (_message.Message, ),
{ {
"Canvaz": _reflection.GeneratedProtocolMessageType( "Canvaz":
_reflection.GeneratedProtocolMessageType(
"Canvaz", "Canvaz",
(_message.Message, ), (_message.Message, ),
{ {
@@ -515,8 +526,10 @@ EntityCanvazResponse = _reflection.GeneratedProtocolMessageType(
# @@protoc_insertion_point(class_scope:com.spotify.canvazcache.EntityCanvazResponse.Canvaz) # @@protoc_insertion_point(class_scope:com.spotify.canvazcache.EntityCanvazResponse.Canvaz)
}, },
), ),
"DESCRIPTOR": _ENTITYCANVAZRESPONSE, "DESCRIPTOR":
"__module__": "canvaz_pb2" _ENTITYCANVAZRESPONSE,
"__module__":
"canvaz_pb2"
# @@protoc_insertion_point(class_scope:com.spotify.canvazcache.EntityCanvazResponse) # @@protoc_insertion_point(class_scope:com.spotify.canvazcache.EntityCanvazResponse)
}, },
) )
@@ -527,7 +540,8 @@ EntityCanvazRequest = _reflection.GeneratedProtocolMessageType(
"EntityCanvazRequest", "EntityCanvazRequest",
(_message.Message, ), (_message.Message, ),
{ {
"Entity": _reflection.GeneratedProtocolMessageType( "Entity":
_reflection.GeneratedProtocolMessageType(
"Entity", "Entity",
(_message.Message, ), (_message.Message, ),
{ {
@@ -536,8 +550,10 @@ EntityCanvazRequest = _reflection.GeneratedProtocolMessageType(
# @@protoc_insertion_point(class_scope:com.spotify.canvazcache.EntityCanvazRequest.Entity) # @@protoc_insertion_point(class_scope:com.spotify.canvazcache.EntityCanvazRequest.Entity)
}, },
), ),
"DESCRIPTOR": _ENTITYCANVAZREQUEST, "DESCRIPTOR":
"__module__": "canvaz_pb2" _ENTITYCANVAZREQUEST,
"__module__":
"canvaz_pb2"
# @@protoc_insertion_point(class_scope:com.spotify.canvazcache.EntityCanvazRequest) # @@protoc_insertion_point(class_scope:com.spotify.canvazcache.EntityCanvazRequest)
}, },
) )

View File

@@ -18,7 +18,8 @@ DESCRIPTOR = _descriptor.FileDescriptor(
syntax="proto3", syntax="proto3",
serialized_options=b"\n\022com.spotify.canvazH\002", serialized_options=b"\n\022com.spotify.canvazH\002",
create_key=_descriptor._internal_create_key, create_key=_descriptor._internal_create_key,
serialized_pb=b"\n\x11\x63\x61nvaz-meta.proto\x12\x12\x63om.spotify.canvaz*R\n\x04Type\x12\t\n\x05IMAGE\x10\x00\x12\t\n\x05VIDEO\x10\x01\x12\x11\n\rVIDEO_LOOPING\x10\x02\x12\x18\n\x14VIDEO_LOOPING_RANDOM\x10\x03\x12\x07\n\x03GIF\x10\x04\x42\x16\n\x12\x63om.spotify.canvazH\x02\x62\x06proto3", serialized_pb=
b"\n\x11\x63\x61nvaz-meta.proto\x12\x12\x63om.spotify.canvaz*R\n\x04Type\x12\t\n\x05IMAGE\x10\x00\x12\t\n\x05VIDEO\x10\x01\x12\x11\n\rVIDEO_LOOPING\x10\x02\x12\x18\n\x14VIDEO_LOOPING_RANDOM\x10\x03\x12\x07\n\x03GIF\x10\x04\x42\x16\n\x12\x63om.spotify.canvazH\x02\x62\x06proto3",
) )
_TYPE = _descriptor.EnumDescriptor( _TYPE = _descriptor.EnumDescriptor(

View File

@@ -13,14 +13,14 @@ from google.protobuf import symbol_database as _symbol_database
_sym_db = _symbol_database.Default() _sym_db = _symbol_database.Default()
DESCRIPTOR = _descriptor.FileDescriptor( DESCRIPTOR = _descriptor.FileDescriptor(
name="context.proto", name="context.proto",
package="spotify.player.proto", package="spotify.player.proto",
syntax="proto2", syntax="proto2",
serialized_options=b"\n\023com.spotify.contextH\002", serialized_options=b"\n\023com.spotify.contextH\002",
create_key=_descriptor._internal_create_key, create_key=_descriptor._internal_create_key,
serialized_pb=b'\n\rcontext.proto\x12\x14spotify.player.proto\x1a\x12\x63ontext_page.proto\x1a\x12restrictions.proto"\x90\x02\n\x07\x43ontext\x12\x0b\n\x03uri\x18\x01 \x01(\t\x12\x0b\n\x03url\x18\x02 \x01(\t\x12=\n\x08metadata\x18\x03 \x03(\x0b\x32+.spotify.player.proto.Context.MetadataEntry\x12\x38\n\x0crestrictions\x18\x04 \x01(\x0b\x32".spotify.player.proto.Restrictions\x12\x30\n\x05pages\x18\x05 \x03(\x0b\x32!.spotify.player.proto.ContextPage\x12\x0f\n\x07loading\x18\x06 \x01(\x08\x1a/\n\rMetadataEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x42\x17\n\x13\x63om.spotify.contextH\x02', serialized_pb=
b'\n\rcontext.proto\x12\x14spotify.player.proto\x1a\x12\x63ontext_page.proto\x1a\x12restrictions.proto"\x90\x02\n\x07\x43ontext\x12\x0b\n\x03uri\x18\x01 \x01(\t\x12\x0b\n\x03url\x18\x02 \x01(\t\x12=\n\x08metadata\x18\x03 \x03(\x0b\x32+.spotify.player.proto.Context.MetadataEntry\x12\x38\n\x0crestrictions\x18\x04 \x01(\x0b\x32".spotify.player.proto.Restrictions\x12\x30\n\x05pages\x18\x05 \x03(\x0b\x32!.spotify.player.proto.ContextPage\x12\x0f\n\x07loading\x18\x06 \x01(\x08\x1a/\n\rMetadataEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x42\x17\n\x13\x63om.spotify.contextH\x02',
dependencies=[ dependencies=[
context__page__pb2.DESCRIPTOR, context__page__pb2.DESCRIPTOR,
restrictions__pb2.DESCRIPTOR, restrictions__pb2.DESCRIPTOR,
@@ -225,7 +225,8 @@ _CONTEXT = _descriptor.Descriptor(
_CONTEXT_METADATAENTRY.containing_type = _CONTEXT _CONTEXT_METADATAENTRY.containing_type = _CONTEXT
_CONTEXT.fields_by_name["metadata"].message_type = _CONTEXT_METADATAENTRY _CONTEXT.fields_by_name["metadata"].message_type = _CONTEXT_METADATAENTRY
_CONTEXT.fields_by_name["restrictions"].message_type = restrictions__pb2._RESTRICTIONS _CONTEXT.fields_by_name[
"restrictions"].message_type = restrictions__pb2._RESTRICTIONS
_CONTEXT.fields_by_name["pages"].message_type = context__page__pb2._CONTEXTPAGE _CONTEXT.fields_by_name["pages"].message_type = context__page__pb2._CONTEXTPAGE
DESCRIPTOR.message_types_by_name["Context"] = _CONTEXT DESCRIPTOR.message_types_by_name["Context"] = _CONTEXT
_sym_db.RegisterFileDescriptor(DESCRIPTOR) _sym_db.RegisterFileDescriptor(DESCRIPTOR)
@@ -234,7 +235,8 @@ Context = _reflection.GeneratedProtocolMessageType(
"Context", "Context",
(_message.Message, ), (_message.Message, ),
{ {
"MetadataEntry": _reflection.GeneratedProtocolMessageType( "MetadataEntry":
_reflection.GeneratedProtocolMessageType(
"MetadataEntry", "MetadataEntry",
(_message.Message, ), (_message.Message, ),
{ {
@@ -243,8 +245,10 @@ Context = _reflection.GeneratedProtocolMessageType(
# @@protoc_insertion_point(class_scope:spotify.player.proto.Context.MetadataEntry) # @@protoc_insertion_point(class_scope:spotify.player.proto.Context.MetadataEntry)
}, },
), ),
"DESCRIPTOR": _CONTEXT, "DESCRIPTOR":
"__module__": "context_pb2" _CONTEXT,
"__module__":
"context_pb2"
# @@protoc_insertion_point(class_scope:spotify.player.proto.Context) # @@protoc_insertion_point(class_scope:spotify.player.proto.Context)
}, },
) )

View File

@@ -12,14 +12,14 @@ from google.protobuf import symbol_database as _symbol_database
_sym_db = _symbol_database.Default() _sym_db = _symbol_database.Default()
DESCRIPTOR = _descriptor.FileDescriptor( DESCRIPTOR = _descriptor.FileDescriptor(
name="context_page.proto", name="context_page.proto",
package="spotify.player.proto", package="spotify.player.proto",
syntax="proto2", syntax="proto2",
serialized_options=b"\n\023com.spotify.contextH\002", serialized_options=b"\n\023com.spotify.contextH\002",
create_key=_descriptor._internal_create_key, create_key=_descriptor._internal_create_key,
serialized_pb=b'\n\x12\x63ontext_page.proto\x12\x14spotify.player.proto\x1a\x13\x63ontext_track.proto"\xef\x01\n\x0b\x43ontextPage\x12\x10\n\x08page_url\x18\x01 \x01(\t\x12\x15\n\rnext_page_url\x18\x02 \x01(\t\x12\x41\n\x08metadata\x18\x03 \x03(\x0b\x32/.spotify.player.proto.ContextPage.MetadataEntry\x12\x32\n\x06tracks\x18\x04 \x03(\x0b\x32".spotify.player.proto.ContextTrack\x12\x0f\n\x07loading\x18\x05 \x01(\x08\x1a/\n\rMetadataEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x42\x17\n\x13\x63om.spotify.contextH\x02', serialized_pb=
b'\n\x12\x63ontext_page.proto\x12\x14spotify.player.proto\x1a\x13\x63ontext_track.proto"\xef\x01\n\x0b\x43ontextPage\x12\x10\n\x08page_url\x18\x01 \x01(\t\x12\x15\n\rnext_page_url\x18\x02 \x01(\t\x12\x41\n\x08metadata\x18\x03 \x03(\x0b\x32/.spotify.player.proto.ContextPage.MetadataEntry\x12\x32\n\x06tracks\x18\x04 \x03(\x0b\x32".spotify.player.proto.ContextTrack\x12\x0f\n\x07loading\x18\x05 \x01(\x08\x1a/\n\rMetadataEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x42\x17\n\x13\x63om.spotify.contextH\x02',
dependencies=[ dependencies=[
context__track__pb2.DESCRIPTOR, context__track__pb2.DESCRIPTOR,
], ],
@@ -203,8 +203,10 @@ _CONTEXTPAGE = _descriptor.Descriptor(
) )
_CONTEXTPAGE_METADATAENTRY.containing_type = _CONTEXTPAGE _CONTEXTPAGE_METADATAENTRY.containing_type = _CONTEXTPAGE
_CONTEXTPAGE.fields_by_name["metadata"].message_type = _CONTEXTPAGE_METADATAENTRY _CONTEXTPAGE.fields_by_name[
_CONTEXTPAGE.fields_by_name["tracks"].message_type = context__track__pb2._CONTEXTTRACK "metadata"].message_type = _CONTEXTPAGE_METADATAENTRY
_CONTEXTPAGE.fields_by_name[
"tracks"].message_type = context__track__pb2._CONTEXTTRACK
DESCRIPTOR.message_types_by_name["ContextPage"] = _CONTEXTPAGE DESCRIPTOR.message_types_by_name["ContextPage"] = _CONTEXTPAGE
_sym_db.RegisterFileDescriptor(DESCRIPTOR) _sym_db.RegisterFileDescriptor(DESCRIPTOR)
@@ -212,7 +214,8 @@ ContextPage = _reflection.GeneratedProtocolMessageType(
"ContextPage", "ContextPage",
(_message.Message, ), (_message.Message, ),
{ {
"MetadataEntry": _reflection.GeneratedProtocolMessageType( "MetadataEntry":
_reflection.GeneratedProtocolMessageType(
"MetadataEntry", "MetadataEntry",
(_message.Message, ), (_message.Message, ),
{ {
@@ -221,8 +224,10 @@ ContextPage = _reflection.GeneratedProtocolMessageType(
# @@protoc_insertion_point(class_scope:spotify.player.proto.ContextPage.MetadataEntry) # @@protoc_insertion_point(class_scope:spotify.player.proto.ContextPage.MetadataEntry)
}, },
), ),
"DESCRIPTOR": _CONTEXTPAGE, "DESCRIPTOR":
"__module__": "context_page_pb2" _CONTEXTPAGE,
"__module__":
"context_page_pb2"
# @@protoc_insertion_point(class_scope:spotify.player.proto.ContextPage) # @@protoc_insertion_point(class_scope:spotify.player.proto.ContextPage)
}, },
) )

View File

@@ -17,7 +17,8 @@ DESCRIPTOR = _descriptor.FileDescriptor(
syntax="proto2", syntax="proto2",
serialized_options=b"\n\023com.spotify.contextH\002", serialized_options=b"\n\023com.spotify.contextH\002",
create_key=_descriptor._internal_create_key, create_key=_descriptor._internal_create_key,
serialized_pb=b'\n\x1c\x63ontext_player_options.proto\x12\x14spotify.player.proto"e\n\x14\x43ontextPlayerOptions\x12\x19\n\x11shuffling_context\x18\x01 \x01(\x08\x12\x19\n\x11repeating_context\x18\x02 \x01(\x08\x12\x17\n\x0frepeating_track\x18\x03 \x01(\x08"m\n\x1c\x43ontextPlayerOptionOverrides\x12\x19\n\x11shuffling_context\x18\x01 \x01(\x08\x12\x19\n\x11repeating_context\x18\x02 \x01(\x08\x12\x17\n\x0frepeating_track\x18\x03 \x01(\x08\x42\x17\n\x13\x63om.spotify.contextH\x02', serialized_pb=
b'\n\x1c\x63ontext_player_options.proto\x12\x14spotify.player.proto"e\n\x14\x43ontextPlayerOptions\x12\x19\n\x11shuffling_context\x18\x01 \x01(\x08\x12\x19\n\x11repeating_context\x18\x02 \x01(\x08\x12\x17\n\x0frepeating_track\x18\x03 \x01(\x08"m\n\x1c\x43ontextPlayerOptionOverrides\x12\x19\n\x11shuffling_context\x18\x01 \x01(\x08\x12\x19\n\x11repeating_context\x18\x02 \x01(\x08\x12\x17\n\x0frepeating_track\x18\x03 \x01(\x08\x42\x17\n\x13\x63om.spotify.contextH\x02',
) )
_CONTEXTPLAYEROPTIONS = _descriptor.Descriptor( _CONTEXTPLAYEROPTIONS = _descriptor.Descriptor(
@@ -30,7 +31,8 @@ _CONTEXTPLAYEROPTIONS = _descriptor.Descriptor(
fields=[ fields=[
_descriptor.FieldDescriptor( _descriptor.FieldDescriptor(
name="shuffling_context", name="shuffling_context",
full_name="spotify.player.proto.ContextPlayerOptions.shuffling_context", full_name=
"spotify.player.proto.ContextPlayerOptions.shuffling_context",
index=0, index=0,
number=1, number=1,
type=8, type=8,
@@ -49,7 +51,8 @@ _CONTEXTPLAYEROPTIONS = _descriptor.Descriptor(
), ),
_descriptor.FieldDescriptor( _descriptor.FieldDescriptor(
name="repeating_context", name="repeating_context",
full_name="spotify.player.proto.ContextPlayerOptions.repeating_context", full_name=
"spotify.player.proto.ContextPlayerOptions.repeating_context",
index=1, index=1,
number=2, number=2,
type=8, type=8,
@@ -68,7 +71,8 @@ _CONTEXTPLAYEROPTIONS = _descriptor.Descriptor(
), ),
_descriptor.FieldDescriptor( _descriptor.FieldDescriptor(
name="repeating_track", name="repeating_track",
full_name="spotify.player.proto.ContextPlayerOptions.repeating_track", full_name=
"spotify.player.proto.ContextPlayerOptions.repeating_track",
index=2, index=2,
number=3, number=3,
type=8, type=8,
@@ -108,7 +112,8 @@ _CONTEXTPLAYEROPTIONOVERRIDES = _descriptor.Descriptor(
fields=[ fields=[
_descriptor.FieldDescriptor( _descriptor.FieldDescriptor(
name="shuffling_context", name="shuffling_context",
full_name="spotify.player.proto.ContextPlayerOptionOverrides.shuffling_context", full_name=
"spotify.player.proto.ContextPlayerOptionOverrides.shuffling_context",
index=0, index=0,
number=1, number=1,
type=8, type=8,
@@ -127,7 +132,8 @@ _CONTEXTPLAYEROPTIONOVERRIDES = _descriptor.Descriptor(
), ),
_descriptor.FieldDescriptor( _descriptor.FieldDescriptor(
name="repeating_context", name="repeating_context",
full_name="spotify.player.proto.ContextPlayerOptionOverrides.repeating_context", full_name=
"spotify.player.proto.ContextPlayerOptionOverrides.repeating_context",
index=1, index=1,
number=2, number=2,
type=8, type=8,
@@ -146,7 +152,8 @@ _CONTEXTPLAYEROPTIONOVERRIDES = _descriptor.Descriptor(
), ),
_descriptor.FieldDescriptor( _descriptor.FieldDescriptor(
name="repeating_track", name="repeating_track",
full_name="spotify.player.proto.ContextPlayerOptionOverrides.repeating_track", full_name=
"spotify.player.proto.ContextPlayerOptionOverrides.repeating_track",
index=2, index=2,
number=3, number=3,
type=8, type=8,
@@ -176,10 +183,10 @@ _CONTEXTPLAYEROPTIONOVERRIDES = _descriptor.Descriptor(
serialized_end=266, serialized_end=266,
) )
DESCRIPTOR.message_types_by_name["ContextPlayerOptions"] = _CONTEXTPLAYEROPTIONS
DESCRIPTOR.message_types_by_name[ DESCRIPTOR.message_types_by_name[
"ContextPlayerOptionOverrides" "ContextPlayerOptions"] = _CONTEXTPLAYEROPTIONS
] = _CONTEXTPLAYEROPTIONOVERRIDES DESCRIPTOR.message_types_by_name[
"ContextPlayerOptionOverrides"] = _CONTEXTPLAYEROPTIONOVERRIDES
_sym_db.RegisterFileDescriptor(DESCRIPTOR) _sym_db.RegisterFileDescriptor(DESCRIPTOR)
ContextPlayerOptions = _reflection.GeneratedProtocolMessageType( ContextPlayerOptions = _reflection.GeneratedProtocolMessageType(

View File

@@ -17,7 +17,8 @@ DESCRIPTOR = _descriptor.FileDescriptor(
syntax="proto2", syntax="proto2",
serialized_options=b"\n\023com.spotify.contextH\002", serialized_options=b"\n\023com.spotify.contextH\002",
create_key=_descriptor._internal_create_key, create_key=_descriptor._internal_create_key,
serialized_pb=b'\n\x13\x63ontext_track.proto\x12\x14spotify.player.proto"\xaa\x01\n\x0c\x43ontextTrack\x12\x0b\n\x03uri\x18\x01 \x01(\t\x12\x0b\n\x03uid\x18\x02 \x01(\t\x12\x0b\n\x03gid\x18\x03 \x01(\x0c\x12\x42\n\x08metadata\x18\x04 \x03(\x0b\x32\x30.spotify.player.proto.ContextTrack.MetadataEntry\x1a/\n\rMetadataEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x42\x17\n\x13\x63om.spotify.contextH\x02', serialized_pb=
b'\n\x13\x63ontext_track.proto\x12\x14spotify.player.proto"\xaa\x01\n\x0c\x43ontextTrack\x12\x0b\n\x03uri\x18\x01 \x01(\t\x12\x0b\n\x03uid\x18\x02 \x01(\t\x12\x0b\n\x03gid\x18\x03 \x01(\x0c\x12\x42\n\x08metadata\x18\x04 \x03(\x0b\x32\x30.spotify.player.proto.ContextTrack.MetadataEntry\x1a/\n\rMetadataEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x42\x17\n\x13\x63om.spotify.contextH\x02',
) )
_CONTEXTTRACK_METADATAENTRY = _descriptor.Descriptor( _CONTEXTTRACK_METADATAENTRY = _descriptor.Descriptor(
@@ -179,7 +180,8 @@ _CONTEXTTRACK = _descriptor.Descriptor(
) )
_CONTEXTTRACK_METADATAENTRY.containing_type = _CONTEXTTRACK _CONTEXTTRACK_METADATAENTRY.containing_type = _CONTEXTTRACK
_CONTEXTTRACK.fields_by_name["metadata"].message_type = _CONTEXTTRACK_METADATAENTRY _CONTEXTTRACK.fields_by_name[
"metadata"].message_type = _CONTEXTTRACK_METADATAENTRY
DESCRIPTOR.message_types_by_name["ContextTrack"] = _CONTEXTTRACK DESCRIPTOR.message_types_by_name["ContextTrack"] = _CONTEXTTRACK
_sym_db.RegisterFileDescriptor(DESCRIPTOR) _sym_db.RegisterFileDescriptor(DESCRIPTOR)
@@ -187,7 +189,8 @@ ContextTrack = _reflection.GeneratedProtocolMessageType(
"ContextTrack", "ContextTrack",
(_message.Message, ), (_message.Message, ),
{ {
"MetadataEntry": _reflection.GeneratedProtocolMessageType( "MetadataEntry":
_reflection.GeneratedProtocolMessageType(
"MetadataEntry", "MetadataEntry",
(_message.Message, ), (_message.Message, ),
{ {
@@ -196,8 +199,10 @@ ContextTrack = _reflection.GeneratedProtocolMessageType(
# @@protoc_insertion_point(class_scope:spotify.player.proto.ContextTrack.MetadataEntry) # @@protoc_insertion_point(class_scope:spotify.player.proto.ContextTrack.MetadataEntry)
}, },
), ),
"DESCRIPTOR": _CONTEXTTRACK, "DESCRIPTOR":
"__module__": "context_track_pb2" _CONTEXTTRACK,
"__module__":
"context_track_pb2"
# @@protoc_insertion_point(class_scope:spotify.player.proto.ContextTrack) # @@protoc_insertion_point(class_scope:spotify.player.proto.ContextTrack)
}, },
) )

View File

@@ -17,7 +17,8 @@ DESCRIPTOR = _descriptor.FileDescriptor(
syntax="proto2", syntax="proto2",
serialized_options=b"\n\023com.spotify.contextH\002", serialized_options=b"\n\023com.spotify.contextH\002",
create_key=_descriptor._internal_create_key, create_key=_descriptor._internal_create_key,
serialized_pb=b'\n\x11play_origin.proto\x12\x14spotify.player.proto"\xbf\x01\n\nPlayOrigin\x12\x1a\n\x12\x66\x65\x61ture_identifier\x18\x01 \x01(\t\x12\x17\n\x0f\x66\x65\x61ture_version\x18\x02 \x01(\t\x12\x10\n\x08view_uri\x18\x03 \x01(\t\x12\x19\n\x11\x65xternal_referrer\x18\x04 \x01(\t\x12\x1b\n\x13referrer_identifier\x18\x05 \x01(\t\x12\x19\n\x11\x64\x65vice_identifier\x18\x06 \x01(\t\x12\x17\n\x0f\x66\x65\x61ture_classes\x18\x07 \x03(\tB\x17\n\x13\x63om.spotify.contextH\x02', serialized_pb=
b'\n\x11play_origin.proto\x12\x14spotify.player.proto"\xbf\x01\n\nPlayOrigin\x12\x1a\n\x12\x66\x65\x61ture_identifier\x18\x01 \x01(\t\x12\x17\n\x0f\x66\x65\x61ture_version\x18\x02 \x01(\t\x12\x10\n\x08view_uri\x18\x03 \x01(\t\x12\x19\n\x11\x65xternal_referrer\x18\x04 \x01(\t\x12\x1b\n\x13referrer_identifier\x18\x05 \x01(\t\x12\x19\n\x11\x64\x65vice_identifier\x18\x06 \x01(\t\x12\x17\n\x0f\x66\x65\x61ture_classes\x18\x07 \x03(\tB\x17\n\x13\x63om.spotify.contextH\x02',
) )
_PLAYORIGIN = _descriptor.Descriptor( _PLAYORIGIN = _descriptor.Descriptor(

View File

@@ -12,14 +12,14 @@ from google.protobuf import symbol_database as _symbol_database
_sym_db = _symbol_database.Default() _sym_db = _symbol_database.Default()
DESCRIPTOR = _descriptor.FileDescriptor( DESCRIPTOR = _descriptor.FileDescriptor(
name="playback.proto", name="playback.proto",
package="spotify.player.proto.transfer", package="spotify.player.proto.transfer",
syntax="proto2", syntax="proto2",
serialized_options=b"\n\024com.spotify.transferH\002", serialized_options=b"\n\024com.spotify.transferH\002",
create_key=_descriptor._internal_create_key, create_key=_descriptor._internal_create_key,
serialized_pb=b'\n\x0eplayback.proto\x12\x1dspotify.player.proto.transfer\x1a\x13\x63ontext_track.proto"\xa5\x01\n\x08Playback\x12\x11\n\ttimestamp\x18\x01 \x01(\x03\x12 \n\x18position_as_of_timestamp\x18\x02 \x01(\x05\x12\x16\n\x0eplayback_speed\x18\x03 \x01(\x01\x12\x11\n\tis_paused\x18\x04 \x01(\x08\x12\x39\n\rcurrent_track\x18\x05 \x01(\x0b\x32".spotify.player.proto.ContextTrackB\x18\n\x14\x63om.spotify.transferH\x02', serialized_pb=
b'\n\x0eplayback.proto\x12\x1dspotify.player.proto.transfer\x1a\x13\x63ontext_track.proto"\xa5\x01\n\x08Playback\x12\x11\n\ttimestamp\x18\x01 \x01(\x03\x12 \n\x18position_as_of_timestamp\x18\x02 \x01(\x05\x12\x16\n\x0eplayback_speed\x18\x03 \x01(\x01\x12\x11\n\tis_paused\x18\x04 \x01(\x08\x12\x39\n\rcurrent_track\x18\x05 \x01(\x0b\x32".spotify.player.proto.ContextTrackB\x18\n\x14\x63om.spotify.transferH\x02',
dependencies=[ dependencies=[
context__track__pb2.DESCRIPTOR, context__track__pb2.DESCRIPTOR,
], ],
@@ -54,7 +54,8 @@ _PLAYBACK = _descriptor.Descriptor(
), ),
_descriptor.FieldDescriptor( _descriptor.FieldDescriptor(
name="position_as_of_timestamp", name="position_as_of_timestamp",
full_name="spotify.player.proto.transfer.Playback.position_as_of_timestamp", full_name=
"spotify.player.proto.transfer.Playback.position_as_of_timestamp",
index=1, index=1,
number=2, number=2,
type=5, type=5,
@@ -142,8 +143,7 @@ _PLAYBACK = _descriptor.Descriptor(
) )
_PLAYBACK.fields_by_name[ _PLAYBACK.fields_by_name[
"current_track" "current_track"].message_type = context__track__pb2._CONTEXTTRACK
].message_type = context__track__pb2._CONTEXTTRACK
DESCRIPTOR.message_types_by_name["Playback"] = _PLAYBACK DESCRIPTOR.message_types_by_name["Playback"] = _PLAYBACK
_sym_db.RegisterFileDescriptor(DESCRIPTOR) _sym_db.RegisterFileDescriptor(DESCRIPTOR)

File diff suppressed because one or more lines are too long

View File

@@ -18,7 +18,8 @@ DESCRIPTOR = _descriptor.FileDescriptor(
syntax="proto2", syntax="proto2",
serialized_options=b"\n\036com.spotify.playlist_annotate3H\002", serialized_options=b"\n\036com.spotify.playlist_annotate3H\002",
create_key=_descriptor._internal_create_key, create_key=_descriptor._internal_create_key,
serialized_pb=b'\n\x18playlist_annotate3.proto\x12 spotify_playlist_annotate3.proto"a\n\x0fTakedownRequest\x12N\n\x12\x61\x62use_report_state\x18\x01 \x01(\x0e\x32\x32.spotify_playlist_annotate3.proto.AbuseReportState"9\n\x0f\x41nnotateRequest\x12\x13\n\x0b\x64\x65scription\x18\x01 \x01(\t\x12\x11\n\timage_uri\x18\x02 \x01(\t"5\n\x11TranscodedPicture\x12\x13\n\x0btarget_name\x18\x01 \x01(\t\x12\x0b\n\x03uri\x18\x02 \x01(\t"\xf4\x02\n\x12PlaylistAnnotation\x12\x13\n\x0b\x64\x65scription\x18\x01 \x01(\t\x12\x0f\n\x07picture\x18\x02 \x01(\t\x12i\n\x1a\x64\x65precated_render_features\x18\x03 \x01(\x0e\x32\x30.spotify_playlist_annotate3.proto.RenderFeatures:\x0fNORMAL_FEATURESB\x02\x18\x01\x12O\n\x12transcoded_picture\x18\x04 \x03(\x0b\x32\x33.spotify_playlist_annotate3.proto.TranscodedPicture\x12(\n\x1ais_abuse_reporting_enabled\x18\x06 \x01(\x08:\x04true\x12R\n\x12\x61\x62use_report_state\x18\x07 \x01(\x0e\x32\x32.spotify_playlist_annotate3.proto.AbuseReportState:\x02OK*<\n\x0eRenderFeatures\x12\x13\n\x0fNORMAL_FEATURES\x10\x01\x12\x15\n\x11\x45XTENDED_FEATURES\x10\x02**\n\x10\x41\x62useReportState\x12\x06\n\x02OK\x10\x00\x12\x0e\n\nTAKEN_DOWN\x10\x01\x42"\n\x1e\x63om.spotify.playlist_annotate3H\x02', serialized_pb=
b'\n\x18playlist_annotate3.proto\x12 spotify_playlist_annotate3.proto"a\n\x0fTakedownRequest\x12N\n\x12\x61\x62use_report_state\x18\x01 \x01(\x0e\x32\x32.spotify_playlist_annotate3.proto.AbuseReportState"9\n\x0f\x41nnotateRequest\x12\x13\n\x0b\x64\x65scription\x18\x01 \x01(\t\x12\x11\n\timage_uri\x18\x02 \x01(\t"5\n\x11TranscodedPicture\x12\x13\n\x0btarget_name\x18\x01 \x01(\t\x12\x0b\n\x03uri\x18\x02 \x01(\t"\xf4\x02\n\x12PlaylistAnnotation\x12\x13\n\x0b\x64\x65scription\x18\x01 \x01(\t\x12\x0f\n\x07picture\x18\x02 \x01(\t\x12i\n\x1a\x64\x65precated_render_features\x18\x03 \x01(\x0e\x32\x30.spotify_playlist_annotate3.proto.RenderFeatures:\x0fNORMAL_FEATURESB\x02\x18\x01\x12O\n\x12transcoded_picture\x18\x04 \x03(\x0b\x32\x33.spotify_playlist_annotate3.proto.TranscodedPicture\x12(\n\x1ais_abuse_reporting_enabled\x18\x06 \x01(\x08:\x04true\x12R\n\x12\x61\x62use_report_state\x18\x07 \x01(\x0e\x32\x32.spotify_playlist_annotate3.proto.AbuseReportState:\x02OK*<\n\x0eRenderFeatures\x12\x13\n\x0fNORMAL_FEATURES\x10\x01\x12\x15\n\x11\x45XTENDED_FEATURES\x10\x02**\n\x10\x41\x62useReportState\x12\x06\n\x02OK\x10\x00\x12\x0e\n\nTAKEN_DOWN\x10\x01\x42"\n\x1e\x63om.spotify.playlist_annotate3H\x02',
) )
_RENDERFEATURES = _descriptor.EnumDescriptor( _RENDERFEATURES = _descriptor.EnumDescriptor(
@@ -100,7 +101,8 @@ _TAKEDOWNREQUEST = _descriptor.Descriptor(
fields=[ fields=[
_descriptor.FieldDescriptor( _descriptor.FieldDescriptor(
name="abuse_report_state", name="abuse_report_state",
full_name="spotify_playlist_annotate3.proto.TakedownRequest.abuse_report_state", full_name=
"spotify_playlist_annotate3.proto.TakedownRequest.abuse_report_state",
index=0, index=0,
number=1, number=1,
type=14, type=14,
@@ -140,7 +142,8 @@ _ANNOTATEREQUEST = _descriptor.Descriptor(
fields=[ fields=[
_descriptor.FieldDescriptor( _descriptor.FieldDescriptor(
name="description", name="description",
full_name="spotify_playlist_annotate3.proto.AnnotateRequest.description", full_name=
"spotify_playlist_annotate3.proto.AnnotateRequest.description",
index=0, index=0,
number=1, number=1,
type=9, type=9,
@@ -159,7 +162,8 @@ _ANNOTATEREQUEST = _descriptor.Descriptor(
), ),
_descriptor.FieldDescriptor( _descriptor.FieldDescriptor(
name="image_uri", name="image_uri",
full_name="spotify_playlist_annotate3.proto.AnnotateRequest.image_uri", full_name=
"spotify_playlist_annotate3.proto.AnnotateRequest.image_uri",
index=1, index=1,
number=2, number=2,
type=9, type=9,
@@ -199,7 +203,8 @@ _TRANSCODEDPICTURE = _descriptor.Descriptor(
fields=[ fields=[
_descriptor.FieldDescriptor( _descriptor.FieldDescriptor(
name="target_name", name="target_name",
full_name="spotify_playlist_annotate3.proto.TranscodedPicture.target_name", full_name=
"spotify_playlist_annotate3.proto.TranscodedPicture.target_name",
index=0, index=0,
number=1, number=1,
type=9, type=9,
@@ -258,7 +263,8 @@ _PLAYLISTANNOTATION = _descriptor.Descriptor(
fields=[ fields=[
_descriptor.FieldDescriptor( _descriptor.FieldDescriptor(
name="description", name="description",
full_name="spotify_playlist_annotate3.proto.PlaylistAnnotation.description", full_name=
"spotify_playlist_annotate3.proto.PlaylistAnnotation.description",
index=0, index=0,
number=1, number=1,
type=9, type=9,
@@ -277,7 +283,8 @@ _PLAYLISTANNOTATION = _descriptor.Descriptor(
), ),
_descriptor.FieldDescriptor( _descriptor.FieldDescriptor(
name="picture", name="picture",
full_name="spotify_playlist_annotate3.proto.PlaylistAnnotation.picture", full_name=
"spotify_playlist_annotate3.proto.PlaylistAnnotation.picture",
index=1, index=1,
number=2, number=2,
type=9, type=9,
@@ -296,7 +303,8 @@ _PLAYLISTANNOTATION = _descriptor.Descriptor(
), ),
_descriptor.FieldDescriptor( _descriptor.FieldDescriptor(
name="deprecated_render_features", name="deprecated_render_features",
full_name="spotify_playlist_annotate3.proto.PlaylistAnnotation.deprecated_render_features", full_name=
"spotify_playlist_annotate3.proto.PlaylistAnnotation.deprecated_render_features",
index=2, index=2,
number=3, number=3,
type=14, type=14,
@@ -315,7 +323,8 @@ _PLAYLISTANNOTATION = _descriptor.Descriptor(
), ),
_descriptor.FieldDescriptor( _descriptor.FieldDescriptor(
name="transcoded_picture", name="transcoded_picture",
full_name="spotify_playlist_annotate3.proto.PlaylistAnnotation.transcoded_picture", full_name=
"spotify_playlist_annotate3.proto.PlaylistAnnotation.transcoded_picture",
index=3, index=3,
number=4, number=4,
type=11, type=11,
@@ -334,7 +343,8 @@ _PLAYLISTANNOTATION = _descriptor.Descriptor(
), ),
_descriptor.FieldDescriptor( _descriptor.FieldDescriptor(
name="is_abuse_reporting_enabled", name="is_abuse_reporting_enabled",
full_name="spotify_playlist_annotate3.proto.PlaylistAnnotation.is_abuse_reporting_enabled", full_name=
"spotify_playlist_annotate3.proto.PlaylistAnnotation.is_abuse_reporting_enabled",
index=4, index=4,
number=6, number=6,
type=8, type=8,
@@ -353,7 +363,8 @@ _PLAYLISTANNOTATION = _descriptor.Descriptor(
), ),
_descriptor.FieldDescriptor( _descriptor.FieldDescriptor(
name="abuse_report_state", name="abuse_report_state",
full_name="spotify_playlist_annotate3.proto.PlaylistAnnotation.abuse_report_state", full_name=
"spotify_playlist_annotate3.proto.PlaylistAnnotation.abuse_report_state",
index=5, index=5,
number=7, number=7,
type=14, type=14,
@@ -383,14 +394,14 @@ _PLAYLISTANNOTATION = _descriptor.Descriptor(
serialized_end=648, serialized_end=648,
) )
_TAKEDOWNREQUEST.fields_by_name["abuse_report_state"].enum_type = _ABUSEREPORTSTATE _TAKEDOWNREQUEST.fields_by_name[
"abuse_report_state"].enum_type = _ABUSEREPORTSTATE
_PLAYLISTANNOTATION.fields_by_name[ _PLAYLISTANNOTATION.fields_by_name[
"deprecated_render_features" "deprecated_render_features"].enum_type = _RENDERFEATURES
].enum_type = _RENDERFEATURES
_PLAYLISTANNOTATION.fields_by_name[ _PLAYLISTANNOTATION.fields_by_name[
"transcoded_picture" "transcoded_picture"].message_type = _TRANSCODEDPICTURE
].message_type = _TRANSCODEDPICTURE _PLAYLISTANNOTATION.fields_by_name[
_PLAYLISTANNOTATION.fields_by_name["abuse_report_state"].enum_type = _ABUSEREPORTSTATE "abuse_report_state"].enum_type = _ABUSEREPORTSTATE
DESCRIPTOR.message_types_by_name["TakedownRequest"] = _TAKEDOWNREQUEST DESCRIPTOR.message_types_by_name["TakedownRequest"] = _TAKEDOWNREQUEST
DESCRIPTOR.message_types_by_name["AnnotateRequest"] = _ANNOTATEREQUEST DESCRIPTOR.message_types_by_name["AnnotateRequest"] = _ANNOTATEREQUEST
DESCRIPTOR.message_types_by_name["TranscodedPicture"] = _TRANSCODEDPICTURE DESCRIPTOR.message_types_by_name["TranscodedPicture"] = _TRANSCODEDPICTURE
@@ -444,5 +455,6 @@ PlaylistAnnotation = _reflection.GeneratedProtocolMessageType(
_sym_db.RegisterMessage(PlaylistAnnotation) _sym_db.RegisterMessage(PlaylistAnnotation)
DESCRIPTOR._options = None DESCRIPTOR._options = None
_PLAYLISTANNOTATION.fields_by_name["deprecated_render_features"]._options = None _PLAYLISTANNOTATION.fields_by_name[
"deprecated_render_features"]._options = None
# @@protoc_insertion_point(module_scope) # @@protoc_insertion_point(module_scope)

View File

@@ -12,14 +12,14 @@ from google.protobuf import symbol_database as _symbol_database
_sym_db = _symbol_database.Default() _sym_db = _symbol_database.Default()
DESCRIPTOR = _descriptor.FileDescriptor( DESCRIPTOR = _descriptor.FileDescriptor(
name="queue.proto", name="queue.proto",
package="spotify.player.proto.transfer", package="spotify.player.proto.transfer",
syntax="proto2", syntax="proto2",
serialized_options=b"\n\024com.spotify.transferH\002", serialized_options=b"\n\024com.spotify.transferH\002",
create_key=_descriptor._internal_create_key, create_key=_descriptor._internal_create_key,
serialized_pb=b'\n\x0bqueue.proto\x12\x1dspotify.player.proto.transfer\x1a\x13\x63ontext_track.proto"U\n\x05Queue\x12\x32\n\x06tracks\x18\x01 \x03(\x0b\x32".spotify.player.proto.ContextTrack\x12\x18\n\x10is_playing_queue\x18\x02 \x01(\x08\x42\x18\n\x14\x63om.spotify.transferH\x02', serialized_pb=
b'\n\x0bqueue.proto\x12\x1dspotify.player.proto.transfer\x1a\x13\x63ontext_track.proto"U\n\x05Queue\x12\x32\n\x06tracks\x18\x01 \x03(\x0b\x32".spotify.player.proto.ContextTrack\x12\x18\n\x10is_playing_queue\x18\x02 \x01(\x08\x42\x18\n\x14\x63om.spotify.transferH\x02',
dependencies=[ dependencies=[
context__track__pb2.DESCRIPTOR, context__track__pb2.DESCRIPTOR,
], ],
@@ -84,7 +84,8 @@ _QUEUE = _descriptor.Descriptor(
serialized_end=152, serialized_end=152,
) )
_QUEUE.fields_by_name["tracks"].message_type = context__track__pb2._CONTEXTTRACK _QUEUE.fields_by_name[
"tracks"].message_type = context__track__pb2._CONTEXTTRACK
DESCRIPTOR.message_types_by_name["Queue"] = _QUEUE DESCRIPTOR.message_types_by_name["Queue"] = _QUEUE
_sym_db.RegisterFileDescriptor(DESCRIPTOR) _sym_db.RegisterFileDescriptor(DESCRIPTOR)

View File

@@ -17,7 +17,8 @@ DESCRIPTOR = _descriptor.FileDescriptor(
syntax="proto2", syntax="proto2",
serialized_options=b"\n\023com.spotify.contextH\002", serialized_options=b"\n\023com.spotify.contextH\002",
create_key=_descriptor._internal_create_key, create_key=_descriptor._internal_create_key,
serialized_pb=b'\n\x12restrictions.proto\x12\x14spotify.player.proto"\xbb\x07\n\x0cRestrictions\x12 \n\x18\x64isallow_pausing_reasons\x18\x01 \x03(\t\x12!\n\x19\x64isallow_resuming_reasons\x18\x02 \x03(\t\x12 \n\x18\x64isallow_seeking_reasons\x18\x03 \x03(\t\x12%\n\x1d\x64isallow_peeking_prev_reasons\x18\x04 \x03(\t\x12%\n\x1d\x64isallow_peeking_next_reasons\x18\x05 \x03(\t\x12&\n\x1e\x64isallow_skipping_prev_reasons\x18\x06 \x03(\t\x12&\n\x1e\x64isallow_skipping_next_reasons\x18\x07 \x03(\t\x12\x30\n(disallow_toggling_repeat_context_reasons\x18\x08 \x03(\t\x12.\n&disallow_toggling_repeat_track_reasons\x18\t \x03(\t\x12)\n!disallow_toggling_shuffle_reasons\x18\n \x03(\t\x12"\n\x1a\x64isallow_set_queue_reasons\x18\x0b \x03(\t\x12.\n&disallow_interrupting_playback_reasons\x18\x0c \x03(\t\x12.\n&disallow_transferring_playback_reasons\x18\r \x03(\t\x12\'\n\x1f\x64isallow_remote_control_reasons\x18\x0e \x03(\t\x12\x33\n+disallow_inserting_into_next_tracks_reasons\x18\x0f \x03(\t\x12\x36\n.disallow_inserting_into_context_tracks_reasons\x18\x10 \x03(\t\x12\x32\n*disallow_reordering_in_next_tracks_reasons\x18\x11 \x03(\t\x12\x35\n-disallow_reordering_in_context_tracks_reasons\x18\x12 \x03(\t\x12\x32\n*disallow_removing_from_next_tracks_reasons\x18\x13 \x03(\t\x12\x35\n-disallow_removing_from_context_tracks_reasons\x18\x14 \x03(\t\x12)\n!disallow_updating_context_reasons\x18\x15 \x03(\tB\x17\n\x13\x63om.spotify.contextH\x02', serialized_pb=
b'\n\x12restrictions.proto\x12\x14spotify.player.proto"\xbb\x07\n\x0cRestrictions\x12 \n\x18\x64isallow_pausing_reasons\x18\x01 \x03(\t\x12!\n\x19\x64isallow_resuming_reasons\x18\x02 \x03(\t\x12 \n\x18\x64isallow_seeking_reasons\x18\x03 \x03(\t\x12%\n\x1d\x64isallow_peeking_prev_reasons\x18\x04 \x03(\t\x12%\n\x1d\x64isallow_peeking_next_reasons\x18\x05 \x03(\t\x12&\n\x1e\x64isallow_skipping_prev_reasons\x18\x06 \x03(\t\x12&\n\x1e\x64isallow_skipping_next_reasons\x18\x07 \x03(\t\x12\x30\n(disallow_toggling_repeat_context_reasons\x18\x08 \x03(\t\x12.\n&disallow_toggling_repeat_track_reasons\x18\t \x03(\t\x12)\n!disallow_toggling_shuffle_reasons\x18\n \x03(\t\x12"\n\x1a\x64isallow_set_queue_reasons\x18\x0b \x03(\t\x12.\n&disallow_interrupting_playback_reasons\x18\x0c \x03(\t\x12.\n&disallow_transferring_playback_reasons\x18\r \x03(\t\x12\'\n\x1f\x64isallow_remote_control_reasons\x18\x0e \x03(\t\x12\x33\n+disallow_inserting_into_next_tracks_reasons\x18\x0f \x03(\t\x12\x36\n.disallow_inserting_into_context_tracks_reasons\x18\x10 \x03(\t\x12\x32\n*disallow_reordering_in_next_tracks_reasons\x18\x11 \x03(\t\x12\x35\n-disallow_reordering_in_context_tracks_reasons\x18\x12 \x03(\t\x12\x32\n*disallow_removing_from_next_tracks_reasons\x18\x13 \x03(\t\x12\x35\n-disallow_removing_from_context_tracks_reasons\x18\x14 \x03(\t\x12)\n!disallow_updating_context_reasons\x18\x15 \x03(\tB\x17\n\x13\x63om.spotify.contextH\x02',
) )
_RESTRICTIONS = _descriptor.Descriptor( _RESTRICTIONS = _descriptor.Descriptor(
@@ -30,7 +31,8 @@ _RESTRICTIONS = _descriptor.Descriptor(
fields=[ fields=[
_descriptor.FieldDescriptor( _descriptor.FieldDescriptor(
name="disallow_pausing_reasons", name="disallow_pausing_reasons",
full_name="spotify.player.proto.Restrictions.disallow_pausing_reasons", full_name=
"spotify.player.proto.Restrictions.disallow_pausing_reasons",
index=0, index=0,
number=1, number=1,
type=9, type=9,
@@ -49,7 +51,8 @@ _RESTRICTIONS = _descriptor.Descriptor(
), ),
_descriptor.FieldDescriptor( _descriptor.FieldDescriptor(
name="disallow_resuming_reasons", name="disallow_resuming_reasons",
full_name="spotify.player.proto.Restrictions.disallow_resuming_reasons", full_name=
"spotify.player.proto.Restrictions.disallow_resuming_reasons",
index=1, index=1,
number=2, number=2,
type=9, type=9,
@@ -68,7 +71,8 @@ _RESTRICTIONS = _descriptor.Descriptor(
), ),
_descriptor.FieldDescriptor( _descriptor.FieldDescriptor(
name="disallow_seeking_reasons", name="disallow_seeking_reasons",
full_name="spotify.player.proto.Restrictions.disallow_seeking_reasons", full_name=
"spotify.player.proto.Restrictions.disallow_seeking_reasons",
index=2, index=2,
number=3, number=3,
type=9, type=9,
@@ -87,7 +91,8 @@ _RESTRICTIONS = _descriptor.Descriptor(
), ),
_descriptor.FieldDescriptor( _descriptor.FieldDescriptor(
name="disallow_peeking_prev_reasons", name="disallow_peeking_prev_reasons",
full_name="spotify.player.proto.Restrictions.disallow_peeking_prev_reasons", full_name=
"spotify.player.proto.Restrictions.disallow_peeking_prev_reasons",
index=3, index=3,
number=4, number=4,
type=9, type=9,
@@ -106,7 +111,8 @@ _RESTRICTIONS = _descriptor.Descriptor(
), ),
_descriptor.FieldDescriptor( _descriptor.FieldDescriptor(
name="disallow_peeking_next_reasons", name="disallow_peeking_next_reasons",
full_name="spotify.player.proto.Restrictions.disallow_peeking_next_reasons", full_name=
"spotify.player.proto.Restrictions.disallow_peeking_next_reasons",
index=4, index=4,
number=5, number=5,
type=9, type=9,
@@ -125,7 +131,8 @@ _RESTRICTIONS = _descriptor.Descriptor(
), ),
_descriptor.FieldDescriptor( _descriptor.FieldDescriptor(
name="disallow_skipping_prev_reasons", name="disallow_skipping_prev_reasons",
full_name="spotify.player.proto.Restrictions.disallow_skipping_prev_reasons", full_name=
"spotify.player.proto.Restrictions.disallow_skipping_prev_reasons",
index=5, index=5,
number=6, number=6,
type=9, type=9,
@@ -144,7 +151,8 @@ _RESTRICTIONS = _descriptor.Descriptor(
), ),
_descriptor.FieldDescriptor( _descriptor.FieldDescriptor(
name="disallow_skipping_next_reasons", name="disallow_skipping_next_reasons",
full_name="spotify.player.proto.Restrictions.disallow_skipping_next_reasons", full_name=
"spotify.player.proto.Restrictions.disallow_skipping_next_reasons",
index=6, index=6,
number=7, number=7,
type=9, type=9,
@@ -163,7 +171,8 @@ _RESTRICTIONS = _descriptor.Descriptor(
), ),
_descriptor.FieldDescriptor( _descriptor.FieldDescriptor(
name="disallow_toggling_repeat_context_reasons", name="disallow_toggling_repeat_context_reasons",
full_name="spotify.player.proto.Restrictions.disallow_toggling_repeat_context_reasons", full_name=
"spotify.player.proto.Restrictions.disallow_toggling_repeat_context_reasons",
index=7, index=7,
number=8, number=8,
type=9, type=9,
@@ -182,7 +191,8 @@ _RESTRICTIONS = _descriptor.Descriptor(
), ),
_descriptor.FieldDescriptor( _descriptor.FieldDescriptor(
name="disallow_toggling_repeat_track_reasons", name="disallow_toggling_repeat_track_reasons",
full_name="spotify.player.proto.Restrictions.disallow_toggling_repeat_track_reasons", full_name=
"spotify.player.proto.Restrictions.disallow_toggling_repeat_track_reasons",
index=8, index=8,
number=9, number=9,
type=9, type=9,
@@ -201,7 +211,8 @@ _RESTRICTIONS = _descriptor.Descriptor(
), ),
_descriptor.FieldDescriptor( _descriptor.FieldDescriptor(
name="disallow_toggling_shuffle_reasons", name="disallow_toggling_shuffle_reasons",
full_name="spotify.player.proto.Restrictions.disallow_toggling_shuffle_reasons", full_name=
"spotify.player.proto.Restrictions.disallow_toggling_shuffle_reasons",
index=9, index=9,
number=10, number=10,
type=9, type=9,
@@ -220,7 +231,8 @@ _RESTRICTIONS = _descriptor.Descriptor(
), ),
_descriptor.FieldDescriptor( _descriptor.FieldDescriptor(
name="disallow_set_queue_reasons", name="disallow_set_queue_reasons",
full_name="spotify.player.proto.Restrictions.disallow_set_queue_reasons", full_name=
"spotify.player.proto.Restrictions.disallow_set_queue_reasons",
index=10, index=10,
number=11, number=11,
type=9, type=9,
@@ -239,7 +251,8 @@ _RESTRICTIONS = _descriptor.Descriptor(
), ),
_descriptor.FieldDescriptor( _descriptor.FieldDescriptor(
name="disallow_interrupting_playback_reasons", name="disallow_interrupting_playback_reasons",
full_name="spotify.player.proto.Restrictions.disallow_interrupting_playback_reasons", full_name=
"spotify.player.proto.Restrictions.disallow_interrupting_playback_reasons",
index=11, index=11,
number=12, number=12,
type=9, type=9,
@@ -258,7 +271,8 @@ _RESTRICTIONS = _descriptor.Descriptor(
), ),
_descriptor.FieldDescriptor( _descriptor.FieldDescriptor(
name="disallow_transferring_playback_reasons", name="disallow_transferring_playback_reasons",
full_name="spotify.player.proto.Restrictions.disallow_transferring_playback_reasons", full_name=
"spotify.player.proto.Restrictions.disallow_transferring_playback_reasons",
index=12, index=12,
number=13, number=13,
type=9, type=9,
@@ -277,7 +291,8 @@ _RESTRICTIONS = _descriptor.Descriptor(
), ),
_descriptor.FieldDescriptor( _descriptor.FieldDescriptor(
name="disallow_remote_control_reasons", name="disallow_remote_control_reasons",
full_name="spotify.player.proto.Restrictions.disallow_remote_control_reasons", full_name=
"spotify.player.proto.Restrictions.disallow_remote_control_reasons",
index=13, index=13,
number=14, number=14,
type=9, type=9,
@@ -296,7 +311,8 @@ _RESTRICTIONS = _descriptor.Descriptor(
), ),
_descriptor.FieldDescriptor( _descriptor.FieldDescriptor(
name="disallow_inserting_into_next_tracks_reasons", name="disallow_inserting_into_next_tracks_reasons",
full_name="spotify.player.proto.Restrictions.disallow_inserting_into_next_tracks_reasons", full_name=
"spotify.player.proto.Restrictions.disallow_inserting_into_next_tracks_reasons",
index=14, index=14,
number=15, number=15,
type=9, type=9,
@@ -315,7 +331,8 @@ _RESTRICTIONS = _descriptor.Descriptor(
), ),
_descriptor.FieldDescriptor( _descriptor.FieldDescriptor(
name="disallow_inserting_into_context_tracks_reasons", name="disallow_inserting_into_context_tracks_reasons",
full_name="spotify.player.proto.Restrictions.disallow_inserting_into_context_tracks_reasons", full_name=
"spotify.player.proto.Restrictions.disallow_inserting_into_context_tracks_reasons",
index=15, index=15,
number=16, number=16,
type=9, type=9,
@@ -334,7 +351,8 @@ _RESTRICTIONS = _descriptor.Descriptor(
), ),
_descriptor.FieldDescriptor( _descriptor.FieldDescriptor(
name="disallow_reordering_in_next_tracks_reasons", name="disallow_reordering_in_next_tracks_reasons",
full_name="spotify.player.proto.Restrictions.disallow_reordering_in_next_tracks_reasons", full_name=
"spotify.player.proto.Restrictions.disallow_reordering_in_next_tracks_reasons",
index=16, index=16,
number=17, number=17,
type=9, type=9,
@@ -353,7 +371,8 @@ _RESTRICTIONS = _descriptor.Descriptor(
), ),
_descriptor.FieldDescriptor( _descriptor.FieldDescriptor(
name="disallow_reordering_in_context_tracks_reasons", name="disallow_reordering_in_context_tracks_reasons",
full_name="spotify.player.proto.Restrictions.disallow_reordering_in_context_tracks_reasons", full_name=
"spotify.player.proto.Restrictions.disallow_reordering_in_context_tracks_reasons",
index=17, index=17,
number=18, number=18,
type=9, type=9,
@@ -372,7 +391,8 @@ _RESTRICTIONS = _descriptor.Descriptor(
), ),
_descriptor.FieldDescriptor( _descriptor.FieldDescriptor(
name="disallow_removing_from_next_tracks_reasons", name="disallow_removing_from_next_tracks_reasons",
full_name="spotify.player.proto.Restrictions.disallow_removing_from_next_tracks_reasons", full_name=
"spotify.player.proto.Restrictions.disallow_removing_from_next_tracks_reasons",
index=18, index=18,
number=19, number=19,
type=9, type=9,
@@ -391,7 +411,8 @@ _RESTRICTIONS = _descriptor.Descriptor(
), ),
_descriptor.FieldDescriptor( _descriptor.FieldDescriptor(
name="disallow_removing_from_context_tracks_reasons", name="disallow_removing_from_context_tracks_reasons",
full_name="spotify.player.proto.Restrictions.disallow_removing_from_context_tracks_reasons", full_name=
"spotify.player.proto.Restrictions.disallow_removing_from_context_tracks_reasons",
index=19, index=19,
number=20, number=20,
type=9, type=9,
@@ -410,7 +431,8 @@ _RESTRICTIONS = _descriptor.Descriptor(
), ),
_descriptor.FieldDescriptor( _descriptor.FieldDescriptor(
name="disallow_updating_context_reasons", name="disallow_updating_context_reasons",
full_name="spotify.player.proto.Restrictions.disallow_updating_context_reasons", full_name=
"spotify.player.proto.Restrictions.disallow_updating_context_reasons",
index=20, index=20,
number=21, number=21,
type=9, type=9,

View File

@@ -14,14 +14,14 @@ from google.protobuf import symbol_database as _symbol_database
_sym_db = _symbol_database.Default() _sym_db = _symbol_database.Default()
DESCRIPTOR = _descriptor.FileDescriptor( DESCRIPTOR = _descriptor.FileDescriptor(
name="session.proto", name="session.proto",
package="spotify.player.proto.transfer", package="spotify.player.proto.transfer",
syntax="proto2", syntax="proto2",
serialized_options=b"\n\024com.spotify.transferH\002", serialized_options=b"\n\024com.spotify.transferH\002",
create_key=_descriptor._internal_create_key, create_key=_descriptor._internal_create_key,
serialized_pb=b'\n\rsession.proto\x12\x1dspotify.player.proto.transfer\x1a\rcontext.proto\x1a\x1c\x63ontext_player_options.proto\x1a\x11play_origin.proto"\xd3\x01\n\x07Session\x12\x35\n\x0bplay_origin\x18\x01 \x01(\x0b\x32 .spotify.player.proto.PlayOrigin\x12.\n\x07\x63ontext\x18\x02 \x01(\x0b\x32\x1d.spotify.player.proto.Context\x12\x13\n\x0b\x63urrent_uid\x18\x03 \x01(\t\x12L\n\x10option_overrides\x18\x04 \x01(\x0b\x32\x32.spotify.player.proto.ContextPlayerOptionOverridesB\x18\n\x14\x63om.spotify.transferH\x02', serialized_pb=
b'\n\rsession.proto\x12\x1dspotify.player.proto.transfer\x1a\rcontext.proto\x1a\x1c\x63ontext_player_options.proto\x1a\x11play_origin.proto"\xd3\x01\n\x07Session\x12\x35\n\x0bplay_origin\x18\x01 \x01(\x0b\x32 .spotify.player.proto.PlayOrigin\x12.\n\x07\x63ontext\x18\x02 \x01(\x0b\x32\x1d.spotify.player.proto.Context\x12\x13\n\x0b\x63urrent_uid\x18\x03 \x01(\t\x12L\n\x10option_overrides\x18\x04 \x01(\x0b\x32\x32.spotify.player.proto.ContextPlayerOptionOverridesB\x18\n\x14\x63om.spotify.transferH\x02',
dependencies=[ dependencies=[
context__pb2.DESCRIPTOR, context__pb2.DESCRIPTOR,
context__player__options__pb2.DESCRIPTOR, context__player__options__pb2.DESCRIPTOR,
@@ -126,11 +126,11 @@ _SESSION = _descriptor.Descriptor(
serialized_end=324, serialized_end=324,
) )
_SESSION.fields_by_name["play_origin"].message_type = play__origin__pb2._PLAYORIGIN _SESSION.fields_by_name[
"play_origin"].message_type = play__origin__pb2._PLAYORIGIN
_SESSION.fields_by_name["context"].message_type = context__pb2._CONTEXT _SESSION.fields_by_name["context"].message_type = context__pb2._CONTEXT
_SESSION.fields_by_name[ _SESSION.fields_by_name[
"option_overrides" "option_overrides"].message_type = context__player__options__pb2._CONTEXTPLAYEROPTIONOVERRIDES
].message_type = context__player__options__pb2._CONTEXTPLAYEROPTIONOVERRIDES
DESCRIPTOR.message_types_by_name["Session"] = _SESSION DESCRIPTOR.message_types_by_name["Session"] = _SESSION
_sym_db.RegisterFileDescriptor(DESCRIPTOR) _sym_db.RegisterFileDescriptor(DESCRIPTOR)

View File

@@ -15,14 +15,14 @@ from google.protobuf import symbol_database as _symbol_database
_sym_db = _symbol_database.Default() _sym_db = _symbol_database.Default()
DESCRIPTOR = _descriptor.FileDescriptor( DESCRIPTOR = _descriptor.FileDescriptor(
name="transfer_state.proto", name="transfer_state.proto",
package="spotify.player.proto.transfer", package="spotify.player.proto.transfer",
syntax="proto2", syntax="proto2",
serialized_options=b"\n\024com.spotify.transferH\002", serialized_options=b"\n\024com.spotify.transferH\002",
create_key=_descriptor._internal_create_key, create_key=_descriptor._internal_create_key,
serialized_pb=b"\n\x14transfer_state.proto\x12\x1dspotify.player.proto.transfer\x1a\x1c\x63ontext_player_options.proto\x1a\x0eplayback.proto\x1a\rsession.proto\x1a\x0bqueue.proto\"\x99\x02\n\rTransferState\x12;\n\x07options\x18\x01 \x01(\x0b\x32*.spotify.player.proto.ContextPlayerOptions\x12\x39\n\x08playback\x18\x02 \x01(\x0b\x32'.spotify.player.proto.transfer.Playback\x12?\n\x0f\x63urrent_session\x18\x03 \x01(\x0b\x32&.spotify.player.proto.transfer.Session\x12\x33\n\x05queue\x18\x04 \x01(\x0b\x32$.spotify.player.proto.transfer.Queue\x12\x1a\n\x12\x63reation_timestamp\x18\x05 \x01(\x03\x42\x18\n\x14\x63om.spotify.transferH\x02", serialized_pb=
b"\n\x14transfer_state.proto\x12\x1dspotify.player.proto.transfer\x1a\x1c\x63ontext_player_options.proto\x1a\x0eplayback.proto\x1a\rsession.proto\x1a\x0bqueue.proto\"\x99\x02\n\rTransferState\x12;\n\x07options\x18\x01 \x01(\x0b\x32*.spotify.player.proto.ContextPlayerOptions\x12\x39\n\x08playback\x18\x02 \x01(\x0b\x32'.spotify.player.proto.transfer.Playback\x12?\n\x0f\x63urrent_session\x18\x03 \x01(\x0b\x32&.spotify.player.proto.transfer.Session\x12\x33\n\x05queue\x18\x04 \x01(\x0b\x32$.spotify.player.proto.transfer.Queue\x12\x1a\n\x12\x63reation_timestamp\x18\x05 \x01(\x03\x42\x18\n\x14\x63om.spotify.transferH\x02",
dependencies=[ dependencies=[
context__player__options__pb2.DESCRIPTOR, context__player__options__pb2.DESCRIPTOR,
playback__pb2.DESCRIPTOR, playback__pb2.DESCRIPTOR,
@@ -79,7 +79,8 @@ _TRANSFERSTATE = _descriptor.Descriptor(
), ),
_descriptor.FieldDescriptor( _descriptor.FieldDescriptor(
name="current_session", name="current_session",
full_name="spotify.player.proto.transfer.TransferState.current_session", full_name=
"spotify.player.proto.transfer.TransferState.current_session",
index=2, index=2,
number=3, number=3,
type=11, type=11,
@@ -117,7 +118,8 @@ _TRANSFERSTATE = _descriptor.Descriptor(
), ),
_descriptor.FieldDescriptor( _descriptor.FieldDescriptor(
name="creation_timestamp", name="creation_timestamp",
full_name="spotify.player.proto.transfer.TransferState.creation_timestamp", full_name=
"spotify.player.proto.transfer.TransferState.creation_timestamp",
index=4, index=4,
number=5, number=5,
type=3, type=3,
@@ -148,10 +150,11 @@ _TRANSFERSTATE = _descriptor.Descriptor(
) )
_TRANSFERSTATE.fields_by_name[ _TRANSFERSTATE.fields_by_name[
"options" "options"].message_type = context__player__options__pb2._CONTEXTPLAYEROPTIONS
].message_type = context__player__options__pb2._CONTEXTPLAYEROPTIONS _TRANSFERSTATE.fields_by_name[
_TRANSFERSTATE.fields_by_name["playback"].message_type = playback__pb2._PLAYBACK "playback"].message_type = playback__pb2._PLAYBACK
_TRANSFERSTATE.fields_by_name["current_session"].message_type = session__pb2._SESSION _TRANSFERSTATE.fields_by_name[
"current_session"].message_type = session__pb2._SESSION
_TRANSFERSTATE.fields_by_name["queue"].message_type = queue__pb2._QUEUE _TRANSFERSTATE.fields_by_name["queue"].message_type = queue__pb2._QUEUE
DESCRIPTOR.message_types_by_name["TransferState"] = _TRANSFERSTATE DESCRIPTOR.message_types_by_name["TransferState"] = _TRANSFERSTATE
_sym_db.RegisterFileDescriptor(DESCRIPTOR) _sym_db.RegisterFileDescriptor(DESCRIPTOR)

View File

@@ -17,7 +17,8 @@ DESCRIPTOR = _descriptor.FileDescriptor(
syntax="proto3", syntax="proto3",
serialized_options=b"\n\024com.spotify.login5v3", serialized_options=b"\n\024com.spotify.login5v3",
create_key=_descriptor._internal_create_key, create_key=_descriptor._internal_create_key,
serialized_pb=b'\n#spotify/login5/v3/client_info.proto\x12\x11spotify.login5.v3"2\n\nClientInfo\x12\x11\n\tclient_id\x18\x01 \x01(\t\x12\x11\n\tdevice_id\x18\x02 \x01(\tB\x16\n\x14\x63om.spotify.login5v3b\x06proto3', serialized_pb=
b'\n#spotify/login5/v3/client_info.proto\x12\x11spotify.login5.v3"2\n\nClientInfo\x12\x11\n\tclient_id\x18\x01 \x01(\t\x12\x11\n\tdevice_id\x18\x02 \x01(\tB\x16\n\x14\x63om.spotify.login5v3b\x06proto3',
) )
_CLIENTINFO = _descriptor.Descriptor( _CLIENTINFO = _descriptor.Descriptor(

View File

@@ -26,21 +26,23 @@ from spotify.login5.v3.identifiers import \
_sym_db = _symbol_database.Default() _sym_db = _symbol_database.Default()
DESCRIPTOR = _descriptor.FileDescriptor( DESCRIPTOR = _descriptor.FileDescriptor(
name="spotify/login5/v3/login5.proto", name="spotify/login5/v3/login5.proto",
package="spotify.login5.v3", package="spotify.login5.v3",
syntax="proto3", syntax="proto3",
serialized_options=b"\n\024com.spotify.login5v3", serialized_options=b"\n\024com.spotify.login5v3",
create_key=_descriptor._internal_create_key, create_key=_descriptor._internal_create_key,
serialized_pb=b'\n\x1espotify/login5/v3/login5.proto\x12\x11spotify.login5.v3\x1a#spotify/login5/v3/client_info.proto\x1a!spotify/login5/v3/user_info.proto\x1a\'spotify/login5/v3/challenges/code.proto\x1a+spotify/login5/v3/challenges/hashcash.proto\x1a/spotify/login5/v3/credentials/credentials.proto\x1a/spotify/login5/v3/identifiers/identifiers.proto">\n\nChallenges\x12\x30\n\nchallenges\x18\x01 \x03(\x0b\x32\x1c.spotify.login5.v3.Challenge"\x89\x01\n\tChallenge\x12\x41\n\x08hashcash\x18\x01 \x01(\x0b\x32/.spotify.login5.v3.challenges.HashcashChallenge\x12\x39\n\x04\x63ode\x18\x02 \x01(\x0b\x32+.spotify.login5.v3.challenges.CodeChallenge"M\n\x12\x43hallengeSolutions\x12\x37\n\tsolutions\x18\x01 \x03(\x0b\x32$.spotify.login5.v3.ChallengeSolution"\x8f\x01\n\x11\x43hallengeSolution\x12@\n\x08hashcash\x18\x01 \x01(\x0b\x32..spotify.login5.v3.challenges.HashcashSolution\x12\x38\n\x04\x63ode\x18\x02 \x01(\x0b\x32*.spotify.login5.v3.challenges.CodeSolution"\xad\x05\n\x0cLoginRequest\x12\x32\n\x0b\x63lient_info\x18\x01 \x01(\x0b\x32\x1d.spotify.login5.v3.ClientInfo\x12\x15\n\rlogin_context\x18\x02 \x01(\x0c\x12\x42\n\x13\x63hallenge_solutions\x18\x03 \x01(\x0b\x32%.spotify.login5.v3.ChallengeSolutions\x12J\n\x11stored_credential\x18\x64 \x01(\x0b\x32/.spotify.login5.v3.credentials.StoredCredential\x12\x39\n\x08password\x18\x65 \x01(\x0b\x32\'.spotify.login5.v3.credentials.Password\x12Q\n\x15\x66\x61\x63\x65\x62ook_access_token\x18\x66 \x01(\x0b\x32\x32.spotify.login5.v3.credentials.FacebookAccessToken\x12@\n\x0cphone_number\x18g \x01(\x0b\x32*.spotify.login5.v3.identifiers.PhoneNumber\x12\x43\n\x0eone_time_token\x18h \x01(\x0b\x32+.spotify.login5.v3.credentials.OneTimeToken\x12U\n\x17parent_child_credential\x18i \x01(\x0b\x32\x34.spotify.login5.v3.credentials.ParentChildCredential\x12V\n\x18\x61pple_sign_in_credential\x18j \x01(\x0b\x32\x34.spotify.login5.v3.credentials.AppleSignInCredential"m\n\x07LoginOk\x12\x10\n\x08username\x18\x01 \x01(\t\x12\x14\n\x0c\x61\x63\x63\x65ss_token\x18\x02 \x01(\t\x12\x19\n\x11stored_credential\x18\x03 \x01(\x0c\x12\x1f\n\x17\x61\x63\x63\x65ss_token_expires_in\x18\x04 \x01(\x05"\xf8\x02\n\rLoginResponse\x12&\n\x02ok\x18\x01 \x01(\x0b\x32\x1a.spotify.login5.v3.LoginOk\x12,\n\x05\x65rror\x18\x02 \x01(\x0e\x32\x1d.spotify.login5.v3.LoginError\x12\x31\n\nchallenges\x18\x03 \x01(\x0b\x32\x1d.spotify.login5.v3.Challenges\x12;\n\x08warnings\x18\x04 \x03(\x0e\x32).spotify.login5.v3.LoginResponse.Warnings\x12\x15\n\rlogin_context\x18\x05 \x01(\x0c\x12\x18\n\x10identifier_token\x18\x06 \x01(\t\x12.\n\tuser_info\x18\x07 \x01(\x0b\x32\x1b.spotify.login5.v3.UserInfo"@\n\x08Warnings\x12\x13\n\x0fUNKNOWN_WARNING\x10\x00\x12\x1f\n\x1b\x44\x45PRECATED_PROTOCOL_VERSION\x10\x01*\xd3\x01\n\nLoginError\x12\x11\n\rUNKNOWN_ERROR\x10\x00\x12\x17\n\x13INVALID_CREDENTIALS\x10\x01\x12\x0f\n\x0b\x42\x41\x44_REQUEST\x10\x02\x12\x1e\n\x1aUNSUPPORTED_LOGIN_PROTOCOL\x10\x03\x12\x0b\n\x07TIMEOUT\x10\x04\x12\x16\n\x12UNKNOWN_IDENTIFIER\x10\x05\x12\x15\n\x11TOO_MANY_ATTEMPTS\x10\x06\x12\x17\n\x13INVALID_PHONENUMBER\x10\x07\x12\x13\n\x0fTRY_AGAIN_LATER\x10\x08\x42\x16\n\x14\x63om.spotify.login5v3b\x06proto3', serialized_pb=
b'\n\x1espotify/login5/v3/login5.proto\x12\x11spotify.login5.v3\x1a#spotify/login5/v3/client_info.proto\x1a!spotify/login5/v3/user_info.proto\x1a\'spotify/login5/v3/challenges/code.proto\x1a+spotify/login5/v3/challenges/hashcash.proto\x1a/spotify/login5/v3/credentials/credentials.proto\x1a/spotify/login5/v3/identifiers/identifiers.proto">\n\nChallenges\x12\x30\n\nchallenges\x18\x01 \x03(\x0b\x32\x1c.spotify.login5.v3.Challenge"\x89\x01\n\tChallenge\x12\x41\n\x08hashcash\x18\x01 \x01(\x0b\x32/.spotify.login5.v3.challenges.HashcashChallenge\x12\x39\n\x04\x63ode\x18\x02 \x01(\x0b\x32+.spotify.login5.v3.challenges.CodeChallenge"M\n\x12\x43hallengeSolutions\x12\x37\n\tsolutions\x18\x01 \x03(\x0b\x32$.spotify.login5.v3.ChallengeSolution"\x8f\x01\n\x11\x43hallengeSolution\x12@\n\x08hashcash\x18\x01 \x01(\x0b\x32..spotify.login5.v3.challenges.HashcashSolution\x12\x38\n\x04\x63ode\x18\x02 \x01(\x0b\x32*.spotify.login5.v3.challenges.CodeSolution"\xad\x05\n\x0cLoginRequest\x12\x32\n\x0b\x63lient_info\x18\x01 \x01(\x0b\x32\x1d.spotify.login5.v3.ClientInfo\x12\x15\n\rlogin_context\x18\x02 \x01(\x0c\x12\x42\n\x13\x63hallenge_solutions\x18\x03 \x01(\x0b\x32%.spotify.login5.v3.ChallengeSolutions\x12J\n\x11stored_credential\x18\x64 \x01(\x0b\x32/.spotify.login5.v3.credentials.StoredCredential\x12\x39\n\x08password\x18\x65 \x01(\x0b\x32\'.spotify.login5.v3.credentials.Password\x12Q\n\x15\x66\x61\x63\x65\x62ook_access_token\x18\x66 \x01(\x0b\x32\x32.spotify.login5.v3.credentials.FacebookAccessToken\x12@\n\x0cphone_number\x18g \x01(\x0b\x32*.spotify.login5.v3.identifiers.PhoneNumber\x12\x43\n\x0eone_time_token\x18h \x01(\x0b\x32+.spotify.login5.v3.credentials.OneTimeToken\x12U\n\x17parent_child_credential\x18i \x01(\x0b\x32\x34.spotify.login5.v3.credentials.ParentChildCredential\x12V\n\x18\x61pple_sign_in_credential\x18j \x01(\x0b\x32\x34.spotify.login5.v3.credentials.AppleSignInCredential"m\n\x07LoginOk\x12\x10\n\x08username\x18\x01 \x01(\t\x12\x14\n\x0c\x61\x63\x63\x65ss_token\x18\x02 \x01(\t\x12\x19\n\x11stored_credential\x18\x03 \x01(\x0c\x12\x1f\n\x17\x61\x63\x63\x65ss_token_expires_in\x18\x04 \x01(\x05"\xf8\x02\n\rLoginResponse\x12&\n\x02ok\x18\x01 \x01(\x0b\x32\x1a.spotify.login5.v3.LoginOk\x12,\n\x05\x65rror\x18\x02 \x01(\x0e\x32\x1d.spotify.login5.v3.LoginError\x12\x31\n\nchallenges\x18\x03 \x01(\x0b\x32\x1d.spotify.login5.v3.Challenges\x12;\n\x08warnings\x18\x04 \x03(\x0e\x32).spotify.login5.v3.LoginResponse.Warnings\x12\x15\n\rlogin_context\x18\x05 \x01(\x0c\x12\x18\n\x10identifier_token\x18\x06 \x01(\t\x12.\n\tuser_info\x18\x07 \x01(\x0b\x32\x1b.spotify.login5.v3.UserInfo"@\n\x08Warnings\x12\x13\n\x0fUNKNOWN_WARNING\x10\x00\x12\x1f\n\x1b\x44\x45PRECATED_PROTOCOL_VERSION\x10\x01*\xd3\x01\n\nLoginError\x12\x11\n\rUNKNOWN_ERROR\x10\x00\x12\x17\n\x13INVALID_CREDENTIALS\x10\x01\x12\x0f\n\x0b\x42\x41\x44_REQUEST\x10\x02\x12\x1e\n\x1aUNSUPPORTED_LOGIN_PROTOCOL\x10\x03\x12\x0b\n\x07TIMEOUT\x10\x04\x12\x16\n\x12UNKNOWN_IDENTIFIER\x10\x05\x12\x15\n\x11TOO_MANY_ATTEMPTS\x10\x06\x12\x17\n\x13INVALID_PHONENUMBER\x10\x07\x12\x13\n\x0fTRY_AGAIN_LATER\x10\x08\x42\x16\n\x14\x63om.spotify.login5v3b\x06proto3',
dependencies=[ dependencies=[
spotify_dot_login5_dot_v3_dot_client__info__pb2.DESCRIPTOR, spotify_dot_login5_dot_v3_dot_client__info__pb2.DESCRIPTOR,
spotify_dot_login5_dot_v3_dot_user__info__pb2.DESCRIPTOR, spotify_dot_login5_dot_v3_dot_user__info__pb2.DESCRIPTOR,
spotify_dot_login5_dot_v3_dot_challenges_dot_code__pb2.DESCRIPTOR, spotify_dot_login5_dot_v3_dot_challenges_dot_code__pb2.DESCRIPTOR,
spotify_dot_login5_dot_v3_dot_challenges_dot_hashcash__pb2.DESCRIPTOR, spotify_dot_login5_dot_v3_dot_challenges_dot_hashcash__pb2.DESCRIPTOR,
spotify_dot_login5_dot_v3_dot_credentials_dot_credentials__pb2.DESCRIPTOR, spotify_dot_login5_dot_v3_dot_credentials_dot_credentials__pb2.
spotify_dot_login5_dot_v3_dot_identifiers_dot_identifiers__pb2.DESCRIPTOR, DESCRIPTOR,
spotify_dot_login5_dot_v3_dot_identifiers_dot_identifiers__pb2.
DESCRIPTOR,
], ],
) )
@@ -836,69 +838,48 @@ _LOGINRESPONSE = _descriptor.Descriptor(
) )
_CHALLENGES.fields_by_name["challenges"].message_type = _CHALLENGE _CHALLENGES.fields_by_name["challenges"].message_type = _CHALLENGE
_CHALLENGE.fields_by_name["hashcash"].message_type = (
spotify_dot_login5_dot_v3_dot_challenges_dot_hashcash__pb2.
_HASHCASHCHALLENGE)
_CHALLENGE.fields_by_name[ _CHALLENGE.fields_by_name[
"hashcash" "code"].message_type = spotify_dot_login5_dot_v3_dot_challenges_dot_code__pb2._CODECHALLENGE
].message_type = ( _CHALLENGESOLUTIONS.fields_by_name[
spotify_dot_login5_dot_v3_dot_challenges_dot_hashcash__pb2._HASHCASHCHALLENGE "solutions"].message_type = _CHALLENGESOLUTION
) _CHALLENGESOLUTION.fields_by_name["hashcash"].message_type = (
_CHALLENGE.fields_by_name[ spotify_dot_login5_dot_v3_dot_challenges_dot_hashcash__pb2.
"code" _HASHCASHSOLUTION)
].message_type = spotify_dot_login5_dot_v3_dot_challenges_dot_code__pb2._CODECHALLENGE
_CHALLENGESOLUTIONS.fields_by_name["solutions"].message_type = _CHALLENGESOLUTION
_CHALLENGESOLUTION.fields_by_name[ _CHALLENGESOLUTION.fields_by_name[
"hashcash" "code"].message_type = spotify_dot_login5_dot_v3_dot_challenges_dot_code__pb2._CODESOLUTION
].message_type = (
spotify_dot_login5_dot_v3_dot_challenges_dot_hashcash__pb2._HASHCASHSOLUTION
)
_CHALLENGESOLUTION.fields_by_name[
"code"
].message_type = spotify_dot_login5_dot_v3_dot_challenges_dot_code__pb2._CODESOLUTION
_LOGINREQUEST.fields_by_name[ _LOGINREQUEST.fields_by_name[
"client_info" "client_info"].message_type = spotify_dot_login5_dot_v3_dot_client__info__pb2._CLIENTINFO
].message_type = spotify_dot_login5_dot_v3_dot_client__info__pb2._CLIENTINFO
_LOGINREQUEST.fields_by_name["challenge_solutions"].message_type = _CHALLENGESOLUTIONS
_LOGINREQUEST.fields_by_name[ _LOGINREQUEST.fields_by_name[
"stored_credential" "challenge_solutions"].message_type = _CHALLENGESOLUTIONS
].message_type = ( _LOGINREQUEST.fields_by_name["stored_credential"].message_type = (
spotify_dot_login5_dot_v3_dot_credentials_dot_credentials__pb2._STOREDCREDENTIAL spotify_dot_login5_dot_v3_dot_credentials_dot_credentials__pb2.
) _STOREDCREDENTIAL)
_LOGINREQUEST.fields_by_name[ _LOGINREQUEST.fields_by_name["password"].message_type = (
"password" spotify_dot_login5_dot_v3_dot_credentials_dot_credentials__pb2._PASSWORD)
].message_type = ( _LOGINREQUEST.fields_by_name["facebook_access_token"].message_type = (
spotify_dot_login5_dot_v3_dot_credentials_dot_credentials__pb2._PASSWORD spotify_dot_login5_dot_v3_dot_credentials_dot_credentials__pb2.
) _FACEBOOKACCESSTOKEN)
_LOGINREQUEST.fields_by_name[ _LOGINREQUEST.fields_by_name["phone_number"].message_type = (
"facebook_access_token"
].message_type = (
spotify_dot_login5_dot_v3_dot_credentials_dot_credentials__pb2._FACEBOOKACCESSTOKEN
)
_LOGINREQUEST.fields_by_name[
"phone_number"
].message_type = (
spotify_dot_login5_dot_v3_dot_identifiers_dot_identifiers__pb2._PHONENUMBER spotify_dot_login5_dot_v3_dot_identifiers_dot_identifiers__pb2._PHONENUMBER
) )
_LOGINREQUEST.fields_by_name[ _LOGINREQUEST.fields_by_name["one_time_token"].message_type = (
"one_time_token" spotify_dot_login5_dot_v3_dot_credentials_dot_credentials__pb2.
].message_type = ( _ONETIMETOKEN)
spotify_dot_login5_dot_v3_dot_credentials_dot_credentials__pb2._ONETIMETOKEN _LOGINREQUEST.fields_by_name["parent_child_credential"].message_type = (
) spotify_dot_login5_dot_v3_dot_credentials_dot_credentials__pb2.
_LOGINREQUEST.fields_by_name[ _PARENTCHILDCREDENTIAL)
"parent_child_credential" _LOGINREQUEST.fields_by_name["apple_sign_in_credential"].message_type = (
].message_type = ( spotify_dot_login5_dot_v3_dot_credentials_dot_credentials__pb2.
spotify_dot_login5_dot_v3_dot_credentials_dot_credentials__pb2._PARENTCHILDCREDENTIAL _APPLESIGNINCREDENTIAL)
)
_LOGINREQUEST.fields_by_name[
"apple_sign_in_credential"
].message_type = (
spotify_dot_login5_dot_v3_dot_credentials_dot_credentials__pb2._APPLESIGNINCREDENTIAL
)
_LOGINRESPONSE.fields_by_name["ok"].message_type = _LOGINOK _LOGINRESPONSE.fields_by_name["ok"].message_type = _LOGINOK
_LOGINRESPONSE.fields_by_name["error"].enum_type = _LOGINERROR _LOGINRESPONSE.fields_by_name["error"].enum_type = _LOGINERROR
_LOGINRESPONSE.fields_by_name["challenges"].message_type = _CHALLENGES _LOGINRESPONSE.fields_by_name["challenges"].message_type = _CHALLENGES
_LOGINRESPONSE.fields_by_name["warnings"].enum_type = _LOGINRESPONSE_WARNINGS _LOGINRESPONSE.fields_by_name["warnings"].enum_type = _LOGINRESPONSE_WARNINGS
_LOGINRESPONSE.fields_by_name[ _LOGINRESPONSE.fields_by_name[
"user_info" "user_info"].message_type = spotify_dot_login5_dot_v3_dot_user__info__pb2._USERINFO
].message_type = spotify_dot_login5_dot_v3_dot_user__info__pb2._USERINFO
_LOGINRESPONSE_WARNINGS.containing_type = _LOGINRESPONSE _LOGINRESPONSE_WARNINGS.containing_type = _LOGINRESPONSE
DESCRIPTOR.message_types_by_name["Challenges"] = _CHALLENGES DESCRIPTOR.message_types_by_name["Challenges"] = _CHALLENGES
DESCRIPTOR.message_types_by_name["Challenge"] = _CHALLENGE DESCRIPTOR.message_types_by_name["Challenge"] = _CHALLENGE

View File

@@ -17,7 +17,8 @@ DESCRIPTOR = _descriptor.FileDescriptor(
syntax="proto3", syntax="proto3",
serialized_options=b"\n\024com.spotify.login5v3", serialized_options=b"\n\024com.spotify.login5v3",
create_key=_descriptor._internal_create_key, create_key=_descriptor._internal_create_key,
serialized_pb=b'\n!spotify/login5/v3/user_info.proto\x12\x11spotify.login5.v3"\x97\x02\n\x08UserInfo\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\r\n\x05\x65mail\x18\x02 \x01(\t\x12\x16\n\x0e\x65mail_verified\x18\x03 \x01(\x08\x12\x11\n\tbirthdate\x18\x04 \x01(\t\x12\x32\n\x06gender\x18\x05 \x01(\x0e\x32".spotify.login5.v3.UserInfo.Gender\x12\x14\n\x0cphone_number\x18\x06 \x01(\t\x12\x1d\n\x15phone_number_verified\x18\x07 \x01(\x08\x12 \n\x18\x65mail_already_registered\x18\x08 \x01(\x08"8\n\x06Gender\x12\x0b\n\x07UNKNOWN\x10\x00\x12\x08\n\x04MALE\x10\x01\x12\n\n\x06\x46\x45MALE\x10\x02\x12\x0b\n\x07NEUTRAL\x10\x03\x42\x16\n\x14\x63om.spotify.login5v3b\x06proto3', serialized_pb=
b'\n!spotify/login5/v3/user_info.proto\x12\x11spotify.login5.v3"\x97\x02\n\x08UserInfo\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\r\n\x05\x65mail\x18\x02 \x01(\t\x12\x16\n\x0e\x65mail_verified\x18\x03 \x01(\x08\x12\x11\n\tbirthdate\x18\x04 \x01(\t\x12\x32\n\x06gender\x18\x05 \x01(\x0e\x32".spotify.login5.v3.UserInfo.Gender\x12\x14\n\x0cphone_number\x18\x06 \x01(\t\x12\x1d\n\x15phone_number_verified\x18\x07 \x01(\x08\x12 \n\x18\x65mail_already_registered\x18\x08 \x01(\x08"8\n\x06Gender\x12\x0b\n\x07UNKNOWN\x10\x00\x12\x08\n\x04MALE\x10\x01\x12\n\n\x06\x46\x45MALE\x10\x02\x12\x0b\n\x07NEUTRAL\x10\x03\x42\x16\n\x14\x63om.spotify.login5v3b\x06proto3',
) )
_USERINFO_GENDER = _descriptor.EnumDescriptor( _USERINFO_GENDER = _descriptor.EnumDescriptor(

View File

@@ -17,7 +17,8 @@ DESCRIPTOR = _descriptor.FileDescriptor(
syntax="proto3", syntax="proto3",
serialized_options=b"\n\024com.spotify.login5v3", serialized_options=b"\n\024com.spotify.login5v3",
create_key=_descriptor._internal_create_key, create_key=_descriptor._internal_create_key,
serialized_pb=b'\n\'spotify/login5/v3/challenges/code.proto\x12\x1cspotify.login5.v3.challenges"\xbc\x01\n\rCodeChallenge\x12\x42\n\x06method\x18\x01 \x01(\x0e\x32\x32.spotify.login5.v3.challenges.CodeChallenge.Method\x12\x13\n\x0b\x63ode_length\x18\x02 \x01(\x05\x12\x12\n\nexpires_in\x18\x03 \x01(\x05\x12\x1e\n\x16\x63\x61nonical_phone_number\x18\x04 \x01(\t"\x1e\n\x06Method\x12\x0b\n\x07UNKNOWN\x10\x00\x12\x07\n\x03SMS\x10\x01"\x1c\n\x0c\x43odeSolution\x12\x0c\n\x04\x63ode\x18\x01 \x01(\tB\x16\n\x14\x63om.spotify.login5v3b\x06proto3', serialized_pb=
b'\n\'spotify/login5/v3/challenges/code.proto\x12\x1cspotify.login5.v3.challenges"\xbc\x01\n\rCodeChallenge\x12\x42\n\x06method\x18\x01 \x01(\x0e\x32\x32.spotify.login5.v3.challenges.CodeChallenge.Method\x12\x13\n\x0b\x63ode_length\x18\x02 \x01(\x05\x12\x12\n\nexpires_in\x18\x03 \x01(\x05\x12\x1e\n\x16\x63\x61nonical_phone_number\x18\x04 \x01(\t"\x1e\n\x06Method\x12\x0b\n\x07UNKNOWN\x10\x00\x12\x07\n\x03SMS\x10\x01"\x1c\n\x0c\x43odeSolution\x12\x0c\n\x04\x63ode\x18\x01 \x01(\tB\x16\n\x14\x63om.spotify.login5v3b\x06proto3',
) )
_CODECHALLENGE_METHOD = _descriptor.EnumDescriptor( _CODECHALLENGE_METHOD = _descriptor.EnumDescriptor(
@@ -118,7 +119,8 @@ _CODECHALLENGE = _descriptor.Descriptor(
), ),
_descriptor.FieldDescriptor( _descriptor.FieldDescriptor(
name="canonical_phone_number", name="canonical_phone_number",
full_name="spotify.login5.v3.challenges.CodeChallenge.canonical_phone_number", full_name=
"spotify.login5.v3.challenges.CodeChallenge.canonical_phone_number",
index=3, index=3,
number=4, number=4,
type=9, type=9,

View File

@@ -13,14 +13,14 @@ from google.protobuf import symbol_database as _symbol_database
_sym_db = _symbol_database.Default() _sym_db = _symbol_database.Default()
DESCRIPTOR = _descriptor.FileDescriptor( DESCRIPTOR = _descriptor.FileDescriptor(
name="spotify/login5/v3/challenges/hashcash.proto", name="spotify/login5/v3/challenges/hashcash.proto",
package="spotify.login5.v3.challenges", package="spotify.login5.v3.challenges",
syntax="proto3", syntax="proto3",
serialized_options=b"\n\024com.spotify.login5v3", serialized_options=b"\n\024com.spotify.login5v3",
create_key=_descriptor._internal_create_key, create_key=_descriptor._internal_create_key,
serialized_pb=b'\n+spotify/login5/v3/challenges/hashcash.proto\x12\x1cspotify.login5.v3.challenges\x1a\x1egoogle/protobuf/duration.proto"3\n\x11HashcashChallenge\x12\x0e\n\x06prefix\x18\x01 \x01(\x0c\x12\x0e\n\x06length\x18\x02 \x01(\x05"O\n\x10HashcashSolution\x12\x0e\n\x06suffix\x18\x01 \x01(\x0c\x12+\n\x08\x64uration\x18\x02 \x01(\x0b\x32\x19.google.protobuf.DurationB\x16\n\x14\x63om.spotify.login5v3b\x06proto3', serialized_pb=
b'\n+spotify/login5/v3/challenges/hashcash.proto\x12\x1cspotify.login5.v3.challenges\x1a\x1egoogle/protobuf/duration.proto"3\n\x11HashcashChallenge\x12\x0e\n\x06prefix\x18\x01 \x01(\x0c\x12\x0e\n\x06length\x18\x02 \x01(\x05"O\n\x10HashcashSolution\x12\x0e\n\x06suffix\x18\x01 \x01(\x0c\x12+\n\x08\x64uration\x18\x02 \x01(\x0b\x32\x19.google.protobuf.DurationB\x16\n\x14\x63om.spotify.login5v3b\x06proto3',
dependencies=[ dependencies=[
google_dot_protobuf_dot_duration__pb2.DESCRIPTOR, google_dot_protobuf_dot_duration__pb2.DESCRIPTOR,
], ],
@@ -145,8 +145,7 @@ _HASHCASHSOLUTION = _descriptor.Descriptor(
) )
_HASHCASHSOLUTION.fields_by_name[ _HASHCASHSOLUTION.fields_by_name[
"duration" "duration"].message_type = google_dot_protobuf_dot_duration__pb2._DURATION
].message_type = google_dot_protobuf_dot_duration__pb2._DURATION
DESCRIPTOR.message_types_by_name["HashcashChallenge"] = _HASHCASHCHALLENGE DESCRIPTOR.message_types_by_name["HashcashChallenge"] = _HASHCASHCHALLENGE
DESCRIPTOR.message_types_by_name["HashcashSolution"] = _HASHCASHSOLUTION DESCRIPTOR.message_types_by_name["HashcashSolution"] = _HASHCASHSOLUTION
_sym_db.RegisterFileDescriptor(DESCRIPTOR) _sym_db.RegisterFileDescriptor(DESCRIPTOR)

View File

@@ -17,7 +17,8 @@ DESCRIPTOR = _descriptor.FileDescriptor(
syntax="proto3", syntax="proto3",
serialized_options=b"\n\024com.spotify.login5v3", serialized_options=b"\n\024com.spotify.login5v3",
create_key=_descriptor._internal_create_key, create_key=_descriptor._internal_create_key,
serialized_pb=b'\n/spotify/login5/v3/credentials/credentials.proto\x12\x1dspotify.login5.v3.credentials"2\n\x10StoredCredential\x12\x10\n\x08username\x18\x01 \x01(\t\x12\x0c\n\x04\x64\x61ta\x18\x02 \x01(\x0c"9\n\x08Password\x12\n\n\x02id\x18\x01 \x01(\t\x12\x10\n\x08password\x18\x02 \x01(\t\x12\x0f\n\x07padding\x18\x03 \x01(\x0c";\n\x13\x46\x61\x63\x65\x62ookAccessToken\x12\x0e\n\x06\x66\x62_uid\x18\x01 \x01(\t\x12\x14\n\x0c\x61\x63\x63\x65ss_token\x18\x02 \x01(\t"\x1d\n\x0cOneTimeToken\x12\r\n\x05token\x18\x01 \x01(\t"|\n\x15ParentChildCredential\x12\x10\n\x08\x63hild_id\x18\x01 \x01(\t\x12Q\n\x18parent_stored_credential\x18\x02 \x01(\x0b\x32/.spotify.login5.v3.credentials.StoredCredential"S\n\x15\x41ppleSignInCredential\x12\x11\n\tauth_code\x18\x01 \x01(\t\x12\x14\n\x0credirect_uri\x18\x02 \x01(\t\x12\x11\n\tbundle_id\x18\x03 \x01(\tB\x16\n\x14\x63om.spotify.login5v3b\x06proto3', serialized_pb=
b'\n/spotify/login5/v3/credentials/credentials.proto\x12\x1dspotify.login5.v3.credentials"2\n\x10StoredCredential\x12\x10\n\x08username\x18\x01 \x01(\t\x12\x0c\n\x04\x64\x61ta\x18\x02 \x01(\x0c"9\n\x08Password\x12\n\n\x02id\x18\x01 \x01(\t\x12\x10\n\x08password\x18\x02 \x01(\t\x12\x0f\n\x07padding\x18\x03 \x01(\x0c";\n\x13\x46\x61\x63\x65\x62ookAccessToken\x12\x0e\n\x06\x66\x62_uid\x18\x01 \x01(\t\x12\x14\n\x0c\x61\x63\x63\x65ss_token\x18\x02 \x01(\t"\x1d\n\x0cOneTimeToken\x12\r\n\x05token\x18\x01 \x01(\t"|\n\x15ParentChildCredential\x12\x10\n\x08\x63hild_id\x18\x01 \x01(\t\x12Q\n\x18parent_stored_credential\x18\x02 \x01(\x0b\x32/.spotify.login5.v3.credentials.StoredCredential"S\n\x15\x41ppleSignInCredential\x12\x11\n\tauth_code\x18\x01 \x01(\t\x12\x14\n\x0credirect_uri\x18\x02 \x01(\t\x12\x11\n\tbundle_id\x18\x03 \x01(\tB\x16\n\x14\x63om.spotify.login5v3b\x06proto3',
) )
_STOREDCREDENTIAL = _descriptor.Descriptor( _STOREDCREDENTIAL = _descriptor.Descriptor(
@@ -167,7 +168,8 @@ _FACEBOOKACCESSTOKEN = _descriptor.Descriptor(
fields=[ fields=[
_descriptor.FieldDescriptor( _descriptor.FieldDescriptor(
name="fb_uid", name="fb_uid",
full_name="spotify.login5.v3.credentials.FacebookAccessToken.fb_uid", full_name=
"spotify.login5.v3.credentials.FacebookAccessToken.fb_uid",
index=0, index=0,
number=1, number=1,
type=9, type=9,
@@ -186,7 +188,8 @@ _FACEBOOKACCESSTOKEN = _descriptor.Descriptor(
), ),
_descriptor.FieldDescriptor( _descriptor.FieldDescriptor(
name="access_token", name="access_token",
full_name="spotify.login5.v3.credentials.FacebookAccessToken.access_token", full_name=
"spotify.login5.v3.credentials.FacebookAccessToken.access_token",
index=1, index=1,
number=2, number=2,
type=9, type=9,
@@ -266,7 +269,8 @@ _PARENTCHILDCREDENTIAL = _descriptor.Descriptor(
fields=[ fields=[
_descriptor.FieldDescriptor( _descriptor.FieldDescriptor(
name="child_id", name="child_id",
full_name="spotify.login5.v3.credentials.ParentChildCredential.child_id", full_name=
"spotify.login5.v3.credentials.ParentChildCredential.child_id",
index=0, index=0,
number=1, number=1,
type=9, type=9,
@@ -285,7 +289,8 @@ _PARENTCHILDCREDENTIAL = _descriptor.Descriptor(
), ),
_descriptor.FieldDescriptor( _descriptor.FieldDescriptor(
name="parent_stored_credential", name="parent_stored_credential",
full_name="spotify.login5.v3.credentials.ParentChildCredential.parent_stored_credential", full_name=
"spotify.login5.v3.credentials.ParentChildCredential.parent_stored_credential",
index=1, index=1,
number=2, number=2,
type=11, type=11,
@@ -325,7 +330,8 @@ _APPLESIGNINCREDENTIAL = _descriptor.Descriptor(
fields=[ fields=[
_descriptor.FieldDescriptor( _descriptor.FieldDescriptor(
name="auth_code", name="auth_code",
full_name="spotify.login5.v3.credentials.AppleSignInCredential.auth_code", full_name=
"spotify.login5.v3.credentials.AppleSignInCredential.auth_code",
index=0, index=0,
number=1, number=1,
type=9, type=9,
@@ -344,7 +350,8 @@ _APPLESIGNINCREDENTIAL = _descriptor.Descriptor(
), ),
_descriptor.FieldDescriptor( _descriptor.FieldDescriptor(
name="redirect_uri", name="redirect_uri",
full_name="spotify.login5.v3.credentials.AppleSignInCredential.redirect_uri", full_name=
"spotify.login5.v3.credentials.AppleSignInCredential.redirect_uri",
index=1, index=1,
number=2, number=2,
type=9, type=9,
@@ -363,7 +370,8 @@ _APPLESIGNINCREDENTIAL = _descriptor.Descriptor(
), ),
_descriptor.FieldDescriptor( _descriptor.FieldDescriptor(
name="bundle_id", name="bundle_id",
full_name="spotify.login5.v3.credentials.AppleSignInCredential.bundle_id", full_name=
"spotify.login5.v3.credentials.AppleSignInCredential.bundle_id",
index=2, index=2,
number=3, number=3,
type=9, type=9,
@@ -394,14 +402,15 @@ _APPLESIGNINCREDENTIAL = _descriptor.Descriptor(
) )
_PARENTCHILDCREDENTIAL.fields_by_name[ _PARENTCHILDCREDENTIAL.fields_by_name[
"parent_stored_credential" "parent_stored_credential"].message_type = _STOREDCREDENTIAL
].message_type = _STOREDCREDENTIAL
DESCRIPTOR.message_types_by_name["StoredCredential"] = _STOREDCREDENTIAL DESCRIPTOR.message_types_by_name["StoredCredential"] = _STOREDCREDENTIAL
DESCRIPTOR.message_types_by_name["Password"] = _PASSWORD DESCRIPTOR.message_types_by_name["Password"] = _PASSWORD
DESCRIPTOR.message_types_by_name["FacebookAccessToken"] = _FACEBOOKACCESSTOKEN DESCRIPTOR.message_types_by_name["FacebookAccessToken"] = _FACEBOOKACCESSTOKEN
DESCRIPTOR.message_types_by_name["OneTimeToken"] = _ONETIMETOKEN DESCRIPTOR.message_types_by_name["OneTimeToken"] = _ONETIMETOKEN
DESCRIPTOR.message_types_by_name["ParentChildCredential"] = _PARENTCHILDCREDENTIAL DESCRIPTOR.message_types_by_name[
DESCRIPTOR.message_types_by_name["AppleSignInCredential"] = _APPLESIGNINCREDENTIAL "ParentChildCredential"] = _PARENTCHILDCREDENTIAL
DESCRIPTOR.message_types_by_name[
"AppleSignInCredential"] = _APPLESIGNINCREDENTIAL
_sym_db.RegisterFileDescriptor(DESCRIPTOR) _sym_db.RegisterFileDescriptor(DESCRIPTOR)
StoredCredential = _reflection.GeneratedProtocolMessageType( StoredCredential = _reflection.GeneratedProtocolMessageType(

View File

@@ -17,7 +17,8 @@ DESCRIPTOR = _descriptor.FileDescriptor(
syntax="proto3", syntax="proto3",
serialized_options=b"\n\024com.spotify.login5v3", serialized_options=b"\n\024com.spotify.login5v3",
create_key=_descriptor._internal_create_key, create_key=_descriptor._internal_create_key,
serialized_pb=b'\n/spotify/login5/v3/identifiers/identifiers.proto\x12\x1dspotify.login5.v3.identifiers"U\n\x0bPhoneNumber\x12\x0e\n\x06number\x18\x01 \x01(\t\x12\x18\n\x10iso_country_code\x18\x02 \x01(\t\x12\x1c\n\x14\x63ountry_calling_code\x18\x03 \x01(\tB\x16\n\x14\x63om.spotify.login5v3b\x06proto3', serialized_pb=
b'\n/spotify/login5/v3/identifiers/identifiers.proto\x12\x1dspotify.login5.v3.identifiers"U\n\x0bPhoneNumber\x12\x0e\n\x06number\x18\x01 \x01(\t\x12\x18\n\x10iso_country_code\x18\x02 \x01(\t\x12\x1c\n\x14\x63ountry_calling_code\x18\x03 \x01(\tB\x16\n\x14\x63om.spotify.login5v3b\x06proto3',
) )
_PHONENUMBER = _descriptor.Descriptor( _PHONENUMBER = _descriptor.Descriptor(
@@ -49,7 +50,8 @@ _PHONENUMBER = _descriptor.Descriptor(
), ),
_descriptor.FieldDescriptor( _descriptor.FieldDescriptor(
name="iso_country_code", name="iso_country_code",
full_name="spotify.login5.v3.identifiers.PhoneNumber.iso_country_code", full_name=
"spotify.login5.v3.identifiers.PhoneNumber.iso_country_code",
index=1, index=1,
number=2, number=2,
type=9, type=9,
@@ -68,7 +70,8 @@ _PHONENUMBER = _descriptor.Descriptor(
), ),
_descriptor.FieldDescriptor( _descriptor.FieldDescriptor(
name="country_calling_code", name="country_calling_code",
full_name="spotify.login5.v3.identifiers.PhoneNumber.country_calling_code", full_name=
"spotify.login5.v3.identifiers.PhoneNumber.country_calling_code",
index=2, index=2,
number=3, number=3,
type=9, type=9,

View File

@@ -3,16 +3,20 @@ from librespot.standard.FilterInputStream import FilterInputStream
class DataInputStream(FilterInputStream, DataInput): class DataInputStream(FilterInputStream, DataInput):
def read(self, b: bytearray = None, offset: int = None, length: int = None) -> int: def read(self,
b: bytearray = None,
offset: int = None,
length: int = None) -> int:
if b is not None and offset is None and length is None: if b is not None and offset is None and length is None:
return self.input_stream.read(b, 0, len(b)) return self.input_stream.read(b, 0, len(b))
if b is not None and offset is not None and length is not None: if b is not None and offset is not None and length is not None:
return self.input_stream.read(b, offset, length) return self.input_stream.read(b, offset, length)
raise TypeError() raise TypeError()
def read_fully( def read_fully(self,
self, b: bytearray = None, offset: int = None, length: int = None b: bytearray = None,
) -> None: offset: int = None,
length: int = None) -> None:
if b is not None and offset is None and length is None: if b is not None and offset is None and length is None:
offset = 0 offset = 0
length = len(b) length = len(b)
@@ -90,16 +94,14 @@ class DataInputStream(FilterInputStream, DataInput):
def read_long(self) -> int: def read_long(self) -> int:
self.read_fully(self.read_buffer, 0, 8) self.read_fully(self.read_buffer, 0, 8)
return ( return ((self.read_buffer[0] << 56) +
(self.read_buffer[0] << 56) ((self.read_buffer[1] & 255) << 48) +
+ ((self.read_buffer[1] & 255) << 48) ((self.read_buffer[2] & 255) << 40) +
+ ((self.read_buffer[2] & 255) << 40) ((self.read_buffer[3] & 255) << 32) +
+ ((self.read_buffer[3] & 255) << 32) ((self.read_buffer[4] & 255) << 24) +
+ ((self.read_buffer[4] & 255) << 24) ((self.read_buffer[5] & 255) << 16) +
+ ((self.read_buffer[5] & 255) << 16) ((self.read_buffer[6] & 255) << 8) +
+ ((self.read_buffer[6] & 255) << 8) ((self.read_buffer[7] & 255) << 0))
+ ((self.read_buffer[7] & 255) << 0)
)
def read_float(self) -> float: def read_float(self) -> float:
pass pass

View File

@@ -18,9 +18,11 @@ class Zeroconf(Closeable):
def __init__(self): def __init__(self):
try: try:
self.__BROADCAST4 = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) self.__BROADCAST4 = socket.socket(socket.AF_INET,
socket.SOCK_DGRAM)
self.__BROADCAST4.connect(("224.0.0.251", 5353)) self.__BROADCAST4.connect(("224.0.0.251", 5353))
self.__BROADCAST6 = socket.socket(socket.AF_INET6, socket.SOCK_DGRAM) self.__BROADCAST6 = socket.socket(socket.AF_INET6,
socket.SOCK_DGRAM)
self.__BROADCAST6.connect(("FF02::FB", 5353)) self.__BROADCAST6.connect(("FF02::FB", 5353))
except Exception as e: except Exception as e:
pass pass
@@ -31,12 +33,9 @@ class Zeroconf(Closeable):
def get_or_create_local_host_name() -> str: def get_or_create_local_host_name() -> str:
host = socket.gethostname() host = socket.gethostname()
if host == "localhost": if host == "localhost":
host = ( host = (base64.b64encode(
base64.b64encode( random.randint(-9223372036854775808,
random.randint(-9223372036854775808, 9223372036854775807) 9223372036854775807)).decode() + ".local")
).decode()
+ ".local"
)
return host return host
def set_use_ipv4(self, ipv4: bool) -> Zeroconf: def set_use_ipv4(self, ipv4: bool) -> Zeroconf: