From 4821831e6f486a024e8533811e2d28b789bd1915 Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 22 Nov 2025 03:39:04 +0100 Subject: [PATCH] Initial commit --- librespot/__init__.py | 34 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 2305 bytes librespot/__pycache__/cache.cpython-312.pyc | Bin 0 -> 885 bytes librespot/__pycache__/core.cpython-312.pyc | Bin 0 -> 121628 bytes librespot/__pycache__/crypto.cpython-312.pyc | Bin 0 -> 22483 bytes librespot/__pycache__/dealer.cpython-312.pyc | Bin 0 -> 714 bytes librespot/__pycache__/mercury.cpython-312.pyc | Bin 0 -> 24001 bytes .../__pycache__/metadata.cpython-312.pyc | Bin 0 -> 18698 bytes .../__pycache__/structure.cpython-312.pyc | Bin 0 -> 6287 bytes librespot/__pycache__/util.cpython-312.pyc | Bin 0 -> 6668 bytes .../__pycache__/zeroconf.cpython-312.pyc | Bin 0 -> 21890 bytes librespot/audio/__init__.zip | Bin 0 -> 8665 bytes librespot/audio/__init__api.py | 1164 ++++++ librespot/audio/__init__old.py | 1033 +++++ .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 59100 bytes .../__pycache__/decoders.cpython-312.pyc | Bin 0 -> 4330 bytes .../audio/__pycache__/decrypt.cpython-312.pyc | Bin 0 -> 3104 bytes .../audio/__pycache__/format.cpython-312.pyc | Bin 0 -> 2292 bytes .../audio/__pycache__/storage.cpython-312.pyc | Bin 0 -> 10153 bytes librespot/audio/decoders.py | 81 + librespot/audio/decrypt.py | 45 + librespot/audio/format.py | 32 + librespot/audio/storage.py | 139 + librespot/cache.py | 18 + librespot/core.py | 2758 ++++++++++++ librespot/crypto.py | 412 ++ librespot/dealer.py | 11 + librespot/mercury.py | 394 ++ librespot/metadata.py | 283 ++ librespot/proto/Authentication_pb2.py | 1984 +++++++++ librespot/proto/CanvazMeta_pb2.py | 91 + librespot/proto/Canvaz_pb2.py | 564 +++ librespot/proto/ClientToken_pb2.py | 63 + librespot/proto/Connect_pb2.py | 2340 +++++++++++ librespot/proto/Connectivity_pb2.py | 36 + librespot/proto/ContextPage_pb2.py | 239 ++ librespot/proto/ContextPlayerOptions_pb2.py | 215 + librespot/proto/ContextTrack_pb2.py | 214 + librespot/proto/Context_pb2.py | 260 ++ librespot/proto/ExplicitContentPubsub_pb2.py | 147 + librespot/proto/Keyexchange_pb2.py | 2497 +++++++++++ librespot/proto/Mercury_pb2.py | 625 +++ librespot/proto/Metadata_pb2.py | 3698 +++++++++++++++++ librespot/proto/PlayOrigin_pb2.py | 193 + librespot/proto/Playback_pb2.py | 162 + librespot/proto/Player_pb2.py | 1851 +++++++++ librespot/proto/Playlist4External_pb2.py | 3221 ++++++++++++++ librespot/proto/PlaylistAnnotate3_pb2.py | 460 ++ librespot/proto/Pubsub_pb2.py | 112 + librespot/proto/Queue_pb2.py | 104 + librespot/proto/Restrictions_pb2.py | 480 +++ librespot/proto/Session_pb2.py | 149 + librespot/proto/StorageResolve_pb2.py | 154 + librespot/proto/TransferState_pb2.py | 174 + librespot/proto/__init__.py | 0 .../Authentication_pb2.cpython-312.pyc | Bin 0 -> 46459 bytes .../CanvazMeta_pb2.cpython-312.pyc | Bin 0 -> 2448 bytes .../__pycache__/Canvaz_pb2.cpython-312.pyc | Bin 0 -> 13788 bytes .../ClientToken_pb2.cpython-312.pyc | Bin 0 -> 5220 bytes .../__pycache__/Connect_pb2.cpython-312.pyc | Bin 0 -> 55763 bytes .../Connectivity_pb2.cpython-312.pyc | Bin 0 -> 2627 bytes .../ContextPage_pb2.cpython-312.pyc | Bin 0 -> 6468 bytes .../ContextPlayerOptions_pb2.cpython-312.pyc | Bin 0 -> 5724 bytes .../ContextTrack_pb2.cpython-312.pyc | Bin 0 -> 5746 bytes .../__pycache__/Context_pb2.cpython-312.pyc | Bin 0 -> 6995 bytes .../ExplicitContentPubsub_pb2.cpython-312.pyc | Bin 0 -> 4460 bytes .../Keyexchange_pb2.cpython-312.pyc | Bin 0 -> 58852 bytes .../__pycache__/Mercury_pb2.cpython-312.pyc | Bin 0 -> 15046 bytes .../__pycache__/Metadata_pb2.cpython-312.pyc | Bin 0 -> 89306 bytes .../PlayOrigin_pb2.cpython-312.pyc | Bin 0 -> 5512 bytes .../__pycache__/Playback_pb2.cpython-312.pyc | Bin 0 -> 4724 bytes .../__pycache__/Player_pb2.cpython-312.pyc | Bin 0 -> 46465 bytes .../Playlist4External_pb2.cpython-312.pyc | Bin 0 -> 72805 bytes .../PlaylistAnnotate3_pb2.cpython-312.pyc | Bin 0 -> 11919 bytes .../__pycache__/Pubsub_pb2.cpython-312.pyc | Bin 0 -> 3379 bytes .../__pycache__/Queue_pb2.cpython-312.pyc | Bin 0 -> 3311 bytes .../Restrictions_pb2.cpython-312.pyc | Bin 0 -> 12740 bytes .../__pycache__/Session_pb2.cpython-312.pyc | Bin 0 -> 4771 bytes .../StorageResolve_pb2.cpython-312.pyc | Bin 0 -> 4573 bytes .../TransferState_pb2.cpython-312.pyc | Bin 0 -> 5421 bytes .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 201 bytes librespot/proto/spotify/__init__.py | 0 .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 209 bytes librespot/proto/spotify/login5/__init__.py | 0 .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 216 bytes .../proto/spotify/login5/v3/ClientInfo_pb2.py | 98 + .../proto/spotify/login5/v3/Login5_pb2.py | 972 +++++ .../proto/spotify/login5/v3/UserInfo_pb2.py | 263 ++ librespot/proto/spotify/login5/v3/__init__.py | 0 .../ClientInfo_pb2.cpython-312.pyc | Bin 0 -> 3160 bytes .../v3/__pycache__/Login5_pb2.cpython-312.pyc | Bin 0 -> 24497 bytes .../__pycache__/UserInfo_pb2.cpython-312.pyc | Bin 0 -> 6872 bytes .../v3/__pycache__/__init__.cpython-312.pyc | Bin 0 -> 219 bytes .../spotify/login5/v3/challenges/Code_pb2.py | 224 + .../login5/v3/challenges/Hashcash_pb2.py | 176 + .../spotify/login5/v3/challenges/__init__.py | 0 .../__pycache__/Code_pb2.cpython-312.pyc | Bin 0 -> 6119 bytes .../__pycache__/Hashcash_pb2.cpython-312.pyc | Bin 0 -> 5059 bytes .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 230 bytes .../login5/v3/credentials/Credentials_pb2.py | 483 +++ .../spotify/login5/v3/credentials/__init__.py | 0 .../Credentials_pb2.cpython-312.pyc | Bin 0 -> 12055 bytes .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 231 bytes .../login5/v3/identifiers/Identifiers.py | 119 + .../spotify/login5/v3/identifiers/__init__.py | 0 .../__pycache__/Identifiers.cpython-312.pyc | Bin 0 -> 3802 bytes .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 231 bytes librespot/proto_ext/__init__.py | 1 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 225 bytes .../audio_files_extension_pb2.cpython-312.pyc | Bin 0 -> 2174 bytes .../proto_ext/audio_files_extension_pb2.py | 33 + .../proto_ext/entity_extension_data_pb2.py | 37 + librespot/proto_ext/extended_metadata_pb2.py | 46 + librespot/proto_ext/extension_kind_pb2.py | 29 + librespot/structure.py | 103 + librespot/util.py | 117 + librespot/zeroconf.py | 345 ++ zotify/zotify.py | 6 +- 118 files changed, 29486 insertions(+), 3 deletions(-) create mode 100644 librespot/__init__.py create mode 100644 librespot/__pycache__/__init__.cpython-312.pyc create mode 100644 librespot/__pycache__/cache.cpython-312.pyc create mode 100644 librespot/__pycache__/core.cpython-312.pyc create mode 100644 librespot/__pycache__/crypto.cpython-312.pyc create mode 100644 librespot/__pycache__/dealer.cpython-312.pyc create mode 100644 librespot/__pycache__/mercury.cpython-312.pyc create mode 100644 librespot/__pycache__/metadata.cpython-312.pyc create mode 100644 librespot/__pycache__/structure.cpython-312.pyc create mode 100644 librespot/__pycache__/util.cpython-312.pyc create mode 100644 librespot/__pycache__/zeroconf.cpython-312.pyc create mode 100644 librespot/audio/__init__.zip create mode 100644 librespot/audio/__init__api.py create mode 100644 librespot/audio/__init__old.py create mode 100644 librespot/audio/__pycache__/__init__.cpython-312.pyc create mode 100644 librespot/audio/__pycache__/decoders.cpython-312.pyc create mode 100644 librespot/audio/__pycache__/decrypt.cpython-312.pyc create mode 100644 librespot/audio/__pycache__/format.cpython-312.pyc create mode 100644 librespot/audio/__pycache__/storage.cpython-312.pyc create mode 100644 librespot/audio/decoders.py create mode 100644 librespot/audio/decrypt.py create mode 100644 librespot/audio/format.py create mode 100644 librespot/audio/storage.py create mode 100644 librespot/cache.py create mode 100644 librespot/core.py create mode 100644 librespot/crypto.py create mode 100644 librespot/dealer.py create mode 100644 librespot/mercury.py create mode 100644 librespot/metadata.py create mode 100644 librespot/proto/Authentication_pb2.py create mode 100644 librespot/proto/CanvazMeta_pb2.py create mode 100644 librespot/proto/Canvaz_pb2.py create mode 100644 librespot/proto/ClientToken_pb2.py create mode 100644 librespot/proto/Connect_pb2.py create mode 100644 librespot/proto/Connectivity_pb2.py create mode 100644 librespot/proto/ContextPage_pb2.py create mode 100644 librespot/proto/ContextPlayerOptions_pb2.py create mode 100644 librespot/proto/ContextTrack_pb2.py create mode 100644 librespot/proto/Context_pb2.py create mode 100644 librespot/proto/ExplicitContentPubsub_pb2.py create mode 100644 librespot/proto/Keyexchange_pb2.py create mode 100644 librespot/proto/Mercury_pb2.py create mode 100644 librespot/proto/Metadata_pb2.py create mode 100644 librespot/proto/PlayOrigin_pb2.py create mode 100644 librespot/proto/Playback_pb2.py create mode 100644 librespot/proto/Player_pb2.py create mode 100644 librespot/proto/Playlist4External_pb2.py create mode 100644 librespot/proto/PlaylistAnnotate3_pb2.py create mode 100644 librespot/proto/Pubsub_pb2.py create mode 100644 librespot/proto/Queue_pb2.py create mode 100644 librespot/proto/Restrictions_pb2.py create mode 100644 librespot/proto/Session_pb2.py create mode 100644 librespot/proto/StorageResolve_pb2.py create mode 100644 librespot/proto/TransferState_pb2.py create mode 100644 librespot/proto/__init__.py create mode 100644 librespot/proto/__pycache__/Authentication_pb2.cpython-312.pyc create mode 100644 librespot/proto/__pycache__/CanvazMeta_pb2.cpython-312.pyc create mode 100644 librespot/proto/__pycache__/Canvaz_pb2.cpython-312.pyc create mode 100644 librespot/proto/__pycache__/ClientToken_pb2.cpython-312.pyc create mode 100644 librespot/proto/__pycache__/Connect_pb2.cpython-312.pyc create mode 100644 librespot/proto/__pycache__/Connectivity_pb2.cpython-312.pyc create mode 100644 librespot/proto/__pycache__/ContextPage_pb2.cpython-312.pyc create mode 100644 librespot/proto/__pycache__/ContextPlayerOptions_pb2.cpython-312.pyc create mode 100644 librespot/proto/__pycache__/ContextTrack_pb2.cpython-312.pyc create mode 100644 librespot/proto/__pycache__/Context_pb2.cpython-312.pyc create mode 100644 librespot/proto/__pycache__/ExplicitContentPubsub_pb2.cpython-312.pyc create mode 100644 librespot/proto/__pycache__/Keyexchange_pb2.cpython-312.pyc create mode 100644 librespot/proto/__pycache__/Mercury_pb2.cpython-312.pyc create mode 100644 librespot/proto/__pycache__/Metadata_pb2.cpython-312.pyc create mode 100644 librespot/proto/__pycache__/PlayOrigin_pb2.cpython-312.pyc create mode 100644 librespot/proto/__pycache__/Playback_pb2.cpython-312.pyc create mode 100644 librespot/proto/__pycache__/Player_pb2.cpython-312.pyc create mode 100644 librespot/proto/__pycache__/Playlist4External_pb2.cpython-312.pyc create mode 100644 librespot/proto/__pycache__/PlaylistAnnotate3_pb2.cpython-312.pyc create mode 100644 librespot/proto/__pycache__/Pubsub_pb2.cpython-312.pyc create mode 100644 librespot/proto/__pycache__/Queue_pb2.cpython-312.pyc create mode 100644 librespot/proto/__pycache__/Restrictions_pb2.cpython-312.pyc create mode 100644 librespot/proto/__pycache__/Session_pb2.cpython-312.pyc create mode 100644 librespot/proto/__pycache__/StorageResolve_pb2.cpython-312.pyc create mode 100644 librespot/proto/__pycache__/TransferState_pb2.cpython-312.pyc create mode 100644 librespot/proto/__pycache__/__init__.cpython-312.pyc create mode 100644 librespot/proto/spotify/__init__.py create mode 100644 librespot/proto/spotify/__pycache__/__init__.cpython-312.pyc create mode 100644 librespot/proto/spotify/login5/__init__.py create mode 100644 librespot/proto/spotify/login5/__pycache__/__init__.cpython-312.pyc create mode 100644 librespot/proto/spotify/login5/v3/ClientInfo_pb2.py create mode 100644 librespot/proto/spotify/login5/v3/Login5_pb2.py create mode 100644 librespot/proto/spotify/login5/v3/UserInfo_pb2.py create mode 100644 librespot/proto/spotify/login5/v3/__init__.py create mode 100644 librespot/proto/spotify/login5/v3/__pycache__/ClientInfo_pb2.cpython-312.pyc create mode 100644 librespot/proto/spotify/login5/v3/__pycache__/Login5_pb2.cpython-312.pyc create mode 100644 librespot/proto/spotify/login5/v3/__pycache__/UserInfo_pb2.cpython-312.pyc create mode 100644 librespot/proto/spotify/login5/v3/__pycache__/__init__.cpython-312.pyc create mode 100644 librespot/proto/spotify/login5/v3/challenges/Code_pb2.py create mode 100644 librespot/proto/spotify/login5/v3/challenges/Hashcash_pb2.py create mode 100644 librespot/proto/spotify/login5/v3/challenges/__init__.py create mode 100644 librespot/proto/spotify/login5/v3/challenges/__pycache__/Code_pb2.cpython-312.pyc create mode 100644 librespot/proto/spotify/login5/v3/challenges/__pycache__/Hashcash_pb2.cpython-312.pyc create mode 100644 librespot/proto/spotify/login5/v3/challenges/__pycache__/__init__.cpython-312.pyc create mode 100644 librespot/proto/spotify/login5/v3/credentials/Credentials_pb2.py create mode 100644 librespot/proto/spotify/login5/v3/credentials/__init__.py create mode 100644 librespot/proto/spotify/login5/v3/credentials/__pycache__/Credentials_pb2.cpython-312.pyc create mode 100644 librespot/proto/spotify/login5/v3/credentials/__pycache__/__init__.cpython-312.pyc create mode 100644 librespot/proto/spotify/login5/v3/identifiers/Identifiers.py create mode 100644 librespot/proto/spotify/login5/v3/identifiers/__init__.py create mode 100644 librespot/proto/spotify/login5/v3/identifiers/__pycache__/Identifiers.cpython-312.pyc create mode 100644 librespot/proto/spotify/login5/v3/identifiers/__pycache__/__init__.cpython-312.pyc create mode 100644 librespot/proto_ext/__init__.py create mode 100644 librespot/proto_ext/__pycache__/__init__.cpython-312.pyc create mode 100644 librespot/proto_ext/__pycache__/audio_files_extension_pb2.cpython-312.pyc create mode 100644 librespot/proto_ext/audio_files_extension_pb2.py create mode 100644 librespot/proto_ext/entity_extension_data_pb2.py create mode 100644 librespot/proto_ext/extended_metadata_pb2.py create mode 100644 librespot/proto_ext/extension_kind_pb2.py create mode 100644 librespot/structure.py create mode 100644 librespot/util.py create mode 100644 librespot/zeroconf.py diff --git a/librespot/__init__.py b/librespot/__init__.py new file mode 100644 index 0000000..9503e25 --- /dev/null +++ b/librespot/__init__.py @@ -0,0 +1,34 @@ +from __future__ import annotations +from librespot.crypto import DiffieHellman +from librespot.proto.Keyexchange_pb2 import BuildInfo, Platform, Product, ProductFlags +from librespot.structure import Closeable, Runnable +import platform + + +class Version: + version_name = "0.0.9" + + @staticmethod + def platform() -> Platform: + if platform.system() == "Windows": + return Platform.PLATFORM_WIN32_X86 + if platform.system() == "Darwin": + return Platform.PLATFORM_OSX_X86 + return Platform.PLATFORM_LINUX_X86 + + @staticmethod + def version_string(): + return "librespot-python " + Version.version_name + + @staticmethod + def system_info_string(): + return Version.version_string() + \ + "; Python " + platform.python_version() + \ + "; " + platform.system() + + @staticmethod + def standard_build_info() -> BuildInfo: + return BuildInfo(product=Product.PRODUCT_CLIENT, + product_flags=[ProductFlags.PRODUCT_FLAG_NONE], + platform=Version.platform(), + version=117300517) diff --git a/librespot/__pycache__/__init__.cpython-312.pyc b/librespot/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..53b267ca65071f331900088d8d23a75468a581bf GIT binary patch literal 2305 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 b@1Njz@ax~@0N(!^{}ud{)E$l>`{@4#=5m#^ literal 0 HcmV?d00001 diff --git a/librespot/__pycache__/dealer.cpython-312.pyc b/librespot/__pycache__/dealer.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..215e6b3f95626ce56120432cc6bdc0a98c6f6773 GIT binary patch literal 714 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 C_LS)W literal 0 HcmV?d00001 diff --git a/librespot/__pycache__/metadata.cpython-312.pyc b/librespot/__pycache__/metadata.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..4af00bc8fecf2524850354e15b4daa41a135ff11 GIT binary patch literal 18698 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 literal 0 HcmV?d00001 diff --git a/librespot/audio/__init__api.py b/librespot/audio/__init__api.py new file mode 100644 index 0000000..623a88a --- /dev/null +++ b/librespot/audio/__init__api.py @@ -0,0 +1,1164 @@ +from __future__ import annotations +from librespot import util +from librespot.audio.decrypt import AesAudioDecrypt +from librespot.audio.format import SuperAudioFormat +from librespot.audio.storage import ChannelManager +from librespot.cache import CacheManager +from librespot.crypto import Packet +from librespot.metadata import EpisodeId, PlayableId, TrackId +from librespot.proto import Metadata_pb2 as Metadata, StorageResolve_pb2 as StorageResolve +from librespot.structure import ( + AudioDecrypt, + AudioQualityPicker, + Closeable, + FeederException, + GeneralAudioStream, + GeneralWritableStream, + HaltListener, + NoopAudioDecrypt, + PacketsReceiver, +) +from pathlib import Path +import concurrent.futures +import io +import logging +import math +import queue +import random +import struct +import threading +import time +import typing +import urllib.parse +import os +import json +import requests +if typing.TYPE_CHECKING: + from librespot.core import Session + +""" +PATCH : SpotiClub Audio Key Fetching +Fetches the audio decryption key from the SpotiClub Audio Key API instead of Spotify directly. +This is a workaround for Spotify's tightened restrictions on Audio Key access (only Premium Tier now). + +There are 3 importants parameters to provide, and one is already filled in: +- server_url: The URL of the SpotiClub Audio Key API endpoint. You should not need to change this, except if a dev instructs you to do so. +- spoticlub_user : Your SpotiClub FTP username. You can get this by using our Padoru Asssistant once. +- spoticlub_password : Your SpotiClub FTP password, also obtainable via the Padoru Assistant. + +Alternatively, you can use the file `spoticlub_credentials.json` in the Zotify project root with the following structure: + + { + "spoticlub_user": "spoticlub-...", + "spoticlub_password": "..." + } +""" +##### WRITE YOUR LOGINS DOWN HERE ##### +####################################### +server_url = "http://api.spoticlub.zip:4277/get_audio_key" +spoticlub_user = "" +spoticlub_password = "" +######################################## +##### END OF USER INPUT AREA ########### + +SPOTICLUB_DISABLE = os.getenv("SPOTICLUB_DISABLE", "").lower() in {"1", "true", "yes"} +SPOTICLUB_FALLBACK_TO_SPOTIFY = os.getenv("SPOTICLUB_FALLBACK_SPOTIFY", "1").lower() not in { + "0", + "false", + "no", +} + +class AbsChunkedInputStream(io.BytesIO, HaltListener): + chunk_exception = None + closed = False + max_chunk_tries = 128 + preload_ahead = 3 + preload_chunk_retries = 2 + retries: typing.List[int] + retry_on_chunk_error: bool + wait_lock: threading.Condition = threading.Condition() + wait_for_chunk = -1 + __decoded_length = 0 + __mark = 0 + __pos = 0 + + def __init__(self, retry_on_chunk_error: bool): + super().__init__() + self.retries = [0] * self.chunks() + self.retry_on_chunk_error = retry_on_chunk_error + + def is_closed(self) -> bool: + return self.closed + + def buffer(self) -> typing.List[bytes]: + raise NotImplementedError() + + def size(self) -> int: + raise NotImplementedError() + + def close(self) -> None: + self.closed = True + with self.wait_lock: + self.wait_lock.notify_all() + + def available(self): + return self.size() - self.__pos + + def mark_supported(self) -> bool: + return True + + def mark(self, read_ahead_limit: int) -> None: + self.__mark = self.__pos + + def reset(self) -> None: + self.__pos = self.__mark + + def pos(self) -> int: + return self.__pos + + def seek(self, where: int, **kwargs) -> None: + if where < 0: + raise TypeError() + if self.closed: + raise IOError("Stream is closed!") + self.__pos = where + self.check_availability(int(self.__pos / (128 * 1024)), False, False) + + def skip(self, n: int) -> int: + if n < 0: + raise TypeError() + if self.closed: + raise IOError("Stream is closed!") + k = self.size() - self.__pos + if n < k: + k = n + self.__pos += k + chunk = int(self.__pos / (128 * 1024)) + self.check_availability(chunk, False, False) + return k + + def requested_chunks(self) -> typing.List[bool]: + raise NotImplementedError() + + def available_chunks(self) -> typing.List[bool]: + raise NotImplementedError() + + def chunks(self) -> int: + raise NotImplementedError() + + def request_chunk_from_stream(self, index: int) -> None: + raise NotImplementedError() + + def should_retry(self, chunk: int) -> bool: + if self.retries[chunk] < 1: + return True + if self.retries[chunk] > self.max_chunk_tries: + return False + return self.retry_on_chunk_error + + def check_availability(self, chunk: int, wait: bool, halted: bool) -> None: + if halted and not wait: + raise TypeError() + if not self.requested_chunks()[chunk]: + self.request_chunk_from_stream(chunk) + self.requested_chunks()[chunk] = True + for i in range(chunk + 1, + min(self.chunks() - 1, chunk + self.preload_ahead) + 1): + if (self.requested_chunks()[i] + and self.retries[i] < self.preload_chunk_retries): + self.request_chunk_from_stream(i) + self.requested_chunks()[chunk] = True + if wait: + if self.available_chunks()[chunk]: + return + retry = False + with self.wait_lock: + if not halted: + self.stream_read_halted(chunk, int(time.time() * 1000)) + self.chunk_exception = None + self.wait_for_chunk = chunk + self.wait_lock.wait_for(lambda: self.available_chunks()[chunk]) + if self.closed: + return + if self.chunk_exception is not None: + if self.should_retry(chunk): + retry = True + else: + raise AbsChunkedInputStream.ChunkException + if not retry: + self.stream_read_halted(chunk, int(time.time() * 1000)) + if retry: + time.sleep(math.log10(self.retries[chunk])) + self.check_availability(chunk, True, True) + + def read(self, __size: int = 0) -> bytes: + if self.closed: + raise IOError("Stream is closed!") + if __size <= 0: + if self.__pos == self.size(): + return b"" + buffer = io.BytesIO() + total_size = self.size() + chunk = int(self.__pos / (128 * 1024)) + chunk_off = int(self.__pos % (128 * 1024)) + chunk_total = int(math.ceil(total_size / (128 * 1024))) + self.check_availability(chunk, True, False) + buffer.write(self.buffer()[chunk][chunk_off:]) + chunk += 1 + if chunk != chunk_total: + while chunk <= chunk_total - 1: + self.check_availability(chunk, True, False) + buffer.write(self.buffer()[chunk]) + chunk += 1 + buffer.seek(0) + self.__pos += buffer.getbuffer().nbytes + return buffer.read() + buffer = io.BytesIO() + chunk = int(self.__pos / (128 * 1024)) + chunk_off = int(self.__pos % (128 * 1024)) + chunk_end = int(__size / (128 * 1024)) + chunk_end_off = int(__size % (128 * 1024)) + if chunk_end > self.size(): + chunk_end = int(self.size() / (128 * 1024)) + chunk_end_off = int(self.size() % (128 * 1024)) + self.check_availability(chunk, True, False) + if chunk_off + __size > len(self.buffer()[chunk]): + buffer.write(self.buffer()[chunk][chunk_off:]) + chunk += 1 + while chunk <= chunk_end: + self.check_availability(chunk, True, False) + if chunk == chunk_end: + buffer.write(self.buffer()[chunk][:chunk_end_off]) + else: + buffer.write(self.buffer()[chunk]) + chunk += 1 + else: + buffer.write(self.buffer()[chunk][chunk_off:chunk_off + __size]) + buffer.seek(0) + self.__pos += buffer.getbuffer().nbytes + return buffer.read() + + def notify_chunk_available(self, index: int) -> None: + self.available_chunks()[index] = True + self.__decoded_length += len(self.buffer()[index]) + with self.wait_lock: + if index == self.wait_for_chunk and not self.closed: + self.wait_for_chunk = -1 + self.wait_lock.notify_all() + + def notify_chunk_error(self, index: int, ex): + self.available_chunks()[index] = False + self.requested_chunks()[index] = False + self.retries[index] += 1 + with self.wait_lock: + if index == self.wait_for_chunk and not self.closed: + self.chunk_exception = ex + self.wait_for_chunk = -1 + self.wait_lock.notify_all() + + def decoded_length(self): + return self.__decoded_length + + class ChunkException(IOError): + + @staticmethod + def from_stream_error(stream_error: int): + return AbsChunkedInputStream \ + .ChunkException("Failed due to stream error, code: {}".format(stream_error)) + + +class AudioKeyManager(PacketsReceiver, Closeable): + audio_key_request_timeout = 20 + logger = logging.getLogger("Librespot:AudioKeyManager") + __callbacks: typing.Dict[int, Callback] = {} + __seq_holder = 0 + __seq_holder_lock = threading.Condition() + __session: Session + __zero_short = b"\x00\x00" + + def __init__(self, session: Session): + self.__session = session + + def dispatch(self, packet: Packet) -> None: + payload = io.BytesIO(packet.payload) + seq = struct.unpack(">i", payload.read(4))[0] + callback = self.__callbacks.get(seq) + if callback is None: + self.logger.warning( + "Couldn't find callback for seq: {}".format(seq)) + return + if packet.is_cmd(Packet.Type.aes_key): + key = payload.read(16) + callback.key(key) + elif packet.is_cmd(Packet.Type.aes_key_error): + code = struct.unpack(">H", payload.read(2))[0] + callback.error(code) + else: + self.logger.warning( + "Couldn't handle packet, cmd: {}, length: {}".format( + packet.cmd, len(packet.payload))) + + def get_audio_key( + self, + gid: bytes, + file_id: bytes, + retry: bool = True, + ) -> bytes: + """Retrieve an audio key via SpotiClub API or fall back to Spotify.""" + + if self._spoticlub_available(): + try: + return self._get_audio_key_via_spoticlub(gid, file_id, retry) + except Exception as exc: # noqa: BLE001 + self.logger.warning( + "SpotiClub API failed for gid=%s file_id=%s: %s", + util.bytes_to_hex(gid), + util.bytes_to_hex(file_id), + exc, + ) + if not SPOTICLUB_FALLBACK_TO_SPOTIFY: + raise + self.logger.info("Falling back to Spotify audio-key pipeline") + + return self._get_audio_key_via_spotify(gid, file_id, retry) + + def _spoticlub_available(self) -> bool: + if SPOTICLUB_DISABLE or not server_url: + return False + return self._ensure_spoticlub_credentials() + + def _ensure_spoticlub_credentials(self) -> bool: + global spoticlub_user, spoticlub_password + if spoticlub_user and spoticlub_password: + return True + + try: + cfg_path = Path.home() / "AppData\\Roaming\\Zotify\\spoticlub_credentials.json" + print(f"\n[SpotiClub API] Looking for credentials file at: {cfg_path}") + if cfg_path.is_file(): + print("[SpotiClub API] Found credentials file") + with open(cfg_path, "r", encoding="utf-8") as f: + cfg = json.load(f) + spoticlub_user = spoticlub_user or cfg.get("spoticlub_user") + spoticlub_password = spoticlub_password or cfg.get("spoticlub_password") + else: + print( + "[SpotiClub API] Credentials file NOT found at: %s. Will proceed with hardcoded credentials if any.\n" + % cfg_path + ) + except Exception as exc: # noqa: BLE001 + print(f"[SpotiClub API] Error while loading credentials file: {exc}\n") + + has_credentials = bool(spoticlub_user and spoticlub_password) + if not has_credentials: + msg = ( + "Missing SpotiClub credentials: please set spoticlub_user & spoticlub_password inside the top of the __init__.py file," + " or use the spoticlub_credentials.json in your Zotify config folder [C:\\Users\\USERNAME\\AppData\\Roaming\\Zotify\\]." + ) + if SPOTICLUB_FALLBACK_TO_SPOTIFY: + self.logger.warning("%s Falling back to Spotify audio keys.", msg) + return False + print(f"[SpotiClub API][FATAL] {msg}") + raise SystemExit(1) + return True + + def _get_audio_key_via_spoticlub(self, gid: bytes, file_id: bytes, retry: bool) -> bytes: + global spoticlub_user, spoticlub_password + + payload = { + "gid": util.bytes_to_hex(gid), + "file_id": util.bytes_to_hex(file_id), + "ftpUser": spoticlub_user, + "password": spoticlub_password, + } + + if not server_url: + msg = ( + "The SpotiClub server_url is not set! It should be defined at the top of __init__.py or via SPOTICLUB_SERVER_URL." + ) + print(f"[SpotiClub API][FATAL] {msg}") + raise SystemExit(1) + + print(f"[SpotiClub API] Loaded credentials - Welcome {spoticlub_user}\n") + + tries = 0 + last_err: typing.Optional[Exception] = None + + while True: + tries += 1 + try: + resp = requests.post( + server_url, + json=payload, + timeout=AudioKeyManager.audio_key_request_timeout, + ) + if resp.status_code != 200: + raise RuntimeError( + f"[SpotiClub API] Unexpected response {resp.status_code}: {resp.text}" + ) + data = resp.json() + key_hex = data.get("key") + if not isinstance(key_hex, str): + raise RuntimeError("[SpotiClub API] Response missing 'key'") + key_bytes = util.hex_to_bytes(key_hex) + if len(key_bytes) != 16: + raise RuntimeError("[SpotiClub API] Audio key must be 16 bytes long") + return key_bytes + except Exception as exc: # noqa: BLE001 + last_err = exc + self.logger.warning( + "[SpotiClub API] Retrying... (try %d/%d): %s", + tries, + 3, + exc, + ) + if not retry or tries >= 3: + break + time.sleep(5) + + raise RuntimeError( + "Failed fetching Audio Key from API for gid: {}, fileId: {} (last error: {})".format( + util.bytes_to_hex(gid), util.bytes_to_hex(file_id), last_err + ) + ) + + def _get_audio_key_via_spotify(self, gid: bytes, file_id: bytes, retry: bool) -> bytes: + callback = AudioKeyManager.SyncCallback(self) + seq = self._next_sequence() + self.__callbacks[seq] = callback + try: + self._send_audio_key_request(seq, gid, file_id) + key = callback.wait_response() + finally: + self.__callbacks.pop(seq, None) + + if key is None: + if retry: + self.logger.warning( + "Spotify audio key request returned no data for gid=%s file_id=%s; retrying once", + util.bytes_to_hex(gid), + util.bytes_to_hex(file_id), + ) + time.sleep(0.5) + return self._get_audio_key_via_spotify(gid, file_id, False) + raise RuntimeError( + "Failed retrieving audio key from Spotify for gid: {}, fileId: {}".format( + util.bytes_to_hex(gid), util.bytes_to_hex(file_id) + ) + ) + return key + + def _send_audio_key_request(self, seq: int, gid: bytes, file_id: bytes) -> None: + buffer = io.BytesIO() + buffer.write(struct.pack(">i", seq)) + buffer.write(gid) + buffer.write(self.__zero_short) + buffer.write(file_id) + buffer.write(self.__zero_short) + self.__session.send(Packet.Type.aes_key, buffer.getvalue()) + + def _next_sequence(self) -> int: + with self.__seq_holder_lock: + self.__seq_holder = (self.__seq_holder + 1) & 0x7FFFFFFF + if self.__seq_holder == 0: + self.__seq_holder = 1 + return self.__seq_holder + + class Callback: + + def key(self, key: bytes) -> None: + raise NotImplementedError + + def error(self, code: int) -> None: + raise NotImplementedError + + class SyncCallback(Callback): + __audio_key_manager: AudioKeyManager + __reference = queue.Queue() + __reference_lock = threading.Condition() + + def __init__(self, audio_key_manager: AudioKeyManager): + self.__audio_key_manager = audio_key_manager + + def key(self, key: bytes) -> None: + with self.__reference_lock: + self.__reference.put(key) + self.__reference_lock.notify_all() + + def error(self, code: int) -> None: + self.__audio_key_manager.logger.fatal( + "Audio key error, code: {}".format(code)) + with self.__reference_lock: + self.__reference.put(None) + self.__reference_lock.notify_all() + + def wait_response(self) -> typing.Optional[bytes]: + with self.__reference_lock: + self.__reference_lock.wait( + AudioKeyManager.audio_key_request_timeout) + try: + return self.__reference.get(block=False) + except queue.Empty: + return None + + +class CdnFeedHelper: + _LOGGER: logging = logging.getLogger(__name__) + + @staticmethod + def get_url(resp: StorageResolve.StorageResolveResponse) -> str: + selected_url = random.choice(resp.cdnurl) + while "audio4-gm-fb" in selected_url or "audio-gm-fb" in selected_url: + selected_url = random.choice(resp.cdnurl) + return selected_url + + @staticmethod + def load_track( + session: Session, track: Metadata.Track, file: Metadata.AudioFile, + resp_or_url: typing.Union[StorageResolve.StorageResolveResponse, + str], preload: bool, + halt_listener: HaltListener) -> PlayableContentFeeder.LoadedStream: + if type(resp_or_url) is str: + url = resp_or_url + else: + url = CdnFeedHelper.get_url(resp_or_url) + start = int(time.time() * 1000) + key = session.audio_key().get_audio_key(track.gid, file.file_id) + audio_key_time = int(time.time() * 1000) - start + + streamer = session.cdn().stream_file(file, key, url, halt_listener) + input_stream = streamer.stream() + normalization_data = NormalizationData.read(input_stream) + if input_stream.skip(0xA7) != 0xA7: + raise IOError("Couldn't skip 0xa7 bytes!") + return PlayableContentFeeder.LoadedStream( + track, + streamer, + normalization_data, + PlayableContentFeeder.Metrics(file.file_id, preload, + -1 if preload else audio_key_time), + ) + + @staticmethod + def load_episode_external( + session: Session, episode: Metadata.Episode, + halt_listener: HaltListener) -> PlayableContentFeeder.LoadedStream: + resp = session.client().head(episode.external_url) + + if resp.status_code != 200: + CdnFeedHelper._LOGGER.warning("Couldn't resolve redirect!") + + url = resp.url + CdnFeedHelper._LOGGER.debug("Fetched external url for {}: {}".format( + util.bytes_to_hex(episode.gid), url)) + + streamer = session.cdn().stream_external_episode( + episode, url, halt_listener) + return PlayableContentFeeder.LoadedStream( + episode, + streamer, + None, + PlayableContentFeeder.Metrics(None, False, -1), + ) + + @staticmethod + def load_episode( + session: Session, + episode: Metadata.Episode, + file: Metadata.AudioFile, + resp_or_url: typing.Union[StorageResolve.StorageResolveResponse, str], + preload: bool, + halt_listener: HaltListener, + ) -> PlayableContentFeeder.LoadedStream: + if type(resp_or_url) is str: + url = resp_or_url + else: + url = CdnFeedHelper.get_url(resp_or_url) + start = int(time.time() * 1000) + key = session.audio_key().get_audio_key(episode.gid, file.file_id) + audio_key_time = int(time.time() * 1000) - start + + streamer = session.cdn().stream_file(file, key, url, halt_listener) + input_stream = streamer.stream() + normalization_data = NormalizationData.read(input_stream) + if input_stream.skip(0xA7) != 0xA7: + raise IOError("Couldn't skip 0xa7 bytes!") + return PlayableContentFeeder.LoadedStream( + episode, + streamer, + normalization_data, + PlayableContentFeeder.Metrics(file.file_id, preload, + -1 if preload else audio_key_time), + ) + + +class CdnManager: + logger: logging = logging.getLogger("Librespot:CdnManager") + __session: Session + + def __init__(self, session: Session): + self.__session = session + + def get_head(self, file_id: bytes): + response = self.__session.client() \ + .get(self.__session.get_user_attribute("head-files-url", "https://heads-fa.spotify.com/head/{file_id}") + .replace("{file_id}", util.bytes_to_hex(file_id))) + if response.status_code != 200: + raise IOError("{}".format(response.status_code)) + body = response.content + if body is None: + raise IOError("Response body is empty!") + return body + + def stream_external_episode(self, episode: Metadata.Episode, + external_url: str, + halt_listener: HaltListener): + return CdnManager.Streamer( + self.__session, + StreamId(episode=episode), + SuperAudioFormat.MP3, + CdnManager.CdnUrl(self, None, external_url), + self.__session.cache(), + NoopAudioDecrypt(), + halt_listener, + ) + + def stream_file(self, file: Metadata.AudioFile, key: bytes, url: str, + halt_listener: HaltListener): + return CdnManager.Streamer( + self.__session, + StreamId(file=file), + SuperAudioFormat.get(file.format), + CdnManager.CdnUrl(self, file.file_id, url), + self.__session.cache(), + AesAudioDecrypt(key), + halt_listener, + ) + + def get_audio_url(self, file_id: bytes): + response = self.__session.api()\ + .send("GET", "/storage-resolve/files/audio/interactive/{}".format(util.bytes_to_hex(file_id)), None, None) + if response.status_code != 200: + raise IOError(response.status_code) + body = response.content + if body is None: + raise IOError("Response body is empty!") + proto = StorageResolve.StorageResolveResponse() + proto.ParseFromString(body) + if proto.result == StorageResolve.StorageResolveResponse.Result.CDN: + url = random.choice(proto.cdnurl) + self.logger.debug("Fetched CDN url for {}: {}".format( + util.bytes_to_hex(file_id), url)) + return url + raise CdnManager.CdnException( + "Could not retrieve CDN url! result: {}".format(proto.result)) + + class CdnException(Exception): + pass + + class InternalResponse: + buffer: bytes + headers: typing.Dict[str, str] + + def __init__(self, buffer: bytes, headers: typing.Dict[str, str]): + self.buffer = buffer + self.headers = headers + + class CdnUrl: + __cdn_manager = None + __file_id: bytes + __expiration: int + url: str + + def __init__(self, cdn_manager, file_id: typing.Union[bytes, None], + url: str): + self.__cdn_manager: CdnManager = cdn_manager + self.__file_id = file_id + self.set_url(url) + + def url(self): + if self.__expiration == -1: + return self.url + if self.__expiration <= int(time.time() * 1000) + 5 * 60 * 1000: + self.url = self.__cdn_manager.get_audio_url(self.__file_id) + return self.url + + def set_url(self, url: str): + self.url = url + if self.__file_id is not None: + token_url = urllib.parse.urlparse(url) + token_query = urllib.parse.parse_qs(token_url.query) + token_list = token_query.get("__token__") + try: + token_str = str(token_list[0]) + except TypeError: + token_str = "" + expires_list = token_query.get("Expires") + try: + expires_str = str(expires_list[0]) + except TypeError: + expires_str = "" + if token_str != "None" and len(token_str) != 0: + expire_at = None + split = token_str.split("~") + for s in split: + try: + i = s.index("=") + except ValueError: + continue + if s[:i] == "exp": + expire_at = int(s[i + 1:]) + break + if expire_at is None: + self.__expiration = -1 + self.__cdn_manager.logger.warning( + "Invalid __token__ in CDN url: {}".format(url)) + return + self.__expiration = expire_at * 1000 + elif expires_str != "None" and len(expires_str) != 0: + expires_at = None + expires_str = expires_str.split("~")[0] + expires_at = int(expires_str) + if expires_at is None: + self.__expiration = -1 + self.__cdn_manager.logger.warning("Invalid Expires param in CDN url: {}".format(url)) + return + self.__expiration = expires_at * 1000 + else: + try: + i = token_url.query.index("_") + except ValueError: + self.__expiration = -1 + self.__cdn_manager.logger \ + .warning("Couldn't extract expiration, invalid parameter in CDN url: {}".format(url)) + return + self.__expiration = int(token_url.query[:i]) * 1000 + + else: + self.__expiration = -1 + + class Streamer(GeneralAudioStream, GeneralWritableStream): + available: typing.List[bool] + buffer: typing.List[bytes] + chunks: int + executor_service = concurrent.futures.ThreadPoolExecutor() + halt_listener: HaltListener + requested: typing.List[bool] + size: int + __audio_format: SuperAudioFormat + __audio_decrypt: AudioDecrypt + __cdn_url: CdnManager.CdnUrl + __internal_stream: InternalStream + __session: Session + __stream_id: StreamId + + def __init__(self, session: Session, stream_id: StreamId, + audio_format: SuperAudioFormat, + cdn_url: CdnManager.CdnUrl, cache: CacheManager, + audio_decrypt: AudioDecrypt, halt_listener: HaltListener): + self.__session = session + self.__stream_id = stream_id + self.__audio_format = audio_format + self.__audio_decrypt = audio_decrypt + self.__cdn_url = cdn_url + self.halt_listener = halt_listener + response = self.request(range_start=0, + range_end=ChannelManager.chunk_size - 1) + content_range = response.headers.get("Content-Range") + if content_range is None: + content_range = response.headers.get("content-range") + if content_range is None: + raise IOError("Missing Content-Range header!") + split = content_range.split("/") + self.size = int(split[1]) + self.chunks = int(math.ceil(self.size / ChannelManager.chunk_size)) + first_chunk = response.buffer + self.available = [False for _ in range(self.chunks)] + self.requested = [False for _ in range(self.chunks)] + self.buffer = [b"" for _ in range(self.chunks)] + self.__internal_stream = CdnManager.Streamer.InternalStream( + self, False) + self.requested[0] = True + self.write_chunk(first_chunk, 0, False) + + def write_chunk(self, chunk: bytes, chunk_index: int, + cached: bool) -> None: + if self.__internal_stream.is_closed(): + return + self.__session.logger.debug( + "Chunk {}/{} completed, cached: {}, stream: {}".format( + chunk_index + 1, self.chunks, cached, self.describe())) + self.buffer[chunk_index] = self.__audio_decrypt.decrypt_chunk( + chunk_index, chunk) + self.__internal_stream.notify_chunk_available(chunk_index) + + def stream(self) -> AbsChunkedInputStream: + return self.__internal_stream + + def codec(self) -> SuperAudioFormat: + return self.__audio_format + + def describe(self) -> str: + if self.__stream_id.is_episode(): + return "episode_gid: {}".format( + self.__stream_id.get_episode_gid()) + return "file_id: {}".format(self.__stream_id.get_file_id()) + + def decrypt_time_ms(self) -> int: + return self.__audio_decrypt.decrypt_time_ms() + + def request_chunk(self, index: int) -> None: + response = self.request(index) + self.write_chunk(response.buffer, index, False) + + def request(self, chunk: int = None, range_start: int = None, range_end: int = None)\ + -> CdnManager.InternalResponse: + if chunk is None and range_start is None and range_end is None: + raise TypeError() + if chunk is not None: + range_start = ChannelManager.chunk_size * chunk + range_end = (chunk + 1) * ChannelManager.chunk_size - 1 + response = self.__session.client().get( + self.__cdn_url.url, + headers={ + "Range": "bytes={}-{}".format(range_start, range_end) + }, + ) + if response.status_code != 206: + raise IOError(response.status_code) + body = response.content + if body is None: + raise IOError("Response body is empty!") + return CdnManager.InternalResponse(body, dict(response.headers)) + + class InternalStream(AbsChunkedInputStream): + streamer: CdnManager.Streamer + + def __init__(self, streamer, retry_on_chunk_error: bool): + self.streamer: CdnManager.Streamer = streamer + super().__init__(retry_on_chunk_error) + + def buffer(self) -> typing.List[bytes]: + return self.streamer.buffer + + def size(self) -> int: + return self.streamer.size + + def close(self) -> None: + super().close() + del self.streamer.buffer + + def requested_chunks(self) -> typing.List[bool]: + return self.streamer.requested + + def available_chunks(self) -> typing.List[bool]: + return self.streamer.available + + def chunks(self) -> int: + return self.streamer.chunks + + def request_chunk_from_stream(self, index: int) -> None: + self.streamer.executor_service \ + .submit(lambda: self.streamer.request_chunk(index)) + + def stream_read_halted(self, chunk: int, _time: int) -> None: + if self.streamer.halt_listener is not None: + self.streamer.executor_service\ + .submit(lambda: self.streamer.halt_listener.stream_read_halted(chunk, _time)) + + def stream_read_resumed(self, chunk: int, _time: int) -> None: + if self.streamer.halt_listener is not None: + self.streamer.executor_service \ + .submit(lambda: self.streamer.halt_listener.stream_read_resumed(chunk, _time)) + + +class NormalizationData: + _LOGGER: logging = logging.getLogger(__name__) + track_gain_db: float + track_peak: float + album_gain_db: float + album_peak: float + + def __init__(self, track_gain_db: float, track_peak: float, + album_gain_db: float, album_peak: float): + self.track_gain_db = track_gain_db + self.track_peak = track_peak + self.album_gain_db = album_gain_db + self.album_peak = album_peak + + self._LOGGER.debug( + "Loaded normalization data, track_gain: {}, track_peak: {}, album_gain: {}, album_peak: {}" + .format(track_gain_db, track_peak, album_gain_db, album_peak)) + + @staticmethod + def read(input_stream: AbsChunkedInputStream) -> NormalizationData: + input_stream.seek(144) + data = input_stream.read(4 * 4) + input_stream.seek(0) + buffer = io.BytesIO(data) + return NormalizationData( + struct.unpack(" float: + normalisation_factor = float( + math.pow(10, (self.track_gain_db + normalisation_pregain) / 20)) + if normalisation_factor * self.track_peak > 1: + self._LOGGER \ + .warning("Reducing normalisation factor to prevent clipping. Please add negative pregain to avoid.") + normalisation_factor = 1 / self.track_peak + return normalisation_factor + + +class PlayableContentFeeder: + logger = logging.getLogger("Librespot:PlayableContentFeeder") + storage_resolve_interactive = "/storage-resolve/files/audio/interactive/{}" + storage_resolve_interactive_prefetch = "/storage-resolve/files/audio/interactive_prefetch/{}" + __session: Session + + def __init__(self, session: Session): + self.__session = session + + def load(self, playable_id: PlayableId, + audio_quality_picker: AudioQualityPicker, preload: bool, + halt_listener: typing.Union[HaltListener, None]): + if type(playable_id) is TrackId: + return self.load_track(playable_id, audio_quality_picker, preload, + halt_listener) + if type(playable_id) is EpisodeId: + return self.load_episode(playable_id, audio_quality_picker, + preload, halt_listener) + raise TypeError("Unknown content: {}".format(playable_id)) + + def load_stream(self, file: Metadata.AudioFile, track: Metadata.Track, + episode: Metadata.Episode, preload: bool, + halt_lister: HaltListener): + if track is None and episode is None: + raise RuntimeError() + response = self.resolve_storage_interactive(file.file_id, preload) + if response.result == StorageResolve.StorageResolveResponse.Result.CDN: + if track is not None: + return CdnFeedHelper.load_track(self.__session, track, file, + response, preload, halt_lister) + return CdnFeedHelper.load_episode(self.__session, episode, file, + response, preload, halt_lister) + if response.result == StorageResolve.StorageResolveResponse.Result.STORAGE: + if track is None: + pass + elif response.result == StorageResolve.StorageResolveResponse.Result.RESTRICTED: + raise RuntimeError("Content is restricted!") + elif response.result == StorageResolve.StorageResolveResponse.Response.UNRECOGNIZED: + raise RuntimeError("Content is unrecognized!") + else: + raise RuntimeError("Unknown result: {}".format(response.result)) + + def load_episode(self, episode_id: EpisodeId, + audio_quality_picker: AudioQualityPicker, preload: bool, + halt_listener: HaltListener) -> "LoadedStream": + episode = self.__session.api().get_metadata_4_episode(episode_id) + if episode.external_url: + return CdnFeedHelper.load_episode_external(self.__session, episode, + halt_listener) + file = audio_quality_picker.get_file(episode.audio) + if file is None: + self.logger.fatal( + "Couldn't find any suitable audio file, available: {}".format( + episode.audio)) + return self.load_stream(file, None, episode, preload, halt_listener) + + def load_track(self, track_id_or_track: typing.Union[TrackId, + Metadata.Track], + audio_quality_picker: AudioQualityPicker, preload: bool, + halt_listener: HaltListener): + if isinstance(track_id_or_track, TrackId): + track_id = track_id_or_track + original = self.__session.api().get_metadata_4_track(track_id) + + if len(original.file) == 0: + self._populate_track_files_from_extended_metadata(track_id, original) + + if len(original.file) == 0: + for alt in original.alternative: + if len(alt.file) > 0 or not alt.gid: + continue + gid_hex = util.bytes_to_hex(alt.gid) + if len(gid_hex) != 32: + continue + try: + alt_track_id = TrackId.from_hex(gid_hex) + except Exception: + continue + self._populate_track_files_from_extended_metadata(alt_track_id, alt) + + track = self.pick_alternative_if_necessary(original) + if track is None: + raise RuntimeError("Cannot get alternative track") + else: + track = track_id_or_track + try: + gid_hex = util.bytes_to_hex(track.gid) + input_track_id = TrackId.from_hex(gid_hex) if len(gid_hex) == 32 else None + except Exception: + input_track_id = None + if input_track_id is not None and len(track.file) == 0: + self._populate_track_files_from_extended_metadata(input_track_id, track) + file = audio_quality_picker.get_file(track.file) + if file is None: + self.logger.fatal( + "Couldn't find any suitable audio file, available: {}".format( + track.file)) + raise FeederException() + return self.load_stream(file, track, None, preload, halt_listener) + + def pick_alternative_if_necessary( + self, track: Metadata.Track) -> typing.Union[Metadata.Track, None]: + if len(track.file) > 0: + return track + for alt in track.alternative: + if len(alt.file) > 0: + return Metadata.Track( + gid=track.gid, + name=track.name, + album=track.album, + artist=track.artist, + number=track.number, + disc_number=track.disc_number, + duration=track.duration, + popularity=track.popularity, + explicit=track.explicit, + external_id=track.external_id, + restriction=track.restriction, + file=alt.file, + sale_period=track.sale_period, + preview=track.preview, + tags=track.tags, + earliest_live_timestamp=track.earliest_live_timestamp, + has_lyrics=track.has_lyrics, + availability=track.availability, + licensor=track.licensor) + return None + + def _populate_track_files_from_extended_metadata( + self, track_id: TrackId, track_proto: Metadata.Track) -> bool: + if len(track_proto.file) > 0: + return True + try: + extension = self.__session.api().get_audio_files_extension(track_id) + except Exception as exc: # pragma: no cover - network errors handled elsewhere + self.logger.debug( + "Extended metadata lookup failed for %s: %s", + track_id.to_spotify_uri(), + exc, + ) + return False + if extension is None or len(extension.files) == 0: + return len(track_proto.file) > 0 + + existing_ids = {util.bytes_to_hex(audio.file_id) for audio in track_proto.file} + added_count = 0 + + for ext_file in extension.files: + if not ext_file.HasField("file"): + continue + file_id_bytes = ext_file.file.file_id + file_id_hex = util.bytes_to_hex(file_id_bytes) + if file_id_hex in existing_ids: + continue + track_proto.file.add().CopyFrom(ext_file.file) + existing_ids.add(file_id_hex) + added_count += 1 + + if added_count: + self.logger.debug( + "Enriched %s with %d file(s) from extended metadata", + track_id.to_spotify_uri(), + added_count, + ) + + return len(track_proto.file) > 0 + + def resolve_storage_interactive( + self, file_id: bytes, + preload: bool) -> StorageResolve.StorageResolveResponse: + resp = self.__session.api().send( + "GET", + (self.storage_resolve_interactive_prefetch + if preload else self.storage_resolve_interactive).format( + util.bytes_to_hex(file_id)), + None, + None, + ) + if resp.status_code != 200: + raise RuntimeError(resp.status_code) + body = resp.content + if body is None: + raise RuntimeError("Response body is empty!") + storage_resolve_response = StorageResolve.StorageResolveResponse() + storage_resolve_response.ParseFromString(body) + return storage_resolve_response + + class LoadedStream: + episode: Metadata.Episode + track: Metadata.Track + input_stream: GeneralAudioStream + normalization_data: NormalizationData + metrics: PlayableContentFeeder.Metrics + + def __init__(self, track_or_episode: typing.Union[Metadata.Track, + Metadata.Episode], + input_stream: GeneralAudioStream, + normalization_data: typing.Union[NormalizationData, None], + metrics: PlayableContentFeeder.Metrics): + if type(track_or_episode) is Metadata.Track: + self.track = track_or_episode + self.episode = None + elif type(track_or_episode) is Metadata.Episode: + self.track = None + self.episode = track_or_episode + else: + raise TypeError() + self.input_stream = input_stream + self.normalization_data = normalization_data + self.metrics = metrics + + class Metrics: + file_id: str + preloaded_audio_key: bool + audio_key_time: int + + def __init__(self, file_id: typing.Union[bytes, None], + preloaded_audio_key: bool, audio_key_time: int): + self.file_id = None if file_id is None else util.bytes_to_hex( + file_id) + self.preloaded_audio_key = preloaded_audio_key + self.audio_key_time = audio_key_time + if preloaded_audio_key and audio_key_time != -1: + raise RuntimeError() + + +class StreamId: + file_id: bytes + episode_gid: bytes + + def __init__(self, + file: Metadata.AudioFile = None, + episode: Metadata.Episode = None): + if file is None and episode is None: + return + self.file_id = None if file is None else file.file_id + self.episode_gid = None if episode is None else episode.gid + + def get_file_id(self): + if self.file_id is None: + raise RuntimeError("Not a file!") + return util.bytes_to_hex(self.file_id) + + def is_episode(self): + return self.episode_gid is not None + + def get_episode_gid(self): + if self.episode_gid is None: + raise RuntimeError("Not an episode!") + return util.bytes_to_hex(self.episode_gid) diff --git a/librespot/audio/__init__old.py b/librespot/audio/__init__old.py new file mode 100644 index 0000000..5946f14 --- /dev/null +++ b/librespot/audio/__init__old.py @@ -0,0 +1,1033 @@ +from __future__ import annotations +from librespot import util +from librespot.audio.decrypt import AesAudioDecrypt +from librespot.audio.format import SuperAudioFormat +from librespot.audio.storage import ChannelManager +from librespot.cache import CacheManager +from librespot.crypto import Packet +from librespot.metadata import EpisodeId, PlayableId, TrackId +from librespot.proto import Metadata_pb2 as Metadata, StorageResolve_pb2 as StorageResolve +from librespot.structure import AudioDecrypt, AudioQualityPicker, Closeable, FeederException, GeneralAudioStream, GeneralWritableStream, HaltListener, NoopAudioDecrypt, PacketsReceiver +import concurrent.futures +import io +import logging +import math +import queue +import random +import struct +import threading +import time +import typing +import urllib.parse +import os +import json +from pathlib import Path +import requests + +if typing.TYPE_CHECKING: + from librespot.core import Session + + +class AbsChunkedInputStream(io.BytesIO, HaltListener): + chunk_exception = None + closed = False + max_chunk_tries = 128 + preload_ahead = 3 + preload_chunk_retries = 2 + retries: typing.List[int] + retry_on_chunk_error: bool + wait_lock: threading.Condition = threading.Condition() + wait_for_chunk = -1 + __decoded_length = 0 + __mark = 0 + __pos = 0 + + def __init__(self, retry_on_chunk_error: bool): + super().__init__() + self.retries = [0] * self.chunks() + self.retry_on_chunk_error = retry_on_chunk_error + + def is_closed(self) -> bool: + return self.closed + + def buffer(self) -> typing.List[bytes]: + raise NotImplementedError() + + def size(self) -> int: + raise NotImplementedError() + + def close(self) -> None: + self.closed = True + with self.wait_lock: + self.wait_lock.notify_all() + + def available(self): + return self.size() - self.__pos + + def mark_supported(self) -> bool: + return True + + def mark(self, read_ahead_limit: int) -> None: + self.__mark = self.__pos + + def reset(self) -> None: + self.__pos = self.__mark + + def pos(self) -> int: + return self.__pos + + def seek(self, where: int, **kwargs) -> None: + if where < 0: + raise TypeError() + if self.closed: + raise IOError("Stream is closed!") + self.__pos = where + self.check_availability(int(self.__pos / (128 * 1024)), False, False) + + def skip(self, n: int) -> int: + if n < 0: + raise TypeError() + if self.closed: + raise IOError("Stream is closed!") + k = self.size() - self.__pos + if n < k: + k = n + self.__pos += k + chunk = int(self.__pos / (128 * 1024)) + self.check_availability(chunk, False, False) + return k + + def requested_chunks(self) -> typing.List[bool]: + raise NotImplementedError() + + def available_chunks(self) -> typing.List[bool]: + raise NotImplementedError() + + def chunks(self) -> int: + raise NotImplementedError() + + def request_chunk_from_stream(self, index: int) -> None: + raise NotImplementedError() + + def should_retry(self, chunk: int) -> bool: + if self.retries[chunk] < 1: + return True + if self.retries[chunk] > self.max_chunk_tries: + return False + return self.retry_on_chunk_error + + def check_availability(self, chunk: int, wait: bool, halted: bool) -> None: + if halted and not wait: + raise TypeError() + if not self.requested_chunks()[chunk]: + self.request_chunk_from_stream(chunk) + self.requested_chunks()[chunk] = True + for i in range(chunk + 1, + min(self.chunks() - 1, chunk + self.preload_ahead) + 1): + if (self.requested_chunks()[i] + and self.retries[i] < self.preload_chunk_retries): + self.request_chunk_from_stream(i) + self.requested_chunks()[chunk] = True + if wait: + if self.available_chunks()[chunk]: + return + retry = False + with self.wait_lock: + if not halted: + self.stream_read_halted(chunk, int(time.time() * 1000)) + self.chunk_exception = None + self.wait_for_chunk = chunk + self.wait_lock.wait_for(lambda: self.available_chunks()[chunk]) + if self.closed: + return + if self.chunk_exception is not None: + if self.should_retry(chunk): + retry = True + else: + raise AbsChunkedInputStream.ChunkException + if not retry: + self.stream_read_halted(chunk, int(time.time() * 1000)) + if retry: + time.sleep(math.log10(self.retries[chunk])) + self.check_availability(chunk, True, True) + + def read(self, __size: int = 0) -> bytes: + if self.closed: + raise IOError("Stream is closed!") + if __size <= 0: + if self.__pos == self.size(): + return b"" + buffer = io.BytesIO() + total_size = self.size() + chunk = int(self.__pos / (128 * 1024)) + chunk_off = int(self.__pos % (128 * 1024)) + chunk_total = int(math.ceil(total_size / (128 * 1024))) + self.check_availability(chunk, True, False) + buffer.write(self.buffer()[chunk][chunk_off:]) + chunk += 1 + if chunk != chunk_total: + while chunk <= chunk_total - 1: + self.check_availability(chunk, True, False) + buffer.write(self.buffer()[chunk]) + chunk += 1 + buffer.seek(0) + self.__pos += buffer.getbuffer().nbytes + return buffer.read() + buffer = io.BytesIO() + chunk = int(self.__pos / (128 * 1024)) + chunk_off = int(self.__pos % (128 * 1024)) + chunk_end = int(__size / (128 * 1024)) + chunk_end_off = int(__size % (128 * 1024)) + if chunk_end > self.size(): + chunk_end = int(self.size() / (128 * 1024)) + chunk_end_off = int(self.size() % (128 * 1024)) + self.check_availability(chunk, True, False) + if chunk_off + __size > len(self.buffer()[chunk]): + buffer.write(self.buffer()[chunk][chunk_off:]) + chunk += 1 + while chunk <= chunk_end: + self.check_availability(chunk, True, False) + if chunk == chunk_end: + buffer.write(self.buffer()[chunk][:chunk_end_off]) + else: + buffer.write(self.buffer()[chunk]) + chunk += 1 + else: + buffer.write(self.buffer()[chunk][chunk_off:chunk_off + __size]) + buffer.seek(0) + self.__pos += buffer.getbuffer().nbytes + return buffer.read() + + def notify_chunk_available(self, index: int) -> None: + self.available_chunks()[index] = True + self.__decoded_length += len(self.buffer()[index]) + with self.wait_lock: + if index == self.wait_for_chunk and not self.closed: + self.wait_for_chunk = -1 + self.wait_lock.notify_all() + + def notify_chunk_error(self, index: int, ex): + self.available_chunks()[index] = False + self.requested_chunks()[index] = False + self.retries[index] += 1 + with self.wait_lock: + if index == self.wait_for_chunk and not self.closed: + self.chunk_exception = ex + self.wait_for_chunk = -1 + self.wait_lock.notify_all() + + def decoded_length(self): + return self.__decoded_length + + class ChunkException(IOError): + + @staticmethod + def from_stream_error(stream_error: int): + return AbsChunkedInputStream \ + .ChunkException("Failed due to stream error, code: {}".format(stream_error)) + + +class AudioKeyManager(PacketsReceiver, Closeable): + audio_key_request_timeout = 20 + logger = logging.getLogger("Librespot:AudioKeyManager") + __callbacks: typing.Dict[int, Callback] = {} + __seq_holder = 0 + __seq_holder_lock = threading.Condition() + __session: Session + __zero_short = b"\x00\x00" + + def __init__(self, session: Session): + self.__session = session + + def dispatch(self, packet: Packet) -> None: + payload = io.BytesIO(packet.payload) + seq = struct.unpack(">i", payload.read(4))[0] + callback = self.__callbacks.get(seq) + if callback is None: + self.logger.warning( + "Couldn't find callback for seq: {}".format(seq)) + return + if packet.is_cmd(Packet.Type.aes_key): + key = payload.read(16) + callback.key(key) + elif packet.is_cmd(Packet.Type.aes_key_error): + code = struct.unpack(">H", payload.read(2))[0] + callback.error(code) + else: + self.logger.warning( + "Couldn't handle packet, cmd: {}, length: {}".format( + packet.cmd, len(packet.payload))) + + def get_audio_key(self, + gid: bytes, + file_id: bytes, + retry: bool = True) -> bytes: + """Retrieve audio key from external Audio Key server instead of Spotify directly. + + The server endpoint and behaviour are configured via environment variables: + + AUDIO_KEY_SERVER_URL (default: http://127.0.0.1:8765/get_key) + + The request payload is: + {"gid": "", "file_id": ""} + + and the expected response is: + {"key": ""} + """ + server_url = os.getenv("AUDIO_KEY_SERVER_URL", "http://127.0.0.1:8765/get_key") + + # SpotiClub client credentials used for authenticating against the audio key server. + # These can be provided via environment variables or a small JSON file next to the + # Zotify project root, `spoticlub_api.json`, with the structure: + # {"ftpUser": "spoticlub-...", "password": "..."} + ftp_user = "" + ftp_password = "" + + if not ftp_user or not ftp_password: + try: + cfg_path = Path.cwd() / "spoticlub_api.json" + if cfg_path.is_file(): + with open(cfg_path, "r", encoding="utf-8") as f: + cfg = json.load(f) + ftp_user = ftp_user or cfg.get("ftpUser") + ftp_password = ftp_password or cfg.get("password") + except Exception: + # If loading fails we simply fall back to env-only behaviour. + pass + + if not ftp_user or not ftp_password: + raise RuntimeError( + "Missing SpotiClub credentials: please set SPOTICLUB_FTP_USER/SPOTICLUB_FTP_PASSWORD " + "or create spoticlub_client.json with ftpUser/password." + ) + + payload = { + "gid": util.bytes_to_hex(gid), + "file_id": util.bytes_to_hex(file_id), + "ftpUser": ftp_user, + "password": ftp_password, + } + + tries = 0 + last_err: typing.Optional[Exception] = None + + while True: + tries += 1 + try: + resp = requests.post(server_url, json=payload, timeout=AudioKeyManager.audio_key_request_timeout) + if resp.status_code != 200: + raise RuntimeError(f"Audio key server returned {resp.status_code}: {resp.text}") + data = resp.json() + key_hex = data.get("key") + if not isinstance(key_hex, str): + raise RuntimeError("Audio key server response missing 'key'") + key_bytes = util.hex_to_bytes(key_hex) + if len(key_bytes) != 16: + raise RuntimeError("Audio key must be 16 bytes long") + return key_bytes + except Exception as exc: # noqa: BLE001 + last_err = exc + self.logger.warning("Audio key server error (try %d): %s", tries, exc) + if not retry or tries >= 3: + break + time.sleep(5) + + raise RuntimeError( + "Failed fetching audio key from server for gid: {}, fileId: {} (last error: {})".format( + util.bytes_to_hex(gid), util.bytes_to_hex(file_id), last_err)) + + class Callback: + + def key(self, key: bytes) -> None: + raise NotImplementedError + + def error(self, code: int) -> None: + raise NotImplementedError + + class SyncCallback(Callback): + __audio_key_manager: AudioKeyManager + __reference = queue.Queue() + __reference_lock = threading.Condition() + + def __init__(self, audio_key_manager: AudioKeyManager): + self.__audio_key_manager = audio_key_manager + + def key(self, key: bytes) -> None: + with self.__reference_lock: + self.__reference.put(key) + self.__reference_lock.notify_all() + + def error(self, code: int) -> None: + self.__audio_key_manager.logger.fatal( + "Audio key error, code: {}".format(code)) + with self.__reference_lock: + self.__reference.put(None) + self.__reference_lock.notify_all() + + def wait_response(self) -> bytes: + with self.__reference_lock: + self.__reference_lock.wait( + AudioKeyManager.audio_key_request_timeout) + return self.__reference.get(block=False) + + +class CdnFeedHelper: + _LOGGER: logging = logging.getLogger(__name__) + + @staticmethod + def get_url(resp: StorageResolve.StorageResolveResponse) -> str: + selected_url = random.choice(resp.cdnurl) + while "audio4-gm-fb" in selected_url or "audio-gm-fb" in selected_url: + selected_url = random.choice(resp.cdnurl) + return selected_url + + @staticmethod + def load_track( + session: Session, track: Metadata.Track, file: Metadata.AudioFile, + resp_or_url: typing.Union[StorageResolve.StorageResolveResponse, + str], preload: bool, + halt_listener: HaltListener) -> PlayableContentFeeder.LoadedStream: + if type(resp_or_url) is str: + url = resp_or_url + else: + url = CdnFeedHelper.get_url(resp_or_url) + start = int(time.time() * 1000) + key = session.audio_key().get_audio_key(track.gid, file.file_id) + audio_key_time = int(time.time() * 1000) - start + + streamer = session.cdn().stream_file(file, key, url, halt_listener) + input_stream = streamer.stream() + normalization_data = NormalizationData.read(input_stream) + if input_stream.skip(0xA7) != 0xA7: + raise IOError("Couldn't skip 0xa7 bytes!") + return PlayableContentFeeder.LoadedStream( + track, + streamer, + normalization_data, + PlayableContentFeeder.Metrics(file.file_id, preload, + -1 if preload else audio_key_time), + ) + + @staticmethod + def load_episode_external( + session: Session, episode: Metadata.Episode, + halt_listener: HaltListener) -> PlayableContentFeeder.LoadedStream: + resp = session.client().head(episode.external_url) + + if resp.status_code != 200: + CdnFeedHelper._LOGGER.warning("Couldn't resolve redirect!") + + url = resp.url + CdnFeedHelper._LOGGER.debug("Fetched external url for {}: {}".format( + util.bytes_to_hex(episode.gid), url)) + + streamer = session.cdn().stream_external_episode( + episode, url, halt_listener) + return PlayableContentFeeder.LoadedStream( + episode, + streamer, + None, + PlayableContentFeeder.Metrics(None, False, -1), + ) + + @staticmethod + def load_episode( + session: Session, + episode: Metadata.Episode, + file: Metadata.AudioFile, + resp_or_url: typing.Union[StorageResolve.StorageResolveResponse, str], + preload: bool, + halt_listener: HaltListener, + ) -> PlayableContentFeeder.LoadedStream: + if type(resp_or_url) is str: + url = resp_or_url + else: + url = CdnFeedHelper.get_url(resp_or_url) + start = int(time.time() * 1000) + key = session.audio_key().get_audio_key(episode.gid, file.file_id) + audio_key_time = int(time.time() * 1000) - start + + streamer = session.cdn().stream_file(file, key, url, halt_listener) + input_stream = streamer.stream() + normalization_data = NormalizationData.read(input_stream) + if input_stream.skip(0xA7) != 0xA7: + raise IOError("Couldn't skip 0xa7 bytes!") + return PlayableContentFeeder.LoadedStream( + episode, + streamer, + normalization_data, + PlayableContentFeeder.Metrics(file.file_id, preload, + -1 if preload else audio_key_time), + ) + + +class CdnManager: + logger: logging = logging.getLogger("Librespot:CdnManager") + __session: Session + + def __init__(self, session: Session): + self.__session = session + + def get_head(self, file_id: bytes): + response = self.__session.client() \ + .get(self.__session.get_user_attribute("head-files-url", "https://heads-fa.spotify.com/head/{file_id}") + .replace("{file_id}", util.bytes_to_hex(file_id))) + if response.status_code != 200: + raise IOError("{}".format(response.status_code)) + body = response.content + if body is None: + raise IOError("Response body is empty!") + return body + + def stream_external_episode(self, episode: Metadata.Episode, + external_url: str, + halt_listener: HaltListener): + return CdnManager.Streamer( + self.__session, + StreamId(episode=episode), + SuperAudioFormat.MP3, + CdnManager.CdnUrl(self, None, external_url), + self.__session.cache(), + NoopAudioDecrypt(), + halt_listener, + ) + + def stream_file(self, file: Metadata.AudioFile, key: bytes, url: str, + halt_listener: HaltListener): + return CdnManager.Streamer( + self.__session, + StreamId(file=file), + SuperAudioFormat.get(file.format), + CdnManager.CdnUrl(self, file.file_id, url), + self.__session.cache(), + AesAudioDecrypt(key), + halt_listener, + ) + + def get_audio_url(self, file_id: bytes): + response = self.__session.api()\ + .send("GET", "/storage-resolve/files/audio/interactive/{}".format(util.bytes_to_hex(file_id)), None, None) + if response.status_code != 200: + raise IOError(response.status_code) + body = response.content + if body is None: + raise IOError("Response body is empty!") + proto = StorageResolve.StorageResolveResponse() + proto.ParseFromString(body) + if proto.result == StorageResolve.StorageResolveResponse.Result.CDN: + url = random.choice(proto.cdnurl) + self.logger.debug("Fetched CDN url for {}: {}".format( + util.bytes_to_hex(file_id), url)) + return url + raise CdnManager.CdnException( + "Could not retrieve CDN url! result: {}".format(proto.result)) + + class CdnException(Exception): + pass + + class InternalResponse: + buffer: bytes + headers: typing.Dict[str, str] + + def __init__(self, buffer: bytes, headers: typing.Dict[str, str]): + self.buffer = buffer + self.headers = headers + + class CdnUrl: + __cdn_manager = None + __file_id: bytes + __expiration: int + url: str + + def __init__(self, cdn_manager, file_id: typing.Union[bytes, None], + url: str): + self.__cdn_manager: CdnManager = cdn_manager + self.__file_id = file_id + self.set_url(url) + + def url(self): + if self.__expiration == -1: + return self.url + if self.__expiration <= int(time.time() * 1000) + 5 * 60 * 1000: + self.url = self.__cdn_manager.get_audio_url(self.__file_id) + return self.url + + def set_url(self, url: str): + self.url = url + if self.__file_id is not None: + token_url = urllib.parse.urlparse(url) + token_query = urllib.parse.parse_qs(token_url.query) + token_list = token_query.get("__token__") + try: + token_str = str(token_list[0]) + except TypeError: + token_str = "" + expires_list = token_query.get("Expires") + try: + expires_str = str(expires_list[0]) + except TypeError: + expires_str = "" + if token_str != "None" and len(token_str) != 0: + expire_at = None + split = token_str.split("~") + for s in split: + try: + i = s.index("=") + except ValueError: + continue + if s[:i] == "exp": + expire_at = int(s[i + 1:]) + break + if expire_at is None: + self.__expiration = -1 + self.__cdn_manager.logger.warning( + "Invalid __token__ in CDN url: {}".format(url)) + return + self.__expiration = expire_at * 1000 + elif expires_str != "None" and len(expires_str) != 0: + expires_at = None + expires_str = expires_str.split("~")[0] + expires_at = int(expires_str) + if expires_at is None: + self.__expiration = -1 + self.__cdn_manager.logger.warning("Invalid Expires param in CDN url: {}".format(url)) + return + self.__expiration = expires_at * 1000 + else: + try: + i = token_url.query.index("_") + except ValueError: + self.__expiration = -1 + self.__cdn_manager.logger \ + .warning("Couldn't extract expiration, invalid parameter in CDN url: {}".format(url)) + return + self.__expiration = int(token_url.query[:i]) * 1000 + + else: + self.__expiration = -1 + + class Streamer(GeneralAudioStream, GeneralWritableStream): + available: typing.List[bool] + buffer: typing.List[bytes] + chunks: int + executor_service = concurrent.futures.ThreadPoolExecutor() + halt_listener: HaltListener + requested: typing.List[bool] + size: int + __audio_format: SuperAudioFormat + __audio_decrypt: AudioDecrypt + __cdn_url: CdnManager.CdnUrl + __internal_stream: InternalStream + __session: Session + __stream_id: StreamId + + def __init__(self, session: Session, stream_id: StreamId, + audio_format: SuperAudioFormat, + cdn_url: CdnManager.CdnUrl, cache: CacheManager, + audio_decrypt: AudioDecrypt, halt_listener: HaltListener): + self.__session = session + self.__stream_id = stream_id + self.__audio_format = audio_format + self.__audio_decrypt = audio_decrypt + self.__cdn_url = cdn_url + self.halt_listener = halt_listener + response = self.request(range_start=0, + range_end=ChannelManager.chunk_size - 1) + content_range = response.headers.get("Content-Range") + if content_range is None: + content_range = response.headers.get("content-range") + if content_range is None: + raise IOError("Missing Content-Range header!") + split = content_range.split("/") + self.size = int(split[1]) + self.chunks = int(math.ceil(self.size / ChannelManager.chunk_size)) + first_chunk = response.buffer + self.available = [False for _ in range(self.chunks)] + self.requested = [False for _ in range(self.chunks)] + self.buffer = [b"" for _ in range(self.chunks)] + self.__internal_stream = CdnManager.Streamer.InternalStream( + self, False) + self.requested[0] = True + self.write_chunk(first_chunk, 0, False) + + def write_chunk(self, chunk: bytes, chunk_index: int, + cached: bool) -> None: + if self.__internal_stream.is_closed(): + return + self.__session.logger.debug( + "Chunk {}/{} completed, cached: {}, stream: {}".format( + chunk_index + 1, self.chunks, cached, self.describe())) + self.buffer[chunk_index] = self.__audio_decrypt.decrypt_chunk( + chunk_index, chunk) + self.__internal_stream.notify_chunk_available(chunk_index) + + def stream(self) -> AbsChunkedInputStream: + return self.__internal_stream + + def codec(self) -> SuperAudioFormat: + return self.__audio_format + + def describe(self) -> str: + if self.__stream_id.is_episode(): + return "episode_gid: {}".format( + self.__stream_id.get_episode_gid()) + return "file_id: {}".format(self.__stream_id.get_file_id()) + + def decrypt_time_ms(self) -> int: + return self.__audio_decrypt.decrypt_time_ms() + + def request_chunk(self, index: int) -> None: + response = self.request(index) + self.write_chunk(response.buffer, index, False) + + def request(self, chunk: int = None, range_start: int = None, range_end: int = None)\ + -> CdnManager.InternalResponse: + if chunk is None and range_start is None and range_end is None: + raise TypeError() + if chunk is not None: + range_start = ChannelManager.chunk_size * chunk + range_end = (chunk + 1) * ChannelManager.chunk_size - 1 + response = self.__session.client().get( + self.__cdn_url.url, + headers={ + "Range": "bytes={}-{}".format(range_start, range_end) + }, + ) + if response.status_code != 206: + raise IOError(response.status_code) + body = response.content + if body is None: + raise IOError("Response body is empty!") + return CdnManager.InternalResponse(body, dict(response.headers)) + + class InternalStream(AbsChunkedInputStream): + streamer: CdnManager.Streamer + + def __init__(self, streamer, retry_on_chunk_error: bool): + self.streamer: CdnManager.Streamer = streamer + super().__init__(retry_on_chunk_error) + + def buffer(self) -> typing.List[bytes]: + return self.streamer.buffer + + def size(self) -> int: + return self.streamer.size + + def close(self) -> None: + super().close() + del self.streamer.buffer + + def requested_chunks(self) -> typing.List[bool]: + return self.streamer.requested + + def available_chunks(self) -> typing.List[bool]: + return self.streamer.available + + def chunks(self) -> int: + return self.streamer.chunks + + def request_chunk_from_stream(self, index: int) -> None: + self.streamer.executor_service \ + .submit(lambda: self.streamer.request_chunk(index)) + + def stream_read_halted(self, chunk: int, _time: int) -> None: + if self.streamer.halt_listener is not None: + self.streamer.executor_service\ + .submit(lambda: self.streamer.halt_listener.stream_read_halted(chunk, _time)) + + def stream_read_resumed(self, chunk: int, _time: int) -> None: + if self.streamer.halt_listener is not None: + self.streamer.executor_service \ + .submit(lambda: self.streamer.halt_listener.stream_read_resumed(chunk, _time)) + + +class NormalizationData: + _LOGGER: logging = logging.getLogger(__name__) + track_gain_db: float + track_peak: float + album_gain_db: float + album_peak: float + + def __init__(self, track_gain_db: float, track_peak: float, + album_gain_db: float, album_peak: float): + self.track_gain_db = track_gain_db + self.track_peak = track_peak + self.album_gain_db = album_gain_db + self.album_peak = album_peak + + self._LOGGER.debug( + "Loaded normalization data, track_gain: {}, track_peak: {}, album_gain: {}, album_peak: {}" + .format(track_gain_db, track_peak, album_gain_db, album_peak)) + + @staticmethod + def read(input_stream: AbsChunkedInputStream) -> NormalizationData: + input_stream.seek(144) + data = input_stream.read(4 * 4) + input_stream.seek(0) + buffer = io.BytesIO(data) + return NormalizationData( + struct.unpack(" float: + normalisation_factor = float( + math.pow(10, (self.track_gain_db + normalisation_pregain) / 20)) + if normalisation_factor * self.track_peak > 1: + self._LOGGER \ + .warning("Reducing normalisation factor to prevent clipping. Please add negative pregain to avoid.") + normalisation_factor = 1 / self.track_peak + return normalisation_factor + + +class PlayableContentFeeder: + logger = logging.getLogger("Librespot:PlayableContentFeeder") + storage_resolve_interactive = "/storage-resolve/files/audio/interactive/{}" + storage_resolve_interactive_prefetch = "/storage-resolve/files/audio/interactive_prefetch/{}" + __session: Session + + def __init__(self, session: Session): + self.__session = session + + def load(self, playable_id: PlayableId, + audio_quality_picker: AudioQualityPicker, preload: bool, + halt_listener: typing.Union[HaltListener, None]): + if type(playable_id) is TrackId: + return self.load_track(playable_id, audio_quality_picker, preload, + halt_listener) + if type(playable_id) is EpisodeId: + return self.load_episode(playable_id, audio_quality_picker, + preload, halt_listener) + raise TypeError("Unknown content: {}".format(playable_id)) + + def load_stream(self, file: Metadata.AudioFile, track: Metadata.Track, + episode: Metadata.Episode, preload: bool, + halt_lister: HaltListener): + if track is None and episode is None: + raise RuntimeError() + response = self.resolve_storage_interactive(file.file_id, preload) + if response.result == StorageResolve.StorageResolveResponse.Result.CDN: + if track is not None: + return CdnFeedHelper.load_track(self.__session, track, file, + response, preload, halt_lister) + return CdnFeedHelper.load_episode(self.__session, episode, file, + response, preload, halt_lister) + if response.result == StorageResolve.StorageResolveResponse.Result.STORAGE: + if track is None: + pass + elif response.result == StorageResolve.StorageResolveResponse.Result.RESTRICTED: + raise RuntimeError("Content is restricted!") + elif response.result == StorageResolve.StorageResolveResponse.Response.UNRECOGNIZED: + raise RuntimeError("Content is unrecognized!") + else: + raise RuntimeError("Unknown result: {}".format(response.result)) + + def load_episode(self, episode_id: EpisodeId, + audio_quality_picker: AudioQualityPicker, preload: bool, + halt_listener: HaltListener) -> LoadedStream: + episode = self.__session.api().get_metadata_4_episode(episode_id) + if episode.external_url: + return CdnFeedHelper.load_episode_external(self.__session, episode, + halt_listener) + file = audio_quality_picker.get_file(episode.audio) + if file is None: + self.logger.fatal( + "Couldn't find any suitable audio file, available: {}".format( + episode.audio)) + return self.load_stream(file, None, episode, preload, halt_listener) + + def load_track(self, track_id_or_track: typing.Union[TrackId, + Metadata.Track], + audio_quality_picker: AudioQualityPicker, preload: bool, + halt_listener: HaltListener): + if isinstance(track_id_or_track, TrackId): + track_id = track_id_or_track + original = self.__session.api().get_metadata_4_track(track_id) + + if len(original.file) == 0: + self._populate_track_files_from_extended_metadata(track_id, original) + + if len(original.file) == 0: + for alt in original.alternative: + if len(alt.file) > 0 or not alt.gid: + continue + gid_hex = util.bytes_to_hex(alt.gid) + if len(gid_hex) != 32: + continue + try: + alt_track_id = TrackId.from_hex(gid_hex) + except Exception: + continue + self._populate_track_files_from_extended_metadata(alt_track_id, alt) + + track = self.pick_alternative_if_necessary(original) + if track is None: + raise RuntimeError("Cannot get alternative track") + else: + track = track_id_or_track + try: + gid_hex = util.bytes_to_hex(track.gid) + input_track_id = TrackId.from_hex(gid_hex) if len(gid_hex) == 32 else None + except Exception: + input_track_id = None + if input_track_id is not None and len(track.file) == 0: + self._populate_track_files_from_extended_metadata(input_track_id, track) + file = audio_quality_picker.get_file(track.file) + if file is None: + self.logger.fatal( + "Couldn't find any suitable audio file, available: {}".format( + track.file)) + raise FeederException() + return self.load_stream(file, track, None, preload, halt_listener) + + def pick_alternative_if_necessary( + self, track: Metadata.Track) -> typing.Union[Metadata.Track, None]: + if len(track.file) > 0: + return track + for alt in track.alternative: + if len(alt.file) > 0: + return Metadata.Track( + gid=track.gid, + name=track.name, + album=track.album, + artist=track.artist, + number=track.number, + disc_number=track.disc_number, + duration=track.duration, + popularity=track.popularity, + explicit=track.explicit, + external_id=track.external_id, + restriction=track.restriction, + file=alt.file, + sale_period=track.sale_period, + preview=track.preview, + tags=track.tags, + earliest_live_timestamp=track.earliest_live_timestamp, + has_lyrics=track.has_lyrics, + availability=track.availability, + licensor=track.licensor) + return None + + def _populate_track_files_from_extended_metadata( + self, track_id: TrackId, track_proto: Metadata.Track) -> bool: + if len(track_proto.file) > 0: + return True + try: + extension = self.__session.api().get_audio_files_extension(track_id) + except Exception as exc: # pragma: no cover - network errors handled elsewhere + self.logger.debug( + "Extended metadata lookup failed for %s: %s", + track_id.to_spotify_uri(), + exc, + ) + return False + if extension is None or len(extension.files) == 0: + return len(track_proto.file) > 0 + + existing_ids = {util.bytes_to_hex(audio.file_id) for audio in track_proto.file} + added_count = 0 + + for ext_file in extension.files: + if not ext_file.HasField("file"): + continue + file_id_bytes = ext_file.file.file_id + file_id_hex = util.bytes_to_hex(file_id_bytes) + if file_id_hex in existing_ids: + continue + track_proto.file.add().CopyFrom(ext_file.file) + existing_ids.add(file_id_hex) + added_count += 1 + + if added_count: + self.logger.debug( + "Enriched %s with %d file(s) from extended metadata", + track_id.to_spotify_uri(), + added_count, + ) + + return len(track_proto.file) > 0 + + def resolve_storage_interactive( + self, file_id: bytes, + preload: bool) -> StorageResolve.StorageResolveResponse: + resp = self.__session.api().send( + "GET", + (self.storage_resolve_interactive_prefetch + if preload else self.storage_resolve_interactive).format( + util.bytes_to_hex(file_id)), + None, + None, + ) + if resp.status_code != 200: + raise RuntimeError(resp.status_code) + body = resp.content + if body is None: + raise RuntimeError("Response body is empty!") + storage_resolve_response = StorageResolve.StorageResolveResponse() + storage_resolve_response.ParseFromString(body) + return storage_resolve_response + + class LoadedStream: + episode: Metadata.Episode + track: Metadata.Track + input_stream: GeneralAudioStream + normalization_data: NormalizationData + metrics: PlayableContentFeeder.Metrics + + def __init__(self, track_or_episode: typing.Union[Metadata.Track, + Metadata.Episode], + input_stream: GeneralAudioStream, + normalization_data: typing.Union[NormalizationData, None], + metrics: PlayableContentFeeder.Metrics): + if type(track_or_episode) is Metadata.Track: + self.track = track_or_episode + self.episode = None + elif type(track_or_episode) is Metadata.Episode: + self.track = None + self.episode = track_or_episode + else: + raise TypeError() + self.input_stream = input_stream + self.normalization_data = normalization_data + self.metrics = metrics + + class Metrics: + file_id: str + preloaded_audio_key: bool + audio_key_time: int + + def __init__(self, file_id: typing.Union[bytes, None], + preloaded_audio_key: bool, audio_key_time: int): + self.file_id = None if file_id is None else util.bytes_to_hex( + file_id) + self.preloaded_audio_key = preloaded_audio_key + self.audio_key_time = audio_key_time + if preloaded_audio_key and audio_key_time != -1: + raise RuntimeError() + + +class StreamId: + file_id: bytes + episode_gid: bytes + + def __init__(self, + file: Metadata.AudioFile = None, + episode: Metadata.Episode = None): + if file is None and episode is None: + return + self.file_id = None if file is None else file.file_id + self.episode_gid = None if episode is None else episode.gid + + def get_file_id(self): + if self.file_id is None: + raise RuntimeError("Not a file!") + return util.bytes_to_hex(self.file_id) + + def is_episode(self): + return self.episode_gid is not None + + def get_episode_gid(self): + if self.episode_gid is None: + raise RuntimeError("Not an episode!") + return util.bytes_to_hex(self.episode_gid) diff --git a/librespot/audio/__pycache__/__init__.cpython-312.pyc b/librespot/audio/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..f9c6619aae1655c429349ddd26e3c14576389962 GIT binary patch literal 59100 zcmeFa33yybb{^U*x*NR$-2fVUV@G2p39jHKk|0QMffiC5Bn|}PHc60JsM`%mfPfKa zEPn%xs1USfOmHNJkY{XxkzNGZPQ;1h3}-xclsw0;FB?kt+=p1SGcU2e#0e~LtQp#g z-+$^Zz2JhPW;A*EzULxQx4NosRo$vnr_MQb>eT<~bY|<|95&~`?~{v#d_#FX`RsT0V8M{T$3Ilq zQ#e%AQ#4fEQ#@4CQ!-TAQ#w@EQ#MrIQ$7^v39!8O!HS+rw9h_R)l{-`S$DZ{)_3Rn!39@HHPXl{4_B66*Q%`fK@$Az|wE06x?-}I=Mmj?M{Mh*jqCCe&&xd#x**U@w^--K_-x<6g8a&!J+;=*}BgV0>um4Oa z`8(^OzW#HeNYE(S_MaaJk8q(bPRxF2uy3sI z7yjH_?Ue46o^!qI=<#rMocm={PYzeldGO5Tf?N)sUao=5#nZBw@hs+AxFS4D@GQo&6!}WjT~&W|r3^T+hY$251wJ(02V1H-3VXcV6s7>=9}Eqo}# z4}`*^>Ey`Bpy;EYW4$B8z5P^NZ;0nd_;GLK3;=_pH}{PUa{~-=Y|r-%M0y8D`p&OX*MRCv<0J&`|QxQ^_-q zvP8)1Mo2WOySVr zDfUCO_4f7;_JzZ}ysrj>6Oyj$MQ`^=q-*H>U}z{b z90_sz38HvbO-c*1PL7^B72?NBw3{cTu1A3@c6jJfS4GTK6}49V{7vJjxK#}?g$Kq% z<3-xdptOzj7V}nh3K0jaQ>G9AaX zDBfzkVcw&+Xu}a9Y6jpcBq2g}3QTEt)OfZ|cTC5iEok63;~lZMSMvjUd(V%ASADas z@43E#L0ae5njC5dYGk+oo-{eerpI1+5p%icYLDQqi(2be10#I_0|`P@S9D`~ek%gk zSHqoasEOOytBmpDecQEyzNkd5Mx>;Jq@8(D}Okf}! zke05BkBRK-3}%V8<74MT(mFzDO|*19DE(qUn+s~Y|6H#;X$Oc77LA~FfCL%5nx8)t z;zMHAx##=%(_wkRSD-Z<3atsPly(^Pg~&Rrj0JYxG~XQk(0X+B2vXlm zu!Nrff=5ty)`HSA+}rYRjF>ee2|o$LP8u-w1_nn6;TMQct-KS4aZKiZLy|H}g9nY$ z)8S##h&B*9$Z!+JbV!*n0OubxV`CIngXp zgM^X;a1xDV3ZEM|zZRmRv}4E~ei0rGy<_UxuW!27&|@*|n(lh#@ND(9hN}&Nqk2j& zzm@RhOzi_DtWj`_=3vk9Vfy%Aw1L<{AWFbIj8+WmaKk&OA3dA6m3-Ot?K$ z*41c7MT?(7h-p(hz}?S|hQQHr61^WDuhqsrnfabUKdeCo{emr07u(NhQD(mWUs8*B zT07UGOC>-$m0mSxe0TY~6zBc74}7K~x9pV(Z$Vm|FJ7@psMvJNzA54LgGGwF>jigx)LJji&D0MfWXI5W z1hHS!eGM$|gpqel7{Z!M@wD!&y0qd=*(s=bnss})8oAV^S;?c*P3x5fm00P|Dv3Td zqAml|dd@%t9#I!_yl+pIt%Q`8AU76-X{v>Ykqk#ADSU}kuJWrxcLGB-X}WjoCQJlg zVg1Dddj-OIG(mbovXnDe$8wv9yJ8QduHmMA%r&#w^l)+B!` zp(OP3MovFz9`-~C>oRw?UI`_iAVkgoD|#~ht0v5RSIXElB-^8eB1Dcdca{Vk84lmB zj!QC0f*qxol_%?M5>R9~%vJnLC78!Fc>jx!NxXkBtNS=l3uEWUe+kq=A=MFH21x5y z=sUh?xPl3NR;KgSJP0V@HmxK0RQPN?|1^Gq10>uliJPdr3l}6>%DQ8)Z|Ee~w`;sz z8~Ls#(OY&vlGryG-i3hl?i30P)1>?91>J%vzHYy;Zhvgufe*~L)^#&n8!VJ4zaDBs zA3V{__YI#8iN>LUVYY0G&hva|a71BGrL`naiIXIpviy^MkR%|OeTNfujWec2Pj#Y}J*!at71w1~+*2ob>K5y}7d;Px z9=Njo*S05oMW4ELxq+FoWseS}dg}ylUDVr_C@78>)C&dm^LdK}t%*SORr8O_+Tvw< zg|fX-|K1-JlzdhjJ}pJDe_f{Yhl#oO$=YZdd7)(+hXF*+L zIt2|8<9V;rCXEr5dDLzV)=hhI-JCStM}G8*^1YMhWd4Y{u4>UD#IUB;q?V9{c4^QO z6DH2gWhF8DgyC#nW-rhNh!*vr^o~RuO_(`dk=kO&mrb07nDR-}glQt{+!plrVG1D@ zJxycB@B3x9N%{KB)}*vSe{mnaS*3!K-<}jek*pkIhg2F{&W1Ntsww%V(l1)Hh%Ba{ zWs5nKP_BfNPo;!oDb(@3;WG&zzijx!%u9o?NlQxIl$Hv&)(H#RbFX>W0XW#2Qo=oR z-=pTwdM~|I_cs^J6Z&xsN~A&=nfsXs3d}Kf^YvfSe6q0l^NstQKc)!_!*{hme``41 zgf(?`4_E&DWhp(BF)O8S(qB9`T>tZzJz>T_HfpJ@MS1_*&hVhMn?DQyW4p+V!sL(O z=kZQPLI-nFM2y5hOIuBbff3QNcPtVLcRk3cM1B-$q6sPxgN!B<&Cf%PBE+}RE5|6! zb~+T1HZ;Yo;gj^LXd+ruG!BM_gEmQ0x#rdj?Lo4_#Ow&vR0exl1kvH5O`=RkPMs3% zQjq0P;zPrn=#+`qVXhb1*v1@@kjydKo&PFIT1yN{t^9SQhyN02Q<9ZrioESPGY`MA zowkm#J%PQkC$B#F`ct>u^@)O_rM!YGJ(qi4dwQxfQCNDd@M_`f#Z!ltdHGIuAoGEKbGIJY}Glvmkv)Kp4DIMrtQ!}Uq3Wk8!u`QiW*`?P4S{O z0skFsuO3Qx3$JXyy#2MEQAc1Y$9tvda?xugQ&}2<;MLt@qo^#1iv7(oU(1w@daDzi zSF%3l-!SD&*nKmRD`S_(UV9PJE2%5Hu6DhCc)ndI*&Oq4L1&hf&zat`y=nWleSTaB zw8u)ePaRE_I7j9mU9`4QNzV!PQnqbz_|3!LKDtmNRBw$1w%xLCyWeikEtuVQE4MnG zSbdbpSFeAz>z21htBV(g7bc?>`#JbAM@m$PTg%T682*|wNl4Kf^^zk1|v z*lu#1}Cz#l7^L@$&6lC;l%FV=ZNPw0YCE~%v;j$Cr1?cVFNBv4f_woJXqR5+sx zN!pmSfAzk+upyh?Nd|15bVf#J82N2(WTV&QyQ@j*g?>i)ra zlQz?=o%@fdRN|h2{({X@rnt3Ku$IQG<#T4iTFWL;=`CyNcf51Q-+JoJr@nmx99zw{ zSVg;FZU4|(s_04p`7U}Dl3V#J2!C%WN_|u5OPNQSm zG4p85T0Hx#U=84TFDR@F$`X(@pwXs6BZge}{p>xay#>Y}6qxr0(lvVkgc6bjf4Qbm zAt_IM1-VwKXSmWQ{8~ye>AB)4DNKS^^pGOVidw5BG>&N1$&*LFLR(BpCDf3SgAn>< zlY+{6Ok;+i>Fyc|Is4K?dTF{%gg#M+e&rA=KcZHwHQ_kD=9Y!Z#w&;)yJLp#@#;>f zEQPoLHyR2=Mgo$+GQdEoDL^=~J@Dcrppg2WCu}8VK|U#IC_7~FCd-|wC76@4t0*ge zZq`PP=^x#)>b)h@7^cZ_LHA>C{YN?Fm&>Ao&UoOc5IFk5U@Y)dEa&NEquzN!&qk#i zf@C5q8T}0PP3Ub7_YH-hx0&7BJ2b+L4pP|B+xslkn&lLH1yr>AheDAvBOHH)-X?7* ziEIy2h(4Qt4W5X&th;T?`@~?dozSlsb=moU&4SV^lpFi60X%q;13>vY3xd{B zewh74(r+O4Zf>dqEu-B}$Vsg6a#%EVj|_*Pbg++#V_FFGHvgMcu!(<04EwR=m!qG9)pSLln91IyHJsssz4Sig zvuY^RN?sdzo5^b@Zzp*Vkk>(8CwT|SJ4W6Uh9PI6dT5UaI*@SsOVwH+0D|sY(3jYY+Pk)t^A}>6caOPgpu>U6}qj}p(w%%O4lBG9S%bw9({|Vyi>8Fpp3e_uG$;vW!>sLH>bIwXp z@|9%BY!0rtD$LvObn2VUr7K_3XPKK;JXUklCqBKo=1!K`d_q54@TrcT%gmQ134Lon z{!~XO4i3j*;3rY2q{j~(eUldDnUv@CWDV$`-*1GbzKMpKGxyl=R`yw%tr<>5$BxwV z0MP2s;cU>9cX7E~HlA+mMtW_!)PJ0hv%hTa@h~lV2ejy&%5G^-4vTXk&K=58WUoEB zW1e6h4t$W__uze}mpksRyXE{!gMrwL# zfGs&OEXf=EC|xXEoh>XKpkS0NDORO)3x(MNlZybUiGeawlND7?J->iBV3ImKL`!OM zGC?A#v->j|s4BAm7reJZssUI}3jK_xD5?p10n=~Xf z6STMvP^<Yb^qw;UjFHU3S5&1`BnKz5l>F=~?tjdznq#IvTfMrD2+bbm?hU<4i&I+^v~}M# z>>Bvkg!kE8AFtd;`booek-#aadIc0r5CDx92#1~};_YJsym7;>gM29k8r3&&yo?(R z1ka%K7_xbnT`Dp$JtZX7$!?ZoYM3D-sWaS3J=ldf4XU12dCne>- z;hk_UxD6Z%$@N`nxZE)N*tIWR{ZcHqY09$X@?9F59-8f#t9z^I&8GQhzug*hZCF?@ zxHe50v6CD3RterJY4dj881ptwSrc||)Lu-|I|%aPj&i|Kp73mpd$tRn?Kk$tJP+If z;ks9U+mV~F=Um!3z4MKHk~GE(n}ouqMSF81xA02S<)&FamRmWsFX8YpnUwcKXb3|- zbz=I&8=Gm5JYKv}DBif}+_VHy;LgiC=X`U|zcumZ#KN9$zZCOsxuF-l?Nc4}I?hzg zZv4;@xSiglopDcx;OQXo88k;Bqw9RD`_1lHpl!vd&)M`7qrtgZ!qWtHic|6QGYn4y zzbPpx&$Z8_U9uks6_K@MUYy}2)9Tr~MqQekJjpqaw{lWCROusiHK2XWv$SYuI4yh>QE8#G>I#v3 zO>3<{?SwNjoYKR}H|li};(M7pOT1c!n^0NL$*c+5v#!j@fS(hLYMaQ?(&$LE;%eM1pH0 zw!S!-J`_7lIUGjO$i|Z}M08@|>1E%}78J)Lqr;?OwV$03r1gg<+$A~~^Vu62={*yA z0WxB?q8QOpqJ=uCcYx!^Df7Rk%*K(?2>${7q;(}s2v1&7BN}%>n%{o{0oh+R@=hE5f zv#$(dak1Jj*`{qXb#&%a4p-5x1B?Df?UlyMjkDa`zF2PkqBW@GsFrG2v{qA$b=o?U zgY$Ke;JKz;b-YQ-l^vTN3XwH*;!@$<0^A!v!x$DRVObe`jrwyC7DQ^_ka`* z$HC2<0Z-GIF_?9C6&av_S{ge-hy)9qeuczpAQgv=62a6)ZR*dYQODEz0- zrWU257QlNMDp(=VBATNn>Zn=G5q+*E{2LUNx>dpdkeX1oW)m2dRe>t_kC2g7-VKQm zHJtx#@_vK7--L%)Dm+CZM6p40rtpTnO0{N4(L}5A-TV?#OHd~}f%dX)#iX~@-pPW; z>gRuqc2UOnBnl zKeU!jIPq`ivhZ|{S%Qwct41>oOEJV1=uM4-$co0F@KW!PWXd58!VLH(24VMRz5g?^ zL2AY@R?eyt(}tX+T;nyFL!R0ul_L+*D9};@j=XN`RL6%7S-MTFQXFlIuoe>bUQ4NO zZBkED8m%swY>8HCN_pN(!RYgB2}-9VO=4-rpzt9a5)Tdchom*nzgDtngb@U38}QH2 zytIxcP#+K6v!gNUP1MIbkrjQMlNZmajpfv`P3(Z+3B*0sf~R`!*rF%M;z*A*?pY^z z)-8HAU@ge4!wW)At&I0J?{OHv?=bJlTSM*AkGj?xAuVECYizK8U`ZJWIhZ7J6rzQV z9HFiZCqn{3Rff|#jR(RWZ6>!?d0OHXWzv2gNTA)0LN-`LAFbNru<|s;_&YUxTN#natD5#4UGztZc3pLS###q5tY}+$5aEs6Y4e6_U z%zH|V-!C!msj<+G*T>Xa`Y!%2$or4*5X)9>TEl~`%r*Kg#ENE|*BlLr=7;GaefB)P zew{o9^|X*kqyWJ;`~HkYosUt%e}Y#{AKQ)q_AN@AV%DZae#K1a%DKzuUK^USCyHBU zx5bNFgyNQ1@w%whPiy|Rl`NyJZ6(`mYrEqz*|tfmKb6=Git2Z%Wa3k?&Gp9=wvnfj zBSHOf5bz0#qi^JC&qN9_3ZCstC40b|*#n;-yJ#Uv6}Tp*M|Xrtt=Rl$%mz=L#Q!OI z$!_^~^poZblXUa{mO{h^Fq%c`jNSCJfxIAjY*@&np$QW!f({B)MzMY4ESq{f?kp3W zWzq8Xm~%UJX2eB--k2sW@GaHDpQMSIG=Z z6quUZwmP>&o2fanSLaAAQ=;J1+;*bmMCU$km~2=b3=P7>5C1o4n`r4h^5B63`yWZ$ zeWy;qpMHe^?K8I|G*6-`YuqG`Tutbo(}hh?i^7u+CM_vwt>Ins9Sp~9Y(72IeCp)5o&A!2z+_Pt&Np!*LuAfqWS}254Enj@QGO76 z)leV}pBEi4X%y!9pFjkR6^L;&=Bt_0;EanFV@Zpc5q|ThSugO zH71{GYc)2Rph{(hFwd-5*PG0q$ktNGR?3*PM~ak^wSO$o@lM-3xtN0!$WF!BcCm`*0$VwnU8BTH$|&7@j0Y60c2CF43kE zEYfWzvAQ6;3!m@BfkjMx><~$3 zBt<8kF@y;p*}$KX63tMvff(=yRIf|@nqGDg(ke9{n?{ZSGCC(4BoLwBmhuI?WWF#= zvnr74*g7j_v%{IJY2*HM%#=(aNnDsjE*Ern=$zk-J!UWYj#02fBv(4U@5j02@!UEg zw{G4Z%iTD&4@%VE=(y5#x$CvVbJc>c76%MrPs5cLca;mS@|de4?rIfWtqbP&ZSUD` zZ2aDi@9v1X4o(@D3QOLQ_0{J$3Z<>F!gbKyEZjQfy6r8Jw6){jCc)b@e|(|shVjOU znD;OQZ3X35Ub_5Jte}3%u~ga;FKrV_+ZK+*O83BSTEbosx0eX^lG)=id*vK=%ih53 z!)%J>ZjL%OFS)DZ?)8FuJ+#uX)01$NEjcRUj-cQO&R4(NbiL_@{Pv zQeqeze6JH|r5Q!xCy<&6`&#md;bh^x_hWG8olD)bsajnkI4ztaR7y;uI-CRl_yc4g zFH$iYFaX&Q4e%jufCtS`F<#zD+YwMI484HkD#Lw)0U!XjCH>+gZ7X*&q!-L3JA(s2 zJEDn9eu)kxJ3}TwX?>AVY#L)bS3-$*Q7`|m$jbxtiDoWza#Y$~X3~8=PDu+W@Y>SF9kUt%7%J!r`4cHrtFGzTlMg$4RW>Wmv_Nf>jpG3w+Gc zzG5>IE-~9=LuUU#q+w_!r_AhsAkw7%_}`C6wkM&(VURewT)B_@}W01B;V&AMBu zNrkr@Ng=`^>PohnVDzp>ZQy=+SxYaKr)`I{k7c0Uj93Z28z{tpypci-(luHqmE*{i zpOLhL|CBtoDif2#zfPW>3M(eBhP*oRc2h!9B*yp~@^&LJY=;MtSV8^F^Rl@Mf2?4` zg#%NM$4nb;n{z%fn9L9 zxqaC}A*-&We%U64nqlRGf^wl0xses>l?$b3-Iiq|p0|tZmd*5R>i&eD@;eAEH?Vh# zkvGS`Y{c_+PQ|hrPgLu!Shi5es>|=zFWV@Xt;@|{wo}NV^H(oBDdf^+H+|wph!y+S z285)3qTcDppX%ggRlgz$>yu{A*Am1f4QoIUXMiBixC4c8CWOo^ z;pS6)Eo6TkwyInDM}}Br>x+~d8b6ccHZ{nXV&ujRFHYVqP*#q>$q{ZW0MoIdq4SZk zilCim07J_(PrF27E|Z61iRtZ&Ku&UUGy=_5K6HMtuRoN+msHRTBy^F~VJ-cV#0AS3 z382{ag=i&V3N2S;LZ2H8(-a}DL*hBCR1tm8cq&{fk#i_Nd=)QXvk7*Ec3s{T_tp#E z`k1%jBd2Hj*o^N=+2yi$&ITc8L$qyQbUz=<34fGZc)4!2@jH=t-BzJ)>y3g~-JV$P zUXcH;4n1VCwjAIxhc9j~7wqM8ZMW>T5IVpPY2($#xij(FcA>UCRjq3`EivsXlh(E~sZzCd@OmV$4LVBxb`7 z1Ob-vvy0;i<%`Cn54DL|z(bFc2(6#)|KLfDQ-K?{s0RqPX!%cv7`_To&=6NKYs(rO zG0nhm4@!kt4C+=zad)NQt|Y}}Xbdkoe6x=)I%<|2C2>bUfRzD9K2+9-rR3&1=9^+< zC_%Q@PRTI`Sk;o4qb%VlTya~8IkYOwVJd!8CHO=;f1!g<8->hi35y_((ZGEQ4oU$H zw^B;-IY9?5v}E)~Wi?y_T)fFLl#l`(N#RjaF&RRk41ghy1gM7qhTl#eLqa_B)p>#qqvPxq%-Wktd4Kai(Zy+sv8u_ua z<1SnUBh`zJaur4-GZ!&Oa~iO`b>z(>3so`4=G6dGJi9OE2xx$e<^ua?i2b4#SXwr< zmeb_MiZ&Q2Afr4XG1DnT4O=iZz>G7p1v4*c?+Z(wMn0uXwj^o*oV+BeAez*8#`cE_ zY+8${0(NA<>udoAGs7jf&mf01X-O_4>UNY?`C3}!S|^U!IsM)UF&xaD4ak9%2kNg( z`6&mLzJY$f?riny^s@x(84hHLJfTt(?stT-$t6RfQaAd>46X5crL?n+N+|h+Cb>qP z+I^~&t31D|2T>y$59~jFx3M)WUDebq%UN3)mD9?0P+DP(9#<~)M{r3}>x+|&eBs+@ z4i_mR*nJ({8PeDBS|+*;z#;%-wqyhu!dp381!BUZgAsQ4Ctq5TjD6<^cmW?KAsAY~ zB~fbyAs9x|Y(_|Qr8C1~e)?~Ppb~Mp6CVzB!tOLyKGMFx>1e7`%t97=8qpa3@2Hyp zLEir)?+?hUqzc)h=>UpStzSZdOJgo!y)Bf7G;c)nd42?4N4Rd4{5C~joXADmFp{~C z6#Z?a{E%LzH8zE+su8?3F>l>R&YbDvGd0n|&UoQbq44ORaPjV5p}RNw%;{M7nONaK z^xR1F+0mHuIYvm`wtF+ksQP$Oi%`@O%WaK1TJJ?YEqTh~o=t*hQ_Qo4?72H7N$)JT zXsyE40c2$Qja~8L2ZZ7W;>8Dq;sf#G!$R@lTlT|Cx&AB7mz(FzZ#mv{#B!UNzPWT7 zi5Bo^S$n)}k5IM;+S_qYh2W`}tAqVaCLt~-39)m-ZErpdE4ln}SB>DRNjNsf9oq%R z_8a@ZcjUWAVva75itfWu)z;e%ODFKtxK?x=IsFRZxTNClm_BH@TaeP{siWBqV*|6u zo^l>MLw;}=#qtlr`}g=`mzKP&gJ!$LIa6X<8^Do~ldRJw+mNa}jAO$vvBS0|_SdzF$v=FHt;=}!N16V5vkKng{C4c}{ zu(Wfw%sL60FFEDZtwFZ;g#^VI2vy4;qmQSu)y2C8KgO%?(P)*4{SWjmtt$ZQqQF$g z#lwl>%BhZ5kFY)@*&3_jx0QPMNASY+RjS@^Q99L{A>k1{tGer96!0Uel~xakdpvos zI1^BXwbtG-8En$sOZ;QV(2sQ0$z7+|y+}$uq|4nxxZI76nh7CEs*!~dyWow*t0QO>+K8G=Yv{GnE{fDS*kg zlpKr}WJr)231E>)Jq9f#jaCq!^xZ0q{AU_1+H1U^yWI@c@I_GcrPY8HW{-@lW6?=O zNeY6js-q8LpKn6!T0|N)cCmQEfW4+we`r)_NbI};Ex3b#?RPSDkb&E;ndmHQ4_=eV@Q2U{=_J$B z6nB(78r4{Xexu`i-QVqw6(624eZxv3 zg{_yjPCd9<>P7qq8*d%@dKI{9j_-{AEB{Z5CKi>D;k4veN%<5G_Nx<4Yy36G@t%Y> zQ$SG3>11P)Qq)P4O_yZtVF;I*t5RSK#HdkAD3Bz~C$rMthhk(Qs!`v!U`yW2n1g?u z!V#*6>Sc|m8BRB8#i2|M!W{;G0R-fr&1J&{39SghpuV{65Y1CD>5%Yt@_%0d##}l0~eBd;(`QaFxZA zFzbEswddul1U2(mSe{=^$y2025z4`G!qSJ&Pd8lw z8W}kk8t(07Cv`=v&-;mH2!+`>I#K^+QNL3(f{u{R^b(Id9_Si=4yt-wKz%tdFsyK8 z#Er4lW4v0)CYK1~4Se5FMpjYZJHAs@&w+9Zafr~xQRtQ?0Noy0M zF0!z|;0jalQ^dE4R{WGh?9uydm>nhH$0R8fBZ`jVo0!=KsQsPCy=nY2h!C?M>l+-E z59P9DkFA1i+4}=}f$8>;iad7X8AnG;9&9|Z-bA&cT?*ph0zXDZYpIt>%TUP!>YKEP zSZ7NKcI6i(*`yy3)bm4BvOdg@v34n$`XXy=;`1kvA6lHNs3n>5x`X5}DI8+~E+_(# zbPx+JY4!;2;8IEDwIf%L#7ox0uqwn~C7Wk#OJ&v92Cojr%i4spwuP?uAAIk@SXsx6 zJyBYJt@mp0{8O>gZ8O=+24hauQlM(?(EPJ+9*qSy%ydB>A85Sx($$yd$71E%W*n5I zW~s7fZg64!nt^=<-=&qadc0p)lL%D2WqH#wZ~V4nb`M@JDV=>}wr_UR-2T^hE!8*9@0ssgsJI@Q zKQ-U=wrjTQM=+6Nc?LkX&U!@_Z)ejBTN*_4%6F855z7|rUTAsTF&?|S#a>kr=8d*k6~)9zUP z12;Dc^#`Q)vUD|dGo}wc6+gX$dE&45M5oWG!qJY`x?qqlr|NI-WXq8?iOTBN4pU^! z-`?@)0u9JnSR5380PaI}j$sN~5n{-(!E2bYWtByDkIQg-QFbwUa>mMn4R=$w86m2JN;x*EzJoSN=JKvlh{*{UF0ZAZqzTJ*qC}f|&!1#w zkBEG+pjRnJITbD0lH`em6LAJtu0=_OIZl4;e1s?95OY(KiNU1>!KDZqq&LN)lsrr} z3XzShOwP`dr4=G84e+#$0`@vtd6+c=d&B*yOrpx@{3h6)Rg4Zxf4Rg95hU zLhsGzrioDV?3X2Mdfy8dHRxQNKHx>ofKYG;a&LcmHYK zt%AB$r3Um#wbK8|CrD?aQJ4d%NmN{hQ;6mc-6coA;WRAnodDZ9>ENuF4HvUa_zgxv z*XvVW`+~|-wb6g>@@#4CQ}=r!O-f6(?j$?AUP(thPg+MSipYVP)>dLyk;n9m#+Vnu3Rv{$_(A;1!RCzD8Nqa2kg*{ zJLR)4&5uyjxKmclXl6OaOOFnO!(><|EmuI2?N*5T)=nl7IUX$Lzk=z{f0eum@+Qgq zGI_MoN-81jepKFq){EJa<#2Z40ts>@(wXh05M?SI{Mn40><$S2%M@Y=mf>5{2$FE{ zi40Fbgn~tjj8oaZF|4t%1JVitrcdB$ zYX#RnNQx`HtbZgr+J0()4@acR_|wR>78PBC7L1pqP|*s`Ri%#GfHlLfp$MiOUsl89 zjpg+uek@5;w$QUYQMHbq0Yw~H!J^AZ)-`c?VnM&uvLoJdKxjGeL50u)x(n)dD>}XZ zsDA3;?UL$vNt0006fapPl&o7QkCp7fg$3@CsJj}5ZsLJ;LSS7yuu%wXT?}~bMC43ceU!CBqgPAv9lXS<#{<(^)2VZxhwJG;YFge@rb;maz74X0Q zXsoO|R`ek998MHfUTeMDI(2xd87KYU-~QhA#pd0y(g%d*-Shfyg`&;7h0+J;(?2u4 zzImQ|_uTb!ixA}%ZHGW_ZvD5~qV?@U(RQk6sisvj4I8gHAk-Xyxqz7vwrpxksRJu- z2O!U7R^ecKpp+RTC=nbbvro-e%s={}qwQy(ICW)v^gk0zANZMAw4KTBe^_WcU@-lW z-gdxZ`lF!jfWwp~{3hKCOi}&HDU9J-(qAq09)*^ot1p2ZfG9Jarle2R^+@K1{R(^X zmlA@(FLpI4%GQwQ(t@oezf)SJZ0sv2ogLDl4U`P0t^EcGmP`zw78TtmU!7nkY><|W zQbSr&s-&g}p+P$9+sy1}Lrj2OU|8)QIzI@mo`X$CQW%oWfJqad$r6Z64mud7kjx=7 z+{Jisw#Q05IKwxh6}A-nq16^*_)K)l2tl6f3>#gf!elkJ#}QU;jA2&~_CuIyGC%=#NDleyLAx<-EbqHqIN`g2*w?Cf}<|s*&X+E z3ZBk{uY9iJ@`KXZ+is%;SsVdRo@h^+b+~?kJohxbzKQh z@$93>QBSji?q0FOItOee#vPTg%@ucS6CB%aG=AuiP=4AGaeR&h_9U@d3+$67>Ip@! zlJDE8Pf|BzROBd)Tpx7@5k!zNkiE&E;0;C{!PPr3pR+M+wQ51RVR}(kHZ;?*tNt{J zhuR#L#AURmR`AwF9g+p7w639<%rJt8z*=2%PmB;;%c8yJe4+IO~FJ`nC0u9?u> zc+;MN8aQTki8Kq{%2}_|lIgv1ER0OYl&Mpg8F3(H!w{;RPf`VSlL}|bo1&c}l-bP&C;M*AU zZ3g7~w_+zhXX|ZmKsID*iq~(2lqOyeSxrZ*zBA@M5Oo|_4RWYb8f2nbex5;A=7vGS zGj0XX(DC5jq4287@*C6*blgta3{#;qckaR{5nWCGHB`Y9Qe+IZvd{kv zUS?ER+CIPNR7}<|B67S!s~6I;oTok@@{y#Ij7XZ>A1i2>I+$GYpI~Cg&;pkI?QD3v z)0TDOgIS;aSF{o1tH0oyFkEmzF587V3cW%myeA#$| z7HZ`V~2^To+#+zO&+N+=)yDPCtcLq7ZDcx%arR^$y2qwGBvx{Od3zs+))vOJS7Oy!XKkJqAGk- zlXJzF%IV5zJrUbaOj+j65uDBDe<`AXa<{Ny_=@rHc@ z{+H~#*(a17n6c56`ts#3#|xT-f~HtOOT1u%P_O}{wshZbrQoT&?JJ%=5ieaYl&)WB zyfGFlg^1Wtn2TF>{cS5cv)?s!5T}AX{exp9#en@CP6x(z-<~5Z z_+r(`=t{rx0;0Z#37x801IZ(!M>!`hZr8&kqNB&extK{rGv{XdQCXaarDY+_f@>4l z2_ih%$sy#SYZS8OYZUC97ndfG8AUJWz!Rmupzm=3w0w6{b<@>xN*C$z<22rWcxj4M z^aTtdZ9w3gdO}GMFsL7xL?_cg7_VXlPp6qBtAIx71ZOo~V`@wa6-%}80gAUzp+`2ZjXG6FVfJ;j z`med1qTEcETt?Y9F#0@`f}qIp;C+06bhG3oRKt!?Ns9*z`bgHvqMpXpbifzYa3=c5 zY&b=Z*WE|MNv!f~)a!(XQ<_aiX`>zuidluGcDz8)lspG84Y+z0%a5{{FwW0}Y#Htu zqoS&1;u%0uQ4)MnhhwLNq=gbd(ZB^{aH4GE_4n~n{evUn&^PI;^6?5_i2>1N=QrFS z<*ppPd{pq&|MCWe37Rqoq=(wxb{}n*Q7^1XF_I;GRRgA4go2i+r{$OT2|Ll+RdnRj z_xlOzC4cfKyn#>P-yuZNfFja3o-b+=Fo9oYpHt+0&0eXeuTeAS)n?+C>IjG#lA&Sz zn(k`=`)O?kDD^G*buIR3N{>as08`6Wg^pn22}5_kTBlT{&Px&^g8Xk9P^n&%kE1!6 z;igr6sSG@K4IhXZ_6+i~X~vFnUXW+l0Ak0x?;lE~0q#w?imYV^tVs3^hIb**H*}Kg z+w~oENth%#n1^#6ZykN}XuNv2P`&%6d9hj&4}gXz6fAl|FNFF>p@)t$s{C`z)LMA- zS zyruRou$u%3B*`H__!^DMeS^YR8rR6HfhDz$L`)eN;LuHZX@CRCRtD%$fedtL!||I& zG}536I`;{$(|Q1uoL2!TnIvHH?qSq&-6)!wjVkHlGs5AF8M}}MT?g)C(8AKDB3*pk zOXjgc+-k78PUA;(IlyY(^se)|GhV+>sNWZ_e@v)ynB z1mA{_3d^tNe;D9CEDV9b^-1hx8u9iI07o*YG#Zrc5qVQ#gbu|Fg*g77DT9~}atA-> zAj-w9hPi*bCd@r9)IT15;zYEUTdWT;nB(6kIJ=>=NCm6kN6h%1QkbWF8U>PF#gxH9Ak}Kg~8ePfO=((oA}Mo$4m_1^yNCNG`%(q|g)O z?Iw>TH~gy0`I;CZ{O6;?y=+}gpO*p{eS59=YejR@`4 z7m~YX|7qb}UiiNuM_g?qV>CC`MWQ4P92Duc1sqOWn;=Vvu`=y z4vQ`=>z9pq-frE#V#ag1C>xPg*gnE@#qTj=52;#jcFv69keu21DQ?NEB9qEhpL!1H z&2@jRBmd4Lh7N-neeSJ^*6sL-j{T7Oo!YjFC`L2&EB^?7syJpX^Df$UmT{0ROFqa( zA?ZjIg|c>_T$ZXHj$#L-po;>Lj0Lx5I!S1wFu6T82zAQtrKNJ_F396WuhB}imInf7u|{UpSPu}zT?&+0a+ZUKXQ7fADcNk*FHaa z<7~{?^%Ju}J@APZtIm!P#znvKXNYBjtJG9ETk=p16Q-!+sFs55Ib{qcA$~clRfcNt z7q^e8Fr~FKkh)WoJn?;RQ#c%~X=-gr!Xl>J7KLw+ZU+7TPie{=f%q1dKxZ&y{0;H| zSTLNk;}ris0s!k{6!}&1Cdiv4kD-x&L80G=2L`zioe5b#873xbD{YsHy*!@38kUI! z_(Ou@e}-28$5vn5S}0fxXR8*iWeIn&eEKaf=B|S!8a1_I(OR;U7%pNb6IcM-?Y!~`L-+OXkE|?jtyUU(u&RG*|@AT**3B@AZ^Rhf=^-7 zW(k2*YvvJka%gR$!Ir${X4nMVQiHw=rlSI=3gD7y3T=eRHrb5lIxs$TJ~A6k$#7c8 zGpRsI=X};E8SS8Y0W`3R{U<1u|EJ{j!yA9%kq|f9PbzjYehst3wSiMOw1P`aBO?J= zm3|I{U;xHq&!0!emcT=Up}ue^(8qCs;m~R1hXn)VqNRvl=zDHtfNKF1ejfnFH0W@P z&&cyBxRznqe}(GhtyVEFt@2*EFwvJDEww2PPQ`4tThAIhUa}fold1m~0c{9%LUdbR z4a2OL4o)AOd1SUaUeqKMHAP!HgrbfQ3_{_dnBy=u;{!+aQESO<7+$J=tM$!R!M=WB z&n^2V(t5$^+mCYmmkXkW;l-RtqN;i>^43dlz9dw^7IYxtu8LZv6V*hBvt@&I1Y2cT zh%GfN#MT=MVef;cBfErLqWx*QDl|UJVb3Jhlf)eB&m=L&ECI6F|EE-D26@Kt0D13G zkDNr0fIQQ-|3@bPOn#gekKyi%l<>021{y38r~x@lfwrw6hY?uLhf%&y3^wz|70F^C zLU-~lX6aTdhJgs^RA-Vxdguqk+E&r=lkac4Mf zkKrh0@*fQ95#41^#z-L;-y^Eaks1#pe6)S$RN^>4+eULKzv;;pa!%yIjpfOIToLC& zoOD;Y8w&n51r^A5m3v6(UyaKh%Y_cB6WuUgp0vOB&|u$K-^sy{tomxMjiz{FnMZ-XfPtV8V0^S}VDflBhQ3!EnA^IeB z;b%v2hA}eMdw!t*9L|b(sW4(2Gw4*&1O|c|FVY?tO8X1K3`3}#StL^o^;-mc9f=-y zU*0{pJ-V*r=4q$`15^4oKyAsn;m3BjWYFIx*uif@MXp-#;;dM7LuaCvU!c#H-o|p^F{9b8cR)+!As~pOILxVui-b?32r$sSp+r3X(eWx37 zwW!v6Td>noVb#)IVMZ1XO&GpX9r566nA22IT|+Gu;D(#hVgE?(698_qoC2l9wA-a12jvMQVd{n@I0-qB{YyyT=o%30TU5YaQZjyY7)Jj` zP7hhhx zHlb`BWPlCLoT;6&kI(kv8r;`fh(;sq)Fyb_7CPQP^4^h~busTDc47Rb-P60@7><|i z6Uz3*%MJ-;hvH@3LRt4Md$+8XR8TD`a4wkMcfIGjX}%drtlN5{?&fx&H~&LqiYezI z{f|k5vsv)c>44$u!#7SNSIg!bmYc0Un^ao$JtCAna?Ab*>YJLxE+P(4 zcuH?O^DgyH_kPC}59}8L`{RKlLf}X|@VF3o{Fd`^d{(r4ODuP5)Uh>@nX_96bjJfv z34y0>IiF%Vx5aYXqmK3;(_3xv@^+!T{l?bs?f&lWSoz^tuBx)c?r2C87^!>`$!gcs zi@}PW>E4zjv{z>Z=-HL=spwyRi?2vQ$Le~UtOIB-`9lp&n1SZyw!or|L5q8WEf1Ia zf*MfUgT>*(MwG51T{VkN3yp&UAo*;DyLTN*T}%|Ch0?QN0Rq-d@GUZB11`?ceRrd3 zVBi!K{R4f&V}bDKK!k`z`4V!{U~U30);BOnv5dfQ@N5Ei(45OB)@Udc=_3I^??y!h zT9P=k8DB%$nAuw@OEfbgLlPYScYLH|kM2JplRUM>Y(`O3VAnl9Y+K^;BRLuz4hK>H>W3VTrVmd8DofGOi?0z?`KD13(l6`pbC0O*)Y2MA2 zv@L{N-Y$GOc?380N)JE_nB33!;%u#+`phq`$5hU{->)6k!@iGw!v2+pl>W>9jB%tI z)`B!xNJ{n+@OVWADB>rqEZqZ=nZ2N0=-bNGZ)(~>GHKeLxn~_pA7U;9m0I4G10Y6q zS|&;-9L)Ap8g7SW9+l8dvAXlBV&Ntu-3+N8dizP;#qTOPNX7@^NB4069*(N?4U?r& zAo~Dmy}*bf6W6hg6aFJY-uZMUW?&d6b8#KF#C#@K317x4A-(r2D4G#+VpH$=k@KU2 zeUVVFv=>85MOf0_qI;Q!agm+6%82%qCP-IB5prYZOhqfx_&O7Mf&U&_C6*Es+nbWV zci>d-aHttK!A2i^Z)o`<4odX4|f9y}I?a$+>55 z71S>n-?#jZCE@hrTD4^K>Qami;V#v*6pj@IuV@z|?+5;x6S^ zMyvM3^7lqPdvE({ruO5W5ohgEQCYmGQ7CGh-~Vpc^{!aa<{8VW?e}Q?9AjBN1~HGr5utjs&;F#ND- zkLh5E?gNMIV4?W~zn=UO`@sg|2SGi2?F|c3giI$Tw63vLkQ0`4ESNk_{eU3WYi((C zz)aYQTG}p1^07dkOH+(OlH4Z4ad`vSS46EE8ym0Tm;+KYP&iUdNYNnD zkzz)Q1{r~rETm|V1W2(UMMFk{6f08lGa8MbNU`2j&CLqOu zl(J-AC4>~Gc26V4g?9o<&g2s*Zlq`|Ye?}Rr8=2c2_Yp1DH!8Shm>5TU@6XYNbw@2 zAv2!!jt?nKS}FfXPZlDM=}dG;I$yR1kw8w-Gz?od;3r5+LCk_d2(lrTH9R_mbIzij z8wmIJ%0H~!sATL_%$C*}9`a4m3WH&T1N{RL5%$F-!@wj3rOQy6j09IhNvo4R+=m08 zxL$f-gk#sEJ~t409(TR=oeqlyp*|khAHs0LAoj1Ak|~zJq4Q$)nZ9uE;27Px3dAq* zPXi=Z6|JZ=G#nn`*_KMMfSFj61R5XHnq^fkg%ZujNgG32;_lEY^%L^`hP+S7`zd)p zBkwMGe@ouqk@r8y`=8|fJ$X9JJYG+pfjlF5CV29`8C#0@|Bjq#n_@hzBI9k^3(h^) z)t$5k_2X?^GGKR2jb0j`9)D%`?8CS0W!V3jIsy-3-4DIhxSbV?P8(SzePwd?*%&r+ zaepe#VSS?W`kNE}(rdPF*>HuEzxj4y*|nl?72z5ue=~4&ao}3xw;Go%^b5B_Rb1Qg ztsToY`jxHxvePezuA(*`Sbr<9e%VRCU9fm|?MvVK(z2U=d31rAczNrs^48@X`kkw! zdg+%h`EDNl&QJa>px=I7QRy}RxBSb6^s6YDT1>x7bfuNoj(+Rtaw+{P(-oDo_LtMI zfUbE%ys7I}Q`d3@{jN;5ql$i4>niKw6>YaF+LmkRcdgQ{I{ZS{as|qnpWH5wgts6@SWNVAMja zDT@J7@~QdnqvcFG1E9`yFx+GAH=KcanG+RQlFXmM+nBYGw9>L)GhD1P=_a!#&76MH z0&B4v%LDk&S5Xg{Z_+rvnN&W(VwZRF{l5(#sRtemQZ1o)&)IQD!0?IL31UhPulhGg>;{FUj; zrZJQBd|t2cS+e;f^Yc*1loq$+;|=>|mM5SH)&hegBj-lXL!APA5yvj!tqHdWYQmk; zy3vpR7~ime7^@B4*jp10JUb)rGI45yB&|0@&H>tMn1vyQH^9{wV(eB$^oOGSmL2Of@L}kE|4Rx zuzzF}>cv>gC2I?!lUjfbz3hy$s2Fb`1}tnxWhso6q;B_@D0+Oa_A2*z*wQBfh2hsx zn6&7eZv&@2L*p{zUJNL>&+kfw?;c3n{q@89#7;KOxbVyE3UcUaDxe?GstXH^|3{7 zQ^Mm*s3aUO7xqWH%wrE4%fvRpDRdHoR9 zIE{QtnUF~twHP5Xp8)d)q~Oh5s)R9VVo+Q3%<9>7n<+5uC= zXWA2gPcLpolIYK@1WjU>1+FrI5J&d$_1b7j`3|M9l<&DfScud&+4hFVN9K#;?h3(O z5hIC3Jtk7Zk@M%C0&EDna^ud;x15_3r4{kgokHo(?>+b3=azEv;yIN_x`o(tu8*=6v!+qkyHPEYqwpE8{WJT8#7%-FUMX{6+ zY4R9PQv_n7AS!jD?{*m1{(Yo*r+{k{X0Hv4HZyfHPc{Nyz4}*aM2Joa!X5gQV6!b1 zXcK`+4=c<=q8D;Ox_s&hW%_guD&QV0Q%Z4PvFJF3%Zvv&#+#Rz@pO{va{{8$?_(^e znP@kB$&qJEA6E)V1{!F!63DCNn}$<$H}3J5P^TaYx0S_huF8Blr3eG;ySgI0hWi@y zlEm<9W1@K{T?vI__I1a8iuSuYopAS@$`mt0rR4Dao?rLI+&#qY{@iQP zA15$Bie1M_og?=PI}>NN@##E+38d~g&O83%c_0~>q=UXA_OSxfTzzyN)9ObXH}Z83 znmx{61+ktS@Xy`XbX_%FMkUAM#&F%^k0`EszMlCytzLo`II0^|IS;U;$B0hDFYHHr zPtT&Gpy}Cpv}D4^3Jsy`E-{wMPL<3lyE9)h^G-Aw%T;nuIR;X2>*H5-r;S-t>!00^ zA*Z-jZy+*t$Dm%F#mWCZ&AlnT6cYu_=(;%;S1lEDC&9sFY03woz(_eTNJd53e&go4 zvX<*c^B0NRy@OT3SFhei2Ft#FyJbmR&IA*z8EX+NxR?TX)9R4P;x-M_3#!#2ufZ)= zY7++266zuzh`EBPM$IRP=_T+CR+V7=k!Brbf3or-#_-&p)c@4rv5))28^@YY4Htj; zv*ImOd-Wn7fO>vz{NB@dPrVo2DO}nvz{OrS)`ioD;G6PFW#sc5+(Y)Dxby7)C^>lV zJ8!2y7&(I-`5!J9Q?PZ@MrVu3LFw`ZG(&3mZPr^_z}`{KxW-(w0h;6h{dBZ@pS8uV zfsD<}_Y;_s9H2eDC9~Iww#A0+@w^jZdTwr?sZ_^e$*%33X_Z(f@(4=pfOJnoMD>k< zy7@K_fzB1MBsZ6DB4C)fRmbQH%<2Ts$zmeQiYzcf5J;Op=HF4(1JC@Kd7|jY{qI0oe??^~ zL(`7IE0w37sY=GljzbH+GIqu>B=g*5l>sJ&^ZIbYEa8yWl1h!bHtxlm>56o!p4 zJDYPNOi!Fs=>^31!@0Adr;Sm&7lI_DmCqb<45oc^Ri?GkE?PeV)TR>#giZizitxQH z;^q5?i_Y}wJT5&3QFS)ApOL6#}GT?`*6_MNw;A_TnGXdMyqu2@%6KEMO z#1Pn&SERuWh));l*fR8=!q3Z60pRC|(i3$tHKiu_rSSmn^)KOmQ%E0{B?oj&n{F9} zvAIXkL=+CA6v7%p3En=s%zRGu`h9f4x}9GZ*AbVNd<6SGQC0zEDCNS`o!PC6TUYHw z8kEM?<`351%={+%Ru*=B37hzL>(rg-hi1>)ZSS|g(=J)Hh~n@3gI$BKUUlD0QEx<;wwqz46Q=K8EhHq6hto2L3<)zsuwlM_X= ziEk~wd3^t0J(QFlS{`uc7JErr`-EQl2^-(zH=ex|nw@{-8<_EWO0kB;_MB*mPM6X% z#l%dgvy{ZWlsr*1Psj)cg~MQ#!LsQumRRJrP;4lOXs{G;;8^Swi}c9o)Cz@$?%_SB4Hv>NAiyL-%uFjF}^UX?2kQxW6%!?T>wX z-+VH7RK<`d-&Ib9t}@QXibV#joDMF(;;LsV0z(KK?!A{o<*6vU+)=WGO{1t>wl&HJ zgK}2atXqrp;-I`x2z|s2a7(mhgeehge$q4&-`=7sYB>$#6xR(z-t_`uy~jS=@3MU*?9|LV01H|FLq%zg3F!o~7|pt6fA zsAmt$c$I+ib?a9I|01C6zA|MMvOtE*)BItafVx*@bM}>$rCZ;;`30*0e1QA4)!zd^ z<3iW>w81^?@Sb*3J}36H(LF8qiFS5dJNt?DQmsXU6s?Ab)?5A|a92CDtHpM;1G`%L zu9n!g*Q{)d;BC(xF_Xm;gz38$1*7Fhly1w=7&o1A+{6=D5lhgf$)|Yhs^lK~k z;I4qV+D6NZx*mU^5!TjPUWn>n(;sM()V^g7>q8GTfZ8?vMnoTe08@K?xOTp+TR-_w I1CW;f7hUCLApigX literal 0 HcmV?d00001 diff --git a/librespot/audio/__pycache__/decoders.cpython-312.pyc b/librespot/audio/__pycache__/decoders.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..0945a576b79297cf12f81f4b71dc1fdc037f1100 GIT binary patch literal 4330 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 literal 0 HcmV?d00001 diff --git a/librespot/audio/decoders.py b/librespot/audio/decoders.py new file mode 100644 index 0000000..ddb726c --- /dev/null +++ b/librespot/audio/decoders.py @@ -0,0 +1,81 @@ +from __future__ import annotations +from librespot.audio import SuperAudioFormat +from librespot.proto import Metadata_pb2 as Metadata +from librespot.proto.Metadata_pb2 import AudioFile +from librespot.structure import AudioQualityPicker +import enum +import logging +import typing + + +class AudioQuality(enum.Enum): + NORMAL = 0x00 + HIGH = 0x01 + VERY_HIGH = 0x02 + + @staticmethod + def get_quality(audio_format: AudioFile.Format) -> AudioQuality: + if audio_format in [ + AudioFile.MP3_96, + AudioFile.OGG_VORBIS_96, + AudioFile.AAC_24_NORM, + ]: + return AudioQuality.NORMAL + if audio_format in [ + AudioFile.MP3_160, + AudioFile.MP3_160_ENC, + AudioFile.OGG_VORBIS_160, + AudioFile.AAC_24, + ]: + return AudioQuality.HIGH + if audio_format in [ + AudioFile.MP3_320, + AudioFile.MP3_256, + AudioFile.OGG_VORBIS_320, + AudioFile.AAC_48, + ]: + return AudioQuality.VERY_HIGH + raise RuntimeError("Unknown format: {}".format(format)) + + def get_matches(self, + files: typing.List[AudioFile]) -> typing.List[AudioFile]: + file_list = [] + for file in files: + if hasattr(file, "format") and AudioQuality.get_quality( + file.format) == self: + file_list.append(file) + return file_list + + +class VorbisOnlyAudioQuality(AudioQualityPicker): + logger = logging.getLogger("Librespot:Player:VorbisOnlyAudioQuality") + preferred: AudioQuality + + def __init__(self, preferred: AudioQuality): + self.preferred = preferred + + @staticmethod + def get_vorbis_file(files: typing.List[Metadata.AudioFile]): + for file in files: + if file.HasField("format") and SuperAudioFormat.get( + file.format) == SuperAudioFormat.VORBIS: + return file + return None + + def get_file(self, files: typing.List[Metadata.AudioFile]): + matches: typing.List[Metadata.AudioFile] = self.preferred.get_matches( + files) + vorbis: Metadata.AudioFile = VorbisOnlyAudioQuality.get_vorbis_file( + matches) + if vorbis is None: + vorbis: Metadata.AudioFile = VorbisOnlyAudioQuality.get_vorbis_file( + files) + if vorbis is not None: + self.logger.warning( + "Using {} because preferred {} couldn't be found.".format( + Metadata.AudioFile.Format.Name(vorbis.format), + self.preferred)) + else: + self.logger.fatal( + "Couldn't find any Vorbis file, available: {}") + return vorbis diff --git a/librespot/audio/decrypt.py b/librespot/audio/decrypt.py new file mode 100644 index 0000000..e72cd37 --- /dev/null +++ b/librespot/audio/decrypt.py @@ -0,0 +1,45 @@ +from __future__ import annotations +from Cryptodome.Cipher import AES +from Cryptodome.Util import Counter +from librespot.audio.storage import ChannelManager +from librespot.structure import AudioDecrypt +import io +import time + + +class AesAudioDecrypt(AudioDecrypt): + audio_aes_iv = b'r\xe0g\xfb\xdd\xcb\xcfw\xeb\xe8\xbcd?c\r\x93' + cipher = None + decrypt_count = 0 + decrypt_total_time = 0 + iv_int = int.from_bytes(audio_aes_iv, "big") + iv_diff = 0x100 + key: bytes + + def __init__(self, key: bytes): + self.key = key + + def decrypt_chunk(self, chunk_index: int, buffer: bytes): + new_buffer = io.BytesIO() + iv = self.iv_int + int(ChannelManager.chunk_size * chunk_index / 16) + start = time.time_ns() + for i in range(0, len(buffer), 4096): + cipher = AES.new(key=self.key, + mode=AES.MODE_CTR, + counter=Counter.new(128, initial_value=iv)) + count = min(4096, len(buffer) - i) + decrypted_buffer = cipher.decrypt(buffer[i:i + count]) + new_buffer.write(decrypted_buffer) + if count != len(decrypted_buffer): + raise RuntimeError( + "Couldn't process all data, actual: {}, expected: {}". + format(len(decrypted_buffer), count)) + iv += self.iv_diff + self.decrypt_total_time += time.time_ns() - start + self.decrypt_count += 1 + new_buffer.seek(0) + return new_buffer.read() + + def decrypt_time_ms(self): + return 0 if self.decrypt_count == 0 else int( + (self.decrypt_total_time / self.decrypt_count) / 1000000) diff --git a/librespot/audio/format.py b/librespot/audio/format.py new file mode 100644 index 0000000..24cb6d9 --- /dev/null +++ b/librespot/audio/format.py @@ -0,0 +1,32 @@ +from librespot.proto import Metadata_pb2 as Metadata +import enum + + +class SuperAudioFormat(enum.Enum): + MP3 = 0x00 + VORBIS = 0x01 + AAC = 0x02 + + @staticmethod + def get(audio_format: Metadata.AudioFile.Format): + if audio_format in [ + Metadata.AudioFile.Format.OGG_VORBIS_96, + Metadata.AudioFile.Format.OGG_VORBIS_160, + Metadata.AudioFile.Format.OGG_VORBIS_320, + ]: + return SuperAudioFormat.VORBIS + if audio_format in [ + Metadata.AudioFile.Format.MP3_256, + Metadata.AudioFile.Format.MP3_320, + Metadata.AudioFile.Format.MP3_160, + Metadata.AudioFile.Format.MP3_96, + Metadata.AudioFile.Format.MP3_160_ENC, + ]: + return SuperAudioFormat.MP3 + if audio_format in [ + Metadata.AudioFile.Format.AAC_24, + Metadata.AudioFile.Format.AAC_48, + Metadata.AudioFile.Format.AAC_24_NORM, + ]: + return SuperAudioFormat.AAC + raise RuntimeError("Unknown audio format: {}".format(audio_format)) diff --git a/librespot/audio/storage.py b/librespot/audio/storage.py new file mode 100644 index 0000000..51321e6 --- /dev/null +++ b/librespot/audio/storage.py @@ -0,0 +1,139 @@ +from __future__ import annotations +from librespot import util +from librespot.crypto import Packet +from librespot.proto.Metadata_pb2 import AudioFile +from librespot.structure import Closeable, PacketsReceiver +import concurrent.futures +import io +import logging +import queue +import struct +import threading +import typing + +if typing.TYPE_CHECKING: + from librespot.core import Session + + +class ChannelManager(Closeable, PacketsReceiver): + channels: typing.Dict[int, Channel] = {} + chunk_size = 128 * 1024 + executor_service = concurrent.futures.ThreadPoolExecutor() + logger = logging.getLogger("Librespot:ChannelManager") + seq_holder = 0 + seq_holder_lock = threading.Condition() + __session: Session = None + + def __init__(self, session: Session): + self.__session = session + + def request_chunk(self, file_id: bytes, index: int, file: AudioFile): + start = int(index * self.chunk_size / 4) + end = int((index + 1) * self.chunk_size / 4) + channel = ChannelManager.Channel(self, file, index) + self.channels[channel.chunk_id] = channel + out = io.BytesIO() + out.write(struct.pack(">H", channel.chunk_id)) + out.write(struct.pack(">i", 0x00000000)) + out.write(struct.pack(">i", 0x00000000)) + out.write(struct.pack(">i", 0x00004E20)) + out.write(struct.pack(">i", 0x00030D40)) + out.write(file_id) + out.write(struct.pack(">i", start)) + out.write(struct.pack(">i", end)) + out.seek(0) + self.__session.send(Packet.Type.stream_chunk, out.read()) + + def dispatch(self, packet: Packet) -> None: + payload = io.BytesIO(packet.payload) + if packet.is_cmd(Packet.Type.stream_chunk_res): + chunk_id = struct.unpack(">H", payload.read(2))[0] + channel = self.channels.get(chunk_id) + if channel is None: + self.logger.warning( + "Couldn't find channel, id: {}, received: {}".format( + chunk_id, len(packet.payload))) + return + channel.add_to_queue(payload) + elif packet.is_cmd(Packet.Type.channel_error): + chunk_id = struct.unpack(">H", payload.read(2))[0] + channel = self.channels.get(chunk_id) + if channel is None: + self.logger.warning( + "Dropping channel error, id: {}, code: {}".format( + chunk_id, + struct.unpack(">H", payload.read(2))[0])) + return + channel.stream_error(struct.unpack(">H", payload.read(2))[0]) + else: + self.logger.warning( + "Couldn't handle packet, cmd: {}, payload: {}".format( + packet.cmd, util.bytes_to_hex(packet.payload))) + + def close(self) -> None: + self.executor_service.shutdown() + + class Channel: + channel_manager: ChannelManager + chunk_id: int + q = queue.Queue() + __buffer: io.BytesIO + __chunk_index: int + __file: AudioFile + __header: bool = True + + def __init__(self, channel_manager: ChannelManager, file: AudioFile, + chunk_index: int): + self.__buffer = io.BytesIO() + self.channel_manager = channel_manager + self.__file = file + self.__chunk_index = chunk_index + with self.channel_manager.seq_holder_lock: + self.chunk_id = self.channel_manager.seq_holder + self.channel_manager.seq_holder += 1 + self.channel_manager.executor_service.submit( + lambda: ChannelManager.Channel.Handler(self)) + + def _handle(self, payload: bytes) -> bool: + if len(payload) == 0: + if not self.__header: + self.__file.write_chunk(payload, self.__chunk_index, False) + return True + self.channel_manager.logger.debug( + "Received empty chunk, skipping.") + return False + if self.__header: + length: int + while len(payload.buffer) > 0: + length = payload.read_short() + if not length > 0: + break + header_id = payload.read_byte() + header_data = payload.read(length - 1) + self.__file.write_header(int.from_bytes(header_id, "big"), + bytearray(header_data), False) + self.__header = False + else: + self.__buffer.write(payload.read(len(payload.buffer))) + return False + + def add_to_queue(self, payload): + self.q.put(payload) + + def stream_error(self, code: int) -> None: + self.__file.stream_error(self.__chunk_index, code) + + class Handler: + __channel: ChannelManager.Channel = None + + def __init__(self, channel: ChannelManager.Channel): + self.__channel = channel + + def run(self) -> None: + self.__channel.channel_manager.logger.debug( + "ChannelManager.Handler is starting") + with self.__channel.q.all_tasks_done: + self.__channel.channel_manager.channels.pop( + self.__channel.chunk_id) + self.__channel.channel_manager.logger.debug( + "ChannelManager.Handler is shutting down") diff --git a/librespot/cache.py b/librespot/cache.py new file mode 100644 index 0000000..7937c46 --- /dev/null +++ b/librespot/cache.py @@ -0,0 +1,18 @@ +from __future__ import annotations +import typing + +if typing.TYPE_CHECKING: + from librespot.core import Session + + +class CacheManager: + clean_up_threshold = 604800000 + header_hash = 253 + header_timestamp = 254 + parent: str + + def __init__(self, session: Session): + """ + @Todo Implement function + :param session: + """ diff --git a/librespot/core.py b/librespot/core.py new file mode 100644 index 0000000..486f0fe --- /dev/null +++ b/librespot/core.py @@ -0,0 +1,2758 @@ +from __future__ import annotations + +import base64 +import binascii +import concurrent.futures +import enum +import gzip +import io +import json +import logging +import os +import random +import sched +import socket +import struct +import threading +import time +import typing +import urllib.parse +from collections.abc import Iterable + +import defusedxml.ElementTree +import requests +import websocket +from google.protobuf import message as _message +from Cryptodome import Random +from Cryptodome.Cipher import AES +from Cryptodome.Hash import HMAC +from Cryptodome.Hash import SHA1 +from Cryptodome.Protocol.KDF import PBKDF2 +from Cryptodome.PublicKey import RSA +from Cryptodome.Signature import PKCS1_v1_5 + +from librespot import util +from librespot import Version +from librespot.audio import AudioKeyManager +from librespot.audio import CdnManager +from librespot.audio import PlayableContentFeeder +from librespot.audio.storage import ChannelManager +from librespot.cache import CacheManager +from librespot.crypto import CipherPair +from librespot.crypto import DiffieHellman +from librespot.crypto import Packet +from librespot.mercury import MercuryClient +from librespot.mercury import MercuryRequests +from librespot.mercury import RawMercuryRequest +from librespot.metadata import AlbumId +from librespot.metadata import ArtistId +from librespot.metadata import EpisodeId +from librespot.metadata import PlaylistId +from librespot.metadata import ShowId +from librespot.metadata import TrackId +from librespot.proto import Authentication_pb2 as Authentication +from librespot.proto import ClientToken_pb2 as ClientToken +from librespot.proto import Connect_pb2 as Connect +from librespot.proto import Connectivity_pb2 as Connectivity +from librespot.proto import Keyexchange_pb2 as Keyexchange +from librespot.proto import Metadata_pb2 as Metadata +from librespot.proto import Playlist4External_pb2 as Playlist4External +from librespot.proto_ext import audio_files_extension_pb2 +from librespot.proto_ext import extended_metadata_pb2 +from librespot.proto_ext import extension_kind_pb2 +try: + from librespot.proto.spotify.login5.v3 import Login5_pb2 as Login5 + from librespot.proto.spotify.login5.v3 import ClientInfo_pb2 as Login5ClientInfo + from librespot.proto.spotify.login5.v3.credentials import Credentials_pb2 as Login5Credentials + LOGIN5_AVAILABLE = True +except ImportError as e: + # Login5 protobuf files not available, will use fallback + LOGIN5_AVAILABLE = False + Login5 = None + Login5ClientInfo = None + Login5Credentials = None +from librespot.proto.ExplicitContentPubsub_pb2 import UserAttributesUpdate +from librespot.structure import Closeable +from librespot.structure import MessageListener +from librespot.structure import RequestListener +from librespot.structure import SubListener + + +class ApiClient(Closeable): + """ """ + logger = logging.getLogger("Librespot:ApiClient") + __base_url: str + __client_token_str: str = None + __session: Session + + def __init__(self, session: Session): + self.__session = session + self.__base_url = "https://{}".format(ApResolver.get_random_spclient()) + + def build_request( + self, + method: str, + suffix: str, + headers: typing.Union[None, typing.Dict[str, str]], + body: typing.Union[None, bytes], + url: typing.Union[None, str], + ) -> requests.PreparedRequest: + """ + + :param method: str: + :param suffix: str: + :param headers: typing.Union[None: + :param typing.Dict[str: + :param str]]: + :param body: typing.Union[None: + :param bytes]: + :param url: typing.Union[None: + :param str]: + + """ + if self.__client_token_str is None: + resp = self.__client_token() + self.__client_token_str = resp.granted_token.token + self.logger.debug("Updated client token: {}".format( + self.__client_token_str)) + + merged_headers: dict[str, str] = {} + if headers is not None: + merged_headers.update(headers) + + if "Authorization" not in merged_headers: + merged_headers["Authorization"] = "Bearer {}".format( + self.__session.tokens().get("playlist-read")) + + if "client-token" not in merged_headers: + merged_headers["client-token"] = self.__client_token_str + + full_url = (self.__base_url if url is None else url) + suffix + request = requests.Request( + method=method, + url=full_url, + headers=merged_headers, + data=body, + ) + session = self.__session.client() + return session.prepare_request(request) + + def send( + self, + method: str, + suffix: str, + headers: typing.Union[None, typing.Dict[str, str]], + body: typing.Union[None, bytes], + ) -> requests.Response: + """ + + :param method: str: + :param suffix: str: + :param headers: typing.Union[None: + :param typing.Dict[str: + :param str]]: + :param body: typing.Union[None: + :param bytes]: + + """ + response = self.__session.client().send( + self.build_request(method, suffix, headers, body, None)) + return response + + def sendToUrl( + self, + method: str, + url: str, + suffix: str, + headers: typing.Union[None, typing.Dict[str, str]], + body: typing.Union[None, bytes], + ) -> requests.Response: + """ + :param method: str: + :param url: str: + :param suffix: str: + :param headers: typing.Union[None: + :param typing.Dict[str: + :param str]]: + :param body: typing.Union[None: + :param bytes]: + """ + response = self.__session.client().send( + self.build_request(method, suffix, headers, body, url)) + return response + + def put_connect_state(self, connection_id: str, + proto: Connect.PutStateRequest) -> None: + """ + + :param connection_id: str: + :param proto: Connect.PutStateRequest: + + """ + response = self.send( + "PUT", + "/connect-state/v1/devices/{}".format(self.__session.device_id()), + { + "Content-Type": "application/protobuf", + "X-Spotify-Connection-Id": connection_id, + }, + proto.SerializeToString(), + ) + if response.status_code == 413: + self.logger.warning( + "PUT state payload is too large: {} bytes uncompressed.". + format(len(proto.SerializeToString()))) + elif response.status_code != 200: + self.logger.warning("PUT state returned {}. headers: {}".format( + response.status_code, response.headers)) + + def get_metadata_4_track(self, track: TrackId) -> Metadata.Track: + """ + + :param track: TrackId: + + """ + response = self.sendToUrl("GET", "https://spclient.wg.spotify.com", + "/metadata/4/track/{}".format(track.hex_id()), + None, None) + ApiClient.StatusCodeException.check_status(response) + body = response.content + if body is None: + raise RuntimeError() + proto = Metadata.Track() + proto.ParseFromString(body) + return proto + + def get_metadata_4_episode(self, episode: EpisodeId) -> Metadata.Episode: + """ + + :param episode: EpisodeId: + + """ + response = self.sendToUrl("GET", "https://spclient.wg.spotify.com", + "/metadata/4/episode/{}".format(episode.hex_id()), + None, None) + ApiClient.StatusCodeException.check_status(response) + body = response.content + if body is None: + raise IOError() + proto = Metadata.Episode() + proto.ParseFromString(body) + return proto + + def get_metadata_4_album(self, album: AlbumId) -> Metadata.Album: + """ + + :param album: AlbumId: + + """ + response = self.sendToUrl("GET", "https://spclient.wg.spotify.com", + "/metadata/4/album/{}".format(album.hex_id()), + None, None) + ApiClient.StatusCodeException.check_status(response) + + body = response.content + if body is None: + raise IOError() + proto = Metadata.Album() + proto.ParseFromString(body) + return proto + + def get_metadata_4_artist(self, artist: ArtistId) -> Metadata.Artist: + """ + + :param artist: ArtistId: + + """ + response = self.sendToUrl("GET", "https://spclient.wg.spotify.com", + "/metadata/4/artist/{}".format(artist.hex_id()), + None, None) + ApiClient.StatusCodeException.check_status(response) + body = response.content + if body is None: + raise IOError() + proto = Metadata.Artist() + proto.ParseFromString(body) + return proto + + def get_metadata_4_show(self, show: ShowId) -> Metadata.Show: + """ + + :param show: ShowId: + + """ + response = self.send("GET", + "/metadata/4/show/{}".format(show.hex_id()), None, + None) + ApiClient.StatusCodeException.check_status(response) + body = response.content + if body is None: + raise IOError() + proto = Metadata.Show() + proto.ParseFromString(body) + return proto + + def get_playlist(self, + _id: PlaylistId) -> Playlist4External.SelectedListContent: + """ + + :param _id: PlaylistId: + + """ + response = self.send("GET", + "/playlist/v2/playlist/{}".format(_id.id()), None, + None) + ApiClient.StatusCodeException.check_status(response) + body = response.content + if body is None: + raise IOError() + proto = Playlist4External.SelectedListContent() + proto.ParseFromString(body) + return proto + + def get_audio_files_extension( + self, track: TrackId + ) -> typing.Optional[audio_files_extension_pb2.AudioFilesExtensionResponse]: + """Fetch audio file metadata via extended metadata for a given track.""" + spotify_uri = track.to_spotify_uri() + + request = extended_metadata_pb2.BatchedEntityRequest() + + header = request.header + + def _resolve_country_code() -> typing.Optional[str]: + code = getattr(self.__session, "_Session__country_code", None) + if code: + code = str(code).strip().upper() + if len(code) == 2 and code.isalpha(): + return code + return None + + country_code = _resolve_country_code() + if country_code: + header.country = country_code + + try: + catalogue = self.__session.ap_welcome().catalogue + except AttributeError: + catalogue = None + except Exception: # pragma: no cover - defensive guard if ap_welcome raises + catalogue = None + if catalogue: + header.catalogue = catalogue + + entity_request = request.entity_request.add() + entity_request.entity_uri = spotify_uri + query = entity_request.query.add() + query.extension_kind = extension_kind_pb2.ExtensionKind.AUDIO_FILES + + request_bytes = request.SerializeToString() + + def _decode_audio_files_extension( + payload: typing.Optional[typing.Union[bytes, bytearray, typing.Iterable[bytes]]] + ) -> typing.Optional[audio_files_extension_pb2.AudioFilesExtensionResponse]: + if not payload: + return None + + if isinstance(payload, (bytes, bytearray)): + payload_bytes = bytes(payload) + elif isinstance(payload, Iterable): # Mercury responses sometimes return payload parts + payload_bytes = b"".join(typing.cast(typing.Iterable[bytes], payload)) + else: + payload_bytes = bytes(payload) + + batch_response = extended_metadata_pb2.BatchedExtensionResponse() + try: + batch_response.ParseFromString(payload_bytes) + except _message.DecodeError: + self.logger.debug( + "Failed to parse extended metadata payload for %s", + spotify_uri, + exc_info=True, + ) + return None + + for extension_array in batch_response.extended_metadata: + if extension_array.extension_kind != extension_kind_pb2.ExtensionKind.AUDIO_FILES: + continue + for entity in extension_array.extension_data: + if entity.entity_uri and entity.entity_uri != spotify_uri: + continue + if not entity.HasField("extension_data"): + continue + + audio_response = audio_files_extension_pb2.AudioFilesExtensionResponse() + try: + entity.extension_data.Unpack(audio_response) + except (ValueError, _message.DecodeError): + try: + audio_response.ParseFromString(entity.extension_data.value) + except _message.DecodeError: + self.logger.debug( + "Failed to unpack audio files extension for %s", + spotify_uri, + exc_info=True, + ) + continue + return audio_response + + return None + + # Prefer the HTTPS extended metadata endpoint; fall back to Mercury if necessary. + login5_token = None + try: + login5_token = self.__session.get_login5_token() + except Exception: # pragma: no cover - defensive guard if session raises unexpectedly + login5_token = None + + bearer_token = login5_token + if not bearer_token: + try: + bearer_token = self.__session.tokens().get("playlist-read") + except Exception: + bearer_token = None + + headers = { + "Content-Type": "application/x-protobuf", + "Accept": "application/x-protobuf", + "Content-Length": str(len(request_bytes)), + } + if bearer_token: + headers["Authorization"] = f"Bearer {bearer_token}" + + preferred_locale = getattr(self.__session, "preferred_locale", None) + if callable(preferred_locale): # Session.preferred_locale() is a method + try: + locale_value = preferred_locale() + except Exception: + locale_value = None + else: + locale_value = preferred_locale + if isinstance(locale_value, str) and locale_value: + headers.setdefault("Accept-Language", locale_value) + + query_params: dict[str, str] = {"product": "0"} + if country_code: + query_params["country"] = country_code + query_params["salt"] = str(random.randint(0, 0xFFFFFFFF)) + + suffix = "/extended-metadata/v0/extended-metadata?" + urllib.parse.urlencode(query_params) + + def _http_post(url_override: typing.Optional[str]) -> typing.Optional[requests.Response]: + target_headers = headers.copy() + for attempt in range(2): + try: + if url_override is None: + response = self.send("POST", suffix, target_headers, request_bytes) + else: + response = self.sendToUrl("POST", url_override, suffix, target_headers, request_bytes) + except Exception as exc: # pragma: no cover - network errors handled gracefully + self.logger.debug( + "Extended metadata HTTP request failed for %s via %s: %s", + spotify_uri, + url_override or "AP host", + exc, + ) + return None + + if response is not None and response.status_code in (401, 403): + self.logger.debug( + "Extended metadata HTTP returned %s for %s; refreshing client token", + response.status_code, + spotify_uri, + ) + self.__client_token_str = None + target_headers.pop("client-token", None) + continue + + return response + + return None + + http_response = _http_post(None) + + if http_response is None or http_response.status_code != 200: + http_response = _http_post("https://spclient.wg.spotify.com") + + if http_response is not None: + if http_response.status_code == 200: + http_payload: typing.Optional[bytes] + if isinstance(http_response.content, (bytes, bytearray)): + http_payload = bytes(http_response.content) + else: + http_payload = None + http_extension = _decode_audio_files_extension(http_payload) + if http_extension is not None: + return http_extension + else: + self.logger.debug( + "Extended metadata HTTP returned status %s for %s", + http_response.status_code, + spotify_uri, + ) + + mercury_request = ( + RawMercuryRequest.new_builder() + .set_uri("hm://extendedmetadata/v1/entity") + .set_method("POST") + .set_content_type("application/x-protobuf") + .add_payload_part(request_bytes) + .build() + ) + + try: + response = self.__session.mercury().send_sync(mercury_request) + except Exception as exc: # pragma: no cover - network errors handled gracefully + self.logger.debug( + "Extended metadata request failed for %s: %s", + spotify_uri, + exc, + ) + return None + + if response.status_code != 200 or not response.payload: + self.logger.debug( + "Extended metadata returned status %s for %s", + response.status_code, + spotify_uri, + ) + return None + + return _decode_audio_files_extension(response.payload) + + def set_client_token(self, client_token): + """ + + :param client_token: + + """ + self.__client_token_str = client_token + + def __client_token(self): + proto_req = ClientToken.ClientTokenRequest( + request_type=ClientToken.ClientTokenRequestType. + REQUEST_CLIENT_DATA_REQUEST, + client_data=ClientToken.ClientDataRequest( + client_id=MercuryRequests.keymaster_client_id, + client_version=Version.version_name, + connectivity_sdk_data=Connectivity.ConnectivitySdkData( + device_id=self.__session.device_id(), + platform_specific_data=Connectivity.PlatformSpecificData( + windows=Connectivity.NativeWindowsData( + something1=10, + something3=21370, + something4=2, + something6=9, + something7=332, + something8=33404, + something10=True, + ), ), + ), + ), + ) + + resp = requests.post( + "https://clienttoken.spotify.com/v1/clienttoken", + proto_req.SerializeToString(), + headers={ + "Accept": "application/x-protobuf", + "Content-Encoding": "", + }, + ) + + ApiClient.StatusCodeException.check_status(resp) + + proto_resp = ClientToken.ClientTokenResponse() + proto_resp.ParseFromString(resp.content) + return proto_resp + + class StatusCodeException(IOError): + """ """ + code: int + + def __init__(self, response: requests.Response): + super().__init__(response.status_code) + self.code = response.status_code + + @staticmethod + def check_status(response: requests.Response) -> None: + """ + + :param response: requests.Response: + + """ + if response.status_code != 200: + raise ApiClient.StatusCodeException(response) + + +class ApResolver: + """ """ + base_url = "https://apresolve.spotify.com/" + + @staticmethod + def request(service_type: str) -> typing.Any: + """Gets the specified ApResolve + + :param service_type: str: + :returns: The resulting object will be returned + + """ + response = requests.get("{}?type={}".format(ApResolver.base_url, + service_type)) + if response.status_code != 200: + if response.status_code == 502: + raise RuntimeError( + f"ApResolve request failed with the following return value: {response.content}. Servers might be down!" + ) + return response.json() + + @staticmethod + def get_random_of(service_type: str) -> str: + """Gets the specified random ApResolve url + + :param service_type: str: + :returns: A random ApResolve url will be returned + + """ + pool = ApResolver.request(service_type) + urls = pool.get(service_type) + if urls is None or len(urls) == 0: + raise RuntimeError("No ApResolve url available") + return random.choice(urls) + + @staticmethod + def get_random_dealer() -> str: + """Get dealer endpoint url + + + :returns: dealer endpoint url + + """ + return ApResolver.get_random_of("dealer") + + @staticmethod + def get_random_spclient() -> str: + """Get spclient endpoint url + + + :returns: spclient endpoint url + + """ + return ApResolver.get_random_of("spclient") + + @staticmethod + def get_random_accesspoint() -> str: + """Get accesspoint endpoint url + + + :returns: accesspoint endpoint url + + """ + return ApResolver.get_random_of("accesspoint") + + +class DealerClient(Closeable): + """ """ + logger = logging.getLogger("Librespot:DealerClient") + __connection: typing.Union[ConnectionHolder, None] + __last_scheduled_reconnection: typing.Union[sched.Event, None] + __message_listeners: typing.Dict[MessageListener, typing.List[str]] = {} + __message_listeners_lock = threading.Condition() + __request_listeners: typing.Dict[str, RequestListener] = {} + __request_listeners_lock = threading.Condition() + __scheduler = sched.scheduler() + __session: Session + __worker = concurrent.futures.ThreadPoolExecutor() + + def __init__(self, session: Session): + self.__session = session + + def add_message_listener(self, listener: MessageListener, + uris: list[str]) -> None: + """ + + :param listener: MessageListener: + :param uris: list[str]: + + """ + with self.__message_listeners_lock: + if listener in self.__message_listeners: + raise TypeError( + "A listener for {} has already been added.".format(uris)) + self.__message_listeners[listener] = uris + self.__message_listeners_lock.notify_all() + + def add_request_listener(self, listener: RequestListener, uri: str): + """ + + :param listener: RequestListener: + :param uri: str: + + """ + with self.__request_listeners_lock: + if uri in self.__request_listeners: + raise TypeError( + "A listener for '{}' has already been added.".format(uri)) + self.__request_listeners[uri] = listener + self.__request_listeners_lock.notify_all() + + def close(self) -> None: + """ """ + self.__worker.shutdown() + + def connect(self) -> None: + """ """ + self.__connection = DealerClient.ConnectionHolder( + self.__session, + self, + "wss://{}/?access_token={}".format( + ApResolver.get_random_dealer(), + self.__session.tokens().get("playlist-read"), + ), + ) + + def connection_invalided(self) -> None: + """ """ + self.__connection = None + self.logger.debug("Scheduled reconnection attempt in 10 seconds...") + + def anonymous(): + """ """ + self.__last_scheduled_reconnection = None + self.connect() + + self.__last_scheduled_reconnection = self.__scheduler.enter( + 10, 1, anonymous) + + def handle_message(self, obj: typing.Any) -> None: + """ + + :param obj: typing.Any: + + """ + uri = obj.get("uri") + headers = self.__get_headers(obj) + payloads = obj.get("payloads") + decoded_payloads: typing.Any + if payloads is not None: + if headers.get("Content-Type") == "application/json": + decoded_payloads = payloads + elif headers.get("Content-Type") == "plain/text": + decoded_payloads = payloads + else: + decoded_payloads = base64.b64decode(payloads) + if headers.get("Transfer-Encoding") == "gzip": + decoded_payloads = gzip.decompress(decoded_payloads) + else: + decoded_payloads = b"" + interesting = False + with self.__message_listeners_lock: + for listener in self.__message_listeners: + dispatched = False + keys = self.__message_listeners.get(listener) + for key in keys: + if uri.startswith(key) and not dispatched: + interesting = True + + def anonymous(): + """ """ + listener.on_message(uri, headers, decoded_payloads) + + self.__worker.submit(anonymous) + dispatched = True + if not interesting: + self.logger.debug("Couldn't dispatch message: {}".format(uri)) + + def handle_request(self, obj: typing.Any) -> None: + """ + + :param obj: typing.Any: + + """ + mid = obj.get("message_ident") + key = obj.get("key") + headers = self.__get_headers(obj) + payload = obj.get("payload") + if headers.get("Transfer-Encoding") == "gzip": + gz = base64.b64decode(payload.get("compressed")) + payload = json.loads(gzip.decompress(gz)) + pid = payload.get("message_id") + sender = payload.get("sent_by_device_id") + command = payload.get("command") + self.logger.debug( + "Received request. [mid: {}, key: {}, pid: {}, sender: {}, command: {}]" + .format(mid, key, pid, sender, command)) + interesting = False + with self.__request_listeners_lock: + for mid_prefix in self.__request_listeners: + if mid.startswith(mid_prefix): + listener = self.__request_listeners.get(mid_prefix) + interesting = True + + def anonymous(): + """ """ + result = listener.on_request(mid, pid, sender, command) + if self.__connection is not None: + self.__connection.send_reply(key, result) + self.logger.warning( + "Handled request. [key: {}, result: {}]".format( + key, result)) + + self.__worker.submit(anonymous) + if not interesting: + self.logger.debug("Couldn't dispatch request: {}".format(mid)) + + def remove_message_listener(self, listener: MessageListener) -> None: + """ + + :param listener: MessageListener: + + """ + with self.__message_listeners_lock: + self.__message_listeners.pop(listener) + + def remove_request_listener(self, listener: RequestListener) -> None: + """ + + :param listener: RequestListener: + + """ + with self.__request_listeners_lock: + request_listeners = {} + for key, value in self.__request_listeners.items(): + if value != listener: + request_listeners[key] = value + self.__request_listeners = request_listeners + + def wait_for_listener(self) -> None: + """ """ + with self.__message_listeners_lock: + if self.__message_listeners == {}: + return + self.__message_listeners_lock.wait() + + def __get_headers(self, obj: typing.Any) -> dict[str, str]: + headers = obj.get("headers") + if headers is None: + return {} + return headers + + class ConnectionHolder(Closeable): + """ """ + __closed = False + __dealer_client: DealerClient + __last_scheduled_ping: sched.Event + __received_pong = False + __scheduler = sched.scheduler() + __session: Session + __url: str + __ws: websocket.WebSocketApp + + def __init__(self, session: Session, dealer_client: DealerClient, + url: str): + self.__session = session + self.__dealer_client = dealer_client + self.__url = url + self.__ws = websocket.WebSocketApp(url) + + def close(self): + """ """ + if not self.__closed: + self.__ws.close() + self.__closed = True + if self.__last_scheduled_ping is not None: + self.__scheduler.cancel(self.__last_scheduled_ping) + + def on_failure(self, ws: websocket.WebSocketApp, error): + """ + + :param ws: websocket.WebSocketApp: + :param error: + + """ + if self.__closed: + return + self.__dealer_client.logger.warning( + "An exception occurred. Reconnecting...") + self.close() + + def on_message(self, ws: websocket.WebSocketApp, text: str): + """ + + :param ws: websocket.WebSocketApp: + :param text: str: + + """ + obj = json.loads(text) + self.__dealer_client.wait_for_listener() + typ = MessageType.parse(obj.get("type")) + if typ == MessageType.MESSAGE: + self.__dealer_client.handle_message(obj) + elif typ == MessageType.REQUEST: + self.__dealer_client.handle_request(obj) + elif typ == MessageType.PONG: + self.__received_pong = True + elif typ == MessageType.PING: + pass + else: + raise RuntimeError("Unknown message type for {}".format( + typ.value)) + + def on_open(self, ws: websocket.WebSocketApp): + """ + + :param ws: websocket.WebSocketApp: + + """ + if self.__closed: + self.__dealer_client.logger.fatal( + "I wonder what happened here... Terminating. [closed: {}]". + format(self.__closed)) + self.__dealer_client.logger.debug( + "Dealer connected! [url: {}]".format(self.__url)) + + def anonymous(): + """ """ + self.send_ping() + self.__received_pong = False + + def anonymous2(): + """ """ + if self.__last_scheduled_ping is None: + return + if not self.__received_pong: + self.__dealer_client.logger.warning( + "Did not receive ping in 3 seconds. Reconnecting..." + ) + self.close() + return + self.__received_pong = False + + self.__scheduler.enter(3, 1, anonymous2) + self.__last_scheduled_ping = self.__scheduler.enter( + 30, 1, anonymous) + + self.__last_scheduled_ping = self.__scheduler.enter( + 30, 1, anonymous) + + def send_ping(self): + """ """ + self.__ws.send('{"type":"ping"}') + + def send_reply(self, key: str, result: DealerClient.RequestResult): + """ + + :param key: str: + :param result: DealerClient.RequestResult: + + """ + success = ("true" if result == DealerClient.RequestResult.SUCCESS + else "false") + self.__ws.send( + '{"type":"reply","key":"%s","payload":{"success":%s}' % + (key, success)) + + class RequestResult(enum.Enum): + """ """ + UNKNOWN_SEND_COMMAND_RESULT = 0 + SUCCESS = 1 + DEVICE_NOT_FOUND = 2 + CONTEXT_PLAYER_ERROR = 3 + DEVICE_DISAPPEARED = 4 + UPSTREAM_ERROR = 5 + DEVICE_DOES_NOT_SUPPORT_COMMAND = 6 + RATE_LIMITED = 7 + + +class EventService(Closeable): + """ """ + logger = logging.getLogger("Librespot:EventService") + __session: Session + __worker = concurrent.futures.ThreadPoolExecutor() + + def __init__(self, session: Session): + self.__session = session + + def __worker_callback(self, event_builder: EventBuilder): + try: + body = event_builder.to_array() + resp = self.__session.mercury().send_sync( + RawMercuryRequest.Builder().set_uri( + "hm://event-service/v1/events").set_method("POST"). + add_user_field("Accept-Language", "en").add_user_field( + "X-ClientTimeStamp", + int(time.time() * 1000)).add_payload_part(body).build()) + self.logger.debug("Event sent. body: {}, result: {}".format( + body, resp.status_code)) + except IOError as ex: + self.logger.error("Failed sending event: {} {}".format( + event_builder, ex)) + + def send_event(self, event_or_builder: typing.Union[GenericEvent, + EventBuilder]): + """ + + :param event_or_builder: typing.Union[GenericEvent: + :param EventBuilder]: + + """ + if type(event_or_builder) is EventService.GenericEvent: + builder = event_or_builder.build() + elif type(event_or_builder) is EventService.EventBuilder: + builder = event_or_builder + else: + raise TypeError() + self.__worker.submit(lambda: self.__worker_callback(builder)) + + def language(self, lang: str): + """ + + :param lang: str: + + """ + event = EventService.EventBuilder(EventService.Type.LANGUAGE) + event.append(s=lang) + + def close(self): + """ """ + self.__worker.shutdown() + + class Type(enum.Enum): + """ """ + LANGUAGE = ("812", 1) + FETCHED_FILE_ID = ("274", 3) + NEW_SESSION_ID = ("557", 3) + NEW_PLAYBACK_ID = ("558", 1) + TRACK_PLAYED = ("372", 1) + TRACK_TRANSITION = ("12", 37) + CDN_REQUEST = ("10", 20) + + eventId: str + unknown: str + + def __init__(self, event_id: str, unknown: str): + self.eventId = event_id + self.unknown = unknown + + class GenericEvent: + """ """ + + def build(self) -> EventService.EventBuilder: + """ """ + raise NotImplementedError + + class EventBuilder: + """ """ + body: io.BytesIO + + def __init__(self, event_type: EventService.Type): + self.body = io.BytesIO() + self.append_no_delimiter(event_type.value[0]) + self.append(event_type.value[1]) + + def append_no_delimiter(self, s: str = None) -> None: + """ + + :param s: str: (Default value = None) + + """ + if s is None: + s = "" + self.body.write(s.encode()) + + def append(self, + c: int = None, + s: str = None) -> EventService.EventBuilder: + """ + + :param c: int: (Default value = None) + :param s: str: (Default value = None) + + """ + if c is None and s is None or c is not None and s is not None: + raise TypeError() + if c is not None: + self.body.write(b"\x09") + self.body.write(bytes([c])) + return self + if s is not None: + self.body.write(b"\x09") + self.append_no_delimiter(s) + return self + + def to_array(self) -> bytes: + """ """ + pos = self.body.tell() + self.body.seek(0) + data = self.body.read() + self.body.seek(pos) + return data + + +class MessageType(enum.Enum): + """ """ + MESSAGE = "message" + PING = "ping" + PONG = "pong" + REQUEST = "request" + + @staticmethod + def parse(_typ: str): + """ + + :param _typ: str: + + """ + if _typ == MessageType.MESSAGE.value: + return MessageType.MESSAGE + if _typ == MessageType.PING.value: + return MessageType.PING + if _typ == MessageType.PONG.value: + return MessageType.PONG + if _typ == MessageType.REQUEST.value: + return MessageType.REQUEST + raise TypeError("Unknown MessageType: {}".format(_typ)) + + +class Session(Closeable, MessageListener, SubListener): + """ """ + cipher_pair: typing.Union[CipherPair, None] + country_code: str = "EN" + connection: typing.Union[ConnectionHolder, None] + logger = logging.getLogger("Librespot:Session") + scheduled_reconnect: typing.Union[sched.Event, None] = None + scheduler = sched.scheduler(time.time) + __api: ApiClient + __ap_welcome: Authentication.APWelcome + __audio_key_manager: typing.Union[AudioKeyManager, None] = None + __auth_lock = threading.Condition() + __auth_lock_bool = False + __cache_manager: typing.Union[CacheManager, None] + __cdn_manager: typing.Union[CdnManager, None] + __channel_manager: typing.Union[ChannelManager, None] = None + __client: typing.Union[requests.Session, None] + __closed = False + __closing = False + __content_feeder: typing.Union[PlayableContentFeeder, None] + __dealer_client: typing.Union[DealerClient, None] = None + __event_service: typing.Union[EventService, None] = None + __keys: DiffieHellman + __mercury_client: MercuryClient + __receiver: typing.Union[Receiver, None] = None + __search: typing.Union[SearchManager, None] + __server_key = (b"\xac\xe0F\x0b\xff\xc20\xaf\xf4k\xfe\xc3\xbf\xbf\x86=" + b"\xa1\x91\xc6\xcc3l\x93\xa1O\xb3\xb0\x16\x12\xac\xacj" + b"\xf1\x80\xe7\xf6\x14\xd9B\x9d\xbe.4fC\xe3b\xd22z\x1a" + b"\r\x92;\xae\xdd\x14\x02\xb1\x81U\x05a\x04\xd5,\x96\xa4" + b"L\x1e\xcc\x02J\xd4\xb2\x0c\x00\x1f\x17\xed\xc2/\xc45" + b"!\xc8\xf0\xcb\xae\xd2\xad\xd7+\x0f\x9d\xb3\xc52\x1a*" + b"\xfeY\xf3Z\r\xach\xf1\xfab\x1e\xfb,\x8d\x0c\xb79-\x92" + b"G\xe3\xd75\x1am\xbd$\xc2\xae%[\x88\xff\xabs)\x8a\x0b" + b"\xcc\xcd\x0cXg1\x89\xe8\xbd4\x80xJ_\xc9k\x89\x9d\x95k" + b"\xfc\x86\xd7O3\xa6x\x17\x96\xc9\xc3-\r2\xa5\xab\xcd\x05'" + b"\xe2\xf7\x10\xa3\x96\x13\xc4/\x99\xc0'\xbf\xed\x04\x9c" + b"<'X\x04\xb6\xb2\x19\xf9\xc1/\x02\xe9Hc\xec\xa1\xb6B\xa0" + b"\x9dH%\xf8\xb3\x9d\xd0\xe8j\xf9HM\xa1\xc2\xba\x860B\xea" + b"\x9d\xb3\x08l\x19\x0eH\xb3\x9df\xeb\x00\x06\xa2Z\xee\xa1" + b"\x1b\x13\x87<\xd7\x19\xe6U\xbd") + __stored_str: str = "" + __token_provider: typing.Union[TokenProvider, None] + __user_attributes = {} + __login5_access_token: typing.Union[str, None] = None + __login5_token_expiry: typing.Union[int, None] = None + + def __init__(self, inner: Inner, address: str) -> None: + self.__client = Session.create_client(inner.conf) + self.connection = Session.ConnectionHolder.create(address, None) + self.__inner = inner + self.__keys = DiffieHellman() + self.logger.info("Created new session! device_id: {}, ap: {}".format( + inner.device_id, address)) + + def api(self) -> ApiClient: + """ """ + self.__wait_auth_lock() + if self.__api is None: + raise RuntimeError("Session isn't authenticated!") + return self.__api + + def ap_welcome(self): + """ """ + self.__wait_auth_lock() + if self.__ap_welcome is None: + raise RuntimeError("Session isn't authenticated!") + return self.__ap_welcome + + def audio_key(self) -> AudioKeyManager: + """ """ + self.__wait_auth_lock() + if self.__audio_key_manager is None: + raise RuntimeError("Session isn't authenticated!") + return self.__audio_key_manager + + def authenticate(self, + credential: Authentication.LoginCredentials) -> None: + """Log in to Spotify + + :param credential: Spotify account login information + :param credential: Authentication.LoginCredentials: + + """ + self.__authenticate_partial(credential, False) + self.__authenticate_login5(credential) + with self.__auth_lock: + self.__mercury_client = MercuryClient(self) + self.__token_provider = TokenProvider(self) + self.__audio_key_manager = AudioKeyManager(self) + self.__channel_manager = ChannelManager(self) + self.__api = ApiClient(self) + self.__cdn_manager = CdnManager(self) + self.__content_feeder = PlayableContentFeeder(self) + self.__cache_manager = CacheManager(self) + self.__dealer_client = DealerClient(self) + self.__search = SearchManager(self) + self.__event_service = EventService(self) + self.__auth_lock_bool = False + self.__auth_lock.notify_all() + self.dealer().connect() + self.logger.info("Authenticated as {}!".format( + self.__ap_welcome.canonical_username)) + self.mercury().interested_in("spotify:user:attributes:update", self) + self.dealer().add_message_listener( + self, ["hm://connect-state/v1/connect/logout"]) + + def cache(self) -> CacheManager: + """ """ + self.__wait_auth_lock() + if self.__cache_manager is None: + raise RuntimeError("Session isn't authenticated!") + return self.__cache_manager + + def cdn(self) -> CdnManager: + """ """ + self.__wait_auth_lock() + if self.__cdn_manager is None: + raise RuntimeError("Session isn't authenticated!") + return self.__cdn_manager + + def channel(self) -> ChannelManager: + """ """ + self.__wait_auth_lock() + if self.__channel_manager is None: + raise RuntimeError("Session isn't authenticated!") + return self.__channel_manager + + def client(self) -> requests.Session: + """ """ + return self.__client + + def close(self) -> None: + """Close instance""" + self.logger.info("Closing session. device_id: {}".format( + self.__inner.device_id)) + self.__closing = True + if self.__dealer_client is not None: + self.__dealer_client.close() + self.__dealer_client = None + if self.__audio_key_manager is not None: + self.__audio_key_manager = None + if self.__channel_manager is not None: + self.__channel_manager.close() + self.__channel_manager = None + if self.__event_service is not None: + self.__event_service.close() + self.__event_service = None + if self.__receiver is not None: + self.__receiver.stop() + self.__receiver = None + if self.__client is not None: + self.__client.close() + self.__client = None + if self.connection is not None: + self.connection.close() + self.connection = None + with self.__auth_lock: + self.__ap_welcome = None + self.cipher_pair = None + self.__closed = True + self.logger.info("Closed session. device_id: {}".format( + self.__inner.device_id)) + + def connect(self) -> None: + """Connect to the Spotify Server""" + acc = Session.Accumulator() + # Send ClientHello + nonce = Random.get_random_bytes(0x10) + client_hello_proto = Keyexchange.ClientHello( + build_info=Version.standard_build_info(), + client_nonce=nonce, + cryptosuites_supported=[ + Keyexchange.Cryptosuite.CRYPTO_SUITE_SHANNON + ], + login_crypto_hello=Keyexchange.LoginCryptoHelloUnion( + diffie_hellman=Keyexchange.LoginCryptoDiffieHellmanHello( + gc=self.__keys.public_key_bytes(), server_keys_known=1), ), + padding=b"\x1e", + ) + client_hello_bytes = client_hello_proto.SerializeToString() + self.connection.write(b"\x00\x04") + self.connection.write_int(2 + 4 + len(client_hello_bytes)) + self.connection.write(client_hello_bytes) + self.connection.flush() + acc.write(b"\x00\x04") + acc.write_int(2 + 4 + len(client_hello_bytes)) + acc.write(client_hello_bytes) + # Read APResponseMessage + ap_response_message_length = self.connection.read_int() + acc.write_int(ap_response_message_length) + ap_response_message_bytes = self.connection.read( + ap_response_message_length - 4) + acc.write(ap_response_message_bytes) + ap_response_message_proto = Keyexchange.APResponseMessage() + ap_response_message_proto.ParseFromString(ap_response_message_bytes) + shared_key = util.int_to_bytes( + self.__keys.compute_shared_key( + ap_response_message_proto.challenge.login_crypto_challenge. + diffie_hellman.gs)) + # Check gs_signature + rsa = RSA.construct((int.from_bytes(self.__server_key, "big"), 65537)) + pkcs1_v1_5 = PKCS1_v1_5.new(rsa) + sha1 = SHA1.new() + sha1.update(ap_response_message_proto.challenge.login_crypto_challenge. + diffie_hellman.gs) + if not pkcs1_v1_5.verify( + sha1, + ap_response_message_proto.challenge.login_crypto_challenge. + diffie_hellman.gs_signature, + ): + raise RuntimeError("Failed signature check!") + # Solve challenge + buffer = io.BytesIO() + for i in range(1, 6): + mac = HMAC.new(shared_key, digestmod=SHA1) + mac.update(acc.read()) + mac.update(bytes([i])) + buffer.write(mac.digest()) + buffer.seek(0) + mac = HMAC.new(buffer.read(20), digestmod=SHA1) + mac.update(acc.read()) + challenge = mac.digest() + client_response_plaintext_proto = Keyexchange.ClientResponsePlaintext( + crypto_response=Keyexchange.CryptoResponseUnion(), + login_crypto_response=Keyexchange.LoginCryptoResponseUnion( + diffie_hellman=Keyexchange.LoginCryptoDiffieHellmanResponse( + hmac=challenge)), + pow_response=Keyexchange.PoWResponseUnion(), + ) + client_response_plaintext_bytes = ( + client_response_plaintext_proto.SerializeToString()) + self.connection.write_int(4 + len(client_response_plaintext_bytes)) + self.connection.write(client_response_plaintext_bytes) + self.connection.flush() + try: + self.connection.set_timeout(1) + scrap = self.connection.read(4) + if len(scrap) == 4: + payload = self.connection.read( + struct.unpack(">i", scrap)[0] - 4) + failed = Keyexchange.APResponseMessage() + failed.ParseFromString(payload) + raise RuntimeError(failed) + except socket.timeout: + pass + finally: + self.connection.set_timeout(0) + buffer.seek(20) + with self.__auth_lock: + self.cipher_pair = CipherPair(buffer.read(32), buffer.read(32)) + self.__auth_lock_bool = True + self.logger.info("Connection successfully!") + + def content_feeder(self) -> PlayableContentFeeder: + """ """ + self.__wait_auth_lock() + if self.__content_feeder is None: + raise RuntimeError("Session isn't authenticated!") + return self.__content_feeder + + @staticmethod + def create_client(conf: Configuration) -> requests.Session: + """ + + :param conf: Configuration: + + """ + client = requests.Session() + return client + + def dealer(self) -> DealerClient: + """ """ + self.__wait_auth_lock() + if self.__dealer_client is None: + raise RuntimeError("Session isn't authenticated!") + return self.__dealer_client + + def device_id(self) -> str: + """ """ + return self.__inner.device_id + + def device_name(self) -> str: + """ """ + return self.__inner.device_name + + def device_type(self) -> Connect.DeviceType: + """ """ + return self.__inner.device_type + + def event(self, resp: MercuryClient.Response) -> None: + """ + + :param resp: MercuryClient.Response: + + """ + if resp.uri == "spotify:user:attributes:update": + attributes_update = UserAttributesUpdate() + attributes_update.ParseFromString(resp.payload) + for pair in attributes_update.pairs_list: + self.__user_attributes[pair.key] = pair.value + self.logger.info("Updated user attribute: {} -> {}".format( + pair.key, pair.value)) + + def get_user_attribute(self, key: str, fallback: str = None) -> str: + """ + + :param key: str: + :param fallback: str: (Default value = None) + + """ + return (self.__user_attributes.get(key) + if self.__user_attributes.get(key) is not None else fallback) + + def is_valid(self) -> bool: + """ """ + if self.__closed: + return False + self.__wait_auth_lock() + return self.__ap_welcome is not None and self.connection is not None + + def mercury(self) -> MercuryClient: + """ """ + self.__wait_auth_lock() + if self.__mercury_client is None: + raise RuntimeError("Session isn't authenticated!") + return self.__mercury_client + + def on_message(self, uri: str, headers: typing.Dict[str, str], + payload: bytes): + """ + + :param uri: str: + :param headers: typing.Dict[str: + :param str]: + :param payload: bytes: + + """ + if uri == "hm://connect-state/v1/connect/logout": + self.close() + + def parse_product_info(self, data) -> None: + """Parse product information + + :param data: Raw product information + + """ + products = defusedxml.ElementTree.fromstring(data) + if products is None: + return + product = products[0] + if product is None: + return + for i in range(len(product)): + self.__user_attributes[product[i].tag] = product[i].text + self.logger.debug("Parsed product info: {}".format( + self.__user_attributes)) + + def preferred_locale(self) -> str: + """ """ + return self.__inner.preferred_locale + + def reconnect(self) -> None: + """Reconnect to the Spotify Server""" + if self.connection is not None: + self.connection.close() + self.__receiver.stop() + self.connection = Session.ConnectionHolder.create( + ApResolver.get_random_accesspoint(), self.__inner.conf) + self.connect() + self.__authenticate_partial( + Authentication.LoginCredentials( + typ=self.__ap_welcome.reusable_auth_credentials_type, + username=self.__ap_welcome.canonical_username, + auth_data=self.__ap_welcome.reusable_auth_credentials, + ), + True, + ) + self.logger.info("Re-authenticated as {}!".format( + self.__ap_welcome.canonical_username)) + + def reconnecting(self) -> bool: + """ """ + return not self.__closing and not self.__closed and self.connection is None + + def search(self) -> SearchManager: + """ """ + self.__wait_auth_lock() + if self.__search is None: + raise RuntimeError("Session isn't authenticated!") + return self.__search + + def send(self, cmd: bytes, payload: bytes): + """Send data to socket using send_unchecked + + :param cmd: Command + :param payload: Payload + :param cmd: bytes: + :param payload: bytes: + + """ + if self.__closing and self.connection is None: + self.logger.debug("Connection was broken while closing.") + return + if self.__closed: + raise RuntimeError("Session is closed!") + with self.__auth_lock: + if self.cipher_pair is None or self.__auth_lock_bool: + self.__auth_lock.wait() + self.__send_unchecked(cmd, payload) + + def tokens(self) -> TokenProvider: + """ """ + self.__wait_auth_lock() + if self.__token_provider is None: + raise RuntimeError("Session isn't authenticated!") + return self.__token_provider + + def username(self): + """ """ + return self.__ap_welcome.canonical_username + + def stored(self): + """ """ + return self.__stored_str + + def __authenticate_partial(self, + credential: Authentication.LoginCredentials, + remove_lock: bool) -> None: + """ + Login to Spotify + Args: + credential: Spotify account login information + """ + if self.cipher_pair is None: + raise RuntimeError("Connection not established!") + client_response_encrypted_proto = Authentication.ClientResponseEncrypted( + login_credentials=credential, + system_info=Authentication.SystemInfo( + os=Authentication.Os.OS_UNKNOWN, + cpu_family=Authentication.CpuFamily.CPU_UNKNOWN, + system_information_string=Version.system_info_string(), + device_id=self.__inner.device_id, + ), + version_string=Version.version_string(), + ) + self.__send_unchecked( + Packet.Type.login, + client_response_encrypted_proto.SerializeToString()) + packet = self.cipher_pair.receive_encoded(self.connection) + if packet.is_cmd(Packet.Type.ap_welcome): + self.__ap_welcome = Authentication.APWelcome() + self.__ap_welcome.ParseFromString(packet.payload) + self.__receiver = Session.Receiver(self) + bytes0x0f = Random.get_random_bytes(0x14) + self.__send_unchecked(Packet.Type.unknown_0x0f, bytes0x0f) + preferred_locale = io.BytesIO() + preferred_locale.write(b"\x00\x00\x10\x00\x02preferred-locale" + + self.__inner.preferred_locale.encode()) + preferred_locale.seek(0) + self.__send_unchecked(Packet.Type.preferred_locale, + preferred_locale.read()) + if remove_lock: + with self.__auth_lock: + self.__auth_lock_bool = False + self.__auth_lock.notify_all() + if self.__inner.conf.store_credentials: + reusable = self.__ap_welcome.reusable_auth_credentials + reusable_type = Authentication.AuthenticationType.Name( + self.__ap_welcome.reusable_auth_credentials_type) + if self.__inner.conf.stored_credentials_file is None: + raise TypeError( + "The file path to be saved is not specified") + self.__stored_str = base64.b64encode( + json.dumps({ + "username": + self.__ap_welcome.canonical_username, + "credentials": + base64.b64encode(reusable).decode(), + "type": + reusable_type, + }).encode()).decode() + with open(self.__inner.conf.stored_credentials_file, "w") as f: + json.dump( + { + "username": self.__ap_welcome.canonical_username, + "credentials": base64.b64encode(reusable).decode(), + "type": reusable_type, + }, + f, + ) + + elif packet.is_cmd(Packet.Type.auth_failure): + ap_login_failed = Keyexchange.APLoginFailed() + ap_login_failed.ParseFromString(packet.payload) + self.close() + raise Session.SpotifyAuthenticationException(ap_login_failed) + else: + raise RuntimeError("Unknown CMD 0x" + packet.cmd.hex()) + + def __send_unchecked(self, cmd: bytes, payload: bytes) -> None: + self.cipher_pair.send_encoded(self.connection, cmd, payload) + + def __authenticate_login5(self, credential: Authentication.LoginCredentials) -> None: + """Authenticate using Login5 to get access token""" + if not LOGIN5_AVAILABLE: + self.logger.warning("Login5 protobuf files not available, skipping Login5 authentication") + return + + try: + # Build Login5 request + login5_request = Login5.LoginRequest() + + # Set client info + login5_request.client_info.client_id = "65b708073fc0480ea92a077233ca87bd" + login5_request.client_info.device_id = self.__inner.device_id + + # Set stored credential from APWelcome + if hasattr(self, '_Session__ap_welcome') and self.__ap_welcome: + stored_cred = Login5Credentials.StoredCredential() + stored_cred.username = self.__ap_welcome.canonical_username + stored_cred.data = self.__ap_welcome.reusable_auth_credentials + login5_request.stored_credential.CopyFrom(stored_cred) + + # Send Login5 request + login5_url = "https://login5.spotify.com/v3/login" + headers = { + "Content-Type": "application/x-protobuf", + "Accept": "application/x-protobuf" + } + + response = requests.post( + login5_url, + data=login5_request.SerializeToString(), + headers=headers + ) + + if response.status_code == 200: + login5_response = Login5.LoginResponse() + login5_response.ParseFromString(response.content) + + if login5_response.HasField('ok'): + self.__login5_access_token = login5_response.ok.access_token + self.__login5_token_expiry = int(time.time()) + login5_response.ok.access_token_expires_in + self.logger.info("Login5 authentication successful, got access token") + else: + self.logger.warning("Login5 authentication failed: {}".format(login5_response.error)) + else: + self.logger.warning("Login5 request failed with status: {}".format(response.status_code)) + except Exception as e: + self.logger.warning("Failed to authenticate with Login5: {}".format(e)) + + def get_login5_token(self) -> typing.Union[str, None]: + """Get the Login5 access token if available and not expired""" + if self.__login5_access_token and self.__login5_token_expiry: + if int(time.time()) < self.__login5_token_expiry - 60: # 60 second buffer + return self.__login5_access_token + else: + self.logger.debug("Login5 token expired, need to re-authenticate") + return None + + def __wait_auth_lock(self) -> None: + if self.__closing and self.connection is None: + self.logger.debug("Connection was broken while closing.") + return + if self.__closed: + raise RuntimeError("Session is closed!") + with self.__auth_lock: + if self.cipher_pair is None or self.__auth_lock_bool: + self.__auth_lock.wait() + + class AbsBuilder: + """ """ + conf = None + device_id = None + device_name = "librespot-python" + device_type = Connect.DeviceType.COMPUTER + preferred_locale = "en" + + def __init__(self, conf: Session.Configuration = None): + if conf is None: + self.conf = Session.Configuration.Builder().build() + else: + self.conf = conf + + def set_preferred_locale(self, locale: str) -> Session.AbsBuilder: + """ + + :param locale: str: + + """ + if len(locale) != 2: + raise TypeError("Invalid locale: {}".format(locale)) + self.preferred_locale = locale + return self + + def set_device_name(self, device_name: str) -> Session.AbsBuilder: + """ + + :param device_name: str: + + """ + self.device_name = device_name + return self + + def set_device_id(self, device_id: str) -> Session.AbsBuilder: + """ + + :param device_id: str: + + """ + if self.device_id is not None and len(device_id) != 40: + raise TypeError("Device ID must be 40 chars long.") + self.device_id = device_id + return self + + def set_device_type( + self, device_type: Connect.DeviceType) -> Session.AbsBuilder: + """ + + :param device_type: Connect.DeviceType: + + """ + self.device_type = device_type + return self + + class Accumulator: + """ """ + __buffer: io.BytesIO + + def __init__(self): + self.__buffer = io.BytesIO() + + def read(self) -> bytes: + """Read all buffer + + + :returns: All buffer + + """ + pos = self.__buffer.tell() + self.__buffer.seek(0) + data = self.__buffer.read() + self.__buffer.seek(pos) + return data + + def write(self, data: bytes) -> None: + """Write data to buffer + + :param data: Bytes to be written + :param data: bytes: + + """ + self.__buffer.write(data) + + def write_int(self, data: int) -> None: + """Write data to buffer + + :param data: Integer to be written + :param data: int: + + """ + self.write(struct.pack(">i", data)) + + def write_short(self, data: int) -> None: + """Write data to buffer + + :param data: Short integer to be written + :param data: int: + + """ + self.write(struct.pack(">h", data)) + + class Builder(AbsBuilder): + """ """ + login_credentials: Authentication.LoginCredentials = None + + def blob(self, username: str, blob: bytes) -> Session.Builder: + """ + + :param username: str: + :param blob: bytes: + + """ + if self.device_id is None: + raise TypeError("You must specify the device ID first.") + self.login_credentials = self.decrypt_blob(self.device_id, + username, blob) + return self + + def decrypt_blob( + self, device_id: str, username: str, + encrypted_blob: bytes) -> Authentication.LoginCredentials: + """ + + :param device_id: str: + :param username: str: + :param encrypted_blob: bytes: + + """ + encrypted_blob = base64.b64decode(encrypted_blob) + sha1 = SHA1.new() + sha1.update(device_id.encode()) + secret = sha1.digest() + base_key = PBKDF2(secret, + username.encode(), + 20, + 0x100, + hmac_hash_module=SHA1) + sha1 = SHA1.new() + sha1.update(base_key) + key = sha1.digest() + b"\x00\x00\x00\x14" + aes = AES.new(key, AES.MODE_ECB) + decrypted_blob = bytearray(aes.decrypt(encrypted_blob)) + l = len(decrypted_blob) + for i in range(0, l - 0x10): + decrypted_blob[l - i - 1] ^= decrypted_blob[l - i - 0x11] + blob = io.BytesIO(decrypted_blob) + blob.read(1) + le = self.read_blob_int(blob) + blob.read(le) + blob.read(1) + type_int = self.read_blob_int(blob) + type_ = Authentication.AuthenticationType.Name(type_int) + if type_ is None: + raise IOError( + TypeError( + "Unknown AuthenticationType: {}".format(type_int))) + blob.read(1) + l = self.read_blob_int(blob) + auth_data = blob.read(l) + return Authentication.LoginCredentials( + auth_data=auth_data, + typ=type_, + username=username, + ) + + def read_blob_int(self, buffer: io.BytesIO) -> int: + """ + + :param buffer: io.BytesIO: + + """ + lo = buffer.read(1) + if (int(lo[0]) & 0x80) == 0: + return int(lo[0]) + hi = buffer.read(1) + return int(lo[0]) & 0x7F | int(hi[0]) << 7 + + def stored(self, stored_credentials_str: str): + """Create credential from stored string + + :param stored_credentials_str: str: + :returns: Builder + + """ + try: + obj = json.loads(base64.b64decode(stored_credentials_str)) + except binascii.Error: + pass + except json.JSONDecodeError: + pass + else: + try: + self.login_credentials = Authentication.LoginCredentials( + typ=Authentication.AuthenticationType.Value( + obj["type"]), + username=obj["username"], + auth_data=base64.b64decode(obj["credentials"]), + ) + except KeyError: + pass + return self + + def stored_file(self, + stored_credentials: str = None) -> Session.Builder: + """Create credential from stored file + + :param stored_credentials: str: (Default value = None) + :returns: Builder + + """ + if stored_credentials is None: + stored_credentials = self.conf.stored_credentials_file + if os.path.isfile(stored_credentials): + try: + with open(stored_credentials) as f: + obj = json.load(f) + except json.JSONDecodeError: + pass + else: + try: + self.login_credentials = Authentication.LoginCredentials( + typ=Authentication.AuthenticationType.Value( + obj["type"]), + username=obj["username"], + auth_data=base64.b64decode(obj["credentials"]), + ) + except KeyError: + pass + return self + + def user_pass(self, username: str, password: str) -> Session.Builder: + """Create credential from username and password + + :param username: Spotify's account username + :param username: str: + :param password: str: + :returns: Builder + + """ + self.login_credentials = Authentication.LoginCredentials( + username=username, + typ=Authentication.AuthenticationType.AUTHENTICATION_USER_PASS, + auth_data=password.encode(), + ) + return self + + def create(self) -> Session: + """Create the Session instance + + + :returns: Session instance + + """ + if self.login_credentials is None: + raise RuntimeError("You must select an authentication method.") + session = Session( + Session.Inner( + self.device_type, + self.device_name, + self.preferred_locale, + self.conf, + self.device_id, + ), + ApResolver.get_random_accesspoint(), + ) + session.connect() + session.authenticate(self.login_credentials) + return session + + class Configuration: + """ """ + # Proxy + # proxyEnabled: bool + # proxyType: Proxy.Type + # proxyAddress: str + # proxyPort: int + # proxyAuth: bool + # proxyUsername: str + # proxyPassword: str + + # Cache + cache_enabled: bool + cache_dir: str + do_cache_clean_up: bool + + # Stored credentials + store_credentials: bool + stored_credentials_file: str + + # Fetching + retry_on_chunk_error: bool + + def __init__( + self, + # proxy_enabled: bool, + # proxy_type: Proxy.Type, + # proxy_address: str, + # proxy_port: int, + # proxy_auth: bool, + # proxy_username: str, + # proxy_password: str, + cache_enabled: bool, + cache_dir: str, + do_cache_clean_up: bool, + store_credentials: bool, + stored_credentials_file: str, + retry_on_chunk_error: bool, + ): + # self.proxyEnabled = proxy_enabled + # self.proxyType = proxy_type + # self.proxyAddress = proxy_address + # self.proxyPort = proxy_port + # self.proxyAuth = proxy_auth + # self.proxyUsername = proxy_username + # self.proxyPassword = proxy_password + self.cache_enabled = cache_enabled + self.cache_dir = cache_dir + self.do_cache_clean_up = do_cache_clean_up + self.store_credentials = store_credentials + self.stored_credentials_file = stored_credentials_file + self.retry_on_chunk_error = retry_on_chunk_error + + class Builder: + """ """ + # Proxy + # proxyEnabled: bool = False + # proxyType: Proxy.Type = Proxy.Type.DIRECT + # proxyAddress: str = None + # proxyPort: int = None + # proxyAuth: bool = None + # proxyUsername: str = None + # proxyPassword: str = None + + # Cache + cache_enabled: bool = True + cache_dir: str = os.path.join(os.getcwd(), "cache") + do_cache_clean_up: bool = True + + # Stored credentials + store_credentials: bool = True + stored_credentials_file: str = os.path.join( + os.getcwd(), "credentials.json") + + # Fetching + retry_on_chunk_error: bool = True + + # def set_proxy_enabled( + # self, + # proxy_enabled: bool) -> Session.Configuration.Builder: + # self.proxyEnabled = proxy_enabled + # return self + + # def set_proxy_type( + # self, + # proxy_type: Proxy.Type) -> Session.Configuration.Builder: + # self.proxyType = proxy_type + # return self + + # def set_proxy_address( + # self, proxy_address: str) -> Session.Configuration.Builder: + # self.proxyAddress = proxy_address + # return self + + # def set_proxy_auth( + # self, proxy_auth: bool) -> Session.Configuration.Builder: + # self.proxyAuth = proxy_auth + # return self + + # def set_proxy_username( + # self, + # proxy_username: str) -> Session.Configuration.Builder: + # self.proxyUsername = proxy_username + # return self + + # def set_proxy_password( + # self, + # proxy_password: str) -> Session.Configuration.Builder: + # self.proxyPassword = proxy_password + # return self + + def set_cache_enabled( + self, + cache_enabled: bool) -> Session.Configuration.Builder: + """Set cache_enabled + + :param cache_enabled: bool: + :returns: Builder + + """ + self.cache_enabled = cache_enabled + return self + + def set_cache_dir(self, + cache_dir: str) -> Session.Configuration.Builder: + """Set cache_dir + + :param cache_dir: str: + :returns: Builder + + """ + self.cache_dir = cache_dir + return self + + def set_do_cache_clean_up( + self, + do_cache_clean_up: bool) -> Session.Configuration.Builder: + """Set do_cache_clean_up + + :param do_cache_clean_up: bool: + :returns: Builder + + """ + self.do_cache_clean_up = do_cache_clean_up + return self + + def set_store_credentials( + self, + store_credentials: bool) -> Session.Configuration.Builder: + """Set store_credentials + + :param store_credentials: bool: + :returns: Builder + + """ + self.store_credentials = store_credentials + return self + + def set_stored_credential_file( + self, stored_credential_file: str + ) -> Session.Configuration.Builder: + """Set stored_credential_file + + :param stored_credential_file: str: + :returns: Builder + + """ + self.stored_credentials_file = stored_credential_file + return self + + def set_retry_on_chunk_error( + self, retry_on_chunk_error: bool + ) -> Session.Configuration.Builder: + """Set retry_on_chunk_error + + :param retry_on_chunk_error: bool: + :returns: Builder + + """ + self.retry_on_chunk_error = retry_on_chunk_error + return self + + def build(self) -> Session.Configuration: + """Build Configuration instance + + + :returns: Session.Configuration + + """ + return Session.Configuration( + # self.proxyEnabled, + # self.proxyType, + # self.proxyAddress, + # self.proxyPort, + # self.proxyAuth, + # self.proxyUsername, + # self.proxyPassword, + self.cache_enabled, + self.cache_dir, + self.do_cache_clean_up, + self.store_credentials, + self.stored_credentials_file, + self.retry_on_chunk_error, + ) + + class ConnectionHolder: + """ """ + __buffer: io.BytesIO + __socket: socket.socket + + def __init__(self, sock: socket.socket): + self.__buffer = io.BytesIO() + self.__socket = sock + + @staticmethod + def create(address: str, conf) -> Session.ConnectionHolder: + """Create the ConnectionHolder instance + + :param address: Address to connect + :param address: str: + :param conf: + :returns: ConnectionHolder instance + + """ + ap_address = address.split(":")[0] + ap_port = int(address.split(":")[1]) + sock = socket.socket() + + # Retry logic: try up to 3 times with 2 seconds between attempts + # for transient connection errors (e.g., ECONNREFUSED / error 111). + attempts = 0 + last_err: typing.Optional[Exception] = None + while attempts < 3: + attempts += 1 + try: + sock.connect((ap_address, ap_port)) + break + except OSError as exc: + last_err = exc + # Connection refused / temporary failure + if attempts >= 3: + raise + time.sleep(2) + + return Session.ConnectionHolder(sock) + + def close(self) -> None: + """Close the connection""" + self.__socket.close() + + def flush(self) -> None: + """Flush data to socket""" + try: + self.__buffer.seek(0) + self.__socket.send(self.__buffer.read()) + self.__buffer = io.BytesIO() + except BrokenPipeError: + pass + + def read(self, length: int) -> bytes: + """Read data from socket + + :param length: int: + :returns: Bytes data from socket + + """ + return self.__socket.recv(length) + + def read_int(self) -> int: + """Read integer from socket + + + :returns: integer from socket + + """ + return struct.unpack(">i", self.read(4))[0] + + def read_short(self) -> int: + """Read short integer from socket + + + :returns: short integer from socket + + """ + return struct.unpack(">h", self.read(2))[0] + + def set_timeout(self, seconds: float) -> None: + """Set socket's timeout + + :param seconds: Number of seconds until timeout + :param seconds: float: + + """ + self.__socket.settimeout(None if seconds == 0 else seconds) + + def write(self, data: bytes) -> None: + """Write data to buffer + + :param data: Bytes to be written + :param data: bytes: + + """ + self.__buffer.write(data) + + def write_int(self, data: int) -> None: + """Write data to buffer + + :param data: Integer to be written + :param data: int: + + """ + self.write(struct.pack(">i", data)) + + def write_short(self, data: int) -> None: + """Write data to buffer + + :param data: Short integer to be written + :param data: int: + + """ + self.write(struct.pack(">h", data)) + + class Inner: + """ """ + device_type: Connect.DeviceType = None + device_name: str + device_id: str + conf = None + preferred_locale: str + + def __init__( + self, + device_type: Connect.DeviceType, + device_name: str, + preferred_locale: str, + conf: Session.Configuration, + device_id: str = None, + ): + self.preferred_locale = preferred_locale + self.conf = conf + self.device_type = device_type + self.device_name = device_name + self.device_id = (device_id if device_id is not None else + util.random_hex_string(40)) + + class Receiver: + """ """ + __session: Session + __thread: threading.Thread + __running: bool = True + + def __init__(self, session): + self.__session = session + self.__thread = threading.Thread(target=self.run) + self.__thread.daemon = True + self.__thread.name = "session-packet-receiver" + self.__thread.start() + + def stop(self) -> None: + """Signal the receiver thread to stop and wait for it. + + This ensures that the background thread exits cleanly before + the underlying socket/connection is closed, avoiding + "Bad file descriptor" errors from pending recv() calls. + """ + self.__running = False + try: + # Joining from within the same thread would deadlock, so + # guard against that. + if threading.current_thread() is not self.__thread: + self.__thread.join(timeout=1) + except Exception: + # Shutdown should be best-effort; if join fails, we + # still proceed with closing the session. + self.__session.logger.debug( + "Receiver.stop: failed to join receiver thread", exc_info=True + ) + + def run(self) -> None: + """Receive Packet thread function""" + self.__session.logger.info("Session.Receiver started") + # If the session has been explicitly closed elsewhere, do not + # start the receive loop at all; this prevents infinite + # reconnect cycles when the caller is done. + if not self.__running: + return + + # Track how many times in a row we have seen a connection + # reset (Errno 104). After a small number of consecutive + # occurrences, stop trying to reconnect to avoid an + # infinite loop when the remote side keeps closing. + consecutive_resets = 0 + max_consecutive_resets = 3 + + while self.__running: + packet: Packet + cmd: bytes + try: + packet = self.__session.cipher_pair.receive_encoded( + self.__session.connection) + cmd = Packet.Type.parse(packet.cmd) + if cmd is None: + self.__session.logger.info( + "Skipping unknown command cmd: 0x{}, payload: {}". + format(util.bytes_to_hex(packet.cmd), + packet.payload)) + continue + except (RuntimeError, ConnectionResetError, OSError) as ex: + # If we've been asked to stop, just exit quietly without + # trying to reconnect. This avoids the situation where the + # session keeps reconnecting in a loop after the work is + # finished and the caller expects shutdown. + if not self.__running: + self.__session.logger.info( + "Receiver stopping after connection error: %s", ex + ) + break + + # Detect repeated "connection reset by peer" errors. + is_reset = isinstance(ex, ConnectionResetError) or ( + isinstance(ex, OSError) + and getattr(ex, "errno", None) == 104 + ) + + # If the underlying socket is already closed (e.g. + # Bad file descriptor), just stop quietly; this can + # happen when Session.close() has torn down the + # connection while the receiver was blocked in recv(). + if isinstance(ex, OSError) and getattr(ex, "errno", None) == 9: + #self.__session.logger.info( + # "Receiver stopping after socket close (errno 9)" + #) + self.__running = False + break + if is_reset: + consecutive_resets += 1 + self.__session.logger.fatal( + "Failed reading packet (reset #%d)! %s", + consecutive_resets, + ex, + ) + if consecutive_resets >= max_consecutive_resets: + self.__session.logger.error( + "Too many consecutive connection resets (%d). " + "Stopping receiver without further reconnect attempts.", + consecutive_resets, + ) + # Mark as not running so the outer loop and + # any future reconnect logic will see that the + # session should shut down. + self.__running = False + break + else: + consecutive_resets = 0 + self.__session.logger.fatal( + "Failed reading packet! %s", ex + ) + + # For both reset and non-reset errors (unless we've + # exceeded the reset threshold), attempt a single + # reconnect. + if self.__running: + self.__session.reconnect() + break + if not self.__running: + break + if cmd == Packet.Type.ping: + if self.__session.scheduled_reconnect is not None: + self.__session.scheduler.cancel( + self.__session.scheduled_reconnect) + + def anonymous(): + """ """ + self.__session.logger.warning( + "Socket timed out. Reconnecting...") + self.__session.reconnect() + + self.__session.scheduled_reconnect = self.__session.scheduler.enter( + 2 * 60 + 5, 1, anonymous) + self.__session.send(Packet.Type.pong, packet.payload) + elif cmd == Packet.Type.pong_ack: + continue + elif cmd == Packet.Type.country_code: + self.__session.__country_code = packet.payload.decode() + self.__session.logger.info( + "Received country_code: {}".format( + self.__session.__country_code)) + elif cmd == Packet.Type.license_version: + license_version = io.BytesIO(packet.payload) + license_id = struct.unpack(">h", + license_version.read(2))[0] + if license_id != 0: + buffer = license_version.read() + self.__session.logger.info( + "Received license_version: {}, {}".format( + license_id, buffer.decode())) + else: + self.__session.logger.info( + "Received license_version: {}".format(license_id)) + elif cmd == Packet.Type.unknown_0x10: + self.__session.logger.debug("Received 0x10: {}".format( + util.bytes_to_hex(packet.payload))) + elif cmd in [ + Packet.Type.mercury_sub, + Packet.Type.mercury_unsub, + Packet.Type.mercury_event, + Packet.Type.mercury_req, + ]: + self.__session.mercury().dispatch(packet) + elif cmd in [Packet.Type.aes_key, Packet.Type.aes_key_error]: + self.__session.audio_key().dispatch(packet) + elif cmd in [ + Packet.Type.channel_error, Packet.Type.stream_chunk_res + ]: + self.__session.channel().dispatch(packet) + elif cmd == Packet.Type.product_info: + self.__session.parse_product_info(packet.payload) + else: + self.__session.logger.info("Skipping {}".format( + util.bytes_to_hex(cmd))) + + class SpotifyAuthenticationException(Exception): + """ """ + + def __init__(self, login_failed: Keyexchange.APLoginFailed): + super().__init__( + Keyexchange.ErrorCode.Name(login_failed.error_code)) + + +class SearchManager: + """ """ + base_url = "hm://searchview/km/v4/search/" + __session: Session + + def __init__(self, session: Session): + self.__session = session + + def request(self, request: SearchRequest) -> typing.Any: + """ + + :param request: SearchRequest: + + """ + if request.get_username() == "": + request.set_username(self.__session.username()) + if request.get_country() == "": + request.set_country(self.__session.country_code) + if request.get_locale() == "": + request.set_locale(self.__session.preferred_locale()) + response = self.__session.mercury().send_sync( + RawMercuryRequest.new_builder().set_method("GET").set_uri( + request.build_url()).build()) + if response.status_code != 200: + raise SearchManager.SearchException(response.status_code) + return json.loads(response.payload) + + class SearchException(Exception): + """ """ + + def __init__(self, status_code: int): + super().__init__("Search failed with code {}.".format(status_code)) + + class SearchRequest: + """ """ + query: typing.Final[str] + __catalogue = "" + __country = "" + __image_size = "" + __limit = 10 + __locale = "" + __username = "" + + def __init__(self, query: str): + self.query = query + if query == "": + raise TypeError + + def build_url(self) -> str: + """ """ + url = SearchManager.base_url + urllib.parse.quote(self.query) + url += "?entityVersion=2" + url += "&catalogue=" + urllib.parse.quote(self.__catalogue) + url += "&country=" + urllib.parse.quote(self.__country) + url += "&imageSize=" + urllib.parse.quote(self.__image_size) + url += "&limit=" + str(self.__limit) + url += "&locale=" + urllib.parse.quote(self.__locale) + url += "&username=" + urllib.parse.quote(self.__username) + return url + + def get_catalogue(self) -> str: + """ """ + return self.__catalogue + + def get_country(self) -> str: + """ """ + return self.__country + + def get_image_size(self) -> str: + """ """ + return self.__image_size + + def get_limit(self) -> int: + """ """ + return self.__limit + + def get_locale(self) -> str: + """ """ + return self.__locale + + def get_username(self) -> str: + """ """ + return self.__username + + def set_catalogue(self, catalogue: str) -> SearchManager.SearchRequest: + """ + + :param catalogue: str: + + """ + self.__catalogue = catalogue + return self + + def set_country(self, country: str) -> SearchManager.SearchRequest: + """ + + :param country: str: + + """ + self.__country = country + return self + + def set_image_size(self, + image_size: str) -> SearchManager.SearchRequest: + """ + + :param image_size: str: + + """ + self.__image_size = image_size + return self + + def set_limit(self, limit: int) -> SearchManager.SearchRequest: + """ + + :param limit: int: + + """ + self.__limit = limit + return self + + def set_locale(self, locale: str) -> SearchManager.SearchRequest: + """ + + :param locale: str: + + """ + self.__locale = locale + return self + + def set_username(self, username: str) -> SearchManager.SearchRequest: + """ + + :param username: str: + + """ + self.__username = username + return self + + +class TokenProvider: + """ """ + logger = logging.getLogger("Librespot:TokenProvider") + token_expire_threshold = 10 + __session: Session + __tokens: typing.List[StoredToken] = [] + + def __init__(self, session: Session): + self._session = session + + def find_token_with_all_scopes( + self, scopes: typing.List[str]) -> typing.Union[StoredToken, None]: + """ + + :param scopes: typing.List[str]: + + """ + for token in self.__tokens: + if token.has_scopes(scopes): + return token + return None + + def get(self, scope: str) -> str: + """ + + :param scope: str: + + """ + return self.get_token(scope).access_token + + def get_token(self, *scopes) -> StoredToken: + """ + + :param *scopes: + + """ + scopes = list(scopes) + if len(scopes) == 0: + raise RuntimeError("The token doesn't have any scope") + + login5_token = self._session.get_login5_token() + if login5_token: + # Create a StoredToken-compatible object using Login5 token + login5_stored_token = TokenProvider.Login5StoredToken(login5_token, scopes) + self.logger.debug("Using Login5 access token for scopes: {}".format(scopes)) + return login5_stored_token + + token = self.find_token_with_all_scopes(scopes) + if token is not None: + if token.expired(): + self.__tokens.remove(token) + else: + return token + self.logger.debug( + "Token expired or not suitable, requesting again. scopes: {}, old_token: {}" + .format(scopes, token)) + + try: + response = self._session.mercury().send_sync_json( + MercuryRequests.request_token(self._session.device_id(), + ",".join(scopes))) + token = TokenProvider.StoredToken(response) + self.logger.debug( + "Updated token successfully! scopes: {}, new_token: {}".format( + scopes, token)) + self.__tokens.append(token) + return token + except Exception as e: + self.logger.warning("Failed to get token from keymaster endpoint: {}".format(e)) + raise RuntimeError("Unable to obtain access token") + + class Login5StoredToken: + """StoredToken-compatible wrapper for Login5 access tokens""" + access_token: str + scopes: typing.List[str] + + def __init__(self, access_token: str, scopes: typing.List[str]): + self.access_token = access_token + self.scopes = scopes + + def expired(self) -> bool: + """Login5 tokens are managed by Session, so delegate expiry check""" + return False # Session handles expiry + + def has_scope(self, scope: str) -> bool: + """Login5 tokens are general-purpose, assume they have all scopes""" + return True + + def has_scopes(self, sc: typing.List[str]) -> bool: + """Login5 tokens are general-purpose, assume they have all scopes""" + return True + + class StoredToken: + """ """ + expires_in: int + access_token: str + scopes: typing.List[str] + timestamp: int + + def __init__(self, obj): + self.timestamp = int(time.time_ns() / 1000) + self.expires_in = obj["expiresIn"] + self.access_token = obj["accessToken"] + self.scopes = obj["scope"] + + def expired(self) -> bool: + """ """ + return self.timestamp + (self.expires_in - TokenProvider. + token_expire_threshold) * 1000 * 1000 < int( + time.time_ns() / 1000) + + def has_scope(self, scope: str) -> bool: + """ + + :param scope: str: + + """ + for s in self.scopes: + if s == scope: + return True + return False + + def has_scopes(self, sc: typing.List[str]) -> bool: + """ + + :param sc: typing.List[str]: + + """ + for s in sc: + if not self.has_scope(s): + return False + return True diff --git a/librespot/crypto.py b/librespot/crypto.py new file mode 100644 index 0000000..6ae8c23 --- /dev/null +++ b/librespot/crypto.py @@ -0,0 +1,412 @@ +from __future__ import annotations +from Cryptodome import Random +from librespot import util +import io +import re +import struct +import typing + +if typing.TYPE_CHECKING: + from librespot.core import Session + + +class CipherPair: + __receive_cipher: Shannon + __receive_nonce = 0 + __send_cipher: Shannon + __send_nonce = 0 + + def __init__(self, send_key: bytes, receive_key: bytes): + self.__send_cipher = Shannon() + self.__send_cipher.key(send_key) + self.__receive_cipher = Shannon() + self.__receive_cipher.key(receive_key) + + def send_encoded(self, connection: Session.ConnectionHolder, cmd: bytes, + payload: bytes) -> None: + """ + Send decrypted data to the socket + :param connection: + :param cmd: + :param payload: + :return: + """ + self.__send_cipher.nonce(self.__send_nonce) + self.__send_nonce += 1 + buffer = io.BytesIO() + buffer.write(cmd) + buffer.write(struct.pack(">H", len(payload))) + buffer.write(payload) + buffer.seek(0) + contents = self.__send_cipher.encrypt(buffer.read()) + mac = self.__send_cipher.finish(4) + connection.write(contents) + connection.write(mac) + connection.flush() + + def receive_encoded(self, connection: Session.ConnectionHolder) -> Packet: + """ + Receive and parse decrypted data from the socket + Args: + connection: ConnectionHolder + Return: + The parsed packet will be returned + """ + try: + self.__receive_cipher.nonce(self.__receive_nonce) + self.__receive_nonce += 1 + header_bytes = self.__receive_cipher.decrypt(connection.read(3)) + cmd = struct.pack(">s", bytes([header_bytes[0]])) + payload_length = (header_bytes[1] << 8) | (header_bytes[2] & 0xff) + payload_bytes = self.__receive_cipher.decrypt( + connection.read(payload_length)) + mac = connection.read(4) + expected_mac = self.__receive_cipher.finish(4) + if mac != expected_mac: + raise RuntimeError() + return Packet(cmd, payload_bytes) + except IndexError: + raise RuntimeError("Failed to receive packet") + + +class DiffieHellman: + """ + DiffieHellman Keyexchange + """ + __prime = int.from_bytes( + b'\xff\xff\xff\xff\xff\xff\xff\xff\xc9\x0f' + b'\xda\xa2!h\xc24\xc4\xc6b\x8b\x80\xdc\x1c' + b'\xd1)\x02N\x08\x8ag\xcct\x02\x0b\xbe\xa6;' + b'\x13\x9b"QJ\x08y\x8e4\x04\xdd\xef\x95\x19' + b'\xb3\xcd:C\x1b0+\nm\xf2_\x147O\xe15mmQ\xc2' + b'E\xe4\x85\xb5vb^~\xc6\xf4LB\xe9\xa6:6 \xff' + b'\xff\xff\xff\xff\xff\xff\xff', + byteorder="big") + __private_key: int + __public_key: int + + def __init__(self): + key_data = Random.get_random_bytes(0x5f) + self.__private_key = int.from_bytes(key_data, byteorder="big") + self.__public_key = pow(2, self.__private_key, self.__prime) + + def compute_shared_key(self, remote_key_bytes: bytes): + """ + Compute shared_key + """ + remote_key = int.from_bytes(remote_key_bytes, "big") + return pow(remote_key, self.__private_key, self.__prime) + + def private_key(self) -> int: + """ + Return DiffieHellman's private key + Returns: + DiffieHellman's private key + """ + return self.__private_key + + def public_key(self) -> int: + """ + Return DiffieHellman's public key + Returns: + DiffieHellman's public key + """ + return self.__public_key + + def public_key_bytes(self) -> bytes: + """ + Return DiffieHellman's packed public key + Returns: + DiffieHellman's packed public key + """ + return util.int_to_bytes(self.__public_key) + + +class Packet: + cmd: bytes + payload: bytes + + def __init__(self, cmd: bytes, payload: bytes): + self.cmd = cmd + self.payload = payload + + def is_cmd(self, cmd: bytes) -> bool: + return cmd == self.cmd + + class Type: + secret_block = b"\x02" + ping = b"\x04" + stream_chunk = b"\x08" + stream_chunk_res = b"\x09" + channel_error = b"\x0a" + channel_abort = b"\x0b" + request_key = b"\x0c" + aes_key = b"\x0d" + aes_key_error = b"\x0e" + image = b"\x19" + country_code = b"\x1b" + pong = b"\x49" + pong_ack = b"\x4a" + pause = b"\x4b" + product_info = b"\x50" + legacy_welcome = b"\x69" + license_version = b"\x76" + login = b"\xab" + ap_welcome = b"\xac" + auth_failure = b"\xad" + mercury_req = b"\xb2" + mercury_sub = b"\xb3" + mercury_unsub = b"\xb4" + mercury_event = b"\xb5" + track_ended_time = b"\x82" + unknown_data_all_zeros = b"\x1f" + preferred_locale = b"\x74" + unknown_0x4f = b"\x4f" + unknown_0x0f = b"\x0f" + unknown_0x10 = b"\x10" + + @staticmethod + def parse(val: typing.Union[bytes, None]) -> typing.Union[bytes, None]: + for cmd in [ + Packet.Type.__dict__[attr] for attr in Packet.Type.__dict__ + if re.search("__.+?__", attr) is None + and type(Packet.Type.__dict__[attr]) is bytes + ]: + if cmd == val: + return cmd + return None + + @staticmethod + def for_method(method: str) -> bytes: + if method == "SUB": + return Packet.Type.mercury_sub + if method == "UNSUB": + return Packet.Type.mercury_unsub + return Packet.Type.mercury_req + + +class Shannon: + n = 16 + fold = n + initkonst = 0x6996c53a + keyp = 13 + r: list + crc: list + init_r: list + konst: int + sbuf: int + mbuf: int + nbuf: int + + def __init__(self): + self.r = [0 for _ in range(self.n)] + self.crc = [0 for _ in range(self.n)] + self.init_r = [0 for _ in range(self.n)] + + def rotl(self, i: int, distance: int) -> int: + return ((i << distance) | (i >> (32 - distance))) & 0xffffffff + + def sbox(self, i: int) -> int: + i ^= self.rotl(i, 5) | self.rotl(i, 7) + i ^= self.rotl(i, 19) | self.rotl(i, 22) + return i + + def sbox2(self, i: int) -> int: + i ^= self.rotl(i, 7) | self.rotl(i, 22) + i ^= self.rotl(i, 5) | self.rotl(i, 19) + return i + + def cycle(self) -> None: + t: int + t = self.r[12] ^ self.r[13] ^ self.konst + t = self.sbox(t) ^ self.rotl(self.r[0], 1) + for i in range(1, self.n): + self.r[i - 1] = self.r[i] + self.r[self.n - 1] = t + t = self.sbox2(self.r[2] ^ self.r[15]) + self.r[0] ^= t + self.sbuf = t ^ self.r[8] ^ self.r[12] + + def crc_func(self, i: int) -> None: + t: int + t = self.crc[0] ^ self.crc[2] ^ self.crc[15] ^ i + for j in range(1, self.n): + self.crc[j - 1] = self.crc[j] + self.crc[self.n - 1] = t + + def mac_func(self, i: int) -> None: + self.crc_func(i) + self.r[self.keyp] ^= i + + def init_state(self) -> None: + self.r[0] = 1 + self.r[1] = 1 + for i in range(2, self.n): + self.r[i] = self.r[i - 1] + self.r[i - 2] + self.konst = self.initkonst + + def save_state(self) -> None: + for i in range(self.n): + self.init_r[i] = self.r[i] + + def reload_state(self) -> None: + for i in range(self.n): + self.r[i] = self.init_r[i] + + def gen_konst(self) -> None: + self.konst = self.r[0] + + def add_key(self, k: int) -> None: + self.r[self.keyp] ^= k + + def diffuse(self) -> None: + for _ in range(self.fold): + self.cycle() + + def load_key(self, key: bytes) -> None: + i: int + j: int + t: int + padding_size = int((len(key) + 3) / 4) * 4 - len(key) + key = key + (b"\x00" * padding_size) + struct.pack(" None: + self.init_state() + self.load_key(key) + self.gen_konst() + self.save_state() + self.nbuf = 0 + + def nonce(self, nonce: typing.Union[bytes, int]) -> None: + if type(nonce) is int: + nonce = bytes(struct.pack(">I", nonce)) + self.reload_state() + self.konst = self.initkonst + self.load_key(nonce) + self.gen_konst() + self.nbuf = 0 + + def encrypt(self, buffer: bytes, n: int = None) -> bytes: + if n is None: + return self.encrypt(buffer, len(buffer)) + buffer = bytearray(buffer) + i = 0 + j: int + t: int + if self.nbuf != 0: + while self.nbuf != 0 and n != 0: + self.mbuf ^= (buffer[i] & 0xff) << (32 - self.nbuf) + buffer[i] ^= (self.sbuf >> (32 - self.nbuf)) & 0xff + i += 1 + self.nbuf -= 8 + n -= 1 + if self.nbuf != 0: + return b"" + self.mac_func(self.mbuf) + j = n & ~0x03 + while i < j: + self.cycle() + t = ((buffer[i + 3] & 0xFF) << 24) | \ + ((buffer[i + 2] & 0xFF) << 16) | \ + ((buffer[i + 1] & 0xFF) << 8) | \ + (buffer[i] & 0xFF) + self.mac_func(t) + t ^= self.sbuf + buffer[i + 3] = (t >> 24) & 0xFF + buffer[i + 2] = (t >> 16) & 0xFF + buffer[i + 1] = (t >> 8) & 0xFF + buffer[i] = t & 0xFF + i += 4 + n &= 0x03 + if n != 0: + self.cycle() + self.mbuf = 0 + self.nbuf = 32 + while self.nbuf != 0 and n != 0: + self.mbuf ^= (buffer[i] & 0xff) << (32 - self.nbuf) + buffer[i] ^= (self.sbuf >> (32 - self.nbuf)) & 0xff + i += 1 + self.nbuf -= 8 + n -= 1 + return bytes(buffer) + + def decrypt(self, buffer: bytes, n: int = None) -> bytes: + if n is None: + return self.decrypt(buffer, len(buffer)) + buffer = bytearray(buffer) + i = 0 + j: int + t: int + if self.nbuf != 0: + while self.nbuf != 0 and n != 0: + buffer[i] ^= (self.sbuf >> (32 - self.nbuf)) & 0xff + self.mbuf ^= (buffer[i] & 0xff) << (32 - self.nbuf) + i += 1 + self.nbuf -= 8 + n -= 1 + if self.nbuf != 0: + return b"" + self.mac_func(self.mbuf) + j = n & ~0x03 + while i < j: + self.cycle() + t = ((buffer[i + 3] & 0xFF) << 24) | \ + ((buffer[i + 2] & 0xFF) << 16) | \ + ((buffer[i + 1] & 0xFF) << 8) | \ + (buffer[i] & 0xFF) + t ^= self.sbuf + self.mac_func(t) + buffer[i + 3] = (t >> 24) & 0xFF + buffer[i + 2] = (t >> 16) & 0xFF + buffer[i + 1] = (t >> 8) & 0xFF + buffer[i] = t & 0xFF + i += 4 + n &= 0x03 + if n != 0: + self.cycle() + self.mbuf = 0 + self.nbuf = 32 + while self.nbuf != 0 and n != 0: + buffer[i] ^= (self.sbuf >> (32 - self.nbuf)) & 0xff + self.mbuf ^= (buffer[i] & 0xff) << (32 - self.nbuf) + i += 1 + self.nbuf -= 8 + n -= 1 + return bytes(buffer) + + def finish(self, n: int) -> bytes: + buffer = bytearray(4) + i = 0 + j: int + if self.nbuf != 0: + self.mac_func(self.mbuf) + self.cycle() + self.add_key(self.initkonst ^ (self.nbuf << 3)) + self.nbuf = 0 + for j in range(self.n): + self.r[j] ^= self.crc[j] + self.diffuse() + while n > 0: + self.cycle() + if n >= 4: + buffer[i + 3] = (self.sbuf >> 24) & 0xff + buffer[i + 2] = (self.sbuf >> 16) & 0xff + buffer[i + 1] = (self.sbuf >> 8) & 0xff + buffer[i] = self.sbuf & 0xff + n -= 4 + i += 4 + else: + for j in range(n): + buffer[i + j] = (self.sbuf >> (i * 8)) & 0xff + break + return bytes(buffer) diff --git a/librespot/dealer.py b/librespot/dealer.py new file mode 100644 index 0000000..143c256 --- /dev/null +++ b/librespot/dealer.py @@ -0,0 +1,11 @@ +from __future__ import annotations +from librespot.core import ApResolver +from librespot.metadata import AlbumId, ArtistId, EpisodeId, ShowId, TrackId +from librespot.proto import Connect_pb2 as Connect, Metadata_pb2 as Metadata +from librespot.structure import Closeable +import logging +import requests +import typing + +if typing.TYPE_CHECKING: + from librespot.core import Session diff --git a/librespot/mercury.py b/librespot/mercury.py new file mode 100644 index 0000000..450b98f --- /dev/null +++ b/librespot/mercury.py @@ -0,0 +1,394 @@ +from __future__ import annotations +from librespot import util +from librespot.crypto import Packet +from librespot.proto import Mercury_pb2 as Mercury, Pubsub_pb2 as Pubsub +from librespot.structure import Closeable, PacketsReceiver, SubListener +import io +import json +import logging +import queue +import struct +import threading +import typing + +if typing.TYPE_CHECKING: + from librespot.core import Session + + +class JsonMercuryRequest: + request: RawMercuryRequest + + def __init__(self, request: RawMercuryRequest): + self.request = request + + +class MercuryClient(Closeable, PacketsReceiver): + logger = logging.getLogger("Librespot:MercuryClient") + mercury_request_timeout = 3 + __callbacks: typing.Dict[int, Callback] = {} + __remove_callback_lock = threading.Condition() + __partials: typing.Dict[int, typing.List[bytes]] = {} + __seq_holder = 0 + __seq_holder_lock = threading.Condition() + __session: Session + __subscriptions: typing.List[InternalSubListener] = [] + __subscriptions_lock = threading.Condition() + + def __init__(self, session: Session): + self.__session = session + + def close(self) -> None: + """ + Close the MercuryClient instance + """ + if len(self.__subscriptions) != 0: + for listener in self.__subscriptions: + if listener.is_sub: + self.unsubscribe(listener.uri) + else: + self.not_interested_in(listener.listener) + if len(self.__callbacks) != 0: + with self.__remove_callback_lock: + self.__remove_callback_lock.wait(self.mercury_request_timeout) + self.__callbacks.clear() + + def dispatch(self, packet: Packet) -> None: + payload = io.BytesIO(packet.payload) + seq_length = struct.unpack(">H", payload.read(2))[0] + if seq_length == 2: + seq = struct.unpack(">H", payload.read(2))[0] + elif seq_length == 4: + seq = struct.unpack(">i", payload.read(4))[0] + elif seq_length == 8: + seq = struct.unpack(">q", payload.read(8))[0] + else: + raise RuntimeError("Unknown seq length: {}".format(seq_length)) + flags = payload.read(1) + parts = struct.unpack(">H", payload.read(2))[0] + partial = self.__partials.get(seq) + if partial is None or flags == 0: + partial = [] + self.__partials[seq] = partial + self.logger.debug( + "Handling packet, cmd: 0x{}, seq: {}, flags: {}, parts: {}".format( + util.bytes_to_hex(packet.cmd), seq, flags, parts)) + for _ in range(parts): + size = struct.unpack(">H", payload.read(2))[0] + buffer = payload.read(size) + partial.append(buffer) + self.__partials[seq] = partial + if flags != b"\x01": + return + self.__partials.pop(seq) + header = Mercury.Header() + header.ParseFromString(partial[0]) + response = MercuryClient.Response(header, partial) + if packet.is_cmd(Packet.Type.mercury_event): + dispatched = False + with self.__subscriptions_lock: + for sub in self.__subscriptions: + if sub.matches(header.uri): + sub.dispatch(response) + dispatched = True + if not dispatched: + self.logger.debug( + "Couldn't dispatch Mercury event seq: {}, uri: {}, code: {}, payload: {}" + .format(seq, header.uri, header.status_code, + response.payload)) + elif (packet.is_cmd(Packet.Type.mercury_req) + or packet.is_cmd(Packet.Type.mercury_sub) + or packet.is_cmd(Packet.Type.mercury_sub)): + callback = self.__callbacks.get(seq) + self.__callbacks.pop(seq) + if callback is not None: + callback.response(response) + else: + self.logger.warning( + "Skipped Mercury response, seq: {}, uri: {}, code: {}". + format(seq, response.uri, response.status_code)) + with self.__remove_callback_lock: + self.__remove_callback_lock.notify_all() + else: + self.logger.warning( + "Couldn't handle packet, seq: {}, uri: {}, code: {}".format( + seq, header.uri, header.status_code)) + + def interested_in(self, uri: str, listener: SubListener) -> None: + self.__subscriptions.append( + MercuryClient.InternalSubListener(uri, listener, False)) + + def not_interested_in(self, listener: SubListener) -> None: + try: + for subscription in self.__subscriptions: + if subscription.listener is listener: + self.__subscriptions.remove(subscription) + break + except ValueError: + pass + + def send(self, request: RawMercuryRequest, callback) -> int: + """ + Send the Mercury request + Args: + request: RawMercuryRequest + callback: Callback function + Returns: + MercuryClient.Response + """ + buffer = io.BytesIO() + seq: int + with self.__seq_holder_lock: + seq = self.__seq_holder + self.__seq_holder += 1 + self.logger.debug( + "Send Mercury request, seq: {}, uri: {}, method: {}".format( + seq, request.header.uri, request.header.method)) + buffer.write(struct.pack(">H", 4)) + buffer.write(struct.pack(">i", seq)) + buffer.write(b"\x01") + buffer.write(struct.pack(">H", 1 + len(request.payload))) + header_bytes = request.header.SerializeToString() + buffer.write(struct.pack(">H", len(header_bytes))) + buffer.write(header_bytes) + for part in request.payload: + buffer.write(struct.pack(">H", len(part))) + buffer.write(part) + buffer.seek(0) + cmd = Packet.Type.for_method(request.header.method) + self.__session.send(cmd, buffer.read()) + self.__callbacks[seq] = callback + return seq + + def send_sync(self, request: RawMercuryRequest) -> Response: + """ + Send the Mercury request + Args: + request: RawMercuryRequest + Returns: + MercuryClient.Response + """ + callback = MercuryClient.SyncCallback() + seq = self.send(request, callback) + try: + response = callback.wait_response() + if response is None: + raise IOError( + "Request timeout out, {} passed, yet no response. seq: {}". + format(self.mercury_request_timeout, seq)) + return response + except queue.Empty as e: + raise IOError(e) + + def send_sync_json(self, request: JsonMercuryRequest) -> typing.Any: + response = self.send_sync(request.request) + if 200 <= response.status_code < 300: + return json.loads(response.payload) + raise MercuryClient.MercuryException(response) + + def subscribe(self, uri: str, listener: SubListener) -> None: + """ + Subscribe URI + Args: + uri: + listener: + """ + response = self.send_sync(RawMercuryRequest.sub(uri)) + if response.status_code != 200: + raise RuntimeError(response) + if len(response.payload) > 0: + for payload in response.payload: + sub = Pubsub.Subscription() + sub.ParseFromString(payload) + self.__subscriptions.append( + MercuryClient.InternalSubListener(sub.uri, listener, True)) + else: + self.__subscriptions.append( + MercuryClient.InternalSubListener(uri, listener, True)) + self.logger.debug("Subscribed successfully to {}!".format(uri)) + + def unsubscribe(self, uri) -> None: + """ + Unsubscribe URI + Args: + uri: + """ + response = self.send_sync(RawMercuryRequest.unsub(uri)) + if response.status_code != 200: + raise RuntimeError(response) + for subscription in self.__subscriptions: + if subscription.matches(uri): + self.__subscriptions.remove(subscription) + break + self.logger.debug("Unsubscribed successfully from {}!".format(uri)) + + class Callback: + def response(self, response: MercuryClient.Response) -> None: + raise NotImplementedError + + class InternalSubListener: + uri: str + listener: SubListener + is_sub: bool + + def __init__(self, uri: str, listener: SubListener, is_sub: bool): + self.uri = uri + self.listener = listener + self.is_sub = is_sub + + def matches(self, uri: str) -> bool: + """ + Compare with the URI given + Args: + uri: URI to be compared + Returns: + bool + """ + return uri.startswith(self.uri) + + def dispatch(self, response: MercuryClient.Response) -> None: + """ + Dispatch the event response + Args: + response: Response generated by the event + """ + self.listener.event(response) + + class MercuryException(Exception): + code: int + + def __init__(self, response: MercuryClient.Response): + super().__init__("status: {}".format(response.status_code)) + self.code = response.status_code + + class PubSubException(MercuryException): + pass + + class Response: + uri: str + payload: bytes + status_code: int + + def __init__(self, header: Mercury.Header, payload: list[bytes]): + self.uri = header.uri + self.status_code = header.status_code + self.payload = b"".join(payload[1:]) + + class SyncCallback(Callback): + __reference = queue.Queue() + + def response(self, response: MercuryClient.Response) -> None: + """ + Set the response + :param response: + :return: + """ + self.__reference.put(response) + self.__reference.task_done() + + def wait_response(self) -> typing.Any: + return self.__reference.get( + timeout=MercuryClient.mercury_request_timeout) + + +class MercuryRequests: + keymaster_client_id = "65b708073fc0480ea92a077233ca87bd" + + @staticmethod + def get_root_playlists(username: str): + """ + @TODO implement function + """ + + @staticmethod + def request_token(device_id, scope): + return JsonMercuryRequest( + RawMercuryRequest.get( + "hm://keymaster/token/authenticated?scope={}&client_id={}&device_id={}" + .format(scope, MercuryRequests.keymaster_client_id, + device_id))) + + +class RawMercuryRequest: + header: Mercury.Header + payload: typing.List[bytes] + + def __init__(self, header: Mercury.Header, payload: typing.List[bytes]): + self.header = header + self.payload = payload + + @staticmethod + def sub(uri: str): + return RawMercuryRequest.new_builder().set_uri(uri).set_method( + "SUB").build() + + @staticmethod + def unsub(uri: str): + return RawMercuryRequest.new_builder().set_uri(uri).set_method( + "UNSUB").build() + + @staticmethod + def get(uri: str): + return RawMercuryRequest.new_builder().set_uri(uri).set_method( + "GET").build() + + @staticmethod + def send(uri: str, part: bytes): + return RawMercuryRequest.new_builder().set_uri(uri) \ + .add_payload_part(part).set_method("SEND").build() + + @staticmethod + def post(uri: str, part: bytes): + return RawMercuryRequest.new_builder().set_uri(uri) \ + .set_method("POST").add_payload_part(part).build() + + @staticmethod + def new_builder(): + return RawMercuryRequest.Builder() + + class Builder: + header_dict: dict + payload: typing.List[bytes] + + def __init__(self): + self.header_dict = {} + self.payload = [] + + def set_uri(self, uri: str): + self.header_dict["uri"] = uri + return self + + def set_content_type(self, content_type: str): + self.header_dict["content_type"] = content_type + return self + + def set_method(self, method: str): + self.header_dict["method"] = method + return self + + def add_user_field(self, + field: Mercury.UserField = None, + key: str = None, + value: str = None): + if field is None and (key is None or value is None): + return self + try: + self.header_dict["user_fields"] + except KeyError: + self.header_dict["user_fields"] = [] + if field is not None: + self.header_dict["user_fields"].append(field) + if key is not None and value is not None: + self.header_dict["user_fields"].append( + Mercury.UserField(key=key, value=value.encode())) + return self + + def add_payload_part(self, part: bytes): + self.payload.append(part) + return self + + def add_protobuf_payload(self, msg): + return self.add_payload_part(msg) + + def build(self): + return RawMercuryRequest(Mercury.Header(**self.header_dict), + self.payload) diff --git a/librespot/metadata.py b/librespot/metadata.py new file mode 100644 index 0000000..a5e01e9 --- /dev/null +++ b/librespot/metadata.py @@ -0,0 +1,283 @@ +from __future__ import annotations +from librespot import util +from librespot.proto.ContextTrack_pb2 import ContextTrack +from librespot.util import Base62 +import re + + +class SpotifyId: + STATIC_FROM_URI = "fromUri" + STATIC_FROM_BASE62 = "fromBase62" + STATIC_FROM_HEX = "fromHex" + + @staticmethod + def from_base62(base62: str): + raise NotImplementedError + + @staticmethod + def from_hex(hex_str: str): + raise NotImplementedError + + @staticmethod + def from_uri(uri: str): + raise NotImplementedError + + def to_spotify_uri(self) -> str: + raise NotImplementedError + + class SpotifyIdParsingException(Exception): + pass + + +class PlayableId: + base62 = Base62.create_instance_with_inverted_character_set() + + @staticmethod + def from_uri(uri: str) -> PlayableId: + if not PlayableId.is_supported(uri): + return UnsupportedId(uri) + if TrackId.pattern.search(uri) is not None: + return TrackId.from_uri(uri) + if EpisodeId.pattern.search(uri) is not None: + return EpisodeId.from_uri(uri) + raise TypeError("Unknown uri: {}".format(uri)) + + @staticmethod + def is_supported(uri: str): + return (not uri.startswith("spotify:local:") + and not uri == "spotify:delimiter" + and not uri == "spotify:meta:delimiter") + + @staticmethod + def should_play(track: ContextTrack): + return track.metadata_or_default + + def get_gid(self) -> bytes: + raise NotImplementedError + + def hex_id(self) -> str: + raise NotImplementedError + + def to_spotify_uri(self) -> str: + raise NotImplementedError + + +class PlaylistId(SpotifyId): + base62 = Base62.create_instance_with_inverted_character_set() + pattern = re.compile(r"spotify:playlist:(.{22})") + __id: str + + def __init__(self, _id: str): + self.__id = _id + + @staticmethod + def from_uri(uri: str) -> PlaylistId: + matcher = PlaylistId.pattern.search(uri) + if matcher is not None: + playlist_id = matcher.group(1) + return PlaylistId(playlist_id) + raise TypeError("Not a Spotify playlist ID: {}.".format(uri)) + + def id(self) -> str: + return self.__id + + def to_spotify_uri(self) -> str: + return "spotify:playlist:" + self.__id + + +class UnsupportedId(PlayableId): + uri: str + + def __init__(self, uri: str): + self.uri = uri + + def get_gid(self) -> bytes: + raise TypeError() + + def hex_id(self) -> str: + raise TypeError() + + def to_spotify_uri(self) -> str: + return self.uri + + +class AlbumId(SpotifyId): + base62 = Base62.create_instance_with_inverted_character_set() + pattern = re.compile(r"spotify:album:(.{22})") + __hex_id: str + + def __init__(self, hex_id: str): + self.__hex_id = hex_id.lower() + + @staticmethod + def from_uri(uri: str) -> AlbumId: + matcher = AlbumId.pattern.search(uri) + if matcher is not None: + album_id = matcher.group(1) + return AlbumId(util.bytes_to_hex(AlbumId.base62.decode(album_id.encode(), 16))) + raise TypeError("Not a Spotify album ID: {}.".format(uri)) + + @staticmethod + def from_base62(base62: str) -> AlbumId: + return AlbumId(util.bytes_to_hex(AlbumId.base62.decode(base62.encode(), 16))) + + @staticmethod + def from_hex(hex_str: str) -> AlbumId: + return AlbumId(hex_str) + + def to_mercury_uri(self) -> str: + return "hm://metadata/4/album/{}".format(self.__hex_id) + + def hex_id(self) -> str: + return self.__hex_id + + def to_spotify_uri(self) -> str: + return "spotify:album:{}".format( + AlbumId.base62.encode(util.hex_to_bytes(self.__hex_id)).decode()) + + +class ArtistId(SpotifyId): + base62 = Base62.create_instance_with_inverted_character_set() + pattern = re.compile("spotify:artist:(.{22})") + __hex_id: str + + def __init__(self, hex_id: str): + self.__hex_id = hex_id.lower() + + @staticmethod + def from_uri(uri: str) -> ArtistId: + matcher = ArtistId.pattern.search(uri) + if matcher is not None: + artist_id = matcher.group(1) + return ArtistId( + util.bytes_to_hex(ArtistId.base62.decode(artist_id.encode(), 16))) + raise TypeError("Not a Spotify artist ID: {}".format(uri)) + + @staticmethod + def from_base62(base62: str) -> ArtistId: + return ArtistId(util.bytes_to_hex(ArtistId.base62.decode(base62.encode(), 16))) + + @staticmethod + def from_hex(hex_str: str) -> ArtistId: + return ArtistId(hex_str) + + def to_mercury_uri(self) -> str: + return "hm://metadata/4/artist/{}".format(self.__hex_id) + + def to_spotify_uri(self) -> str: + return "spotify:artist:{}".format( + ArtistId.base62.encode(util.hex_to_bytes(self.__hex_id)).decode()) + + def hex_id(self) -> str: + return self.__hex_id + + +class EpisodeId(SpotifyId, PlayableId): + pattern = re.compile(r"spotify:episode:(.{22})") + __hex_id: str + + def __init__(self, hex_id: str): + self.__hex_id = hex_id.lower() + + @staticmethod + def from_uri(uri: str) -> EpisodeId: + matcher = EpisodeId.pattern.search(uri) + if matcher is not None: + episode_id = matcher.group(1) + return EpisodeId( + util.bytes_to_hex(PlayableId.base62.decode(episode_id.encode(), 16))) + raise TypeError("Not a Spotify episode ID: {}".format(uri)) + + @staticmethod + def from_base62(base62: str) -> EpisodeId: + return EpisodeId( + util.bytes_to_hex(PlayableId.base62.decode(base62.encode(), 16))) + + @staticmethod + def from_hex(hex_str: str) -> EpisodeId: + return EpisodeId(hex_str) + + def to_mercury_uri(self) -> str: + return "hm://metadata/4/episode/{}".format(self.__hex_id) + + def to_spotify_uri(self) -> str: + return "Spotify:episode:{}".format( + PlayableId.base62.encode(util.hex_to_bytes(self.__hex_id)).decode()) + + def hex_id(self) -> str: + return self.__hex_id + + def get_gid(self) -> bytes: + return util.hex_to_bytes(self.__hex_id) + + +class ShowId(SpotifyId): + base62 = Base62.create_instance_with_inverted_character_set() + pattern = re.compile("spotify:show:(.{22})") + __hex_id: str + + def __init__(self, hex_id: str): + self.__hex_id = hex_id + + @staticmethod + def from_uri(uri: str) -> ShowId: + matcher = ShowId.pattern.search(uri) + if matcher is not None: + show_id = matcher.group(1) + return ShowId(util.bytes_to_hex(ShowId.base62.decode(show_id.encode(), 16))) + raise TypeError("Not a Spotify show ID: {}".format(uri)) + + @staticmethod + def from_base62(base62: str) -> ShowId: + return ShowId(util.bytes_to_hex(ShowId.base62.decode(base62.encode(), 16))) + + @staticmethod + def from_hex(hex_str: str) -> ShowId: + return ShowId(hex_str) + + def to_mercury_uri(self) -> str: + return "hm://metadata/4/show/{}".format(self.__hex_id) + + def to_spotify_uri(self) -> str: + return "spotify:show:{}".format( + ShowId.base62.encode(util.hex_to_bytes(self.__hex_id)).decode()) + + def hex_id(self) -> str: + return self.__hex_id + + +class TrackId(PlayableId, SpotifyId): + pattern = re.compile("spotify:track:(.{22})") + __hex_id: str + + def __init__(self, hex_id: str): + self.__hex_id = hex_id.lower() + + @staticmethod + def from_uri(uri: str) -> TrackId: + search = TrackId.pattern.search(uri) + if search is not None: + track_id = search.group(1) + return TrackId( + util.bytes_to_hex(PlayableId.base62.decode(track_id.encode(), 16))) + raise RuntimeError("Not a Spotify track ID: {}".format(uri)) + + @staticmethod + def from_base62(base62: str) -> TrackId: + return TrackId(util.bytes_to_hex(PlayableId.base62.decode(base62.encode(), 16))) + + @staticmethod + def from_hex(hex_str: str) -> TrackId: + return TrackId(hex_str) + + def to_mercury_uri(self) -> str: + return "hm://metadata/4/track/{}".format(self.__hex_id) + + def to_spotify_uri(self) -> str: + return "spotify:track:{}".format(TrackId.base62.encode(util.hex_to_bytes(self.__hex_id)).decode()) + + def hex_id(self) -> str: + return self.__hex_id + + def get_gid(self) -> bytes: + return util.hex_to_bytes(self.__hex_id) diff --git a/librespot/proto/Authentication_pb2.py b/librespot/proto/Authentication_pb2.py new file mode 100644 index 0000000..b38baf1 --- /dev/null +++ b/librespot/proto/Authentication_pb2.py @@ -0,0 +1,1984 @@ +# -*- coding: utf-8 -*- +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: authentication.proto +"""Generated protocol buffer code.""" +from google.protobuf.internal import enum_type_wrapper +from google.protobuf import descriptor as _descriptor +from google.protobuf import message as _message +from google.protobuf import reflection as _reflection +from google.protobuf import symbol_database as _symbol_database +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + +DESCRIPTOR = _descriptor.FileDescriptor( + name='authentication.proto', + package='spotify', + syntax='proto2', + serialized_options=b'\n\013com.spotify', + create_key=_descriptor._internal_create_key, + serialized_pb= + b'\n\x14\x61uthentication.proto\x12\x07spotify\"\xa2\x03\n\x17\x43lientResponseEncrypted\x12\x34\n\x11login_credentials\x18\n \x02(\x0b\x32\x19.spotify.LoginCredentials\x12\x32\n\x10\x61\x63\x63ount_creation\x18\x14 \x01(\x0e\x32\x18.spotify.AccountCreation\x12?\n\x14\x66ingerprint_response\x18\x1e \x01(\x0b\x32!.spotify.FingerprintResponseUnion\x12-\n\x0bpeer_ticket\x18( \x01(\x0b\x32\x18.spotify.PeerTicketUnion\x12(\n\x0bsystem_info\x18\x32 \x02(\x0b\x32\x13.spotify.SystemInfo\x12\x16\n\x0eplatform_model\x18< \x01(\t\x12\x16\n\x0eversion_string\x18\x46 \x01(\t\x12)\n\x06\x61ppkey\x18P \x01(\x0b\x32\x19.spotify.LibspotifyAppKey\x12(\n\x0b\x63lient_info\x18Z \x01(\x0b\x32\x13.spotify.ClientInfo\"a\n\x10LoginCredentials\x12\x10\n\x08username\x18\n \x01(\t\x12(\n\x03typ\x18\x14 \x02(\x0e\x32\x1b.spotify.AuthenticationType\x12\x11\n\tauth_data\x18\x1e \x01(\x0c\"\x89\x01\n\x18\x46ingerprintResponseUnion\x12\x30\n\x05grain\x18\n \x01(\x0b\x32!.spotify.FingerprintGrainResponse\x12;\n\x0bhmac_ripemd\x18\x14 \x01(\x0b\x32&.spotify.FingerprintHmacRipemdResponse\"1\n\x18\x46ingerprintGrainResponse\x12\x15\n\rencrypted_key\x18\n \x02(\x0c\"-\n\x1d\x46ingerprintHmacRipemdResponse\x12\x0c\n\x04hmac\x18\n \x02(\x0c\"o\n\x0fPeerTicketUnion\x12\x30\n\npublic_key\x18\n \x01(\x0b\x32\x1c.spotify.PeerTicketPublicKey\x12*\n\nold_ticket\x18\x14 \x01(\x0b\x32\x16.spotify.PeerTicketOld\")\n\x13PeerTicketPublicKey\x12\x12\n\npublic_key\x18\n \x02(\x0c\"C\n\rPeerTicketOld\x12\x13\n\x0bpeer_ticket\x18\n \x02(\x0c\x12\x1d\n\x15peer_ticket_signature\x18\x14 \x02(\x0c\"\x81\x02\n\nSystemInfo\x12&\n\ncpu_family\x18\n \x02(\x0e\x32\x12.spotify.CpuFamily\x12\x13\n\x0b\x63pu_subtype\x18\x14 \x01(\r\x12\x0f\n\x07\x63pu_ext\x18\x1e \x01(\r\x12\x1d\n\x05\x62rand\x18( \x01(\x0e\x32\x0e.spotify.Brand\x12\x13\n\x0b\x62rand_flags\x18\x32 \x01(\r\x12\x17\n\x02os\x18< \x02(\x0e\x32\x0b.spotify.Os\x12\x12\n\nos_version\x18\x46 \x01(\r\x12\x0e\n\x06os_ext\x18P \x01(\r\x12!\n\x19system_information_string\x18Z \x01(\t\x12\x11\n\tdevice_id\x18\x64 \x01(\t\"p\n\x10LibspotifyAppKey\x12\x0f\n\x07version\x18\x01 \x02(\r\x12\x0e\n\x06\x64\x65vkey\x18\x02 \x02(\x0c\x12\x11\n\tsignature\x18\x03 \x02(\x0c\x12\x11\n\tuseragent\x18\x04 \x02(\t\x12\x15\n\rcallback_hash\x18\x05 \x02(\x0c\"X\n\nClientInfo\x12\x0f\n\x07limited\x18\x01 \x01(\x08\x12\'\n\x02\x66\x62\x18\x02 \x01(\x0b\x32\x1b.spotify.ClientInfoFacebook\x12\x10\n\x08language\x18\x03 \x01(\t\"(\n\x12\x43lientInfoFacebook\x12\x12\n\nmachine_id\x18\x01 \x01(\t\"\xe9\x02\n\tAPWelcome\x12\x1a\n\x12\x63\x61nonical_username\x18\n \x02(\t\x12\x34\n\x16\x61\x63\x63ount_type_logged_in\x18\x14 \x02(\x0e\x32\x14.spotify.AccountType\x12\x38\n\x1a\x63redentials_type_logged_in\x18\x19 \x02(\x0e\x32\x14.spotify.AccountType\x12\x43\n\x1ereusable_auth_credentials_type\x18\x1e \x02(\x0e\x32\x1b.spotify.AuthenticationType\x12!\n\x19reusable_auth_credentials\x18( \x02(\x0c\x12\x12\n\nlfs_secret\x18\x32 \x01(\x0c\x12*\n\x0c\x61\x63\x63ount_info\x18< \x01(\x0b\x32\x14.spotify.AccountInfo\x12(\n\x02\x66\x62\x18\x46 \x01(\x0b\x32\x1c.spotify.AccountInfoFacebook\"k\n\x0b\x41\x63\x63ountInfo\x12,\n\x07spotify\x18\x01 \x01(\x0b\x32\x1b.spotify.AccountInfoSpotify\x12.\n\x08\x66\x61\x63\x65\x62ook\x18\x02 \x01(\x0b\x32\x1c.spotify.AccountInfoFacebook\"\x14\n\x12\x41\x63\x63ountInfoSpotify\"?\n\x13\x41\x63\x63ountInfoFacebook\x12\x14\n\x0c\x61\x63\x63\x65ss_token\x18\x01 \x01(\t\x12\x12\n\nmachine_id\x18\x02 \x01(\t*\xd6\x01\n\x12\x41uthenticationType\x12\x1c\n\x18\x41UTHENTICATION_USER_PASS\x10\x00\x12-\n)AUTHENTICATION_STORED_SPOTIFY_CREDENTIALS\x10\x01\x12.\n*AUTHENTICATION_STORED_FACEBOOK_CREDENTIALS\x10\x02\x12 \n\x1c\x41UTHENTICATION_SPOTIFY_TOKEN\x10\x03\x12!\n\x1d\x41UTHENTICATION_FACEBOOK_TOKEN\x10\x04*Y\n\x0f\x41\x63\x63ountCreation\x12\"\n\x1e\x41\x43\x43OUNT_CREATION_ALWAYS_PROMPT\x10\x01\x12\"\n\x1e\x41\x43\x43OUNT_CREATION_ALWAYS_CREATE\x10\x03*\x9d\x01\n\tCpuFamily\x12\x0f\n\x0b\x43PU_UNKNOWN\x10\x00\x12\x0b\n\x07\x43PU_X86\x10\x01\x12\x0e\n\nCPU_X86_64\x10\x02\x12\x0b\n\x07\x43PU_PPC\x10\x03\x12\x0e\n\nCPU_PPC_64\x10\x04\x12\x0b\n\x07\x43PU_ARM\x10\x05\x12\x0c\n\x08\x43PU_IA64\x10\x06\x12\n\n\x06\x43PU_SH\x10\x07\x12\x0c\n\x08\x43PU_MIPS\x10\x08\x12\x10\n\x0c\x43PU_BLACKFIN\x10\t*K\n\x05\x42rand\x12\x13\n\x0f\x42RAND_UNBRANDED\x10\x00\x12\r\n\tBRAND_INQ\x10\x01\x12\r\n\tBRAND_HTC\x10\x02\x12\x0f\n\x0b\x42RAND_NOKIA\x10\x03*\xd1\x02\n\x02Os\x12\x0e\n\nOS_UNKNOWN\x10\x00\x12\x0e\n\nOS_WINDOWS\x10\x01\x12\n\n\x06OS_OSX\x10\x02\x12\r\n\tOS_IPHONE\x10\x03\x12\n\n\x06OS_S60\x10\x04\x12\x0c\n\x08OS_LINUX\x10\x05\x12\x11\n\rOS_WINDOWS_CE\x10\x06\x12\x0e\n\nOS_ANDROID\x10\x07\x12\x0b\n\x07OS_PALM\x10\x08\x12\x0e\n\nOS_FREEBSD\x10\t\x12\x11\n\rOS_BLACKBERRY\x10\n\x12\x0c\n\x08OS_SONOS\x10\x0b\x12\x0f\n\x0bOS_LOGITECH\x10\x0c\x12\n\n\x06OS_WP7\x10\r\x12\x0c\n\x08OS_ONKYO\x10\x0e\x12\x0e\n\nOS_PHILIPS\x10\x0f\x12\t\n\x05OS_WD\x10\x10\x12\x0c\n\x08OS_VOLVO\x10\x11\x12\x0b\n\x07OS_TIVO\x10\x12\x12\x0b\n\x07OS_AWOX\x10\x13\x12\x0c\n\x08OS_MEEGO\x10\x14\x12\r\n\tOS_QNXNTO\x10\x15\x12\n\n\x06OS_BCO\x10\x16*(\n\x0b\x41\x63\x63ountType\x12\x0b\n\x07Spotify\x10\x00\x12\x0c\n\x08\x46\x61\x63\x65\x62ook\x10\x01\x42\r\n\x0b\x63om.spotify' +) + +_AUTHENTICATIONTYPE = _descriptor.EnumDescriptor( + name='AuthenticationType', + full_name='spotify.AuthenticationType', + filename=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + values=[ + _descriptor.EnumValueDescriptor( + name='AUTHENTICATION_USER_PASS', + index=0, + number=0, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='AUTHENTICATION_STORED_SPOTIFY_CREDENTIALS', + index=1, + number=1, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='AUTHENTICATION_STORED_FACEBOOK_CREDENTIALS', + index=2, + number=2, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='AUTHENTICATION_SPOTIFY_TOKEN', + index=3, + number=3, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='AUTHENTICATION_FACEBOOK_TOKEN', + index=4, + number=4, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + ], + containing_type=None, + serialized_options=None, + serialized_start=2083, + serialized_end=2297, +) +_sym_db.RegisterEnumDescriptor(_AUTHENTICATIONTYPE) + +AuthenticationType = enum_type_wrapper.EnumTypeWrapper(_AUTHENTICATIONTYPE) +_ACCOUNTCREATION = _descriptor.EnumDescriptor( + name='AccountCreation', + full_name='spotify.AccountCreation', + filename=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + values=[ + _descriptor.EnumValueDescriptor( + name='ACCOUNT_CREATION_ALWAYS_PROMPT', + index=0, + number=1, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='ACCOUNT_CREATION_ALWAYS_CREATE', + index=1, + number=3, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + ], + containing_type=None, + serialized_options=None, + serialized_start=2299, + serialized_end=2388, +) +_sym_db.RegisterEnumDescriptor(_ACCOUNTCREATION) + +AccountCreation = enum_type_wrapper.EnumTypeWrapper(_ACCOUNTCREATION) +_CPUFAMILY = _descriptor.EnumDescriptor( + name='CpuFamily', + full_name='spotify.CpuFamily', + filename=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + values=[ + _descriptor.EnumValueDescriptor( + name='CPU_UNKNOWN', + index=0, + number=0, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='CPU_X86', + index=1, + number=1, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='CPU_X86_64', + index=2, + number=2, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='CPU_PPC', + index=3, + number=3, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='CPU_PPC_64', + index=4, + number=4, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='CPU_ARM', + index=5, + number=5, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='CPU_IA64', + index=6, + number=6, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='CPU_SH', + index=7, + number=7, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='CPU_MIPS', + index=8, + number=8, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='CPU_BLACKFIN', + index=9, + number=9, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + ], + containing_type=None, + serialized_options=None, + serialized_start=2391, + serialized_end=2548, +) +_sym_db.RegisterEnumDescriptor(_CPUFAMILY) + +CpuFamily = enum_type_wrapper.EnumTypeWrapper(_CPUFAMILY) +_BRAND = _descriptor.EnumDescriptor( + name='Brand', + full_name='spotify.Brand', + filename=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + values=[ + _descriptor.EnumValueDescriptor( + name='BRAND_UNBRANDED', + index=0, + number=0, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='BRAND_INQ', + index=1, + number=1, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='BRAND_HTC', + index=2, + number=2, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='BRAND_NOKIA', + index=3, + number=3, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + ], + containing_type=None, + serialized_options=None, + serialized_start=2550, + serialized_end=2625, +) +_sym_db.RegisterEnumDescriptor(_BRAND) + +Brand = enum_type_wrapper.EnumTypeWrapper(_BRAND) +_OS = _descriptor.EnumDescriptor( + name='Os', + full_name='spotify.Os', + filename=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + values=[ + _descriptor.EnumValueDescriptor( + name='OS_UNKNOWN', + index=0, + number=0, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='OS_WINDOWS', + index=1, + number=1, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='OS_OSX', + index=2, + number=2, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='OS_IPHONE', + index=3, + number=3, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='OS_S60', + index=4, + number=4, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='OS_LINUX', + index=5, + number=5, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='OS_WINDOWS_CE', + index=6, + number=6, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='OS_ANDROID', + index=7, + number=7, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='OS_PALM', + index=8, + number=8, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='OS_FREEBSD', + index=9, + number=9, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='OS_BLACKBERRY', + index=10, + number=10, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='OS_SONOS', + index=11, + number=11, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='OS_LOGITECH', + index=12, + number=12, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='OS_WP7', + index=13, + number=13, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='OS_ONKYO', + index=14, + number=14, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='OS_PHILIPS', + index=15, + number=15, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='OS_WD', + index=16, + number=16, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='OS_VOLVO', + index=17, + number=17, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='OS_TIVO', + index=18, + number=18, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='OS_AWOX', + index=19, + number=19, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='OS_MEEGO', + index=20, + number=20, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='OS_QNXNTO', + index=21, + number=21, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='OS_BCO', + index=22, + number=22, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + ], + containing_type=None, + serialized_options=None, + serialized_start=2628, + serialized_end=2965, +) +_sym_db.RegisterEnumDescriptor(_OS) + +Os = enum_type_wrapper.EnumTypeWrapper(_OS) +_ACCOUNTTYPE = _descriptor.EnumDescriptor( + name='AccountType', + full_name='spotify.AccountType', + filename=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + values=[ + _descriptor.EnumValueDescriptor( + name='Spotify', + index=0, + number=0, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='Facebook', + index=1, + number=1, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + ], + containing_type=None, + serialized_options=None, + serialized_start=2967, + serialized_end=3007, +) +_sym_db.RegisterEnumDescriptor(_ACCOUNTTYPE) + +AccountType = enum_type_wrapper.EnumTypeWrapper(_ACCOUNTTYPE) +AUTHENTICATION_USER_PASS = 0 +AUTHENTICATION_STORED_SPOTIFY_CREDENTIALS = 1 +AUTHENTICATION_STORED_FACEBOOK_CREDENTIALS = 2 +AUTHENTICATION_SPOTIFY_TOKEN = 3 +AUTHENTICATION_FACEBOOK_TOKEN = 4 +ACCOUNT_CREATION_ALWAYS_PROMPT = 1 +ACCOUNT_CREATION_ALWAYS_CREATE = 3 +CPU_UNKNOWN = 0 +CPU_X86 = 1 +CPU_X86_64 = 2 +CPU_PPC = 3 +CPU_PPC_64 = 4 +CPU_ARM = 5 +CPU_IA64 = 6 +CPU_SH = 7 +CPU_MIPS = 8 +CPU_BLACKFIN = 9 +BRAND_UNBRANDED = 0 +BRAND_INQ = 1 +BRAND_HTC = 2 +BRAND_NOKIA = 3 +OS_UNKNOWN = 0 +OS_WINDOWS = 1 +OS_OSX = 2 +OS_IPHONE = 3 +OS_S60 = 4 +OS_LINUX = 5 +OS_WINDOWS_CE = 6 +OS_ANDROID = 7 +OS_PALM = 8 +OS_FREEBSD = 9 +OS_BLACKBERRY = 10 +OS_SONOS = 11 +OS_LOGITECH = 12 +OS_WP7 = 13 +OS_ONKYO = 14 +OS_PHILIPS = 15 +OS_WD = 16 +OS_VOLVO = 17 +OS_TIVO = 18 +OS_AWOX = 19 +OS_MEEGO = 20 +OS_QNXNTO = 21 +OS_BCO = 22 +Spotify = 0 +Facebook = 1 + +_CLIENTRESPONSEENCRYPTED = _descriptor.Descriptor( + name='ClientResponseEncrypted', + full_name='spotify.ClientResponseEncrypted', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='login_credentials', + full_name='spotify.ClientResponseEncrypted.login_credentials', + index=0, + number=10, + type=11, + cpp_type=10, + label=2, + has_default_value=False, + default_value=None, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='account_creation', + full_name='spotify.ClientResponseEncrypted.account_creation', + index=1, + number=20, + type=14, + cpp_type=8, + label=1, + has_default_value=False, + default_value=1, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='fingerprint_response', + full_name='spotify.ClientResponseEncrypted.fingerprint_response', + index=2, + number=30, + type=11, + cpp_type=10, + label=1, + has_default_value=False, + default_value=None, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='peer_ticket', + full_name='spotify.ClientResponseEncrypted.peer_ticket', + index=3, + number=40, + type=11, + cpp_type=10, + label=1, + has_default_value=False, + default_value=None, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='system_info', + full_name='spotify.ClientResponseEncrypted.system_info', + index=4, + number=50, + type=11, + cpp_type=10, + label=2, + has_default_value=False, + default_value=None, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='platform_model', + full_name='spotify.ClientResponseEncrypted.platform_model', + index=5, + number=60, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"".decode('utf-8'), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='version_string', + full_name='spotify.ClientResponseEncrypted.version_string', + index=6, + number=70, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"".decode('utf-8'), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='appkey', + full_name='spotify.ClientResponseEncrypted.appkey', + index=7, + number=80, + type=11, + cpp_type=10, + label=1, + has_default_value=False, + default_value=None, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='client_info', + full_name='spotify.ClientResponseEncrypted.client_info', + index=8, + number=90, + type=11, + cpp_type=10, + label=1, + has_default_value=False, + default_value=None, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[], + serialized_start=34, + serialized_end=452, +) + +_LOGINCREDENTIALS = _descriptor.Descriptor( + name='LoginCredentials', + full_name='spotify.LoginCredentials', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='username', + full_name='spotify.LoginCredentials.username', + index=0, + number=10, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"".decode('utf-8'), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='typ', + full_name='spotify.LoginCredentials.typ', + index=1, + number=20, + type=14, + cpp_type=8, + label=2, + has_default_value=False, + default_value=0, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='auth_data', + full_name='spotify.LoginCredentials.auth_data', + index=2, + number=30, + type=12, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"", + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[], + serialized_start=454, + serialized_end=551, +) + +_FINGERPRINTRESPONSEUNION = _descriptor.Descriptor( + name='FingerprintResponseUnion', + full_name='spotify.FingerprintResponseUnion', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='grain', + full_name='spotify.FingerprintResponseUnion.grain', + index=0, + number=10, + type=11, + cpp_type=10, + label=1, + has_default_value=False, + default_value=None, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='hmac_ripemd', + full_name='spotify.FingerprintResponseUnion.hmac_ripemd', + index=1, + number=20, + type=11, + cpp_type=10, + label=1, + has_default_value=False, + default_value=None, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[], + serialized_start=554, + serialized_end=691, +) + +_FINGERPRINTGRAINRESPONSE = _descriptor.Descriptor( + name='FingerprintGrainResponse', + full_name='spotify.FingerprintGrainResponse', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='encrypted_key', + full_name='spotify.FingerprintGrainResponse.encrypted_key', + index=0, + number=10, + type=12, + cpp_type=9, + label=2, + has_default_value=False, + default_value=b"", + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[], + serialized_start=693, + serialized_end=742, +) + +_FINGERPRINTHMACRIPEMDRESPONSE = _descriptor.Descriptor( + name='FingerprintHmacRipemdResponse', + full_name='spotify.FingerprintHmacRipemdResponse', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='hmac', + full_name='spotify.FingerprintHmacRipemdResponse.hmac', + index=0, + number=10, + type=12, + cpp_type=9, + label=2, + has_default_value=False, + default_value=b"", + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[], + serialized_start=744, + serialized_end=789, +) + +_PEERTICKETUNION = _descriptor.Descriptor( + name='PeerTicketUnion', + full_name='spotify.PeerTicketUnion', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='public_key', + full_name='spotify.PeerTicketUnion.public_key', + index=0, + number=10, + type=11, + cpp_type=10, + label=1, + has_default_value=False, + default_value=None, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='old_ticket', + full_name='spotify.PeerTicketUnion.old_ticket', + index=1, + number=20, + type=11, + cpp_type=10, + label=1, + has_default_value=False, + default_value=None, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[], + serialized_start=791, + serialized_end=902, +) + +_PEERTICKETPUBLICKEY = _descriptor.Descriptor( + name='PeerTicketPublicKey', + full_name='spotify.PeerTicketPublicKey', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='public_key', + full_name='spotify.PeerTicketPublicKey.public_key', + index=0, + number=10, + type=12, + cpp_type=9, + label=2, + has_default_value=False, + default_value=b"", + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[], + serialized_start=904, + serialized_end=945, +) + +_PEERTICKETOLD = _descriptor.Descriptor( + name='PeerTicketOld', + full_name='spotify.PeerTicketOld', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='peer_ticket', + full_name='spotify.PeerTicketOld.peer_ticket', + index=0, + number=10, + type=12, + cpp_type=9, + label=2, + has_default_value=False, + default_value=b"", + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='peer_ticket_signature', + full_name='spotify.PeerTicketOld.peer_ticket_signature', + index=1, + number=20, + type=12, + cpp_type=9, + label=2, + has_default_value=False, + default_value=b"", + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[], + serialized_start=947, + serialized_end=1014, +) + +_SYSTEMINFO = _descriptor.Descriptor( + name='SystemInfo', + full_name='spotify.SystemInfo', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='cpu_family', + full_name='spotify.SystemInfo.cpu_family', + index=0, + number=10, + type=14, + cpp_type=8, + label=2, + has_default_value=False, + default_value=0, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='cpu_subtype', + full_name='spotify.SystemInfo.cpu_subtype', + index=1, + number=20, + type=13, + cpp_type=3, + label=1, + has_default_value=False, + default_value=0, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='cpu_ext', + full_name='spotify.SystemInfo.cpu_ext', + index=2, + number=30, + type=13, + cpp_type=3, + label=1, + has_default_value=False, + default_value=0, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='brand', + full_name='spotify.SystemInfo.brand', + index=3, + number=40, + type=14, + cpp_type=8, + label=1, + has_default_value=False, + default_value=0, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='brand_flags', + full_name='spotify.SystemInfo.brand_flags', + index=4, + number=50, + type=13, + cpp_type=3, + label=1, + has_default_value=False, + default_value=0, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='os', + full_name='spotify.SystemInfo.os', + index=5, + number=60, + type=14, + cpp_type=8, + label=2, + has_default_value=False, + default_value=0, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='os_version', + full_name='spotify.SystemInfo.os_version', + index=6, + number=70, + type=13, + cpp_type=3, + label=1, + has_default_value=False, + default_value=0, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='os_ext', + full_name='spotify.SystemInfo.os_ext', + index=7, + number=80, + type=13, + cpp_type=3, + label=1, + has_default_value=False, + default_value=0, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='system_information_string', + full_name='spotify.SystemInfo.system_information_string', + index=8, + number=90, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"".decode('utf-8'), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='device_id', + full_name='spotify.SystemInfo.device_id', + index=9, + number=100, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"".decode('utf-8'), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[], + serialized_start=1017, + serialized_end=1274, +) + +_LIBSPOTIFYAPPKEY = _descriptor.Descriptor( + name='LibspotifyAppKey', + full_name='spotify.LibspotifyAppKey', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='version', + full_name='spotify.LibspotifyAppKey.version', + index=0, + number=1, + type=13, + cpp_type=3, + label=2, + has_default_value=False, + default_value=0, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='devkey', + full_name='spotify.LibspotifyAppKey.devkey', + index=1, + number=2, + type=12, + cpp_type=9, + label=2, + has_default_value=False, + default_value=b"", + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='signature', + full_name='spotify.LibspotifyAppKey.signature', + index=2, + number=3, + type=12, + cpp_type=9, + label=2, + has_default_value=False, + default_value=b"", + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='useragent', + full_name='spotify.LibspotifyAppKey.useragent', + index=3, + number=4, + type=9, + cpp_type=9, + label=2, + has_default_value=False, + default_value=b"".decode('utf-8'), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='callback_hash', + full_name='spotify.LibspotifyAppKey.callback_hash', + index=4, + number=5, + type=12, + cpp_type=9, + label=2, + has_default_value=False, + default_value=b"", + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[], + serialized_start=1276, + serialized_end=1388, +) + +_CLIENTINFO = _descriptor.Descriptor( + name='ClientInfo', + full_name='spotify.ClientInfo', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='limited', + full_name='spotify.ClientInfo.limited', + index=0, + number=1, + type=8, + cpp_type=7, + label=1, + has_default_value=False, + default_value=False, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='fb', + full_name='spotify.ClientInfo.fb', + index=1, + number=2, + type=11, + cpp_type=10, + label=1, + has_default_value=False, + default_value=None, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='language', + full_name='spotify.ClientInfo.language', + index=2, + number=3, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"".decode('utf-8'), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[], + serialized_start=1390, + serialized_end=1478, +) + +_CLIENTINFOFACEBOOK = _descriptor.Descriptor( + name='ClientInfoFacebook', + full_name='spotify.ClientInfoFacebook', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='machine_id', + full_name='spotify.ClientInfoFacebook.machine_id', + index=0, + number=1, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"".decode('utf-8'), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[], + serialized_start=1480, + serialized_end=1520, +) + +_APWELCOME = _descriptor.Descriptor( + name='APWelcome', + full_name='spotify.APWelcome', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='canonical_username', + full_name='spotify.APWelcome.canonical_username', + index=0, + number=10, + type=9, + cpp_type=9, + label=2, + has_default_value=False, + default_value=b"".decode('utf-8'), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='account_type_logged_in', + full_name='spotify.APWelcome.account_type_logged_in', + index=1, + number=20, + type=14, + cpp_type=8, + label=2, + has_default_value=False, + default_value=0, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='credentials_type_logged_in', + full_name='spotify.APWelcome.credentials_type_logged_in', + index=2, + number=25, + type=14, + cpp_type=8, + label=2, + has_default_value=False, + default_value=0, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='reusable_auth_credentials_type', + full_name='spotify.APWelcome.reusable_auth_credentials_type', + index=3, + number=30, + type=14, + cpp_type=8, + label=2, + has_default_value=False, + default_value=0, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='reusable_auth_credentials', + full_name='spotify.APWelcome.reusable_auth_credentials', + index=4, + number=40, + type=12, + cpp_type=9, + label=2, + has_default_value=False, + default_value=b"", + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='lfs_secret', + full_name='spotify.APWelcome.lfs_secret', + index=5, + number=50, + type=12, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"", + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='account_info', + full_name='spotify.APWelcome.account_info', + index=6, + number=60, + type=11, + cpp_type=10, + label=1, + has_default_value=False, + default_value=None, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='fb', + full_name='spotify.APWelcome.fb', + index=7, + number=70, + type=11, + cpp_type=10, + label=1, + has_default_value=False, + default_value=None, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[], + serialized_start=1523, + serialized_end=1884, +) + +_ACCOUNTINFO = _descriptor.Descriptor( + name='AccountInfo', + full_name='spotify.AccountInfo', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='spotify', + full_name='spotify.AccountInfo.spotify', + index=0, + number=1, + type=11, + cpp_type=10, + label=1, + has_default_value=False, + default_value=None, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='facebook', + full_name='spotify.AccountInfo.facebook', + index=1, + number=2, + type=11, + cpp_type=10, + label=1, + has_default_value=False, + default_value=None, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[], + serialized_start=1886, + serialized_end=1993, +) + +_ACCOUNTINFOSPOTIFY = _descriptor.Descriptor( + name='AccountInfoSpotify', + full_name='spotify.AccountInfoSpotify', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[], + serialized_start=1995, + serialized_end=2015, +) + +_ACCOUNTINFOFACEBOOK = _descriptor.Descriptor( + name='AccountInfoFacebook', + full_name='spotify.AccountInfoFacebook', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='access_token', + full_name='spotify.AccountInfoFacebook.access_token', + index=0, + number=1, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"".decode('utf-8'), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='machine_id', + full_name='spotify.AccountInfoFacebook.machine_id', + index=1, + number=2, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"".decode('utf-8'), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[], + serialized_start=2017, + serialized_end=2080, +) + +_CLIENTRESPONSEENCRYPTED.fields_by_name[ + 'login_credentials'].message_type = _LOGINCREDENTIALS +_CLIENTRESPONSEENCRYPTED.fields_by_name[ + 'account_creation'].enum_type = _ACCOUNTCREATION +_CLIENTRESPONSEENCRYPTED.fields_by_name[ + 'fingerprint_response'].message_type = _FINGERPRINTRESPONSEUNION +_CLIENTRESPONSEENCRYPTED.fields_by_name[ + 'peer_ticket'].message_type = _PEERTICKETUNION +_CLIENTRESPONSEENCRYPTED.fields_by_name[ + 'system_info'].message_type = _SYSTEMINFO +_CLIENTRESPONSEENCRYPTED.fields_by_name[ + 'appkey'].message_type = _LIBSPOTIFYAPPKEY +_CLIENTRESPONSEENCRYPTED.fields_by_name[ + 'client_info'].message_type = _CLIENTINFO +_LOGINCREDENTIALS.fields_by_name['typ'].enum_type = _AUTHENTICATIONTYPE +_FINGERPRINTRESPONSEUNION.fields_by_name[ + 'grain'].message_type = _FINGERPRINTGRAINRESPONSE +_FINGERPRINTRESPONSEUNION.fields_by_name[ + 'hmac_ripemd'].message_type = _FINGERPRINTHMACRIPEMDRESPONSE +_PEERTICKETUNION.fields_by_name[ + 'public_key'].message_type = _PEERTICKETPUBLICKEY +_PEERTICKETUNION.fields_by_name['old_ticket'].message_type = _PEERTICKETOLD +_SYSTEMINFO.fields_by_name['cpu_family'].enum_type = _CPUFAMILY +_SYSTEMINFO.fields_by_name['brand'].enum_type = _BRAND +_SYSTEMINFO.fields_by_name['os'].enum_type = _OS +_CLIENTINFO.fields_by_name['fb'].message_type = _CLIENTINFOFACEBOOK +_APWELCOME.fields_by_name['account_type_logged_in'].enum_type = _ACCOUNTTYPE +_APWELCOME.fields_by_name[ + 'credentials_type_logged_in'].enum_type = _ACCOUNTTYPE +_APWELCOME.fields_by_name[ + 'reusable_auth_credentials_type'].enum_type = _AUTHENTICATIONTYPE +_APWELCOME.fields_by_name['account_info'].message_type = _ACCOUNTINFO +_APWELCOME.fields_by_name['fb'].message_type = _ACCOUNTINFOFACEBOOK +_ACCOUNTINFO.fields_by_name['spotify'].message_type = _ACCOUNTINFOSPOTIFY +_ACCOUNTINFO.fields_by_name['facebook'].message_type = _ACCOUNTINFOFACEBOOK +DESCRIPTOR.message_types_by_name[ + 'ClientResponseEncrypted'] = _CLIENTRESPONSEENCRYPTED +DESCRIPTOR.message_types_by_name['LoginCredentials'] = _LOGINCREDENTIALS +DESCRIPTOR.message_types_by_name[ + 'FingerprintResponseUnion'] = _FINGERPRINTRESPONSEUNION +DESCRIPTOR.message_types_by_name[ + 'FingerprintGrainResponse'] = _FINGERPRINTGRAINRESPONSE +DESCRIPTOR.message_types_by_name[ + 'FingerprintHmacRipemdResponse'] = _FINGERPRINTHMACRIPEMDRESPONSE +DESCRIPTOR.message_types_by_name['PeerTicketUnion'] = _PEERTICKETUNION +DESCRIPTOR.message_types_by_name['PeerTicketPublicKey'] = _PEERTICKETPUBLICKEY +DESCRIPTOR.message_types_by_name['PeerTicketOld'] = _PEERTICKETOLD +DESCRIPTOR.message_types_by_name['SystemInfo'] = _SYSTEMINFO +DESCRIPTOR.message_types_by_name['LibspotifyAppKey'] = _LIBSPOTIFYAPPKEY +DESCRIPTOR.message_types_by_name['ClientInfo'] = _CLIENTINFO +DESCRIPTOR.message_types_by_name['ClientInfoFacebook'] = _CLIENTINFOFACEBOOK +DESCRIPTOR.message_types_by_name['APWelcome'] = _APWELCOME +DESCRIPTOR.message_types_by_name['AccountInfo'] = _ACCOUNTINFO +DESCRIPTOR.message_types_by_name['AccountInfoSpotify'] = _ACCOUNTINFOSPOTIFY +DESCRIPTOR.message_types_by_name['AccountInfoFacebook'] = _ACCOUNTINFOFACEBOOK +DESCRIPTOR.enum_types_by_name['AuthenticationType'] = _AUTHENTICATIONTYPE +DESCRIPTOR.enum_types_by_name['AccountCreation'] = _ACCOUNTCREATION +DESCRIPTOR.enum_types_by_name['CpuFamily'] = _CPUFAMILY +DESCRIPTOR.enum_types_by_name['Brand'] = _BRAND +DESCRIPTOR.enum_types_by_name['Os'] = _OS +DESCRIPTOR.enum_types_by_name['AccountType'] = _ACCOUNTTYPE +_sym_db.RegisterFileDescriptor(DESCRIPTOR) + +ClientResponseEncrypted = _reflection.GeneratedProtocolMessageType( + 'ClientResponseEncrypted', + (_message.Message, ), + { + 'DESCRIPTOR': _CLIENTRESPONSEENCRYPTED, + '__module__': 'authentication_pb2' + # @@protoc_insertion_point(class_scope:spotify.ClientResponseEncrypted) + }) +_sym_db.RegisterMessage(ClientResponseEncrypted) + +LoginCredentials = _reflection.GeneratedProtocolMessageType( + 'LoginCredentials', + (_message.Message, ), + { + 'DESCRIPTOR': _LOGINCREDENTIALS, + '__module__': 'authentication_pb2' + # @@protoc_insertion_point(class_scope:spotify.LoginCredentials) + }) +_sym_db.RegisterMessage(LoginCredentials) + +FingerprintResponseUnion = _reflection.GeneratedProtocolMessageType( + 'FingerprintResponseUnion', + (_message.Message, ), + { + 'DESCRIPTOR': _FINGERPRINTRESPONSEUNION, + '__module__': 'authentication_pb2' + # @@protoc_insertion_point(class_scope:spotify.FingerprintResponseUnion) + }) +_sym_db.RegisterMessage(FingerprintResponseUnion) + +FingerprintGrainResponse = _reflection.GeneratedProtocolMessageType( + 'FingerprintGrainResponse', + (_message.Message, ), + { + 'DESCRIPTOR': _FINGERPRINTGRAINRESPONSE, + '__module__': 'authentication_pb2' + # @@protoc_insertion_point(class_scope:spotify.FingerprintGrainResponse) + }) +_sym_db.RegisterMessage(FingerprintGrainResponse) + +FingerprintHmacRipemdResponse = _reflection.GeneratedProtocolMessageType( + 'FingerprintHmacRipemdResponse', + (_message.Message, ), + { + 'DESCRIPTOR': _FINGERPRINTHMACRIPEMDRESPONSE, + '__module__': 'authentication_pb2' + # @@protoc_insertion_point(class_scope:spotify.FingerprintHmacRipemdResponse) + }) +_sym_db.RegisterMessage(FingerprintHmacRipemdResponse) + +PeerTicketUnion = _reflection.GeneratedProtocolMessageType( + 'PeerTicketUnion', + (_message.Message, ), + { + 'DESCRIPTOR': _PEERTICKETUNION, + '__module__': 'authentication_pb2' + # @@protoc_insertion_point(class_scope:spotify.PeerTicketUnion) + }) +_sym_db.RegisterMessage(PeerTicketUnion) + +PeerTicketPublicKey = _reflection.GeneratedProtocolMessageType( + 'PeerTicketPublicKey', + (_message.Message, ), + { + 'DESCRIPTOR': _PEERTICKETPUBLICKEY, + '__module__': 'authentication_pb2' + # @@protoc_insertion_point(class_scope:spotify.PeerTicketPublicKey) + }) +_sym_db.RegisterMessage(PeerTicketPublicKey) + +PeerTicketOld = _reflection.GeneratedProtocolMessageType( + 'PeerTicketOld', + (_message.Message, ), + { + 'DESCRIPTOR': _PEERTICKETOLD, + '__module__': 'authentication_pb2' + # @@protoc_insertion_point(class_scope:spotify.PeerTicketOld) + }) +_sym_db.RegisterMessage(PeerTicketOld) + +SystemInfo = _reflection.GeneratedProtocolMessageType( + 'SystemInfo', + (_message.Message, ), + { + 'DESCRIPTOR': _SYSTEMINFO, + '__module__': 'authentication_pb2' + # @@protoc_insertion_point(class_scope:spotify.SystemInfo) + }) +_sym_db.RegisterMessage(SystemInfo) + +LibspotifyAppKey = _reflection.GeneratedProtocolMessageType( + 'LibspotifyAppKey', + (_message.Message, ), + { + 'DESCRIPTOR': _LIBSPOTIFYAPPKEY, + '__module__': 'authentication_pb2' + # @@protoc_insertion_point(class_scope:spotify.LibspotifyAppKey) + }) +_sym_db.RegisterMessage(LibspotifyAppKey) + +ClientInfo = _reflection.GeneratedProtocolMessageType( + 'ClientInfo', + (_message.Message, ), + { + 'DESCRIPTOR': _CLIENTINFO, + '__module__': 'authentication_pb2' + # @@protoc_insertion_point(class_scope:spotify.ClientInfo) + }) +_sym_db.RegisterMessage(ClientInfo) + +ClientInfoFacebook = _reflection.GeneratedProtocolMessageType( + 'ClientInfoFacebook', + (_message.Message, ), + { + 'DESCRIPTOR': _CLIENTINFOFACEBOOK, + '__module__': 'authentication_pb2' + # @@protoc_insertion_point(class_scope:spotify.ClientInfoFacebook) + }) +_sym_db.RegisterMessage(ClientInfoFacebook) + +APWelcome = _reflection.GeneratedProtocolMessageType( + 'APWelcome', + (_message.Message, ), + { + 'DESCRIPTOR': _APWELCOME, + '__module__': 'authentication_pb2' + # @@protoc_insertion_point(class_scope:spotify.APWelcome) + }) +_sym_db.RegisterMessage(APWelcome) + +AccountInfo = _reflection.GeneratedProtocolMessageType( + 'AccountInfo', + (_message.Message, ), + { + 'DESCRIPTOR': _ACCOUNTINFO, + '__module__': 'authentication_pb2' + # @@protoc_insertion_point(class_scope:spotify.AccountInfo) + }) +_sym_db.RegisterMessage(AccountInfo) + +AccountInfoSpotify = _reflection.GeneratedProtocolMessageType( + 'AccountInfoSpotify', + (_message.Message, ), + { + 'DESCRIPTOR': _ACCOUNTINFOSPOTIFY, + '__module__': 'authentication_pb2' + # @@protoc_insertion_point(class_scope:spotify.AccountInfoSpotify) + }) +_sym_db.RegisterMessage(AccountInfoSpotify) + +AccountInfoFacebook = _reflection.GeneratedProtocolMessageType( + 'AccountInfoFacebook', + (_message.Message, ), + { + 'DESCRIPTOR': _ACCOUNTINFOFACEBOOK, + '__module__': 'authentication_pb2' + # @@protoc_insertion_point(class_scope:spotify.AccountInfoFacebook) + }) +_sym_db.RegisterMessage(AccountInfoFacebook) + +DESCRIPTOR._options = None +# @@protoc_insertion_point(module_scope) diff --git a/librespot/proto/CanvazMeta_pb2.py b/librespot/proto/CanvazMeta_pb2.py new file mode 100644 index 0000000..3b769fc --- /dev/null +++ b/librespot/proto/CanvazMeta_pb2.py @@ -0,0 +1,91 @@ +# -*- coding: utf-8 -*- +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: canvaz-meta.proto +"""Generated protocol buffer code.""" +from google.protobuf import descriptor as _descriptor +from google.protobuf import message as _message +from google.protobuf import reflection as _reflection +from google.protobuf import symbol_database as _symbol_database +from google.protobuf.internal import enum_type_wrapper + +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + +DESCRIPTOR = _descriptor.FileDescriptor( + name="canvaz-meta.proto", + package="com.spotify.canvaz", + syntax="proto3", + serialized_options=b"\n\022com.spotify.canvazH\002", + 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", +) + +_TYPE = _descriptor.EnumDescriptor( + name="Type", + full_name="com.spotify.canvaz.Type", + filename=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + values=[ + _descriptor.EnumValueDescriptor( + name="IMAGE", + index=0, + number=0, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key, + ), + _descriptor.EnumValueDescriptor( + name="VIDEO", + index=1, + number=1, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key, + ), + _descriptor.EnumValueDescriptor( + name="VIDEO_LOOPING", + index=2, + number=2, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key, + ), + _descriptor.EnumValueDescriptor( + name="VIDEO_LOOPING_RANDOM", + index=3, + number=3, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key, + ), + _descriptor.EnumValueDescriptor( + name="GIF", + index=4, + number=4, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key, + ), + ], + containing_type=None, + serialized_options=None, + serialized_start=41, + serialized_end=123, +) +_sym_db.RegisterEnumDescriptor(_TYPE) + +Type = enum_type_wrapper.EnumTypeWrapper(_TYPE) +IMAGE = 0 +VIDEO = 1 +VIDEO_LOOPING = 2 +VIDEO_LOOPING_RANDOM = 3 +GIF = 4 + +DESCRIPTOR.enum_types_by_name["Type"] = _TYPE +_sym_db.RegisterFileDescriptor(DESCRIPTOR) + +DESCRIPTOR._options = None +# @@protoc_insertion_point(module_scope) diff --git a/librespot/proto/Canvaz_pb2.py b/librespot/proto/Canvaz_pb2.py new file mode 100644 index 0000000..07f31b4 --- /dev/null +++ b/librespot/proto/Canvaz_pb2.py @@ -0,0 +1,564 @@ +# -*- coding: utf-8 -*- +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: canvaz.proto +"""Generated protocol buffer code.""" +import CanvazMeta_pb2 as canvaz__meta__pb2 +from google.protobuf import descriptor as _descriptor +from google.protobuf import message as _message +from google.protobuf import reflection as _reflection +from google.protobuf import symbol_database as _symbol_database + +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + +DESCRIPTOR = _descriptor.FileDescriptor( + name="canvaz.proto", + package="com.spotify.canvazcache", + syntax="proto3", + serialized_options=b"\n\022com.spotify.canvazH\002", + 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', + dependencies=[ + canvaz__meta__pb2.DESCRIPTOR, + ], +) + +_ARTIST = _descriptor.Descriptor( + name="Artist", + full_name="com.spotify.canvazcache.Artist", + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name="uri", + full_name="com.spotify.canvazcache.Artist.uri", + index=0, + number=1, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"".decode("utf-8"), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="name", + full_name="com.spotify.canvazcache.Artist.name", + index=1, + number=2, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"".decode("utf-8"), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="avatar", + full_name="com.spotify.canvazcache.Artist.avatar", + index=2, + number=3, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"".decode("utf-8"), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax="proto3", + extension_ranges=[], + oneofs=[], + serialized_start=60, + serialized_end=111, +) + +_ENTITYCANVAZRESPONSE_CANVAZ = _descriptor.Descriptor( + name="Canvaz", + full_name="com.spotify.canvazcache.EntityCanvazResponse.Canvaz", + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name="id", + full_name="com.spotify.canvazcache.EntityCanvazResponse.Canvaz.id", + index=0, + number=1, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"".decode("utf-8"), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="url", + full_name="com.spotify.canvazcache.EntityCanvazResponse.Canvaz.url", + index=1, + number=2, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"".decode("utf-8"), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="file_id", + full_name= + "com.spotify.canvazcache.EntityCanvazResponse.Canvaz.file_id", + index=2, + number=3, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"".decode("utf-8"), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="type", + full_name= + "com.spotify.canvazcache.EntityCanvazResponse.Canvaz.type", + index=3, + number=4, + type=14, + cpp_type=8, + label=1, + has_default_value=False, + default_value=0, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="entity_uri", + full_name= + "com.spotify.canvazcache.EntityCanvazResponse.Canvaz.entity_uri", + index=4, + number=5, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"".decode("utf-8"), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="artist", + full_name= + "com.spotify.canvazcache.EntityCanvazResponse.Canvaz.artist", + index=5, + number=6, + type=11, + cpp_type=10, + label=1, + has_default_value=False, + default_value=None, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="explicit", + full_name= + "com.spotify.canvazcache.EntityCanvazResponse.Canvaz.explicit", + index=6, + number=7, + type=8, + cpp_type=7, + label=1, + has_default_value=False, + default_value=False, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="uploaded_by", + full_name= + "com.spotify.canvazcache.EntityCanvazResponse.Canvaz.uploaded_by", + index=7, + number=8, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"".decode("utf-8"), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="etag", + full_name= + "com.spotify.canvazcache.EntityCanvazResponse.Canvaz.etag", + index=8, + number=9, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"".decode("utf-8"), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="canvas_uri", + full_name= + "com.spotify.canvazcache.EntityCanvazResponse.Canvaz.canvas_uri", + index=9, + number=11, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"".decode("utf-8"), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax="proto3", + extension_ranges=[], + oneofs=[], + serialized_start=235, + serialized_end=467, +) + +_ENTITYCANVAZRESPONSE = _descriptor.Descriptor( + name="EntityCanvazResponse", + full_name="com.spotify.canvazcache.EntityCanvazResponse", + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name="canvases", + full_name="com.spotify.canvazcache.EntityCanvazResponse.canvases", + index=0, + number=1, + type=11, + cpp_type=10, + label=3, + has_default_value=False, + default_value=[], + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="ttl_in_seconds", + full_name= + "com.spotify.canvazcache.EntityCanvazResponse.ttl_in_seconds", + index=1, + number=2, + type=3, + cpp_type=2, + label=1, + has_default_value=False, + default_value=0, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + ], + extensions=[], + nested_types=[ + _ENTITYCANVAZRESPONSE_CANVAZ, + ], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax="proto3", + extension_ranges=[], + oneofs=[], + serialized_start=114, + serialized_end=467, +) + +_ENTITYCANVAZREQUEST_ENTITY = _descriptor.Descriptor( + name="Entity", + full_name="com.spotify.canvazcache.EntityCanvazRequest.Entity", + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name="entity_uri", + full_name= + "com.spotify.canvazcache.EntityCanvazRequest.Entity.entity_uri", + index=0, + number=1, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"".decode("utf-8"), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="etag", + full_name="com.spotify.canvazcache.EntityCanvazRequest.Entity.etag", + index=1, + number=2, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"".decode("utf-8"), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax="proto3", + extension_ranges=[], + oneofs=[], + serialized_start=564, + serialized_end=606, +) + +_ENTITYCANVAZREQUEST = _descriptor.Descriptor( + name="EntityCanvazRequest", + full_name="com.spotify.canvazcache.EntityCanvazRequest", + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name="entities", + full_name="com.spotify.canvazcache.EntityCanvazRequest.entities", + index=0, + number=1, + type=11, + cpp_type=10, + label=3, + has_default_value=False, + default_value=[], + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + ], + extensions=[], + nested_types=[ + _ENTITYCANVAZREQUEST_ENTITY, + ], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax="proto3", + extension_ranges=[], + oneofs=[], + serialized_start=470, + serialized_end=606, +) + +_ENTITYCANVAZRESPONSE_CANVAZ.fields_by_name[ + "type"].enum_type = canvaz__meta__pb2._TYPE +_ENTITYCANVAZRESPONSE_CANVAZ.fields_by_name["artist"].message_type = _ARTIST +_ENTITYCANVAZRESPONSE_CANVAZ.containing_type = _ENTITYCANVAZRESPONSE +_ENTITYCANVAZRESPONSE.fields_by_name[ + "canvases"].message_type = _ENTITYCANVAZRESPONSE_CANVAZ +_ENTITYCANVAZREQUEST_ENTITY.containing_type = _ENTITYCANVAZREQUEST +_ENTITYCANVAZREQUEST.fields_by_name[ + "entities"].message_type = _ENTITYCANVAZREQUEST_ENTITY +DESCRIPTOR.message_types_by_name["Artist"] = _ARTIST +DESCRIPTOR.message_types_by_name[ + "EntityCanvazResponse"] = _ENTITYCANVAZRESPONSE +DESCRIPTOR.message_types_by_name["EntityCanvazRequest"] = _ENTITYCANVAZREQUEST +_sym_db.RegisterFileDescriptor(DESCRIPTOR) + +Artist = _reflection.GeneratedProtocolMessageType( + "Artist", + (_message.Message, ), + { + "DESCRIPTOR": _ARTIST, + "__module__": "canvaz_pb2" + # @@protoc_insertion_point(class_scope:com.spotify.canvazcache.Artist) + }, +) +_sym_db.RegisterMessage(Artist) + +EntityCanvazResponse = _reflection.GeneratedProtocolMessageType( + "EntityCanvazResponse", + (_message.Message, ), + { + "Canvaz": + _reflection.GeneratedProtocolMessageType( + "Canvaz", + (_message.Message, ), + { + "DESCRIPTOR": _ENTITYCANVAZRESPONSE_CANVAZ, + "__module__": "canvaz_pb2" + # @@protoc_insertion_point(class_scope:com.spotify.canvazcache.EntityCanvazResponse.Canvaz) + }, + ), + "DESCRIPTOR": + _ENTITYCANVAZRESPONSE, + "__module__": + "canvaz_pb2" + # @@protoc_insertion_point(class_scope:com.spotify.canvazcache.EntityCanvazResponse) + }, +) +_sym_db.RegisterMessage(EntityCanvazResponse) +_sym_db.RegisterMessage(EntityCanvazResponse.Canvaz) + +EntityCanvazRequest = _reflection.GeneratedProtocolMessageType( + "EntityCanvazRequest", + (_message.Message, ), + { + "Entity": + _reflection.GeneratedProtocolMessageType( + "Entity", + (_message.Message, ), + { + "DESCRIPTOR": _ENTITYCANVAZREQUEST_ENTITY, + "__module__": "canvaz_pb2" + # @@protoc_insertion_point(class_scope:com.spotify.canvazcache.EntityCanvazRequest.Entity) + }, + ), + "DESCRIPTOR": + _ENTITYCANVAZREQUEST, + "__module__": + "canvaz_pb2" + # @@protoc_insertion_point(class_scope:com.spotify.canvazcache.EntityCanvazRequest) + }, +) +_sym_db.RegisterMessage(EntityCanvazRequest) +_sym_db.RegisterMessage(EntityCanvazRequest.Entity) + +DESCRIPTOR._options = None +# @@protoc_insertion_point(module_scope) diff --git a/librespot/proto/ClientToken_pb2.py b/librespot/proto/ClientToken_pb2.py new file mode 100644 index 0000000..2b7e954 --- /dev/null +++ b/librespot/proto/ClientToken_pb2.py @@ -0,0 +1,63 @@ +# -*- coding: utf-8 -*- +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: client_token.proto +"""Generated protocol buffer code.""" +from google.protobuf.internal import builder as _builder +from google.protobuf import descriptor as _descriptor +from google.protobuf import descriptor_pool as _descriptor_pool +from google.protobuf import symbol_database as _symbol_database +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + +from librespot.proto import Connectivity_pb2 as connectivity__pb2 + + +DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x12\x63lient_token.proto\x12\x1bspotify.clienttoken.http.v0\x1a\x12\x63onnectivity.proto\"\x84\x02\n\x12\x43lientTokenRequest\x12I\n\x0crequest_type\x18\x01 \x01(\x0e\x32\x33.spotify.clienttoken.http.v0.ClientTokenRequestType\x12\x45\n\x0b\x63lient_data\x18\x02 \x01(\x0b\x32..spotify.clienttoken.http.v0.ClientDataRequestH\x00\x12Q\n\x11\x63hallenge_answers\x18\x03 \x01(\x0b\x32\x34.spotify.clienttoken.http.v0.ChallengeAnswersRequestH\x00\x42\t\n\x07request\"\x99\x01\n\x11\x43lientDataRequest\x12\x16\n\x0e\x63lient_version\x18\x01 \x01(\t\x12\x11\n\tclient_id\x18\x02 \x01(\t\x12Q\n\x15\x63onnectivity_sdk_data\x18\x03 \x01(\x0b\x32\x30.spotify.clienttoken.data.v0.ConnectivitySdkDataH\x00\x42\x06\n\x04\x64\x61ta\"g\n\x17\x43hallengeAnswersRequest\x12\r\n\x05state\x18\x01 \x01(\t\x12=\n\x07\x61nswers\x18\x02 \x03(\x0b\x32,.spotify.clienttoken.http.v0.ChallengeAnswer\"\x81\x02\n\x13\x43lientTokenResponse\x12K\n\rresponse_type\x18\x01 \x01(\x0e\x32\x34.spotify.clienttoken.http.v0.ClientTokenResponseType\x12J\n\rgranted_token\x18\x02 \x01(\x0b\x32\x31.spotify.clienttoken.http.v0.GrantedTokenResponseH\x00\x12\x45\n\nchallenges\x18\x03 \x01(\x0b\x32/.spotify.clienttoken.http.v0.ChallengesResponseH\x00\x42\n\n\x08response\"\x1d\n\x0bTokenDomain\x12\x0e\n\x06\x64omain\x18\x01 \x01(\t\"\x9e\x01\n\x14GrantedTokenResponse\x12\r\n\x05token\x18\x01 \x01(\t\x12\x1d\n\x15\x65xpires_after_seconds\x18\x02 \x01(\x05\x12\x1d\n\x15refresh_after_seconds\x18\x03 \x01(\x05\x12\x39\n\x07\x64omains\x18\x04 \x03(\x0b\x32(.spotify.clienttoken.http.v0.TokenDomain\"_\n\x12\x43hallengesResponse\x12\r\n\x05state\x18\x01 \x01(\t\x12:\n\nchallenges\x18\x02 \x03(\x0b\x32&.spotify.clienttoken.http.v0.Challenge\"&\n\x16\x43lientSecretParameters\x12\x0c\n\x04salt\x18\x01 \x01(\t\"7\n\x14\x45valuateJSParameters\x12\x0c\n\x04\x63ode\x18\x01 \x01(\t\x12\x11\n\tlibraries\x18\x02 \x03(\t\"4\n\x12HashCashParameters\x12\x0e\n\x06length\x18\x01 \x01(\x05\x12\x0e\n\x06prefix\x18\x02 \x01(\t\"\xda\x02\n\tChallenge\x12\x38\n\x04type\x18\x01 \x01(\x0e\x32*.spotify.clienttoken.http.v0.ChallengeType\x12W\n\x18\x63lient_secret_parameters\x18\x02 \x01(\x0b\x32\x33.spotify.clienttoken.http.v0.ClientSecretParametersH\x00\x12S\n\x16\x65valuate_js_parameters\x18\x03 \x01(\x0b\x32\x31.spotify.clienttoken.http.v0.EvaluateJSParametersH\x00\x12W\n\x1c\x65valuate_hashcash_parameters\x18\x04 \x01(\x0b\x32/.spotify.clienttoken.http.v0.HashCashParametersH\x00\x42\x0c\n\nparameters\"&\n\x16\x43lientSecretHMACAnswer\x12\x0c\n\x04hmac\x18\x01 \x01(\t\"\"\n\x10\x45valuateJSAnswer\x12\x0e\n\x06result\x18\x01 \x01(\t\" \n\x0eHashCashAnswer\x12\x0e\n\x06suffix\x18\x01 \x01(\t\"\xb4\x02\n\x0f\x43hallengeAnswer\x12\x41\n\rChallengeType\x18\x01 \x01(\x0e\x32*.spotify.clienttoken.http.v0.ChallengeType\x12L\n\rclient_secret\x18\x02 \x01(\x0b\x32\x33.spotify.clienttoken.http.v0.ClientSecretHMACAnswerH\x00\x12\x44\n\x0b\x65valuate_js\x18\x03 \x01(\x0b\x32-.spotify.clienttoken.http.v0.EvaluateJSAnswerH\x00\x12@\n\thash_cash\x18\x04 \x01(\x0b\x32+.spotify.clienttoken.http.v0.HashCashAnswerH\x00\x42\x08\n\x06\x61nswer\"(\n\x15\x43lientTokenBadRequest\x12\x0f\n\x07message\x18\x01 \x01(\t*u\n\x16\x43lientTokenRequestType\x12\x13\n\x0fREQUEST_UNKNOWN\x10\x00\x12\x1f\n\x1bREQUEST_CLIENT_DATA_REQUEST\x10\x01\x12%\n!REQUEST_CHALLENGE_ANSWERS_REQUEST\x10\x02*v\n\x17\x43lientTokenResponseType\x12\x14\n\x10RESPONSE_UNKNOWN\x10\x00\x12#\n\x1fRESPONSE_GRANTED_TOKEN_RESPONSE\x10\x01\x12 \n\x1cRESPONSE_CHALLENGES_RESPONSE\x10\x02*|\n\rChallengeType\x12\x15\n\x11\x43HALLENGE_UNKNOWN\x10\x00\x12 \n\x1c\x43HALLENGE_CLIENT_SECRET_HMAC\x10\x01\x12\x19\n\x15\x43HALLENGE_EVALUATE_JS\x10\x02\x12\x17\n\x13\x43HALLENGE_HASH_CASH\x10\x03\x42#\n\x1f\x63om.spotify.clienttoken.http.v0H\x02\x62\x06proto3') + +_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, globals()) +_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'client_token_pb2', globals()) +if _descriptor._USE_C_DESCRIPTORS == False: + + DESCRIPTOR._options = None + DESCRIPTOR._serialized_options = b'\n\037com.spotify.clienttoken.http.v0H\002' + _CLIENTTOKENREQUESTTYPE._serialized_start=2107 + _CLIENTTOKENREQUESTTYPE._serialized_end=2224 + _CLIENTTOKENRESPONSETYPE._serialized_start=2226 + _CLIENTTOKENRESPONSETYPE._serialized_end=2344 + _CHALLENGETYPE._serialized_start=2346 + _CHALLENGETYPE._serialized_end=2470 + _CLIENTTOKENREQUEST._serialized_start=72 + _CLIENTTOKENREQUEST._serialized_end=332 + _CLIENTDATAREQUEST._serialized_start=335 + _CLIENTDATAREQUEST._serialized_end=488 + _CHALLENGEANSWERSREQUEST._serialized_start=490 + _CHALLENGEANSWERSREQUEST._serialized_end=593 + _CLIENTTOKENRESPONSE._serialized_start=596 + _CLIENTTOKENRESPONSE._serialized_end=853 + _TOKENDOMAIN._serialized_start=855 + _TOKENDOMAIN._serialized_end=884 + _GRANTEDTOKENRESPONSE._serialized_start=887 + _GRANTEDTOKENRESPONSE._serialized_end=1045 + _CHALLENGESRESPONSE._serialized_start=1047 + _CHALLENGESRESPONSE._serialized_end=1142 + _CLIENTSECRETPARAMETERS._serialized_start=1144 + _CLIENTSECRETPARAMETERS._serialized_end=1182 + _EVALUATEJSPARAMETERS._serialized_start=1184 + _EVALUATEJSPARAMETERS._serialized_end=1239 + _HASHCASHPARAMETERS._serialized_start=1241 + _HASHCASHPARAMETERS._serialized_end=1293 + _CHALLENGE._serialized_start=1296 + _CHALLENGE._serialized_end=1642 + _CLIENTSECRETHMACANSWER._serialized_start=1644 + _CLIENTSECRETHMACANSWER._serialized_end=1682 + _EVALUATEJSANSWER._serialized_start=1684 + _EVALUATEJSANSWER._serialized_end=1718 + _HASHCASHANSWER._serialized_start=1720 + _HASHCASHANSWER._serialized_end=1752 + _CHALLENGEANSWER._serialized_start=1755 + _CHALLENGEANSWER._serialized_end=2063 + _CLIENTTOKENBADREQUEST._serialized_start=2065 + _CLIENTTOKENBADREQUEST._serialized_end=2105 +# @@protoc_insertion_point(module_scope) diff --git a/librespot/proto/Connect_pb2.py b/librespot/proto/Connect_pb2.py new file mode 100644 index 0000000..f356a1c --- /dev/null +++ b/librespot/proto/Connect_pb2.py @@ -0,0 +1,2340 @@ +# -*- coding: utf-8 -*- +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: connect.proto +"""Generated protocol buffer code.""" +from google.protobuf.internal import enum_type_wrapper +from google.protobuf import descriptor as _descriptor +from google.protobuf import message as _message +from google.protobuf import reflection as _reflection +from google.protobuf import symbol_database as _symbol_database +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + +import librespot.proto.Player_pb2 as player__pb2 + +DESCRIPTOR = _descriptor.FileDescriptor( + name='connect.proto', + package='connectstate', + syntax='proto3', + serialized_options=b'\n\030com.spotify.connectstateH\002', + create_key=_descriptor._internal_create_key, + serialized_pb= + b'\n\rconnect.proto\x12\x0c\x63onnectstate\x1a\x0cplayer.proto\"\x9f\x01\n\rClusterUpdate\x12&\n\x07\x63luster\x18\x01 \x01(\x0b\x32\x15.connectstate.Cluster\x12\x38\n\rupdate_reason\x18\x02 \x01(\x0e\x32!.connectstate.ClusterUpdateReason\x12\x0e\n\x06\x61\x63k_id\x18\x03 \x01(\t\x12\x1c\n\x14\x64\x65vices_that_changed\x18\x04 \x03(\t\"\xa6\x01\n\x06\x44\x65vice\x12-\n\x0b\x64\x65vice_info\x18\x01 \x01(\x0b\x32\x18.connectstate.DeviceInfo\x12/\n\x0cplayer_state\x18\x02 \x01(\x0b\x32\x19.connectstate.PlayerState\x12<\n\x13private_device_info\x18\x03 \x01(\x0b\x32\x1f.connectstate.PrivateDeviceInfo\"\xfa\x01\n\x07\x43luster\x12\x11\n\ttimestamp\x18\x01 \x01(\x03\x12\x18\n\x10\x61\x63tive_device_id\x18\x02 \x01(\t\x12/\n\x0cplayer_state\x18\x03 \x01(\x0b\x32\x19.connectstate.PlayerState\x12\x31\n\x06\x64\x65vice\x18\x04 \x03(\x0b\x32!.connectstate.Cluster.DeviceEntry\x12\x15\n\rtransfer_data\x18\x05 \x01(\x0c\x1aG\n\x0b\x44\x65viceEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\'\n\x05value\x18\x02 \x01(\x0b\x32\x18.connectstate.DeviceInfo:\x02\x38\x01\"\xa1\x03\n\x0fPutStateRequest\x12\x14\n\x0c\x63\x61llback_url\x18\x01 \x01(\t\x12$\n\x06\x64\x65vice\x18\x02 \x01(\x0b\x32\x14.connectstate.Device\x12-\n\x0bmember_type\x18\x03 \x01(\x0e\x32\x18.connectstate.MemberType\x12\x11\n\tis_active\x18\x04 \x01(\x08\x12\x36\n\x10put_state_reason\x18\x05 \x01(\x0e\x32\x1c.connectstate.PutStateReason\x12\x12\n\nmessage_id\x18\x06 \x01(\r\x12&\n\x1elast_command_sent_by_device_id\x18\x07 \x01(\t\x12\x1f\n\x17last_command_message_id\x18\x08 \x01(\r\x12\x1a\n\x12started_playing_at\x18\t \x01(\x04\x12\x1f\n\x17has_been_playing_for_ms\x18\x0b \x01(\x04\x12\x1d\n\x15\x63lient_side_timestamp\x18\x0c \x01(\x04\x12\x1f\n\x17only_write_player_state\x18\r \x01(\x08\"%\n\x11PrivateDeviceInfo\x12\x10\n\x08platform\x18\x01 \x01(\t\"(\n\x10SubscribeRequest\x12\x14\n\x0c\x63\x61llback_url\x18\x01 \x01(\t\"\xc5\x03\n\nDeviceInfo\x12\x10\n\x08\x63\x61n_play\x18\x01 \x01(\x08\x12\x0e\n\x06volume\x18\x02 \x01(\r\x12\x0c\n\x04name\x18\x03 \x01(\t\x12\x30\n\x0c\x63\x61pabilities\x18\x04 \x01(\x0b\x32\x1a.connectstate.Capabilities\x12\x1f\n\x17\x64\x65vice_software_version\x18\x06 \x01(\t\x12-\n\x0b\x64\x65vice_type\x18\x07 \x01(\x0e\x32\x18.connectstate.DeviceType\x12\x15\n\rspirc_version\x18\t \x01(\t\x12\x11\n\tdevice_id\x18\n \x01(\t\x12\x1a\n\x12is_private_session\x18\x0b \x01(\x08\x12\x19\n\x11is_social_connect\x18\x0c \x01(\x08\x12\x11\n\tclient_id\x18\r \x01(\t\x12\r\n\x05\x62rand\x18\x0e \x01(\t\x12\r\n\x05model\x18\x0f \x01(\t\x12?\n\x0cmetadata_map\x18\x10 \x03(\x0b\x32).connectstate.DeviceInfo.MetadataMapEntry\x1a\x32\n\x10MetadataMapEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\"\xcc\x04\n\x0c\x43\x61pabilities\x12\x15\n\rcan_be_player\x18\x02 \x01(\x08\x12\x19\n\x11restrict_to_local\x18\x03 \x01(\x08\x12\x1a\n\x12gaia_eq_connect_id\x18\x05 \x01(\x08\x12\x17\n\x0fsupports_logout\x18\x06 \x01(\x08\x12\x15\n\ris_observable\x18\x07 \x01(\x08\x12\x14\n\x0cvolume_steps\x18\x08 \x01(\x05\x12\x17\n\x0fsupported_types\x18\t \x03(\t\x12\x14\n\x0c\x63ommand_acks\x18\n \x01(\x08\x12\x17\n\x0fsupports_rename\x18\x0b \x01(\x08\x12\x0e\n\x06hidden\x18\x0c \x01(\x08\x12\x16\n\x0e\x64isable_volume\x18\r \x01(\x08\x12\x18\n\x10\x63onnect_disabled\x18\x0e \x01(\x08\x12\x1c\n\x14supports_playlist_v2\x18\x0f \x01(\x08\x12\x17\n\x0fis_controllable\x18\x10 \x01(\x08\x12\"\n\x1asupports_external_episodes\x18\x11 \x01(\x08\x12%\n\x1dsupports_set_backend_metadata\x18\x12 \x01(\x08\x12!\n\x19supports_transfer_command\x18\x13 \x01(\x08\x12 \n\x18supports_command_request\x18\x14 \x01(\x08\x12\x18\n\x10is_voice_enabled\x18\x15 \x01(\x08\x12\x1f\n\x17needs_full_player_state\x18\x16 \x01(\x08\x12\x1c\n\x14supports_gzip_pushes\x18\x17 \x01(\x08\"+\n\x15\x43onnectCommandOptions\x12\x12\n\nmessage_id\x18\x01 \x01(\x05\"M\n\rLogoutCommand\x12<\n\x0f\x63ommand_options\x18\x01 \x01(\x0b\x32#.connectstate.ConnectCommandOptions\"`\n\x10SetVolumeCommand\x12\x0e\n\x06volume\x18\x01 \x01(\x05\x12<\n\x0f\x63ommand_options\x18\x02 \x01(\x0b\x32#.connectstate.ConnectCommandOptions\"`\n\rRenameCommand\x12\x11\n\trename_to\x18\x01 \x01(\t\x12<\n\x0f\x63ommand_options\x18\x02 \x01(\x0b\x32#.connectstate.ConnectCommandOptions\"\x95\x01\n\x19SetBackendMetadataCommand\x12G\n\x08metadata\x18\x01 \x03(\x0b\x32\x35.connectstate.SetBackendMetadataCommand.MetadataEntry\x1a/\n\rMetadataEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01*\xd4\x01\n\x11SendCommandResult\x12\x1f\n\x1bUNKNOWN_SEND_COMMAND_RESULT\x10\x00\x12\x0b\n\x07SUCCESS\x10\x01\x12\x14\n\x10\x44\x45VICE_NOT_FOUND\x10\x02\x12\x18\n\x14\x43ONTEXT_PLAYER_ERROR\x10\x03\x12\x16\n\x12\x44\x45VICE_DISAPPEARED\x10\x04\x12\x12\n\x0eUPSTREAM_ERROR\x10\x05\x12#\n\x1f\x44\x45VICE_DOES_NOT_SUPPORT_COMMAND\x10\x06\x12\x10\n\x0cRATE_LIMITED\x10\x07*\xb7\x01\n\x0ePutStateReason\x12\x1c\n\x18UNKNOWN_PUT_STATE_REASON\x10\x00\x12\x0f\n\x0bSPIRC_HELLO\x10\x01\x12\x10\n\x0cSPIRC_NOTIFY\x10\x02\x12\x0e\n\nNEW_DEVICE\x10\x03\x12\x18\n\x14PLAYER_STATE_CHANGED\x10\x04\x12\x12\n\x0eVOLUME_CHANGED\x10\x05\x12\x11\n\rPICKER_OPENED\x10\x06\x12\x13\n\x0f\x42\x45\x43\x41ME_INACTIVE\x10\x07*;\n\nMemberType\x12\x0c\n\x08SPIRC_V2\x10\x00\x12\x0c\n\x08SPIRC_V3\x10\x01\x12\x11\n\rCONNECT_STATE\x10\x02*\x84\x01\n\x13\x43lusterUpdateReason\x12!\n\x1dUNKNOWN_CLUSTER_UPDATE_REASON\x10\x00\x12\x17\n\x13\x44\x45VICES_DISAPPEARED\x10\x01\x12\x18\n\x14\x44\x45VICE_STATE_CHANGED\x10\x02\x12\x17\n\x13NEW_DEVICE_APPEARED\x10\x03*\xa0\x02\n\nDeviceType\x12\x0b\n\x07UNKNOWN\x10\x00\x12\x0c\n\x08\x43OMPUTER\x10\x01\x12\n\n\x06TABLET\x10\x02\x12\x0e\n\nSMARTPHONE\x10\x03\x12\x0b\n\x07SPEAKER\x10\x04\x12\x06\n\x02TV\x10\x05\x12\x07\n\x03\x41VR\x10\x06\x12\x07\n\x03STB\x10\x07\x12\x10\n\x0c\x41UDIO_DONGLE\x10\x08\x12\x10\n\x0cGAME_CONSOLE\x10\t\x12\x0e\n\nCAST_VIDEO\x10\n\x12\x0e\n\nCAST_AUDIO\x10\x0b\x12\x0e\n\nAUTOMOBILE\x10\x0c\x12\x0e\n\nSMARTWATCH\x10\r\x12\x0e\n\nCHROMEBOOK\x10\x0e\x12\x13\n\x0fUNKNOWN_SPOTIFY\x10\x64\x12\r\n\tCAR_THING\x10\x65\x12\x0c\n\x08OBSERVER\x10\x66\x12\x0e\n\nHOME_THING\x10gB\x1c\n\x18\x63om.spotify.connectstateH\x02\x62\x06proto3', + dependencies=[ + player__pb2.DESCRIPTOR, + ]) + +_SENDCOMMANDRESULT = _descriptor.EnumDescriptor( + name='SendCommandResult', + full_name='connectstate.SendCommandResult', + filename=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + values=[ + _descriptor.EnumValueDescriptor( + name='UNKNOWN_SEND_COMMAND_RESULT', + index=0, + number=0, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='SUCCESS', + index=1, + number=1, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='DEVICE_NOT_FOUND', + index=2, + number=2, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='CONTEXT_PLAYER_ERROR', + index=3, + number=3, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='DEVICE_DISAPPEARED', + index=4, + number=4, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='UPSTREAM_ERROR', + index=5, + number=5, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='DEVICE_DOES_NOT_SUPPORT_COMMAND', + index=6, + number=6, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='RATE_LIMITED', + index=7, + number=7, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + ], + containing_type=None, + serialized_options=None, + serialized_start=2650, + serialized_end=2862, +) +_sym_db.RegisterEnumDescriptor(_SENDCOMMANDRESULT) + +SendCommandResult = enum_type_wrapper.EnumTypeWrapper(_SENDCOMMANDRESULT) +_PUTSTATEREASON = _descriptor.EnumDescriptor( + name='PutStateReason', + full_name='connectstate.PutStateReason', + filename=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + values=[ + _descriptor.EnumValueDescriptor( + name='UNKNOWN_PUT_STATE_REASON', + index=0, + number=0, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='SPIRC_HELLO', + index=1, + number=1, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='SPIRC_NOTIFY', + index=2, + number=2, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='NEW_DEVICE', + index=3, + number=3, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='PLAYER_STATE_CHANGED', + index=4, + number=4, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='VOLUME_CHANGED', + index=5, + number=5, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='PICKER_OPENED', + index=6, + number=6, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='BECAME_INACTIVE', + index=7, + number=7, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + ], + containing_type=None, + serialized_options=None, + serialized_start=2865, + serialized_end=3048, +) +_sym_db.RegisterEnumDescriptor(_PUTSTATEREASON) + +PutStateReason = enum_type_wrapper.EnumTypeWrapper(_PUTSTATEREASON) +_MEMBERTYPE = _descriptor.EnumDescriptor( + name='MemberType', + full_name='connectstate.MemberType', + filename=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + values=[ + _descriptor.EnumValueDescriptor( + name='SPIRC_V2', + index=0, + number=0, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='SPIRC_V3', + index=1, + number=1, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='CONNECT_STATE', + index=2, + number=2, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + ], + containing_type=None, + serialized_options=None, + serialized_start=3050, + serialized_end=3109, +) +_sym_db.RegisterEnumDescriptor(_MEMBERTYPE) + +MemberType = enum_type_wrapper.EnumTypeWrapper(_MEMBERTYPE) +_CLUSTERUPDATEREASON = _descriptor.EnumDescriptor( + name='ClusterUpdateReason', + full_name='connectstate.ClusterUpdateReason', + filename=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + values=[ + _descriptor.EnumValueDescriptor( + name='UNKNOWN_CLUSTER_UPDATE_REASON', + index=0, + number=0, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='DEVICES_DISAPPEARED', + index=1, + number=1, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='DEVICE_STATE_CHANGED', + index=2, + number=2, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='NEW_DEVICE_APPEARED', + index=3, + number=3, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + ], + containing_type=None, + serialized_options=None, + serialized_start=3112, + serialized_end=3244, +) +_sym_db.RegisterEnumDescriptor(_CLUSTERUPDATEREASON) + +ClusterUpdateReason = enum_type_wrapper.EnumTypeWrapper(_CLUSTERUPDATEREASON) +_DEVICETYPE = _descriptor.EnumDescriptor( + name='DeviceType', + full_name='connectstate.DeviceType', + filename=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + values=[ + _descriptor.EnumValueDescriptor( + name='UNKNOWN', + index=0, + number=0, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='COMPUTER', + index=1, + number=1, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='TABLET', + index=2, + number=2, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='SMARTPHONE', + index=3, + number=3, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='SPEAKER', + index=4, + number=4, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='TV', + index=5, + number=5, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='AVR', + index=6, + number=6, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='STB', + index=7, + number=7, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='AUDIO_DONGLE', + index=8, + number=8, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='GAME_CONSOLE', + index=9, + number=9, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='CAST_VIDEO', + index=10, + number=10, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='CAST_AUDIO', + index=11, + number=11, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='AUTOMOBILE', + index=12, + number=12, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='SMARTWATCH', + index=13, + number=13, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='CHROMEBOOK', + index=14, + number=14, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='UNKNOWN_SPOTIFY', + index=15, + number=100, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='CAR_THING', + index=16, + number=101, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='OBSERVER', + index=17, + number=102, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='HOME_THING', + index=18, + number=103, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + ], + containing_type=None, + serialized_options=None, + serialized_start=3247, + serialized_end=3535, +) +_sym_db.RegisterEnumDescriptor(_DEVICETYPE) + +DeviceType = enum_type_wrapper.EnumTypeWrapper(_DEVICETYPE) +UNKNOWN_SEND_COMMAND_RESULT = 0 +SUCCESS = 1 +DEVICE_NOT_FOUND = 2 +CONTEXT_PLAYER_ERROR = 3 +DEVICE_DISAPPEARED = 4 +UPSTREAM_ERROR = 5 +DEVICE_DOES_NOT_SUPPORT_COMMAND = 6 +RATE_LIMITED = 7 +UNKNOWN_PUT_STATE_REASON = 0 +SPIRC_HELLO = 1 +SPIRC_NOTIFY = 2 +NEW_DEVICE = 3 +PLAYER_STATE_CHANGED = 4 +VOLUME_CHANGED = 5 +PICKER_OPENED = 6 +BECAME_INACTIVE = 7 +SPIRC_V2 = 0 +SPIRC_V3 = 1 +CONNECT_STATE = 2 +UNKNOWN_CLUSTER_UPDATE_REASON = 0 +DEVICES_DISAPPEARED = 1 +DEVICE_STATE_CHANGED = 2 +NEW_DEVICE_APPEARED = 3 +UNKNOWN = 0 +COMPUTER = 1 +TABLET = 2 +SMARTPHONE = 3 +SPEAKER = 4 +TV = 5 +AVR = 6 +STB = 7 +AUDIO_DONGLE = 8 +GAME_CONSOLE = 9 +CAST_VIDEO = 10 +CAST_AUDIO = 11 +AUTOMOBILE = 12 +SMARTWATCH = 13 +CHROMEBOOK = 14 +UNKNOWN_SPOTIFY = 100 +CAR_THING = 101 +OBSERVER = 102 +HOME_THING = 103 + +_CLUSTERUPDATE = _descriptor.Descriptor( + name='ClusterUpdate', + full_name='connectstate.ClusterUpdate', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='cluster', + full_name='connectstate.ClusterUpdate.cluster', + index=0, + number=1, + type=11, + cpp_type=10, + label=1, + has_default_value=False, + default_value=None, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='update_reason', + full_name='connectstate.ClusterUpdate.update_reason', + index=1, + number=2, + type=14, + cpp_type=8, + label=1, + has_default_value=False, + default_value=0, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='ack_id', + full_name='connectstate.ClusterUpdate.ack_id', + index=2, + number=3, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"".decode('utf-8'), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='devices_that_changed', + full_name='connectstate.ClusterUpdate.devices_that_changed', + index=3, + number=4, + type=9, + cpp_type=9, + label=3, + has_default_value=False, + default_value=[], + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[], + serialized_start=46, + serialized_end=205, +) + +_DEVICE = _descriptor.Descriptor( + name='Device', + full_name='connectstate.Device', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='device_info', + full_name='connectstate.Device.device_info', + index=0, + number=1, + type=11, + cpp_type=10, + label=1, + has_default_value=False, + default_value=None, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='player_state', + full_name='connectstate.Device.player_state', + index=1, + number=2, + type=11, + cpp_type=10, + label=1, + has_default_value=False, + default_value=None, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='private_device_info', + full_name='connectstate.Device.private_device_info', + index=2, + number=3, + type=11, + cpp_type=10, + label=1, + has_default_value=False, + default_value=None, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[], + serialized_start=208, + serialized_end=374, +) + +_CLUSTER_DEVICEENTRY = _descriptor.Descriptor( + name='DeviceEntry', + full_name='connectstate.Cluster.DeviceEntry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='key', + full_name='connectstate.Cluster.DeviceEntry.key', + index=0, + number=1, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"".decode('utf-8'), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='value', + full_name='connectstate.Cluster.DeviceEntry.value', + index=1, + number=2, + type=11, + cpp_type=10, + label=1, + has_default_value=False, + default_value=None, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=b'8\001', + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[], + serialized_start=556, + serialized_end=627, +) + +_CLUSTER = _descriptor.Descriptor( + name='Cluster', + full_name='connectstate.Cluster', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='timestamp', + full_name='connectstate.Cluster.timestamp', + index=0, + number=1, + type=3, + cpp_type=2, + label=1, + has_default_value=False, + default_value=0, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='active_device_id', + full_name='connectstate.Cluster.active_device_id', + index=1, + number=2, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"".decode('utf-8'), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='player_state', + full_name='connectstate.Cluster.player_state', + index=2, + number=3, + type=11, + cpp_type=10, + label=1, + has_default_value=False, + default_value=None, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='device', + full_name='connectstate.Cluster.device', + index=3, + number=4, + type=11, + cpp_type=10, + label=3, + has_default_value=False, + default_value=[], + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='transfer_data', + full_name='connectstate.Cluster.transfer_data', + index=4, + number=5, + type=12, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"", + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + ], + extensions=[], + nested_types=[ + _CLUSTER_DEVICEENTRY, + ], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[], + serialized_start=377, + serialized_end=627, +) + +_PUTSTATEREQUEST = _descriptor.Descriptor( + name='PutStateRequest', + full_name='connectstate.PutStateRequest', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='callback_url', + full_name='connectstate.PutStateRequest.callback_url', + index=0, + number=1, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"".decode('utf-8'), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='device', + full_name='connectstate.PutStateRequest.device', + index=1, + number=2, + type=11, + cpp_type=10, + label=1, + has_default_value=False, + default_value=None, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='member_type', + full_name='connectstate.PutStateRequest.member_type', + index=2, + number=3, + type=14, + cpp_type=8, + label=1, + has_default_value=False, + default_value=0, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='is_active', + full_name='connectstate.PutStateRequest.is_active', + index=3, + number=4, + type=8, + cpp_type=7, + label=1, + has_default_value=False, + default_value=False, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='put_state_reason', + full_name='connectstate.PutStateRequest.put_state_reason', + index=4, + number=5, + type=14, + cpp_type=8, + label=1, + has_default_value=False, + default_value=0, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='message_id', + full_name='connectstate.PutStateRequest.message_id', + index=5, + number=6, + type=13, + cpp_type=3, + label=1, + has_default_value=False, + default_value=0, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='last_command_sent_by_device_id', + full_name= + 'connectstate.PutStateRequest.last_command_sent_by_device_id', + index=6, + number=7, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"".decode('utf-8'), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='last_command_message_id', + full_name='connectstate.PutStateRequest.last_command_message_id', + index=7, + number=8, + type=13, + cpp_type=3, + label=1, + has_default_value=False, + default_value=0, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='started_playing_at', + full_name='connectstate.PutStateRequest.started_playing_at', + index=8, + number=9, + type=4, + cpp_type=4, + label=1, + has_default_value=False, + default_value=0, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='has_been_playing_for_ms', + full_name='connectstate.PutStateRequest.has_been_playing_for_ms', + index=9, + number=11, + type=4, + cpp_type=4, + label=1, + has_default_value=False, + default_value=0, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='client_side_timestamp', + full_name='connectstate.PutStateRequest.client_side_timestamp', + index=10, + number=12, + type=4, + cpp_type=4, + label=1, + has_default_value=False, + default_value=0, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='only_write_player_state', + full_name='connectstate.PutStateRequest.only_write_player_state', + index=11, + number=13, + type=8, + cpp_type=7, + label=1, + has_default_value=False, + default_value=False, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[], + serialized_start=630, + serialized_end=1047, +) + +_PRIVATEDEVICEINFO = _descriptor.Descriptor( + name='PrivateDeviceInfo', + full_name='connectstate.PrivateDeviceInfo', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='platform', + full_name='connectstate.PrivateDeviceInfo.platform', + index=0, + number=1, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"".decode('utf-8'), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[], + serialized_start=1049, + serialized_end=1086, +) + +_SUBSCRIBEREQUEST = _descriptor.Descriptor( + name='SubscribeRequest', + full_name='connectstate.SubscribeRequest', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='callback_url', + full_name='connectstate.SubscribeRequest.callback_url', + index=0, + number=1, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"".decode('utf-8'), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[], + serialized_start=1088, + serialized_end=1128, +) + +_DEVICEINFO_METADATAMAPENTRY = _descriptor.Descriptor( + name='MetadataMapEntry', + full_name='connectstate.DeviceInfo.MetadataMapEntry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='key', + full_name='connectstate.DeviceInfo.MetadataMapEntry.key', + index=0, + number=1, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"".decode('utf-8'), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='value', + full_name='connectstate.DeviceInfo.MetadataMapEntry.value', + index=1, + number=2, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"".decode('utf-8'), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=b'8\001', + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[], + serialized_start=1534, + serialized_end=1584, +) + +_DEVICEINFO = _descriptor.Descriptor( + name='DeviceInfo', + full_name='connectstate.DeviceInfo', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='can_play', + full_name='connectstate.DeviceInfo.can_play', + index=0, + number=1, + type=8, + cpp_type=7, + label=1, + has_default_value=False, + default_value=False, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='volume', + full_name='connectstate.DeviceInfo.volume', + index=1, + number=2, + type=13, + cpp_type=3, + label=1, + has_default_value=False, + default_value=0, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='name', + full_name='connectstate.DeviceInfo.name', + index=2, + number=3, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"".decode('utf-8'), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='capabilities', + full_name='connectstate.DeviceInfo.capabilities', + index=3, + number=4, + type=11, + cpp_type=10, + label=1, + has_default_value=False, + default_value=None, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='device_software_version', + full_name='connectstate.DeviceInfo.device_software_version', + index=4, + number=6, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"".decode('utf-8'), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='device_type', + full_name='connectstate.DeviceInfo.device_type', + index=5, + number=7, + type=14, + cpp_type=8, + label=1, + has_default_value=False, + default_value=0, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='spirc_version', + full_name='connectstate.DeviceInfo.spirc_version', + index=6, + number=9, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"".decode('utf-8'), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='device_id', + full_name='connectstate.DeviceInfo.device_id', + index=7, + number=10, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"".decode('utf-8'), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='is_private_session', + full_name='connectstate.DeviceInfo.is_private_session', + index=8, + number=11, + type=8, + cpp_type=7, + label=1, + has_default_value=False, + default_value=False, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='is_social_connect', + full_name='connectstate.DeviceInfo.is_social_connect', + index=9, + number=12, + type=8, + cpp_type=7, + label=1, + has_default_value=False, + default_value=False, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='client_id', + full_name='connectstate.DeviceInfo.client_id', + index=10, + number=13, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"".decode('utf-8'), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='brand', + full_name='connectstate.DeviceInfo.brand', + index=11, + number=14, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"".decode('utf-8'), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='model', + full_name='connectstate.DeviceInfo.model', + index=12, + number=15, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"".decode('utf-8'), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='metadata_map', + full_name='connectstate.DeviceInfo.metadata_map', + index=13, + number=16, + type=11, + cpp_type=10, + label=3, + has_default_value=False, + default_value=[], + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + ], + extensions=[], + nested_types=[ + _DEVICEINFO_METADATAMAPENTRY, + ], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[], + serialized_start=1131, + serialized_end=1584, +) + +_CAPABILITIES = _descriptor.Descriptor( + name='Capabilities', + full_name='connectstate.Capabilities', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='can_be_player', + full_name='connectstate.Capabilities.can_be_player', + index=0, + number=2, + type=8, + cpp_type=7, + label=1, + has_default_value=False, + default_value=False, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='restrict_to_local', + full_name='connectstate.Capabilities.restrict_to_local', + index=1, + number=3, + type=8, + cpp_type=7, + label=1, + has_default_value=False, + default_value=False, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='gaia_eq_connect_id', + full_name='connectstate.Capabilities.gaia_eq_connect_id', + index=2, + number=5, + type=8, + cpp_type=7, + label=1, + has_default_value=False, + default_value=False, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='supports_logout', + full_name='connectstate.Capabilities.supports_logout', + index=3, + number=6, + type=8, + cpp_type=7, + label=1, + has_default_value=False, + default_value=False, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='is_observable', + full_name='connectstate.Capabilities.is_observable', + index=4, + number=7, + type=8, + cpp_type=7, + label=1, + has_default_value=False, + default_value=False, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='volume_steps', + full_name='connectstate.Capabilities.volume_steps', + index=5, + number=8, + type=5, + cpp_type=1, + label=1, + has_default_value=False, + default_value=0, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='supported_types', + full_name='connectstate.Capabilities.supported_types', + index=6, + number=9, + type=9, + cpp_type=9, + label=3, + has_default_value=False, + default_value=[], + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='command_acks', + full_name='connectstate.Capabilities.command_acks', + index=7, + number=10, + type=8, + cpp_type=7, + label=1, + has_default_value=False, + default_value=False, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='supports_rename', + full_name='connectstate.Capabilities.supports_rename', + index=8, + number=11, + type=8, + cpp_type=7, + label=1, + has_default_value=False, + default_value=False, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='hidden', + full_name='connectstate.Capabilities.hidden', + index=9, + number=12, + type=8, + cpp_type=7, + label=1, + has_default_value=False, + default_value=False, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='disable_volume', + full_name='connectstate.Capabilities.disable_volume', + index=10, + number=13, + type=8, + cpp_type=7, + label=1, + has_default_value=False, + default_value=False, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='connect_disabled', + full_name='connectstate.Capabilities.connect_disabled', + index=11, + number=14, + type=8, + cpp_type=7, + label=1, + has_default_value=False, + default_value=False, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='supports_playlist_v2', + full_name='connectstate.Capabilities.supports_playlist_v2', + index=12, + number=15, + type=8, + cpp_type=7, + label=1, + has_default_value=False, + default_value=False, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='is_controllable', + full_name='connectstate.Capabilities.is_controllable', + index=13, + number=16, + type=8, + cpp_type=7, + label=1, + has_default_value=False, + default_value=False, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='supports_external_episodes', + full_name='connectstate.Capabilities.supports_external_episodes', + index=14, + number=17, + type=8, + cpp_type=7, + label=1, + has_default_value=False, + default_value=False, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='supports_set_backend_metadata', + full_name='connectstate.Capabilities.supports_set_backend_metadata', + index=15, + number=18, + type=8, + cpp_type=7, + label=1, + has_default_value=False, + default_value=False, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='supports_transfer_command', + full_name='connectstate.Capabilities.supports_transfer_command', + index=16, + number=19, + type=8, + cpp_type=7, + label=1, + has_default_value=False, + default_value=False, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='supports_command_request', + full_name='connectstate.Capabilities.supports_command_request', + index=17, + number=20, + type=8, + cpp_type=7, + label=1, + has_default_value=False, + default_value=False, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='is_voice_enabled', + full_name='connectstate.Capabilities.is_voice_enabled', + index=18, + number=21, + type=8, + cpp_type=7, + label=1, + has_default_value=False, + default_value=False, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='needs_full_player_state', + full_name='connectstate.Capabilities.needs_full_player_state', + index=19, + number=22, + type=8, + cpp_type=7, + label=1, + has_default_value=False, + default_value=False, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='supports_gzip_pushes', + full_name='connectstate.Capabilities.supports_gzip_pushes', + index=20, + number=23, + type=8, + cpp_type=7, + label=1, + has_default_value=False, + default_value=False, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[], + serialized_start=1587, + serialized_end=2175, +) + +_CONNECTCOMMANDOPTIONS = _descriptor.Descriptor( + name='ConnectCommandOptions', + full_name='connectstate.ConnectCommandOptions', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='message_id', + full_name='connectstate.ConnectCommandOptions.message_id', + index=0, + number=1, + type=5, + cpp_type=1, + label=1, + has_default_value=False, + default_value=0, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[], + serialized_start=2177, + serialized_end=2220, +) + +_LOGOUTCOMMAND = _descriptor.Descriptor( + name='LogoutCommand', + full_name='connectstate.LogoutCommand', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='command_options', + full_name='connectstate.LogoutCommand.command_options', + index=0, + number=1, + type=11, + cpp_type=10, + label=1, + has_default_value=False, + default_value=None, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[], + serialized_start=2222, + serialized_end=2299, +) + +_SETVOLUMECOMMAND = _descriptor.Descriptor( + name='SetVolumeCommand', + full_name='connectstate.SetVolumeCommand', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='volume', + full_name='connectstate.SetVolumeCommand.volume', + index=0, + number=1, + type=5, + cpp_type=1, + label=1, + has_default_value=False, + default_value=0, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='command_options', + full_name='connectstate.SetVolumeCommand.command_options', + index=1, + number=2, + type=11, + cpp_type=10, + label=1, + has_default_value=False, + default_value=None, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[], + serialized_start=2301, + serialized_end=2397, +) + +_RENAMECOMMAND = _descriptor.Descriptor( + name='RenameCommand', + full_name='connectstate.RenameCommand', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='rename_to', + full_name='connectstate.RenameCommand.rename_to', + index=0, + number=1, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"".decode('utf-8'), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='command_options', + full_name='connectstate.RenameCommand.command_options', + index=1, + number=2, + type=11, + cpp_type=10, + label=1, + has_default_value=False, + default_value=None, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[], + serialized_start=2399, + serialized_end=2495, +) + +_SETBACKENDMETADATACOMMAND_METADATAENTRY = _descriptor.Descriptor( + name='MetadataEntry', + full_name='connectstate.SetBackendMetadataCommand.MetadataEntry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='key', + full_name= + 'connectstate.SetBackendMetadataCommand.MetadataEntry.key', + index=0, + number=1, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"".decode('utf-8'), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='value', + full_name= + 'connectstate.SetBackendMetadataCommand.MetadataEntry.value', + index=1, + number=2, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"".decode('utf-8'), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=b'8\001', + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[], + serialized_start=2600, + serialized_end=2647, +) + +_SETBACKENDMETADATACOMMAND = _descriptor.Descriptor( + name='SetBackendMetadataCommand', + full_name='connectstate.SetBackendMetadataCommand', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='metadata', + full_name='connectstate.SetBackendMetadataCommand.metadata', + index=0, + number=1, + type=11, + cpp_type=10, + label=3, + has_default_value=False, + default_value=[], + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + ], + extensions=[], + nested_types=[ + _SETBACKENDMETADATACOMMAND_METADATAENTRY, + ], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[], + serialized_start=2498, + serialized_end=2647, +) + +_CLUSTERUPDATE.fields_by_name['cluster'].message_type = _CLUSTER +_CLUSTERUPDATE.fields_by_name['update_reason'].enum_type = _CLUSTERUPDATEREASON +_DEVICE.fields_by_name['device_info'].message_type = _DEVICEINFO +_DEVICE.fields_by_name['player_state'].message_type = player__pb2._PLAYERSTATE +_DEVICE.fields_by_name['private_device_info'].message_type = _PRIVATEDEVICEINFO +_CLUSTER_DEVICEENTRY.fields_by_name['value'].message_type = _DEVICEINFO +_CLUSTER_DEVICEENTRY.containing_type = _CLUSTER +_CLUSTER.fields_by_name['player_state'].message_type = player__pb2._PLAYERSTATE +_CLUSTER.fields_by_name['device'].message_type = _CLUSTER_DEVICEENTRY +_PUTSTATEREQUEST.fields_by_name['device'].message_type = _DEVICE +_PUTSTATEREQUEST.fields_by_name['member_type'].enum_type = _MEMBERTYPE +_PUTSTATEREQUEST.fields_by_name['put_state_reason'].enum_type = _PUTSTATEREASON +_DEVICEINFO_METADATAMAPENTRY.containing_type = _DEVICEINFO +_DEVICEINFO.fields_by_name['capabilities'].message_type = _CAPABILITIES +_DEVICEINFO.fields_by_name['device_type'].enum_type = _DEVICETYPE +_DEVICEINFO.fields_by_name[ + 'metadata_map'].message_type = _DEVICEINFO_METADATAMAPENTRY +_LOGOUTCOMMAND.fields_by_name[ + 'command_options'].message_type = _CONNECTCOMMANDOPTIONS +_SETVOLUMECOMMAND.fields_by_name[ + 'command_options'].message_type = _CONNECTCOMMANDOPTIONS +_RENAMECOMMAND.fields_by_name[ + 'command_options'].message_type = _CONNECTCOMMANDOPTIONS +_SETBACKENDMETADATACOMMAND_METADATAENTRY.containing_type = _SETBACKENDMETADATACOMMAND +_SETBACKENDMETADATACOMMAND.fields_by_name[ + 'metadata'].message_type = _SETBACKENDMETADATACOMMAND_METADATAENTRY +DESCRIPTOR.message_types_by_name['ClusterUpdate'] = _CLUSTERUPDATE +DESCRIPTOR.message_types_by_name['Device'] = _DEVICE +DESCRIPTOR.message_types_by_name['Cluster'] = _CLUSTER +DESCRIPTOR.message_types_by_name['PutStateRequest'] = _PUTSTATEREQUEST +DESCRIPTOR.message_types_by_name['PrivateDeviceInfo'] = _PRIVATEDEVICEINFO +DESCRIPTOR.message_types_by_name['SubscribeRequest'] = _SUBSCRIBEREQUEST +DESCRIPTOR.message_types_by_name['DeviceInfo'] = _DEVICEINFO +DESCRIPTOR.message_types_by_name['Capabilities'] = _CAPABILITIES +DESCRIPTOR.message_types_by_name[ + 'ConnectCommandOptions'] = _CONNECTCOMMANDOPTIONS +DESCRIPTOR.message_types_by_name['LogoutCommand'] = _LOGOUTCOMMAND +DESCRIPTOR.message_types_by_name['SetVolumeCommand'] = _SETVOLUMECOMMAND +DESCRIPTOR.message_types_by_name['RenameCommand'] = _RENAMECOMMAND +DESCRIPTOR.message_types_by_name[ + 'SetBackendMetadataCommand'] = _SETBACKENDMETADATACOMMAND +DESCRIPTOR.enum_types_by_name['SendCommandResult'] = _SENDCOMMANDRESULT +DESCRIPTOR.enum_types_by_name['PutStateReason'] = _PUTSTATEREASON +DESCRIPTOR.enum_types_by_name['MemberType'] = _MEMBERTYPE +DESCRIPTOR.enum_types_by_name['ClusterUpdateReason'] = _CLUSTERUPDATEREASON +DESCRIPTOR.enum_types_by_name['DeviceType'] = _DEVICETYPE +_sym_db.RegisterFileDescriptor(DESCRIPTOR) + +ClusterUpdate = _reflection.GeneratedProtocolMessageType( + 'ClusterUpdate', + (_message.Message, ), + { + 'DESCRIPTOR': _CLUSTERUPDATE, + '__module__': 'connect_pb2' + # @@protoc_insertion_point(class_scope:connectstate.ClusterUpdate) + }) +_sym_db.RegisterMessage(ClusterUpdate) + +Device = _reflection.GeneratedProtocolMessageType( + 'Device', + (_message.Message, ), + { + 'DESCRIPTOR': _DEVICE, + '__module__': 'connect_pb2' + # @@protoc_insertion_point(class_scope:connectstate.Device) + }) +_sym_db.RegisterMessage(Device) + +Cluster = _reflection.GeneratedProtocolMessageType( + 'Cluster', + (_message.Message, ), + { + 'DeviceEntry': + _reflection.GeneratedProtocolMessageType( + 'DeviceEntry', + (_message.Message, ), + { + 'DESCRIPTOR': _CLUSTER_DEVICEENTRY, + '__module__': 'connect_pb2' + # @@protoc_insertion_point(class_scope:connectstate.Cluster.DeviceEntry) + }), + 'DESCRIPTOR': + _CLUSTER, + '__module__': + 'connect_pb2' + # @@protoc_insertion_point(class_scope:connectstate.Cluster) + }) +_sym_db.RegisterMessage(Cluster) +_sym_db.RegisterMessage(Cluster.DeviceEntry) + +PutStateRequest = _reflection.GeneratedProtocolMessageType( + 'PutStateRequest', + (_message.Message, ), + { + 'DESCRIPTOR': _PUTSTATEREQUEST, + '__module__': 'connect_pb2' + # @@protoc_insertion_point(class_scope:connectstate.PutStateRequest) + }) +_sym_db.RegisterMessage(PutStateRequest) + +PrivateDeviceInfo = _reflection.GeneratedProtocolMessageType( + 'PrivateDeviceInfo', + (_message.Message, ), + { + 'DESCRIPTOR': _PRIVATEDEVICEINFO, + '__module__': 'connect_pb2' + # @@protoc_insertion_point(class_scope:connectstate.PrivateDeviceInfo) + }) +_sym_db.RegisterMessage(PrivateDeviceInfo) + +SubscribeRequest = _reflection.GeneratedProtocolMessageType( + 'SubscribeRequest', + (_message.Message, ), + { + 'DESCRIPTOR': _SUBSCRIBEREQUEST, + '__module__': 'connect_pb2' + # @@protoc_insertion_point(class_scope:connectstate.SubscribeRequest) + }) +_sym_db.RegisterMessage(SubscribeRequest) + +DeviceInfo = _reflection.GeneratedProtocolMessageType( + 'DeviceInfo', + (_message.Message, ), + { + 'MetadataMapEntry': + _reflection.GeneratedProtocolMessageType( + 'MetadataMapEntry', + (_message.Message, ), + { + 'DESCRIPTOR': _DEVICEINFO_METADATAMAPENTRY, + '__module__': 'connect_pb2' + # @@protoc_insertion_point(class_scope:connectstate.DeviceInfo.MetadataMapEntry) + }), + 'DESCRIPTOR': + _DEVICEINFO, + '__module__': + 'connect_pb2' + # @@protoc_insertion_point(class_scope:connectstate.DeviceInfo) + }) +_sym_db.RegisterMessage(DeviceInfo) +_sym_db.RegisterMessage(DeviceInfo.MetadataMapEntry) + +Capabilities = _reflection.GeneratedProtocolMessageType( + 'Capabilities', + (_message.Message, ), + { + 'DESCRIPTOR': _CAPABILITIES, + '__module__': 'connect_pb2' + # @@protoc_insertion_point(class_scope:connectstate.Capabilities) + }) +_sym_db.RegisterMessage(Capabilities) + +ConnectCommandOptions = _reflection.GeneratedProtocolMessageType( + 'ConnectCommandOptions', + (_message.Message, ), + { + 'DESCRIPTOR': _CONNECTCOMMANDOPTIONS, + '__module__': 'connect_pb2' + # @@protoc_insertion_point(class_scope:connectstate.ConnectCommandOptions) + }) +_sym_db.RegisterMessage(ConnectCommandOptions) + +LogoutCommand = _reflection.GeneratedProtocolMessageType( + 'LogoutCommand', + (_message.Message, ), + { + 'DESCRIPTOR': _LOGOUTCOMMAND, + '__module__': 'connect_pb2' + # @@protoc_insertion_point(class_scope:connectstate.LogoutCommand) + }) +_sym_db.RegisterMessage(LogoutCommand) + +SetVolumeCommand = _reflection.GeneratedProtocolMessageType( + 'SetVolumeCommand', + (_message.Message, ), + { + 'DESCRIPTOR': _SETVOLUMECOMMAND, + '__module__': 'connect_pb2' + # @@protoc_insertion_point(class_scope:connectstate.SetVolumeCommand) + }) +_sym_db.RegisterMessage(SetVolumeCommand) + +RenameCommand = _reflection.GeneratedProtocolMessageType( + 'RenameCommand', + (_message.Message, ), + { + 'DESCRIPTOR': _RENAMECOMMAND, + '__module__': 'connect_pb2' + # @@protoc_insertion_point(class_scope:connectstate.RenameCommand) + }) +_sym_db.RegisterMessage(RenameCommand) + +SetBackendMetadataCommand = _reflection.GeneratedProtocolMessageType( + 'SetBackendMetadataCommand', + (_message.Message, ), + { + 'MetadataEntry': + _reflection.GeneratedProtocolMessageType( + 'MetadataEntry', + (_message.Message, ), + { + 'DESCRIPTOR': _SETBACKENDMETADATACOMMAND_METADATAENTRY, + '__module__': 'connect_pb2' + # @@protoc_insertion_point(class_scope:connectstate.SetBackendMetadataCommand.MetadataEntry) + }), + 'DESCRIPTOR': + _SETBACKENDMETADATACOMMAND, + '__module__': + 'connect_pb2' + # @@protoc_insertion_point(class_scope:connectstate.SetBackendMetadataCommand) + }) +_sym_db.RegisterMessage(SetBackendMetadataCommand) +_sym_db.RegisterMessage(SetBackendMetadataCommand.MetadataEntry) + +DESCRIPTOR._options = None +_CLUSTER_DEVICEENTRY._options = None +_DEVICEINFO_METADATAMAPENTRY._options = None +_SETBACKENDMETADATACOMMAND_METADATAENTRY._options = None +# @@protoc_insertion_point(module_scope) diff --git a/librespot/proto/Connectivity_pb2.py b/librespot/proto/Connectivity_pb2.py new file mode 100644 index 0000000..bf17a91 --- /dev/null +++ b/librespot/proto/Connectivity_pb2.py @@ -0,0 +1,36 @@ +# -*- coding: utf-8 -*- +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: connectivity.proto +"""Generated protocol buffer code.""" +from google.protobuf.internal import builder as _builder +from google.protobuf import descriptor as _descriptor +from google.protobuf import descriptor_pool as _descriptor_pool +from google.protobuf import symbol_database as _symbol_database +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + + + +DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x12\x63onnectivity.proto\x12\x1bspotify.clienttoken.data.v0\"{\n\x13\x43onnectivitySdkData\x12Q\n\x16platform_specific_data\x18\x01 \x01(\x0b\x32\x31.spotify.clienttoken.data.v0.PlatformSpecificData\x12\x11\n\tdevice_id\x18\x02 \x01(\t\"\xdf\x01\n\x14PlatformSpecificData\x12\x41\n\x07\x61ndroid\x18\x01 \x01(\x0b\x32..spotify.clienttoken.data.v0.NativeAndroidDataH\x00\x12\x39\n\x03ios\x18\x02 \x01(\x0b\x32*.spotify.clienttoken.data.v0.NativeIOSDataH\x00\x12\x41\n\x07windows\x18\x04 \x01(\x0b\x32..spotify.clienttoken.data.v0.NativeWindowsDataH\x00\x42\x06\n\x04\x64\x61ta\"\xb9\x01\n\x11NativeAndroidData\x12\x19\n\x11major_sdk_version\x18\x01 \x01(\x05\x12\x19\n\x11minor_sdk_version\x18\x02 \x01(\x05\x12\x19\n\x11patch_sdk_version\x18\x03 \x01(\x05\x12\x13\n\x0b\x61pi_version\x18\x04 \x01(\r\x12>\n\x11screen_dimensions\x18\x05 \x01(\x0b\x32#.spotify.clienttoken.data.v0.Screen\"\x9e\x01\n\rNativeIOSData\x12\x1c\n\x14user_interface_idiom\x18\x01 \x01(\x05\x12\x1f\n\x17target_iphone_simulator\x18\x02 \x01(\x08\x12\x12\n\nhw_machine\x18\x03 \x01(\t\x12\x16\n\x0esystem_version\x18\x04 \x01(\t\x12\"\n\x1asimulator_model_identifier\x18\x05 \x01(\t\"\xa0\x01\n\x11NativeWindowsData\x12\x12\n\nsomething1\x18\x01 \x01(\x05\x12\x12\n\nsomething3\x18\x03 \x01(\x05\x12\x12\n\nsomething4\x18\x04 \x01(\x05\x12\x12\n\nsomething6\x18\x06 \x01(\x05\x12\x12\n\nsomething7\x18\x07 \x01(\x05\x12\x12\n\nsomething8\x18\x08 \x01(\x05\x12\x13\n\x0bsomething10\x18\n \x01(\x08\"8\n\x06Screen\x12\r\n\x05width\x18\x01 \x01(\x05\x12\x0e\n\x06height\x18\x02 \x01(\x05\x12\x0f\n\x07\x64\x65nsity\x18\x03 \x01(\x05\x42#\n\x1f\x63om.spotify.clienttoken.data.v0H\x02\x62\x06proto3') + +_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, globals()) +_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'connectivity_pb2', globals()) +if _descriptor._USE_C_DESCRIPTORS == False: + + DESCRIPTOR._options = None + DESCRIPTOR._serialized_options = b'\n\037com.spotify.clienttoken.data.v0H\002' + _CONNECTIVITYSDKDATA._serialized_start=51 + _CONNECTIVITYSDKDATA._serialized_end=174 + _PLATFORMSPECIFICDATA._serialized_start=177 + _PLATFORMSPECIFICDATA._serialized_end=400 + _NATIVEANDROIDDATA._serialized_start=403 + _NATIVEANDROIDDATA._serialized_end=588 + _NATIVEIOSDATA._serialized_start=591 + _NATIVEIOSDATA._serialized_end=749 + _NATIVEWINDOWSDATA._serialized_start=752 + _NATIVEWINDOWSDATA._serialized_end=912 + _SCREEN._serialized_start=914 + _SCREEN._serialized_end=970 +# @@protoc_insertion_point(module_scope) diff --git a/librespot/proto/ContextPage_pb2.py b/librespot/proto/ContextPage_pb2.py new file mode 100644 index 0000000..5256d5a --- /dev/null +++ b/librespot/proto/ContextPage_pb2.py @@ -0,0 +1,239 @@ +# -*- coding: utf-8 -*- +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: context_page.proto +"""Generated protocol buffer code.""" +import ContextTrack_pb2 as context__track__pb2 +from google.protobuf import descriptor as _descriptor +from google.protobuf import message as _message +from google.protobuf import reflection as _reflection +from google.protobuf import symbol_database as _symbol_database + +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + +DESCRIPTOR = _descriptor.FileDescriptor( + name="context_page.proto", + package="spotify.player.proto", + syntax="proto2", + serialized_options=b"\n\023com.spotify.contextH\002", + 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', + dependencies=[ + context__track__pb2.DESCRIPTOR, + ], +) + +_CONTEXTPAGE_METADATAENTRY = _descriptor.Descriptor( + name="MetadataEntry", + full_name="spotify.player.proto.ContextPage.MetadataEntry", + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name="key", + full_name="spotify.player.proto.ContextPage.MetadataEntry.key", + index=0, + number=1, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"".decode("utf-8"), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="value", + full_name="spotify.player.proto.ContextPage.MetadataEntry.value", + index=1, + number=2, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"".decode("utf-8"), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=b"8\001", + is_extendable=False, + syntax="proto2", + extension_ranges=[], + oneofs=[], + serialized_start=258, + serialized_end=305, +) + +_CONTEXTPAGE = _descriptor.Descriptor( + name="ContextPage", + full_name="spotify.player.proto.ContextPage", + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name="page_url", + full_name="spotify.player.proto.ContextPage.page_url", + index=0, + number=1, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"".decode("utf-8"), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="next_page_url", + full_name="spotify.player.proto.ContextPage.next_page_url", + index=1, + number=2, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"".decode("utf-8"), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="metadata", + full_name="spotify.player.proto.ContextPage.metadata", + index=2, + number=3, + type=11, + cpp_type=10, + label=3, + has_default_value=False, + default_value=[], + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="tracks", + full_name="spotify.player.proto.ContextPage.tracks", + index=3, + number=4, + type=11, + cpp_type=10, + label=3, + has_default_value=False, + default_value=[], + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="loading", + full_name="spotify.player.proto.ContextPage.loading", + index=4, + number=5, + type=8, + cpp_type=7, + label=1, + has_default_value=False, + default_value=False, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + ], + extensions=[], + nested_types=[ + _CONTEXTPAGE_METADATAENTRY, + ], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax="proto2", + extension_ranges=[], + oneofs=[], + serialized_start=66, + serialized_end=305, +) + +_CONTEXTPAGE_METADATAENTRY.containing_type = _CONTEXTPAGE +_CONTEXTPAGE.fields_by_name[ + "metadata"].message_type = _CONTEXTPAGE_METADATAENTRY +_CONTEXTPAGE.fields_by_name[ + "tracks"].message_type = context__track__pb2._CONTEXTTRACK +DESCRIPTOR.message_types_by_name["ContextPage"] = _CONTEXTPAGE +_sym_db.RegisterFileDescriptor(DESCRIPTOR) + +ContextPage = _reflection.GeneratedProtocolMessageType( + "ContextPage", + (_message.Message, ), + { + "MetadataEntry": + _reflection.GeneratedProtocolMessageType( + "MetadataEntry", + (_message.Message, ), + { + "DESCRIPTOR": _CONTEXTPAGE_METADATAENTRY, + "__module__": "context_page_pb2" + # @@protoc_insertion_point(class_scope:spotify.player.proto.ContextPage.MetadataEntry) + }, + ), + "DESCRIPTOR": + _CONTEXTPAGE, + "__module__": + "context_page_pb2" + # @@protoc_insertion_point(class_scope:spotify.player.proto.ContextPage) + }, +) +_sym_db.RegisterMessage(ContextPage) +_sym_db.RegisterMessage(ContextPage.MetadataEntry) + +DESCRIPTOR._options = None +_CONTEXTPAGE_METADATAENTRY._options = None +# @@protoc_insertion_point(module_scope) diff --git a/librespot/proto/ContextPlayerOptions_pb2.py b/librespot/proto/ContextPlayerOptions_pb2.py new file mode 100644 index 0000000..7b62e05 --- /dev/null +++ b/librespot/proto/ContextPlayerOptions_pb2.py @@ -0,0 +1,215 @@ +# -*- coding: utf-8 -*- +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: context_player_options.proto +"""Generated protocol buffer code.""" +from google.protobuf import descriptor as _descriptor +from google.protobuf import message as _message +from google.protobuf import reflection as _reflection +from google.protobuf import symbol_database as _symbol_database + +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + +DESCRIPTOR = _descriptor.FileDescriptor( + name="context_player_options.proto", + package="spotify.player.proto", + syntax="proto2", + serialized_options=b"\n\023com.spotify.contextH\002", + 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', +) + +_CONTEXTPLAYEROPTIONS = _descriptor.Descriptor( + name="ContextPlayerOptions", + full_name="spotify.player.proto.ContextPlayerOptions", + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name="shuffling_context", + full_name= + "spotify.player.proto.ContextPlayerOptions.shuffling_context", + index=0, + number=1, + type=8, + cpp_type=7, + label=1, + has_default_value=False, + default_value=False, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="repeating_context", + full_name= + "spotify.player.proto.ContextPlayerOptions.repeating_context", + index=1, + number=2, + type=8, + cpp_type=7, + label=1, + has_default_value=False, + default_value=False, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="repeating_track", + full_name= + "spotify.player.proto.ContextPlayerOptions.repeating_track", + index=2, + number=3, + type=8, + cpp_type=7, + label=1, + has_default_value=False, + default_value=False, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax="proto2", + extension_ranges=[], + oneofs=[], + serialized_start=54, + serialized_end=155, +) + +_CONTEXTPLAYEROPTIONOVERRIDES = _descriptor.Descriptor( + name="ContextPlayerOptionOverrides", + full_name="spotify.player.proto.ContextPlayerOptionOverrides", + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name="shuffling_context", + full_name= + "spotify.player.proto.ContextPlayerOptionOverrides.shuffling_context", + index=0, + number=1, + type=8, + cpp_type=7, + label=1, + has_default_value=False, + default_value=False, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="repeating_context", + full_name= + "spotify.player.proto.ContextPlayerOptionOverrides.repeating_context", + index=1, + number=2, + type=8, + cpp_type=7, + label=1, + has_default_value=False, + default_value=False, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="repeating_track", + full_name= + "spotify.player.proto.ContextPlayerOptionOverrides.repeating_track", + index=2, + number=3, + type=8, + cpp_type=7, + label=1, + has_default_value=False, + default_value=False, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax="proto2", + extension_ranges=[], + oneofs=[], + serialized_start=157, + serialized_end=266, +) + +DESCRIPTOR.message_types_by_name[ + "ContextPlayerOptions"] = _CONTEXTPLAYEROPTIONS +DESCRIPTOR.message_types_by_name[ + "ContextPlayerOptionOverrides"] = _CONTEXTPLAYEROPTIONOVERRIDES +_sym_db.RegisterFileDescriptor(DESCRIPTOR) + +ContextPlayerOptions = _reflection.GeneratedProtocolMessageType( + "ContextPlayerOptions", + (_message.Message, ), + { + "DESCRIPTOR": _CONTEXTPLAYEROPTIONS, + "__module__": "context_player_options_pb2" + # @@protoc_insertion_point(class_scope:spotify.player.proto.ContextPlayerOptions) + }, +) +_sym_db.RegisterMessage(ContextPlayerOptions) + +ContextPlayerOptionOverrides = _reflection.GeneratedProtocolMessageType( + "ContextPlayerOptionOverrides", + (_message.Message, ), + { + "DESCRIPTOR": _CONTEXTPLAYEROPTIONOVERRIDES, + "__module__": "context_player_options_pb2" + # @@protoc_insertion_point(class_scope:spotify.player.proto.ContextPlayerOptionOverrides) + }, +) +_sym_db.RegisterMessage(ContextPlayerOptionOverrides) + +DESCRIPTOR._options = None +# @@protoc_insertion_point(module_scope) diff --git a/librespot/proto/ContextTrack_pb2.py b/librespot/proto/ContextTrack_pb2.py new file mode 100644 index 0000000..495b4ea --- /dev/null +++ b/librespot/proto/ContextTrack_pb2.py @@ -0,0 +1,214 @@ +# -*- coding: utf-8 -*- +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: context_track.proto +"""Generated protocol buffer code.""" +from google.protobuf import descriptor as _descriptor +from google.protobuf import message as _message +from google.protobuf import reflection as _reflection +from google.protobuf import symbol_database as _symbol_database + +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + +DESCRIPTOR = _descriptor.FileDescriptor( + name="context_track.proto", + package="spotify.player.proto", + syntax="proto2", + serialized_options=b"\n\023com.spotify.contextH\002", + 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', +) + +_CONTEXTTRACK_METADATAENTRY = _descriptor.Descriptor( + name="MetadataEntry", + full_name="spotify.player.proto.ContextTrack.MetadataEntry", + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name="key", + full_name="spotify.player.proto.ContextTrack.MetadataEntry.key", + index=0, + number=1, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"".decode("utf-8"), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="value", + full_name="spotify.player.proto.ContextTrack.MetadataEntry.value", + index=1, + number=2, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"".decode("utf-8"), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=b"8\001", + is_extendable=False, + syntax="proto2", + extension_ranges=[], + oneofs=[], + serialized_start=169, + serialized_end=216, +) + +_CONTEXTTRACK = _descriptor.Descriptor( + name="ContextTrack", + full_name="spotify.player.proto.ContextTrack", + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name="uri", + full_name="spotify.player.proto.ContextTrack.uri", + index=0, + number=1, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"".decode("utf-8"), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="uid", + full_name="spotify.player.proto.ContextTrack.uid", + index=1, + number=2, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"".decode("utf-8"), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="gid", + full_name="spotify.player.proto.ContextTrack.gid", + index=2, + number=3, + type=12, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"", + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="metadata", + full_name="spotify.player.proto.ContextTrack.metadata", + index=3, + number=4, + type=11, + cpp_type=10, + label=3, + has_default_value=False, + default_value=[], + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + ], + extensions=[], + nested_types=[ + _CONTEXTTRACK_METADATAENTRY, + ], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax="proto2", + extension_ranges=[], + oneofs=[], + serialized_start=46, + serialized_end=216, +) + +_CONTEXTTRACK_METADATAENTRY.containing_type = _CONTEXTTRACK +_CONTEXTTRACK.fields_by_name[ + "metadata"].message_type = _CONTEXTTRACK_METADATAENTRY +DESCRIPTOR.message_types_by_name["ContextTrack"] = _CONTEXTTRACK +_sym_db.RegisterFileDescriptor(DESCRIPTOR) + +ContextTrack = _reflection.GeneratedProtocolMessageType( + "ContextTrack", + (_message.Message, ), + { + "MetadataEntry": + _reflection.GeneratedProtocolMessageType( + "MetadataEntry", + (_message.Message, ), + { + "DESCRIPTOR": _CONTEXTTRACK_METADATAENTRY, + "__module__": "context_track_pb2" + # @@protoc_insertion_point(class_scope:spotify.player.proto.ContextTrack.MetadataEntry) + }, + ), + "DESCRIPTOR": + _CONTEXTTRACK, + "__module__": + "context_track_pb2" + # @@protoc_insertion_point(class_scope:spotify.player.proto.ContextTrack) + }, +) +_sym_db.RegisterMessage(ContextTrack) +_sym_db.RegisterMessage(ContextTrack.MetadataEntry) + +DESCRIPTOR._options = None +_CONTEXTTRACK_METADATAENTRY._options = None +# @@protoc_insertion_point(module_scope) diff --git a/librespot/proto/Context_pb2.py b/librespot/proto/Context_pb2.py new file mode 100644 index 0000000..0b2eeae --- /dev/null +++ b/librespot/proto/Context_pb2.py @@ -0,0 +1,260 @@ +# -*- coding: utf-8 -*- +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: context.proto +"""Generated protocol buffer code.""" +import ContextPage_pb2 as context__page__pb2 +import Restrictions_pb2 as restrictions__pb2 +from google.protobuf import descriptor as _descriptor +from google.protobuf import message as _message +from google.protobuf import reflection as _reflection +from google.protobuf import symbol_database as _symbol_database + +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + +DESCRIPTOR = _descriptor.FileDescriptor( + name="context.proto", + package="spotify.player.proto", + syntax="proto2", + serialized_options=b"\n\023com.spotify.contextH\002", + 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', + dependencies=[ + context__page__pb2.DESCRIPTOR, + restrictions__pb2.DESCRIPTOR, + ], +) + +_CONTEXT_METADATAENTRY = _descriptor.Descriptor( + name="MetadataEntry", + full_name="spotify.player.proto.Context.MetadataEntry", + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name="key", + full_name="spotify.player.proto.Context.MetadataEntry.key", + index=0, + number=1, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"".decode("utf-8"), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="value", + full_name="spotify.player.proto.Context.MetadataEntry.value", + index=1, + number=2, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"".decode("utf-8"), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=b"8\001", + is_extendable=False, + syntax="proto2", + extension_ranges=[], + oneofs=[], + serialized_start=305, + serialized_end=352, +) + +_CONTEXT = _descriptor.Descriptor( + name="Context", + full_name="spotify.player.proto.Context", + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name="uri", + full_name="spotify.player.proto.Context.uri", + index=0, + number=1, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"".decode("utf-8"), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="url", + full_name="spotify.player.proto.Context.url", + index=1, + number=2, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"".decode("utf-8"), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="metadata", + full_name="spotify.player.proto.Context.metadata", + index=2, + number=3, + type=11, + cpp_type=10, + label=3, + has_default_value=False, + default_value=[], + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="restrictions", + full_name="spotify.player.proto.Context.restrictions", + index=3, + number=4, + type=11, + cpp_type=10, + label=1, + has_default_value=False, + default_value=None, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="pages", + full_name="spotify.player.proto.Context.pages", + index=4, + number=5, + type=11, + cpp_type=10, + label=3, + has_default_value=False, + default_value=[], + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="loading", + full_name="spotify.player.proto.Context.loading", + index=5, + number=6, + type=8, + cpp_type=7, + label=1, + has_default_value=False, + default_value=False, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + ], + extensions=[], + nested_types=[ + _CONTEXT_METADATAENTRY, + ], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax="proto2", + extension_ranges=[], + oneofs=[], + serialized_start=80, + serialized_end=352, +) + +_CONTEXT_METADATAENTRY.containing_type = _CONTEXT +_CONTEXT.fields_by_name["metadata"].message_type = _CONTEXT_METADATAENTRY +_CONTEXT.fields_by_name[ + "restrictions"].message_type = restrictions__pb2._RESTRICTIONS +_CONTEXT.fields_by_name["pages"].message_type = context__page__pb2._CONTEXTPAGE +DESCRIPTOR.message_types_by_name["Context"] = _CONTEXT +_sym_db.RegisterFileDescriptor(DESCRIPTOR) + +Context = _reflection.GeneratedProtocolMessageType( + "Context", + (_message.Message, ), + { + "MetadataEntry": + _reflection.GeneratedProtocolMessageType( + "MetadataEntry", + (_message.Message, ), + { + "DESCRIPTOR": _CONTEXT_METADATAENTRY, + "__module__": "context_pb2" + # @@protoc_insertion_point(class_scope:spotify.player.proto.Context.MetadataEntry) + }, + ), + "DESCRIPTOR": + _CONTEXT, + "__module__": + "context_pb2" + # @@protoc_insertion_point(class_scope:spotify.player.proto.Context) + }, +) +_sym_db.RegisterMessage(Context) +_sym_db.RegisterMessage(Context.MetadataEntry) + +DESCRIPTOR._options = None +_CONTEXT_METADATAENTRY._options = None +# @@protoc_insertion_point(module_scope) diff --git a/librespot/proto/ExplicitContentPubsub_pb2.py b/librespot/proto/ExplicitContentPubsub_pb2.py new file mode 100644 index 0000000..26ed33e --- /dev/null +++ b/librespot/proto/ExplicitContentPubsub_pb2.py @@ -0,0 +1,147 @@ +# -*- coding: utf-8 -*- +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: explicit_content_pubsub.proto +"""Generated protocol buffer code.""" +from google.protobuf import descriptor as _descriptor +from google.protobuf import message as _message +from google.protobuf import reflection as _reflection +from google.protobuf import symbol_database as _symbol_database +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + +DESCRIPTOR = _descriptor.FileDescriptor( + name='explicit_content_pubsub.proto', + package='spotify.explicit_content.proto', + syntax='proto2', + serialized_options=b'\n\024com.spotify.explicitH\002', + create_key=_descriptor._internal_create_key, + serialized_pb= + b'\n\x1d\x65xplicit_content_pubsub.proto\x12\x1espotify.explicit_content.proto\"*\n\x0cKeyValuePair\x12\x0b\n\x03key\x18\x01 \x02(\t\x12\r\n\x05value\x18\x02 \x02(\t\"S\n\x14UserAttributesUpdate\x12;\n\x05pairs\x18\x01 \x03(\x0b\x32,.spotify.explicit_content.proto.KeyValuePairB\x18\n\x14\x63om.spotify.explicitH\x02' +) + +_KEYVALUEPAIR = _descriptor.Descriptor( + name='KeyValuePair', + full_name='spotify.explicit_content.proto.KeyValuePair', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='key', + full_name='spotify.explicit_content.proto.KeyValuePair.key', + index=0, + number=1, + type=9, + cpp_type=9, + label=2, + has_default_value=False, + default_value=b"".decode('utf-8'), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='value', + full_name='spotify.explicit_content.proto.KeyValuePair.value', + index=1, + number=2, + type=9, + cpp_type=9, + label=2, + has_default_value=False, + default_value=b"".decode('utf-8'), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[], + serialized_start=65, + serialized_end=107, +) + +_USERATTRIBUTESUPDATE = _descriptor.Descriptor( + name='UserAttributesUpdate', + full_name='spotify.explicit_content.proto.UserAttributesUpdate', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='pairs', + full_name= + 'spotify.explicit_content.proto.UserAttributesUpdate.pairs', + index=0, + number=1, + type=11, + cpp_type=10, + label=3, + has_default_value=False, + default_value=[], + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[], + serialized_start=109, + serialized_end=192, +) + +_USERATTRIBUTESUPDATE.fields_by_name['pairs'].message_type = _KEYVALUEPAIR +DESCRIPTOR.message_types_by_name['KeyValuePair'] = _KEYVALUEPAIR +DESCRIPTOR.message_types_by_name[ + 'UserAttributesUpdate'] = _USERATTRIBUTESUPDATE +_sym_db.RegisterFileDescriptor(DESCRIPTOR) + +KeyValuePair = _reflection.GeneratedProtocolMessageType( + 'KeyValuePair', + (_message.Message, ), + { + 'DESCRIPTOR': _KEYVALUEPAIR, + '__module__': 'explicit_content_pubsub_pb2' + # @@protoc_insertion_point(class_scope:spotify.explicit_content.proto.KeyValuePair) + }) +_sym_db.RegisterMessage(KeyValuePair) + +UserAttributesUpdate = _reflection.GeneratedProtocolMessageType( + 'UserAttributesUpdate', + (_message.Message, ), + { + 'DESCRIPTOR': _USERATTRIBUTESUPDATE, + '__module__': 'explicit_content_pubsub_pb2' + # @@protoc_insertion_point(class_scope:spotify.explicit_content.proto.UserAttributesUpdate) + }) +_sym_db.RegisterMessage(UserAttributesUpdate) + +DESCRIPTOR._options = None +# @@protoc_insertion_point(module_scope) diff --git a/librespot/proto/Keyexchange_pb2.py b/librespot/proto/Keyexchange_pb2.py new file mode 100644 index 0000000..663ee3b --- /dev/null +++ b/librespot/proto/Keyexchange_pb2.py @@ -0,0 +1,2497 @@ +# -*- coding: utf-8 -*- +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: keyexchange.proto +"""Generated protocol buffer code.""" +from google.protobuf.internal import enum_type_wrapper +from google.protobuf import descriptor as _descriptor +from google.protobuf import message as _message +from google.protobuf import reflection as _reflection +from google.protobuf import symbol_database as _symbol_database +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + +DESCRIPTOR = _descriptor.FileDescriptor( + name='keyexchange.proto', + package='spotify', + syntax='proto2', + serialized_options=b'\n\013com.spotify', + create_key=_descriptor._internal_create_key, + serialized_pb= + b'\n\x11keyexchange.proto\x12\x07spotify\"\xe0\x02\n\x0b\x43lientHello\x12&\n\nbuild_info\x18\n \x02(\x0b\x32\x12.spotify.BuildInfo\x12\x34\n\x16\x66ingerprints_supported\x18\x14 \x03(\x0e\x32\x14.spotify.Fingerprint\x12\x34\n\x16\x63ryptosuites_supported\x18\x1e \x03(\x0e\x32\x14.spotify.Cryptosuite\x12\x30\n\x14powschemes_supported\x18( \x03(\x0e\x32\x12.spotify.Powscheme\x12:\n\x12login_crypto_hello\x18\x32 \x02(\x0b\x32\x1e.spotify.LoginCryptoHelloUnion\x12\x14\n\x0c\x63lient_nonce\x18< \x02(\x0c\x12\x0f\n\x07padding\x18\x46 \x01(\x0c\x12(\n\x0b\x66\x65\x61ture_set\x18P \x01(\x0b\x32\x13.spotify.FeatureSet\"\x92\x01\n\tBuildInfo\x12!\n\x07product\x18\n \x02(\x0e\x32\x10.spotify.Product\x12,\n\rproduct_flags\x18\x14 \x03(\x0e\x32\x15.spotify.ProductFlags\x12#\n\x08platform\x18\x1e \x02(\x0e\x32\x11.spotify.Platform\x12\x0f\n\x07version\x18( \x02(\x04\"W\n\x15LoginCryptoHelloUnion\x12>\n\x0e\x64iffie_hellman\x18\n \x01(\x0b\x32&.spotify.LoginCryptoDiffieHellmanHello\"F\n\x1dLoginCryptoDiffieHellmanHello\x12\n\n\x02gc\x18\n \x02(\x0c\x12\x19\n\x11server_keys_known\x18\x14 \x02(\r\";\n\nFeatureSet\x12\x13\n\x0b\x61utoupdate2\x18\x01 \x01(\x08\x12\x18\n\x10\x63urrent_location\x18\x02 \x01(\x08\"\x9c\x01\n\x11\x41PResponseMessage\x12\'\n\tchallenge\x18\n \x01(\x0b\x32\x14.spotify.APChallenge\x12\x30\n\x07upgrade\x18\x14 \x01(\x0b\x32\x1f.spotify.UpgradeRequiredMessage\x12,\n\x0clogin_failed\x18\x1e \x01(\x0b\x32\x16.spotify.APLoginFailed\"\xa7\x02\n\x0b\x41PChallenge\x12\x42\n\x16login_crypto_challenge\x18\n \x02(\x0b\x32\".spotify.LoginCryptoChallengeUnion\x12\x41\n\x15\x66ingerprint_challenge\x18\x14 \x02(\x0b\x32\".spotify.FingerprintChallengeUnion\x12\x31\n\rpow_challenge\x18\x1e \x02(\x0b\x32\x1a.spotify.PoWChallengeUnion\x12\x37\n\x10\x63rypto_challenge\x18( \x02(\x0b\x32\x1d.spotify.CryptoChallengeUnion\x12\x14\n\x0cserver_nonce\x18\x32 \x02(\x0c\x12\x0f\n\x07padding\x18< \x01(\x0c\"_\n\x19LoginCryptoChallengeUnion\x12\x42\n\x0e\x64iffie_hellman\x18\n \x01(\x0b\x32*.spotify.LoginCryptoDiffieHellmanChallenge\"c\n!LoginCryptoDiffieHellmanChallenge\x12\n\n\x02gs\x18\n \x02(\x0c\x12\x1c\n\x14server_signature_key\x18\x14 \x02(\x05\x12\x14\n\x0cgs_signature\x18\x1e \x02(\x0c\"\x8c\x01\n\x19\x46ingerprintChallengeUnion\x12\x31\n\x05grain\x18\n \x01(\x0b\x32\".spotify.FingerprintGrainChallenge\x12<\n\x0bhmac_ripemd\x18\x14 \x01(\x0b\x32\'.spotify.FingerprintHmacRipemdChallenge\"(\n\x19\x46ingerprintGrainChallenge\x12\x0b\n\x03kek\x18\n \x02(\x0c\"3\n\x1e\x46ingerprintHmacRipemdChallenge\x12\x11\n\tchallenge\x18\n \x02(\x0c\"E\n\x11PoWChallengeUnion\x12\x30\n\thash_cash\x18\n \x01(\x0b\x32\x1d.spotify.PoWHashCashChallenge\"F\n\x14PoWHashCashChallenge\x12\x0e\n\x06prefix\x18\n \x01(\x0c\x12\x0e\n\x06length\x18\x14 \x01(\x05\x12\x0e\n\x06target\x18\x1e \x01(\x05\"\x84\x01\n\x14\x43ryptoChallengeUnion\x12\x30\n\x07shannon\x18\n \x01(\x0b\x32\x1f.spotify.CryptoShannonChallenge\x12:\n\rrc4_sha1_hmac\x18\x14 \x01(\x0b\x32#.spotify.CryptoRc4Sha1HmacChallenge\"\x18\n\x16\x43ryptoShannonChallenge\"\x1c\n\x1a\x43ryptoRc4Sha1HmacChallenge\"]\n\x16UpgradeRequiredMessage\x12\x1b\n\x13upgrade_signed_part\x18\n \x02(\x0c\x12\x11\n\tsignature\x18\x14 \x02(\x0c\x12\x13\n\x0bhttp_suffix\x18\x1e \x01(\t\"w\n\rAPLoginFailed\x12&\n\nerror_code\x18\n \x02(\x0e\x32\x12.spotify.ErrorCode\x12\x13\n\x0bretry_delay\x18\x14 \x01(\x05\x12\x0e\n\x06\x65xpiry\x18\x1e \x01(\x05\x12\x19\n\x11\x65rror_description\x18( \x01(\t\"\xc3\x01\n\x17\x43lientResponsePlaintext\x12@\n\x15login_crypto_response\x18\n \x02(\x0b\x32!.spotify.LoginCryptoResponseUnion\x12/\n\x0cpow_response\x18\x14 \x02(\x0b\x32\x19.spotify.PoWResponseUnion\x12\x35\n\x0f\x63rypto_response\x18\x1e \x02(\x0b\x32\x1c.spotify.CryptoResponseUnion\"]\n\x18LoginCryptoResponseUnion\x12\x41\n\x0e\x64iffie_hellman\x18\n \x01(\x0b\x32).spotify.LoginCryptoDiffieHellmanResponse\"0\n LoginCryptoDiffieHellmanResponse\x12\x0c\n\x04hmac\x18\n \x02(\x0c\"C\n\x10PoWResponseUnion\x12/\n\thash_cash\x18\n \x01(\x0b\x32\x1c.spotify.PoWHashCashResponse\"*\n\x13PoWHashCashResponse\x12\x13\n\x0bhash_suffix\x18\n \x02(\x0c\"\x81\x01\n\x13\x43ryptoResponseUnion\x12/\n\x07shannon\x18\n \x01(\x0b\x32\x1e.spotify.CryptoShannonResponse\x12\x39\n\rrc4_sha1_hmac\x18\x14 \x01(\x0b\x32\".spotify.CryptoRc4Sha1HmacResponse\"&\n\x15\x43ryptoShannonResponse\x12\r\n\x05\x64ummy\x18\x01 \x01(\x05\"*\n\x19\x43ryptoRc4Sha1HmacResponse\x12\r\n\x05\x64ummy\x18\x01 \x01(\x05*\x7f\n\x07Product\x12\x12\n\x0ePRODUCT_CLIENT\x10\x00\x12\x16\n\x12PRODUCT_LIBSPOTIFY\x10\x01\x12\x12\n\x0ePRODUCT_MOBILE\x10\x02\x12\x13\n\x0fPRODUCT_PARTNER\x10\x03\x12\x1f\n\x1bPRODUCT_LIBSPOTIFY_EMBEDDED\x10\x05*A\n\x0cProductFlags\x12\x15\n\x11PRODUCT_FLAG_NONE\x10\x00\x12\x1a\n\x16PRODUCT_FLAG_DEV_BUILD\x10\x01*\xdc\x04\n\x08Platform\x12\x16\n\x12PLATFORM_WIN32_X86\x10\x00\x12\x14\n\x10PLATFORM_OSX_X86\x10\x01\x12\x16\n\x12PLATFORM_LINUX_X86\x10\x02\x12\x17\n\x13PLATFORM_IPHONE_ARM\x10\x03\x12\x14\n\x10PLATFORM_S60_ARM\x10\x04\x12\x14\n\x10PLATFORM_OSX_PPC\x10\x05\x12\x18\n\x14PLATFORM_ANDROID_ARM\x10\x06\x12\x1b\n\x17PLATFORM_WINDOWS_CE_ARM\x10\x07\x12\x19\n\x15PLATFORM_LINUX_X86_64\x10\x08\x12\x17\n\x13PLATFORM_OSX_X86_64\x10\t\x12\x15\n\x11PLATFORM_PALM_ARM\x10\n\x12\x15\n\x11PLATFORM_LINUX_SH\x10\x0b\x12\x18\n\x14PLATFORM_FREEBSD_X86\x10\x0c\x12\x1b\n\x17PLATFORM_FREEBSD_X86_64\x10\r\x12\x1b\n\x17PLATFORM_BLACKBERRY_ARM\x10\x0e\x12\x12\n\x0ePLATFORM_SONOS\x10\x0f\x12\x17\n\x13PLATFORM_LINUX_MIPS\x10\x10\x12\x16\n\x12PLATFORM_LINUX_ARM\x10\x11\x12\x19\n\x15PLATFORM_LOGITECH_ARM\x10\x12\x12\x1b\n\x17PLATFORM_LINUX_BLACKFIN\x10\x13\x12\x14\n\x10PLATFORM_WP7_ARM\x10\x14\x12\x16\n\x12PLATFORM_ONKYO_ARM\x10\x15\x12\x17\n\x13PLATFORM_QNXNTO_ARM\x10\x16\x12\x14\n\x10PLATFORM_BCO_ARM\x10\x17*A\n\x0b\x46ingerprint\x12\x15\n\x11\x46INGERPRINT_GRAIN\x10\x00\x12\x1b\n\x17\x46INGERPRINT_HMAC_RIPEMD\x10\x01*G\n\x0b\x43ryptosuite\x12\x18\n\x14\x43RYPTO_SUITE_SHANNON\x10\x00\x12\x1e\n\x1a\x43RYPTO_SUITE_RC4_SHA1_HMAC\x10\x01*\x1e\n\tPowscheme\x12\x11\n\rPOW_HASH_CASH\x10\x00*\x89\x02\n\tErrorCode\x12\x11\n\rProtocolError\x10\x00\x12\x10\n\x0cTryAnotherAP\x10\x02\x12\x13\n\x0f\x42\x61\x64\x43onnectionId\x10\x05\x12\x15\n\x11TravelRestriction\x10\t\x12\x1a\n\x16PremiumAccountRequired\x10\x0b\x12\x12\n\x0e\x42\x61\x64\x43redentials\x10\x0c\x12\x1f\n\x1b\x43ouldNotValidateCredentials\x10\r\x12\x11\n\rAccountExists\x10\x0e\x12\x1d\n\x19\x45xtraVerificationRequired\x10\x0f\x12\x11\n\rInvalidAppKey\x10\x10\x12\x15\n\x11\x41pplicationBanned\x10\x11\x42\r\n\x0b\x63om.spotify' +) + +_PRODUCT = _descriptor.EnumDescriptor( + name='Product', + full_name='spotify.Product', + filename=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + values=[ + _descriptor.EnumValueDescriptor( + name='PRODUCT_CLIENT', + index=0, + number=0, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='PRODUCT_LIBSPOTIFY', + index=1, + number=1, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='PRODUCT_MOBILE', + index=2, + number=2, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='PRODUCT_PARTNER', + index=3, + number=3, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='PRODUCT_LIBSPOTIFY_EMBEDDED', + index=4, + number=5, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + ], + containing_type=None, + serialized_options=None, + serialized_start=2871, + serialized_end=2998, +) +_sym_db.RegisterEnumDescriptor(_PRODUCT) + +Product = enum_type_wrapper.EnumTypeWrapper(_PRODUCT) +_PRODUCTFLAGS = _descriptor.EnumDescriptor( + name='ProductFlags', + full_name='spotify.ProductFlags', + filename=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + values=[ + _descriptor.EnumValueDescriptor( + name='PRODUCT_FLAG_NONE', + index=0, + number=0, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='PRODUCT_FLAG_DEV_BUILD', + index=1, + number=1, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + ], + containing_type=None, + serialized_options=None, + serialized_start=3000, + serialized_end=3065, +) +_sym_db.RegisterEnumDescriptor(_PRODUCTFLAGS) + +ProductFlags = enum_type_wrapper.EnumTypeWrapper(_PRODUCTFLAGS) +_PLATFORM = _descriptor.EnumDescriptor( + name='Platform', + full_name='spotify.Platform', + filename=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + values=[ + _descriptor.EnumValueDescriptor( + name='PLATFORM_WIN32_X86', + index=0, + number=0, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='PLATFORM_OSX_X86', + index=1, + number=1, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='PLATFORM_LINUX_X86', + index=2, + number=2, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='PLATFORM_IPHONE_ARM', + index=3, + number=3, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='PLATFORM_S60_ARM', + index=4, + number=4, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='PLATFORM_OSX_PPC', + index=5, + number=5, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='PLATFORM_ANDROID_ARM', + index=6, + number=6, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='PLATFORM_WINDOWS_CE_ARM', + index=7, + number=7, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='PLATFORM_LINUX_X86_64', + index=8, + number=8, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='PLATFORM_OSX_X86_64', + index=9, + number=9, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='PLATFORM_PALM_ARM', + index=10, + number=10, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='PLATFORM_LINUX_SH', + index=11, + number=11, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='PLATFORM_FREEBSD_X86', + index=12, + number=12, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='PLATFORM_FREEBSD_X86_64', + index=13, + number=13, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='PLATFORM_BLACKBERRY_ARM', + index=14, + number=14, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='PLATFORM_SONOS', + index=15, + number=15, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='PLATFORM_LINUX_MIPS', + index=16, + number=16, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='PLATFORM_LINUX_ARM', + index=17, + number=17, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='PLATFORM_LOGITECH_ARM', + index=18, + number=18, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='PLATFORM_LINUX_BLACKFIN', + index=19, + number=19, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='PLATFORM_WP7_ARM', + index=20, + number=20, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='PLATFORM_ONKYO_ARM', + index=21, + number=21, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='PLATFORM_QNXNTO_ARM', + index=22, + number=22, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='PLATFORM_BCO_ARM', + index=23, + number=23, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + ], + containing_type=None, + serialized_options=None, + serialized_start=3068, + serialized_end=3672, +) +_sym_db.RegisterEnumDescriptor(_PLATFORM) + +Platform = enum_type_wrapper.EnumTypeWrapper(_PLATFORM) +_FINGERPRINT = _descriptor.EnumDescriptor( + name='Fingerprint', + full_name='spotify.Fingerprint', + filename=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + values=[ + _descriptor.EnumValueDescriptor( + name='FINGERPRINT_GRAIN', + index=0, + number=0, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='FINGERPRINT_HMAC_RIPEMD', + index=1, + number=1, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + ], + containing_type=None, + serialized_options=None, + serialized_start=3674, + serialized_end=3739, +) +_sym_db.RegisterEnumDescriptor(_FINGERPRINT) + +Fingerprint = enum_type_wrapper.EnumTypeWrapper(_FINGERPRINT) +_CRYPTOSUITE = _descriptor.EnumDescriptor( + name='Cryptosuite', + full_name='spotify.Cryptosuite', + filename=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + values=[ + _descriptor.EnumValueDescriptor( + name='CRYPTO_SUITE_SHANNON', + index=0, + number=0, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='CRYPTO_SUITE_RC4_SHA1_HMAC', + index=1, + number=1, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + ], + containing_type=None, + serialized_options=None, + serialized_start=3741, + serialized_end=3812, +) +_sym_db.RegisterEnumDescriptor(_CRYPTOSUITE) + +Cryptosuite = enum_type_wrapper.EnumTypeWrapper(_CRYPTOSUITE) +_POWSCHEME = _descriptor.EnumDescriptor( + name='Powscheme', + full_name='spotify.Powscheme', + filename=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + values=[ + _descriptor.EnumValueDescriptor( + name='POW_HASH_CASH', + index=0, + number=0, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + ], + containing_type=None, + serialized_options=None, + serialized_start=3814, + serialized_end=3844, +) +_sym_db.RegisterEnumDescriptor(_POWSCHEME) + +Powscheme = enum_type_wrapper.EnumTypeWrapper(_POWSCHEME) +_ERRORCODE = _descriptor.EnumDescriptor( + name='ErrorCode', + full_name='spotify.ErrorCode', + filename=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + values=[ + _descriptor.EnumValueDescriptor( + name='ProtocolError', + index=0, + number=0, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='TryAnotherAP', + index=1, + number=2, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='BadConnectionId', + index=2, + number=5, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='TravelRestriction', + index=3, + number=9, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='PremiumAccountRequired', + index=4, + number=11, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='BadCredentials', + index=5, + number=12, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='CouldNotValidateCredentials', + index=6, + number=13, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='AccountExists', + index=7, + number=14, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='ExtraVerificationRequired', + index=8, + number=15, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='InvalidAppKey', + index=9, + number=16, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='ApplicationBanned', + index=10, + number=17, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + ], + containing_type=None, + serialized_options=None, + serialized_start=3847, + serialized_end=4112, +) +_sym_db.RegisterEnumDescriptor(_ERRORCODE) + +ErrorCode = enum_type_wrapper.EnumTypeWrapper(_ERRORCODE) +PRODUCT_CLIENT = 0 +PRODUCT_LIBSPOTIFY = 1 +PRODUCT_MOBILE = 2 +PRODUCT_PARTNER = 3 +PRODUCT_LIBSPOTIFY_EMBEDDED = 5 +PRODUCT_FLAG_NONE = 0 +PRODUCT_FLAG_DEV_BUILD = 1 +PLATFORM_WIN32_X86 = 0 +PLATFORM_OSX_X86 = 1 +PLATFORM_LINUX_X86 = 2 +PLATFORM_IPHONE_ARM = 3 +PLATFORM_S60_ARM = 4 +PLATFORM_OSX_PPC = 5 +PLATFORM_ANDROID_ARM = 6 +PLATFORM_WINDOWS_CE_ARM = 7 +PLATFORM_LINUX_X86_64 = 8 +PLATFORM_OSX_X86_64 = 9 +PLATFORM_PALM_ARM = 10 +PLATFORM_LINUX_SH = 11 +PLATFORM_FREEBSD_X86 = 12 +PLATFORM_FREEBSD_X86_64 = 13 +PLATFORM_BLACKBERRY_ARM = 14 +PLATFORM_SONOS = 15 +PLATFORM_LINUX_MIPS = 16 +PLATFORM_LINUX_ARM = 17 +PLATFORM_LOGITECH_ARM = 18 +PLATFORM_LINUX_BLACKFIN = 19 +PLATFORM_WP7_ARM = 20 +PLATFORM_ONKYO_ARM = 21 +PLATFORM_QNXNTO_ARM = 22 +PLATFORM_BCO_ARM = 23 +FINGERPRINT_GRAIN = 0 +FINGERPRINT_HMAC_RIPEMD = 1 +CRYPTO_SUITE_SHANNON = 0 +CRYPTO_SUITE_RC4_SHA1_HMAC = 1 +POW_HASH_CASH = 0 +ProtocolError = 0 +TryAnotherAP = 2 +BadConnectionId = 5 +TravelRestriction = 9 +PremiumAccountRequired = 11 +BadCredentials = 12 +CouldNotValidateCredentials = 13 +AccountExists = 14 +ExtraVerificationRequired = 15 +InvalidAppKey = 16 +ApplicationBanned = 17 + +_CLIENTHELLO = _descriptor.Descriptor( + name='ClientHello', + full_name='spotify.ClientHello', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='build_info', + full_name='spotify.ClientHello.build_info', + index=0, + number=10, + type=11, + cpp_type=10, + label=2, + has_default_value=False, + default_value=None, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='fingerprints_supported', + full_name='spotify.ClientHello.fingerprints_supported', + index=1, + number=20, + type=14, + cpp_type=8, + label=3, + has_default_value=False, + default_value=[], + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='cryptosuites_supported', + full_name='spotify.ClientHello.cryptosuites_supported', + index=2, + number=30, + type=14, + cpp_type=8, + label=3, + has_default_value=False, + default_value=[], + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='powschemes_supported', + full_name='spotify.ClientHello.powschemes_supported', + index=3, + number=40, + type=14, + cpp_type=8, + label=3, + has_default_value=False, + default_value=[], + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='login_crypto_hello', + full_name='spotify.ClientHello.login_crypto_hello', + index=4, + number=50, + type=11, + cpp_type=10, + label=2, + has_default_value=False, + default_value=None, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='client_nonce', + full_name='spotify.ClientHello.client_nonce', + index=5, + number=60, + type=12, + cpp_type=9, + label=2, + has_default_value=False, + default_value=b"", + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='padding', + full_name='spotify.ClientHello.padding', + index=6, + number=70, + type=12, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"", + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='feature_set', + full_name='spotify.ClientHello.feature_set', + index=7, + number=80, + type=11, + cpp_type=10, + label=1, + has_default_value=False, + default_value=None, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[], + serialized_start=31, + serialized_end=383, +) + +_BUILDINFO = _descriptor.Descriptor( + name='BuildInfo', + full_name='spotify.BuildInfo', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='product', + full_name='spotify.BuildInfo.product', + index=0, + number=10, + type=14, + cpp_type=8, + label=2, + has_default_value=False, + default_value=0, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='product_flags', + full_name='spotify.BuildInfo.product_flags', + index=1, + number=20, + type=14, + cpp_type=8, + label=3, + has_default_value=False, + default_value=[], + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='platform', + full_name='spotify.BuildInfo.platform', + index=2, + number=30, + type=14, + cpp_type=8, + label=2, + has_default_value=False, + default_value=0, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='version', + full_name='spotify.BuildInfo.version', + index=3, + number=40, + type=4, + cpp_type=4, + label=2, + has_default_value=False, + default_value=0, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[], + serialized_start=386, + serialized_end=532, +) + +_LOGINCRYPTOHELLOUNION = _descriptor.Descriptor( + name='LoginCryptoHelloUnion', + full_name='spotify.LoginCryptoHelloUnion', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='diffie_hellman', + full_name='spotify.LoginCryptoHelloUnion.diffie_hellman', + index=0, + number=10, + type=11, + cpp_type=10, + label=1, + has_default_value=False, + default_value=None, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[], + serialized_start=534, + serialized_end=621, +) + +_LOGINCRYPTODIFFIEHELLMANHELLO = _descriptor.Descriptor( + name='LoginCryptoDiffieHellmanHello', + full_name='spotify.LoginCryptoDiffieHellmanHello', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='gc', + full_name='spotify.LoginCryptoDiffieHellmanHello.gc', + index=0, + number=10, + type=12, + cpp_type=9, + label=2, + has_default_value=False, + default_value=b"", + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='server_keys_known', + full_name='spotify.LoginCryptoDiffieHellmanHello.server_keys_known', + index=1, + number=20, + type=13, + cpp_type=3, + label=2, + has_default_value=False, + default_value=0, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[], + serialized_start=623, + serialized_end=693, +) + +_FEATURESET = _descriptor.Descriptor( + name='FeatureSet', + full_name='spotify.FeatureSet', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='autoupdate2', + full_name='spotify.FeatureSet.autoupdate2', + index=0, + number=1, + type=8, + cpp_type=7, + label=1, + has_default_value=False, + default_value=False, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='current_location', + full_name='spotify.FeatureSet.current_location', + index=1, + number=2, + type=8, + cpp_type=7, + label=1, + has_default_value=False, + default_value=False, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[], + serialized_start=695, + serialized_end=754, +) + +_APRESPONSEMESSAGE = _descriptor.Descriptor( + name='APResponseMessage', + full_name='spotify.APResponseMessage', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='challenge', + full_name='spotify.APResponseMessage.challenge', + index=0, + number=10, + type=11, + cpp_type=10, + label=1, + has_default_value=False, + default_value=None, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='upgrade', + full_name='spotify.APResponseMessage.upgrade', + index=1, + number=20, + type=11, + cpp_type=10, + label=1, + has_default_value=False, + default_value=None, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='login_failed', + full_name='spotify.APResponseMessage.login_failed', + index=2, + number=30, + type=11, + cpp_type=10, + label=1, + has_default_value=False, + default_value=None, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[], + serialized_start=757, + serialized_end=913, +) + +_APCHALLENGE = _descriptor.Descriptor( + name='APChallenge', + full_name='spotify.APChallenge', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='login_crypto_challenge', + full_name='spotify.APChallenge.login_crypto_challenge', + index=0, + number=10, + type=11, + cpp_type=10, + label=2, + has_default_value=False, + default_value=None, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='fingerprint_challenge', + full_name='spotify.APChallenge.fingerprint_challenge', + index=1, + number=20, + type=11, + cpp_type=10, + label=2, + has_default_value=False, + default_value=None, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='pow_challenge', + full_name='spotify.APChallenge.pow_challenge', + index=2, + number=30, + type=11, + cpp_type=10, + label=2, + has_default_value=False, + default_value=None, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='crypto_challenge', + full_name='spotify.APChallenge.crypto_challenge', + index=3, + number=40, + type=11, + cpp_type=10, + label=2, + has_default_value=False, + default_value=None, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='server_nonce', + full_name='spotify.APChallenge.server_nonce', + index=4, + number=50, + type=12, + cpp_type=9, + label=2, + has_default_value=False, + default_value=b"", + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='padding', + full_name='spotify.APChallenge.padding', + index=5, + number=60, + type=12, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"", + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[], + serialized_start=916, + serialized_end=1211, +) + +_LOGINCRYPTOCHALLENGEUNION = _descriptor.Descriptor( + name='LoginCryptoChallengeUnion', + full_name='spotify.LoginCryptoChallengeUnion', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='diffie_hellman', + full_name='spotify.LoginCryptoChallengeUnion.diffie_hellman', + index=0, + number=10, + type=11, + cpp_type=10, + label=1, + has_default_value=False, + default_value=None, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[], + serialized_start=1213, + serialized_end=1308, +) + +_LOGINCRYPTODIFFIEHELLMANCHALLENGE = _descriptor.Descriptor( + name='LoginCryptoDiffieHellmanChallenge', + full_name='spotify.LoginCryptoDiffieHellmanChallenge', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='gs', + full_name='spotify.LoginCryptoDiffieHellmanChallenge.gs', + index=0, + number=10, + type=12, + cpp_type=9, + label=2, + has_default_value=False, + default_value=b"", + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='server_signature_key', + full_name= + 'spotify.LoginCryptoDiffieHellmanChallenge.server_signature_key', + index=1, + number=20, + type=5, + cpp_type=1, + label=2, + has_default_value=False, + default_value=0, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='gs_signature', + full_name='spotify.LoginCryptoDiffieHellmanChallenge.gs_signature', + index=2, + number=30, + type=12, + cpp_type=9, + label=2, + has_default_value=False, + default_value=b"", + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[], + serialized_start=1310, + serialized_end=1409, +) + +_FINGERPRINTCHALLENGEUNION = _descriptor.Descriptor( + name='FingerprintChallengeUnion', + full_name='spotify.FingerprintChallengeUnion', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='grain', + full_name='spotify.FingerprintChallengeUnion.grain', + index=0, + number=10, + type=11, + cpp_type=10, + label=1, + has_default_value=False, + default_value=None, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='hmac_ripemd', + full_name='spotify.FingerprintChallengeUnion.hmac_ripemd', + index=1, + number=20, + type=11, + cpp_type=10, + label=1, + has_default_value=False, + default_value=None, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[], + serialized_start=1412, + serialized_end=1552, +) + +_FINGERPRINTGRAINCHALLENGE = _descriptor.Descriptor( + name='FingerprintGrainChallenge', + full_name='spotify.FingerprintGrainChallenge', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='kek', + full_name='spotify.FingerprintGrainChallenge.kek', + index=0, + number=10, + type=12, + cpp_type=9, + label=2, + has_default_value=False, + default_value=b"", + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[], + serialized_start=1554, + serialized_end=1594, +) + +_FINGERPRINTHMACRIPEMDCHALLENGE = _descriptor.Descriptor( + name='FingerprintHmacRipemdChallenge', + full_name='spotify.FingerprintHmacRipemdChallenge', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='challenge', + full_name='spotify.FingerprintHmacRipemdChallenge.challenge', + index=0, + number=10, + type=12, + cpp_type=9, + label=2, + has_default_value=False, + default_value=b"", + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[], + serialized_start=1596, + serialized_end=1647, +) + +_POWCHALLENGEUNION = _descriptor.Descriptor( + name='PoWChallengeUnion', + full_name='spotify.PoWChallengeUnion', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='hash_cash', + full_name='spotify.PoWChallengeUnion.hash_cash', + index=0, + number=10, + type=11, + cpp_type=10, + label=1, + has_default_value=False, + default_value=None, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[], + serialized_start=1649, + serialized_end=1718, +) + +_POWHASHCASHCHALLENGE = _descriptor.Descriptor( + name='PoWHashCashChallenge', + full_name='spotify.PoWHashCashChallenge', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='prefix', + full_name='spotify.PoWHashCashChallenge.prefix', + index=0, + number=10, + type=12, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"", + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='length', + full_name='spotify.PoWHashCashChallenge.length', + index=1, + number=20, + type=5, + cpp_type=1, + label=1, + has_default_value=False, + default_value=0, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='target', + full_name='spotify.PoWHashCashChallenge.target', + index=2, + number=30, + type=5, + cpp_type=1, + label=1, + has_default_value=False, + default_value=0, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[], + serialized_start=1720, + serialized_end=1790, +) + +_CRYPTOCHALLENGEUNION = _descriptor.Descriptor( + name='CryptoChallengeUnion', + full_name='spotify.CryptoChallengeUnion', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='shannon', + full_name='spotify.CryptoChallengeUnion.shannon', + index=0, + number=10, + type=11, + cpp_type=10, + label=1, + has_default_value=False, + default_value=None, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='rc4_sha1_hmac', + full_name='spotify.CryptoChallengeUnion.rc4_sha1_hmac', + index=1, + number=20, + type=11, + cpp_type=10, + label=1, + has_default_value=False, + default_value=None, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[], + serialized_start=1793, + serialized_end=1925, +) + +_CRYPTOSHANNONCHALLENGE = _descriptor.Descriptor( + name='CryptoShannonChallenge', + full_name='spotify.CryptoShannonChallenge', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[], + serialized_start=1927, + serialized_end=1951, +) + +_CRYPTORC4SHA1HMACCHALLENGE = _descriptor.Descriptor( + name='CryptoRc4Sha1HmacChallenge', + full_name='spotify.CryptoRc4Sha1HmacChallenge', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[], + serialized_start=1953, + serialized_end=1981, +) + +_UPGRADEREQUIREDMESSAGE = _descriptor.Descriptor( + name='UpgradeRequiredMessage', + full_name='spotify.UpgradeRequiredMessage', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='upgrade_signed_part', + full_name='spotify.UpgradeRequiredMessage.upgrade_signed_part', + index=0, + number=10, + type=12, + cpp_type=9, + label=2, + has_default_value=False, + default_value=b"", + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='signature', + full_name='spotify.UpgradeRequiredMessage.signature', + index=1, + number=20, + type=12, + cpp_type=9, + label=2, + has_default_value=False, + default_value=b"", + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='http_suffix', + full_name='spotify.UpgradeRequiredMessage.http_suffix', + index=2, + number=30, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"".decode('utf-8'), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[], + serialized_start=1983, + serialized_end=2076, +) + +_APLOGINFAILED = _descriptor.Descriptor( + name='APLoginFailed', + full_name='spotify.APLoginFailed', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='error_code', + full_name='spotify.APLoginFailed.error_code', + index=0, + number=10, + type=14, + cpp_type=8, + label=2, + has_default_value=False, + default_value=0, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='retry_delay', + full_name='spotify.APLoginFailed.retry_delay', + index=1, + number=20, + type=5, + cpp_type=1, + label=1, + has_default_value=False, + default_value=0, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='expiry', + full_name='spotify.APLoginFailed.expiry', + index=2, + number=30, + type=5, + cpp_type=1, + label=1, + has_default_value=False, + default_value=0, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='error_description', + full_name='spotify.APLoginFailed.error_description', + index=3, + number=40, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"".decode('utf-8'), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[], + serialized_start=2078, + serialized_end=2197, +) + +_CLIENTRESPONSEPLAINTEXT = _descriptor.Descriptor( + name='ClientResponsePlaintext', + full_name='spotify.ClientResponsePlaintext', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='login_crypto_response', + full_name='spotify.ClientResponsePlaintext.login_crypto_response', + index=0, + number=10, + type=11, + cpp_type=10, + label=2, + has_default_value=False, + default_value=None, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='pow_response', + full_name='spotify.ClientResponsePlaintext.pow_response', + index=1, + number=20, + type=11, + cpp_type=10, + label=2, + has_default_value=False, + default_value=None, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='crypto_response', + full_name='spotify.ClientResponsePlaintext.crypto_response', + index=2, + number=30, + type=11, + cpp_type=10, + label=2, + has_default_value=False, + default_value=None, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[], + serialized_start=2200, + serialized_end=2395, +) + +_LOGINCRYPTORESPONSEUNION = _descriptor.Descriptor( + name='LoginCryptoResponseUnion', + full_name='spotify.LoginCryptoResponseUnion', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='diffie_hellman', + full_name='spotify.LoginCryptoResponseUnion.diffie_hellman', + index=0, + number=10, + type=11, + cpp_type=10, + label=1, + has_default_value=False, + default_value=None, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[], + serialized_start=2397, + serialized_end=2490, +) + +_LOGINCRYPTODIFFIEHELLMANRESPONSE = _descriptor.Descriptor( + name='LoginCryptoDiffieHellmanResponse', + full_name='spotify.LoginCryptoDiffieHellmanResponse', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='hmac', + full_name='spotify.LoginCryptoDiffieHellmanResponse.hmac', + index=0, + number=10, + type=12, + cpp_type=9, + label=2, + has_default_value=False, + default_value=b"", + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[], + serialized_start=2492, + serialized_end=2540, +) + +_POWRESPONSEUNION = _descriptor.Descriptor( + name='PoWResponseUnion', + full_name='spotify.PoWResponseUnion', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='hash_cash', + full_name='spotify.PoWResponseUnion.hash_cash', + index=0, + number=10, + type=11, + cpp_type=10, + label=1, + has_default_value=False, + default_value=None, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[], + serialized_start=2542, + serialized_end=2609, +) + +_POWHASHCASHRESPONSE = _descriptor.Descriptor( + name='PoWHashCashResponse', + full_name='spotify.PoWHashCashResponse', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='hash_suffix', + full_name='spotify.PoWHashCashResponse.hash_suffix', + index=0, + number=10, + type=12, + cpp_type=9, + label=2, + has_default_value=False, + default_value=b"", + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[], + serialized_start=2611, + serialized_end=2653, +) + +_CRYPTORESPONSEUNION = _descriptor.Descriptor( + name='CryptoResponseUnion', + full_name='spotify.CryptoResponseUnion', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='shannon', + full_name='spotify.CryptoResponseUnion.shannon', + index=0, + number=10, + type=11, + cpp_type=10, + label=1, + has_default_value=False, + default_value=None, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='rc4_sha1_hmac', + full_name='spotify.CryptoResponseUnion.rc4_sha1_hmac', + index=1, + number=20, + type=11, + cpp_type=10, + label=1, + has_default_value=False, + default_value=None, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[], + serialized_start=2656, + serialized_end=2785, +) + +_CRYPTOSHANNONRESPONSE = _descriptor.Descriptor( + name='CryptoShannonResponse', + full_name='spotify.CryptoShannonResponse', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='dummy', + full_name='spotify.CryptoShannonResponse.dummy', + index=0, + number=1, + type=5, + cpp_type=1, + label=1, + has_default_value=False, + default_value=0, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[], + serialized_start=2787, + serialized_end=2825, +) + +_CRYPTORC4SHA1HMACRESPONSE = _descriptor.Descriptor( + name='CryptoRc4Sha1HmacResponse', + full_name='spotify.CryptoRc4Sha1HmacResponse', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='dummy', + full_name='spotify.CryptoRc4Sha1HmacResponse.dummy', + index=0, + number=1, + type=5, + cpp_type=1, + label=1, + has_default_value=False, + default_value=0, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[], + serialized_start=2827, + serialized_end=2869, +) + +_CLIENTHELLO.fields_by_name['build_info'].message_type = _BUILDINFO +_CLIENTHELLO.fields_by_name['fingerprints_supported'].enum_type = _FINGERPRINT +_CLIENTHELLO.fields_by_name['cryptosuites_supported'].enum_type = _CRYPTOSUITE +_CLIENTHELLO.fields_by_name['powschemes_supported'].enum_type = _POWSCHEME +_CLIENTHELLO.fields_by_name[ + 'login_crypto_hello'].message_type = _LOGINCRYPTOHELLOUNION +_CLIENTHELLO.fields_by_name['feature_set'].message_type = _FEATURESET +_BUILDINFO.fields_by_name['product'].enum_type = _PRODUCT +_BUILDINFO.fields_by_name['product_flags'].enum_type = _PRODUCTFLAGS +_BUILDINFO.fields_by_name['platform'].enum_type = _PLATFORM +_LOGINCRYPTOHELLOUNION.fields_by_name[ + 'diffie_hellman'].message_type = _LOGINCRYPTODIFFIEHELLMANHELLO +_APRESPONSEMESSAGE.fields_by_name['challenge'].message_type = _APCHALLENGE +_APRESPONSEMESSAGE.fields_by_name[ + 'upgrade'].message_type = _UPGRADEREQUIREDMESSAGE +_APRESPONSEMESSAGE.fields_by_name['login_failed'].message_type = _APLOGINFAILED +_APCHALLENGE.fields_by_name[ + 'login_crypto_challenge'].message_type = _LOGINCRYPTOCHALLENGEUNION +_APCHALLENGE.fields_by_name[ + 'fingerprint_challenge'].message_type = _FINGERPRINTCHALLENGEUNION +_APCHALLENGE.fields_by_name['pow_challenge'].message_type = _POWCHALLENGEUNION +_APCHALLENGE.fields_by_name[ + 'crypto_challenge'].message_type = _CRYPTOCHALLENGEUNION +_LOGINCRYPTOCHALLENGEUNION.fields_by_name[ + 'diffie_hellman'].message_type = _LOGINCRYPTODIFFIEHELLMANCHALLENGE +_FINGERPRINTCHALLENGEUNION.fields_by_name[ + 'grain'].message_type = _FINGERPRINTGRAINCHALLENGE +_FINGERPRINTCHALLENGEUNION.fields_by_name[ + 'hmac_ripemd'].message_type = _FINGERPRINTHMACRIPEMDCHALLENGE +_POWCHALLENGEUNION.fields_by_name[ + 'hash_cash'].message_type = _POWHASHCASHCHALLENGE +_CRYPTOCHALLENGEUNION.fields_by_name[ + 'shannon'].message_type = _CRYPTOSHANNONCHALLENGE +_CRYPTOCHALLENGEUNION.fields_by_name[ + 'rc4_sha1_hmac'].message_type = _CRYPTORC4SHA1HMACCHALLENGE +_APLOGINFAILED.fields_by_name['error_code'].enum_type = _ERRORCODE +_CLIENTRESPONSEPLAINTEXT.fields_by_name[ + 'login_crypto_response'].message_type = _LOGINCRYPTORESPONSEUNION +_CLIENTRESPONSEPLAINTEXT.fields_by_name[ + 'pow_response'].message_type = _POWRESPONSEUNION +_CLIENTRESPONSEPLAINTEXT.fields_by_name[ + 'crypto_response'].message_type = _CRYPTORESPONSEUNION +_LOGINCRYPTORESPONSEUNION.fields_by_name[ + 'diffie_hellman'].message_type = _LOGINCRYPTODIFFIEHELLMANRESPONSE +_POWRESPONSEUNION.fields_by_name[ + 'hash_cash'].message_type = _POWHASHCASHRESPONSE +_CRYPTORESPONSEUNION.fields_by_name[ + 'shannon'].message_type = _CRYPTOSHANNONRESPONSE +_CRYPTORESPONSEUNION.fields_by_name[ + 'rc4_sha1_hmac'].message_type = _CRYPTORC4SHA1HMACRESPONSE +DESCRIPTOR.message_types_by_name['ClientHello'] = _CLIENTHELLO +DESCRIPTOR.message_types_by_name['BuildInfo'] = _BUILDINFO +DESCRIPTOR.message_types_by_name[ + 'LoginCryptoHelloUnion'] = _LOGINCRYPTOHELLOUNION +DESCRIPTOR.message_types_by_name[ + 'LoginCryptoDiffieHellmanHello'] = _LOGINCRYPTODIFFIEHELLMANHELLO +DESCRIPTOR.message_types_by_name['FeatureSet'] = _FEATURESET +DESCRIPTOR.message_types_by_name['APResponseMessage'] = _APRESPONSEMESSAGE +DESCRIPTOR.message_types_by_name['APChallenge'] = _APCHALLENGE +DESCRIPTOR.message_types_by_name[ + 'LoginCryptoChallengeUnion'] = _LOGINCRYPTOCHALLENGEUNION +DESCRIPTOR.message_types_by_name[ + 'LoginCryptoDiffieHellmanChallenge'] = _LOGINCRYPTODIFFIEHELLMANCHALLENGE +DESCRIPTOR.message_types_by_name[ + 'FingerprintChallengeUnion'] = _FINGERPRINTCHALLENGEUNION +DESCRIPTOR.message_types_by_name[ + 'FingerprintGrainChallenge'] = _FINGERPRINTGRAINCHALLENGE +DESCRIPTOR.message_types_by_name[ + 'FingerprintHmacRipemdChallenge'] = _FINGERPRINTHMACRIPEMDCHALLENGE +DESCRIPTOR.message_types_by_name['PoWChallengeUnion'] = _POWCHALLENGEUNION +DESCRIPTOR.message_types_by_name[ + 'PoWHashCashChallenge'] = _POWHASHCASHCHALLENGE +DESCRIPTOR.message_types_by_name[ + 'CryptoChallengeUnion'] = _CRYPTOCHALLENGEUNION +DESCRIPTOR.message_types_by_name[ + 'CryptoShannonChallenge'] = _CRYPTOSHANNONCHALLENGE +DESCRIPTOR.message_types_by_name[ + 'CryptoRc4Sha1HmacChallenge'] = _CRYPTORC4SHA1HMACCHALLENGE +DESCRIPTOR.message_types_by_name[ + 'UpgradeRequiredMessage'] = _UPGRADEREQUIREDMESSAGE +DESCRIPTOR.message_types_by_name['APLoginFailed'] = _APLOGINFAILED +DESCRIPTOR.message_types_by_name[ + 'ClientResponsePlaintext'] = _CLIENTRESPONSEPLAINTEXT +DESCRIPTOR.message_types_by_name[ + 'LoginCryptoResponseUnion'] = _LOGINCRYPTORESPONSEUNION +DESCRIPTOR.message_types_by_name[ + 'LoginCryptoDiffieHellmanResponse'] = _LOGINCRYPTODIFFIEHELLMANRESPONSE +DESCRIPTOR.message_types_by_name['PoWResponseUnion'] = _POWRESPONSEUNION +DESCRIPTOR.message_types_by_name['PoWHashCashResponse'] = _POWHASHCASHRESPONSE +DESCRIPTOR.message_types_by_name['CryptoResponseUnion'] = _CRYPTORESPONSEUNION +DESCRIPTOR.message_types_by_name[ + 'CryptoShannonResponse'] = _CRYPTOSHANNONRESPONSE +DESCRIPTOR.message_types_by_name[ + 'CryptoRc4Sha1HmacResponse'] = _CRYPTORC4SHA1HMACRESPONSE +DESCRIPTOR.enum_types_by_name['Product'] = _PRODUCT +DESCRIPTOR.enum_types_by_name['ProductFlags'] = _PRODUCTFLAGS +DESCRIPTOR.enum_types_by_name['Platform'] = _PLATFORM +DESCRIPTOR.enum_types_by_name['Fingerprint'] = _FINGERPRINT +DESCRIPTOR.enum_types_by_name['Cryptosuite'] = _CRYPTOSUITE +DESCRIPTOR.enum_types_by_name['Powscheme'] = _POWSCHEME +DESCRIPTOR.enum_types_by_name['ErrorCode'] = _ERRORCODE +_sym_db.RegisterFileDescriptor(DESCRIPTOR) + +ClientHello = _reflection.GeneratedProtocolMessageType( + 'ClientHello', + (_message.Message, ), + { + 'DESCRIPTOR': _CLIENTHELLO, + '__module__': 'keyexchange_pb2' + # @@protoc_insertion_point(class_scope:spotify.ClientHello) + }) +_sym_db.RegisterMessage(ClientHello) + +BuildInfo = _reflection.GeneratedProtocolMessageType( + 'BuildInfo', + (_message.Message, ), + { + 'DESCRIPTOR': _BUILDINFO, + '__module__': 'keyexchange_pb2' + # @@protoc_insertion_point(class_scope:spotify.BuildInfo) + }) +_sym_db.RegisterMessage(BuildInfo) + +LoginCryptoHelloUnion = _reflection.GeneratedProtocolMessageType( + 'LoginCryptoHelloUnion', + (_message.Message, ), + { + 'DESCRIPTOR': _LOGINCRYPTOHELLOUNION, + '__module__': 'keyexchange_pb2' + # @@protoc_insertion_point(class_scope:spotify.LoginCryptoHelloUnion) + }) +_sym_db.RegisterMessage(LoginCryptoHelloUnion) + +LoginCryptoDiffieHellmanHello = _reflection.GeneratedProtocolMessageType( + 'LoginCryptoDiffieHellmanHello', + (_message.Message, ), + { + 'DESCRIPTOR': _LOGINCRYPTODIFFIEHELLMANHELLO, + '__module__': 'keyexchange_pb2' + # @@protoc_insertion_point(class_scope:spotify.LoginCryptoDiffieHellmanHello) + }) +_sym_db.RegisterMessage(LoginCryptoDiffieHellmanHello) + +FeatureSet = _reflection.GeneratedProtocolMessageType( + 'FeatureSet', + (_message.Message, ), + { + 'DESCRIPTOR': _FEATURESET, + '__module__': 'keyexchange_pb2' + # @@protoc_insertion_point(class_scope:spotify.FeatureSet) + }) +_sym_db.RegisterMessage(FeatureSet) + +APResponseMessage = _reflection.GeneratedProtocolMessageType( + 'APResponseMessage', + (_message.Message, ), + { + 'DESCRIPTOR': _APRESPONSEMESSAGE, + '__module__': 'keyexchange_pb2' + # @@protoc_insertion_point(class_scope:spotify.APResponseMessage) + }) +_sym_db.RegisterMessage(APResponseMessage) + +APChallenge = _reflection.GeneratedProtocolMessageType( + 'APChallenge', + (_message.Message, ), + { + 'DESCRIPTOR': _APCHALLENGE, + '__module__': 'keyexchange_pb2' + # @@protoc_insertion_point(class_scope:spotify.APChallenge) + }) +_sym_db.RegisterMessage(APChallenge) + +LoginCryptoChallengeUnion = _reflection.GeneratedProtocolMessageType( + 'LoginCryptoChallengeUnion', + (_message.Message, ), + { + 'DESCRIPTOR': _LOGINCRYPTOCHALLENGEUNION, + '__module__': 'keyexchange_pb2' + # @@protoc_insertion_point(class_scope:spotify.LoginCryptoChallengeUnion) + }) +_sym_db.RegisterMessage(LoginCryptoChallengeUnion) + +LoginCryptoDiffieHellmanChallenge = _reflection.GeneratedProtocolMessageType( + 'LoginCryptoDiffieHellmanChallenge', + (_message.Message, ), + { + 'DESCRIPTOR': _LOGINCRYPTODIFFIEHELLMANCHALLENGE, + '__module__': 'keyexchange_pb2' + # @@protoc_insertion_point(class_scope:spotify.LoginCryptoDiffieHellmanChallenge) + }) +_sym_db.RegisterMessage(LoginCryptoDiffieHellmanChallenge) + +FingerprintChallengeUnion = _reflection.GeneratedProtocolMessageType( + 'FingerprintChallengeUnion', + (_message.Message, ), + { + 'DESCRIPTOR': _FINGERPRINTCHALLENGEUNION, + '__module__': 'keyexchange_pb2' + # @@protoc_insertion_point(class_scope:spotify.FingerprintChallengeUnion) + }) +_sym_db.RegisterMessage(FingerprintChallengeUnion) + +FingerprintGrainChallenge = _reflection.GeneratedProtocolMessageType( + 'FingerprintGrainChallenge', + (_message.Message, ), + { + 'DESCRIPTOR': _FINGERPRINTGRAINCHALLENGE, + '__module__': 'keyexchange_pb2' + # @@protoc_insertion_point(class_scope:spotify.FingerprintGrainChallenge) + }) +_sym_db.RegisterMessage(FingerprintGrainChallenge) + +FingerprintHmacRipemdChallenge = _reflection.GeneratedProtocolMessageType( + 'FingerprintHmacRipemdChallenge', + (_message.Message, ), + { + 'DESCRIPTOR': _FINGERPRINTHMACRIPEMDCHALLENGE, + '__module__': 'keyexchange_pb2' + # @@protoc_insertion_point(class_scope:spotify.FingerprintHmacRipemdChallenge) + }) +_sym_db.RegisterMessage(FingerprintHmacRipemdChallenge) + +PoWChallengeUnion = _reflection.GeneratedProtocolMessageType( + 'PoWChallengeUnion', + (_message.Message, ), + { + 'DESCRIPTOR': _POWCHALLENGEUNION, + '__module__': 'keyexchange_pb2' + # @@protoc_insertion_point(class_scope:spotify.PoWChallengeUnion) + }) +_sym_db.RegisterMessage(PoWChallengeUnion) + +PoWHashCashChallenge = _reflection.GeneratedProtocolMessageType( + 'PoWHashCashChallenge', + (_message.Message, ), + { + 'DESCRIPTOR': _POWHASHCASHCHALLENGE, + '__module__': 'keyexchange_pb2' + # @@protoc_insertion_point(class_scope:spotify.PoWHashCashChallenge) + }) +_sym_db.RegisterMessage(PoWHashCashChallenge) + +CryptoChallengeUnion = _reflection.GeneratedProtocolMessageType( + 'CryptoChallengeUnion', + (_message.Message, ), + { + 'DESCRIPTOR': _CRYPTOCHALLENGEUNION, + '__module__': 'keyexchange_pb2' + # @@protoc_insertion_point(class_scope:spotify.CryptoChallengeUnion) + }) +_sym_db.RegisterMessage(CryptoChallengeUnion) + +CryptoShannonChallenge = _reflection.GeneratedProtocolMessageType( + 'CryptoShannonChallenge', + (_message.Message, ), + { + 'DESCRIPTOR': _CRYPTOSHANNONCHALLENGE, + '__module__': 'keyexchange_pb2' + # @@protoc_insertion_point(class_scope:spotify.CryptoShannonChallenge) + }) +_sym_db.RegisterMessage(CryptoShannonChallenge) + +CryptoRc4Sha1HmacChallenge = _reflection.GeneratedProtocolMessageType( + 'CryptoRc4Sha1HmacChallenge', + (_message.Message, ), + { + 'DESCRIPTOR': _CRYPTORC4SHA1HMACCHALLENGE, + '__module__': 'keyexchange_pb2' + # @@protoc_insertion_point(class_scope:spotify.CryptoRc4Sha1HmacChallenge) + }) +_sym_db.RegisterMessage(CryptoRc4Sha1HmacChallenge) + +UpgradeRequiredMessage = _reflection.GeneratedProtocolMessageType( + 'UpgradeRequiredMessage', + (_message.Message, ), + { + 'DESCRIPTOR': _UPGRADEREQUIREDMESSAGE, + '__module__': 'keyexchange_pb2' + # @@protoc_insertion_point(class_scope:spotify.UpgradeRequiredMessage) + }) +_sym_db.RegisterMessage(UpgradeRequiredMessage) + +APLoginFailed = _reflection.GeneratedProtocolMessageType( + 'APLoginFailed', + (_message.Message, ), + { + 'DESCRIPTOR': _APLOGINFAILED, + '__module__': 'keyexchange_pb2' + # @@protoc_insertion_point(class_scope:spotify.APLoginFailed) + }) +_sym_db.RegisterMessage(APLoginFailed) + +ClientResponsePlaintext = _reflection.GeneratedProtocolMessageType( + 'ClientResponsePlaintext', + (_message.Message, ), + { + 'DESCRIPTOR': _CLIENTRESPONSEPLAINTEXT, + '__module__': 'keyexchange_pb2' + # @@protoc_insertion_point(class_scope:spotify.ClientResponsePlaintext) + }) +_sym_db.RegisterMessage(ClientResponsePlaintext) + +LoginCryptoResponseUnion = _reflection.GeneratedProtocolMessageType( + 'LoginCryptoResponseUnion', + (_message.Message, ), + { + 'DESCRIPTOR': _LOGINCRYPTORESPONSEUNION, + '__module__': 'keyexchange_pb2' + # @@protoc_insertion_point(class_scope:spotify.LoginCryptoResponseUnion) + }) +_sym_db.RegisterMessage(LoginCryptoResponseUnion) + +LoginCryptoDiffieHellmanResponse = _reflection.GeneratedProtocolMessageType( + 'LoginCryptoDiffieHellmanResponse', + (_message.Message, ), + { + 'DESCRIPTOR': _LOGINCRYPTODIFFIEHELLMANRESPONSE, + '__module__': 'keyexchange_pb2' + # @@protoc_insertion_point(class_scope:spotify.LoginCryptoDiffieHellmanResponse) + }) +_sym_db.RegisterMessage(LoginCryptoDiffieHellmanResponse) + +PoWResponseUnion = _reflection.GeneratedProtocolMessageType( + 'PoWResponseUnion', + (_message.Message, ), + { + 'DESCRIPTOR': _POWRESPONSEUNION, + '__module__': 'keyexchange_pb2' + # @@protoc_insertion_point(class_scope:spotify.PoWResponseUnion) + }) +_sym_db.RegisterMessage(PoWResponseUnion) + +PoWHashCashResponse = _reflection.GeneratedProtocolMessageType( + 'PoWHashCashResponse', + (_message.Message, ), + { + 'DESCRIPTOR': _POWHASHCASHRESPONSE, + '__module__': 'keyexchange_pb2' + # @@protoc_insertion_point(class_scope:spotify.PoWHashCashResponse) + }) +_sym_db.RegisterMessage(PoWHashCashResponse) + +CryptoResponseUnion = _reflection.GeneratedProtocolMessageType( + 'CryptoResponseUnion', + (_message.Message, ), + { + 'DESCRIPTOR': _CRYPTORESPONSEUNION, + '__module__': 'keyexchange_pb2' + # @@protoc_insertion_point(class_scope:spotify.CryptoResponseUnion) + }) +_sym_db.RegisterMessage(CryptoResponseUnion) + +CryptoShannonResponse = _reflection.GeneratedProtocolMessageType( + 'CryptoShannonResponse', + (_message.Message, ), + { + 'DESCRIPTOR': _CRYPTOSHANNONRESPONSE, + '__module__': 'keyexchange_pb2' + # @@protoc_insertion_point(class_scope:spotify.CryptoShannonResponse) + }) +_sym_db.RegisterMessage(CryptoShannonResponse) + +CryptoRc4Sha1HmacResponse = _reflection.GeneratedProtocolMessageType( + 'CryptoRc4Sha1HmacResponse', + (_message.Message, ), + { + 'DESCRIPTOR': _CRYPTORC4SHA1HMACRESPONSE, + '__module__': 'keyexchange_pb2' + # @@protoc_insertion_point(class_scope:spotify.CryptoRc4Sha1HmacResponse) + }) +_sym_db.RegisterMessage(CryptoRc4Sha1HmacResponse) + +DESCRIPTOR._options = None +# @@protoc_insertion_point(module_scope) diff --git a/librespot/proto/Mercury_pb2.py b/librespot/proto/Mercury_pb2.py new file mode 100644 index 0000000..8109c9f --- /dev/null +++ b/librespot/proto/Mercury_pb2.py @@ -0,0 +1,625 @@ +# -*- coding: utf-8 -*- +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: mercury.proto +"""Generated protocol buffer code.""" +from google.protobuf import descriptor as _descriptor +from google.protobuf import message as _message +from google.protobuf import reflection as _reflection +from google.protobuf import symbol_database as _symbol_database +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + +DESCRIPTOR = _descriptor.FileDescriptor( + name='mercury.proto', + package='spotify', + syntax='proto2', + serialized_options=b'\n\013com.spotify', + create_key=_descriptor._internal_create_key, + serialized_pb= + b'\n\rmercury.proto\x12\x07spotify\"B\n\x16MercuryMultiGetRequest\x12(\n\x07request\x18\x01 \x03(\x0b\x32\x17.spotify.MercuryRequest\"<\n\x14MercuryMultiGetReply\x12$\n\x05reply\x18\x01 \x03(\x0b\x32\x15.spotify.MercuryReply\"O\n\x0eMercuryRequest\x12\x0b\n\x03uri\x18\x01 \x01(\t\x12\x14\n\x0c\x63ontent_type\x18\x02 \x01(\t\x12\x0c\n\x04\x62ody\x18\x03 \x01(\x0c\x12\x0c\n\x04\x65tag\x18\x04 \x01(\x0c\"\xf5\x01\n\x0cMercuryReply\x12\x13\n\x0bstatus_code\x18\x01 \x01(\x11\x12\x16\n\x0estatus_message\x18\x02 \x01(\t\x12\x37\n\x0c\x63\x61\x63he_policy\x18\x03 \x01(\x0e\x32!.spotify.MercuryReply.CachePolicy\x12\x0b\n\x03ttl\x18\x04 \x01(\x11\x12\x0c\n\x04\x65tag\x18\x05 \x01(\x0c\x12\x14\n\x0c\x63ontent_type\x18\x06 \x01(\t\x12\x0c\n\x04\x62ody\x18\x07 \x01(\x0c\"@\n\x0b\x43\x61\x63hePolicy\x12\x0c\n\x08\x43\x41\x43HE_NO\x10\x01\x12\x11\n\rCACHE_PRIVATE\x10\x02\x12\x10\n\x0c\x43\x41\x43HE_PUBLIC\x10\x03\"y\n\x06Header\x12\x0b\n\x03uri\x18\x01 \x01(\t\x12\x14\n\x0c\x63ontent_type\x18\x02 \x01(\t\x12\x0e\n\x06method\x18\x03 \x01(\t\x12\x13\n\x0bstatus_code\x18\x04 \x01(\x11\x12\'\n\x0buser_fields\x18\x06 \x03(\x0b\x32\x12.spotify.UserField\"\'\n\tUserField\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\x0c\x42\r\n\x0b\x63om.spotify' +) + +_MERCURYREPLY_CACHEPOLICY = _descriptor.EnumDescriptor( + name='CachePolicy', + full_name='spotify.MercuryReply.CachePolicy', + filename=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + values=[ + _descriptor.EnumValueDescriptor( + name='CACHE_NO', + index=0, + number=1, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='CACHE_PRIVATE', + index=1, + number=2, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='CACHE_PUBLIC', + index=2, + number=3, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + ], + containing_type=None, + serialized_options=None, + serialized_start=419, + serialized_end=483, +) +_sym_db.RegisterEnumDescriptor(_MERCURYREPLY_CACHEPOLICY) + +_MERCURYMULTIGETREQUEST = _descriptor.Descriptor( + name='MercuryMultiGetRequest', + full_name='spotify.MercuryMultiGetRequest', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='request', + full_name='spotify.MercuryMultiGetRequest.request', + index=0, + number=1, + type=11, + cpp_type=10, + label=3, + has_default_value=False, + default_value=[], + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[], + serialized_start=26, + serialized_end=92, +) + +_MERCURYMULTIGETREPLY = _descriptor.Descriptor( + name='MercuryMultiGetReply', + full_name='spotify.MercuryMultiGetReply', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='reply', + full_name='spotify.MercuryMultiGetReply.reply', + index=0, + number=1, + type=11, + cpp_type=10, + label=3, + has_default_value=False, + default_value=[], + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[], + serialized_start=94, + serialized_end=154, +) + +_MERCURYREQUEST = _descriptor.Descriptor( + name='MercuryRequest', + full_name='spotify.MercuryRequest', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='uri', + full_name='spotify.MercuryRequest.uri', + index=0, + number=1, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"".decode('utf-8'), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='content_type', + full_name='spotify.MercuryRequest.content_type', + index=1, + number=2, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"".decode('utf-8'), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='body', + full_name='spotify.MercuryRequest.body', + index=2, + number=3, + type=12, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"", + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='etag', + full_name='spotify.MercuryRequest.etag', + index=3, + number=4, + type=12, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"", + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[], + serialized_start=156, + serialized_end=235, +) + +_MERCURYREPLY = _descriptor.Descriptor( + name='MercuryReply', + full_name='spotify.MercuryReply', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='status_code', + full_name='spotify.MercuryReply.status_code', + index=0, + number=1, + type=17, + cpp_type=1, + label=1, + has_default_value=False, + default_value=0, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='status_message', + full_name='spotify.MercuryReply.status_message', + index=1, + number=2, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"".decode('utf-8'), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='cache_policy', + full_name='spotify.MercuryReply.cache_policy', + index=2, + number=3, + type=14, + cpp_type=8, + label=1, + has_default_value=False, + default_value=1, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='ttl', + full_name='spotify.MercuryReply.ttl', + index=3, + number=4, + type=17, + cpp_type=1, + label=1, + has_default_value=False, + default_value=0, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='etag', + full_name='spotify.MercuryReply.etag', + index=4, + number=5, + type=12, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"", + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='content_type', + full_name='spotify.MercuryReply.content_type', + index=5, + number=6, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"".decode('utf-8'), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='body', + full_name='spotify.MercuryReply.body', + index=6, + number=7, + type=12, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"", + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + ], + extensions=[], + nested_types=[], + enum_types=[ + _MERCURYREPLY_CACHEPOLICY, + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[], + serialized_start=238, + serialized_end=483, +) + +_HEADER = _descriptor.Descriptor( + name='Header', + full_name='spotify.Header', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='uri', + full_name='spotify.Header.uri', + index=0, + number=1, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"".decode('utf-8'), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='content_type', + full_name='spotify.Header.content_type', + index=1, + number=2, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"".decode('utf-8'), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='method', + full_name='spotify.Header.method', + index=2, + number=3, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"".decode('utf-8'), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='status_code', + full_name='spotify.Header.status_code', + index=3, + number=4, + type=17, + cpp_type=1, + label=1, + has_default_value=False, + default_value=0, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='user_fields', + full_name='spotify.Header.user_fields', + index=4, + number=6, + type=11, + cpp_type=10, + label=3, + has_default_value=False, + default_value=[], + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[], + serialized_start=485, + serialized_end=606, +) + +_USERFIELD = _descriptor.Descriptor( + name='UserField', + full_name='spotify.UserField', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='key', + full_name='spotify.UserField.key', + index=0, + number=1, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"".decode('utf-8'), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='value', + full_name='spotify.UserField.value', + index=1, + number=2, + type=12, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"", + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[], + serialized_start=608, + serialized_end=647, +) + +_MERCURYMULTIGETREQUEST.fields_by_name[ + 'request'].message_type = _MERCURYREQUEST +_MERCURYMULTIGETREPLY.fields_by_name['reply'].message_type = _MERCURYREPLY +_MERCURYREPLY.fields_by_name[ + 'cache_policy'].enum_type = _MERCURYREPLY_CACHEPOLICY +_MERCURYREPLY_CACHEPOLICY.containing_type = _MERCURYREPLY +_HEADER.fields_by_name['user_fields'].message_type = _USERFIELD +DESCRIPTOR.message_types_by_name[ + 'MercuryMultiGetRequest'] = _MERCURYMULTIGETREQUEST +DESCRIPTOR.message_types_by_name[ + 'MercuryMultiGetReply'] = _MERCURYMULTIGETREPLY +DESCRIPTOR.message_types_by_name['MercuryRequest'] = _MERCURYREQUEST +DESCRIPTOR.message_types_by_name['MercuryReply'] = _MERCURYREPLY +DESCRIPTOR.message_types_by_name['Header'] = _HEADER +DESCRIPTOR.message_types_by_name['UserField'] = _USERFIELD +_sym_db.RegisterFileDescriptor(DESCRIPTOR) + +MercuryMultiGetRequest = _reflection.GeneratedProtocolMessageType( + 'MercuryMultiGetRequest', + (_message.Message, ), + { + 'DESCRIPTOR': _MERCURYMULTIGETREQUEST, + '__module__': 'mercury_pb2' + # @@protoc_insertion_point(class_scope:spotify.MercuryMultiGetRequest) + }) +_sym_db.RegisterMessage(MercuryMultiGetRequest) + +MercuryMultiGetReply = _reflection.GeneratedProtocolMessageType( + 'MercuryMultiGetReply', + (_message.Message, ), + { + 'DESCRIPTOR': _MERCURYMULTIGETREPLY, + '__module__': 'mercury_pb2' + # @@protoc_insertion_point(class_scope:spotify.MercuryMultiGetReply) + }) +_sym_db.RegisterMessage(MercuryMultiGetReply) + +MercuryRequest = _reflection.GeneratedProtocolMessageType( + 'MercuryRequest', + (_message.Message, ), + { + 'DESCRIPTOR': _MERCURYREQUEST, + '__module__': 'mercury_pb2' + # @@protoc_insertion_point(class_scope:spotify.MercuryRequest) + }) +_sym_db.RegisterMessage(MercuryRequest) + +MercuryReply = _reflection.GeneratedProtocolMessageType( + 'MercuryReply', + (_message.Message, ), + { + 'DESCRIPTOR': _MERCURYREPLY, + '__module__': 'mercury_pb2' + # @@protoc_insertion_point(class_scope:spotify.MercuryReply) + }) +_sym_db.RegisterMessage(MercuryReply) + +Header = _reflection.GeneratedProtocolMessageType( + 'Header', + (_message.Message, ), + { + 'DESCRIPTOR': _HEADER, + '__module__': 'mercury_pb2' + # @@protoc_insertion_point(class_scope:spotify.Header) + }) +_sym_db.RegisterMessage(Header) + +UserField = _reflection.GeneratedProtocolMessageType( + 'UserField', + (_message.Message, ), + { + 'DESCRIPTOR': _USERFIELD, + '__module__': 'mercury_pb2' + # @@protoc_insertion_point(class_scope:spotify.UserField) + }) +_sym_db.RegisterMessage(UserField) + +DESCRIPTOR._options = None +# @@protoc_insertion_point(module_scope) diff --git a/librespot/proto/Metadata_pb2.py b/librespot/proto/Metadata_pb2.py new file mode 100644 index 0000000..e8ac38c --- /dev/null +++ b/librespot/proto/Metadata_pb2.py @@ -0,0 +1,3698 @@ +# -*- coding: utf-8 -*- +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: metadata.proto +"""Generated protocol buffer code.""" +from google.protobuf import descriptor as _descriptor +from google.protobuf import message as _message +from google.protobuf import reflection as _reflection +from google.protobuf import symbol_database as _symbol_database +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + +DESCRIPTOR = _descriptor.FileDescriptor( + name='metadata.proto', + package='spotify.metadata.proto', + syntax='proto2', + serialized_options=b'\n\024com.spotify.metadataB\010MetadataH\002', + create_key=_descriptor._internal_create_key, + serialized_pb= + b'\n\x0emetadata.proto\x12\x16spotify.metadata.proto\"\x8a\x07\n\x06\x41rtist\x12\x0b\n\x03gid\x18\x01 \x01(\x0c\x12\x0c\n\x04name\x18\x02 \x01(\t\x12\x12\n\npopularity\x18\x03 \x01(\x11\x12\x34\n\ttop_track\x18\x04 \x03(\x0b\x32!.spotify.metadata.proto.TopTracks\x12\x37\n\x0b\x61lbum_group\x18\x05 \x03(\x0b\x32\".spotify.metadata.proto.AlbumGroup\x12\x38\n\x0csingle_group\x18\x06 \x03(\x0b\x32\".spotify.metadata.proto.AlbumGroup\x12=\n\x11\x63ompilation_group\x18\x07 \x03(\x0b\x32\".spotify.metadata.proto.AlbumGroup\x12<\n\x10\x61ppears_on_group\x18\x08 \x03(\x0b\x32\".spotify.metadata.proto.AlbumGroup\x12\r\n\x05genre\x18\t \x03(\t\x12\x37\n\x0b\x65xternal_id\x18\n \x03(\x0b\x32\".spotify.metadata.proto.ExternalId\x12/\n\x08portrait\x18\x0b \x03(\x0b\x32\x1d.spotify.metadata.proto.Image\x12\x34\n\tbiography\x18\x0c \x03(\x0b\x32!.spotify.metadata.proto.Biography\x12?\n\x0f\x61\x63tivity_period\x18\r \x03(\x0b\x32&.spotify.metadata.proto.ActivityPeriod\x12\x38\n\x0brestriction\x18\x0e \x03(\x0b\x32#.spotify.metadata.proto.Restriction\x12/\n\x07related\x18\x0f \x03(\x0b\x32\x1e.spotify.metadata.proto.Artist\x12\x1f\n\x17is_portrait_album_cover\x18\x10 \x01(\x08\x12:\n\x0eportrait_group\x18\x11 \x01(\x0b\x32\".spotify.metadata.proto.ImageGroup\x12\x37\n\x0bsale_period\x18\x12 \x03(\x0b\x32\".spotify.metadata.proto.SalePeriod\x12:\n\x0c\x61vailability\x18\x14 \x03(\x0b\x32$.spotify.metadata.proto.Availability\"\xe8\x06\n\x05\x41lbum\x12\x0b\n\x03gid\x18\x01 \x01(\x0c\x12\x0c\n\x04name\x18\x02 \x01(\t\x12.\n\x06\x61rtist\x18\x03 \x03(\x0b\x32\x1e.spotify.metadata.proto.Artist\x12\x30\n\x04type\x18\x04 \x01(\x0e\x32\".spotify.metadata.proto.Album.Type\x12\r\n\x05label\x18\x05 \x01(\t\x12*\n\x04\x64\x61te\x18\x06 \x01(\x0b\x32\x1c.spotify.metadata.proto.Date\x12\x12\n\npopularity\x18\x07 \x01(\x11\x12\r\n\x05genre\x18\x08 \x03(\t\x12,\n\x05\x63over\x18\t \x03(\x0b\x32\x1d.spotify.metadata.proto.Image\x12\x37\n\x0b\x65xternal_id\x18\n \x03(\x0b\x32\".spotify.metadata.proto.ExternalId\x12*\n\x04\x64isc\x18\x0b \x03(\x0b\x32\x1c.spotify.metadata.proto.Disc\x12\x0e\n\x06review\x18\x0c \x03(\t\x12\x34\n\tcopyright\x18\r \x03(\x0b\x32!.spotify.metadata.proto.Copyright\x12\x38\n\x0brestriction\x18\x0e \x03(\x0b\x32#.spotify.metadata.proto.Restriction\x12.\n\x07related\x18\x0f \x03(\x0b\x32\x1d.spotify.metadata.proto.Album\x12\x37\n\x0bsale_period\x18\x10 \x03(\x0b\x32\".spotify.metadata.proto.SalePeriod\x12\x37\n\x0b\x63over_group\x18\x11 \x01(\x0b\x32\".spotify.metadata.proto.ImageGroup\x12\x16\n\x0eoriginal_title\x18\x12 \x01(\t\x12\x15\n\rversion_title\x18\x13 \x01(\t\x12\x10\n\x08type_str\x18\x14 \x01(\t\x12:\n\x0c\x61vailability\x18\x17 \x03(\x0b\x32$.spotify.metadata.proto.Availability\"R\n\x04Type\x12\t\n\x05\x41LBUM\x10\x01\x12\n\n\x06SINGLE\x10\x02\x12\x0f\n\x0b\x43OMPILATION\x10\x03\x12\x06\n\x02\x45P\x10\x04\x12\r\n\tAUDIOBOOK\x10\x05\x12\x0b\n\x07PODCAST\x10\x06\"\xd5\x05\n\x05Track\x12\x0b\n\x03gid\x18\x01 \x01(\x0c\x12\x0c\n\x04name\x18\x02 \x01(\t\x12,\n\x05\x61lbum\x18\x03 \x01(\x0b\x32\x1d.spotify.metadata.proto.Album\x12.\n\x06\x61rtist\x18\x04 \x03(\x0b\x32\x1e.spotify.metadata.proto.Artist\x12\x0e\n\x06number\x18\x05 \x01(\x11\x12\x13\n\x0b\x64isc_number\x18\x06 \x01(\x11\x12\x10\n\x08\x64uration\x18\x07 \x01(\x11\x12\x12\n\npopularity\x18\x08 \x01(\x11\x12\x10\n\x08\x65xplicit\x18\t \x01(\x08\x12\x37\n\x0b\x65xternal_id\x18\n \x03(\x0b\x32\".spotify.metadata.proto.ExternalId\x12\x38\n\x0brestriction\x18\x0b \x03(\x0b\x32#.spotify.metadata.proto.Restriction\x12/\n\x04\x66ile\x18\x0c \x03(\x0b\x32!.spotify.metadata.proto.AudioFile\x12\x32\n\x0b\x61lternative\x18\r \x03(\x0b\x32\x1d.spotify.metadata.proto.Track\x12\x37\n\x0bsale_period\x18\x0e \x03(\x0b\x32\".spotify.metadata.proto.SalePeriod\x12\x32\n\x07preview\x18\x0f \x03(\x0b\x32!.spotify.metadata.proto.AudioFile\x12\x0c\n\x04tags\x18\x10 \x03(\t\x12\x1f\n\x17\x65\x61rliest_live_timestamp\x18\x11 \x01(\x03\x12\x12\n\nhas_lyrics\x18\x12 \x01(\x08\x12:\n\x0c\x61vailability\x18\x13 \x03(\x0b\x32$.spotify.metadata.proto.Availability\x12\x32\n\x08licensor\x18\x15 \x01(\x0b\x32 .spotify.metadata.proto.Licensor\"\xbf\x05\n\x04Show\x12\x0b\n\x03gid\x18\x01 \x01(\x0c\x12\x0c\n\x04name\x18\x02 \x01(\t\x12\x13\n\x0b\x64\x65scription\x18@ \x01(\t\x12!\n\x15\x64\x65precated_popularity\x18\x41 \x01(\x11\x42\x02\x18\x01\x12\x11\n\tpublisher\x18\x42 \x01(\t\x12\x10\n\x08language\x18\x43 \x01(\t\x12\x10\n\x08\x65xplicit\x18\x44 \x01(\x08\x12\x37\n\x0b\x63over_image\x18\x45 \x01(\x0b\x32\".spotify.metadata.proto.ImageGroup\x12\x30\n\x07\x65pisode\x18\x46 \x03(\x0b\x32\x1f.spotify.metadata.proto.Episode\x12\x34\n\tcopyright\x18G \x03(\x0b\x32!.spotify.metadata.proto.Copyright\x12\x38\n\x0brestriction\x18H \x03(\x0b\x32#.spotify.metadata.proto.Restriction\x12\x0f\n\x07keyword\x18I \x03(\t\x12:\n\nmedia_type\x18J \x01(\x0e\x32&.spotify.metadata.proto.Show.MediaType\x12H\n\x11\x63onsumption_order\x18K \x01(\x0e\x32-.spotify.metadata.proto.Show.ConsumptionOrder\x12:\n\x0c\x61vailability\x18N \x03(\x0b\x32$.spotify.metadata.proto.Availability\x12\x13\n\x0btrailer_uri\x18S \x01(\t\",\n\tMediaType\x12\t\n\x05MIXED\x10\x00\x12\t\n\x05\x41UDIO\x10\x01\x12\t\n\x05VIDEO\x10\x02\"<\n\x10\x43onsumptionOrder\x12\x0e\n\nSEQUENTIAL\x10\x01\x12\x0c\n\x08\x45PISODIC\x10\x02\x12\n\n\x06RECENT\x10\x03\"\xf9\x06\n\x07\x45pisode\x12\x0b\n\x03gid\x18\x01 \x01(\x0c\x12\x0c\n\x04name\x18\x02 \x01(\t\x12\x10\n\x08\x64uration\x18\x07 \x01(\x11\x12\x30\n\x05\x61udio\x18\x0c \x03(\x0b\x32!.spotify.metadata.proto.AudioFile\x12\x13\n\x0b\x64\x65scription\x18@ \x01(\t\x12\x0e\n\x06number\x18\x41 \x01(\x11\x12\x32\n\x0cpublish_time\x18\x42 \x01(\x0b\x32\x1c.spotify.metadata.proto.Date\x12!\n\x15\x64\x65precated_popularity\x18\x43 \x01(\x11\x42\x02\x18\x01\x12\x37\n\x0b\x63over_image\x18\x44 \x01(\x0b\x32\".spotify.metadata.proto.ImageGroup\x12\x10\n\x08language\x18\x45 \x01(\t\x12\x10\n\x08\x65xplicit\x18\x46 \x01(\x08\x12*\n\x04show\x18G \x01(\x0b\x32\x1c.spotify.metadata.proto.Show\x12\x30\n\x05video\x18H \x03(\x0b\x32!.spotify.metadata.proto.VideoFile\x12\x38\n\rvideo_preview\x18I \x03(\x0b\x32!.spotify.metadata.proto.VideoFile\x12\x38\n\raudio_preview\x18J \x03(\x0b\x32!.spotify.metadata.proto.AudioFile\x12\x38\n\x0brestriction\x18K \x03(\x0b\x32#.spotify.metadata.proto.Restriction\x12\x38\n\x0c\x66reeze_frame\x18L \x01(\x0b\x32\".spotify.metadata.proto.ImageGroup\x12\x0f\n\x07keyword\x18M \x03(\t\x12!\n\x19\x61llow_background_playback\x18Q \x01(\x08\x12:\n\x0c\x61vailability\x18R \x03(\x0b\x32$.spotify.metadata.proto.Availability\x12\x14\n\x0c\x65xternal_url\x18S \x01(\t\x12\x39\n\x04type\x18W \x01(\x0e\x32+.spotify.metadata.proto.Episode.EpisodeType\"/\n\x0b\x45pisodeType\x12\x08\n\x04\x46ULL\x10\x00\x12\x0b\n\x07TRAILER\x10\x01\x12\t\n\x05\x42ONUS\x10\x02\"\x18\n\x08Licensor\x12\x0c\n\x04uuid\x18\x01 \x01(\x0c\"J\n\tTopTracks\x12\x0f\n\x07\x63ountry\x18\x01 \x01(\t\x12,\n\x05track\x18\x02 \x03(\x0b\x32\x1d.spotify.metadata.proto.Track\"F\n\x0e\x41\x63tivityPeriod\x12\x12\n\nstart_year\x18\x01 \x01(\x11\x12\x10\n\x08\x65nd_year\x18\x02 \x01(\x11\x12\x0e\n\x06\x64\x65\x63\x61\x64\x65\x18\x03 \x01(\x11\":\n\nAlbumGroup\x12,\n\x05\x61lbum\x18\x01 \x03(\x0b\x32\x1d.spotify.metadata.proto.Album\"N\n\x04\x44\x61te\x12\x0c\n\x04year\x18\x01 \x01(\x11\x12\r\n\x05month\x18\x02 \x01(\x11\x12\x0b\n\x03\x64\x61y\x18\x03 \x01(\x11\x12\x0c\n\x04hour\x18\x04 \x01(\x11\x12\x0e\n\x06minute\x18\x05 \x01(\x11\"\xa0\x01\n\x05Image\x12\x0f\n\x07\x66ile_id\x18\x01 \x01(\x0c\x12\x30\n\x04size\x18\x02 \x01(\x0e\x32\".spotify.metadata.proto.Image.Size\x12\r\n\x05width\x18\x03 \x01(\x11\x12\x0e\n\x06height\x18\x04 \x01(\x11\"5\n\x04Size\x12\x0b\n\x07\x44\x45\x46\x41ULT\x10\x00\x12\t\n\x05SMALL\x10\x01\x12\t\n\x05LARGE\x10\x02\x12\n\n\x06XLARGE\x10\x03\":\n\nImageGroup\x12,\n\x05image\x18\x01 \x03(\x0b\x32\x1d.spotify.metadata.proto.Image\"\x86\x01\n\tBiography\x12\x0c\n\x04text\x18\x01 \x01(\t\x12/\n\x08portrait\x18\x02 \x03(\x0b\x32\x1d.spotify.metadata.proto.Image\x12:\n\x0eportrait_group\x18\x03 \x03(\x0b\x32\".spotify.metadata.proto.ImageGroup\"R\n\x04\x44isc\x12\x0e\n\x06number\x18\x01 \x01(\x11\x12\x0c\n\x04name\x18\x02 \x01(\t\x12,\n\x05track\x18\x03 \x03(\x0b\x32\x1d.spotify.metadata.proto.Track\"e\n\tCopyright\x12\x34\n\x04type\x18\x01 \x01(\x0e\x32&.spotify.metadata.proto.Copyright.Type\x12\x0c\n\x04text\x18\x02 \x01(\t\"\x14\n\x04Type\x12\x05\n\x01P\x10\x00\x12\x05\n\x01\x43\x10\x01\"\xdf\x02\n\x0bRestriction\x12@\n\tcatalogue\x18\x01 \x03(\x0e\x32-.spotify.metadata.proto.Restriction.Catalogue\x12\x36\n\x04type\x18\x04 \x01(\x0e\x32(.spotify.metadata.proto.Restriction.Type\x12\x15\n\rcatalogue_str\x18\x05 \x03(\t\x12\x1b\n\x11\x63ountries_allowed\x18\x02 \x01(\tH\x00\x12\x1d\n\x13\x63ountries_forbidden\x18\x03 \x01(\tH\x00\"U\n\tCatalogue\x12\x06\n\x02\x41\x44\x10\x00\x12\x10\n\x0cSUBSCRIPTION\x10\x01\x12\x11\n\rCATALOGUE_ALL\x10\x02\x12\x0b\n\x07SHUFFLE\x10\x03\x12\x0e\n\nCOMMERCIAL\x10\x04\"\x15\n\x04Type\x12\r\n\tSTREAMING\x10\x00\x42\x15\n\x13\x63ountry_restriction\"R\n\x0c\x41vailability\x12\x15\n\rcatalogue_str\x18\x01 \x03(\t\x12+\n\x05start\x18\x02 \x01(\x0b\x32\x1c.spotify.metadata.proto.Date\"\x9e\x01\n\nSalePeriod\x12\x38\n\x0brestriction\x18\x01 \x03(\x0b\x32#.spotify.metadata.proto.Restriction\x12+\n\x05start\x18\x02 \x01(\x0b\x32\x1c.spotify.metadata.proto.Date\x12)\n\x03\x65nd\x18\x03 \x01(\x0b\x32\x1c.spotify.metadata.proto.Date\"&\n\nExternalId\x12\x0c\n\x04type\x18\x01 \x01(\t\x12\n\n\x02id\x18\x02 \x01(\t\"\x89\x02\n\tAudioFile\x12\x0f\n\x07\x66ile_id\x18\x01 \x01(\x0c\x12\x38\n\x06\x66ormat\x18\x02 \x01(\x0e\x32(.spotify.metadata.proto.AudioFile.Format\"\xb0\x01\n\x06\x46ormat\x12\x11\n\rOGG_VORBIS_96\x10\x00\x12\x12\n\x0eOGG_VORBIS_160\x10\x01\x12\x12\n\x0eOGG_VORBIS_320\x10\x02\x12\x0b\n\x07MP3_256\x10\x03\x12\x0b\n\x07MP3_320\x10\x04\x12\x0b\n\x07MP3_160\x10\x05\x12\n\n\x06MP3_96\x10\x06\x12\x0f\n\x0bMP3_160_ENC\x10\x07\x12\n\n\x06\x41\x41\x43_24\x10\x08\x12\n\n\x06\x41\x41\x43_48\x10\t\x12\x0f\n\x0b\x41\x41\x43_24_NORM\x10\x10\"\x1c\n\tVideoFile\x12\x0f\n\x07\x66ile_id\x18\x01 \x01(\x0c\x42\"\n\x14\x63om.spotify.metadataB\x08MetadataH\x02' +) + +_ALBUM_TYPE = _descriptor.EnumDescriptor( + name='Type', + full_name='spotify.metadata.proto.Album.Type', + filename=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + values=[ + _descriptor.EnumValueDescriptor( + name='ALBUM', + index=0, + number=1, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='SINGLE', + index=1, + number=2, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='COMPILATION', + index=2, + number=3, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='EP', + index=3, + number=4, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='AUDIOBOOK', + index=4, + number=5, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='PODCAST', + index=5, + number=6, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + ], + containing_type=None, + serialized_options=None, + serialized_start=1742, + serialized_end=1824, +) +_sym_db.RegisterEnumDescriptor(_ALBUM_TYPE) + +_SHOW_MEDIATYPE = _descriptor.EnumDescriptor( + name='MediaType', + full_name='spotify.metadata.proto.Show.MediaType', + filename=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + values=[ + _descriptor.EnumValueDescriptor( + name='MIXED', + index=0, + number=0, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='AUDIO', + index=1, + number=1, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='VIDEO', + index=2, + number=2, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + ], + containing_type=None, + serialized_options=None, + serialized_start=3152, + serialized_end=3196, +) +_sym_db.RegisterEnumDescriptor(_SHOW_MEDIATYPE) + +_SHOW_CONSUMPTIONORDER = _descriptor.EnumDescriptor( + name='ConsumptionOrder', + full_name='spotify.metadata.proto.Show.ConsumptionOrder', + filename=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + values=[ + _descriptor.EnumValueDescriptor( + name='SEQUENTIAL', + index=0, + number=1, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='EPISODIC', + index=1, + number=2, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='RECENT', + index=2, + number=3, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + ], + containing_type=None, + serialized_options=None, + serialized_start=3198, + serialized_end=3258, +) +_sym_db.RegisterEnumDescriptor(_SHOW_CONSUMPTIONORDER) + +_EPISODE_EPISODETYPE = _descriptor.EnumDescriptor( + name='EpisodeType', + full_name='spotify.metadata.proto.Episode.EpisodeType', + filename=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + values=[ + _descriptor.EnumValueDescriptor( + name='FULL', + index=0, + number=0, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='TRAILER', + index=1, + number=1, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='BONUS', + index=2, + number=2, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + ], + containing_type=None, + serialized_options=None, + serialized_start=4103, + serialized_end=4150, +) +_sym_db.RegisterEnumDescriptor(_EPISODE_EPISODETYPE) + +_IMAGE_SIZE = _descriptor.EnumDescriptor( + name='Size', + full_name='spotify.metadata.proto.Image.Size', + filename=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + values=[ + _descriptor.EnumValueDescriptor( + name='DEFAULT', + index=0, + number=0, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='SMALL', + index=1, + number=1, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='LARGE', + index=2, + number=2, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='XLARGE', + index=3, + number=3, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + ], + containing_type=None, + serialized_options=None, + serialized_start=4574, + serialized_end=4627, +) +_sym_db.RegisterEnumDescriptor(_IMAGE_SIZE) + +_COPYRIGHT_TYPE = _descriptor.EnumDescriptor( + name='Type', + full_name='spotify.metadata.proto.Copyright.Type', + filename=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + values=[ + _descriptor.EnumValueDescriptor( + name='P', + index=0, + number=0, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='C', + index=1, + number=1, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + ], + containing_type=None, + serialized_options=None, + serialized_start=4991, + serialized_end=5011, +) +_sym_db.RegisterEnumDescriptor(_COPYRIGHT_TYPE) + +_RESTRICTION_CATALOGUE = _descriptor.EnumDescriptor( + name='Catalogue', + full_name='spotify.metadata.proto.Restriction.Catalogue', + filename=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + values=[ + _descriptor.EnumValueDescriptor( + name='AD', + index=0, + number=0, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='SUBSCRIPTION', + index=1, + number=1, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='CATALOGUE_ALL', + index=2, + number=2, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='SHUFFLE', + index=3, + number=3, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='COMMERCIAL', + index=4, + number=4, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + ], + containing_type=None, + serialized_options=None, + serialized_start=5234, + serialized_end=5319, +) +_sym_db.RegisterEnumDescriptor(_RESTRICTION_CATALOGUE) + +_RESTRICTION_TYPE = _descriptor.EnumDescriptor( + name='Type', + full_name='spotify.metadata.proto.Restriction.Type', + filename=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + values=[ + _descriptor.EnumValueDescriptor( + name='STREAMING', + index=0, + number=0, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + ], + containing_type=None, + serialized_options=None, + serialized_start=5321, + serialized_end=5342, +) +_sym_db.RegisterEnumDescriptor(_RESTRICTION_TYPE) + +_AUDIOFILE_FORMAT = _descriptor.EnumDescriptor( + name='Format', + full_name='spotify.metadata.proto.AudioFile.Format', + filename=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + values=[ + _descriptor.EnumValueDescriptor( + name='OGG_VORBIS_96', + index=0, + number=0, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='OGG_VORBIS_160', + index=1, + number=1, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='OGG_VORBIS_320', + index=2, + number=2, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='MP3_256', + index=3, + number=3, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='MP3_320', + index=4, + number=4, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='MP3_160', + index=5, + number=5, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='MP3_96', + index=6, + number=6, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='MP3_160_ENC', + index=7, + number=7, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='AAC_24', + index=8, + number=8, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='AAC_48', + index=9, + number=9, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='AAC_24_NORM', + index=10, + number=16, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + ], + containing_type=None, + serialized_options=None, + serialized_start=5742, + serialized_end=5918, +) +_sym_db.RegisterEnumDescriptor(_AUDIOFILE_FORMAT) + +_ARTIST = _descriptor.Descriptor( + name='Artist', + full_name='spotify.metadata.proto.Artist', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='gid', + full_name='spotify.metadata.proto.Artist.gid', + index=0, + number=1, + type=12, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"", + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='name', + full_name='spotify.metadata.proto.Artist.name', + index=1, + number=2, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"".decode('utf-8'), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='popularity', + full_name='spotify.metadata.proto.Artist.popularity', + index=2, + number=3, + type=17, + cpp_type=1, + label=1, + has_default_value=False, + default_value=0, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='top_track', + full_name='spotify.metadata.proto.Artist.top_track', + index=3, + number=4, + type=11, + cpp_type=10, + label=3, + has_default_value=False, + default_value=[], + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='album_group', + full_name='spotify.metadata.proto.Artist.album_group', + index=4, + number=5, + type=11, + cpp_type=10, + label=3, + has_default_value=False, + default_value=[], + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='single_group', + full_name='spotify.metadata.proto.Artist.single_group', + index=5, + number=6, + type=11, + cpp_type=10, + label=3, + has_default_value=False, + default_value=[], + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='compilation_group', + full_name='spotify.metadata.proto.Artist.compilation_group', + index=6, + number=7, + type=11, + cpp_type=10, + label=3, + has_default_value=False, + default_value=[], + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='appears_on_group', + full_name='spotify.metadata.proto.Artist.appears_on_group', + index=7, + number=8, + type=11, + cpp_type=10, + label=3, + has_default_value=False, + default_value=[], + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='genre', + full_name='spotify.metadata.proto.Artist.genre', + index=8, + number=9, + type=9, + cpp_type=9, + label=3, + has_default_value=False, + default_value=[], + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='external_id', + full_name='spotify.metadata.proto.Artist.external_id', + index=9, + number=10, + type=11, + cpp_type=10, + label=3, + has_default_value=False, + default_value=[], + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='portrait', + full_name='spotify.metadata.proto.Artist.portrait', + index=10, + number=11, + type=11, + cpp_type=10, + label=3, + has_default_value=False, + default_value=[], + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='biography', + full_name='spotify.metadata.proto.Artist.biography', + index=11, + number=12, + type=11, + cpp_type=10, + label=3, + has_default_value=False, + default_value=[], + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='activity_period', + full_name='spotify.metadata.proto.Artist.activity_period', + index=12, + number=13, + type=11, + cpp_type=10, + label=3, + has_default_value=False, + default_value=[], + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='restriction', + full_name='spotify.metadata.proto.Artist.restriction', + index=13, + number=14, + type=11, + cpp_type=10, + label=3, + has_default_value=False, + default_value=[], + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='related', + full_name='spotify.metadata.proto.Artist.related', + index=14, + number=15, + type=11, + cpp_type=10, + label=3, + has_default_value=False, + default_value=[], + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='is_portrait_album_cover', + full_name='spotify.metadata.proto.Artist.is_portrait_album_cover', + index=15, + number=16, + type=8, + cpp_type=7, + label=1, + has_default_value=False, + default_value=False, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='portrait_group', + full_name='spotify.metadata.proto.Artist.portrait_group', + index=16, + number=17, + type=11, + cpp_type=10, + label=1, + has_default_value=False, + default_value=None, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='sale_period', + full_name='spotify.metadata.proto.Artist.sale_period', + index=17, + number=18, + type=11, + cpp_type=10, + label=3, + has_default_value=False, + default_value=[], + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='availability', + full_name='spotify.metadata.proto.Artist.availability', + index=18, + number=20, + type=11, + cpp_type=10, + label=3, + has_default_value=False, + default_value=[], + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[], + serialized_start=43, + serialized_end=949, +) + +_ALBUM = _descriptor.Descriptor( + name='Album', + full_name='spotify.metadata.proto.Album', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='gid', + full_name='spotify.metadata.proto.Album.gid', + index=0, + number=1, + type=12, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"", + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='name', + full_name='spotify.metadata.proto.Album.name', + index=1, + number=2, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"".decode('utf-8'), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='artist', + full_name='spotify.metadata.proto.Album.artist', + index=2, + number=3, + type=11, + cpp_type=10, + label=3, + has_default_value=False, + default_value=[], + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='type', + full_name='spotify.metadata.proto.Album.type', + index=3, + number=4, + type=14, + cpp_type=8, + label=1, + has_default_value=False, + default_value=1, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='label', + full_name='spotify.metadata.proto.Album.label', + index=4, + number=5, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"".decode('utf-8'), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='date', + full_name='spotify.metadata.proto.Album.date', + index=5, + number=6, + type=11, + cpp_type=10, + label=1, + has_default_value=False, + default_value=None, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='popularity', + full_name='spotify.metadata.proto.Album.popularity', + index=6, + number=7, + type=17, + cpp_type=1, + label=1, + has_default_value=False, + default_value=0, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='genre', + full_name='spotify.metadata.proto.Album.genre', + index=7, + number=8, + type=9, + cpp_type=9, + label=3, + has_default_value=False, + default_value=[], + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='cover', + full_name='spotify.metadata.proto.Album.cover', + index=8, + number=9, + type=11, + cpp_type=10, + label=3, + has_default_value=False, + default_value=[], + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='external_id', + full_name='spotify.metadata.proto.Album.external_id', + index=9, + number=10, + type=11, + cpp_type=10, + label=3, + has_default_value=False, + default_value=[], + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='disc', + full_name='spotify.metadata.proto.Album.disc', + index=10, + number=11, + type=11, + cpp_type=10, + label=3, + has_default_value=False, + default_value=[], + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='review', + full_name='spotify.metadata.proto.Album.review', + index=11, + number=12, + type=9, + cpp_type=9, + label=3, + has_default_value=False, + default_value=[], + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='copyright', + full_name='spotify.metadata.proto.Album.copyright', + index=12, + number=13, + type=11, + cpp_type=10, + label=3, + has_default_value=False, + default_value=[], + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='restriction', + full_name='spotify.metadata.proto.Album.restriction', + index=13, + number=14, + type=11, + cpp_type=10, + label=3, + has_default_value=False, + default_value=[], + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='related', + full_name='spotify.metadata.proto.Album.related', + index=14, + number=15, + type=11, + cpp_type=10, + label=3, + has_default_value=False, + default_value=[], + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='sale_period', + full_name='spotify.metadata.proto.Album.sale_period', + index=15, + number=16, + type=11, + cpp_type=10, + label=3, + has_default_value=False, + default_value=[], + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='cover_group', + full_name='spotify.metadata.proto.Album.cover_group', + index=16, + number=17, + type=11, + cpp_type=10, + label=1, + has_default_value=False, + default_value=None, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='original_title', + full_name='spotify.metadata.proto.Album.original_title', + index=17, + number=18, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"".decode('utf-8'), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='version_title', + full_name='spotify.metadata.proto.Album.version_title', + index=18, + number=19, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"".decode('utf-8'), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='type_str', + full_name='spotify.metadata.proto.Album.type_str', + index=19, + number=20, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"".decode('utf-8'), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='availability', + full_name='spotify.metadata.proto.Album.availability', + index=20, + number=23, + type=11, + cpp_type=10, + label=3, + has_default_value=False, + default_value=[], + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + ], + extensions=[], + nested_types=[], + enum_types=[ + _ALBUM_TYPE, + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[], + serialized_start=952, + serialized_end=1824, +) + +_TRACK = _descriptor.Descriptor( + name='Track', + full_name='spotify.metadata.proto.Track', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='gid', + full_name='spotify.metadata.proto.Track.gid', + index=0, + number=1, + type=12, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"", + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='name', + full_name='spotify.metadata.proto.Track.name', + index=1, + number=2, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"".decode('utf-8'), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='album', + full_name='spotify.metadata.proto.Track.album', + index=2, + number=3, + type=11, + cpp_type=10, + label=1, + has_default_value=False, + default_value=None, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='artist', + full_name='spotify.metadata.proto.Track.artist', + index=3, + number=4, + type=11, + cpp_type=10, + label=3, + has_default_value=False, + default_value=[], + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='number', + full_name='spotify.metadata.proto.Track.number', + index=4, + number=5, + type=17, + cpp_type=1, + label=1, + has_default_value=False, + default_value=0, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='disc_number', + full_name='spotify.metadata.proto.Track.disc_number', + index=5, + number=6, + type=17, + cpp_type=1, + label=1, + has_default_value=False, + default_value=0, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='duration', + full_name='spotify.metadata.proto.Track.duration', + index=6, + number=7, + type=17, + cpp_type=1, + label=1, + has_default_value=False, + default_value=0, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='popularity', + full_name='spotify.metadata.proto.Track.popularity', + index=7, + number=8, + type=17, + cpp_type=1, + label=1, + has_default_value=False, + default_value=0, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='explicit', + full_name='spotify.metadata.proto.Track.explicit', + index=8, + number=9, + type=8, + cpp_type=7, + label=1, + has_default_value=False, + default_value=False, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='external_id', + full_name='spotify.metadata.proto.Track.external_id', + index=9, + number=10, + type=11, + cpp_type=10, + label=3, + has_default_value=False, + default_value=[], + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='restriction', + full_name='spotify.metadata.proto.Track.restriction', + index=10, + number=11, + type=11, + cpp_type=10, + label=3, + has_default_value=False, + default_value=[], + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='file', + full_name='spotify.metadata.proto.Track.file', + index=11, + number=12, + type=11, + cpp_type=10, + label=3, + has_default_value=False, + default_value=[], + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='alternative', + full_name='spotify.metadata.proto.Track.alternative', + index=12, + number=13, + type=11, + cpp_type=10, + label=3, + has_default_value=False, + default_value=[], + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='sale_period', + full_name='spotify.metadata.proto.Track.sale_period', + index=13, + number=14, + type=11, + cpp_type=10, + label=3, + has_default_value=False, + default_value=[], + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='preview', + full_name='spotify.metadata.proto.Track.preview', + index=14, + number=15, + type=11, + cpp_type=10, + label=3, + has_default_value=False, + default_value=[], + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='tags', + full_name='spotify.metadata.proto.Track.tags', + index=15, + number=16, + type=9, + cpp_type=9, + label=3, + has_default_value=False, + default_value=[], + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='earliest_live_timestamp', + full_name='spotify.metadata.proto.Track.earliest_live_timestamp', + index=16, + number=17, + type=3, + cpp_type=2, + label=1, + has_default_value=False, + default_value=0, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='has_lyrics', + full_name='spotify.metadata.proto.Track.has_lyrics', + index=17, + number=18, + type=8, + cpp_type=7, + label=1, + has_default_value=False, + default_value=False, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='availability', + full_name='spotify.metadata.proto.Track.availability', + index=18, + number=19, + type=11, + cpp_type=10, + label=3, + has_default_value=False, + default_value=[], + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='licensor', + full_name='spotify.metadata.proto.Track.licensor', + index=19, + number=21, + type=11, + cpp_type=10, + label=1, + has_default_value=False, + default_value=None, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[], + serialized_start=1827, + serialized_end=2552, +) + +_SHOW = _descriptor.Descriptor( + name='Show', + full_name='spotify.metadata.proto.Show', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='gid', + full_name='spotify.metadata.proto.Show.gid', + index=0, + number=1, + type=12, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"", + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='name', + full_name='spotify.metadata.proto.Show.name', + index=1, + number=2, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"".decode('utf-8'), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='description', + full_name='spotify.metadata.proto.Show.description', + index=2, + number=64, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"".decode('utf-8'), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='deprecated_popularity', + full_name='spotify.metadata.proto.Show.deprecated_popularity', + index=3, + number=65, + type=17, + cpp_type=1, + label=1, + has_default_value=False, + default_value=0, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=b'\030\001', + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='publisher', + full_name='spotify.metadata.proto.Show.publisher', + index=4, + number=66, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"".decode('utf-8'), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='language', + full_name='spotify.metadata.proto.Show.language', + index=5, + number=67, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"".decode('utf-8'), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='explicit', + full_name='spotify.metadata.proto.Show.explicit', + index=6, + number=68, + type=8, + cpp_type=7, + label=1, + has_default_value=False, + default_value=False, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='cover_image', + full_name='spotify.metadata.proto.Show.cover_image', + index=7, + number=69, + type=11, + cpp_type=10, + label=1, + has_default_value=False, + default_value=None, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='episode', + full_name='spotify.metadata.proto.Show.episode', + index=8, + number=70, + type=11, + cpp_type=10, + label=3, + has_default_value=False, + default_value=[], + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='copyright', + full_name='spotify.metadata.proto.Show.copyright', + index=9, + number=71, + type=11, + cpp_type=10, + label=3, + has_default_value=False, + default_value=[], + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='restriction', + full_name='spotify.metadata.proto.Show.restriction', + index=10, + number=72, + type=11, + cpp_type=10, + label=3, + has_default_value=False, + default_value=[], + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='keyword', + full_name='spotify.metadata.proto.Show.keyword', + index=11, + number=73, + type=9, + cpp_type=9, + label=3, + has_default_value=False, + default_value=[], + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='media_type', + full_name='spotify.metadata.proto.Show.media_type', + index=12, + number=74, + type=14, + cpp_type=8, + label=1, + has_default_value=False, + default_value=0, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='consumption_order', + full_name='spotify.metadata.proto.Show.consumption_order', + index=13, + number=75, + type=14, + cpp_type=8, + label=1, + has_default_value=False, + default_value=1, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='availability', + full_name='spotify.metadata.proto.Show.availability', + index=14, + number=78, + type=11, + cpp_type=10, + label=3, + has_default_value=False, + default_value=[], + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='trailer_uri', + full_name='spotify.metadata.proto.Show.trailer_uri', + index=15, + number=83, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"".decode('utf-8'), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + ], + extensions=[], + nested_types=[], + enum_types=[ + _SHOW_MEDIATYPE, + _SHOW_CONSUMPTIONORDER, + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[], + serialized_start=2555, + serialized_end=3258, +) + +_EPISODE = _descriptor.Descriptor( + name='Episode', + full_name='spotify.metadata.proto.Episode', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='gid', + full_name='spotify.metadata.proto.Episode.gid', + index=0, + number=1, + type=12, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"", + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='name', + full_name='spotify.metadata.proto.Episode.name', + index=1, + number=2, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"".decode('utf-8'), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='duration', + full_name='spotify.metadata.proto.Episode.duration', + index=2, + number=7, + type=17, + cpp_type=1, + label=1, + has_default_value=False, + default_value=0, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='audio', + full_name='spotify.metadata.proto.Episode.audio', + index=3, + number=12, + type=11, + cpp_type=10, + label=3, + has_default_value=False, + default_value=[], + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='description', + full_name='spotify.metadata.proto.Episode.description', + index=4, + number=64, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"".decode('utf-8'), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='number', + full_name='spotify.metadata.proto.Episode.number', + index=5, + number=65, + type=17, + cpp_type=1, + label=1, + has_default_value=False, + default_value=0, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='publish_time', + full_name='spotify.metadata.proto.Episode.publish_time', + index=6, + number=66, + type=11, + cpp_type=10, + label=1, + has_default_value=False, + default_value=None, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='deprecated_popularity', + full_name='spotify.metadata.proto.Episode.deprecated_popularity', + index=7, + number=67, + type=17, + cpp_type=1, + label=1, + has_default_value=False, + default_value=0, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=b'\030\001', + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='cover_image', + full_name='spotify.metadata.proto.Episode.cover_image', + index=8, + number=68, + type=11, + cpp_type=10, + label=1, + has_default_value=False, + default_value=None, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='language', + full_name='spotify.metadata.proto.Episode.language', + index=9, + number=69, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"".decode('utf-8'), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='explicit', + full_name='spotify.metadata.proto.Episode.explicit', + index=10, + number=70, + type=8, + cpp_type=7, + label=1, + has_default_value=False, + default_value=False, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='show', + full_name='spotify.metadata.proto.Episode.show', + index=11, + number=71, + type=11, + cpp_type=10, + label=1, + has_default_value=False, + default_value=None, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='video', + full_name='spotify.metadata.proto.Episode.video', + index=12, + number=72, + type=11, + cpp_type=10, + label=3, + has_default_value=False, + default_value=[], + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='video_preview', + full_name='spotify.metadata.proto.Episode.video_preview', + index=13, + number=73, + type=11, + cpp_type=10, + label=3, + has_default_value=False, + default_value=[], + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='audio_preview', + full_name='spotify.metadata.proto.Episode.audio_preview', + index=14, + number=74, + type=11, + cpp_type=10, + label=3, + has_default_value=False, + default_value=[], + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='restriction', + full_name='spotify.metadata.proto.Episode.restriction', + index=15, + number=75, + type=11, + cpp_type=10, + label=3, + has_default_value=False, + default_value=[], + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='freeze_frame', + full_name='spotify.metadata.proto.Episode.freeze_frame', + index=16, + number=76, + type=11, + cpp_type=10, + label=1, + has_default_value=False, + default_value=None, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='keyword', + full_name='spotify.metadata.proto.Episode.keyword', + index=17, + number=77, + type=9, + cpp_type=9, + label=3, + has_default_value=False, + default_value=[], + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='allow_background_playback', + full_name= + 'spotify.metadata.proto.Episode.allow_background_playback', + index=18, + number=81, + type=8, + cpp_type=7, + label=1, + has_default_value=False, + default_value=False, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='availability', + full_name='spotify.metadata.proto.Episode.availability', + index=19, + number=82, + type=11, + cpp_type=10, + label=3, + has_default_value=False, + default_value=[], + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='external_url', + full_name='spotify.metadata.proto.Episode.external_url', + index=20, + number=83, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"".decode('utf-8'), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='type', + full_name='spotify.metadata.proto.Episode.type', + index=21, + number=87, + type=14, + cpp_type=8, + label=1, + has_default_value=False, + default_value=0, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + ], + extensions=[], + nested_types=[], + enum_types=[ + _EPISODE_EPISODETYPE, + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[], + serialized_start=3261, + serialized_end=4150, +) + +_LICENSOR = _descriptor.Descriptor( + name='Licensor', + full_name='spotify.metadata.proto.Licensor', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='uuid', + full_name='spotify.metadata.proto.Licensor.uuid', + index=0, + number=1, + type=12, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"", + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[], + serialized_start=4152, + serialized_end=4176, +) + +_TOPTRACKS = _descriptor.Descriptor( + name='TopTracks', + full_name='spotify.metadata.proto.TopTracks', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='country', + full_name='spotify.metadata.proto.TopTracks.country', + index=0, + number=1, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"".decode('utf-8'), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='track', + full_name='spotify.metadata.proto.TopTracks.track', + index=1, + number=2, + type=11, + cpp_type=10, + label=3, + has_default_value=False, + default_value=[], + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[], + serialized_start=4178, + serialized_end=4252, +) + +_ACTIVITYPERIOD = _descriptor.Descriptor( + name='ActivityPeriod', + full_name='spotify.metadata.proto.ActivityPeriod', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='start_year', + full_name='spotify.metadata.proto.ActivityPeriod.start_year', + index=0, + number=1, + type=17, + cpp_type=1, + label=1, + has_default_value=False, + default_value=0, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='end_year', + full_name='spotify.metadata.proto.ActivityPeriod.end_year', + index=1, + number=2, + type=17, + cpp_type=1, + label=1, + has_default_value=False, + default_value=0, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='decade', + full_name='spotify.metadata.proto.ActivityPeriod.decade', + index=2, + number=3, + type=17, + cpp_type=1, + label=1, + has_default_value=False, + default_value=0, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[], + serialized_start=4254, + serialized_end=4324, +) + +_ALBUMGROUP = _descriptor.Descriptor( + name='AlbumGroup', + full_name='spotify.metadata.proto.AlbumGroup', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='album', + full_name='spotify.metadata.proto.AlbumGroup.album', + index=0, + number=1, + type=11, + cpp_type=10, + label=3, + has_default_value=False, + default_value=[], + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[], + serialized_start=4326, + serialized_end=4384, +) + +_DATE = _descriptor.Descriptor( + name='Date', + full_name='spotify.metadata.proto.Date', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='year', + full_name='spotify.metadata.proto.Date.year', + index=0, + number=1, + type=17, + cpp_type=1, + label=1, + has_default_value=False, + default_value=0, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='month', + full_name='spotify.metadata.proto.Date.month', + index=1, + number=2, + type=17, + cpp_type=1, + label=1, + has_default_value=False, + default_value=0, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='day', + full_name='spotify.metadata.proto.Date.day', + index=2, + number=3, + type=17, + cpp_type=1, + label=1, + has_default_value=False, + default_value=0, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='hour', + full_name='spotify.metadata.proto.Date.hour', + index=3, + number=4, + type=17, + cpp_type=1, + label=1, + has_default_value=False, + default_value=0, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='minute', + full_name='spotify.metadata.proto.Date.minute', + index=4, + number=5, + type=17, + cpp_type=1, + label=1, + has_default_value=False, + default_value=0, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[], + serialized_start=4386, + serialized_end=4464, +) + +_IMAGE = _descriptor.Descriptor( + name='Image', + full_name='spotify.metadata.proto.Image', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='file_id', + full_name='spotify.metadata.proto.Image.file_id', + index=0, + number=1, + type=12, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"", + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='size', + full_name='spotify.metadata.proto.Image.size', + index=1, + number=2, + type=14, + cpp_type=8, + label=1, + has_default_value=False, + default_value=0, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='width', + full_name='spotify.metadata.proto.Image.width', + index=2, + number=3, + type=17, + cpp_type=1, + label=1, + has_default_value=False, + default_value=0, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='height', + full_name='spotify.metadata.proto.Image.height', + index=3, + number=4, + type=17, + cpp_type=1, + label=1, + has_default_value=False, + default_value=0, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + ], + extensions=[], + nested_types=[], + enum_types=[ + _IMAGE_SIZE, + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[], + serialized_start=4467, + serialized_end=4627, +) + +_IMAGEGROUP = _descriptor.Descriptor( + name='ImageGroup', + full_name='spotify.metadata.proto.ImageGroup', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='image', + full_name='spotify.metadata.proto.ImageGroup.image', + index=0, + number=1, + type=11, + cpp_type=10, + label=3, + has_default_value=False, + default_value=[], + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[], + serialized_start=4629, + serialized_end=4687, +) + +_BIOGRAPHY = _descriptor.Descriptor( + name='Biography', + full_name='spotify.metadata.proto.Biography', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='text', + full_name='spotify.metadata.proto.Biography.text', + index=0, + number=1, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"".decode('utf-8'), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='portrait', + full_name='spotify.metadata.proto.Biography.portrait', + index=1, + number=2, + type=11, + cpp_type=10, + label=3, + has_default_value=False, + default_value=[], + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='portrait_group', + full_name='spotify.metadata.proto.Biography.portrait_group', + index=2, + number=3, + type=11, + cpp_type=10, + label=3, + has_default_value=False, + default_value=[], + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[], + serialized_start=4690, + serialized_end=4824, +) + +_DISC = _descriptor.Descriptor( + name='Disc', + full_name='spotify.metadata.proto.Disc', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='number', + full_name='spotify.metadata.proto.Disc.number', + index=0, + number=1, + type=17, + cpp_type=1, + label=1, + has_default_value=False, + default_value=0, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='name', + full_name='spotify.metadata.proto.Disc.name', + index=1, + number=2, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"".decode('utf-8'), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='track', + full_name='spotify.metadata.proto.Disc.track', + index=2, + number=3, + type=11, + cpp_type=10, + label=3, + has_default_value=False, + default_value=[], + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[], + serialized_start=4826, + serialized_end=4908, +) + +_COPYRIGHT = _descriptor.Descriptor( + name='Copyright', + full_name='spotify.metadata.proto.Copyright', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='type', + full_name='spotify.metadata.proto.Copyright.type', + index=0, + number=1, + type=14, + cpp_type=8, + label=1, + has_default_value=False, + default_value=0, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='text', + full_name='spotify.metadata.proto.Copyright.text', + index=1, + number=2, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"".decode('utf-8'), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + ], + extensions=[], + nested_types=[], + enum_types=[ + _COPYRIGHT_TYPE, + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[], + serialized_start=4910, + serialized_end=5011, +) + +_RESTRICTION = _descriptor.Descriptor( + name='Restriction', + full_name='spotify.metadata.proto.Restriction', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='catalogue', + full_name='spotify.metadata.proto.Restriction.catalogue', + index=0, + number=1, + type=14, + cpp_type=8, + label=3, + has_default_value=False, + default_value=[], + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='type', + full_name='spotify.metadata.proto.Restriction.type', + index=1, + number=4, + type=14, + cpp_type=8, + label=1, + has_default_value=False, + default_value=0, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='catalogue_str', + full_name='spotify.metadata.proto.Restriction.catalogue_str', + index=2, + number=5, + type=9, + cpp_type=9, + label=3, + has_default_value=False, + default_value=[], + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='countries_allowed', + full_name='spotify.metadata.proto.Restriction.countries_allowed', + index=3, + number=2, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"".decode('utf-8'), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='countries_forbidden', + full_name='spotify.metadata.proto.Restriction.countries_forbidden', + index=4, + number=3, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"".decode('utf-8'), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + ], + extensions=[], + nested_types=[], + enum_types=[ + _RESTRICTION_CATALOGUE, + _RESTRICTION_TYPE, + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[ + _descriptor.OneofDescriptor( + name='country_restriction', + full_name='spotify.metadata.proto.Restriction.country_restriction', + index=0, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[]), + ], + serialized_start=5014, + serialized_end=5365, +) + +_AVAILABILITY = _descriptor.Descriptor( + name='Availability', + full_name='spotify.metadata.proto.Availability', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='catalogue_str', + full_name='spotify.metadata.proto.Availability.catalogue_str', + index=0, + number=1, + type=9, + cpp_type=9, + label=3, + has_default_value=False, + default_value=[], + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='start', + full_name='spotify.metadata.proto.Availability.start', + index=1, + number=2, + type=11, + cpp_type=10, + label=1, + has_default_value=False, + default_value=None, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[], + serialized_start=5367, + serialized_end=5449, +) + +_SALEPERIOD = _descriptor.Descriptor( + name='SalePeriod', + full_name='spotify.metadata.proto.SalePeriod', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='restriction', + full_name='spotify.metadata.proto.SalePeriod.restriction', + index=0, + number=1, + type=11, + cpp_type=10, + label=3, + has_default_value=False, + default_value=[], + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='start', + full_name='spotify.metadata.proto.SalePeriod.start', + index=1, + number=2, + type=11, + cpp_type=10, + label=1, + has_default_value=False, + default_value=None, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='end', + full_name='spotify.metadata.proto.SalePeriod.end', + index=2, + number=3, + type=11, + cpp_type=10, + label=1, + has_default_value=False, + default_value=None, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[], + serialized_start=5452, + serialized_end=5610, +) + +_EXTERNALID = _descriptor.Descriptor( + name='ExternalId', + full_name='spotify.metadata.proto.ExternalId', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='type', + full_name='spotify.metadata.proto.ExternalId.type', + index=0, + number=1, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"".decode('utf-8'), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='id', + full_name='spotify.metadata.proto.ExternalId.id', + index=1, + number=2, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"".decode('utf-8'), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[], + serialized_start=5612, + serialized_end=5650, +) + +_AUDIOFILE = _descriptor.Descriptor( + name='AudioFile', + full_name='spotify.metadata.proto.AudioFile', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='file_id', + full_name='spotify.metadata.proto.AudioFile.file_id', + index=0, + number=1, + type=12, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"", + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='format', + full_name='spotify.metadata.proto.AudioFile.format', + index=1, + number=2, + type=14, + cpp_type=8, + label=1, + has_default_value=False, + default_value=0, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + ], + extensions=[], + nested_types=[], + enum_types=[ + _AUDIOFILE_FORMAT, + ], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[], + serialized_start=5653, + serialized_end=5918, +) + +_VIDEOFILE = _descriptor.Descriptor( + name='VideoFile', + full_name='spotify.metadata.proto.VideoFile', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='file_id', + full_name='spotify.metadata.proto.VideoFile.file_id', + index=0, + number=1, + type=12, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"", + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[], + serialized_start=5920, + serialized_end=5948, +) + +_ARTIST.fields_by_name['top_track'].message_type = _TOPTRACKS +_ARTIST.fields_by_name['album_group'].message_type = _ALBUMGROUP +_ARTIST.fields_by_name['single_group'].message_type = _ALBUMGROUP +_ARTIST.fields_by_name['compilation_group'].message_type = _ALBUMGROUP +_ARTIST.fields_by_name['appears_on_group'].message_type = _ALBUMGROUP +_ARTIST.fields_by_name['external_id'].message_type = _EXTERNALID +_ARTIST.fields_by_name['portrait'].message_type = _IMAGE +_ARTIST.fields_by_name['biography'].message_type = _BIOGRAPHY +_ARTIST.fields_by_name['activity_period'].message_type = _ACTIVITYPERIOD +_ARTIST.fields_by_name['restriction'].message_type = _RESTRICTION +_ARTIST.fields_by_name['related'].message_type = _ARTIST +_ARTIST.fields_by_name['portrait_group'].message_type = _IMAGEGROUP +_ARTIST.fields_by_name['sale_period'].message_type = _SALEPERIOD +_ARTIST.fields_by_name['availability'].message_type = _AVAILABILITY +_ALBUM.fields_by_name['artist'].message_type = _ARTIST +_ALBUM.fields_by_name['type'].enum_type = _ALBUM_TYPE +_ALBUM.fields_by_name['date'].message_type = _DATE +_ALBUM.fields_by_name['cover'].message_type = _IMAGE +_ALBUM.fields_by_name['external_id'].message_type = _EXTERNALID +_ALBUM.fields_by_name['disc'].message_type = _DISC +_ALBUM.fields_by_name['copyright'].message_type = _COPYRIGHT +_ALBUM.fields_by_name['restriction'].message_type = _RESTRICTION +_ALBUM.fields_by_name['related'].message_type = _ALBUM +_ALBUM.fields_by_name['sale_period'].message_type = _SALEPERIOD +_ALBUM.fields_by_name['cover_group'].message_type = _IMAGEGROUP +_ALBUM.fields_by_name['availability'].message_type = _AVAILABILITY +_ALBUM_TYPE.containing_type = _ALBUM +_TRACK.fields_by_name['album'].message_type = _ALBUM +_TRACK.fields_by_name['artist'].message_type = _ARTIST +_TRACK.fields_by_name['external_id'].message_type = _EXTERNALID +_TRACK.fields_by_name['restriction'].message_type = _RESTRICTION +_TRACK.fields_by_name['file'].message_type = _AUDIOFILE +_TRACK.fields_by_name['alternative'].message_type = _TRACK +_TRACK.fields_by_name['sale_period'].message_type = _SALEPERIOD +_TRACK.fields_by_name['preview'].message_type = _AUDIOFILE +_TRACK.fields_by_name['availability'].message_type = _AVAILABILITY +_TRACK.fields_by_name['licensor'].message_type = _LICENSOR +_SHOW.fields_by_name['cover_image'].message_type = _IMAGEGROUP +_SHOW.fields_by_name['episode'].message_type = _EPISODE +_SHOW.fields_by_name['copyright'].message_type = _COPYRIGHT +_SHOW.fields_by_name['restriction'].message_type = _RESTRICTION +_SHOW.fields_by_name['media_type'].enum_type = _SHOW_MEDIATYPE +_SHOW.fields_by_name['consumption_order'].enum_type = _SHOW_CONSUMPTIONORDER +_SHOW.fields_by_name['availability'].message_type = _AVAILABILITY +_SHOW_MEDIATYPE.containing_type = _SHOW +_SHOW_CONSUMPTIONORDER.containing_type = _SHOW +_EPISODE.fields_by_name['audio'].message_type = _AUDIOFILE +_EPISODE.fields_by_name['publish_time'].message_type = _DATE +_EPISODE.fields_by_name['cover_image'].message_type = _IMAGEGROUP +_EPISODE.fields_by_name['show'].message_type = _SHOW +_EPISODE.fields_by_name['video'].message_type = _VIDEOFILE +_EPISODE.fields_by_name['video_preview'].message_type = _VIDEOFILE +_EPISODE.fields_by_name['audio_preview'].message_type = _AUDIOFILE +_EPISODE.fields_by_name['restriction'].message_type = _RESTRICTION +_EPISODE.fields_by_name['freeze_frame'].message_type = _IMAGEGROUP +_EPISODE.fields_by_name['availability'].message_type = _AVAILABILITY +_EPISODE.fields_by_name['type'].enum_type = _EPISODE_EPISODETYPE +_EPISODE_EPISODETYPE.containing_type = _EPISODE +_TOPTRACKS.fields_by_name['track'].message_type = _TRACK +_ALBUMGROUP.fields_by_name['album'].message_type = _ALBUM +_IMAGE.fields_by_name['size'].enum_type = _IMAGE_SIZE +_IMAGE_SIZE.containing_type = _IMAGE +_IMAGEGROUP.fields_by_name['image'].message_type = _IMAGE +_BIOGRAPHY.fields_by_name['portrait'].message_type = _IMAGE +_BIOGRAPHY.fields_by_name['portrait_group'].message_type = _IMAGEGROUP +_DISC.fields_by_name['track'].message_type = _TRACK +_COPYRIGHT.fields_by_name['type'].enum_type = _COPYRIGHT_TYPE +_COPYRIGHT_TYPE.containing_type = _COPYRIGHT +_RESTRICTION.fields_by_name['catalogue'].enum_type = _RESTRICTION_CATALOGUE +_RESTRICTION.fields_by_name['type'].enum_type = _RESTRICTION_TYPE +_RESTRICTION_CATALOGUE.containing_type = _RESTRICTION +_RESTRICTION_TYPE.containing_type = _RESTRICTION +_RESTRICTION.oneofs_by_name['country_restriction'].fields.append( + _RESTRICTION.fields_by_name['countries_allowed']) +_RESTRICTION.fields_by_name[ + 'countries_allowed'].containing_oneof = _RESTRICTION.oneofs_by_name[ + 'country_restriction'] +_RESTRICTION.oneofs_by_name['country_restriction'].fields.append( + _RESTRICTION.fields_by_name['countries_forbidden']) +_RESTRICTION.fields_by_name[ + 'countries_forbidden'].containing_oneof = _RESTRICTION.oneofs_by_name[ + 'country_restriction'] +_AVAILABILITY.fields_by_name['start'].message_type = _DATE +_SALEPERIOD.fields_by_name['restriction'].message_type = _RESTRICTION +_SALEPERIOD.fields_by_name['start'].message_type = _DATE +_SALEPERIOD.fields_by_name['end'].message_type = _DATE +_AUDIOFILE.fields_by_name['format'].enum_type = _AUDIOFILE_FORMAT +_AUDIOFILE_FORMAT.containing_type = _AUDIOFILE +DESCRIPTOR.message_types_by_name['Artist'] = _ARTIST +DESCRIPTOR.message_types_by_name['Album'] = _ALBUM +DESCRIPTOR.message_types_by_name['Track'] = _TRACK +DESCRIPTOR.message_types_by_name['Show'] = _SHOW +DESCRIPTOR.message_types_by_name['Episode'] = _EPISODE +DESCRIPTOR.message_types_by_name['Licensor'] = _LICENSOR +DESCRIPTOR.message_types_by_name['TopTracks'] = _TOPTRACKS +DESCRIPTOR.message_types_by_name['ActivityPeriod'] = _ACTIVITYPERIOD +DESCRIPTOR.message_types_by_name['AlbumGroup'] = _ALBUMGROUP +DESCRIPTOR.message_types_by_name['Date'] = _DATE +DESCRIPTOR.message_types_by_name['Image'] = _IMAGE +DESCRIPTOR.message_types_by_name['ImageGroup'] = _IMAGEGROUP +DESCRIPTOR.message_types_by_name['Biography'] = _BIOGRAPHY +DESCRIPTOR.message_types_by_name['Disc'] = _DISC +DESCRIPTOR.message_types_by_name['Copyright'] = _COPYRIGHT +DESCRIPTOR.message_types_by_name['Restriction'] = _RESTRICTION +DESCRIPTOR.message_types_by_name['Availability'] = _AVAILABILITY +DESCRIPTOR.message_types_by_name['SalePeriod'] = _SALEPERIOD +DESCRIPTOR.message_types_by_name['ExternalId'] = _EXTERNALID +DESCRIPTOR.message_types_by_name['AudioFile'] = _AUDIOFILE +DESCRIPTOR.message_types_by_name['VideoFile'] = _VIDEOFILE +_sym_db.RegisterFileDescriptor(DESCRIPTOR) + +Artist = _reflection.GeneratedProtocolMessageType( + 'Artist', + (_message.Message, ), + { + 'DESCRIPTOR': _ARTIST, + '__module__': 'metadata_pb2' + # @@protoc_insertion_point(class_scope:spotify.metadata.proto.Artist) + }) +_sym_db.RegisterMessage(Artist) + +Album = _reflection.GeneratedProtocolMessageType( + 'Album', + (_message.Message, ), + { + 'DESCRIPTOR': _ALBUM, + '__module__': 'metadata_pb2' + # @@protoc_insertion_point(class_scope:spotify.metadata.proto.Album) + }) +_sym_db.RegisterMessage(Album) + +Track = _reflection.GeneratedProtocolMessageType( + 'Track', + (_message.Message, ), + { + 'DESCRIPTOR': _TRACK, + '__module__': 'metadata_pb2' + # @@protoc_insertion_point(class_scope:spotify.metadata.proto.Track) + }) +_sym_db.RegisterMessage(Track) + +Show = _reflection.GeneratedProtocolMessageType( + 'Show', + (_message.Message, ), + { + 'DESCRIPTOR': _SHOW, + '__module__': 'metadata_pb2' + # @@protoc_insertion_point(class_scope:spotify.metadata.proto.Show) + }) +_sym_db.RegisterMessage(Show) + +Episode = _reflection.GeneratedProtocolMessageType( + 'Episode', + (_message.Message, ), + { + 'DESCRIPTOR': _EPISODE, + '__module__': 'metadata_pb2' + # @@protoc_insertion_point(class_scope:spotify.metadata.proto.Episode) + }) +_sym_db.RegisterMessage(Episode) + +Licensor = _reflection.GeneratedProtocolMessageType( + 'Licensor', + (_message.Message, ), + { + 'DESCRIPTOR': _LICENSOR, + '__module__': 'metadata_pb2' + # @@protoc_insertion_point(class_scope:spotify.metadata.proto.Licensor) + }) +_sym_db.RegisterMessage(Licensor) + +TopTracks = _reflection.GeneratedProtocolMessageType( + 'TopTracks', + (_message.Message, ), + { + 'DESCRIPTOR': _TOPTRACKS, + '__module__': 'metadata_pb2' + # @@protoc_insertion_point(class_scope:spotify.metadata.proto.TopTracks) + }) +_sym_db.RegisterMessage(TopTracks) + +ActivityPeriod = _reflection.GeneratedProtocolMessageType( + 'ActivityPeriod', + (_message.Message, ), + { + 'DESCRIPTOR': _ACTIVITYPERIOD, + '__module__': 'metadata_pb2' + # @@protoc_insertion_point(class_scope:spotify.metadata.proto.ActivityPeriod) + }) +_sym_db.RegisterMessage(ActivityPeriod) + +AlbumGroup = _reflection.GeneratedProtocolMessageType( + 'AlbumGroup', + (_message.Message, ), + { + 'DESCRIPTOR': _ALBUMGROUP, + '__module__': 'metadata_pb2' + # @@protoc_insertion_point(class_scope:spotify.metadata.proto.AlbumGroup) + }) +_sym_db.RegisterMessage(AlbumGroup) + +Date = _reflection.GeneratedProtocolMessageType( + 'Date', + (_message.Message, ), + { + 'DESCRIPTOR': _DATE, + '__module__': 'metadata_pb2' + # @@protoc_insertion_point(class_scope:spotify.metadata.proto.Date) + }) +_sym_db.RegisterMessage(Date) + +Image = _reflection.GeneratedProtocolMessageType( + 'Image', + (_message.Message, ), + { + 'DESCRIPTOR': _IMAGE, + '__module__': 'metadata_pb2' + # @@protoc_insertion_point(class_scope:spotify.metadata.proto.Image) + }) +_sym_db.RegisterMessage(Image) + +ImageGroup = _reflection.GeneratedProtocolMessageType( + 'ImageGroup', + (_message.Message, ), + { + 'DESCRIPTOR': _IMAGEGROUP, + '__module__': 'metadata_pb2' + # @@protoc_insertion_point(class_scope:spotify.metadata.proto.ImageGroup) + }) +_sym_db.RegisterMessage(ImageGroup) + +Biography = _reflection.GeneratedProtocolMessageType( + 'Biography', + (_message.Message, ), + { + 'DESCRIPTOR': _BIOGRAPHY, + '__module__': 'metadata_pb2' + # @@protoc_insertion_point(class_scope:spotify.metadata.proto.Biography) + }) +_sym_db.RegisterMessage(Biography) + +Disc = _reflection.GeneratedProtocolMessageType( + 'Disc', + (_message.Message, ), + { + 'DESCRIPTOR': _DISC, + '__module__': 'metadata_pb2' + # @@protoc_insertion_point(class_scope:spotify.metadata.proto.Disc) + }) +_sym_db.RegisterMessage(Disc) + +Copyright = _reflection.GeneratedProtocolMessageType( + 'Copyright', + (_message.Message, ), + { + 'DESCRIPTOR': _COPYRIGHT, + '__module__': 'metadata_pb2' + # @@protoc_insertion_point(class_scope:spotify.metadata.proto.Copyright) + }) +_sym_db.RegisterMessage(Copyright) + +Restriction = _reflection.GeneratedProtocolMessageType( + 'Restriction', + (_message.Message, ), + { + 'DESCRIPTOR': _RESTRICTION, + '__module__': 'metadata_pb2' + # @@protoc_insertion_point(class_scope:spotify.metadata.proto.Restriction) + }) +_sym_db.RegisterMessage(Restriction) + +Availability = _reflection.GeneratedProtocolMessageType( + 'Availability', + (_message.Message, ), + { + 'DESCRIPTOR': _AVAILABILITY, + '__module__': 'metadata_pb2' + # @@protoc_insertion_point(class_scope:spotify.metadata.proto.Availability) + }) +_sym_db.RegisterMessage(Availability) + +SalePeriod = _reflection.GeneratedProtocolMessageType( + 'SalePeriod', + (_message.Message, ), + { + 'DESCRIPTOR': _SALEPERIOD, + '__module__': 'metadata_pb2' + # @@protoc_insertion_point(class_scope:spotify.metadata.proto.SalePeriod) + }) +_sym_db.RegisterMessage(SalePeriod) + +ExternalId = _reflection.GeneratedProtocolMessageType( + 'ExternalId', + (_message.Message, ), + { + 'DESCRIPTOR': _EXTERNALID, + '__module__': 'metadata_pb2' + # @@protoc_insertion_point(class_scope:spotify.metadata.proto.ExternalId) + }) +_sym_db.RegisterMessage(ExternalId) + +AudioFile = _reflection.GeneratedProtocolMessageType( + 'AudioFile', + (_message.Message, ), + { + 'DESCRIPTOR': _AUDIOFILE, + '__module__': 'metadata_pb2' + # @@protoc_insertion_point(class_scope:spotify.metadata.proto.AudioFile) + }) +_sym_db.RegisterMessage(AudioFile) + +VideoFile = _reflection.GeneratedProtocolMessageType( + 'VideoFile', + (_message.Message, ), + { + 'DESCRIPTOR': _VIDEOFILE, + '__module__': 'metadata_pb2' + # @@protoc_insertion_point(class_scope:spotify.metadata.proto.VideoFile) + }) +_sym_db.RegisterMessage(VideoFile) + +DESCRIPTOR._options = None +_SHOW.fields_by_name['deprecated_popularity']._options = None +_EPISODE.fields_by_name['deprecated_popularity']._options = None +# @@protoc_insertion_point(module_scope) diff --git a/librespot/proto/PlayOrigin_pb2.py b/librespot/proto/PlayOrigin_pb2.py new file mode 100644 index 0000000..64b3efe --- /dev/null +++ b/librespot/proto/PlayOrigin_pb2.py @@ -0,0 +1,193 @@ +# -*- coding: utf-8 -*- +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: play_origin.proto +"""Generated protocol buffer code.""" +from google.protobuf import descriptor as _descriptor +from google.protobuf import message as _message +from google.protobuf import reflection as _reflection +from google.protobuf import symbol_database as _symbol_database + +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + +DESCRIPTOR = _descriptor.FileDescriptor( + name="play_origin.proto", + package="spotify.player.proto", + syntax="proto2", + serialized_options=b"\n\023com.spotify.contextH\002", + 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', +) + +_PLAYORIGIN = _descriptor.Descriptor( + name="PlayOrigin", + full_name="spotify.player.proto.PlayOrigin", + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name="feature_identifier", + full_name="spotify.player.proto.PlayOrigin.feature_identifier", + index=0, + number=1, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"".decode("utf-8"), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="feature_version", + full_name="spotify.player.proto.PlayOrigin.feature_version", + index=1, + number=2, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"".decode("utf-8"), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="view_uri", + full_name="spotify.player.proto.PlayOrigin.view_uri", + index=2, + number=3, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"".decode("utf-8"), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="external_referrer", + full_name="spotify.player.proto.PlayOrigin.external_referrer", + index=3, + number=4, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"".decode("utf-8"), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="referrer_identifier", + full_name="spotify.player.proto.PlayOrigin.referrer_identifier", + index=4, + number=5, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"".decode("utf-8"), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="device_identifier", + full_name="spotify.player.proto.PlayOrigin.device_identifier", + index=5, + number=6, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"".decode("utf-8"), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="feature_classes", + full_name="spotify.player.proto.PlayOrigin.feature_classes", + index=6, + number=7, + type=9, + cpp_type=9, + label=3, + has_default_value=False, + default_value=[], + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax="proto2", + extension_ranges=[], + oneofs=[], + serialized_start=44, + serialized_end=235, +) + +DESCRIPTOR.message_types_by_name["PlayOrigin"] = _PLAYORIGIN +_sym_db.RegisterFileDescriptor(DESCRIPTOR) + +PlayOrigin = _reflection.GeneratedProtocolMessageType( + "PlayOrigin", + (_message.Message, ), + { + "DESCRIPTOR": _PLAYORIGIN, + "__module__": "play_origin_pb2" + # @@protoc_insertion_point(class_scope:spotify.player.proto.PlayOrigin) + }, +) +_sym_db.RegisterMessage(PlayOrigin) + +DESCRIPTOR._options = None +# @@protoc_insertion_point(module_scope) diff --git a/librespot/proto/Playback_pb2.py b/librespot/proto/Playback_pb2.py new file mode 100644 index 0000000..881cfeb --- /dev/null +++ b/librespot/proto/Playback_pb2.py @@ -0,0 +1,162 @@ +# -*- coding: utf-8 -*- +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: playback.proto +"""Generated protocol buffer code.""" +import ContextTrack_pb2 as context__track__pb2 +from google.protobuf import descriptor as _descriptor +from google.protobuf import message as _message +from google.protobuf import reflection as _reflection +from google.protobuf import symbol_database as _symbol_database + +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + +DESCRIPTOR = _descriptor.FileDescriptor( + name="playback.proto", + package="spotify.player.proto.transfer", + syntax="proto2", + serialized_options=b"\n\024com.spotify.transferH\002", + 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', + dependencies=[ + context__track__pb2.DESCRIPTOR, + ], +) + +_PLAYBACK = _descriptor.Descriptor( + name="Playback", + full_name="spotify.player.proto.transfer.Playback", + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name="timestamp", + full_name="spotify.player.proto.transfer.Playback.timestamp", + index=0, + number=1, + type=3, + cpp_type=2, + label=1, + has_default_value=False, + default_value=0, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="position_as_of_timestamp", + full_name= + "spotify.player.proto.transfer.Playback.position_as_of_timestamp", + index=1, + number=2, + type=5, + cpp_type=1, + label=1, + has_default_value=False, + default_value=0, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="playback_speed", + full_name="spotify.player.proto.transfer.Playback.playback_speed", + index=2, + number=3, + type=1, + cpp_type=5, + label=1, + has_default_value=False, + default_value=float(0), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="is_paused", + full_name="spotify.player.proto.transfer.Playback.is_paused", + index=3, + number=4, + type=8, + cpp_type=7, + label=1, + has_default_value=False, + default_value=False, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="current_track", + full_name="spotify.player.proto.transfer.Playback.current_track", + index=4, + number=5, + type=11, + cpp_type=10, + label=1, + has_default_value=False, + default_value=None, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax="proto2", + extension_ranges=[], + oneofs=[], + serialized_start=71, + serialized_end=236, +) + +_PLAYBACK.fields_by_name[ + "current_track"].message_type = context__track__pb2._CONTEXTTRACK +DESCRIPTOR.message_types_by_name["Playback"] = _PLAYBACK +_sym_db.RegisterFileDescriptor(DESCRIPTOR) + +Playback = _reflection.GeneratedProtocolMessageType( + "Playback", + (_message.Message, ), + { + "DESCRIPTOR": _PLAYBACK, + "__module__": "playback_pb2" + # @@protoc_insertion_point(class_scope:spotify.player.proto.transfer.Playback) + }, +) +_sym_db.RegisterMessage(Playback) + +DESCRIPTOR._options = None +# @@protoc_insertion_point(module_scope) diff --git a/librespot/proto/Player_pb2.py b/librespot/proto/Player_pb2.py new file mode 100644 index 0000000..cd267de --- /dev/null +++ b/librespot/proto/Player_pb2.py @@ -0,0 +1,1851 @@ +# -*- coding: utf-8 -*- +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: player.proto +"""Generated protocol buffer code.""" +from google.protobuf import descriptor as _descriptor +from google.protobuf import message as _message +from google.protobuf import reflection as _reflection +from google.protobuf import symbol_database as _symbol_database +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + +DESCRIPTOR = _descriptor.FileDescriptor( + name='player.proto', + package='connectstate', + syntax='proto3', + serialized_options=b'\n\030com.spotify.connectstateH\002', + create_key=_descriptor._internal_create_key, + serialized_pb= + b'\n\x0cplayer.proto\x12\x0c\x63onnectstate\"\xea\x08\n\x0bPlayerState\x12\x11\n\ttimestamp\x18\x01 \x01(\x03\x12\x13\n\x0b\x63ontext_uri\x18\x02 \x01(\t\x12\x13\n\x0b\x63ontext_url\x18\x03 \x01(\t\x12\x38\n\x14\x63ontext_restrictions\x18\x04 \x01(\x0b\x32\x1a.connectstate.Restrictions\x12-\n\x0bplay_origin\x18\x05 \x01(\x0b\x32\x18.connectstate.PlayOrigin\x12)\n\x05index\x18\x06 \x01(\x0b\x32\x1a.connectstate.ContextIndex\x12*\n\x05track\x18\x07 \x01(\x0b\x32\x1b.connectstate.ProvidedTrack\x12\x13\n\x0bplayback_id\x18\x08 \x01(\t\x12\x16\n\x0eplayback_speed\x18\t \x01(\x01\x12 \n\x18position_as_of_timestamp\x18\n \x01(\x03\x12\x10\n\x08\x64uration\x18\x0b \x01(\x03\x12\x12\n\nis_playing\x18\x0c \x01(\x08\x12\x11\n\tis_paused\x18\r \x01(\x08\x12\x14\n\x0cis_buffering\x18\x0e \x01(\x08\x12\x1b\n\x13is_system_initiated\x18\x0f \x01(\x08\x12\x33\n\x07options\x18\x10 \x01(\x0b\x32\".connectstate.ContextPlayerOptions\x12\x30\n\x0crestrictions\x18\x11 \x01(\x0b\x32\x1a.connectstate.Restrictions\x12\x30\n\x0csuppressions\x18\x12 \x01(\x0b\x32\x1a.connectstate.Suppressions\x12\x30\n\x0bprev_tracks\x18\x13 \x03(\x0b\x32\x1b.connectstate.ProvidedTrack\x12\x30\n\x0bnext_tracks\x18\x14 \x03(\x0b\x32\x1b.connectstate.ProvidedTrack\x12H\n\x10\x63ontext_metadata\x18\x15 \x03(\x0b\x32..connectstate.PlayerState.ContextMetadataEntry\x12\x42\n\rpage_metadata\x18\x16 \x03(\x0b\x32+.connectstate.PlayerState.PageMetadataEntry\x12\x12\n\nsession_id\x18\x17 \x01(\t\x12\x16\n\x0equeue_revision\x18\x18 \x01(\t\x12\x10\n\x08position\x18\x19 \x01(\x03\x12\x12\n\nentity_uri\x18\x1a \x01(\t\x12,\n\x07reverse\x18\x1b \x03(\x0b\x32\x1b.connectstate.ProvidedTrack\x12+\n\x06\x66uture\x18\x1c \x03(\x0b\x32\x1b.connectstate.ProvidedTrack\x1a\x36\n\x14\x43ontextMetadataEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x1a\x33\n\x11PageMetadataEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\"\xda\x02\n\rProvidedTrack\x12\x0b\n\x03uri\x18\x01 \x01(\t\x12\x0b\n\x03uid\x18\x02 \x01(\t\x12;\n\x08metadata\x18\x03 \x03(\x0b\x32).connectstate.ProvidedTrack.MetadataEntry\x12\x0f\n\x07removed\x18\x04 \x03(\t\x12\x0f\n\x07\x62locked\x18\x05 \x03(\t\x12\x10\n\x08provider\x18\x06 \x01(\t\x12\x30\n\x0crestrictions\x18\x07 \x01(\x0b\x32\x1a.connectstate.Restrictions\x12\x11\n\talbum_uri\x18\x08 \x01(\t\x12\x18\n\x10\x64isallow_reasons\x18\t \x03(\t\x12\x12\n\nartist_uri\x18\n \x01(\t\x12\x1a\n\x12\x64isallow_undecided\x18\x0b \x03(\t\x1a/\n\rMetadataEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\"+\n\x0c\x43ontextIndex\x12\x0c\n\x04page\x18\x01 \x01(\r\x12\r\n\x05track\x18\x02 \x01(\r\"\x80\x08\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(\t\x12 \n\x18\x64isallow_playing_reasons\x18\x16 \x03(\t\x12!\n\x19\x64isallow_stopping_reasons\x18\x17 \x03(\t\"\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(\t\"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\"!\n\x0cSuppressions\x12\x11\n\tproviders\x18\x01 \x03(\tB\x1c\n\x18\x63om.spotify.connectstateH\x02\x62\x06proto3' +) + +_PLAYERSTATE_CONTEXTMETADATAENTRY = _descriptor.Descriptor( + name='ContextMetadataEntry', + full_name='connectstate.PlayerState.ContextMetadataEntry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='key', + full_name='connectstate.PlayerState.ContextMetadataEntry.key', + index=0, + number=1, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"".decode('utf-8'), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='value', + full_name='connectstate.PlayerState.ContextMetadataEntry.value', + index=1, + number=2, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"".decode('utf-8'), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=b'8\001', + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[], + serialized_start=1054, + serialized_end=1108, +) + +_PLAYERSTATE_PAGEMETADATAENTRY = _descriptor.Descriptor( + name='PageMetadataEntry', + full_name='connectstate.PlayerState.PageMetadataEntry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='key', + full_name='connectstate.PlayerState.PageMetadataEntry.key', + index=0, + number=1, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"".decode('utf-8'), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='value', + full_name='connectstate.PlayerState.PageMetadataEntry.value', + index=1, + number=2, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"".decode('utf-8'), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=b'8\001', + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[], + serialized_start=1110, + serialized_end=1161, +) + +_PLAYERSTATE = _descriptor.Descriptor( + name='PlayerState', + full_name='connectstate.PlayerState', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='timestamp', + full_name='connectstate.PlayerState.timestamp', + index=0, + number=1, + type=3, + cpp_type=2, + label=1, + has_default_value=False, + default_value=0, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='context_uri', + full_name='connectstate.PlayerState.context_uri', + index=1, + number=2, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"".decode('utf-8'), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='context_url', + full_name='connectstate.PlayerState.context_url', + index=2, + number=3, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"".decode('utf-8'), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='context_restrictions', + full_name='connectstate.PlayerState.context_restrictions', + index=3, + number=4, + type=11, + cpp_type=10, + label=1, + has_default_value=False, + default_value=None, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='play_origin', + full_name='connectstate.PlayerState.play_origin', + index=4, + number=5, + type=11, + cpp_type=10, + label=1, + has_default_value=False, + default_value=None, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='index', + full_name='connectstate.PlayerState.index', + index=5, + number=6, + type=11, + cpp_type=10, + label=1, + has_default_value=False, + default_value=None, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='track', + full_name='connectstate.PlayerState.track', + index=6, + number=7, + type=11, + cpp_type=10, + label=1, + has_default_value=False, + default_value=None, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='playback_id', + full_name='connectstate.PlayerState.playback_id', + index=7, + number=8, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"".decode('utf-8'), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='playback_speed', + full_name='connectstate.PlayerState.playback_speed', + index=8, + number=9, + type=1, + cpp_type=5, + label=1, + has_default_value=False, + default_value=float(0), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='position_as_of_timestamp', + full_name='connectstate.PlayerState.position_as_of_timestamp', + index=9, + number=10, + type=3, + cpp_type=2, + label=1, + has_default_value=False, + default_value=0, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='duration', + full_name='connectstate.PlayerState.duration', + index=10, + number=11, + type=3, + cpp_type=2, + label=1, + has_default_value=False, + default_value=0, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='is_playing', + full_name='connectstate.PlayerState.is_playing', + index=11, + number=12, + type=8, + cpp_type=7, + label=1, + has_default_value=False, + default_value=False, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='is_paused', + full_name='connectstate.PlayerState.is_paused', + index=12, + number=13, + type=8, + cpp_type=7, + label=1, + has_default_value=False, + default_value=False, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='is_buffering', + full_name='connectstate.PlayerState.is_buffering', + index=13, + number=14, + type=8, + cpp_type=7, + label=1, + has_default_value=False, + default_value=False, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='is_system_initiated', + full_name='connectstate.PlayerState.is_system_initiated', + index=14, + number=15, + type=8, + cpp_type=7, + label=1, + has_default_value=False, + default_value=False, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='options', + full_name='connectstate.PlayerState.options', + index=15, + number=16, + type=11, + cpp_type=10, + label=1, + has_default_value=False, + default_value=None, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='restrictions', + full_name='connectstate.PlayerState.restrictions', + index=16, + number=17, + type=11, + cpp_type=10, + label=1, + has_default_value=False, + default_value=None, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='suppressions', + full_name='connectstate.PlayerState.suppressions', + index=17, + number=18, + type=11, + cpp_type=10, + label=1, + has_default_value=False, + default_value=None, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='prev_tracks', + full_name='connectstate.PlayerState.prev_tracks', + index=18, + number=19, + type=11, + cpp_type=10, + label=3, + has_default_value=False, + default_value=[], + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='next_tracks', + full_name='connectstate.PlayerState.next_tracks', + index=19, + number=20, + type=11, + cpp_type=10, + label=3, + has_default_value=False, + default_value=[], + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='context_metadata', + full_name='connectstate.PlayerState.context_metadata', + index=20, + number=21, + type=11, + cpp_type=10, + label=3, + has_default_value=False, + default_value=[], + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='page_metadata', + full_name='connectstate.PlayerState.page_metadata', + index=21, + number=22, + type=11, + cpp_type=10, + label=3, + has_default_value=False, + default_value=[], + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='session_id', + full_name='connectstate.PlayerState.session_id', + index=22, + number=23, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"".decode('utf-8'), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='queue_revision', + full_name='connectstate.PlayerState.queue_revision', + index=23, + number=24, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"".decode('utf-8'), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='position', + full_name='connectstate.PlayerState.position', + index=24, + number=25, + type=3, + cpp_type=2, + label=1, + has_default_value=False, + default_value=0, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='entity_uri', + full_name='connectstate.PlayerState.entity_uri', + index=25, + number=26, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"".decode('utf-8'), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='reverse', + full_name='connectstate.PlayerState.reverse', + index=26, + number=27, + type=11, + cpp_type=10, + label=3, + has_default_value=False, + default_value=[], + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='future', + full_name='connectstate.PlayerState.future', + index=27, + number=28, + type=11, + cpp_type=10, + label=3, + has_default_value=False, + default_value=[], + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + ], + extensions=[], + nested_types=[ + _PLAYERSTATE_CONTEXTMETADATAENTRY, + _PLAYERSTATE_PAGEMETADATAENTRY, + ], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[], + serialized_start=31, + serialized_end=1161, +) + +_PROVIDEDTRACK_METADATAENTRY = _descriptor.Descriptor( + name='MetadataEntry', + full_name='connectstate.ProvidedTrack.MetadataEntry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='key', + full_name='connectstate.ProvidedTrack.MetadataEntry.key', + index=0, + number=1, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"".decode('utf-8'), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='value', + full_name='connectstate.ProvidedTrack.MetadataEntry.value', + index=1, + number=2, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"".decode('utf-8'), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=b'8\001', + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[], + serialized_start=1463, + serialized_end=1510, +) + +_PROVIDEDTRACK = _descriptor.Descriptor( + name='ProvidedTrack', + full_name='connectstate.ProvidedTrack', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='uri', + full_name='connectstate.ProvidedTrack.uri', + index=0, + number=1, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"".decode('utf-8'), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='uid', + full_name='connectstate.ProvidedTrack.uid', + index=1, + number=2, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"".decode('utf-8'), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='metadata', + full_name='connectstate.ProvidedTrack.metadata', + index=2, + number=3, + type=11, + cpp_type=10, + label=3, + has_default_value=False, + default_value=[], + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='removed', + full_name='connectstate.ProvidedTrack.removed', + index=3, + number=4, + type=9, + cpp_type=9, + label=3, + has_default_value=False, + default_value=[], + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='blocked', + full_name='connectstate.ProvidedTrack.blocked', + index=4, + number=5, + type=9, + cpp_type=9, + label=3, + has_default_value=False, + default_value=[], + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='provider', + full_name='connectstate.ProvidedTrack.provider', + index=5, + number=6, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"".decode('utf-8'), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='restrictions', + full_name='connectstate.ProvidedTrack.restrictions', + index=6, + number=7, + type=11, + cpp_type=10, + label=1, + has_default_value=False, + default_value=None, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='album_uri', + full_name='connectstate.ProvidedTrack.album_uri', + index=7, + number=8, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"".decode('utf-8'), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='disallow_reasons', + full_name='connectstate.ProvidedTrack.disallow_reasons', + index=8, + number=9, + type=9, + cpp_type=9, + label=3, + has_default_value=False, + default_value=[], + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='artist_uri', + full_name='connectstate.ProvidedTrack.artist_uri', + index=9, + number=10, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"".decode('utf-8'), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='disallow_undecided', + full_name='connectstate.ProvidedTrack.disallow_undecided', + index=10, + number=11, + type=9, + cpp_type=9, + label=3, + has_default_value=False, + default_value=[], + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + ], + extensions=[], + nested_types=[ + _PROVIDEDTRACK_METADATAENTRY, + ], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[], + serialized_start=1164, + serialized_end=1510, +) + +_CONTEXTINDEX = _descriptor.Descriptor( + name='ContextIndex', + full_name='connectstate.ContextIndex', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='page', + full_name='connectstate.ContextIndex.page', + index=0, + number=1, + type=13, + cpp_type=3, + label=1, + has_default_value=False, + default_value=0, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='track', + full_name='connectstate.ContextIndex.track', + index=1, + number=2, + type=13, + cpp_type=3, + label=1, + has_default_value=False, + default_value=0, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[], + serialized_start=1512, + serialized_end=1555, +) + +_RESTRICTIONS = _descriptor.Descriptor( + name='Restrictions', + full_name='connectstate.Restrictions', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='disallow_pausing_reasons', + full_name='connectstate.Restrictions.disallow_pausing_reasons', + index=0, + number=1, + type=9, + cpp_type=9, + label=3, + has_default_value=False, + default_value=[], + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='disallow_resuming_reasons', + full_name='connectstate.Restrictions.disallow_resuming_reasons', + index=1, + number=2, + type=9, + cpp_type=9, + label=3, + has_default_value=False, + default_value=[], + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='disallow_seeking_reasons', + full_name='connectstate.Restrictions.disallow_seeking_reasons', + index=2, + number=3, + type=9, + cpp_type=9, + label=3, + has_default_value=False, + default_value=[], + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='disallow_peeking_prev_reasons', + full_name='connectstate.Restrictions.disallow_peeking_prev_reasons', + index=3, + number=4, + type=9, + cpp_type=9, + label=3, + has_default_value=False, + default_value=[], + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='disallow_peeking_next_reasons', + full_name='connectstate.Restrictions.disallow_peeking_next_reasons', + index=4, + number=5, + type=9, + cpp_type=9, + label=3, + has_default_value=False, + default_value=[], + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='disallow_skipping_prev_reasons', + full_name= + 'connectstate.Restrictions.disallow_skipping_prev_reasons', + index=5, + number=6, + type=9, + cpp_type=9, + label=3, + has_default_value=False, + default_value=[], + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='disallow_skipping_next_reasons', + full_name= + 'connectstate.Restrictions.disallow_skipping_next_reasons', + index=6, + number=7, + type=9, + cpp_type=9, + label=3, + has_default_value=False, + default_value=[], + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='disallow_toggling_repeat_context_reasons', + full_name= + 'connectstate.Restrictions.disallow_toggling_repeat_context_reasons', + index=7, + number=8, + type=9, + cpp_type=9, + label=3, + has_default_value=False, + default_value=[], + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='disallow_toggling_repeat_track_reasons', + full_name= + 'connectstate.Restrictions.disallow_toggling_repeat_track_reasons', + index=8, + number=9, + type=9, + cpp_type=9, + label=3, + has_default_value=False, + default_value=[], + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='disallow_toggling_shuffle_reasons', + full_name= + 'connectstate.Restrictions.disallow_toggling_shuffle_reasons', + index=9, + number=10, + type=9, + cpp_type=9, + label=3, + has_default_value=False, + default_value=[], + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='disallow_set_queue_reasons', + full_name='connectstate.Restrictions.disallow_set_queue_reasons', + index=10, + number=11, + type=9, + cpp_type=9, + label=3, + has_default_value=False, + default_value=[], + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='disallow_interrupting_playback_reasons', + full_name= + 'connectstate.Restrictions.disallow_interrupting_playback_reasons', + index=11, + number=12, + type=9, + cpp_type=9, + label=3, + has_default_value=False, + default_value=[], + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='disallow_transferring_playback_reasons', + full_name= + 'connectstate.Restrictions.disallow_transferring_playback_reasons', + index=12, + number=13, + type=9, + cpp_type=9, + label=3, + has_default_value=False, + default_value=[], + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='disallow_remote_control_reasons', + full_name= + 'connectstate.Restrictions.disallow_remote_control_reasons', + index=13, + number=14, + type=9, + cpp_type=9, + label=3, + has_default_value=False, + default_value=[], + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='disallow_inserting_into_next_tracks_reasons', + full_name= + 'connectstate.Restrictions.disallow_inserting_into_next_tracks_reasons', + index=14, + number=15, + type=9, + cpp_type=9, + label=3, + has_default_value=False, + default_value=[], + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='disallow_inserting_into_context_tracks_reasons', + full_name= + 'connectstate.Restrictions.disallow_inserting_into_context_tracks_reasons', + index=15, + number=16, + type=9, + cpp_type=9, + label=3, + has_default_value=False, + default_value=[], + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='disallow_reordering_in_next_tracks_reasons', + full_name= + 'connectstate.Restrictions.disallow_reordering_in_next_tracks_reasons', + index=16, + number=17, + type=9, + cpp_type=9, + label=3, + has_default_value=False, + default_value=[], + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='disallow_reordering_in_context_tracks_reasons', + full_name= + 'connectstate.Restrictions.disallow_reordering_in_context_tracks_reasons', + index=17, + number=18, + type=9, + cpp_type=9, + label=3, + has_default_value=False, + default_value=[], + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='disallow_removing_from_next_tracks_reasons', + full_name= + 'connectstate.Restrictions.disallow_removing_from_next_tracks_reasons', + index=18, + number=19, + type=9, + cpp_type=9, + label=3, + has_default_value=False, + default_value=[], + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='disallow_removing_from_context_tracks_reasons', + full_name= + 'connectstate.Restrictions.disallow_removing_from_context_tracks_reasons', + index=19, + number=20, + type=9, + cpp_type=9, + label=3, + has_default_value=False, + default_value=[], + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='disallow_updating_context_reasons', + full_name= + 'connectstate.Restrictions.disallow_updating_context_reasons', + index=20, + number=21, + type=9, + cpp_type=9, + label=3, + has_default_value=False, + default_value=[], + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='disallow_playing_reasons', + full_name='connectstate.Restrictions.disallow_playing_reasons', + index=21, + number=22, + type=9, + cpp_type=9, + label=3, + has_default_value=False, + default_value=[], + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='disallow_stopping_reasons', + full_name='connectstate.Restrictions.disallow_stopping_reasons', + index=22, + number=23, + type=9, + cpp_type=9, + label=3, + has_default_value=False, + default_value=[], + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[], + serialized_start=1558, + serialized_end=2582, +) + +_PLAYORIGIN = _descriptor.Descriptor( + name='PlayOrigin', + full_name='connectstate.PlayOrigin', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='feature_identifier', + full_name='connectstate.PlayOrigin.feature_identifier', + index=0, + number=1, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"".decode('utf-8'), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='feature_version', + full_name='connectstate.PlayOrigin.feature_version', + index=1, + number=2, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"".decode('utf-8'), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='view_uri', + full_name='connectstate.PlayOrigin.view_uri', + index=2, + number=3, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"".decode('utf-8'), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='external_referrer', + full_name='connectstate.PlayOrigin.external_referrer', + index=3, + number=4, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"".decode('utf-8'), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='referrer_identifier', + full_name='connectstate.PlayOrigin.referrer_identifier', + index=4, + number=5, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"".decode('utf-8'), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='device_identifier', + full_name='connectstate.PlayOrigin.device_identifier', + index=5, + number=6, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"".decode('utf-8'), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='feature_classes', + full_name='connectstate.PlayOrigin.feature_classes', + index=6, + number=7, + type=9, + cpp_type=9, + label=3, + has_default_value=False, + default_value=[], + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[], + serialized_start=2585, + serialized_end=2776, +) + +_CONTEXTPLAYEROPTIONS = _descriptor.Descriptor( + name='ContextPlayerOptions', + full_name='connectstate.ContextPlayerOptions', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='shuffling_context', + full_name='connectstate.ContextPlayerOptions.shuffling_context', + index=0, + number=1, + type=8, + cpp_type=7, + label=1, + has_default_value=False, + default_value=False, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='repeating_context', + full_name='connectstate.ContextPlayerOptions.repeating_context', + index=1, + number=2, + type=8, + cpp_type=7, + label=1, + has_default_value=False, + default_value=False, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='repeating_track', + full_name='connectstate.ContextPlayerOptions.repeating_track', + index=2, + number=3, + type=8, + cpp_type=7, + label=1, + has_default_value=False, + default_value=False, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[], + serialized_start=2778, + serialized_end=2879, +) + +_SUPPRESSIONS = _descriptor.Descriptor( + name='Suppressions', + full_name='connectstate.Suppressions', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='providers', + full_name='connectstate.Suppressions.providers', + index=0, + number=1, + type=9, + cpp_type=9, + label=3, + has_default_value=False, + default_value=[], + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[], + serialized_start=2881, + serialized_end=2914, +) + +_PLAYERSTATE_CONTEXTMETADATAENTRY.containing_type = _PLAYERSTATE +_PLAYERSTATE_PAGEMETADATAENTRY.containing_type = _PLAYERSTATE +_PLAYERSTATE.fields_by_name[ + 'context_restrictions'].message_type = _RESTRICTIONS +_PLAYERSTATE.fields_by_name['play_origin'].message_type = _PLAYORIGIN +_PLAYERSTATE.fields_by_name['index'].message_type = _CONTEXTINDEX +_PLAYERSTATE.fields_by_name['track'].message_type = _PROVIDEDTRACK +_PLAYERSTATE.fields_by_name['options'].message_type = _CONTEXTPLAYEROPTIONS +_PLAYERSTATE.fields_by_name['restrictions'].message_type = _RESTRICTIONS +_PLAYERSTATE.fields_by_name['suppressions'].message_type = _SUPPRESSIONS +_PLAYERSTATE.fields_by_name['prev_tracks'].message_type = _PROVIDEDTRACK +_PLAYERSTATE.fields_by_name['next_tracks'].message_type = _PROVIDEDTRACK +_PLAYERSTATE.fields_by_name[ + 'context_metadata'].message_type = _PLAYERSTATE_CONTEXTMETADATAENTRY +_PLAYERSTATE.fields_by_name[ + 'page_metadata'].message_type = _PLAYERSTATE_PAGEMETADATAENTRY +_PLAYERSTATE.fields_by_name['reverse'].message_type = _PROVIDEDTRACK +_PLAYERSTATE.fields_by_name['future'].message_type = _PROVIDEDTRACK +_PROVIDEDTRACK_METADATAENTRY.containing_type = _PROVIDEDTRACK +_PROVIDEDTRACK.fields_by_name[ + 'metadata'].message_type = _PROVIDEDTRACK_METADATAENTRY +_PROVIDEDTRACK.fields_by_name['restrictions'].message_type = _RESTRICTIONS +DESCRIPTOR.message_types_by_name['PlayerState'] = _PLAYERSTATE +DESCRIPTOR.message_types_by_name['ProvidedTrack'] = _PROVIDEDTRACK +DESCRIPTOR.message_types_by_name['ContextIndex'] = _CONTEXTINDEX +DESCRIPTOR.message_types_by_name['Restrictions'] = _RESTRICTIONS +DESCRIPTOR.message_types_by_name['PlayOrigin'] = _PLAYORIGIN +DESCRIPTOR.message_types_by_name[ + 'ContextPlayerOptions'] = _CONTEXTPLAYEROPTIONS +DESCRIPTOR.message_types_by_name['Suppressions'] = _SUPPRESSIONS +_sym_db.RegisterFileDescriptor(DESCRIPTOR) + +PlayerState = _reflection.GeneratedProtocolMessageType( + 'PlayerState', + (_message.Message, ), + { + 'ContextMetadataEntry': + _reflection.GeneratedProtocolMessageType( + 'ContextMetadataEntry', + (_message.Message, ), + { + 'DESCRIPTOR': _PLAYERSTATE_CONTEXTMETADATAENTRY, + '__module__': 'player_pb2' + # @@protoc_insertion_point(class_scope:connectstate.PlayerState.ContextMetadataEntry) + }), + 'PageMetadataEntry': + _reflection.GeneratedProtocolMessageType( + 'PageMetadataEntry', + (_message.Message, ), + { + 'DESCRIPTOR': _PLAYERSTATE_PAGEMETADATAENTRY, + '__module__': 'player_pb2' + # @@protoc_insertion_point(class_scope:connectstate.PlayerState.PageMetadataEntry) + }), + 'DESCRIPTOR': + _PLAYERSTATE, + '__module__': + 'player_pb2' + # @@protoc_insertion_point(class_scope:connectstate.PlayerState) + }) +_sym_db.RegisterMessage(PlayerState) +_sym_db.RegisterMessage(PlayerState.ContextMetadataEntry) +_sym_db.RegisterMessage(PlayerState.PageMetadataEntry) + +ProvidedTrack = _reflection.GeneratedProtocolMessageType( + 'ProvidedTrack', + (_message.Message, ), + { + 'MetadataEntry': + _reflection.GeneratedProtocolMessageType( + 'MetadataEntry', + (_message.Message, ), + { + 'DESCRIPTOR': _PROVIDEDTRACK_METADATAENTRY, + '__module__': 'player_pb2' + # @@protoc_insertion_point(class_scope:connectstate.ProvidedTrack.MetadataEntry) + }), + 'DESCRIPTOR': + _PROVIDEDTRACK, + '__module__': + 'player_pb2' + # @@protoc_insertion_point(class_scope:connectstate.ProvidedTrack) + }) +_sym_db.RegisterMessage(ProvidedTrack) +_sym_db.RegisterMessage(ProvidedTrack.MetadataEntry) + +ContextIndex = _reflection.GeneratedProtocolMessageType( + 'ContextIndex', + (_message.Message, ), + { + 'DESCRIPTOR': _CONTEXTINDEX, + '__module__': 'player_pb2' + # @@protoc_insertion_point(class_scope:connectstate.ContextIndex) + }) +_sym_db.RegisterMessage(ContextIndex) + +Restrictions = _reflection.GeneratedProtocolMessageType( + 'Restrictions', + (_message.Message, ), + { + 'DESCRIPTOR': _RESTRICTIONS, + '__module__': 'player_pb2' + # @@protoc_insertion_point(class_scope:connectstate.Restrictions) + }) +_sym_db.RegisterMessage(Restrictions) + +PlayOrigin = _reflection.GeneratedProtocolMessageType( + 'PlayOrigin', + (_message.Message, ), + { + 'DESCRIPTOR': _PLAYORIGIN, + '__module__': 'player_pb2' + # @@protoc_insertion_point(class_scope:connectstate.PlayOrigin) + }) +_sym_db.RegisterMessage(PlayOrigin) + +ContextPlayerOptions = _reflection.GeneratedProtocolMessageType( + 'ContextPlayerOptions', + (_message.Message, ), + { + 'DESCRIPTOR': _CONTEXTPLAYEROPTIONS, + '__module__': 'player_pb2' + # @@protoc_insertion_point(class_scope:connectstate.ContextPlayerOptions) + }) +_sym_db.RegisterMessage(ContextPlayerOptions) + +Suppressions = _reflection.GeneratedProtocolMessageType( + 'Suppressions', + (_message.Message, ), + { + 'DESCRIPTOR': _SUPPRESSIONS, + '__module__': 'player_pb2' + # @@protoc_insertion_point(class_scope:connectstate.Suppressions) + }) +_sym_db.RegisterMessage(Suppressions) + +DESCRIPTOR._options = None +_PLAYERSTATE_CONTEXTMETADATAENTRY._options = None +_PLAYERSTATE_PAGEMETADATAENTRY._options = None +_PROVIDEDTRACK_METADATAENTRY._options = None +# @@protoc_insertion_point(module_scope) diff --git a/librespot/proto/Playlist4External_pb2.py b/librespot/proto/Playlist4External_pb2.py new file mode 100644 index 0000000..f49f4ff --- /dev/null +++ b/librespot/proto/Playlist4External_pb2.py @@ -0,0 +1,3221 @@ +# -*- coding: utf-8 -*- +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: playlist4_external.proto +"""Generated protocol buffer code.""" +from google.protobuf import descriptor as _descriptor +from google.protobuf import message as _message +from google.protobuf import reflection as _reflection +from google.protobuf import symbol_database as _symbol_database +from google.protobuf.internal import enum_type_wrapper + +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + +DESCRIPTOR = _descriptor.FileDescriptor( + name="playlist4_external.proto", + package="spotify.playlist4.proto", + syntax="proto2", + serialized_options= + b"\n\025com.spotify.playlist4B\021Playlist4ApiProtoH\002", + create_key=_descriptor._internal_create_key, + serialized_pb= + b'\n\x18playlist4_external.proto\x12\x17spotify.playlist4.proto"P\n\x04Item\x12\x0b\n\x03uri\x18\x01 \x02(\t\x12;\n\nattributes\x18\x02 \x01(\x0b\x32\'.spotify.playlist4.proto.ItemAttributes"\x94\x01\n\x08MetaItem\x12\x10\n\x08revision\x18\x01 \x01(\x0c\x12;\n\nattributes\x18\x02 \x01(\x0b\x32\'.spotify.playlist4.proto.ListAttributes\x12\x0e\n\x06length\x18\x03 \x01(\x05\x12\x11\n\ttimestamp\x18\x04 \x01(\x03\x12\x16\n\x0eowner_username\x18\x05 \x01(\t"\x90\x01\n\tListItems\x12\x0b\n\x03pos\x18\x01 \x02(\x05\x12\x11\n\ttruncated\x18\x02 \x02(\x08\x12,\n\x05items\x18\x03 \x03(\x0b\x32\x1d.spotify.playlist4.proto.Item\x12\x35\n\nmeta_items\x18\x04 \x03(\x0b\x32!.spotify.playlist4.proto.MetaItem"1\n\x13\x46ormatListAttribute\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t"\xf6\x01\n\x0eListAttributes\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x13\n\x0b\x64\x65scription\x18\x02 \x01(\t\x12\x0f\n\x07picture\x18\x03 \x01(\x0c\x12\x15\n\rcollaborative\x18\x04 \x01(\x08\x12\x13\n\x0bpl3_version\x18\x05 \x01(\t\x12\x18\n\x10\x64\x65leted_by_owner\x18\x06 \x01(\x08\x12\x11\n\tclient_id\x18\n \x01(\t\x12\x0e\n\x06\x66ormat\x18\x0b \x01(\t\x12G\n\x11\x66ormat_attributes\x18\x0c \x03(\x0b\x32,.spotify.playlist4.proto.FormatListAttribute"\xb0\x01\n\x0eItemAttributes\x12\x10\n\x08\x61\x64\x64\x65\x64_by\x18\x01 \x01(\t\x12\x11\n\ttimestamp\x18\x02 \x01(\x03\x12\x0f\n\x07seen_at\x18\t \x01(\x03\x12\x0e\n\x06public\x18\n \x01(\x08\x12G\n\x11\x66ormat_attributes\x18\x0b \x03(\x0b\x32,.spotify.playlist4.proto.FormatListAttribute\x12\x0f\n\x07item_id\x18\x0c \x01(\x0c"l\n\x03\x41\x64\x64\x12\x12\n\nfrom_index\x18\x01 \x01(\x05\x12,\n\x05items\x18\x02 \x03(\x0b\x32\x1d.spotify.playlist4.proto.Item\x12\x10\n\x08\x61\x64\x64_last\x18\x04 \x01(\x08\x12\x11\n\tadd_first\x18\x05 \x01(\x08"m\n\x03Rem\x12\x12\n\nfrom_index\x18\x01 \x01(\x05\x12\x0e\n\x06length\x18\x02 \x01(\x05\x12,\n\x05items\x18\x03 \x03(\x0b\x32\x1d.spotify.playlist4.proto.Item\x12\x14\n\x0citems_as_key\x18\x07 \x01(\x08";\n\x03Mov\x12\x12\n\nfrom_index\x18\x01 \x02(\x05\x12\x0e\n\x06length\x18\x02 \x02(\x05\x12\x10\n\x08to_index\x18\x03 \x02(\x05"\x93\x01\n\x1aItemAttributesPartialState\x12\x37\n\x06values\x18\x01 \x02(\x0b\x32\'.spotify.playlist4.proto.ItemAttributes\x12<\n\x08no_value\x18\x02 \x03(\x0e\x32*.spotify.playlist4.proto.ItemAttributeKind"\x93\x01\n\x1aListAttributesPartialState\x12\x37\n\x06values\x18\x01 \x02(\x0b\x32\'.spotify.playlist4.proto.ListAttributes\x12<\n\x08no_value\x18\x02 \x03(\x0e\x32*.spotify.playlist4.proto.ListAttributeKind"\xbf\x01\n\x14UpdateItemAttributes\x12\r\n\x05index\x18\x01 \x02(\x05\x12K\n\x0enew_attributes\x18\x02 \x02(\x0b\x32\x33.spotify.playlist4.proto.ItemAttributesPartialState\x12K\n\x0eold_attributes\x18\x03 \x01(\x0b\x32\x33.spotify.playlist4.proto.ItemAttributesPartialState"\xb0\x01\n\x14UpdateListAttributes\x12K\n\x0enew_attributes\x18\x01 \x02(\x0b\x32\x33.spotify.playlist4.proto.ListAttributesPartialState\x12K\n\x0eold_attributes\x18\x02 \x01(\x0b\x32\x33.spotify.playlist4.proto.ListAttributesPartialState"\xc0\x03\n\x02Op\x12.\n\x04kind\x18\x01 \x02(\x0e\x32 .spotify.playlist4.proto.Op.Kind\x12)\n\x03\x61\x64\x64\x18\x02 \x01(\x0b\x32\x1c.spotify.playlist4.proto.Add\x12)\n\x03rem\x18\x03 \x01(\x0b\x32\x1c.spotify.playlist4.proto.Rem\x12)\n\x03mov\x18\x04 \x01(\x0b\x32\x1c.spotify.playlist4.proto.Mov\x12M\n\x16update_item_attributes\x18\x05 \x01(\x0b\x32-.spotify.playlist4.proto.UpdateItemAttributes\x12M\n\x16update_list_attributes\x18\x06 \x01(\x0b\x32-.spotify.playlist4.proto.UpdateListAttributes"k\n\x04Kind\x12\x10\n\x0cKIND_UNKNOWN\x10\x00\x12\x07\n\x03\x41\x44\x44\x10\x02\x12\x07\n\x03REM\x10\x03\x12\x07\n\x03MOV\x10\x04\x12\x1a\n\x16UPDATE_ITEM_ATTRIBUTES\x10\x05\x12\x1a\n\x16UPDATE_LIST_ATTRIBUTES\x10\x06"2\n\x06OpList\x12(\n\x03ops\x18\x01 \x03(\x0b\x32\x1b.spotify.playlist4.proto.Op"\xd5\x01\n\nChangeInfo\x12\x0c\n\x04user\x18\x01 \x01(\t\x12\x11\n\ttimestamp\x18\x02 \x01(\x03\x12\r\n\x05\x61\x64min\x18\x03 \x01(\x08\x12\x0c\n\x04undo\x18\x04 \x01(\x08\x12\x0c\n\x04redo\x18\x05 \x01(\x08\x12\r\n\x05merge\x18\x06 \x01(\x08\x12\x12\n\ncompressed\x18\x07 \x01(\x08\x12\x11\n\tmigration\x18\x08 \x01(\x08\x12\x10\n\x08split_id\x18\t \x01(\x05\x12\x33\n\x06source\x18\n \x01(\x0b\x32#.spotify.playlist4.proto.SourceInfo"\xe8\x01\n\nSourceInfo\x12:\n\x06\x63lient\x18\x01 \x01(\x0e\x32*.spotify.playlist4.proto.SourceInfo.Client\x12\x0b\n\x03\x61pp\x18\x03 \x01(\t\x12\x0e\n\x06source\x18\x04 \x01(\t\x12\x0f\n\x07version\x18\x05 \x01(\t"p\n\x06\x43lient\x12\x12\n\x0e\x43LIENT_UNKNOWN\x10\x00\x12\x11\n\rNATIVE_HERMES\x10\x01\x12\n\n\x06\x43LIENT\x10\x02\x12\n\n\x06PYTHON\x10\x03\x12\x08\n\x04JAVA\x10\x04\x12\r\n\tWEBPLAYER\x10\x05\x12\x0e\n\nLIBSPOTIFY\x10\x06"z\n\x05\x44\x65lta\x12\x14\n\x0c\x62\x61se_version\x18\x01 \x01(\x0c\x12(\n\x03ops\x18\x02 \x03(\x0b\x32\x1b.spotify.playlist4.proto.Op\x12\x31\n\x04info\x18\x04 \x01(\x0b\x32#.spotify.playlist4.proto.ChangeInfo"\\\n\x04\x44iff\x12\x15\n\rfrom_revision\x18\x01 \x02(\x0c\x12(\n\x03ops\x18\x02 \x03(\x0b\x32\x1b.spotify.playlist4.proto.Op\x12\x13\n\x0bto_revision\x18\x03 \x02(\x0c"\xa0\x01\n\x0bListChanges\x12\x15\n\rbase_revision\x18\x01 \x01(\x0c\x12.\n\x06\x64\x65ltas\x18\x02 \x03(\x0b\x32\x1e.spotify.playlist4.proto.Delta\x12 \n\x18want_resulting_revisions\x18\x03 \x01(\x08\x12\x18\n\x10want_sync_result\x18\x04 \x01(\x08\x12\x0e\n\x06nonces\x18\x06 \x03(\x03"\x8f\x03\n\x13SelectedListContent\x12\x10\n\x08revision\x18\x01 \x01(\x0c\x12\x0e\n\x06length\x18\x02 \x01(\x05\x12;\n\nattributes\x18\x03 \x01(\x0b\x32\'.spotify.playlist4.proto.ListAttributes\x12\x34\n\x08\x63ontents\x18\x05 \x01(\x0b\x32".spotify.playlist4.proto.ListItems\x12+\n\x04\x64iff\x18\x06 \x01(\x0b\x32\x1d.spotify.playlist4.proto.Diff\x12\x32\n\x0bsync_result\x18\x07 \x01(\x0b\x32\x1d.spotify.playlist4.proto.Diff\x12\x1b\n\x13resulting_revisions\x18\x08 \x03(\x0c\x12\x16\n\x0emultiple_heads\x18\t \x01(\x08\x12\x12\n\nup_to_date\x18\n \x01(\x08\x12\x0e\n\x06nonces\x18\x0e \x03(\x03\x12\x11\n\ttimestamp\x18\x0f \x01(\x03\x12\x16\n\x0eowner_username\x18\x10 \x01(\t"0\n\x0f\x43reateListReply\x12\x0b\n\x03uri\x18\x01 \x02(\x0c\x12\x10\n\x08revision\x18\x02 \x01(\x0c",\n\x0bModifyReply\x12\x0b\n\x03uri\x18\x01 \x02(\x0c\x12\x10\n\x08revision\x18\x02 \x01(\x0c" \n\x10SubscribeRequest\x12\x0c\n\x04uris\x18\x01 \x03(\x0c""\n\x12UnsubscribeRequest\x12\x0c\n\x04uris\x18\x01 \x03(\x0c"\x80\x01\n\x18PlaylistModificationInfo\x12\x0b\n\x03uri\x18\x01 \x01(\x0c\x12\x14\n\x0cnew_revision\x18\x02 \x01(\x0c\x12\x17\n\x0fparent_revision\x18\x03 \x01(\x0c\x12(\n\x03ops\x18\x04 \x03(\x0b\x32\x1b.spotify.playlist4.proto.Op*\xe6\x01\n\x11ListAttributeKind\x12\x10\n\x0cLIST_UNKNOWN\x10\x00\x12\r\n\tLIST_NAME\x10\x01\x12\x14\n\x10LIST_DESCRIPTION\x10\x02\x12\x10\n\x0cLIST_PICTURE\x10\x03\x12\x16\n\x12LIST_COLLABORATIVE\x10\x04\x12\x14\n\x10LIST_PL3_VERSION\x10\x05\x12\x19\n\x15LIST_DELETED_BY_OWNER\x10\x06\x12\x12\n\x0eLIST_CLIENT_ID\x10\n\x12\x0f\n\x0bLIST_FORMAT\x10\x0b\x12\x1a\n\x16LIST_FORMAT_ATTRIBUTES\x10\x0c*\x98\x01\n\x11ItemAttributeKind\x12\x10\n\x0cITEM_UNKNOWN\x10\x00\x12\x11\n\rITEM_ADDED_BY\x10\x01\x12\x12\n\x0eITEM_TIMESTAMP\x10\x02\x12\x10\n\x0cITEM_SEEN_AT\x10\t\x12\x0f\n\x0bITEM_PUBLIC\x10\n\x12\x1a\n\x16ITEM_FORMAT_ATTRIBUTES\x10\x0b\x12\x0b\n\x07ITEM_ID\x10\x0c\x42,\n\x15\x63om.spotify.playlist4B\x11Playlist4ApiProtoH\x02', +) + +_LISTATTRIBUTEKIND = _descriptor.EnumDescriptor( + name="ListAttributeKind", + full_name="spotify.playlist4.proto.ListAttributeKind", + filename=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + values=[ + _descriptor.EnumValueDescriptor( + name="LIST_UNKNOWN", + index=0, + number=0, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key, + ), + _descriptor.EnumValueDescriptor( + name="LIST_NAME", + index=1, + number=1, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key, + ), + _descriptor.EnumValueDescriptor( + name="LIST_DESCRIPTION", + index=2, + number=2, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key, + ), + _descriptor.EnumValueDescriptor( + name="LIST_PICTURE", + index=3, + number=3, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key, + ), + _descriptor.EnumValueDescriptor( + name="LIST_COLLABORATIVE", + index=4, + number=4, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key, + ), + _descriptor.EnumValueDescriptor( + name="LIST_PL3_VERSION", + index=5, + number=5, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key, + ), + _descriptor.EnumValueDescriptor( + name="LIST_DELETED_BY_OWNER", + index=6, + number=6, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key, + ), + _descriptor.EnumValueDescriptor( + name="LIST_CLIENT_ID", + index=7, + number=10, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key, + ), + _descriptor.EnumValueDescriptor( + name="LIST_FORMAT", + index=8, + number=11, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key, + ), + _descriptor.EnumValueDescriptor( + name="LIST_FORMAT_ATTRIBUTES", + index=9, + number=12, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key, + ), + ], + containing_type=None, + serialized_options=None, + serialized_start=3902, + serialized_end=4132, +) +_sym_db.RegisterEnumDescriptor(_LISTATTRIBUTEKIND) + +ListAttributeKind = enum_type_wrapper.EnumTypeWrapper(_LISTATTRIBUTEKIND) +_ITEMATTRIBUTEKIND = _descriptor.EnumDescriptor( + name="ItemAttributeKind", + full_name="spotify.playlist4.proto.ItemAttributeKind", + filename=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + values=[ + _descriptor.EnumValueDescriptor( + name="ITEM_UNKNOWN", + index=0, + number=0, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key, + ), + _descriptor.EnumValueDescriptor( + name="ITEM_ADDED_BY", + index=1, + number=1, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key, + ), + _descriptor.EnumValueDescriptor( + name="ITEM_TIMESTAMP", + index=2, + number=2, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key, + ), + _descriptor.EnumValueDescriptor( + name="ITEM_SEEN_AT", + index=3, + number=9, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key, + ), + _descriptor.EnumValueDescriptor( + name="ITEM_PUBLIC", + index=4, + number=10, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key, + ), + _descriptor.EnumValueDescriptor( + name="ITEM_FORMAT_ATTRIBUTES", + index=5, + number=11, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key, + ), + _descriptor.EnumValueDescriptor( + name="ITEM_ID", + index=6, + number=12, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key, + ), + ], + containing_type=None, + serialized_options=None, + serialized_start=4135, + serialized_end=4287, +) +_sym_db.RegisterEnumDescriptor(_ITEMATTRIBUTEKIND) + +ItemAttributeKind = enum_type_wrapper.EnumTypeWrapper(_ITEMATTRIBUTEKIND) +LIST_UNKNOWN = 0 +LIST_NAME = 1 +LIST_DESCRIPTION = 2 +LIST_PICTURE = 3 +LIST_COLLABORATIVE = 4 +LIST_PL3_VERSION = 5 +LIST_DELETED_BY_OWNER = 6 +LIST_CLIENT_ID = 10 +LIST_FORMAT = 11 +LIST_FORMAT_ATTRIBUTES = 12 +ITEM_UNKNOWN = 0 +ITEM_ADDED_BY = 1 +ITEM_TIMESTAMP = 2 +ITEM_SEEN_AT = 9 +ITEM_PUBLIC = 10 +ITEM_FORMAT_ATTRIBUTES = 11 +ITEM_ID = 12 + +_OP_KIND = _descriptor.EnumDescriptor( + name="Kind", + full_name="spotify.playlist4.proto.Op.Kind", + filename=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + values=[ + _descriptor.EnumValueDescriptor( + name="KIND_UNKNOWN", + index=0, + number=0, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key, + ), + _descriptor.EnumValueDescriptor( + name="ADD", + index=1, + number=2, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key, + ), + _descriptor.EnumValueDescriptor( + name="REM", + index=2, + number=3, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key, + ), + _descriptor.EnumValueDescriptor( + name="MOV", + index=3, + number=4, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key, + ), + _descriptor.EnumValueDescriptor( + name="UPDATE_ITEM_ATTRIBUTES", + index=4, + number=5, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key, + ), + _descriptor.EnumValueDescriptor( + name="UPDATE_LIST_ATTRIBUTES", + index=5, + number=6, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key, + ), + ], + containing_type=None, + serialized_options=None, + serialized_start=2209, + serialized_end=2316, +) +_sym_db.RegisterEnumDescriptor(_OP_KIND) + +_SOURCEINFO_CLIENT = _descriptor.EnumDescriptor( + name="Client", + full_name="spotify.playlist4.proto.SourceInfo.Client", + filename=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + values=[ + _descriptor.EnumValueDescriptor( + name="CLIENT_UNKNOWN", + index=0, + number=0, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key, + ), + _descriptor.EnumValueDescriptor( + name="NATIVE_HERMES", + index=1, + number=1, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key, + ), + _descriptor.EnumValueDescriptor( + name="CLIENT", + index=2, + number=2, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key, + ), + _descriptor.EnumValueDescriptor( + name="PYTHON", + index=3, + number=3, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key, + ), + _descriptor.EnumValueDescriptor( + name="JAVA", + index=4, + number=4, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key, + ), + _descriptor.EnumValueDescriptor( + name="WEBPLAYER", + index=5, + number=5, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key, + ), + _descriptor.EnumValueDescriptor( + name="LIBSPOTIFY", + index=6, + number=6, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key, + ), + ], + containing_type=None, + serialized_options=None, + serialized_start=2707, + serialized_end=2819, +) +_sym_db.RegisterEnumDescriptor(_SOURCEINFO_CLIENT) + +_ITEM = _descriptor.Descriptor( + name="Item", + full_name="spotify.playlist4.proto.Item", + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name="uri", + full_name="spotify.playlist4.proto.Item.uri", + index=0, + number=1, + type=9, + cpp_type=9, + label=2, + has_default_value=False, + default_value=b"".decode("utf-8"), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="attributes", + full_name="spotify.playlist4.proto.Item.attributes", + index=1, + number=2, + type=11, + cpp_type=10, + label=1, + has_default_value=False, + default_value=None, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax="proto2", + extension_ranges=[], + oneofs=[], + serialized_start=53, + serialized_end=133, +) + +_METAITEM = _descriptor.Descriptor( + name="MetaItem", + full_name="spotify.playlist4.proto.MetaItem", + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name="revision", + full_name="spotify.playlist4.proto.MetaItem.revision", + index=0, + number=1, + type=12, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"", + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="attributes", + full_name="spotify.playlist4.proto.MetaItem.attributes", + index=1, + number=2, + type=11, + cpp_type=10, + label=1, + has_default_value=False, + default_value=None, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="length", + full_name="spotify.playlist4.proto.MetaItem.length", + index=2, + number=3, + type=5, + cpp_type=1, + label=1, + has_default_value=False, + default_value=0, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="timestamp", + full_name="spotify.playlist4.proto.MetaItem.timestamp", + index=3, + number=4, + type=3, + cpp_type=2, + label=1, + has_default_value=False, + default_value=0, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="owner_username", + full_name="spotify.playlist4.proto.MetaItem.owner_username", + index=4, + number=5, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"".decode("utf-8"), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax="proto2", + extension_ranges=[], + oneofs=[], + serialized_start=136, + serialized_end=284, +) + +_LISTITEMS = _descriptor.Descriptor( + name="ListItems", + full_name="spotify.playlist4.proto.ListItems", + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name="pos", + full_name="spotify.playlist4.proto.ListItems.pos", + index=0, + number=1, + type=5, + cpp_type=1, + label=2, + has_default_value=False, + default_value=0, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="truncated", + full_name="spotify.playlist4.proto.ListItems.truncated", + index=1, + number=2, + type=8, + cpp_type=7, + label=2, + has_default_value=False, + default_value=False, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="items", + full_name="spotify.playlist4.proto.ListItems.items", + index=2, + number=3, + type=11, + cpp_type=10, + label=3, + has_default_value=False, + default_value=[], + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="meta_items", + full_name="spotify.playlist4.proto.ListItems.meta_items", + index=3, + number=4, + type=11, + cpp_type=10, + label=3, + has_default_value=False, + default_value=[], + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax="proto2", + extension_ranges=[], + oneofs=[], + serialized_start=287, + serialized_end=431, +) + +_FORMATLISTATTRIBUTE = _descriptor.Descriptor( + name="FormatListAttribute", + full_name="spotify.playlist4.proto.FormatListAttribute", + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name="key", + full_name="spotify.playlist4.proto.FormatListAttribute.key", + index=0, + number=1, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"".decode("utf-8"), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="value", + full_name="spotify.playlist4.proto.FormatListAttribute.value", + index=1, + number=2, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"".decode("utf-8"), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax="proto2", + extension_ranges=[], + oneofs=[], + serialized_start=433, + serialized_end=482, +) + +_LISTATTRIBUTES = _descriptor.Descriptor( + name="ListAttributes", + full_name="spotify.playlist4.proto.ListAttributes", + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name="name", + full_name="spotify.playlist4.proto.ListAttributes.name", + index=0, + number=1, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"".decode("utf-8"), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="description", + full_name="spotify.playlist4.proto.ListAttributes.description", + index=1, + number=2, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"".decode("utf-8"), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="picture", + full_name="spotify.playlist4.proto.ListAttributes.picture", + index=2, + number=3, + type=12, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"", + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="collaborative", + full_name="spotify.playlist4.proto.ListAttributes.collaborative", + index=3, + number=4, + type=8, + cpp_type=7, + label=1, + has_default_value=False, + default_value=False, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="pl3_version", + full_name="spotify.playlist4.proto.ListAttributes.pl3_version", + index=4, + number=5, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"".decode("utf-8"), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="deleted_by_owner", + full_name="spotify.playlist4.proto.ListAttributes.deleted_by_owner", + index=5, + number=6, + type=8, + cpp_type=7, + label=1, + has_default_value=False, + default_value=False, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="client_id", + full_name="spotify.playlist4.proto.ListAttributes.client_id", + index=6, + number=10, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"".decode("utf-8"), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="format", + full_name="spotify.playlist4.proto.ListAttributes.format", + index=7, + number=11, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"".decode("utf-8"), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="format_attributes", + full_name= + "spotify.playlist4.proto.ListAttributes.format_attributes", + index=8, + number=12, + type=11, + cpp_type=10, + label=3, + has_default_value=False, + default_value=[], + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax="proto2", + extension_ranges=[], + oneofs=[], + serialized_start=485, + serialized_end=731, +) + +_ITEMATTRIBUTES = _descriptor.Descriptor( + name="ItemAttributes", + full_name="spotify.playlist4.proto.ItemAttributes", + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name="added_by", + full_name="spotify.playlist4.proto.ItemAttributes.added_by", + index=0, + number=1, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"".decode("utf-8"), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="timestamp", + full_name="spotify.playlist4.proto.ItemAttributes.timestamp", + index=1, + number=2, + type=3, + cpp_type=2, + label=1, + has_default_value=False, + default_value=0, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="seen_at", + full_name="spotify.playlist4.proto.ItemAttributes.seen_at", + index=2, + number=9, + type=3, + cpp_type=2, + label=1, + has_default_value=False, + default_value=0, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="public", + full_name="spotify.playlist4.proto.ItemAttributes.public", + index=3, + number=10, + type=8, + cpp_type=7, + label=1, + has_default_value=False, + default_value=False, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="format_attributes", + full_name= + "spotify.playlist4.proto.ItemAttributes.format_attributes", + index=4, + number=11, + type=11, + cpp_type=10, + label=3, + has_default_value=False, + default_value=[], + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="item_id", + full_name="spotify.playlist4.proto.ItemAttributes.item_id", + index=5, + number=12, + type=12, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"", + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax="proto2", + extension_ranges=[], + oneofs=[], + serialized_start=734, + serialized_end=910, +) + +_ADD = _descriptor.Descriptor( + name="Add", + full_name="spotify.playlist4.proto.Add", + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name="from_index", + full_name="spotify.playlist4.proto.Add.from_index", + index=0, + number=1, + type=5, + cpp_type=1, + label=1, + has_default_value=False, + default_value=0, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="items", + full_name="spotify.playlist4.proto.Add.items", + index=1, + number=2, + type=11, + cpp_type=10, + label=3, + has_default_value=False, + default_value=[], + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="add_last", + full_name="spotify.playlist4.proto.Add.add_last", + index=2, + number=4, + type=8, + cpp_type=7, + label=1, + has_default_value=False, + default_value=False, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="add_first", + full_name="spotify.playlist4.proto.Add.add_first", + index=3, + number=5, + type=8, + cpp_type=7, + label=1, + has_default_value=False, + default_value=False, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax="proto2", + extension_ranges=[], + oneofs=[], + serialized_start=912, + serialized_end=1020, +) + +_REM = _descriptor.Descriptor( + name="Rem", + full_name="spotify.playlist4.proto.Rem", + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name="from_index", + full_name="spotify.playlist4.proto.Rem.from_index", + index=0, + number=1, + type=5, + cpp_type=1, + label=1, + has_default_value=False, + default_value=0, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="length", + full_name="spotify.playlist4.proto.Rem.length", + index=1, + number=2, + type=5, + cpp_type=1, + label=1, + has_default_value=False, + default_value=0, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="items", + full_name="spotify.playlist4.proto.Rem.items", + index=2, + number=3, + type=11, + cpp_type=10, + label=3, + has_default_value=False, + default_value=[], + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="items_as_key", + full_name="spotify.playlist4.proto.Rem.items_as_key", + index=3, + number=7, + type=8, + cpp_type=7, + label=1, + has_default_value=False, + default_value=False, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax="proto2", + extension_ranges=[], + oneofs=[], + serialized_start=1022, + serialized_end=1131, +) + +_MOV = _descriptor.Descriptor( + name="Mov", + full_name="spotify.playlist4.proto.Mov", + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name="from_index", + full_name="spotify.playlist4.proto.Mov.from_index", + index=0, + number=1, + type=5, + cpp_type=1, + label=2, + has_default_value=False, + default_value=0, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="length", + full_name="spotify.playlist4.proto.Mov.length", + index=1, + number=2, + type=5, + cpp_type=1, + label=2, + has_default_value=False, + default_value=0, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="to_index", + full_name="spotify.playlist4.proto.Mov.to_index", + index=2, + number=3, + type=5, + cpp_type=1, + label=2, + has_default_value=False, + default_value=0, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax="proto2", + extension_ranges=[], + oneofs=[], + serialized_start=1133, + serialized_end=1192, +) + +_ITEMATTRIBUTESPARTIALSTATE = _descriptor.Descriptor( + name="ItemAttributesPartialState", + full_name="spotify.playlist4.proto.ItemAttributesPartialState", + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name="values", + full_name= + "spotify.playlist4.proto.ItemAttributesPartialState.values", + index=0, + number=1, + type=11, + cpp_type=10, + label=2, + has_default_value=False, + default_value=None, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="no_value", + full_name= + "spotify.playlist4.proto.ItemAttributesPartialState.no_value", + index=1, + number=2, + type=14, + cpp_type=8, + label=3, + has_default_value=False, + default_value=[], + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax="proto2", + extension_ranges=[], + oneofs=[], + serialized_start=1195, + serialized_end=1342, +) + +_LISTATTRIBUTESPARTIALSTATE = _descriptor.Descriptor( + name="ListAttributesPartialState", + full_name="spotify.playlist4.proto.ListAttributesPartialState", + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name="values", + full_name= + "spotify.playlist4.proto.ListAttributesPartialState.values", + index=0, + number=1, + type=11, + cpp_type=10, + label=2, + has_default_value=False, + default_value=None, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="no_value", + full_name= + "spotify.playlist4.proto.ListAttributesPartialState.no_value", + index=1, + number=2, + type=14, + cpp_type=8, + label=3, + has_default_value=False, + default_value=[], + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax="proto2", + extension_ranges=[], + oneofs=[], + serialized_start=1345, + serialized_end=1492, +) + +_UPDATEITEMATTRIBUTES = _descriptor.Descriptor( + name="UpdateItemAttributes", + full_name="spotify.playlist4.proto.UpdateItemAttributes", + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name="index", + full_name="spotify.playlist4.proto.UpdateItemAttributes.index", + index=0, + number=1, + type=5, + cpp_type=1, + label=2, + has_default_value=False, + default_value=0, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="new_attributes", + full_name= + "spotify.playlist4.proto.UpdateItemAttributes.new_attributes", + index=1, + number=2, + type=11, + cpp_type=10, + label=2, + has_default_value=False, + default_value=None, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="old_attributes", + full_name= + "spotify.playlist4.proto.UpdateItemAttributes.old_attributes", + index=2, + number=3, + type=11, + cpp_type=10, + label=1, + has_default_value=False, + default_value=None, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax="proto2", + extension_ranges=[], + oneofs=[], + serialized_start=1495, + serialized_end=1686, +) + +_UPDATELISTATTRIBUTES = _descriptor.Descriptor( + name="UpdateListAttributes", + full_name="spotify.playlist4.proto.UpdateListAttributes", + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name="new_attributes", + full_name= + "spotify.playlist4.proto.UpdateListAttributes.new_attributes", + index=0, + number=1, + type=11, + cpp_type=10, + label=2, + has_default_value=False, + default_value=None, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="old_attributes", + full_name= + "spotify.playlist4.proto.UpdateListAttributes.old_attributes", + index=1, + number=2, + type=11, + cpp_type=10, + label=1, + has_default_value=False, + default_value=None, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax="proto2", + extension_ranges=[], + oneofs=[], + serialized_start=1689, + serialized_end=1865, +) + +_OP = _descriptor.Descriptor( + name="Op", + full_name="spotify.playlist4.proto.Op", + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name="kind", + full_name="spotify.playlist4.proto.Op.kind", + index=0, + number=1, + type=14, + cpp_type=8, + label=2, + has_default_value=False, + default_value=0, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="add", + full_name="spotify.playlist4.proto.Op.add", + index=1, + number=2, + type=11, + cpp_type=10, + label=1, + has_default_value=False, + default_value=None, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="rem", + full_name="spotify.playlist4.proto.Op.rem", + index=2, + number=3, + type=11, + cpp_type=10, + label=1, + has_default_value=False, + default_value=None, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="mov", + full_name="spotify.playlist4.proto.Op.mov", + index=3, + number=4, + type=11, + cpp_type=10, + label=1, + has_default_value=False, + default_value=None, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="update_item_attributes", + full_name="spotify.playlist4.proto.Op.update_item_attributes", + index=4, + number=5, + type=11, + cpp_type=10, + label=1, + has_default_value=False, + default_value=None, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="update_list_attributes", + full_name="spotify.playlist4.proto.Op.update_list_attributes", + index=5, + number=6, + type=11, + cpp_type=10, + label=1, + has_default_value=False, + default_value=None, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + ], + extensions=[], + nested_types=[], + enum_types=[ + _OP_KIND, + ], + serialized_options=None, + is_extendable=False, + syntax="proto2", + extension_ranges=[], + oneofs=[], + serialized_start=1868, + serialized_end=2316, +) + +_OPLIST = _descriptor.Descriptor( + name="OpList", + full_name="spotify.playlist4.proto.OpList", + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name="ops", + full_name="spotify.playlist4.proto.OpList.ops", + index=0, + number=1, + type=11, + cpp_type=10, + label=3, + has_default_value=False, + default_value=[], + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax="proto2", + extension_ranges=[], + oneofs=[], + serialized_start=2318, + serialized_end=2368, +) + +_CHANGEINFO = _descriptor.Descriptor( + name="ChangeInfo", + full_name="spotify.playlist4.proto.ChangeInfo", + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name="user", + full_name="spotify.playlist4.proto.ChangeInfo.user", + index=0, + number=1, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"".decode("utf-8"), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="timestamp", + full_name="spotify.playlist4.proto.ChangeInfo.timestamp", + index=1, + number=2, + type=3, + cpp_type=2, + label=1, + has_default_value=False, + default_value=0, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="admin", + full_name="spotify.playlist4.proto.ChangeInfo.admin", + index=2, + number=3, + type=8, + cpp_type=7, + label=1, + has_default_value=False, + default_value=False, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="undo", + full_name="spotify.playlist4.proto.ChangeInfo.undo", + index=3, + number=4, + type=8, + cpp_type=7, + label=1, + has_default_value=False, + default_value=False, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="redo", + full_name="spotify.playlist4.proto.ChangeInfo.redo", + index=4, + number=5, + type=8, + cpp_type=7, + label=1, + has_default_value=False, + default_value=False, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="merge", + full_name="spotify.playlist4.proto.ChangeInfo.merge", + index=5, + number=6, + type=8, + cpp_type=7, + label=1, + has_default_value=False, + default_value=False, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="compressed", + full_name="spotify.playlist4.proto.ChangeInfo.compressed", + index=6, + number=7, + type=8, + cpp_type=7, + label=1, + has_default_value=False, + default_value=False, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="migration", + full_name="spotify.playlist4.proto.ChangeInfo.migration", + index=7, + number=8, + type=8, + cpp_type=7, + label=1, + has_default_value=False, + default_value=False, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="split_id", + full_name="spotify.playlist4.proto.ChangeInfo.split_id", + index=8, + number=9, + type=5, + cpp_type=1, + label=1, + has_default_value=False, + default_value=0, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="source", + full_name="spotify.playlist4.proto.ChangeInfo.source", + index=9, + number=10, + type=11, + cpp_type=10, + label=1, + has_default_value=False, + default_value=None, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax="proto2", + extension_ranges=[], + oneofs=[], + serialized_start=2371, + serialized_end=2584, +) + +_SOURCEINFO = _descriptor.Descriptor( + name="SourceInfo", + full_name="spotify.playlist4.proto.SourceInfo", + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name="client", + full_name="spotify.playlist4.proto.SourceInfo.client", + index=0, + number=1, + type=14, + cpp_type=8, + label=1, + has_default_value=False, + default_value=0, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="app", + full_name="spotify.playlist4.proto.SourceInfo.app", + index=1, + number=3, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"".decode("utf-8"), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="source", + full_name="spotify.playlist4.proto.SourceInfo.source", + index=2, + number=4, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"".decode("utf-8"), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="version", + full_name="spotify.playlist4.proto.SourceInfo.version", + index=3, + number=5, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"".decode("utf-8"), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + ], + extensions=[], + nested_types=[], + enum_types=[ + _SOURCEINFO_CLIENT, + ], + serialized_options=None, + is_extendable=False, + syntax="proto2", + extension_ranges=[], + oneofs=[], + serialized_start=2587, + serialized_end=2819, +) + +_DELTA = _descriptor.Descriptor( + name="Delta", + full_name="spotify.playlist4.proto.Delta", + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name="base_version", + full_name="spotify.playlist4.proto.Delta.base_version", + index=0, + number=1, + type=12, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"", + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="ops", + full_name="spotify.playlist4.proto.Delta.ops", + index=1, + number=2, + type=11, + cpp_type=10, + label=3, + has_default_value=False, + default_value=[], + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="info", + full_name="spotify.playlist4.proto.Delta.info", + index=2, + number=4, + type=11, + cpp_type=10, + label=1, + has_default_value=False, + default_value=None, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax="proto2", + extension_ranges=[], + oneofs=[], + serialized_start=2821, + serialized_end=2943, +) + +_DIFF = _descriptor.Descriptor( + name="Diff", + full_name="spotify.playlist4.proto.Diff", + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name="from_revision", + full_name="spotify.playlist4.proto.Diff.from_revision", + index=0, + number=1, + type=12, + cpp_type=9, + label=2, + has_default_value=False, + default_value=b"", + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="ops", + full_name="spotify.playlist4.proto.Diff.ops", + index=1, + number=2, + type=11, + cpp_type=10, + label=3, + has_default_value=False, + default_value=[], + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="to_revision", + full_name="spotify.playlist4.proto.Diff.to_revision", + index=2, + number=3, + type=12, + cpp_type=9, + label=2, + has_default_value=False, + default_value=b"", + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax="proto2", + extension_ranges=[], + oneofs=[], + serialized_start=2945, + serialized_end=3037, +) + +_LISTCHANGES = _descriptor.Descriptor( + name="ListChanges", + full_name="spotify.playlist4.proto.ListChanges", + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name="base_revision", + full_name="spotify.playlist4.proto.ListChanges.base_revision", + index=0, + number=1, + type=12, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"", + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="deltas", + full_name="spotify.playlist4.proto.ListChanges.deltas", + index=1, + number=2, + type=11, + cpp_type=10, + label=3, + has_default_value=False, + default_value=[], + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="want_resulting_revisions", + full_name= + "spotify.playlist4.proto.ListChanges.want_resulting_revisions", + index=2, + number=3, + type=8, + cpp_type=7, + label=1, + has_default_value=False, + default_value=False, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="want_sync_result", + full_name="spotify.playlist4.proto.ListChanges.want_sync_result", + index=3, + number=4, + type=8, + cpp_type=7, + label=1, + has_default_value=False, + default_value=False, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="nonces", + full_name="spotify.playlist4.proto.ListChanges.nonces", + index=4, + number=6, + type=3, + cpp_type=2, + label=3, + has_default_value=False, + default_value=[], + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax="proto2", + extension_ranges=[], + oneofs=[], + serialized_start=3040, + serialized_end=3200, +) + +_SELECTEDLISTCONTENT = _descriptor.Descriptor( + name="SelectedListContent", + full_name="spotify.playlist4.proto.SelectedListContent", + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name="revision", + full_name="spotify.playlist4.proto.SelectedListContent.revision", + index=0, + number=1, + type=12, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"", + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="length", + full_name="spotify.playlist4.proto.SelectedListContent.length", + index=1, + number=2, + type=5, + cpp_type=1, + label=1, + has_default_value=False, + default_value=0, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="attributes", + full_name="spotify.playlist4.proto.SelectedListContent.attributes", + index=2, + number=3, + type=11, + cpp_type=10, + label=1, + has_default_value=False, + default_value=None, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="contents", + full_name="spotify.playlist4.proto.SelectedListContent.contents", + index=3, + number=5, + type=11, + cpp_type=10, + label=1, + has_default_value=False, + default_value=None, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="diff", + full_name="spotify.playlist4.proto.SelectedListContent.diff", + index=4, + number=6, + type=11, + cpp_type=10, + label=1, + has_default_value=False, + default_value=None, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="sync_result", + full_name="spotify.playlist4.proto.SelectedListContent.sync_result", + index=5, + number=7, + type=11, + cpp_type=10, + label=1, + has_default_value=False, + default_value=None, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="resulting_revisions", + full_name= + "spotify.playlist4.proto.SelectedListContent.resulting_revisions", + index=6, + number=8, + type=12, + cpp_type=9, + label=3, + has_default_value=False, + default_value=[], + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="multiple_heads", + full_name= + "spotify.playlist4.proto.SelectedListContent.multiple_heads", + index=7, + number=9, + type=8, + cpp_type=7, + label=1, + has_default_value=False, + default_value=False, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="up_to_date", + full_name="spotify.playlist4.proto.SelectedListContent.up_to_date", + index=8, + number=10, + type=8, + cpp_type=7, + label=1, + has_default_value=False, + default_value=False, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="nonces", + full_name="spotify.playlist4.proto.SelectedListContent.nonces", + index=9, + number=14, + type=3, + cpp_type=2, + label=3, + has_default_value=False, + default_value=[], + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="timestamp", + full_name="spotify.playlist4.proto.SelectedListContent.timestamp", + index=10, + number=15, + type=3, + cpp_type=2, + label=1, + has_default_value=False, + default_value=0, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="owner_username", + full_name= + "spotify.playlist4.proto.SelectedListContent.owner_username", + index=11, + number=16, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"".decode("utf-8"), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax="proto2", + extension_ranges=[], + oneofs=[], + serialized_start=3203, + serialized_end=3602, +) + +_CREATELISTREPLY = _descriptor.Descriptor( + name="CreateListReply", + full_name="spotify.playlist4.proto.CreateListReply", + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name="uri", + full_name="spotify.playlist4.proto.CreateListReply.uri", + index=0, + number=1, + type=12, + cpp_type=9, + label=2, + has_default_value=False, + default_value=b"", + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="revision", + full_name="spotify.playlist4.proto.CreateListReply.revision", + index=1, + number=2, + type=12, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"", + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax="proto2", + extension_ranges=[], + oneofs=[], + serialized_start=3604, + serialized_end=3652, +) + +_MODIFYREPLY = _descriptor.Descriptor( + name="ModifyReply", + full_name="spotify.playlist4.proto.ModifyReply", + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name="uri", + full_name="spotify.playlist4.proto.ModifyReply.uri", + index=0, + number=1, + type=12, + cpp_type=9, + label=2, + has_default_value=False, + default_value=b"", + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="revision", + full_name="spotify.playlist4.proto.ModifyReply.revision", + index=1, + number=2, + type=12, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"", + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax="proto2", + extension_ranges=[], + oneofs=[], + serialized_start=3654, + serialized_end=3698, +) + +_SUBSCRIBEREQUEST = _descriptor.Descriptor( + name="SubscribeRequest", + full_name="spotify.playlist4.proto.SubscribeRequest", + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name="uris", + full_name="spotify.playlist4.proto.SubscribeRequest.uris", + index=0, + number=1, + type=12, + cpp_type=9, + label=3, + has_default_value=False, + default_value=[], + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax="proto2", + extension_ranges=[], + oneofs=[], + serialized_start=3700, + serialized_end=3732, +) + +_UNSUBSCRIBEREQUEST = _descriptor.Descriptor( + name="UnsubscribeRequest", + full_name="spotify.playlist4.proto.UnsubscribeRequest", + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name="uris", + full_name="spotify.playlist4.proto.UnsubscribeRequest.uris", + index=0, + number=1, + type=12, + cpp_type=9, + label=3, + has_default_value=False, + default_value=[], + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax="proto2", + extension_ranges=[], + oneofs=[], + serialized_start=3734, + serialized_end=3768, +) + +_PLAYLISTMODIFICATIONINFO = _descriptor.Descriptor( + name="PlaylistModificationInfo", + full_name="spotify.playlist4.proto.PlaylistModificationInfo", + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name="uri", + full_name="spotify.playlist4.proto.PlaylistModificationInfo.uri", + index=0, + number=1, + type=12, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"", + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="new_revision", + full_name= + "spotify.playlist4.proto.PlaylistModificationInfo.new_revision", + index=1, + number=2, + type=12, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"", + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="parent_revision", + full_name= + "spotify.playlist4.proto.PlaylistModificationInfo.parent_revision", + index=2, + number=3, + type=12, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"", + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="ops", + full_name="spotify.playlist4.proto.PlaylistModificationInfo.ops", + index=3, + number=4, + type=11, + cpp_type=10, + label=3, + has_default_value=False, + default_value=[], + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax="proto2", + extension_ranges=[], + oneofs=[], + serialized_start=3771, + serialized_end=3899, +) + +_ITEM.fields_by_name["attributes"].message_type = _ITEMATTRIBUTES +_METAITEM.fields_by_name["attributes"].message_type = _LISTATTRIBUTES +_LISTITEMS.fields_by_name["items"].message_type = _ITEM +_LISTITEMS.fields_by_name["meta_items"].message_type = _METAITEM +_LISTATTRIBUTES.fields_by_name[ + "format_attributes"].message_type = _FORMATLISTATTRIBUTE +_ITEMATTRIBUTES.fields_by_name[ + "format_attributes"].message_type = _FORMATLISTATTRIBUTE +_ADD.fields_by_name["items"].message_type = _ITEM +_REM.fields_by_name["items"].message_type = _ITEM +_ITEMATTRIBUTESPARTIALSTATE.fields_by_name[ + "values"].message_type = _ITEMATTRIBUTES +_ITEMATTRIBUTESPARTIALSTATE.fields_by_name[ + "no_value"].enum_type = _ITEMATTRIBUTEKIND +_LISTATTRIBUTESPARTIALSTATE.fields_by_name[ + "values"].message_type = _LISTATTRIBUTES +_LISTATTRIBUTESPARTIALSTATE.fields_by_name[ + "no_value"].enum_type = _LISTATTRIBUTEKIND +_UPDATEITEMATTRIBUTES.fields_by_name[ + "new_attributes"].message_type = _ITEMATTRIBUTESPARTIALSTATE +_UPDATEITEMATTRIBUTES.fields_by_name[ + "old_attributes"].message_type = _ITEMATTRIBUTESPARTIALSTATE +_UPDATELISTATTRIBUTES.fields_by_name[ + "new_attributes"].message_type = _LISTATTRIBUTESPARTIALSTATE +_UPDATELISTATTRIBUTES.fields_by_name[ + "old_attributes"].message_type = _LISTATTRIBUTESPARTIALSTATE +_OP.fields_by_name["kind"].enum_type = _OP_KIND +_OP.fields_by_name["add"].message_type = _ADD +_OP.fields_by_name["rem"].message_type = _REM +_OP.fields_by_name["mov"].message_type = _MOV +_OP.fields_by_name[ + "update_item_attributes"].message_type = _UPDATEITEMATTRIBUTES +_OP.fields_by_name[ + "update_list_attributes"].message_type = _UPDATELISTATTRIBUTES +_OP_KIND.containing_type = _OP +_OPLIST.fields_by_name["ops"].message_type = _OP +_CHANGEINFO.fields_by_name["source"].message_type = _SOURCEINFO +_SOURCEINFO.fields_by_name["client"].enum_type = _SOURCEINFO_CLIENT +_SOURCEINFO_CLIENT.containing_type = _SOURCEINFO +_DELTA.fields_by_name["ops"].message_type = _OP +_DELTA.fields_by_name["info"].message_type = _CHANGEINFO +_DIFF.fields_by_name["ops"].message_type = _OP +_LISTCHANGES.fields_by_name["deltas"].message_type = _DELTA +_SELECTEDLISTCONTENT.fields_by_name[ + "attributes"].message_type = _LISTATTRIBUTES +_SELECTEDLISTCONTENT.fields_by_name["contents"].message_type = _LISTITEMS +_SELECTEDLISTCONTENT.fields_by_name["diff"].message_type = _DIFF +_SELECTEDLISTCONTENT.fields_by_name["sync_result"].message_type = _DIFF +_PLAYLISTMODIFICATIONINFO.fields_by_name["ops"].message_type = _OP +DESCRIPTOR.message_types_by_name["Item"] = _ITEM +DESCRIPTOR.message_types_by_name["MetaItem"] = _METAITEM +DESCRIPTOR.message_types_by_name["ListItems"] = _LISTITEMS +DESCRIPTOR.message_types_by_name["FormatListAttribute"] = _FORMATLISTATTRIBUTE +DESCRIPTOR.message_types_by_name["ListAttributes"] = _LISTATTRIBUTES +DESCRIPTOR.message_types_by_name["ItemAttributes"] = _ITEMATTRIBUTES +DESCRIPTOR.message_types_by_name["Add"] = _ADD +DESCRIPTOR.message_types_by_name["Rem"] = _REM +DESCRIPTOR.message_types_by_name["Mov"] = _MOV +DESCRIPTOR.message_types_by_name[ + "ItemAttributesPartialState"] = _ITEMATTRIBUTESPARTIALSTATE +DESCRIPTOR.message_types_by_name[ + "ListAttributesPartialState"] = _LISTATTRIBUTESPARTIALSTATE +DESCRIPTOR.message_types_by_name[ + "UpdateItemAttributes"] = _UPDATEITEMATTRIBUTES +DESCRIPTOR.message_types_by_name[ + "UpdateListAttributes"] = _UPDATELISTATTRIBUTES +DESCRIPTOR.message_types_by_name["Op"] = _OP +DESCRIPTOR.message_types_by_name["OpList"] = _OPLIST +DESCRIPTOR.message_types_by_name["ChangeInfo"] = _CHANGEINFO +DESCRIPTOR.message_types_by_name["SourceInfo"] = _SOURCEINFO +DESCRIPTOR.message_types_by_name["Delta"] = _DELTA +DESCRIPTOR.message_types_by_name["Diff"] = _DIFF +DESCRIPTOR.message_types_by_name["ListChanges"] = _LISTCHANGES +DESCRIPTOR.message_types_by_name["SelectedListContent"] = _SELECTEDLISTCONTENT +DESCRIPTOR.message_types_by_name["CreateListReply"] = _CREATELISTREPLY +DESCRIPTOR.message_types_by_name["ModifyReply"] = _MODIFYREPLY +DESCRIPTOR.message_types_by_name["SubscribeRequest"] = _SUBSCRIBEREQUEST +DESCRIPTOR.message_types_by_name["UnsubscribeRequest"] = _UNSUBSCRIBEREQUEST +DESCRIPTOR.message_types_by_name[ + "PlaylistModificationInfo"] = _PLAYLISTMODIFICATIONINFO +DESCRIPTOR.enum_types_by_name["ListAttributeKind"] = _LISTATTRIBUTEKIND +DESCRIPTOR.enum_types_by_name["ItemAttributeKind"] = _ITEMATTRIBUTEKIND +_sym_db.RegisterFileDescriptor(DESCRIPTOR) + +Item = _reflection.GeneratedProtocolMessageType( + "Item", + (_message.Message, ), + { + "DESCRIPTOR": _ITEM, + "__module__": "playlist4_external_pb2" + # @@protoc_insertion_point(class_scope:spotify.playlist4.proto.Item) + }, +) +_sym_db.RegisterMessage(Item) + +MetaItem = _reflection.GeneratedProtocolMessageType( + "MetaItem", + (_message.Message, ), + { + "DESCRIPTOR": _METAITEM, + "__module__": "playlist4_external_pb2" + # @@protoc_insertion_point(class_scope:spotify.playlist4.proto.MetaItem) + }, +) +_sym_db.RegisterMessage(MetaItem) + +ListItems = _reflection.GeneratedProtocolMessageType( + "ListItems", + (_message.Message, ), + { + "DESCRIPTOR": _LISTITEMS, + "__module__": "playlist4_external_pb2" + # @@protoc_insertion_point(class_scope:spotify.playlist4.proto.ListItems) + }, +) +_sym_db.RegisterMessage(ListItems) + +FormatListAttribute = _reflection.GeneratedProtocolMessageType( + "FormatListAttribute", + (_message.Message, ), + { + "DESCRIPTOR": _FORMATLISTATTRIBUTE, + "__module__": "playlist4_external_pb2" + # @@protoc_insertion_point(class_scope:spotify.playlist4.proto.FormatListAttribute) + }, +) +_sym_db.RegisterMessage(FormatListAttribute) + +ListAttributes = _reflection.GeneratedProtocolMessageType( + "ListAttributes", + (_message.Message, ), + { + "DESCRIPTOR": _LISTATTRIBUTES, + "__module__": "playlist4_external_pb2" + # @@protoc_insertion_point(class_scope:spotify.playlist4.proto.ListAttributes) + }, +) +_sym_db.RegisterMessage(ListAttributes) + +ItemAttributes = _reflection.GeneratedProtocolMessageType( + "ItemAttributes", + (_message.Message, ), + { + "DESCRIPTOR": _ITEMATTRIBUTES, + "__module__": "playlist4_external_pb2" + # @@protoc_insertion_point(class_scope:spotify.playlist4.proto.ItemAttributes) + }, +) +_sym_db.RegisterMessage(ItemAttributes) + +Add = _reflection.GeneratedProtocolMessageType( + "Add", + (_message.Message, ), + { + "DESCRIPTOR": _ADD, + "__module__": "playlist4_external_pb2" + # @@protoc_insertion_point(class_scope:spotify.playlist4.proto.Add) + }, +) +_sym_db.RegisterMessage(Add) + +Rem = _reflection.GeneratedProtocolMessageType( + "Rem", + (_message.Message, ), + { + "DESCRIPTOR": _REM, + "__module__": "playlist4_external_pb2" + # @@protoc_insertion_point(class_scope:spotify.playlist4.proto.Rem) + }, +) +_sym_db.RegisterMessage(Rem) + +Mov = _reflection.GeneratedProtocolMessageType( + "Mov", + (_message.Message, ), + { + "DESCRIPTOR": _MOV, + "__module__": "playlist4_external_pb2" + # @@protoc_insertion_point(class_scope:spotify.playlist4.proto.Mov) + }, +) +_sym_db.RegisterMessage(Mov) + +ItemAttributesPartialState = _reflection.GeneratedProtocolMessageType( + "ItemAttributesPartialState", + (_message.Message, ), + { + "DESCRIPTOR": _ITEMATTRIBUTESPARTIALSTATE, + "__module__": "playlist4_external_pb2" + # @@protoc_insertion_point(class_scope:spotify.playlist4.proto.ItemAttributesPartialState) + }, +) +_sym_db.RegisterMessage(ItemAttributesPartialState) + +ListAttributesPartialState = _reflection.GeneratedProtocolMessageType( + "ListAttributesPartialState", + (_message.Message, ), + { + "DESCRIPTOR": _LISTATTRIBUTESPARTIALSTATE, + "__module__": "playlist4_external_pb2" + # @@protoc_insertion_point(class_scope:spotify.playlist4.proto.ListAttributesPartialState) + }, +) +_sym_db.RegisterMessage(ListAttributesPartialState) + +UpdateItemAttributes = _reflection.GeneratedProtocolMessageType( + "UpdateItemAttributes", + (_message.Message, ), + { + "DESCRIPTOR": _UPDATEITEMATTRIBUTES, + "__module__": "playlist4_external_pb2" + # @@protoc_insertion_point(class_scope:spotify.playlist4.proto.UpdateItemAttributes) + }, +) +_sym_db.RegisterMessage(UpdateItemAttributes) + +UpdateListAttributes = _reflection.GeneratedProtocolMessageType( + "UpdateListAttributes", + (_message.Message, ), + { + "DESCRIPTOR": _UPDATELISTATTRIBUTES, + "__module__": "playlist4_external_pb2" + # @@protoc_insertion_point(class_scope:spotify.playlist4.proto.UpdateListAttributes) + }, +) +_sym_db.RegisterMessage(UpdateListAttributes) + +Op = _reflection.GeneratedProtocolMessageType( + "Op", + (_message.Message, ), + { + "DESCRIPTOR": _OP, + "__module__": "playlist4_external_pb2" + # @@protoc_insertion_point(class_scope:spotify.playlist4.proto.Op) + }, +) +_sym_db.RegisterMessage(Op) + +OpList = _reflection.GeneratedProtocolMessageType( + "OpList", + (_message.Message, ), + { + "DESCRIPTOR": _OPLIST, + "__module__": "playlist4_external_pb2" + # @@protoc_insertion_point(class_scope:spotify.playlist4.proto.OpList) + }, +) +_sym_db.RegisterMessage(OpList) + +ChangeInfo = _reflection.GeneratedProtocolMessageType( + "ChangeInfo", + (_message.Message, ), + { + "DESCRIPTOR": _CHANGEINFO, + "__module__": "playlist4_external_pb2" + # @@protoc_insertion_point(class_scope:spotify.playlist4.proto.ChangeInfo) + }, +) +_sym_db.RegisterMessage(ChangeInfo) + +SourceInfo = _reflection.GeneratedProtocolMessageType( + "SourceInfo", + (_message.Message, ), + { + "DESCRIPTOR": _SOURCEINFO, + "__module__": "playlist4_external_pb2" + # @@protoc_insertion_point(class_scope:spotify.playlist4.proto.SourceInfo) + }, +) +_sym_db.RegisterMessage(SourceInfo) + +Delta = _reflection.GeneratedProtocolMessageType( + "Delta", + (_message.Message, ), + { + "DESCRIPTOR": _DELTA, + "__module__": "playlist4_external_pb2" + # @@protoc_insertion_point(class_scope:spotify.playlist4.proto.Delta) + }, +) +_sym_db.RegisterMessage(Delta) + +Diff = _reflection.GeneratedProtocolMessageType( + "Diff", + (_message.Message, ), + { + "DESCRIPTOR": _DIFF, + "__module__": "playlist4_external_pb2" + # @@protoc_insertion_point(class_scope:spotify.playlist4.proto.Diff) + }, +) +_sym_db.RegisterMessage(Diff) + +ListChanges = _reflection.GeneratedProtocolMessageType( + "ListChanges", + (_message.Message, ), + { + "DESCRIPTOR": _LISTCHANGES, + "__module__": "playlist4_external_pb2" + # @@protoc_insertion_point(class_scope:spotify.playlist4.proto.ListChanges) + }, +) +_sym_db.RegisterMessage(ListChanges) + +SelectedListContent = _reflection.GeneratedProtocolMessageType( + "SelectedListContent", + (_message.Message, ), + { + "DESCRIPTOR": _SELECTEDLISTCONTENT, + "__module__": "playlist4_external_pb2" + # @@protoc_insertion_point(class_scope:spotify.playlist4.proto.SelectedListContent) + }, +) +_sym_db.RegisterMessage(SelectedListContent) + +CreateListReply = _reflection.GeneratedProtocolMessageType( + "CreateListReply", + (_message.Message, ), + { + "DESCRIPTOR": _CREATELISTREPLY, + "__module__": "playlist4_external_pb2" + # @@protoc_insertion_point(class_scope:spotify.playlist4.proto.CreateListReply) + }, +) +_sym_db.RegisterMessage(CreateListReply) + +ModifyReply = _reflection.GeneratedProtocolMessageType( + "ModifyReply", + (_message.Message, ), + { + "DESCRIPTOR": _MODIFYREPLY, + "__module__": "playlist4_external_pb2" + # @@protoc_insertion_point(class_scope:spotify.playlist4.proto.ModifyReply) + }, +) +_sym_db.RegisterMessage(ModifyReply) + +SubscribeRequest = _reflection.GeneratedProtocolMessageType( + "SubscribeRequest", + (_message.Message, ), + { + "DESCRIPTOR": _SUBSCRIBEREQUEST, + "__module__": "playlist4_external_pb2" + # @@protoc_insertion_point(class_scope:spotify.playlist4.proto.SubscribeRequest) + }, +) +_sym_db.RegisterMessage(SubscribeRequest) + +UnsubscribeRequest = _reflection.GeneratedProtocolMessageType( + "UnsubscribeRequest", + (_message.Message, ), + { + "DESCRIPTOR": _UNSUBSCRIBEREQUEST, + "__module__": "playlist4_external_pb2" + # @@protoc_insertion_point(class_scope:spotify.playlist4.proto.UnsubscribeRequest) + }, +) +_sym_db.RegisterMessage(UnsubscribeRequest) + +PlaylistModificationInfo = _reflection.GeneratedProtocolMessageType( + "PlaylistModificationInfo", + (_message.Message, ), + { + "DESCRIPTOR": _PLAYLISTMODIFICATIONINFO, + "__module__": "playlist4_external_pb2" + # @@protoc_insertion_point(class_scope:spotify.playlist4.proto.PlaylistModificationInfo) + }, +) +_sym_db.RegisterMessage(PlaylistModificationInfo) + +DESCRIPTOR._options = None +# @@protoc_insertion_point(module_scope) diff --git a/librespot/proto/PlaylistAnnotate3_pb2.py b/librespot/proto/PlaylistAnnotate3_pb2.py new file mode 100644 index 0000000..265b99b --- /dev/null +++ b/librespot/proto/PlaylistAnnotate3_pb2.py @@ -0,0 +1,460 @@ +# -*- coding: utf-8 -*- +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: playlist_annotate3.proto +"""Generated protocol buffer code.""" +from google.protobuf import descriptor as _descriptor +from google.protobuf import message as _message +from google.protobuf import reflection as _reflection +from google.protobuf import symbol_database as _symbol_database +from google.protobuf.internal import enum_type_wrapper + +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + +DESCRIPTOR = _descriptor.FileDescriptor( + name="playlist_annotate3.proto", + package="spotify_playlist_annotate3.proto", + syntax="proto2", + serialized_options=b"\n\036com.spotify.playlist_annotate3H\002", + 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', +) + +_RENDERFEATURES = _descriptor.EnumDescriptor( + name="RenderFeatures", + full_name="spotify_playlist_annotate3.proto.RenderFeatures", + filename=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + values=[ + _descriptor.EnumValueDescriptor( + name="NORMAL_FEATURES", + index=0, + number=1, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key, + ), + _descriptor.EnumValueDescriptor( + name="EXTENDED_FEATURES", + index=1, + number=2, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key, + ), + ], + containing_type=None, + serialized_options=None, + serialized_start=650, + serialized_end=710, +) +_sym_db.RegisterEnumDescriptor(_RENDERFEATURES) + +RenderFeatures = enum_type_wrapper.EnumTypeWrapper(_RENDERFEATURES) +_ABUSEREPORTSTATE = _descriptor.EnumDescriptor( + name="AbuseReportState", + full_name="spotify_playlist_annotate3.proto.AbuseReportState", + filename=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + values=[ + _descriptor.EnumValueDescriptor( + name="OK", + index=0, + number=0, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key, + ), + _descriptor.EnumValueDescriptor( + name="TAKEN_DOWN", + index=1, + number=1, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key, + ), + ], + containing_type=None, + serialized_options=None, + serialized_start=712, + serialized_end=754, +) +_sym_db.RegisterEnumDescriptor(_ABUSEREPORTSTATE) + +AbuseReportState = enum_type_wrapper.EnumTypeWrapper(_ABUSEREPORTSTATE) +NORMAL_FEATURES = 1 +EXTENDED_FEATURES = 2 +OK = 0 +TAKEN_DOWN = 1 + +_TAKEDOWNREQUEST = _descriptor.Descriptor( + name="TakedownRequest", + full_name="spotify_playlist_annotate3.proto.TakedownRequest", + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name="abuse_report_state", + full_name= + "spotify_playlist_annotate3.proto.TakedownRequest.abuse_report_state", + index=0, + number=1, + type=14, + cpp_type=8, + label=1, + has_default_value=False, + default_value=0, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax="proto2", + extension_ranges=[], + oneofs=[], + serialized_start=62, + serialized_end=159, +) + +_ANNOTATEREQUEST = _descriptor.Descriptor( + name="AnnotateRequest", + full_name="spotify_playlist_annotate3.proto.AnnotateRequest", + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name="description", + full_name= + "spotify_playlist_annotate3.proto.AnnotateRequest.description", + index=0, + number=1, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"".decode("utf-8"), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="image_uri", + full_name= + "spotify_playlist_annotate3.proto.AnnotateRequest.image_uri", + index=1, + number=2, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"".decode("utf-8"), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax="proto2", + extension_ranges=[], + oneofs=[], + serialized_start=161, + serialized_end=218, +) + +_TRANSCODEDPICTURE = _descriptor.Descriptor( + name="TranscodedPicture", + full_name="spotify_playlist_annotate3.proto.TranscodedPicture", + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name="target_name", + full_name= + "spotify_playlist_annotate3.proto.TranscodedPicture.target_name", + index=0, + number=1, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"".decode("utf-8"), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="uri", + full_name="spotify_playlist_annotate3.proto.TranscodedPicture.uri", + index=1, + number=2, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"".decode("utf-8"), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax="proto2", + extension_ranges=[], + oneofs=[], + serialized_start=220, + serialized_end=273, +) + +_PLAYLISTANNOTATION = _descriptor.Descriptor( + name="PlaylistAnnotation", + full_name="spotify_playlist_annotate3.proto.PlaylistAnnotation", + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name="description", + full_name= + "spotify_playlist_annotate3.proto.PlaylistAnnotation.description", + index=0, + number=1, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"".decode("utf-8"), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="picture", + full_name= + "spotify_playlist_annotate3.proto.PlaylistAnnotation.picture", + index=1, + number=2, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"".decode("utf-8"), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="deprecated_render_features", + full_name= + "spotify_playlist_annotate3.proto.PlaylistAnnotation.deprecated_render_features", + index=2, + number=3, + type=14, + cpp_type=8, + label=1, + has_default_value=True, + default_value=1, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=b"\030\001", + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="transcoded_picture", + full_name= + "spotify_playlist_annotate3.proto.PlaylistAnnotation.transcoded_picture", + index=3, + number=4, + type=11, + cpp_type=10, + label=3, + has_default_value=False, + default_value=[], + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="is_abuse_reporting_enabled", + full_name= + "spotify_playlist_annotate3.proto.PlaylistAnnotation.is_abuse_reporting_enabled", + index=4, + number=6, + type=8, + cpp_type=7, + label=1, + has_default_value=True, + default_value=True, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="abuse_report_state", + full_name= + "spotify_playlist_annotate3.proto.PlaylistAnnotation.abuse_report_state", + index=5, + number=7, + type=14, + cpp_type=8, + label=1, + has_default_value=True, + default_value=0, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax="proto2", + extension_ranges=[], + oneofs=[], + serialized_start=276, + serialized_end=648, +) + +_TAKEDOWNREQUEST.fields_by_name[ + "abuse_report_state"].enum_type = _ABUSEREPORTSTATE +_PLAYLISTANNOTATION.fields_by_name[ + "deprecated_render_features"].enum_type = _RENDERFEATURES +_PLAYLISTANNOTATION.fields_by_name[ + "transcoded_picture"].message_type = _TRANSCODEDPICTURE +_PLAYLISTANNOTATION.fields_by_name[ + "abuse_report_state"].enum_type = _ABUSEREPORTSTATE +DESCRIPTOR.message_types_by_name["TakedownRequest"] = _TAKEDOWNREQUEST +DESCRIPTOR.message_types_by_name["AnnotateRequest"] = _ANNOTATEREQUEST +DESCRIPTOR.message_types_by_name["TranscodedPicture"] = _TRANSCODEDPICTURE +DESCRIPTOR.message_types_by_name["PlaylistAnnotation"] = _PLAYLISTANNOTATION +DESCRIPTOR.enum_types_by_name["RenderFeatures"] = _RENDERFEATURES +DESCRIPTOR.enum_types_by_name["AbuseReportState"] = _ABUSEREPORTSTATE +_sym_db.RegisterFileDescriptor(DESCRIPTOR) + +TakedownRequest = _reflection.GeneratedProtocolMessageType( + "TakedownRequest", + (_message.Message, ), + { + "DESCRIPTOR": _TAKEDOWNREQUEST, + "__module__": "playlist_annotate3_pb2" + # @@protoc_insertion_point(class_scope:spotify_playlist_annotate3.proto.TakedownRequest) + }, +) +_sym_db.RegisterMessage(TakedownRequest) + +AnnotateRequest = _reflection.GeneratedProtocolMessageType( + "AnnotateRequest", + (_message.Message, ), + { + "DESCRIPTOR": _ANNOTATEREQUEST, + "__module__": "playlist_annotate3_pb2" + # @@protoc_insertion_point(class_scope:spotify_playlist_annotate3.proto.AnnotateRequest) + }, +) +_sym_db.RegisterMessage(AnnotateRequest) + +TranscodedPicture = _reflection.GeneratedProtocolMessageType( + "TranscodedPicture", + (_message.Message, ), + { + "DESCRIPTOR": _TRANSCODEDPICTURE, + "__module__": "playlist_annotate3_pb2" + # @@protoc_insertion_point(class_scope:spotify_playlist_annotate3.proto.TranscodedPicture) + }, +) +_sym_db.RegisterMessage(TranscodedPicture) + +PlaylistAnnotation = _reflection.GeneratedProtocolMessageType( + "PlaylistAnnotation", + (_message.Message, ), + { + "DESCRIPTOR": _PLAYLISTANNOTATION, + "__module__": "playlist_annotate3_pb2" + # @@protoc_insertion_point(class_scope:spotify_playlist_annotate3.proto.PlaylistAnnotation) + }, +) +_sym_db.RegisterMessage(PlaylistAnnotation) + +DESCRIPTOR._options = None +_PLAYLISTANNOTATION.fields_by_name[ + "deprecated_render_features"]._options = None +# @@protoc_insertion_point(module_scope) diff --git a/librespot/proto/Pubsub_pb2.py b/librespot/proto/Pubsub_pb2.py new file mode 100644 index 0000000..abe1b3e --- /dev/null +++ b/librespot/proto/Pubsub_pb2.py @@ -0,0 +1,112 @@ +# -*- coding: utf-8 -*- +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: pubsub.proto +"""Generated protocol buffer code.""" +from google.protobuf import descriptor as _descriptor +from google.protobuf import message as _message +from google.protobuf import reflection as _reflection +from google.protobuf import symbol_database as _symbol_database +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + +DESCRIPTOR = _descriptor.FileDescriptor( + name='pubsub.proto', + package='spotify', + syntax='proto2', + serialized_options=b'\n\013com.spotify', + create_key=_descriptor._internal_create_key, + serialized_pb= + b'\n\x0cpubsub.proto\x12\x07spotify\"@\n\x0cSubscription\x12\x0b\n\x03uri\x18\x01 \x01(\t\x12\x0e\n\x06\x65xpiry\x18\x02 \x01(\x05\x12\x13\n\x0bstatus_code\x18\x03 \x01(\x05\x42\r\n\x0b\x63om.spotify' +) + +_SUBSCRIPTION = _descriptor.Descriptor( + name='Subscription', + full_name='spotify.Subscription', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='uri', + full_name='spotify.Subscription.uri', + index=0, + number=1, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"".decode('utf-8'), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='expiry', + full_name='spotify.Subscription.expiry', + index=1, + number=2, + type=5, + cpp_type=1, + label=1, + has_default_value=False, + default_value=0, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='status_code', + full_name='spotify.Subscription.status_code', + index=2, + number=3, + type=5, + cpp_type=1, + label=1, + has_default_value=False, + default_value=0, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax='proto2', + extension_ranges=[], + oneofs=[], + serialized_start=25, + serialized_end=89, +) + +DESCRIPTOR.message_types_by_name['Subscription'] = _SUBSCRIPTION +_sym_db.RegisterFileDescriptor(DESCRIPTOR) + +Subscription = _reflection.GeneratedProtocolMessageType( + 'Subscription', + (_message.Message, ), + { + 'DESCRIPTOR': _SUBSCRIPTION, + '__module__': 'pubsub_pb2' + # @@protoc_insertion_point(class_scope:spotify.Subscription) + }) +_sym_db.RegisterMessage(Subscription) + +DESCRIPTOR._options = None +# @@protoc_insertion_point(module_scope) diff --git a/librespot/proto/Queue_pb2.py b/librespot/proto/Queue_pb2.py new file mode 100644 index 0000000..0abb762 --- /dev/null +++ b/librespot/proto/Queue_pb2.py @@ -0,0 +1,104 @@ +# -*- coding: utf-8 -*- +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: queue.proto +"""Generated protocol buffer code.""" +import ContextTrack_pb2 as context__track__pb2 +from google.protobuf import descriptor as _descriptor +from google.protobuf import message as _message +from google.protobuf import reflection as _reflection +from google.protobuf import symbol_database as _symbol_database + +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + +DESCRIPTOR = _descriptor.FileDescriptor( + name="queue.proto", + package="spotify.player.proto.transfer", + syntax="proto2", + serialized_options=b"\n\024com.spotify.transferH\002", + 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', + dependencies=[ + context__track__pb2.DESCRIPTOR, + ], +) + +_QUEUE = _descriptor.Descriptor( + name="Queue", + full_name="spotify.player.proto.transfer.Queue", + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name="tracks", + full_name="spotify.player.proto.transfer.Queue.tracks", + index=0, + number=1, + type=11, + cpp_type=10, + label=3, + has_default_value=False, + default_value=[], + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="is_playing_queue", + full_name="spotify.player.proto.transfer.Queue.is_playing_queue", + index=1, + number=2, + type=8, + cpp_type=7, + label=1, + has_default_value=False, + default_value=False, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax="proto2", + extension_ranges=[], + oneofs=[], + serialized_start=67, + serialized_end=152, +) + +_QUEUE.fields_by_name[ + "tracks"].message_type = context__track__pb2._CONTEXTTRACK +DESCRIPTOR.message_types_by_name["Queue"] = _QUEUE +_sym_db.RegisterFileDescriptor(DESCRIPTOR) + +Queue = _reflection.GeneratedProtocolMessageType( + "Queue", + (_message.Message, ), + { + "DESCRIPTOR": _QUEUE, + "__module__": "queue_pb2" + # @@protoc_insertion_point(class_scope:spotify.player.proto.transfer.Queue) + }, +) +_sym_db.RegisterMessage(Queue) + +DESCRIPTOR._options = None +# @@protoc_insertion_point(module_scope) diff --git a/librespot/proto/Restrictions_pb2.py b/librespot/proto/Restrictions_pb2.py new file mode 100644 index 0000000..489e934 --- /dev/null +++ b/librespot/proto/Restrictions_pb2.py @@ -0,0 +1,480 @@ +# -*- coding: utf-8 -*- +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: restrictions.proto +"""Generated protocol buffer code.""" +from google.protobuf import descriptor as _descriptor +from google.protobuf import message as _message +from google.protobuf import reflection as _reflection +from google.protobuf import symbol_database as _symbol_database + +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + +DESCRIPTOR = _descriptor.FileDescriptor( + name="restrictions.proto", + package="spotify.player.proto", + syntax="proto2", + serialized_options=b"\n\023com.spotify.contextH\002", + 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', +) + +_RESTRICTIONS = _descriptor.Descriptor( + name="Restrictions", + full_name="spotify.player.proto.Restrictions", + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name="disallow_pausing_reasons", + full_name= + "spotify.player.proto.Restrictions.disallow_pausing_reasons", + index=0, + number=1, + type=9, + cpp_type=9, + label=3, + has_default_value=False, + default_value=[], + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="disallow_resuming_reasons", + full_name= + "spotify.player.proto.Restrictions.disallow_resuming_reasons", + index=1, + number=2, + type=9, + cpp_type=9, + label=3, + has_default_value=False, + default_value=[], + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="disallow_seeking_reasons", + full_name= + "spotify.player.proto.Restrictions.disallow_seeking_reasons", + index=2, + number=3, + type=9, + cpp_type=9, + label=3, + has_default_value=False, + default_value=[], + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="disallow_peeking_prev_reasons", + full_name= + "spotify.player.proto.Restrictions.disallow_peeking_prev_reasons", + index=3, + number=4, + type=9, + cpp_type=9, + label=3, + has_default_value=False, + default_value=[], + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="disallow_peeking_next_reasons", + full_name= + "spotify.player.proto.Restrictions.disallow_peeking_next_reasons", + index=4, + number=5, + type=9, + cpp_type=9, + label=3, + has_default_value=False, + default_value=[], + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="disallow_skipping_prev_reasons", + full_name= + "spotify.player.proto.Restrictions.disallow_skipping_prev_reasons", + index=5, + number=6, + type=9, + cpp_type=9, + label=3, + has_default_value=False, + default_value=[], + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="disallow_skipping_next_reasons", + full_name= + "spotify.player.proto.Restrictions.disallow_skipping_next_reasons", + index=6, + number=7, + type=9, + cpp_type=9, + label=3, + has_default_value=False, + default_value=[], + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="disallow_toggling_repeat_context_reasons", + full_name= + "spotify.player.proto.Restrictions.disallow_toggling_repeat_context_reasons", + index=7, + number=8, + type=9, + cpp_type=9, + label=3, + has_default_value=False, + default_value=[], + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="disallow_toggling_repeat_track_reasons", + full_name= + "spotify.player.proto.Restrictions.disallow_toggling_repeat_track_reasons", + index=8, + number=9, + type=9, + cpp_type=9, + label=3, + has_default_value=False, + default_value=[], + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="disallow_toggling_shuffle_reasons", + full_name= + "spotify.player.proto.Restrictions.disallow_toggling_shuffle_reasons", + index=9, + number=10, + type=9, + cpp_type=9, + label=3, + has_default_value=False, + default_value=[], + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="disallow_set_queue_reasons", + full_name= + "spotify.player.proto.Restrictions.disallow_set_queue_reasons", + index=10, + number=11, + type=9, + cpp_type=9, + label=3, + has_default_value=False, + default_value=[], + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="disallow_interrupting_playback_reasons", + full_name= + "spotify.player.proto.Restrictions.disallow_interrupting_playback_reasons", + index=11, + number=12, + type=9, + cpp_type=9, + label=3, + has_default_value=False, + default_value=[], + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="disallow_transferring_playback_reasons", + full_name= + "spotify.player.proto.Restrictions.disallow_transferring_playback_reasons", + index=12, + number=13, + type=9, + cpp_type=9, + label=3, + has_default_value=False, + default_value=[], + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="disallow_remote_control_reasons", + full_name= + "spotify.player.proto.Restrictions.disallow_remote_control_reasons", + index=13, + number=14, + type=9, + cpp_type=9, + label=3, + has_default_value=False, + default_value=[], + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="disallow_inserting_into_next_tracks_reasons", + full_name= + "spotify.player.proto.Restrictions.disallow_inserting_into_next_tracks_reasons", + index=14, + number=15, + type=9, + cpp_type=9, + label=3, + has_default_value=False, + default_value=[], + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="disallow_inserting_into_context_tracks_reasons", + full_name= + "spotify.player.proto.Restrictions.disallow_inserting_into_context_tracks_reasons", + index=15, + number=16, + type=9, + cpp_type=9, + label=3, + has_default_value=False, + default_value=[], + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="disallow_reordering_in_next_tracks_reasons", + full_name= + "spotify.player.proto.Restrictions.disallow_reordering_in_next_tracks_reasons", + index=16, + number=17, + type=9, + cpp_type=9, + label=3, + has_default_value=False, + default_value=[], + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="disallow_reordering_in_context_tracks_reasons", + full_name= + "spotify.player.proto.Restrictions.disallow_reordering_in_context_tracks_reasons", + index=17, + number=18, + type=9, + cpp_type=9, + label=3, + has_default_value=False, + default_value=[], + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="disallow_removing_from_next_tracks_reasons", + full_name= + "spotify.player.proto.Restrictions.disallow_removing_from_next_tracks_reasons", + index=18, + number=19, + type=9, + cpp_type=9, + label=3, + has_default_value=False, + default_value=[], + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="disallow_removing_from_context_tracks_reasons", + full_name= + "spotify.player.proto.Restrictions.disallow_removing_from_context_tracks_reasons", + index=19, + number=20, + type=9, + cpp_type=9, + label=3, + has_default_value=False, + default_value=[], + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="disallow_updating_context_reasons", + full_name= + "spotify.player.proto.Restrictions.disallow_updating_context_reasons", + index=20, + number=21, + type=9, + cpp_type=9, + label=3, + has_default_value=False, + default_value=[], + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax="proto2", + extension_ranges=[], + oneofs=[], + serialized_start=45, + serialized_end=1000, +) + +DESCRIPTOR.message_types_by_name["Restrictions"] = _RESTRICTIONS +_sym_db.RegisterFileDescriptor(DESCRIPTOR) + +Restrictions = _reflection.GeneratedProtocolMessageType( + "Restrictions", + (_message.Message, ), + { + "DESCRIPTOR": _RESTRICTIONS, + "__module__": "restrictions_pb2" + # @@protoc_insertion_point(class_scope:spotify.player.proto.Restrictions) + }, +) +_sym_db.RegisterMessage(Restrictions) + +DESCRIPTOR._options = None +# @@protoc_insertion_point(module_scope) diff --git a/librespot/proto/Session_pb2.py b/librespot/proto/Session_pb2.py new file mode 100644 index 0000000..9214092 --- /dev/null +++ b/librespot/proto/Session_pb2.py @@ -0,0 +1,149 @@ +# -*- coding: utf-8 -*- +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: session.proto +"""Generated protocol buffer code.""" +import Context_pb2 as context__pb2 +import ContextPlayerOptions_pb2 as context__player__options__pb2 +import PlayOrigin_pb2 as play__origin__pb2 +from google.protobuf import descriptor as _descriptor +from google.protobuf import message as _message +from google.protobuf import reflection as _reflection +from google.protobuf import symbol_database as _symbol_database + +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + +DESCRIPTOR = _descriptor.FileDescriptor( + name="session.proto", + package="spotify.player.proto.transfer", + syntax="proto2", + serialized_options=b"\n\024com.spotify.transferH\002", + 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', + dependencies=[ + context__pb2.DESCRIPTOR, + context__player__options__pb2.DESCRIPTOR, + play__origin__pb2.DESCRIPTOR, + ], +) + +_SESSION = _descriptor.Descriptor( + name="Session", + full_name="spotify.player.proto.transfer.Session", + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name="play_origin", + full_name="spotify.player.proto.transfer.Session.play_origin", + index=0, + number=1, + type=11, + cpp_type=10, + label=1, + has_default_value=False, + default_value=None, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="context", + full_name="spotify.player.proto.transfer.Session.context", + index=1, + number=2, + type=11, + cpp_type=10, + label=1, + has_default_value=False, + default_value=None, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="current_uid", + full_name="spotify.player.proto.transfer.Session.current_uid", + index=2, + number=3, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"".decode("utf-8"), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="option_overrides", + full_name="spotify.player.proto.transfer.Session.option_overrides", + index=3, + number=4, + type=11, + cpp_type=10, + label=1, + has_default_value=False, + default_value=None, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax="proto2", + extension_ranges=[], + oneofs=[], + serialized_start=113, + serialized_end=324, +) + +_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[ + "option_overrides"].message_type = context__player__options__pb2._CONTEXTPLAYEROPTIONOVERRIDES +DESCRIPTOR.message_types_by_name["Session"] = _SESSION +_sym_db.RegisterFileDescriptor(DESCRIPTOR) + +Session = _reflection.GeneratedProtocolMessageType( + "Session", + (_message.Message, ), + { + "DESCRIPTOR": _SESSION, + "__module__": "session_pb2" + # @@protoc_insertion_point(class_scope:spotify.player.proto.transfer.Session) + }, +) +_sym_db.RegisterMessage(Session) + +DESCRIPTOR._options = None +# @@protoc_insertion_point(module_scope) diff --git a/librespot/proto/StorageResolve_pb2.py b/librespot/proto/StorageResolve_pb2.py new file mode 100644 index 0000000..3319832 --- /dev/null +++ b/librespot/proto/StorageResolve_pb2.py @@ -0,0 +1,154 @@ +# -*- coding: utf-8 -*- +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: storage-resolve.proto +"""Generated protocol buffer code.""" +from google.protobuf import descriptor as _descriptor +from google.protobuf import message as _message +from google.protobuf import reflection as _reflection +from google.protobuf import symbol_database as _symbol_database +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + +DESCRIPTOR = _descriptor.FileDescriptor( + name='storage-resolve.proto', + package='spotify.download.proto', + syntax='proto3', + serialized_options=b'\n\023com.spotify.storageH\002', + create_key=_descriptor._internal_create_key, + serialized_pb= + b'\n\x15storage-resolve.proto\x12\x16spotify.download.proto\"\xaf\x01\n\x16StorageResolveResponse\x12\x45\n\x06result\x18\x01 \x01(\x0e\x32\x35.spotify.download.proto.StorageResolveResponse.Result\x12\x0e\n\x06\x63\x64nurl\x18\x02 \x03(\t\x12\x0e\n\x06\x66ileid\x18\x04 \x01(\x0c\".\n\x06Result\x12\x07\n\x03\x43\x44N\x10\x00\x12\x0b\n\x07STORAGE\x10\x01\x12\x0e\n\nRESTRICTED\x10\x03\x42\x17\n\x13\x63om.spotify.storageH\x02\x62\x06proto3' +) + +_STORAGERESOLVERESPONSE_RESULT = _descriptor.EnumDescriptor( + name='Result', + full_name='spotify.download.proto.StorageResolveResponse.Result', + filename=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + values=[ + _descriptor.EnumValueDescriptor( + name='CDN', + index=0, + number=0, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='STORAGE', + index=1, + number=1, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + _descriptor.EnumValueDescriptor( + name='RESTRICTED', + index=2, + number=3, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key), + ], + containing_type=None, + serialized_options=None, + serialized_start=179, + serialized_end=225, +) +_sym_db.RegisterEnumDescriptor(_STORAGERESOLVERESPONSE_RESULT) + +_STORAGERESOLVERESPONSE = _descriptor.Descriptor( + name='StorageResolveResponse', + full_name='spotify.download.proto.StorageResolveResponse', + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name='result', + full_name='spotify.download.proto.StorageResolveResponse.result', + index=0, + number=1, + type=14, + cpp_type=8, + label=1, + has_default_value=False, + default_value=0, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='cdnurl', + full_name='spotify.download.proto.StorageResolveResponse.cdnurl', + index=1, + number=2, + type=9, + cpp_type=9, + label=3, + has_default_value=False, + default_value=[], + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + _descriptor.FieldDescriptor( + name='fileid', + full_name='spotify.download.proto.StorageResolveResponse.fileid', + index=2, + number=4, + type=12, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"", + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key), + ], + extensions=[], + nested_types=[], + enum_types=[ + _STORAGERESOLVERESPONSE_RESULT, + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[], + serialized_start=50, + serialized_end=225, +) + +_STORAGERESOLVERESPONSE.fields_by_name[ + 'result'].enum_type = _STORAGERESOLVERESPONSE_RESULT +_STORAGERESOLVERESPONSE_RESULT.containing_type = _STORAGERESOLVERESPONSE +DESCRIPTOR.message_types_by_name[ + 'StorageResolveResponse'] = _STORAGERESOLVERESPONSE +_sym_db.RegisterFileDescriptor(DESCRIPTOR) + +StorageResolveResponse = _reflection.GeneratedProtocolMessageType( + 'StorageResolveResponse', + (_message.Message, ), + { + 'DESCRIPTOR': _STORAGERESOLVERESPONSE, + '__module__': 'storage_resolve_pb2' + # @@protoc_insertion_point(class_scope:spotify.download.proto.StorageResolveResponse) + }) +_sym_db.RegisterMessage(StorageResolveResponse) + +DESCRIPTOR._options = None +# @@protoc_insertion_point(module_scope) diff --git a/librespot/proto/TransferState_pb2.py b/librespot/proto/TransferState_pb2.py new file mode 100644 index 0000000..1db7786 --- /dev/null +++ b/librespot/proto/TransferState_pb2.py @@ -0,0 +1,174 @@ +# -*- coding: utf-8 -*- +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: transfer_state.proto +"""Generated protocol buffer code.""" +import ContextPlayerOptions_pb2 as context__player__options__pb2 +import Playback_pb2 as playback__pb2 +import Queue_pb2 as queue__pb2 +import Session_pb2 as session__pb2 +from google.protobuf import descriptor as _descriptor +from google.protobuf import message as _message +from google.protobuf import reflection as _reflection +from google.protobuf import symbol_database as _symbol_database + +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + +DESCRIPTOR = _descriptor.FileDescriptor( + name="transfer_state.proto", + package="spotify.player.proto.transfer", + syntax="proto2", + serialized_options=b"\n\024com.spotify.transferH\002", + 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", + dependencies=[ + context__player__options__pb2.DESCRIPTOR, + playback__pb2.DESCRIPTOR, + session__pb2.DESCRIPTOR, + queue__pb2.DESCRIPTOR, + ], +) + +_TRANSFERSTATE = _descriptor.Descriptor( + name="TransferState", + full_name="spotify.player.proto.transfer.TransferState", + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name="options", + full_name="spotify.player.proto.transfer.TransferState.options", + index=0, + number=1, + type=11, + cpp_type=10, + label=1, + has_default_value=False, + default_value=None, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="playback", + full_name="spotify.player.proto.transfer.TransferState.playback", + index=1, + number=2, + type=11, + cpp_type=10, + label=1, + has_default_value=False, + default_value=None, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="current_session", + full_name= + "spotify.player.proto.transfer.TransferState.current_session", + index=2, + number=3, + type=11, + cpp_type=10, + label=1, + has_default_value=False, + default_value=None, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="queue", + full_name="spotify.player.proto.transfer.TransferState.queue", + index=3, + number=4, + type=11, + cpp_type=10, + label=1, + has_default_value=False, + default_value=None, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="creation_timestamp", + full_name= + "spotify.player.proto.transfer.TransferState.creation_timestamp", + index=4, + number=5, + type=3, + cpp_type=2, + label=1, + has_default_value=False, + default_value=0, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax="proto2", + extension_ranges=[], + oneofs=[], + serialized_start=130, + serialized_end=411, +) + +_TRANSFERSTATE.fields_by_name[ + "options"].message_type = context__player__options__pb2._CONTEXTPLAYEROPTIONS +_TRANSFERSTATE.fields_by_name[ + "playback"].message_type = playback__pb2._PLAYBACK +_TRANSFERSTATE.fields_by_name[ + "current_session"].message_type = session__pb2._SESSION +_TRANSFERSTATE.fields_by_name["queue"].message_type = queue__pb2._QUEUE +DESCRIPTOR.message_types_by_name["TransferState"] = _TRANSFERSTATE +_sym_db.RegisterFileDescriptor(DESCRIPTOR) + +TransferState = _reflection.GeneratedProtocolMessageType( + "TransferState", + (_message.Message, ), + { + "DESCRIPTOR": _TRANSFERSTATE, + "__module__": "transfer_state_pb2" + # @@protoc_insertion_point(class_scope:spotify.player.proto.transfer.TransferState) + }, +) +_sym_db.RegisterMessage(TransferState) + +DESCRIPTOR._options = None +# @@protoc_insertion_point(module_scope) diff --git a/librespot/proto/__init__.py b/librespot/proto/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/librespot/proto/__pycache__/Authentication_pb2.cpython-312.pyc b/librespot/proto/__pycache__/Authentication_pb2.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..c2a0134cab7c17e09e71f540be82999db664e007 GIT binary patch literal 46459 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 R8!0MX;QyF&vp>)C{{j2KWI_M{ literal 0 HcmV?d00001 diff --git a/librespot/proto/__pycache__/CanvazMeta_pb2.cpython-312.pyc b/librespot/proto/__pycache__/CanvazMeta_pb2.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..d7b8246664a1f7da832dd4901bb1ed83a2c2dfb1 GIT binary patch literal 2448 zcmbtV-*3}K96#rmf26LRI8D+*p(?O6NW>a!V`69%qou1fDC#Pvc@LJ8y95`#z^3w_Y!5^*#j=D{X)nuLCV1j$cTU}u(oJaiq`S}E_s4y|-}~J8H&GM- z`Nq48t!r5T{-l%mQx3q(zY+la1R&4=WMIN#+6gVmP@E(V55l$1#X?%n; zme9^>Sq3Bk;&;li^Xa&E05y?lBzI0vB{705uy>8#r8e@7TC{C1-*DPB&vksW*{w~)VI~q?@ron_ z;RJ=R65h{L^tQYF3ECI8gw!^PBF_uyjoUZY*JME9y^YniO_|B(1Tlj8*PEMnH}0&< ziF{coys@Nj-MF*5d0S5ASs}T;aZ65pSv)ze`a$T`OqjBbHVRqSXgnYV3o~BV_Kk;O z-b2_lEVGB8?zpsiUMMs$A}66gK;2M0B6sUy6nU@oc9Ci{r90syqiP28q#$A1v>|#J zW=P@d2;&*LmZB$s#Yh}wHKKG3-%NT$9zPJCnDr=0MKtYEil7mt_~=K{RfWl>e6wR& zdXz2KG%XaN6h)I=GrNY>L0%{|98v+(Htkl#ib;6#k$gShzfV$14Nj$#^P$ms_>#c4Xt>Qk;_`iO?IevGeS`IzgPY5NGCt~Xxl&jn(P5c(1=`UogX#YVFOV+GBcdKv+tcga z$srxOK9&F%^YK^klGuXRwtC-bBel^bT(S+nfV{t)*T`+-#yRj0=E2_b5B$mIvH&z)QhwB@lA~ zuNb3tw{C@l|5R|lo5uSAv?#xmen{*UI;JNvA>vu5!> zG;cE1nap^b0dw;~=~OUR3Y6lj7V{CG=%>d!3}Cn+I5Ple9(SID3;XQKQ?@*0R|f3L zFLTdWwVw(&zMr0Sa;`51rSely2r_IxxxaF$FATxr04zRk4#0%~um`Ss&%wq0;zD2e L11R_!In{pvqFj1> literal 0 HcmV?d00001 diff --git a/librespot/proto/__pycache__/Canvaz_pb2.cpython-312.pyc b/librespot/proto/__pycache__/Canvaz_pb2.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..9dfcc05b39956dda5cea1f3dd71d19c5754b6fd4 GIT binary patch literal 13788 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 Jdg(XQ{{sd7eh2^n literal 0 HcmV?d00001 diff --git a/librespot/proto/__pycache__/ClientToken_pb2.cpython-312.pyc b/librespot/proto/__pycache__/ClientToken_pb2.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..f13a7e4918881e7e8f449a5e76a3838111baece0 GIT binary patch literal 5220 zcmb7H-A^0Y6(5fQ;|n(S@Z}^B%z%wCU?(K2Zkl#mVdQX$-1&y3-mC>@&bhyP z&pn@a?tB`HAqswPk0$rb6h-}u2=1@XVZPiBQ`E01k=mxjkVwm+CcPaF5k4&UG<&!E zEWQW$$acTQ_W~c?Mj?u(Fgh4>75dMY4!b=FTKeQzGrm1!&F=3u`(WDF;BsQ*Wyt2Y zldxO(VAe(aCnm_SyXQ;VMy&n92RVP9%i*Nhe{Kc%Pktc^_Z{SIK1jvrGtlyjka|T# zILUkdiUS~xyEDZ>oZ_!|QVgW4o)pK|0@x5pK9;}}0W1lUk1=>MfDMD>V9# z$Hwqf02>F%$5J>Qz^;JgV^{HX0J{c~k4<1UfK7trW7qLa0Gk5I$I^H{OCb4J0WSowB1k@V z11|=!n;?1EF*-)`%P*$x;}%v09gFFdTM zbmjpXRBe{mkJ~sEN{4dsI+|2Q-`GthXx!&iAyOOGz}~l-a*qUOn2;AqnIZs z+1M9k8MpQ@FSN7|v8tuQma^O3mAR`*_99Q^N)$yLC)wYGP|~(Puq!i$;*RM@u$!c` ztT;rOB#JuYl4v;;1@lIO(d9MqnUzAv#2c5INCErXaPLIO-EE&W)MP8!I`#3UNU&)X8H<%L}xtGtGxJVed% zwwD1|#k+v+Uw}zL_cC`-#NJg)^;mh#b#*FWFv~+byT#)9c(G2tdoFHvsbsru;pt?v zXw0sW8g8gq-xO4#iNQmS8ALsrAnQ(~zJo@%BSAid>U>x`KZ~4=PMn~VWNAkgR0)&V zgmY2$He%KUZNCivfn|^g()#+owXl~YrVSyKp4c~x@_dR? zPHRKPz(2n2Ip|dCyBvZSV*|BXLu1&92Y;Xi)!K(x_XfBul%Vt}n(&nFL%i?E$(kBp{x+FiN3nC6{nqL9-G<1oq5&`R2kzOk)V0tq zh6c3!5JgGac#=10b@FCh=&Iv<=pa%3s86uoYitgU1`h8PL3Cbp%n*t+v8D-oPSfQN z-4=GvQ|py)RsS#=s&Y@ZxLTdxsywP}Jgp=sW(r+%2g~aZxJsR0E!9iBGnNQ388q!p zSSzisbCvrXU#irea@CqQjm{szd+h(b6h=^@%GEYEDm5;!@eG>sM(tytR-k>9A2Fsv{tIE@ns;1@CrE5P@3J6x<>E7Sq9g~TV}$kQ0rAfZhH4B z+6>$w-$93Tx1XY<-xKmjLUM3Ll=6gp0_5{G&?2qFCzrHA$iE5s4jjb^>vTba+k)B>WECu;%zoavO`Ag(CaPcw zWe)KErCJ4xC^Hclv98%F7(j+ET(!-}D&7^~r~+F6;>8_vh`gQ1O+mNKQ6pq!^4wLA zLFd*H_3Fz+<}&OD&OW9X40JF9FSr?8(ZG zAZyOVy3!7yFyC3JnGC-LJyPa<-8G1a($?X2s+q%Z&v0$<2FH23n61`v8nyo8P0maP zXTv>G)y<*c5N?TP>ilB6sjSs;zuhc(`20-k6ajPXy~&B;Y)w?Uo#Gr4E;4dng}s?M zXgB@p#^ch1iaE+VM}gyxGYNKgmDb$eH(k%|F5WCvOOLra97>?X?OwQ>_`}0I>0Hvd zfkEVJzM#;0Ay~&8gwj`NI|ZS1l{o_mUy(C17W8+ewCcp+chr|qWz<(nabIcTV&iy+ zl)rwc6$`S`5agn^FQ~ZKmfFvYN4RyQ6<=5%eMKnNV*6O%S6a6UHS%@-`hTFVCEEEJwxm(#J)zeCz1d5QK6L(0P*Z;Z1OCYc@@jNj?JCL?!1cKc}r1u zwY%V1T)%sQKBMMN`p>AjSJd2Z(I4*r=|PA3zzB|=-oE#@$fwZ`RW-u#v+(q*@bt%9 zufzGzQWGcn4n1njY?5c%SiEscU+K^bM!sM%^TyK6Q~GL$UNjbp7Lzw-=1vM7nl+{~ zto#{A+bJ=URf)?{F^#`NsT zBGEU+lIL|JzjR8Ecj$Q|2UCHWvlx3Pd&|rv_7cOtY1PyW@%FkgIZd7umuSht2E!dX zW6XjFz{~)1QY23{OPzg literal 0 HcmV?d00001 diff --git a/librespot/proto/__pycache__/Connect_pb2.cpython-312.pyc b/librespot/proto/__pycache__/Connect_pb2.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..f34dfa0e8dd420c99db7958f87f02aad3d0118f3 GIT binary patch literal 55763 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 literal 0 HcmV?d00001 diff --git a/librespot/proto/__pycache__/ContextTrack_pb2.cpython-312.pyc b/librespot/proto/__pycache__/ContextTrack_pb2.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..6b7532193d214eb688d5e11cb9313abf50cdc8c8 GIT binary patch literal 5746 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 literal 0 HcmV?d00001 diff --git a/librespot/proto/__pycache__/Keyexchange_pb2.cpython-312.pyc b/librespot/proto/__pycache__/Keyexchange_pb2.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..78e9c458418cf93d22793f85228e500efa90f746 GIT binary patch literal 58852 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 literal 0 HcmV?d00001 diff --git a/librespot/proto/__pycache__/Metadata_pb2.cpython-312.pyc b/librespot/proto/__pycache__/Metadata_pb2.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..c20d66d2312ce1b4d7585209eba13c733e89a348 GIT binary patch literal 89306 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 H`Mvxfh;P3j literal 0 HcmV?d00001 diff --git a/librespot/proto/__pycache__/Playback_pb2.cpython-312.pyc b/librespot/proto/__pycache__/Playback_pb2.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..16bb6e0c1c0f3579838cfe49c26af050fc087a01 GIT binary patch literal 4724 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 XE4_WBMYgPL-2sc|t4t4l9qa!AU4Jlp literal 0 HcmV?d00001 diff --git a/librespot/proto/__pycache__/Playlist4External_pb2.cpython-312.pyc b/librespot/proto/__pycache__/Playlist4External_pb2.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..f7ffdbb3e85f53dd9fd2dcfac71d6e9320a98d4d GIT binary patch literal 72805 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 L||d53A_ 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 F{{zrJ99jSX literal 0 HcmV?d00001 diff --git a/librespot/proto/__pycache__/Pubsub_pb2.cpython-312.pyc b/librespot/proto/__pycache__/Pubsub_pb2.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..71e193e1e07a48a95328e6911aa1173d0ca71d94 GIT binary patch literal 3379 zcmd5-&2JmW6`x&xFS%TjqDYGRq9sL&l$i8aA}4Xu#BrQDi9c$mDasxeOU{s5WwlG} zl7`3vt&Tng1#)Nt1Zb{>`=8_zIu6JTkibEK0J@Fho^tA&SyH4@7d-?px`#Kv_ukC= znD^f77pkft_}JaW=65PW|K!a0173WO9|REkE5fLXu!Lnx+LNmRiQ@p^U^OIg5OBB} z5jX@mT8&9aMkKbI9UGji_eZcAhaG|4!bCGhIE*7WiesQHj%AY-EB}b!5Bq#IDQqlF zv}1%{H4#o=^pdHg)kMIkvEHP7s6#C00{BykyNK}0l%D}bLuT+IOZInzWy&kA}@ zQ2(~ii~GNTqo933$X^t68(##;OZerFrH`a)hCo$z*T*%TtXRDS42kb6@2M4`94f0|EhWLa@NPwl;kH~aGE6bxv{pJ-h8dM z{5G+PYqSY2wOps|)E%o->ogj~E!7=N%7=XSrbHD?yt-?)+KvlcWRG~B(Ii~ql7>a< zZPT%V)4c9p&9QWBw2hkKkzS(Jsd=4RSs14gujRDOMwf;Kf6n6%j1sRqd*zYF+u@QE zr!wPHE3YewJ77-40sb;^CD3urf>e^8jb)NbnC!Pqw_A{b4`pVQxYst?9Z%W<27WhGq5$)}0nl&ZA1*C2&#thono@DSfNv z#vo{VA~qUpbSz8f)_d7eZsqCVX|!QlgzIn6Acs_|JK)>2O}nYLyDj4K%c0?hNi6J9 zo@uY}Buiz`(2!|kvQNWyXRk)wL;j@DAh&WTVvE*WEn$>~ETcv&n%*%y9g~L9vD*4w z!|IT$R6W5z1{0_k>a-iDFVe)Q;J%F*0XIHOn4V7d+r;+Zj;MAFb+7I~3JH;dUzgte z6QlQ)hcfIu4Ds#LW$TrmcxI}whrIu(a_rcn37dG(&mumk+HtHNRmZ_%qh=8|&QGR} zPwK8=H;G5Xj!m3~M^jTZ28V9@kdF>cPKk+)4}UNG`)#hbYUeg(s$6;N&YQQd-FpA# zZK~+{o`X9U(e=Nh%_5EHI(F*1PPL}vG%ey!28^655{W}m#)IYtx#_4rx_j5Z9epxz zF8}}0l>W1!qme6qVZj-wbX=p!tI%OrjxE!yZrW|)+J>c1y4t-UQkmMOUFFR;B?x1} zr-`cio!?&ebG&x*2A!R54^OXkMdQ=lZPGNM7VgiyFC0HQw?=Qyb^kqi9~zcMMvSZR zaI~?FkreJ@G?4C#pm&#n{IpxyarQ{1-i6+``OH_!mQy#Zinn99q|!25`<1)IzUx(b z;{B;uX06idws#!+eEICTif6XT>CqeDaivRm-&MpbRk;w(l5`YB()zdPg>O+s&|k4Iim!gD6bH&mUs?G|Sv!b4QaA4XVW4jG)s0~+ zKTOOH<1@qjb3?5-&?QG7Ib! zAhv=EtAqUZgZwsI<^0-zrZG249GHJ^D$M!5oe*Js`X zO_E*rnHxfL(`RnUD4S!y5zK+gK9JFcH>3k)fJ%K-`h2O6&J0mxfB-Cg(tC)u9%GuDL1?xgn*B0Zc$8Zm=2nhE!BF^dB$A38Bv=Yb(E-Z$QT~&}L-fp} NT=78p8qJ93=HJbBpeq0X literal 0 HcmV?d00001 diff --git a/librespot/proto/__pycache__/Queue_pb2.cpython-312.pyc b/librespot/proto/__pycache__/Queue_pb2.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..7582164c8c2fdacc80f90468129b87d7a9ee83d1 GIT binary patch literal 3311 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 OC)__#RF~-|nEwH|!}yW_ literal 0 HcmV?d00001 diff --git a/librespot/proto/__pycache__/Session_pb2.cpython-312.pyc b/librespot/proto/__pycache__/Session_pb2.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..1f715af69ea53350f7ee812ad819253969b19bc8 GIT binary patch literal 4771 zcmdT{&2JmW6`x)4W4Zj2C`wv=)0Avka!lHczmmANV@q}fB$go=ZOQ^&EIC7Z=@pmR zB~_Dc03ChGC5NU!f#h1a|4A=l;)2XL0Tkq<+dA$kr@oop6(z?`eR5j?e)D_p&HLCl zZ{E=Vh{t6Ff6mTqbt{d~4~+5uk{)>02_p1ogi#S;0gHxE6!|(-4DdBr48b~Ngtw() zL|}UYfaPM8;~?NzG0t%aaH5zLkcddKmhl4()<+&Jj=+vcZE>LS5e{PsN3aaq6TWP) z;wTYoCkMQbNZ^Ii(2Jzip})r-gHn&+|N`x&hGT^->#PJAlhBpwDjf<>Syk_I}; zar(tMf_{v9ePiIwN1oSl*ptK)Kou+ioy1c>r|}HXSv&`Ho=Y&6klMpS5mw_rg{v=)j{NK;(6wm7oo)^n#5})RI<$%s&MvvAj zU(5RyAFTMyBf;fh|LdscS%{Ow1)vJgcM`t|_%&3s8h|+GstD+LPA_ok_Q*xvHJ5M% zv~O|w+nm0GFN5S)_{yikCqhvnp;}>3J0B6HcFxCx6^~B>qfYx0xTBYRJXl|1d-6Hk zK<({;jgMYpd-ge7g`{hjeVf6G6HG`(YF7s`ACa`*6?|&NYu9|uV8sa%tz94RKB@>r z!B_FMzlx8BTv;&-QEvJA!Ai1&C|D$E^)vuqlfQmaxS zR;FxXlG|sVZZ8W|#>6gLdZTGtz=gMoZEID+6c(u%q}Ckcq}iks zw_zvfa@>7q)^39V<<^Y{B(-V^QL!)20> z`c3_^->G=ntT)MnrWfe*%zDKa5GJf%F%MmvPiwDwsfovflVa!zC7&a zs+v2*vUE5UCBVHEe$gAtgIF8&nYYyd0*1y0%SdxS^Hr!#UHC-L5ya2Q+09 zOV!yaEi-BrB+<*Y$c;ZMGZ4im?EpicSn{)5E9KIr~ZxcvpHSPlGxn z{(y$+t?d%A_Spod0TyOI%AizkGc%V?@Qn$aRRY5WLJ zW8U52#xz2}zYAl!twN8II=e44c>qtHP!I02 zQL`Tb@(li=PO#OioW4YV){&hHua?{MoxC3auT(zxZkxvH#D>wt%VUGaFO^N>eyy-p zGKj^GVEDjNg?UmXHVv6|VpeQAe5fn!re-zwKVqR0hs4mO`YN0;jd}x1ZIlYjB9&Ly zwr*^$-?_W7No7^tHgU@!s`@vye4K_=6`N&MrBUzFG8-E6YOZol@l=Ozpv^V2gMIvV zs{Vy?4HJXe!MD3p$!kt`OR{R3RfD)=3#PWk4v0pf|NK#H@sdia*K!v8+-4gFBijlw z$*}s|*rwrCw};^yL8amnP27Ylw|d~2rd1tAs#Vtvb#VW!3(TE-Xj}3oyN!ngAxzlI zLM3%;ZEI_N<2K}T=lyqoyRo@`YyCD&xVKj=wfShUGR&c*-q^T(ckRQwbk;}AWNmZf z&Ry`Z@$0qC&2=~^I(GPO*}fAxzDcS&bdvSlH_RNoes{db?*sQ;y9?KxhCRk&|6QR; z--joKq`YUtVm~>oWgtJ@&)+k*Nxs~MiBZ>@Ejynx%(7EZ8s z@uhBjsUK1Lu~Yr%Xn*3ZesZdp%y*M{CxC(Ru}LS&pc6yG(-8eDh#u#HVH8<>80|?5U1{M*l#0mTjLbPhuzo+j?gU{4pQC9f z%#eiAV@`x28Ku%rl%W_JSDZLQ3AQiE&@h@`bVe9Tq3L;Nl%X`5nsde&8b=e;&ICgW znmy)BGBkyz=ACJVW|(Z2p*fUUbmke#pwx_W43LvW%0h4A;#U(Fodw39_<8nIUiNGM zm)XBs?MDx4Kk?GqJ5c+%&sYAk^2Ki+Pn~|vhp^xs!tMY0LwMQ}J`iFdC&_P0O+>>f z=f21pLu6gP?J{+)FF9XWn_*{Q{;b|}s3_S}=QE@j6y(Rdu!;evB OZ+vQ3{wEsc)B4|A@EZ>R literal 0 HcmV?d00001 diff --git a/librespot/proto/__pycache__/StorageResolve_pb2.cpython-312.pyc b/librespot/proto/__pycache__/StorageResolve_pb2.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..cc3d4c28f3a06e30671c0d19f92400fb9b156d44 GIT binary patch literal 4573 zcmd5;OK%(36}~fk56R*CAyNqnwU@}qWaS5ksPEif4JUeQ!WGsFz# zS_0a7nN>Df)Qc{2+4)KVDR>AMl-aQsRv2~GKhLxmm}H7kC%O~k z`kebGab1MfiuhfiBW(RMI1P9dUjjPL=vkZr?8a3`fd3b9y$9JFZ`a19vf>`Mo-E+XO^ogG+xud6wD z;sWulUOwQvXoVvgJdbbwmf!L?vgJNl<$70t@FaZ)tI)Y34Rm!I;>7LEfm=i+y4)hT z)YP?>R@0PHb$w-p=%t#5NqLuAPjHriiBZ!V&6cJE7g!^PA=e32=wwA9wN^t@fr}X% zYgJ8=u-uZXvOzX82D|~5lR7apk?a%tsXy=tI?A6mL(pN5EVO%oX{IOy~Q^tPgNMb2=C~< zl+fGV4RWPH6l_>-r=7OePJilg>W_Zl=t&^EA`mNBYc^TFyUq?Ma+N4n;*o4fn5@Xq znG!3|O)L5aZ$;cA%wD!a1oq5 zPseFpIA?0tOAA1o>J|J$FYQNZSP_*NFwR&q(D?g_8CJBL8J4TiKJ>%GitoQE>9Sgf zM)GSa(N+wd&dFUm()AKGOt}L{g3X|VOlnrACU{Gjn_rw=xbqOsu_Z{-nugaEB1ykT z6D2DkNm#2%k`=3KT3vBxA52%Bwz?ID9qP_hohD=jC3jPF_;{rT2eVbDAC6XBIx=6a zz?`$ouo$Q$T(!iTa5m=lJzHt1p|*&w%8GO_1ax{WS>inG`XSR45#Bra)%U* zrw8{wnTN;22lp4}B>*4aTe7kXq~3sv>qndkhkV3t(*8dr$erNS5}lJGRX5m~*Uv$m z>>yd0!wqY64Gxw+l6LR@#rDv>*FJLYtR^q)cqbZi=5L#Nmtj^p-%h#UPD zUHTSP7=7RNqww&yQ0NFlZDHuo!pPIWPITR?dX^pDw&ZHGn_JWm(5tA6RWgi z72At^zx2P31x5a;V5ia0wciyxgIC*wSItnu6z9xn!VIPM&3A%hpM^WYv379GOk~Yu z%1ourfnhU|F>^zm+;lrP{W|IoU9m+J8b7csytQTDKd>CgM*MaeWqQn9(ahw{RQB}@ zH#o#^qkemiLtLJcX_&bycUHK-_V|(EFGJDVV z!4rI@(sqENAWCQK5Jdt?rtL6A5tPl@QHn%r7o#YS21e`zMM+fbwNn(OQK8??P?SZv zqMf5CkNO7f9*PR6Fklxc>ZP(iiuzG$#2%oigp$4XARv1P<%eNYzRXSA!;~NSSEEn8 zW%Pajm(jm%?fd_W(eK^mrlEUdtiyiAp?K2%HOH6_c-kE^JnOGH9)-sCJbc`5&oas0 zZ64)&?K=+hV;-gQ_Fad$$D>Hv{>WkO^C+9QA2`fI(1`X=9A<%O79D1ZN9mmXF=Mt- z&i*-%idSq8;_@9d+D4+`<~1PXy|l(pmRtmfJ% Ux1BG)K$V?r;i>QyO0hBfceVc6yZ`_I literal 0 HcmV?d00001 diff --git a/librespot/proto/__pycache__/TransferState_pb2.cpython-312.pyc b/librespot/proto/__pycache__/TransferState_pb2.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..3559a7ce35b1765e8d5a2ae3634ac58f3a1c60d3 GIT binary patch literal 5421 zcmdT{Npl;=74E@07%YR0*hml%32~8RK%!(yG8OHVqR7@lQi%n{nGDbk2=owuXF!#J z6Dud5T(0sVN+pL}Q_3~JA{WC^3h+p-qADlehE`5KrC$$*5GhJ3RV5W0Rp|cSd;OMv z{rWZVcfVgi^kY0oS0@t){R;@|BM!ie8!m)?k1#4C%we0t6>V&`7aeSN7F}$17kN6{ z70;Sb^m4G)L9wssXV^(`peQozqBvL#ama>9Xf^AKcV=TJ7Wqml~3pIrOIPevRMI5AK z2;1lwCNVlj7>@2AIhBtvt4D{{EHtnRHbfk!V*+z@OyU$BNAVaP(|DYY8OF)t0~Aj% zZbgzx;3+^p(%}{S5o~2`g`A_0Q6#xI@I?Uoa!s3F6lK8zJ zMO=9nSAoR^5hd}_A4OcpSX^@~E{G_JkF&TS#xy(A-Sq`E_+P27s*_qeQAKoopN;cu zG^_I@tJhQ5L#3w~{{uEI;4_r-Gko?d?hCG%r1$=Wbzg=vNv_ThDGT9Pl0s?BqG@;d zz{11%HM%o%$cmBDtX#Y$Gvg%96Bg zvlly=tE5g;xkYfcsWw`Tazn|M)+-gFX3Gss@>{U_#w@1`m}q6S)@(IYO1amFrpZ+T z0+m!0Qf}26bxMg^d#%(^BrLb&lB|(Vw57^*joOp67Il+nUOH*5*=W@&?R-;_+e9_F zd26ZeVyosf`W7M~T5hc6t@YNDpWC#*(d-HPnh(F(d}^%RsJF<&mSlRD8cm2^Gowfa zfLoHwpAKlhM)ykP1Je81I$0m=W8x1s!M`%t;4(nxu|Ny<8)j%F|-ecb|stsjMrC z1kO5#trFUG3_FS3b&5J)sVRiT=m4aPP%(0?UaME7R=Y`5A2@SWYDB@BZk>4N_&fN> z56VP$*60=<>aP0wT8XGz&=YhAIN9<7ClTMkg)r&>E_-^JFe)xPBf!@^D$HQiUI_kdO~oS{Y~ zR^m0?Z)G0KC55Q$K!ZD)5^W?^s^MzXNu#3a!I!F?UM#h>^*eACc!^D`zxGF3F?!f4 zWV6jm&C=YgO&2aNE?-)@c5CJ4k}gQnS_7{uM3Vl3W~X(xB;iI`lJvxWtq2V0X{%3K zjncZ55)=EZ=EEqzb@ryv!x{vW2Y0o31yDytJg>IUPBwW%1SLn6Aykl99N;Ucsf(740hf9o^dj{XmA{~0^uuR``;9eHD7R@( zs>`i)t&mq5Wmzd`_hpq7nziP`!UIx&pcOjoB`+woQlZ&y-EY*7=a0=5v|5Y2H|Xyg z2vq|2tiWFO!me%$wUBSNf8fuU1$tJ!Mtn_Nii`=AnC!(*eiJ`wOaeXiYV@On=s*0aMIV9OPZ)MO)13Q%!5MCVJfzhF zNPzTv0r?>Pen0_8zX&J@>q3CSkp2juD5QS`Pz=%^2b6&HCjq4()uVvMApL1TS_?SuVnncl#5@W_allZkAMH0p*Ch;3P@EY!aACk_It}iXBDcMwJm80i$k5nKQld+uiZoh8=NY52d>(-FNu6 zX(JV%iKCmDBfZRgH#5IW8~}0fS#WG~YOXi6(4AV?B_08B{8@amKYzYAf3-V*bt7O} zepKzEsVC@o|HQ=&p@*_vl>Kw2i;ne?yNAZRX#7#<2|BbHJoTlw7d+Jsp6WXyeW$`P zm{(aYNW!OIUNXP)`o}O$mj{VtMUPM7CdmysGYSx-tsFZ2A0x!5ju+rY3 zN8Nk4n;_2-l&rzVAdKEsn=N=5aBX>WCjsfz&aBQFebGOj8!&{^L=Yhox+2g QrDB@KXYnm4rLIWo2O+9ANdN!< literal 0 HcmV?d00001 diff --git a/librespot/proto/spotify/__init__.py b/librespot/proto/spotify/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/librespot/proto/spotify/__pycache__/__init__.cpython-312.pyc b/librespot/proto/spotify/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..dda7669d64fe0060f1e19e25eb98e2e8b993832d GIT binary patch literal 209 zcmZ9G!41MN3`H9X5<=<-48Va}z!fn9D@18AG$Ku`B&`UGFaxtN1`B|C>xtybmux@# z+mc^JvB;u6{qmCPJEeaO(>Qr#AzQKIGqaP}4QXd2XiSSxhYGD0zH?A2Qws&I5f*_Y z-JnO^JGdJ!&jFOIfP!y~-j$mzIO%asqP~g?x@1~(WIT{H-ax{1#JSYcb6!#y=lj;2 UI)w*2ix03EF2OfvjM+TW4=lDijsO4v literal 0 HcmV?d00001 diff --git a/librespot/proto/spotify/login5/__init__.py b/librespot/proto/spotify/login5/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/librespot/proto/spotify/login5/__pycache__/__init__.cpython-312.pyc b/librespot/proto/spotify/login5/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..5f57b586085b6e352881d8a82bf6223ee50c6a6c GIT binary patch literal 216 zcmZ9G!41MN3`H9X5<=<-48Va}fVd$>V1+0xp^Zr6C`k)p5oTZ(#$W+ZZ#|K4L5`q4Whein-Q8F0o`1Y|RV@ zE%X&St~v`hbmHVeiUPEEHL6X%T7wmiFEuOAtl~DBhFgsev_Xdu@ppukP+Oo>DB&p0 awI8Ot29K@edou}tkPtS)CnbcKG|(6OYdsPG literal 0 HcmV?d00001 diff --git a/librespot/proto/spotify/login5/v3/ClientInfo_pb2.py b/librespot/proto/spotify/login5/v3/ClientInfo_pb2.py new file mode 100644 index 0000000..81fc083 --- /dev/null +++ b/librespot/proto/spotify/login5/v3/ClientInfo_pb2.py @@ -0,0 +1,98 @@ +# -*- coding: utf-8 -*- +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: spotify/login5/v3/client_info.proto +"""Generated protocol buffer code.""" +from google.protobuf import descriptor as _descriptor +from google.protobuf import message as _message +from google.protobuf import reflection as _reflection +from google.protobuf import symbol_database as _symbol_database + +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + +DESCRIPTOR = _descriptor.FileDescriptor( + name="spotify/login5/v3/client_info.proto", + package="spotify.login5.v3", + syntax="proto3", + serialized_options=b"\n\024com.spotify.login5v3", + 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', +) + +_CLIENTINFO = _descriptor.Descriptor( + name="ClientInfo", + full_name="spotify.login5.v3.ClientInfo", + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name="client_id", + full_name="spotify.login5.v3.ClientInfo.client_id", + index=0, + number=1, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"".decode("utf-8"), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="device_id", + full_name="spotify.login5.v3.ClientInfo.device_id", + index=1, + number=2, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"".decode("utf-8"), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax="proto3", + extension_ranges=[], + oneofs=[], + serialized_start=58, + serialized_end=108, +) + +DESCRIPTOR.message_types_by_name["ClientInfo"] = _CLIENTINFO +_sym_db.RegisterFileDescriptor(DESCRIPTOR) + +ClientInfo = _reflection.GeneratedProtocolMessageType( + "ClientInfo", + (_message.Message, ), + { + "DESCRIPTOR": _CLIENTINFO, + "__module__": "spotify.login5.v3.client_info_pb2" + # @@protoc_insertion_point(class_scope:spotify.login5.v3.ClientInfo) + }, +) +_sym_db.RegisterMessage(ClientInfo) + +DESCRIPTOR._options = None +# @@protoc_insertion_point(module_scope) diff --git a/librespot/proto/spotify/login5/v3/Login5_pb2.py b/librespot/proto/spotify/login5/v3/Login5_pb2.py new file mode 100644 index 0000000..6fed2a6 --- /dev/null +++ b/librespot/proto/spotify/login5/v3/Login5_pb2.py @@ -0,0 +1,972 @@ +# -*- coding: utf-8 -*- +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: spotify/login5/v3/login5.proto +"""Generated protocol buffer code.""" +from google.protobuf import descriptor as _descriptor +from google.protobuf import message as _message +from google.protobuf import reflection as _reflection +from google.protobuf import symbol_database as _symbol_database +from google.protobuf.internal import enum_type_wrapper +from librespot.proto.spotify.login5.v3 import \ + ClientInfo_pb2 as spotify_dot_login5_dot_v3_dot_client__info__pb2 +from librespot.proto.spotify.login5.v3 import \ + UserInfo_pb2 as spotify_dot_login5_dot_v3_dot_user__info__pb2 +from librespot.proto.spotify.login5.v3.challenges import \ + Code_pb2 as spotify_dot_login5_dot_v3_dot_challenges_dot_code__pb2 +from librespot.proto.spotify.login5.v3.challenges import \ + Hashcash_pb2 as spotify_dot_login5_dot_v3_dot_challenges_dot_hashcash__pb2 +from librespot.proto.spotify.login5.v3.credentials import \ + Credentials_pb2 as \ + spotify_dot_login5_dot_v3_dot_credentials_dot_credentials__pb2 +from librespot.proto.spotify.login5.v3.identifiers import \ + Identifiers as \ + spotify_dot_login5_dot_v3_dot_identifiers_dot_identifiers__pb2 + +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + +DESCRIPTOR = _descriptor.FileDescriptor( + name="spotify/login5/v3/login5.proto", + package="spotify.login5.v3", + syntax="proto3", + serialized_options=b"\n\024com.spotify.login5v3", + 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', + dependencies=[ + 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_challenges_dot_code__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_identifiers_dot_identifiers__pb2. + DESCRIPTOR, + ], +) + +_LOGINERROR = _descriptor.EnumDescriptor( + name="LoginError", + full_name="spotify.login5.v3.LoginError", + filename=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + values=[ + _descriptor.EnumValueDescriptor( + name="UNKNOWN_ERROR", + index=0, + number=0, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key, + ), + _descriptor.EnumValueDescriptor( + name="INVALID_CREDENTIALS", + index=1, + number=1, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key, + ), + _descriptor.EnumValueDescriptor( + name="BAD_REQUEST", + index=2, + number=2, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key, + ), + _descriptor.EnumValueDescriptor( + name="UNSUPPORTED_LOGIN_PROTOCOL", + index=3, + number=3, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key, + ), + _descriptor.EnumValueDescriptor( + name="TIMEOUT", + index=4, + number=4, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key, + ), + _descriptor.EnumValueDescriptor( + name="UNKNOWN_IDENTIFIER", + index=5, + number=5, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key, + ), + _descriptor.EnumValueDescriptor( + name="TOO_MANY_ATTEMPTS", + index=6, + number=6, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key, + ), + _descriptor.EnumValueDescriptor( + name="INVALID_PHONENUMBER", + index=7, + number=7, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key, + ), + _descriptor.EnumValueDescriptor( + name="TRY_AGAIN_LATER", + index=8, + number=8, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key, + ), + ], + containing_type=None, + serialized_options=None, + serialized_start=1917, + serialized_end=2128, +) +_sym_db.RegisterEnumDescriptor(_LOGINERROR) + +LoginError = enum_type_wrapper.EnumTypeWrapper(_LOGINERROR) +UNKNOWN_ERROR = 0 +INVALID_CREDENTIALS = 1 +BAD_REQUEST = 2 +UNSUPPORTED_LOGIN_PROTOCOL = 3 +TIMEOUT = 4 +UNKNOWN_IDENTIFIER = 5 +TOO_MANY_ATTEMPTS = 6 +INVALID_PHONENUMBER = 7 +TRY_AGAIN_LATER = 8 + +_LOGINRESPONSE_WARNINGS = _descriptor.EnumDescriptor( + name="Warnings", + full_name="spotify.login5.v3.LoginResponse.Warnings", + filename=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + values=[ + _descriptor.EnumValueDescriptor( + name="UNKNOWN_WARNING", + index=0, + number=0, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key, + ), + _descriptor.EnumValueDescriptor( + name="DEPRECATED_PROTOCOL_VERSION", + index=1, + number=1, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key, + ), + ], + containing_type=None, + serialized_options=None, + serialized_start=1850, + serialized_end=1914, +) +_sym_db.RegisterEnumDescriptor(_LOGINRESPONSE_WARNINGS) + +_CHALLENGES = _descriptor.Descriptor( + name="Challenges", + full_name="spotify.login5.v3.Challenges", + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name="challenges", + full_name="spotify.login5.v3.Challenges.challenges", + index=0, + number=1, + type=11, + cpp_type=10, + label=3, + has_default_value=False, + default_value=[], + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax="proto3", + extension_ranges=[], + oneofs=[], + serialized_start=309, + serialized_end=371, +) + +_CHALLENGE = _descriptor.Descriptor( + name="Challenge", + full_name="spotify.login5.v3.Challenge", + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name="hashcash", + full_name="spotify.login5.v3.Challenge.hashcash", + index=0, + number=1, + type=11, + cpp_type=10, + label=1, + has_default_value=False, + default_value=None, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="code", + full_name="spotify.login5.v3.Challenge.code", + index=1, + number=2, + type=11, + cpp_type=10, + label=1, + has_default_value=False, + default_value=None, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax="proto3", + extension_ranges=[], + oneofs=[], + serialized_start=374, + serialized_end=511, +) + +_CHALLENGESOLUTIONS = _descriptor.Descriptor( + name="ChallengeSolutions", + full_name="spotify.login5.v3.ChallengeSolutions", + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name="solutions", + full_name="spotify.login5.v3.ChallengeSolutions.solutions", + index=0, + number=1, + type=11, + cpp_type=10, + label=3, + has_default_value=False, + default_value=[], + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax="proto3", + extension_ranges=[], + oneofs=[], + serialized_start=513, + serialized_end=590, +) + +_CHALLENGESOLUTION = _descriptor.Descriptor( + name="ChallengeSolution", + full_name="spotify.login5.v3.ChallengeSolution", + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name="hashcash", + full_name="spotify.login5.v3.ChallengeSolution.hashcash", + index=0, + number=1, + type=11, + cpp_type=10, + label=1, + has_default_value=False, + default_value=None, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="code", + full_name="spotify.login5.v3.ChallengeSolution.code", + index=1, + number=2, + type=11, + cpp_type=10, + label=1, + has_default_value=False, + default_value=None, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax="proto3", + extension_ranges=[], + oneofs=[], + serialized_start=593, + serialized_end=736, +) + +_LOGINREQUEST = _descriptor.Descriptor( + name="LoginRequest", + full_name="spotify.login5.v3.LoginRequest", + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name="client_info", + full_name="spotify.login5.v3.LoginRequest.client_info", + index=0, + number=1, + type=11, + cpp_type=10, + label=1, + has_default_value=False, + default_value=None, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="login_context", + full_name="spotify.login5.v3.LoginRequest.login_context", + index=1, + number=2, + type=12, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"", + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="challenge_solutions", + full_name="spotify.login5.v3.LoginRequest.challenge_solutions", + index=2, + number=3, + type=11, + cpp_type=10, + label=1, + has_default_value=False, + default_value=None, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="stored_credential", + full_name="spotify.login5.v3.LoginRequest.stored_credential", + index=3, + number=100, + type=11, + cpp_type=10, + label=1, + has_default_value=False, + default_value=None, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="password", + full_name="spotify.login5.v3.LoginRequest.password", + index=4, + number=101, + type=11, + cpp_type=10, + label=1, + has_default_value=False, + default_value=None, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="facebook_access_token", + full_name="spotify.login5.v3.LoginRequest.facebook_access_token", + index=5, + number=102, + type=11, + cpp_type=10, + label=1, + has_default_value=False, + default_value=None, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="phone_number", + full_name="spotify.login5.v3.LoginRequest.phone_number", + index=6, + number=103, + type=11, + cpp_type=10, + label=1, + has_default_value=False, + default_value=None, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="one_time_token", + full_name="spotify.login5.v3.LoginRequest.one_time_token", + index=7, + number=104, + type=11, + cpp_type=10, + label=1, + has_default_value=False, + default_value=None, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="parent_child_credential", + full_name="spotify.login5.v3.LoginRequest.parent_child_credential", + index=8, + number=105, + type=11, + cpp_type=10, + label=1, + has_default_value=False, + default_value=None, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="apple_sign_in_credential", + full_name="spotify.login5.v3.LoginRequest.apple_sign_in_credential", + index=9, + number=106, + type=11, + cpp_type=10, + label=1, + has_default_value=False, + default_value=None, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax="proto3", + extension_ranges=[], + oneofs=[], + serialized_start=739, + serialized_end=1424, +) + +_LOGINOK = _descriptor.Descriptor( + name="LoginOk", + full_name="spotify.login5.v3.LoginOk", + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name="username", + full_name="spotify.login5.v3.LoginOk.username", + index=0, + number=1, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"".decode("utf-8"), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="access_token", + full_name="spotify.login5.v3.LoginOk.access_token", + index=1, + number=2, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"".decode("utf-8"), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="stored_credential", + full_name="spotify.login5.v3.LoginOk.stored_credential", + index=2, + number=3, + type=12, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"", + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="access_token_expires_in", + full_name="spotify.login5.v3.LoginOk.access_token_expires_in", + index=3, + number=4, + type=5, + cpp_type=1, + label=1, + has_default_value=False, + default_value=0, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax="proto3", + extension_ranges=[], + oneofs=[], + serialized_start=1426, + serialized_end=1535, +) + +_LOGINRESPONSE = _descriptor.Descriptor( + name="LoginResponse", + full_name="spotify.login5.v3.LoginResponse", + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name="ok", + full_name="spotify.login5.v3.LoginResponse.ok", + index=0, + number=1, + type=11, + cpp_type=10, + label=1, + has_default_value=False, + default_value=None, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="error", + full_name="spotify.login5.v3.LoginResponse.error", + index=1, + number=2, + type=14, + cpp_type=8, + label=1, + has_default_value=False, + default_value=0, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="challenges", + full_name="spotify.login5.v3.LoginResponse.challenges", + index=2, + number=3, + type=11, + cpp_type=10, + label=1, + has_default_value=False, + default_value=None, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="warnings", + full_name="spotify.login5.v3.LoginResponse.warnings", + index=3, + number=4, + type=14, + cpp_type=8, + label=3, + has_default_value=False, + default_value=[], + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="login_context", + full_name="spotify.login5.v3.LoginResponse.login_context", + index=4, + number=5, + type=12, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"", + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="identifier_token", + full_name="spotify.login5.v3.LoginResponse.identifier_token", + index=5, + number=6, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"".decode("utf-8"), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="user_info", + full_name="spotify.login5.v3.LoginResponse.user_info", + index=6, + number=7, + type=11, + cpp_type=10, + label=1, + has_default_value=False, + default_value=None, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + ], + extensions=[], + nested_types=[], + enum_types=[ + _LOGINRESPONSE_WARNINGS, + ], + serialized_options=None, + is_extendable=False, + syntax="proto3", + extension_ranges=[], + oneofs=[], + serialized_start=1538, + serialized_end=1914, +) + +_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[ + "code"].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["hashcash"].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[ + "client_info"].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["stored_credential"].message_type = ( + spotify_dot_login5_dot_v3_dot_credentials_dot_credentials__pb2. + _STOREDCREDENTIAL) +_LOGINREQUEST.fields_by_name["password"].message_type = ( + spotify_dot_login5_dot_v3_dot_credentials_dot_credentials__pb2._PASSWORD) +_LOGINREQUEST.fields_by_name["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 +) +_LOGINREQUEST.fields_by_name["one_time_token"].message_type = ( + 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. + _PARENTCHILDCREDENTIAL) +_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["error"].enum_type = _LOGINERROR +_LOGINRESPONSE.fields_by_name["challenges"].message_type = _CHALLENGES +_LOGINRESPONSE.fields_by_name["warnings"].enum_type = _LOGINRESPONSE_WARNINGS +_LOGINRESPONSE.fields_by_name[ + "user_info"].message_type = spotify_dot_login5_dot_v3_dot_user__info__pb2._USERINFO +_LOGINRESPONSE_WARNINGS.containing_type = _LOGINRESPONSE +DESCRIPTOR.message_types_by_name["Challenges"] = _CHALLENGES +DESCRIPTOR.message_types_by_name["Challenge"] = _CHALLENGE +DESCRIPTOR.message_types_by_name["ChallengeSolutions"] = _CHALLENGESOLUTIONS +DESCRIPTOR.message_types_by_name["ChallengeSolution"] = _CHALLENGESOLUTION +DESCRIPTOR.message_types_by_name["LoginRequest"] = _LOGINREQUEST +DESCRIPTOR.message_types_by_name["LoginOk"] = _LOGINOK +DESCRIPTOR.message_types_by_name["LoginResponse"] = _LOGINRESPONSE +DESCRIPTOR.enum_types_by_name["LoginError"] = _LOGINERROR +_sym_db.RegisterFileDescriptor(DESCRIPTOR) + +Challenges = _reflection.GeneratedProtocolMessageType( + "Challenges", + (_message.Message, ), + { + "DESCRIPTOR": _CHALLENGES, + "__module__": "spotify.login5.v3.login5_pb2" + # @@protoc_insertion_point(class_scope:spotify.login5.v3.Challenges) + }, +) +_sym_db.RegisterMessage(Challenges) + +Challenge = _reflection.GeneratedProtocolMessageType( + "Challenge", + (_message.Message, ), + { + "DESCRIPTOR": _CHALLENGE, + "__module__": "spotify.login5.v3.login5_pb2" + # @@protoc_insertion_point(class_scope:spotify.login5.v3.Challenge) + }, +) +_sym_db.RegisterMessage(Challenge) + +ChallengeSolutions = _reflection.GeneratedProtocolMessageType( + "ChallengeSolutions", + (_message.Message, ), + { + "DESCRIPTOR": _CHALLENGESOLUTIONS, + "__module__": "spotify.login5.v3.login5_pb2" + # @@protoc_insertion_point(class_scope:spotify.login5.v3.ChallengeSolutions) + }, +) +_sym_db.RegisterMessage(ChallengeSolutions) + +ChallengeSolution = _reflection.GeneratedProtocolMessageType( + "ChallengeSolution", + (_message.Message, ), + { + "DESCRIPTOR": _CHALLENGESOLUTION, + "__module__": "spotify.login5.v3.login5_pb2" + # @@protoc_insertion_point(class_scope:spotify.login5.v3.ChallengeSolution) + }, +) +_sym_db.RegisterMessage(ChallengeSolution) + +LoginRequest = _reflection.GeneratedProtocolMessageType( + "LoginRequest", + (_message.Message, ), + { + "DESCRIPTOR": _LOGINREQUEST, + "__module__": "spotify.login5.v3.login5_pb2" + # @@protoc_insertion_point(class_scope:spotify.login5.v3.LoginRequest) + }, +) +_sym_db.RegisterMessage(LoginRequest) + +LoginOk = _reflection.GeneratedProtocolMessageType( + "LoginOk", + (_message.Message, ), + { + "DESCRIPTOR": _LOGINOK, + "__module__": "spotify.login5.v3.login5_pb2" + # @@protoc_insertion_point(class_scope:spotify.login5.v3.LoginOk) + }, +) +_sym_db.RegisterMessage(LoginOk) + +LoginResponse = _reflection.GeneratedProtocolMessageType( + "LoginResponse", + (_message.Message, ), + { + "DESCRIPTOR": _LOGINRESPONSE, + "__module__": "spotify.login5.v3.login5_pb2" + # @@protoc_insertion_point(class_scope:spotify.login5.v3.LoginResponse) + }, +) +_sym_db.RegisterMessage(LoginResponse) + +DESCRIPTOR._options = None +# @@protoc_insertion_point(module_scope) diff --git a/librespot/proto/spotify/login5/v3/UserInfo_pb2.py b/librespot/proto/spotify/login5/v3/UserInfo_pb2.py new file mode 100644 index 0000000..99f9235 --- /dev/null +++ b/librespot/proto/spotify/login5/v3/UserInfo_pb2.py @@ -0,0 +1,263 @@ +# -*- coding: utf-8 -*- +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: spotify/login5/v3/user_info.proto +"""Generated protocol buffer code.""" +from google.protobuf import descriptor as _descriptor +from google.protobuf import message as _message +from google.protobuf import reflection as _reflection +from google.protobuf import symbol_database as _symbol_database + +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + +DESCRIPTOR = _descriptor.FileDescriptor( + name="spotify/login5/v3/user_info.proto", + package="spotify.login5.v3", + syntax="proto3", + serialized_options=b"\n\024com.spotify.login5v3", + 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', +) + +_USERINFO_GENDER = _descriptor.EnumDescriptor( + name="Gender", + full_name="spotify.login5.v3.UserInfo.Gender", + filename=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + values=[ + _descriptor.EnumValueDescriptor( + name="UNKNOWN", + index=0, + number=0, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key, + ), + _descriptor.EnumValueDescriptor( + name="MALE", + index=1, + number=1, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key, + ), + _descriptor.EnumValueDescriptor( + name="FEMALE", + index=2, + number=2, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key, + ), + _descriptor.EnumValueDescriptor( + name="NEUTRAL", + index=3, + number=3, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key, + ), + ], + containing_type=None, + serialized_options=None, + serialized_start=280, + serialized_end=336, +) +_sym_db.RegisterEnumDescriptor(_USERINFO_GENDER) + +_USERINFO = _descriptor.Descriptor( + name="UserInfo", + full_name="spotify.login5.v3.UserInfo", + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name="name", + full_name="spotify.login5.v3.UserInfo.name", + index=0, + number=1, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"".decode("utf-8"), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="email", + full_name="spotify.login5.v3.UserInfo.email", + index=1, + number=2, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"".decode("utf-8"), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="email_verified", + full_name="spotify.login5.v3.UserInfo.email_verified", + index=2, + number=3, + type=8, + cpp_type=7, + label=1, + has_default_value=False, + default_value=False, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="birthdate", + full_name="spotify.login5.v3.UserInfo.birthdate", + index=3, + number=4, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"".decode("utf-8"), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="gender", + full_name="spotify.login5.v3.UserInfo.gender", + index=4, + number=5, + type=14, + cpp_type=8, + label=1, + has_default_value=False, + default_value=0, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="phone_number", + full_name="spotify.login5.v3.UserInfo.phone_number", + index=5, + number=6, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"".decode("utf-8"), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="phone_number_verified", + full_name="spotify.login5.v3.UserInfo.phone_number_verified", + index=6, + number=7, + type=8, + cpp_type=7, + label=1, + has_default_value=False, + default_value=False, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="email_already_registered", + full_name="spotify.login5.v3.UserInfo.email_already_registered", + index=7, + number=8, + type=8, + cpp_type=7, + label=1, + has_default_value=False, + default_value=False, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + ], + extensions=[], + nested_types=[], + enum_types=[ + _USERINFO_GENDER, + ], + serialized_options=None, + is_extendable=False, + syntax="proto3", + extension_ranges=[], + oneofs=[], + serialized_start=57, + serialized_end=336, +) + +_USERINFO.fields_by_name["gender"].enum_type = _USERINFO_GENDER +_USERINFO_GENDER.containing_type = _USERINFO +DESCRIPTOR.message_types_by_name["UserInfo"] = _USERINFO +_sym_db.RegisterFileDescriptor(DESCRIPTOR) + +UserInfo = _reflection.GeneratedProtocolMessageType( + "UserInfo", + (_message.Message, ), + { + "DESCRIPTOR": _USERINFO, + "__module__": "spotify.login5.v3.user_info_pb2" + # @@protoc_insertion_point(class_scope:spotify.login5.v3.UserInfo) + }, +) +_sym_db.RegisterMessage(UserInfo) + +DESCRIPTOR._options = None +# @@protoc_insertion_point(module_scope) diff --git a/librespot/proto/spotify/login5/v3/__init__.py b/librespot/proto/spotify/login5/v3/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/librespot/proto/spotify/login5/v3/__pycache__/ClientInfo_pb2.cpython-312.pyc b/librespot/proto/spotify/login5/v3/__pycache__/ClientInfo_pb2.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..4625346f1f3ac9ab83c78b9079136550345a5204 GIT binary patch literal 3160 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 literal 0 HcmV?d00001 diff --git a/librespot/proto/spotify/login5/v3/challenges/Code_pb2.py b/librespot/proto/spotify/login5/v3/challenges/Code_pb2.py new file mode 100644 index 0000000..03dca14 --- /dev/null +++ b/librespot/proto/spotify/login5/v3/challenges/Code_pb2.py @@ -0,0 +1,224 @@ +# -*- coding: utf-8 -*- +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: spotify/login5/v3/challenges/code.proto +"""Generated protocol buffer code.""" +from google.protobuf import descriptor as _descriptor +from google.protobuf import message as _message +from google.protobuf import reflection as _reflection +from google.protobuf import symbol_database as _symbol_database + +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + +DESCRIPTOR = _descriptor.FileDescriptor( + name="spotify/login5/v3/challenges/code.proto", + package="spotify.login5.v3.challenges", + syntax="proto3", + serialized_options=b"\n\024com.spotify.login5v3", + 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', +) + +_CODECHALLENGE_METHOD = _descriptor.EnumDescriptor( + name="Method", + full_name="spotify.login5.v3.challenges.CodeChallenge.Method", + filename=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + values=[ + _descriptor.EnumValueDescriptor( + name="UNKNOWN", + index=0, + number=0, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key, + ), + _descriptor.EnumValueDescriptor( + name="SMS", + index=1, + number=1, + serialized_options=None, + type=None, + create_key=_descriptor._internal_create_key, + ), + ], + containing_type=None, + serialized_options=None, + serialized_start=232, + serialized_end=262, +) +_sym_db.RegisterEnumDescriptor(_CODECHALLENGE_METHOD) + +_CODECHALLENGE = _descriptor.Descriptor( + name="CodeChallenge", + full_name="spotify.login5.v3.challenges.CodeChallenge", + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name="method", + full_name="spotify.login5.v3.challenges.CodeChallenge.method", + index=0, + number=1, + type=14, + cpp_type=8, + label=1, + has_default_value=False, + default_value=0, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="code_length", + full_name="spotify.login5.v3.challenges.CodeChallenge.code_length", + index=1, + number=2, + type=5, + cpp_type=1, + label=1, + has_default_value=False, + default_value=0, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="expires_in", + full_name="spotify.login5.v3.challenges.CodeChallenge.expires_in", + index=2, + number=3, + type=5, + cpp_type=1, + label=1, + has_default_value=False, + default_value=0, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="canonical_phone_number", + full_name= + "spotify.login5.v3.challenges.CodeChallenge.canonical_phone_number", + index=3, + number=4, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"".decode("utf-8"), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + ], + extensions=[], + nested_types=[], + enum_types=[ + _CODECHALLENGE_METHOD, + ], + serialized_options=None, + is_extendable=False, + syntax="proto3", + extension_ranges=[], + oneofs=[], + serialized_start=74, + serialized_end=262, +) + +_CODESOLUTION = _descriptor.Descriptor( + name="CodeSolution", + full_name="spotify.login5.v3.challenges.CodeSolution", + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name="code", + full_name="spotify.login5.v3.challenges.CodeSolution.code", + index=0, + number=1, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"".decode("utf-8"), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax="proto3", + extension_ranges=[], + oneofs=[], + serialized_start=264, + serialized_end=292, +) + +_CODECHALLENGE.fields_by_name["method"].enum_type = _CODECHALLENGE_METHOD +_CODECHALLENGE_METHOD.containing_type = _CODECHALLENGE +DESCRIPTOR.message_types_by_name["CodeChallenge"] = _CODECHALLENGE +DESCRIPTOR.message_types_by_name["CodeSolution"] = _CODESOLUTION +_sym_db.RegisterFileDescriptor(DESCRIPTOR) + +CodeChallenge = _reflection.GeneratedProtocolMessageType( + "CodeChallenge", + (_message.Message, ), + { + "DESCRIPTOR": _CODECHALLENGE, + "__module__": "spotify.login5.v3.challenges.code_pb2" + # @@protoc_insertion_point(class_scope:spotify.login5.v3.challenges.CodeChallenge) + }, +) +_sym_db.RegisterMessage(CodeChallenge) + +CodeSolution = _reflection.GeneratedProtocolMessageType( + "CodeSolution", + (_message.Message, ), + { + "DESCRIPTOR": _CODESOLUTION, + "__module__": "spotify.login5.v3.challenges.code_pb2" + # @@protoc_insertion_point(class_scope:spotify.login5.v3.challenges.CodeSolution) + }, +) +_sym_db.RegisterMessage(CodeSolution) + +DESCRIPTOR._options = None +# @@protoc_insertion_point(module_scope) diff --git a/librespot/proto/spotify/login5/v3/challenges/Hashcash_pb2.py b/librespot/proto/spotify/login5/v3/challenges/Hashcash_pb2.py new file mode 100644 index 0000000..d12b2a5 --- /dev/null +++ b/librespot/proto/spotify/login5/v3/challenges/Hashcash_pb2.py @@ -0,0 +1,176 @@ +# -*- coding: utf-8 -*- +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: spotify/login5/v3/challenges/hashcash.proto +"""Generated protocol buffer code.""" +from google.protobuf import descriptor as _descriptor +from google.protobuf import \ + duration_pb2 as google_dot_protobuf_dot_duration__pb2 +from google.protobuf import message as _message +from google.protobuf import reflection as _reflection +from google.protobuf import symbol_database as _symbol_database + +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + +DESCRIPTOR = _descriptor.FileDescriptor( + name="spotify/login5/v3/challenges/hashcash.proto", + package="spotify.login5.v3.challenges", + syntax="proto3", + serialized_options=b"\n\024com.spotify.login5v3", + 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', + dependencies=[ + google_dot_protobuf_dot_duration__pb2.DESCRIPTOR, + ], +) + +_HASHCASHCHALLENGE = _descriptor.Descriptor( + name="HashcashChallenge", + full_name="spotify.login5.v3.challenges.HashcashChallenge", + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name="prefix", + full_name="spotify.login5.v3.challenges.HashcashChallenge.prefix", + index=0, + number=1, + type=12, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"", + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="length", + full_name="spotify.login5.v3.challenges.HashcashChallenge.length", + index=1, + number=2, + type=5, + cpp_type=1, + label=1, + has_default_value=False, + default_value=0, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax="proto3", + extension_ranges=[], + oneofs=[], + serialized_start=109, + serialized_end=160, +) + +_HASHCASHSOLUTION = _descriptor.Descriptor( + name="HashcashSolution", + full_name="spotify.login5.v3.challenges.HashcashSolution", + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name="suffix", + full_name="spotify.login5.v3.challenges.HashcashSolution.suffix", + index=0, + number=1, + type=12, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"", + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="duration", + full_name="spotify.login5.v3.challenges.HashcashSolution.duration", + index=1, + number=2, + type=11, + cpp_type=10, + label=1, + has_default_value=False, + default_value=None, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax="proto3", + extension_ranges=[], + oneofs=[], + serialized_start=162, + serialized_end=241, +) + +_HASHCASHSOLUTION.fields_by_name[ + "duration"].message_type = google_dot_protobuf_dot_duration__pb2._DURATION +DESCRIPTOR.message_types_by_name["HashcashChallenge"] = _HASHCASHCHALLENGE +DESCRIPTOR.message_types_by_name["HashcashSolution"] = _HASHCASHSOLUTION +_sym_db.RegisterFileDescriptor(DESCRIPTOR) + +HashcashChallenge = _reflection.GeneratedProtocolMessageType( + "HashcashChallenge", + (_message.Message, ), + { + "DESCRIPTOR": _HASHCASHCHALLENGE, + "__module__": "spotify.login5.v3.challenges.hashcash_pb2" + # @@protoc_insertion_point(class_scope:spotify.login5.v3.challenges.HashcashChallenge) + }, +) +_sym_db.RegisterMessage(HashcashChallenge) + +HashcashSolution = _reflection.GeneratedProtocolMessageType( + "HashcashSolution", + (_message.Message, ), + { + "DESCRIPTOR": _HASHCASHSOLUTION, + "__module__": "spotify.login5.v3.challenges.hashcash_pb2" + # @@protoc_insertion_point(class_scope:spotify.login5.v3.challenges.HashcashSolution) + }, +) +_sym_db.RegisterMessage(HashcashSolution) + +DESCRIPTOR._options = None +# @@protoc_insertion_point(module_scope) diff --git a/librespot/proto/spotify/login5/v3/challenges/__init__.py b/librespot/proto/spotify/login5/v3/challenges/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/librespot/proto/spotify/login5/v3/challenges/__pycache__/Code_pb2.cpython-312.pyc b/librespot/proto/spotify/login5/v3/challenges/__pycache__/Code_pb2.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..767ff09aa3ee6d3fe562c826e4d6ebf497c3e3d8 GIT binary patch literal 6119 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 literal 0 HcmV?d00001 diff --git a/librespot/proto/spotify/login5/v3/credentials/Credentials_pb2.py b/librespot/proto/spotify/login5/v3/credentials/Credentials_pb2.py new file mode 100644 index 0000000..f141f66 --- /dev/null +++ b/librespot/proto/spotify/login5/v3/credentials/Credentials_pb2.py @@ -0,0 +1,483 @@ +# -*- coding: utf-8 -*- +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: spotify/login5/v3/credentials/credentials.proto +"""Generated protocol buffer code.""" +from google.protobuf import descriptor as _descriptor +from google.protobuf import message as _message +from google.protobuf import reflection as _reflection +from google.protobuf import symbol_database as _symbol_database + +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + +DESCRIPTOR = _descriptor.FileDescriptor( + name="spotify/login5/v3/credentials/credentials.proto", + package="spotify.login5.v3.credentials", + syntax="proto3", + serialized_options=b"\n\024com.spotify.login5v3", + 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', +) + +_STOREDCREDENTIAL = _descriptor.Descriptor( + name="StoredCredential", + full_name="spotify.login5.v3.credentials.StoredCredential", + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name="username", + full_name="spotify.login5.v3.credentials.StoredCredential.username", + index=0, + number=1, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"".decode("utf-8"), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="data", + full_name="spotify.login5.v3.credentials.StoredCredential.data", + index=1, + number=2, + type=12, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"", + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax="proto3", + extension_ranges=[], + oneofs=[], + serialized_start=82, + serialized_end=132, +) + +_PASSWORD = _descriptor.Descriptor( + name="Password", + full_name="spotify.login5.v3.credentials.Password", + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name="id", + full_name="spotify.login5.v3.credentials.Password.id", + index=0, + number=1, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"".decode("utf-8"), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="password", + full_name="spotify.login5.v3.credentials.Password.password", + index=1, + number=2, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"".decode("utf-8"), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="padding", + full_name="spotify.login5.v3.credentials.Password.padding", + index=2, + number=3, + type=12, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"", + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax="proto3", + extension_ranges=[], + oneofs=[], + serialized_start=134, + serialized_end=191, +) + +_FACEBOOKACCESSTOKEN = _descriptor.Descriptor( + name="FacebookAccessToken", + full_name="spotify.login5.v3.credentials.FacebookAccessToken", + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name="fb_uid", + full_name= + "spotify.login5.v3.credentials.FacebookAccessToken.fb_uid", + index=0, + number=1, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"".decode("utf-8"), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="access_token", + full_name= + "spotify.login5.v3.credentials.FacebookAccessToken.access_token", + index=1, + number=2, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"".decode("utf-8"), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax="proto3", + extension_ranges=[], + oneofs=[], + serialized_start=193, + serialized_end=252, +) + +_ONETIMETOKEN = _descriptor.Descriptor( + name="OneTimeToken", + full_name="spotify.login5.v3.credentials.OneTimeToken", + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name="token", + full_name="spotify.login5.v3.credentials.OneTimeToken.token", + index=0, + number=1, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"".decode("utf-8"), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax="proto3", + extension_ranges=[], + oneofs=[], + serialized_start=254, + serialized_end=283, +) + +_PARENTCHILDCREDENTIAL = _descriptor.Descriptor( + name="ParentChildCredential", + full_name="spotify.login5.v3.credentials.ParentChildCredential", + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name="child_id", + full_name= + "spotify.login5.v3.credentials.ParentChildCredential.child_id", + index=0, + number=1, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"".decode("utf-8"), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="parent_stored_credential", + full_name= + "spotify.login5.v3.credentials.ParentChildCredential.parent_stored_credential", + index=1, + number=2, + type=11, + cpp_type=10, + label=1, + has_default_value=False, + default_value=None, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax="proto3", + extension_ranges=[], + oneofs=[], + serialized_start=285, + serialized_end=409, +) + +_APPLESIGNINCREDENTIAL = _descriptor.Descriptor( + name="AppleSignInCredential", + full_name="spotify.login5.v3.credentials.AppleSignInCredential", + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name="auth_code", + full_name= + "spotify.login5.v3.credentials.AppleSignInCredential.auth_code", + index=0, + number=1, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"".decode("utf-8"), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="redirect_uri", + full_name= + "spotify.login5.v3.credentials.AppleSignInCredential.redirect_uri", + index=1, + number=2, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"".decode("utf-8"), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="bundle_id", + full_name= + "spotify.login5.v3.credentials.AppleSignInCredential.bundle_id", + index=2, + number=3, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"".decode("utf-8"), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax="proto3", + extension_ranges=[], + oneofs=[], + serialized_start=411, + serialized_end=494, +) + +_PARENTCHILDCREDENTIAL.fields_by_name[ + "parent_stored_credential"].message_type = _STOREDCREDENTIAL +DESCRIPTOR.message_types_by_name["StoredCredential"] = _STOREDCREDENTIAL +DESCRIPTOR.message_types_by_name["Password"] = _PASSWORD +DESCRIPTOR.message_types_by_name["FacebookAccessToken"] = _FACEBOOKACCESSTOKEN +DESCRIPTOR.message_types_by_name["OneTimeToken"] = _ONETIMETOKEN +DESCRIPTOR.message_types_by_name[ + "ParentChildCredential"] = _PARENTCHILDCREDENTIAL +DESCRIPTOR.message_types_by_name[ + "AppleSignInCredential"] = _APPLESIGNINCREDENTIAL +_sym_db.RegisterFileDescriptor(DESCRIPTOR) + +StoredCredential = _reflection.GeneratedProtocolMessageType( + "StoredCredential", + (_message.Message, ), + { + "DESCRIPTOR": _STOREDCREDENTIAL, + "__module__": "spotify.login5.v3.credentials.credentials_pb2" + # @@protoc_insertion_point(class_scope:spotify.login5.v3.credentials.StoredCredential) + }, +) +_sym_db.RegisterMessage(StoredCredential) + +Password = _reflection.GeneratedProtocolMessageType( + "Password", + (_message.Message, ), + { + "DESCRIPTOR": _PASSWORD, + "__module__": "spotify.login5.v3.credentials.credentials_pb2" + # @@protoc_insertion_point(class_scope:spotify.login5.v3.credentials.Password) + }, +) +_sym_db.RegisterMessage(Password) + +FacebookAccessToken = _reflection.GeneratedProtocolMessageType( + "FacebookAccessToken", + (_message.Message, ), + { + "DESCRIPTOR": _FACEBOOKACCESSTOKEN, + "__module__": "spotify.login5.v3.credentials.credentials_pb2" + # @@protoc_insertion_point(class_scope:spotify.login5.v3.credentials.FacebookAccessToken) + }, +) +_sym_db.RegisterMessage(FacebookAccessToken) + +OneTimeToken = _reflection.GeneratedProtocolMessageType( + "OneTimeToken", + (_message.Message, ), + { + "DESCRIPTOR": _ONETIMETOKEN, + "__module__": "spotify.login5.v3.credentials.credentials_pb2" + # @@protoc_insertion_point(class_scope:spotify.login5.v3.credentials.OneTimeToken) + }, +) +_sym_db.RegisterMessage(OneTimeToken) + +ParentChildCredential = _reflection.GeneratedProtocolMessageType( + "ParentChildCredential", + (_message.Message, ), + { + "DESCRIPTOR": _PARENTCHILDCREDENTIAL, + "__module__": "spotify.login5.v3.credentials.credentials_pb2" + # @@protoc_insertion_point(class_scope:spotify.login5.v3.credentials.ParentChildCredential) + }, +) +_sym_db.RegisterMessage(ParentChildCredential) + +AppleSignInCredential = _reflection.GeneratedProtocolMessageType( + "AppleSignInCredential", + (_message.Message, ), + { + "DESCRIPTOR": _APPLESIGNINCREDENTIAL, + "__module__": "spotify.login5.v3.credentials.credentials_pb2" + # @@protoc_insertion_point(class_scope:spotify.login5.v3.credentials.AppleSignInCredential) + }, +) +_sym_db.RegisterMessage(AppleSignInCredential) + +DESCRIPTOR._options = None +# @@protoc_insertion_point(module_scope) diff --git a/librespot/proto/spotify/login5/v3/credentials/__init__.py b/librespot/proto/spotify/login5/v3/credentials/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/librespot/proto/spotify/login5/v3/credentials/__pycache__/Credentials_pb2.cpython-312.pyc b/librespot/proto/spotify/login5/v3/credentials/__pycache__/Credentials_pb2.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..281e5ebb255a77f6d756c843ac1cf47566d30f21 GIT binary patch literal 12055 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 literal 0 HcmV?d00001 diff --git a/librespot/proto/spotify/login5/v3/identifiers/Identifiers.py b/librespot/proto/spotify/login5/v3/identifiers/Identifiers.py new file mode 100644 index 0000000..42457c5 --- /dev/null +++ b/librespot/proto/spotify/login5/v3/identifiers/Identifiers.py @@ -0,0 +1,119 @@ +# -*- coding: utf-8 -*- +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: spotify/login5/v3/identifiers/identifiers.proto +"""Generated protocol buffer code.""" +from google.protobuf import descriptor as _descriptor +from google.protobuf import message as _message +from google.protobuf import reflection as _reflection +from google.protobuf import symbol_database as _symbol_database + +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + +DESCRIPTOR = _descriptor.FileDescriptor( + name="spotify/login5/v3/identifiers/identifiers.proto", + package="spotify.login5.v3.identifiers", + syntax="proto3", + serialized_options=b"\n\024com.spotify.login5v3", + 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', +) + +_PHONENUMBER = _descriptor.Descriptor( + name="PhoneNumber", + full_name="spotify.login5.v3.identifiers.PhoneNumber", + filename=None, + file=DESCRIPTOR, + containing_type=None, + create_key=_descriptor._internal_create_key, + fields=[ + _descriptor.FieldDescriptor( + name="number", + full_name="spotify.login5.v3.identifiers.PhoneNumber.number", + index=0, + number=1, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"".decode("utf-8"), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="iso_country_code", + full_name= + "spotify.login5.v3.identifiers.PhoneNumber.iso_country_code", + index=1, + number=2, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"".decode("utf-8"), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + _descriptor.FieldDescriptor( + name="country_calling_code", + full_name= + "spotify.login5.v3.identifiers.PhoneNumber.country_calling_code", + index=2, + number=3, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=b"".decode("utf-8"), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + create_key=_descriptor._internal_create_key, + ), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax="proto3", + extension_ranges=[], + oneofs=[], + serialized_start=82, + serialized_end=167, +) + +DESCRIPTOR.message_types_by_name["PhoneNumber"] = _PHONENUMBER +_sym_db.RegisterFileDescriptor(DESCRIPTOR) + +PhoneNumber = _reflection.GeneratedProtocolMessageType( + "PhoneNumber", + (_message.Message, ), + { + "DESCRIPTOR": _PHONENUMBER, + "__module__": "spotify.login5.v3.identifiers.identifiers_pb2" + # @@protoc_insertion_point(class_scope:spotify.login5.v3.identifiers.PhoneNumber) + }, +) +_sym_db.RegisterMessage(PhoneNumber) + +DESCRIPTOR._options = None +# @@protoc_insertion_point(module_scope) diff --git a/librespot/proto/spotify/login5/v3/identifiers/__init__.py b/librespot/proto/spotify/login5/v3/identifiers/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/librespot/proto/spotify/login5/v3/identifiers/__pycache__/Identifiers.cpython-312.pyc b/librespot/proto/spotify/login5/v3/identifiers/__pycache__/Identifiers.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..5294ab07554a924afd5978247029880ce747de42 GIT binary patch literal 3802 zcmdT`&2JmW6`$odm*kS7D3YSSXi1hVC*s;xY$vXf0IBWRZ7nN`-L%YMyW|Y%l~=pO zE+v@kMMw9NOAbwe0?jQb-2NRs^b#g6s4Nh`K~K7ka4iCb2J9t z4Pk#x$n*39ST54nKaxI_s#yj%y0bE@htWt=mqB5Powbo|h?p|08u7xSJEw=9(MVG) zyz}ZvAEJiDvh)pl>5qYjLEly_z%FNp{?W(^qh06(Q?%)!uQRcBxx4TVvzVi|87;RQ zyKUEPvs~M2G?-Ja+muy~aQ2$y$&|Tu$7r=}2ejxeb6vg3(BZI#$?9#xwm?g}o!y#k zYE*CQHQi-h)os~rqtQ`KyJ=YG)%^|Cpv(f3!5nuSSH%9^xxs>pzo4?eQ5jp{MZ~NP zHxFsaxw^eud3OH(hWj^k{jd9GzklDwJ91*{u5Gc+z1urY9WOQJZ`GU_oQXHiz>7EbOjE<)-L+?r@VO(e zjPdqj4Z~!(XwwTJ^wM=3@-Zyr)$X*Ilf<1OaJwdTy}==M&%E>w75`YhuwhYl{|MWv z7s9|tafGpYt0ngF!lqthrZ;g{cQwiy`kvX=_H}cQUGq}U=ucrC>4x{(jrG^P`7mj?8oS?SmJ3JerH`TJ)@@*wz|FsN#obFU&+GZ}I0|6M7uH7i&6f}RqS`vb zmf*?999%DHF&Cb=pbB+zOxyKRL*7)cnash@2rqNIQgd{x$>1KL^6iG}WyY$?ZR<|^ zXd4$OV`gU2qff!uUH^U(V~<*E)y}O2Jo(Di_kOy4W9#;?WW26W&w@L5nK~c0>k#?z-JB=iZ-}uCyZ)B8?`A1zc{>%_FSv-qF4Mf zg3Z9C(VC}RgA%`T9NEihhSg?{rJLI5sX1pboIExyeGRLB%n+drJA#+gwyxjWyt;Yk z=G#}dy{Yk9bhTPXyhbm-&6)<>mh;@^v&Wr!YtX1~`c3#YybdoqP#gubNe^QTtZ*EI zCgGd|zcUBo+ux~o?OmqUJJ8T9y}jqE&~xj$sk(P{hp8>2bzj|Q*1oHD2QA#FsjW^M z+Tcdz>^apn+H8H$mt55}Y7WCIS4D^Zf&P1A^dC@Zb-s;V_HX-5=Q?DDkKX+^Tr3Yt zlJq1-q?ND8`LBp7za?=%-eDsnx^yrNiVahl$C< z!fS`=Qa`Qs(kc&;a3l1ubW8~x$UH|fD-V9#PoM0iPkuu-rA*+Xr7dp`2wOc$ZhnfhdbiCIP|m zk29GvW;b~EV*8?Pz-8^g{QJJD&?w+#nQwhek=)TF7cHWDT~G z20@cPL5HfdaArpb4>j#TdsneqX7dGDayZknILZ=j92&Hm9caUjA>!|dOHwQ7mOy({ k!6Gyk@|+a8JkPZMjMfeB+Zs1!7~T>gY=l=|2x0nxz9OeWz5oCK literal 0 HcmV?d00001 diff --git a/librespot/proto_ext/__init__.py b/librespot/proto_ext/__init__.py new file mode 100644 index 0000000..854e597 --- /dev/null +++ b/librespot/proto_ext/__init__.py @@ -0,0 +1 @@ +"""Protobuf helpers for Spotify extended metadata.""" diff --git a/librespot/proto_ext/__pycache__/__init__.cpython-312.pyc b/librespot/proto_ext/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..3783c0bd0e94b398baf83c253239037790bea01d GIT binary patch literal 225 zcmXwzF$w}P6hsphU4*?uS{toI5V25e5yVCUpI!4;gX<&@#=1K(Fl8W{km%+*?r_wTG2h24Z%Q9uyS}P~B zis9K|AyBXrxe)i87pS$pN8p%bdwYEiWqK>lJ)(<$Qt z1FOtdxrtPZvsM{c#-nPDY6jWXbY>Cusm&^uW>k`*i|8e*YS`NLUQ!q+qvdvdQbdWM zk&p|Dpu`;<%NS-^)wO-qhFoi^sg|v13LZTI z98G9AlIER2!4&WA9yAx7!CqcZ1O{ivlAYF`ub%7%oWo)D6Cibmk)mdEa)-T;zVAbC zKpynK-81M-d@tisH^dTE`SWiuNMEs7G>!YjQ$ktKRB-mXTlN)`BpyCEd*eTqcp1YKCptw`y;v*1yov`n_&-$!aX`F$qEW%;z}+~$P%_GH z+rnD?7~WNDitfurpO}oR&iPiPV6;1Id>AthUQXwhHdfX)vl~_%rv2ZNo@|1XGek1k zjn&kHm3(S*C7W4GZKPInCtrZ+CAF^IkmOClD)U`Abs*XxBkhk7l@1I zgkKJFY@~B**-S32-Gcp?9(DYLP@_bM6W%e5oz7FicAEV3ae}0~g{GGygFT4YOOqef z0H4`SXZTFQq*k$+Sy6S<#{&YSy}6Emxivh{3*>-Bal*P*H2IL)Es{+?k5D?xKscvP zBt>bCnHpb3M)?+*{oKvJqZ>t4x1d5tdh;$nBvxTLVP8@eny%E!%kEiYIW7C9QSAZ2 ztsP(i&s(`PSt8w+m~+BJH&obRVpRD#U^y{jx!t&6q!+Yo)wCh7#}AHyZ_qPn8~u?h zEfluEWEGb7ikv9BW)+~JN48Nd?2D7C;PO%sGsmZ_@Q+iMtnN91#j-(bI=gN1&kX-q zS%1Op)FVmKuLDS$c#5t)MemE>jZ+^AUOL1h$2ifzi6{82y8kyHk`@3DO<394q4u zW&DXUd92Jgl=)MHZmxx(`Otc(j(-Y9KcBA$nrN~fI7X8VH2F3D_WlvN^&E0Impxp6 zc!cszfArWt{@6d>e0!!o_1R)W9zK$%nllew\x12\x15\n\x11NEXT_BEST_EPISODE\x10?\x12\x13\n\x0f\x41UDIOBOOK_PRICE\x10@\x12\x18\n\x14\x45XPRESSIVE_PLAYLISTS\x10\x41\x12\x18\n\x14\x44YNAMIC_SHOW_EPISODE\x10\x42\x12\x08\n\x04LIVE\x10\x43\x12\x0f\n\x0bSKIP_PLAYED\x10\x44\x12\x1a\n\x16\x41\x44_BREAK_FREE_PODCASTS\x10\x45\x12\x10\n\x0c\x41SSOCIATIONS\x10\x46\x12\x17\n\x13PLAYLIST_EVALUATION\x10G\x12\x17\n\x13\x43\x41\x43HE_INVALIDATIONS\x10H\x12\x15\n\x11LIVESTREAM_ENTITY\x10I\x12\x18\n\x14SINGLE_TAP_REACTIONS\x10J\x12\x11\n\rUSER_COMMENTS\x10K\x12\x17\n\x13\x43LIENT_RESTRICTIONS\x10L\x12\x11\n\rPODCAST_GUEST\x10M\x12\x0f\n\x0bPLAYABILITY\x10N\x12\x0f\n\x0b\x43OVER_IMAGE\x10O\x12\x0f\n\x0bSHARE_TRAIT\x10P\x12\x14\n\x10INSTANCE_SHARING\x10Q\x12\x0f\n\x0b\x41RTIST_TOUR\x10R\x12\x13\n\x0f\x41UDIOBOOK_GENRE\x10S\x12\x0b\n\x07\x43ONCEPT\x10T\x12\x12\n\x0eORIGINAL_VIDEO\x10U\x12\x11\n\rSMART_SHUFFLE\x10V\x12\x0f\n\x0bLIVE_EVENTS\x10W\x12\x17\n\x13\x41UDIOBOOK_RELATIONS\x10X\x12\x15\n\x11HOME_POC_BASECARD\x10Y\x12\x19\n\x15\x41UDIOBOOK_SUPPLEMENTS\x10Z\x12\x17\n\x13PAID_PODCAST_BANNER\x10[\x12\r\n\tFEWER_ADS\x10\\\x12\x1c\n\x18WATCH_FEED_SHOW_EXPLORER\x10]\x12\x1b\n\x17TRACK_EXTRA_DESCRIPTORS\x10^\x12 \n\x1cTRACK_EXTRA_AUDIO_ATTRIBUTES\x10_\x12\x1a\n\x16TRACK_EXTENDED_CREDITS\x10`\x12\x10\n\x0cSIMPLE_TRAIT\x10\x61\x12\x16\n\x12\x41UDIO_ASSOCIATIONS\x10\x62\x12\x16\n\x12VIDEO_ASSOCIATIONS\x10\x63\x12\x12\n\x0ePLAYLIST_TUNER\x10\x64\x12\x1c\n\x18\x41RTIST_VIDEOS_ENTRYPOINT\x10\x65\x12\x14\n\x10\x41LBUM_PRERELEASE\x10\x66\x12\x18\n\x14\x43ONTENT_ALTERNATIVES\x10g\x12\x14\n\x10SNAPSHOT_SHARING\x10i\x12\x1a\n\x16\x44ISPLAY_SEGMENTS_COUNT\x10j\x12\x1c\n\x18PODCAST_FEATURED_EPISODE\x10k\x12\x1d\n\x19PODCAST_SPONSORED_CONTENT\x10l\x12\x1e\n\x1aPODCAST_EPISODE_TOPICS_LLM\x10m\x12\x1d\n\x19PODCAST_EPISODE_TOPICS_KG\x10n\x12\x1e\n\x1a\x45PISODE_RANKING_POPULARITY\x10o\x12\t\n\x05MERCH\x10p\x12\x15\n\x11\x43OMPANION_CONTENT\x10q\x12\x1e\n\x1aWATCH_FEED_ENTITY_EXPLORER\x10r\x12\x15\n\x11\x41NCHOR_CARD_TRAIT\x10s\x12 \n\x1c\x41UDIO_PREVIEW_PLAYBACK_TRAIT\x10t\x12\x1d\n\x19VIDEO_PREVIEW_STILL_TRAIT\x10u\x12\x16\n\x12PREVIEW_CARD_TRAIT\x10v\x12\x18\n\x14SHORTCUTS_CARD_TRAIT\x10w\x12 \n\x1cVIDEO_PREVIEW_PLAYBACK_TRAIT\x10x\x12\x14\n\x10\x43OURSE_SPECIFICS\x10y\x12\x0b\n\x07\x43ONCERT\x10z\x12\x14\n\x10\x43ONCERT_LOCATION\x10{\x12\x15\n\x11\x43ONCERT_MARKETING\x10|\x12\x16\n\x12\x43ONCERT_PERFORMERS\x10}\x12\x19\n\x15TRACK_PAIR_TRANSITION\x10~\x12\x16\n\x12\x43ONTENT_TYPE_TRAIT\x10\x7f\x12\x0f\n\nNAME_TRAIT\x10\x80\x01\x12\x12\n\rARTWORK_TRAIT\x10\x81\x01\x12\x17\n\x12RELEASE_DATE_TRAIT\x10\x82\x01\x12\x12\n\rCREDITS_TRAIT\x10\x83\x01\x12\x16\n\x11RELEASE_URI_TRAIT\x10\x84\x01\x12\x13\n\x0e\x45NTITY_CAPPING\x10\x85\x01\x12\x15\n\x10LESSON_SPECIFICS\x10\x86\x01\x12\x13\n\x0e\x43ONCERT_OFFERS\x10\x87\x01\x12\x14\n\x0fTRANSITION_MAPS\x10\x88\x01\x12\x18\n\x13\x41RTIST_HAS_CONCERTS\x10\x89\x01\x12\x0f\n\nPRERELEASE\x10\x8a\x01\x12\x1b\n\x16PLAYLIST_ATTRIBUTES_V2\x10\x8b\x01\x12\x17\n\x12LIST_ATTRIBUTES_V2\x10\x8c\x01\x12\x12\n\rLIST_METADATA\x10\x8d\x01\x12\x1e\n\x19LIST_TUNER_AUDIO_ANALYSIS\x10\x8e\x01\x12\x19\n\x14LIST_TUNER_CUEPOINTS\x10\x8f\x01\x12\x19\n\x14\x43ONTENT_RATING_TRAIT\x10\x90\x01\x12\x14\n\x0f\x43OPYRIGHT_TRAIT\x10\x91\x01\x12\x15\n\x10SUPPORTED_BADGES\x10\x92\x01\x12\x0b\n\x06\x42\x41\x44GES\x10\x93\x01\x12\x12\n\rPREVIEW_TRAIT\x10\x94\x01\x12\x1a\n\x15ROOTLISTABILITY_TRAIT\x10\x95\x01\x12\x13\n\x0eLOCAL_CONCERTS\x10\x96\x01\x12\x1a\n\x15RECOMMENDED_PLAYLISTS\x10\x97\x01\x12\x15\n\x10POPULAR_RELEASES\x10\x98\x01\x12\x15\n\x10RELATED_RELEASES\x10\x99\x01\x12\x17\n\x12SHARE_RESTRICTIONS\x10\x9a\x01\x12\x12\n\rCONCERT_OFFER\x10\x9b\x01\x12\x1b\n\x16\x43ONCERT_OFFER_PROVIDER\x10\x9c\x01\x12\x15\n\x10\x45NTITY_BOOKMARKS\x10\x9d\x01\x12\x12\n\rPRIVACY_TRAIT\x10\x9e\x01\x12\x1a\n\x15\x44UPLICATE_ITEMS_TRAIT\x10\x9f\x01\x12\x15\n\x10REORDERING_TRAIT\x10\xa0\x01\x12 \n\x1bPODCAST_RESUMPTION_SEGMENTS\x10\xa1\x01\x12\x1c\n\x17\x41RTIST_EXPRESSION_VIDEO\x10\xa2\x01\x12\x15\n\x10PRERELEASE_VIDEO\x10\xa3\x01\x12\x1b\n\x16GATED_ENTITY_RELATIONS\x10\xa4\x01\x12\x1d\n\x18RELATED_CREATORS_SECTION\x10\xa5\x01\x12 \n\x1b\x43REATORS_APPEARS_ON_SECTION\x10\xa6\x01\x12\x13\n\x0ePROMO_V1_TRAIT\x10\xa7\x01\x12\x1a\n\x15SPEECHLESS_SHARE_CARD\x10\xa8\x01\x12\x1a\n\x15TOP_PLAYABLES_SECTION\x10\xa9\x01\x12\x0e\n\tAUTO_LENS\x10\xaa\x01\x12\x13\n\x0ePROMO_V3_TRAIT\x10\xab\x01\x12\x19\n\x14TRACK_CONTENT_FILTER\x10\xac\x01\x12\x15\n\x10HIGHLIGHTABILITY\x10\xad\x01\x12\x1f\n\x1aLINK_CARD_WITH_IMAGE_TRAIT\x10\xae\x01\x12\x18\n\x13TRACK_CLOUD_SECTION\x10\xaf\x01\x12\x13\n\x0e\x45PISODE_TOPICS\x10\xb0\x01\x12\x14\n\x0fVIDEO_THUMBNAIL\x10\xb1\x01\x12\x13\n\x0eIDENTITY_TRAIT\x10\xb2\x01\x12\x1a\n\x15VISUAL_IDENTITY_TRAIT\x10\xb3\x01\x12\x1a\n\x15\x43ONTENT_TYPE_V2_TRAIT\x10\xb4\x01\x12\x1b\n\x16PREVIEW_PLAYBACK_TRAIT\x10\xb5\x01\x12!\n\x1c\x43ONSUMPTION_EXPERIENCE_TRAIT\x10\xb6\x01\x12\x1e\n\x19PUBLISHING_METADATA_TRAIT\x10\xb7\x01\x12\x1e\n\x19\x44\x45TAILED_EVALUATION_TRAIT\x10\xb8\x01\x12!\n\x1cON_PLATFORM_REPUTATION_TRAIT\x10\xb9\x01\x12\x15\n\x10\x43REDITS_V2_TRAIT\x10\xba\x01\x12 \n\x1bHIGHLIGHT_PLAYABILITY_TRAIT\x10\xbb\x01\x12\x16\n\x11SHOW_EPISODE_LIST\x10\xbc\x01\x12\x17\n\x12\x41VAILABLE_RELEASES\x10\xbd\x01\x12\x19\n\x14PLAYLIST_DESCRIPTORS\x10\xbe\x01\x12$\n\x1fLINK_CARD_WITH_ANIMATIONS_TRAIT\x10\xbf\x01\x12\n\n\x05RECAP\x10\xc0\x01\x12 \n\x1b\x41UDIOBOOK_COMPANION_CONTENT\x10\xc1\x01\x12\x1e\n\x19THREE_OH_THREE_PLAY_TRAIT\x10\xc2\x01\x12\x1e\n\x19\x41RTIST_WRAPPED_2024_VIDEO\x10\xc3\x01\x42\x41\n\"com.spotify.extendedmetadata.protoH\x02P\x01\xf8\x01\x01\xa2\x02\x13SPTExtendedMetadatab\x06proto3') + +_globals = globals() +_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) +_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'extension_kind_pb2', _globals) +if not _descriptor._USE_C_DESCRIPTORS: + _globals['DESCRIPTOR']._loaded_options = None + _globals['DESCRIPTOR']._serialized_options = b'\n\"com.spotify.extendedmetadata.protoH\002P\001\370\001\001\242\002\023SPTExtendedMetadata' + _globals['_EXTENSIONKIND']._serialized_start=51 + _globals['_EXTENSIONKIND']._serialized_end=4590 +# @@protoc_insertion_point(module_scope) diff --git a/librespot/structure.py b/librespot/structure.py new file mode 100644 index 0000000..9171ada --- /dev/null +++ b/librespot/structure.py @@ -0,0 +1,103 @@ +from __future__ import annotations +import typing + +if typing.TYPE_CHECKING: + from librespot.audio import AbsChunkedInputStream + from librespot.audio.format import SuperAudioFormat + from librespot.core import DealerClient, Session + from librespot.crypto import Packet + from librespot.mercury import MercuryClient + from librespot.proto import Metadata_pb2 as Metadata + + +class AudioDecrypt: + def decrypt_chunk(self, chunk_index: int, buffer: bytes): + raise NotImplementedError + + def decrypt_time_ms(self): + raise NotImplementedError + + +class AudioQualityPicker: + def get_file(self, + files: typing.List[Metadata.AudioFile]) -> Metadata.AudioFile: + raise NotImplementedError + + +class Closeable: + def close(self) -> None: + raise NotImplementedError + + +class FeederException(Exception): + pass + + +class GeneralAudioStream: + def stream(self) -> AbsChunkedInputStream: + raise NotImplementedError + + def codec(self) -> SuperAudioFormat: + raise NotImplementedError + + def describe(self) -> str: + raise NotImplementedError + + def decrypt_time_ms(self) -> int: + raise NotImplementedError + + +class GeneralWritableStream: + def write_chunk(self, buffer: bytearray, chunk_index: int, cached: bool): + raise NotImplementedError + + +class HaltListener: + def stream_read_halted(self, chunk: int, _time: int) -> None: + raise NotImplementedError + + def stream_read_resumed(self, chunk: int, _time: int) -> None: + raise NotImplementedError + + +class MessageListener: + def on_message(self, uri: str, headers: typing.Dict[str, str], + payload: bytes): + raise NotImplementedError + + +class NoopAudioDecrypt(AudioDecrypt): + def decrypt_chunk(self, chunk_index: int, buffer: bytes): + return buffer + + def decrypt_time_ms(self): + return 0 + + +class PacketsReceiver: + def dispatch(self, packet: Packet): + raise NotImplementedError + + +class RequestListener: + def on_request(self, mid: str, pid: int, sender: str, + command: typing.Any) -> DealerClient.RequestResult: + raise NotImplementedError + + +class Runnable: + def run(self): + raise NotImplementedError + + +class SessionListener: + def session_closing(self, session: Session) -> None: + raise NotImplementedError + + def session_changed(self, session: Session) -> None: + raise NotImplementedError + + +class SubListener: + def event(self, resp: MercuryClient.Response) -> None: + raise NotImplementedError diff --git a/librespot/util.py b/librespot/util.py new file mode 100644 index 0000000..28d7441 --- /dev/null +++ b/librespot/util.py @@ -0,0 +1,117 @@ +from Cryptodome import Random +import binascii +import math + + +def bytes_to_hex(buffer: bytes) -> str: + """ + Convert bytes to hex + Args: + buffer: Bytes to convert + Returns: + hex + """ + return binascii.hexlify(buffer).decode() + + +def hex_to_bytes(s: str) -> bytes: + return binascii.unhexlify(s) + + +def int_to_bytes(i: int): + """ + Convert an integer to a byte(s) + Args: + i: Integer to convert + Returns: + bytes + """ + width = i.bit_length() + width += 8 - ((width % 8) or 8) + fmt = '%%0%dx' % (width // 4) + return b"\x00" if i == 0 else binascii.unhexlify(fmt % i) + + +def random_hex_string(length: int): + buffer = Random.get_random_bytes(int(length / 2)) + return bytes_to_hex(buffer) + + +class Base62: + standard_base = 256 + target_base = 62 + alphabet: bytes + lookup: bytearray + + def __init__(self, alphabet: bytes): + self.alphabet = alphabet + self.create_lookup_table() + + @staticmethod + def create_instance_with_inverted_character_set(): + return Base62(Base62.CharacterSets.inverted) + + def encode(self, message: bytes, length: int = -1): + indices = self.convert(message, self.standard_base, self.target_base, + length) + return self.translate(indices, self.alphabet) + + def decode(self, encoded: bytes, length: int = -1): + prepared = self.translate(encoded, self.lookup) + return self.convert(prepared, self.target_base, self.standard_base, + length) + + def translate(self, indices: bytes, dictionary: bytes): + translation = bytearray(len(indices)) + for i in range(len(indices)): + translation[i] = dictionary[int.from_bytes(bytes([indices[i]]), "big")] + return translation + + def convert(self, message: bytes, source_base: int, target_base: int, + length: int): + estimated_length = self.estimate_output_length( + len(message), source_base, target_base) if length == -1 else length + out = b"" + source = message + while len(source) > 0: + quotient = b"" + remainder = 0 + for b in source: + accumulator = int(b & 0xff) + remainder * source_base + digit = int( + (accumulator - (accumulator % target_base)) / target_base) + remainder = int(accumulator % target_base) + if len(quotient) > 0 or digit > 0: + quotient += bytes([digit]) + out += bytes([remainder]) + source = quotient + if len(out) < estimated_length: + size = len(out) + for _ in range(estimated_length - size): + out += bytes([0]) + return self.reverse(out) + if len(out) > estimated_length: + return self.reverse(out[:estimated_length]) + return self.reverse(out) + + def estimate_output_length(self, input_length: int, source_base: int, + target_base: int): + return int( + math.ceil((math.log(source_base) / math.log(target_base)) * + input_length)) + + def reverse(self, arr: bytes): + length = len(arr) + reversed_arr = bytearray(length) + for i in range(length): + reversed_arr[length - i - 1] = arr[i] + return bytes(reversed_arr) + + def create_lookup_table(self): + self.lookup = bytearray(256) + for i in range(len(self.alphabet)): + self.lookup[self.alphabet[i]] = i & 0xff + + class CharacterSets: + gmp = b'0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz' + inverted = b'0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ' diff --git a/librespot/zeroconf.py b/librespot/zeroconf.py new file mode 100644 index 0000000..afe6847 --- /dev/null +++ b/librespot/zeroconf.py @@ -0,0 +1,345 @@ +from __future__ import annotations +from Cryptodome.Cipher import AES +from Cryptodome.Hash import HMAC, SHA1 +from Cryptodome.Util import Counter +from librespot import util, Version +from librespot.core import Session +from librespot.crypto import DiffieHellman +from librespot.proto import Connect_pb2 as Connect +from librespot.structure import Closeable, Runnable, SessionListener +import base64 +import concurrent.futures +import copy +import io +import json +import logging +import random +import socket +import threading +import typing +import urllib.parse +import zeroconf + + +class ZeroconfServer(Closeable): + logger = logging.getLogger("Librespot:ZeroconfServer") + service = "_spotify-connect._tcp.local." + __connecting_username: typing.Union[str, None] = None + __connection_lock = threading.Condition() + __default_get_info_fields = { + "status": 101, + "statusString": "OK", + "spotifyError": 0, + "version": "2.7.1", + "libraryVersion": Version.version_name, + "accountReq": "PREMIUM", + "brandDisplayName": "kokarare1212", + "modelDisplayName": "librespot-python", + "voiceSupport": "NO", + "availability": "", + "productID": 0, + "tokenType": "default", + "groupStatus": "NONE", + "resolverVersion": "0", + "scope": "streaming,client-authorization-universal", + } + __default_successful_add_user = { + "status": 101, + "spotifyError": 0, + "statusString": "OK", + } + __eol = b"\r\n" + __max_port = 65536 + __min_port = 1024 + __runner: HttpRunner + __service_info: zeroconf.ServiceInfo + __session: typing.Union[Session, None] = None + __session_listeners: typing.List[SessionListener] = [] + __zeroconf: zeroconf.Zeroconf + + def __init__(self, inner: Inner, listen_port): + self.__inner = inner + self.__keys = DiffieHellman() + if listen_port == -1: + listen_port = random.randint(self.__min_port + 1, self.__max_port) + self.__runner = ZeroconfServer.HttpRunner(self, listen_port) + threading.Thread(target=self.__runner.run, + name="zeroconf-http-server").start() + self.__zeroconf = zeroconf.Zeroconf() + self.__service_info = zeroconf.ServiceInfo( + ZeroconfServer.service, + inner.device_name + "." + ZeroconfServer.service, + listen_port, + 0, + 0, { + "CPath": "/", + "VERSION": "1.0", + "STACK": "SP", + }, + self.get_useful_hostname() + ".", + addresses=[ + socket.inet_aton( + socket.gethostbyname(self.get_useful_hostname())) + ]) + self.__zeroconf.register_service(self.__service_info) + threading.Thread(target=self.__zeroconf.start, + name="zeroconf-multicast-dns-server").start() + + def add_session_listener(self, listener: ZeroconfServer): + self.__session_listeners.append(listener) + + def close(self) -> None: + self.__zeroconf.close() + self.__runner.close() + + def close_session(self) -> None: + if self.__session is None: + return + for session_listener in self.__session_listeners: + session_listener.session_closing(self.__session) + self.__session.close() + self.__session = None + + def get_useful_hostname(self) -> str: + host = socket.gethostname() + if host == "localhost": + pass + else: + return host + + def handle_add_user(self, __socket: socket.socket, params: dict[str, str], + http_version: str) -> None: + username = params.get("userName") + if not username: + self.logger.error("Missing userName!") + return + blob_str = params.get("blob") + if not blob_str: + self.logger.error("Missing blob!") + return + client_key_str = params.get("clientKey") + if not client_key_str: + self.logger.error("Missing clientKey!") + with self.__connection_lock: + if username == self.__connecting_username: + self.logger.info( + "{} is already trying to connect.".format(username)) + __socket.send(http_version.encode()) + __socket.send(b" 403 Forbidden") + __socket.send(self.__eol) + __socket.send(self.__eol) + return + shared_key = util.int_to_bytes( + self.__keys.compute_shared_key( + base64.b64decode(client_key_str.encode()))) + blob_bytes = base64.b64decode(blob_str) + iv = blob_bytes[:16] + encrypted = blob_bytes[16:len(blob_bytes) - 20] + checksum = blob_bytes[len(blob_bytes) - 20:] + sha1 = SHA1.new() + sha1.update(shared_key) + base_key = sha1.digest()[:16] + hmac = HMAC.new(base_key, digestmod=SHA1) + hmac.update(b"checksum") + checksum_key = hmac.digest() + hmac = HMAC.new(base_key, digestmod=SHA1) + hmac.update(b"encryption") + encryption_key = hmac.digest() + hmac = HMAC.new(checksum_key, digestmod=SHA1) + hmac.update(encrypted) + mac = hmac.digest() + if mac != checksum: + self.logger.error("Mac and checksum don't match!") + __socket.send(http_version.encode()) + __socket.send(b" 400 Bad Request") + __socket.send(self.__eol) + __socket.send(self.__eol) + return + aes = AES.new(encryption_key[:16], + AES.MODE_CTR, + counter=Counter.new(128, + initial_value=int.from_bytes( + iv, "big"))) + decrypted = aes.decrypt(encrypted) + self.close_session() + with self.__connection_lock: + self.__connecting_username = username + self.logger.info("Accepted new user from {}. [deviceId: {}]".format( + params.get("deviceName"), self.__inner.device_id)) + response = json.dumps(self.__default_successful_add_user) + __socket.send(http_version.encode()) + __socket.send(b" 200 OK") + __socket.send(self.__eol) + __socket.send(b"Content-Length: ") + __socket.send(str(len(response)).encode()) + __socket.send(self.__eol) + __socket.send(self.__eol) + __socket.send(response.encode()) + self.__session = Session.Builder(self.__inner.conf) \ + .set_device_id(self.__inner.device_id) \ + .set_device_name(self.__inner.device_name) \ + .set_device_type(self.__inner.device_type) \ + .set_preferred_locale(self.__inner.preferred_locale) \ + .blob(username, decrypted) \ + .create() + with self.__connection_lock: + self.__connecting_username = None + for session_listener in self.__session_listeners: + session_listener.session_changed(self.__session) + + def handle_get_info(self, __socket: socket.socket, + http_version: str) -> None: + info = copy.deepcopy(self.__default_get_info_fields) + info["deviceID"] = self.__inner.device_id + info["remoteName"] = self.__inner.device_name + info["publicKey"] = base64.b64encode( + self.__keys.public_key_bytes()).decode() + info["deviceType"] = Connect.DeviceType.Name(self.__inner.device_type) + with self.__connection_lock: + info[ + "activeUser"] = self.__connecting_username if self.__connecting_username is not None else self.__session.username( + ) if self.has_valid_session() else "" + __socket.send(http_version.encode()) + __socket.send(b" 200 OK") + __socket.send(self.__eol) + __socket.send(b"Content-Type: application/json") + __socket.send(self.__eol) + __socket.send(self.__eol) + __socket.send(json.dumps(info).encode()) + + def has_valid_session(self) -> bool: + valid = self.__session and self.__session.is_valid() + if not valid: + self.__session = None + return valid + + def parse_path(self, path: str) -> dict[str, str]: + url = "https://host" + path + parsed = {} + params = urllib.parse.parse_qs(urllib.parse.urlparse(url).query) + for key, values in params.items(): + for value in values: + parsed[key] = value + return parsed + + def remove_session_listener(self, listener: SessionListener): + self.__session_listeners.remove(listener) + + class Builder(Session.Builder): + listen_port: int = -1 + + def set_listen_port(self, listen_port: int): + self.listen_port = listen_port + return self + + def create(self) -> ZeroconfServer: + return ZeroconfServer( + ZeroconfServer.Inner(self.device_type, self.device_name, + self.device_id, self.preferred_locale, + self.conf), self.listen_port) + + class HttpRunner(Closeable, Runnable): + __should_stop = False + __socket: socket.socket + __worker = concurrent.futures.ThreadPoolExecutor() + __zeroconf_server: ZeroconfServer + + def __init__(self, zeroconf_server: ZeroconfServer, port: int): + self.__socket = socket.socket() + self.__socket.bind((".".join(["0"] * 4), port)) + self.__socket.listen(5) + self.__zeroconf_server = zeroconf_server + self.__zeroconf_server.logger.info( + "Zeroconf HTTP server started successfully on port {}!".format( + port)) + + def close(self) -> None: + pass + + def run(self): + while not self.__should_stop: + __socket, address = self.__socket.accept() + + def anonymous(): + self.__handle(__socket) + __socket.close() + + self.__worker.submit(anonymous) + + def __handle(self, __socket: socket.socket) -> None: + request = io.BytesIO(__socket.recv(1024 * 1024)) + request_line = request.readline().strip().split(b" ") + if len(request_line) != 3: + self.__zeroconf_server.logger.warning( + "Unexpected request line: {}".format(request_line)) + method = request_line[0].decode() + path = request_line[1].decode() + http_version = request_line[2].decode() + headers = {} + while True: + header = request.readline().strip() + if not header: + break + split = header.split(b":") + headers[split[0].decode()] = split[1].strip().decode() + if not self.__zeroconf_server.has_valid_session(): + self.__zeroconf_server.logger.debug( + "Handling request: {}, {}, {}, headers: {}".format( + method, path, http_version, headers)) + params = {} + if method == "POST": + content_type = headers.get("Content-Type") + if content_type != "application/x-www-form-urlencoded": + self.__zeroconf_server.logger.error( + "Bad Content-Type: {}".format(content_type)) + return + content_length_str = headers.get("Content-Length") + if content_length_str is None: + self.__zeroconf_server.logger.error( + "Missing Content-Length header!") + return + content_length = int(content_length_str) + body = request.read(content_length).decode() + pairs = body.split("&") + for pair in pairs: + split = pair.split("=") + params[urllib.parse.unquote( + split[0])] = urllib.parse.unquote(split[1]) + else: + params = self.__zeroconf_server.parse_path(path) + action = params.get("action") + if action is None: + self.__zeroconf_server.logger.debug( + "Request is missing action.") + return + self.handle_request(__socket, http_version, action, params) + + def handle_request(self, __socket: socket.socket, http_version: str, + action: str, params: dict[str, str]) -> None: + if action == "addUser": + if params is None: + raise RuntimeError + self.__zeroconf_server.handle_add_user(__socket, params, + http_version) + elif action == "getInfo": + self.__zeroconf_server.handle_get_info(__socket, http_version) + else: + self.__zeroconf_server.logger.warning( + "Unknown action: {}".format(action)) + + class Inner: + conf: typing.Final[Session.Configuration] + device_name: typing.Final[str] + device_id: typing.Final[str] + device_type: typing.Final[Connect.DeviceType] + preferred_locale: typing.Final[str] + + def __init__(self, device_type: Connect.DeviceType, device_name: str, + device_id: str, preferred_locale: str, + conf: Session.Configuration): + self.conf = conf + self.device_name = device_name + self.device_id = util.random_hex_string( + 40).lower() if not device_id else device_id + self.device_type = device_type + self.preferred_locale = preferred_locale diff --git a/zotify/zotify.py b/zotify/zotify.py index af32721..35c844b 100644 --- a/zotify/zotify.py +++ b/zotify/zotify.py @@ -65,7 +65,6 @@ class Zotify: 'Accept-Language': f'{cls.CONFIG.get_language()}', 'Accept': 'application/json', 'app-platform': 'WebPlayer', - # Some Spotify spclient endpoints (e.g., color-lyrics) require a browser-like UA 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv=136.0) Gecko/20100101 Firefox/136.0', } @@ -109,5 +108,6 @@ class Zotify: @classmethod def check_premium(cls) -> bool: - """ If user has spotify premium return true """ - return (cls.SESSION.get_user_attribute(TYPE) == PREMIUM) + """ As we always use SpotiClub API, we just return true """ + # return (cls.SESSION.get_user_attribute(TYPE) == PREMIUM) + return True