#135 Add ClientToken support
This commit is contained in:
parent
1a91446084
commit
b28e684e97
|
@ -6,7 +6,7 @@ import platform
|
||||||
|
|
||||||
|
|
||||||
class Version:
|
class Version:
|
||||||
version_name = "0.0.1"
|
version_name = "0.0.4"
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def platform() -> Platform:
|
def platform() -> Platform:
|
||||||
|
|
|
@ -12,7 +12,7 @@ from librespot.cache import CacheManager
|
||||||
from librespot.crypto import CipherPair, DiffieHellman, Packet
|
from librespot.crypto import CipherPair, DiffieHellman, Packet
|
||||||
from librespot.mercury import MercuryClient, MercuryRequests, RawMercuryRequest
|
from librespot.mercury import MercuryClient, MercuryRequests, RawMercuryRequest
|
||||||
from librespot.metadata import AlbumId, ArtistId, EpisodeId, ShowId, TrackId
|
from librespot.metadata import AlbumId, ArtistId, EpisodeId, ShowId, TrackId
|
||||||
from librespot.proto import Authentication_pb2 as Authentication, Connect_pb2 as Connect, Keyexchange_pb2 as Keyexchange, Metadata_pb2 as Metadata
|
from librespot.proto import Authentication_pb2 as Authentication, ClientToken_pb2 as ClientToken, Connect_pb2 as Connect, Connectivity_pb2 as Connectivity, Keyexchange_pb2 as Keyexchange, Metadata_pb2 as Metadata
|
||||||
from librespot.proto.ExplicitContentPubsub_pb2 import UserAttributesUpdate
|
from librespot.proto.ExplicitContentPubsub_pb2 import UserAttributesUpdate
|
||||||
from librespot.structure import Closeable, MessageListener, RequestListener, SubListener
|
from librespot.structure import Closeable, MessageListener, RequestListener, SubListener
|
||||||
import base64
|
import base64
|
||||||
|
@ -39,6 +39,7 @@ import websocket
|
||||||
class ApiClient(Closeable):
|
class ApiClient(Closeable):
|
||||||
logger = logging.getLogger("Librespot:ApiClient")
|
logger = logging.getLogger("Librespot:ApiClient")
|
||||||
__base_url: str
|
__base_url: str
|
||||||
|
__client_token_str: str = None
|
||||||
__session: Session
|
__session: Session
|
||||||
|
|
||||||
def __init__(self, session: Session):
|
def __init__(self, session: Session):
|
||||||
|
@ -49,6 +50,11 @@ class ApiClient(Closeable):
|
||||||
self, method: str, suffix: str,
|
self, method: str, suffix: str,
|
||||||
headers: typing.Union[None, typing.Dict[str, str]],
|
headers: typing.Union[None, typing.Dict[str, str]],
|
||||||
body: typing.Union[None, bytes]) -> requests.PreparedRequest:
|
body: typing.Union[None, bytes]) -> requests.PreparedRequest:
|
||||||
|
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))
|
||||||
|
|
||||||
request = requests.PreparedRequest()
|
request = requests.PreparedRequest()
|
||||||
request.method = method
|
request.method = method
|
||||||
request.data = body
|
request.data = body
|
||||||
|
@ -147,6 +153,45 @@ class ApiClient(Closeable):
|
||||||
proto.ParseFromString(body)
|
proto.ParseFromString(body)
|
||||||
return proto
|
return proto
|
||||||
|
|
||||||
|
def set_client_token(self, 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):
|
class StatusCodeException(IOError):
|
||||||
code: int
|
code: int
|
||||||
|
|
||||||
|
|
|
@ -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)
|
|
@ -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)
|
|
@ -0,0 +1,125 @@
|
||||||
|
syntax = "proto3";
|
||||||
|
|
||||||
|
package spotify.clienttoken.http.v0;
|
||||||
|
|
||||||
|
import "connectivity.proto";
|
||||||
|
|
||||||
|
option optimize_for = CODE_SIZE;
|
||||||
|
option java_package = "com.spotify.clienttoken.http.v0";
|
||||||
|
|
||||||
|
message ClientTokenRequest {
|
||||||
|
ClientTokenRequestType request_type = 1;
|
||||||
|
|
||||||
|
oneof request {
|
||||||
|
ClientDataRequest client_data = 2;
|
||||||
|
ChallengeAnswersRequest challenge_answers = 3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
message ClientDataRequest {
|
||||||
|
string client_version = 1;
|
||||||
|
string client_id = 2;
|
||||||
|
|
||||||
|
oneof data {
|
||||||
|
data.v0.ConnectivitySdkData connectivity_sdk_data = 3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
message ChallengeAnswersRequest {
|
||||||
|
string state = 1;
|
||||||
|
repeated ChallengeAnswer answers = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ClientTokenResponse {
|
||||||
|
ClientTokenResponseType response_type = 1;
|
||||||
|
|
||||||
|
oneof response {
|
||||||
|
GrantedTokenResponse granted_token = 2;
|
||||||
|
ChallengesResponse challenges = 3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
message TokenDomain {
|
||||||
|
string domain = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message GrantedTokenResponse {
|
||||||
|
string token = 1;
|
||||||
|
int32 expires_after_seconds = 2;
|
||||||
|
int32 refresh_after_seconds = 3;
|
||||||
|
repeated TokenDomain domains = 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ChallengesResponse {
|
||||||
|
string state = 1;
|
||||||
|
repeated Challenge challenges = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ClientSecretParameters {
|
||||||
|
string salt = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message EvaluateJSParameters {
|
||||||
|
string code = 1;
|
||||||
|
repeated string libraries = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message HashCashParameters {
|
||||||
|
int32 length = 1;
|
||||||
|
string prefix = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message Challenge {
|
||||||
|
ChallengeType type = 1;
|
||||||
|
|
||||||
|
oneof parameters {
|
||||||
|
ClientSecretParameters client_secret_parameters = 2;
|
||||||
|
EvaluateJSParameters evaluate_js_parameters = 3;
|
||||||
|
HashCashParameters evaluate_hashcash_parameters = 4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
message ClientSecretHMACAnswer {
|
||||||
|
string hmac = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message EvaluateJSAnswer {
|
||||||
|
string result = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message HashCashAnswer {
|
||||||
|
string suffix = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ChallengeAnswer {
|
||||||
|
ChallengeType ChallengeType = 1;
|
||||||
|
|
||||||
|
oneof answer {
|
||||||
|
ClientSecretHMACAnswer client_secret = 2;
|
||||||
|
EvaluateJSAnswer evaluate_js = 3;
|
||||||
|
HashCashAnswer hash_cash = 4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
message ClientTokenBadRequest {
|
||||||
|
string message = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum ClientTokenRequestType {
|
||||||
|
REQUEST_UNKNOWN = 0;
|
||||||
|
REQUEST_CLIENT_DATA_REQUEST = 1;
|
||||||
|
REQUEST_CHALLENGE_ANSWERS_REQUEST = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum ClientTokenResponseType {
|
||||||
|
RESPONSE_UNKNOWN = 0;
|
||||||
|
RESPONSE_GRANTED_TOKEN_RESPONSE = 1;
|
||||||
|
RESPONSE_CHALLENGES_RESPONSE = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum ChallengeType {
|
||||||
|
CHALLENGE_UNKNOWN = 0;
|
||||||
|
CHALLENGE_CLIENT_SECRET_HMAC = 1;
|
||||||
|
CHALLENGE_EVALUATE_JS = 2;
|
||||||
|
CHALLENGE_HASH_CASH = 3;
|
||||||
|
}
|
|
@ -0,0 +1,51 @@
|
||||||
|
syntax = "proto3";
|
||||||
|
|
||||||
|
package spotify.clienttoken.data.v0;
|
||||||
|
|
||||||
|
option optimize_for = CODE_SIZE;
|
||||||
|
option java_package = "com.spotify.clienttoken.data.v0";
|
||||||
|
|
||||||
|
message ConnectivitySdkData {
|
||||||
|
PlatformSpecificData platform_specific_data = 1;
|
||||||
|
string device_id = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message PlatformSpecificData {
|
||||||
|
oneof data {
|
||||||
|
NativeAndroidData android = 1;
|
||||||
|
NativeIOSData ios = 2;
|
||||||
|
NativeWindowsData windows = 4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
message NativeAndroidData {
|
||||||
|
int32 major_sdk_version = 1;
|
||||||
|
int32 minor_sdk_version = 2;
|
||||||
|
int32 patch_sdk_version = 3;
|
||||||
|
uint32 api_version = 4;
|
||||||
|
Screen screen_dimensions = 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
message NativeIOSData {
|
||||||
|
int32 user_interface_idiom = 1;
|
||||||
|
bool target_iphone_simulator = 2;
|
||||||
|
string hw_machine = 3;
|
||||||
|
string system_version = 4;
|
||||||
|
string simulator_model_identifier = 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
message NativeWindowsData {
|
||||||
|
int32 something1 = 1;
|
||||||
|
int32 something3 = 3;
|
||||||
|
int32 something4 = 4;
|
||||||
|
int32 something6 = 6;
|
||||||
|
int32 something7 = 7;
|
||||||
|
int32 something8 = 8;
|
||||||
|
bool something10 = 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
message Screen {
|
||||||
|
int32 width = 1;
|
||||||
|
int32 height = 2;
|
||||||
|
int32 density = 3;
|
||||||
|
}
|
2
setup.py
2
setup.py
|
@ -1,7 +1,7 @@
|
||||||
import setuptools
|
import setuptools
|
||||||
|
|
||||||
setuptools.setup(name="librespot",
|
setuptools.setup(name="librespot",
|
||||||
version="0.0.3",
|
version="0.0.4",
|
||||||
description="Open Source Spotify Client",
|
description="Open Source Spotify Client",
|
||||||
long_description=open("README.md").read(),
|
long_description=open("README.md").read(),
|
||||||
long_description_content_type="text/markdown",
|
long_description_content_type="text/markdown",
|
||||||
|
|
Loading…
Reference in New Issue