reverse engineered Spotify Canvas API only available on iOS and Android displays short looping video for song in place of album when available
57 lines
1.7 KiB
Python
57 lines
1.7 KiB
Python
import requests
|
|
import random
|
|
from protos.canvas_pb2 import EntityCanvazRequest, EntityCanvazResponse
|
|
|
|
API_HOST = "https://spclient.wg.spotify.com"
|
|
CANVAS_ROUTE = "/canvaz-cache/v0/canvases"
|
|
TOKEN_ENDPOINT = "https://open.spotify.com/get_access_token?reason=transport"
|
|
TOKEN_RENEW_TIME = 900
|
|
|
|
TRACK_URI_PREFIX = "spotify:track:"
|
|
OAUTH_SCOPES = "playlist-read"
|
|
|
|
def get_access_token():
|
|
try:
|
|
response = requests.get(TOKEN_ENDPOINT)
|
|
data = response.json()
|
|
return data["accessToken"]
|
|
except Exception as e:
|
|
raise Exception(e)
|
|
|
|
|
|
def get_canvas_for_track(access_token, track_id):
|
|
canvas_request = EntityCanvazRequest()
|
|
canvas_request_entities = canvas_request.entities.add()
|
|
canvas_request_entities.entity_uri = TRACK_URI_PREFIX + track_id
|
|
|
|
try:
|
|
resp = requests.post(
|
|
API_HOST + CANVAS_ROUTE,
|
|
headers={
|
|
"Accept": "application/protobuf",
|
|
"Content-Type": "application/x-www-form-urlencoded",
|
|
"Accept-Language": "en",
|
|
"User-Agent": "Spotify/8.5.49 iOS/Version 13.3.1 (Build 17D50)",
|
|
"Accept-Encoding": "gzip, deflate, br",
|
|
"Authorization": "Bearer %s" % access_token
|
|
},
|
|
data=canvas_request.SerializeToString(),
|
|
)
|
|
except:
|
|
raise ConnectionError
|
|
|
|
canvas_response = EntityCanvazResponse()
|
|
canvas_response.ParseFromString(resp.content)
|
|
|
|
if(len(canvas_response.canvases) == 0):
|
|
raise AttributeError
|
|
|
|
canvas = random.choice(canvas_response.canvases)
|
|
|
|
if canvas.url is not None:
|
|
return canvas.url
|
|
else:
|
|
return None
|
|
|
|
# access_token = get_access_token()
|
|
# print(get_canvas_for_track(access_token, "1kADZJDyRUbmlLxYiqi077")) |