Skip to content

Instantly share code, notes, and snippets.

@Romern
Created March 3, 2021 19:38
Show Gist options
  • Save Romern/b47f749213910366684b056d7140a1e9 to your computer and use it in GitHub Desktop.
Save Romern/b47f749213910366684b056d7140a1e9 to your computer and use it in GitHub Desktop.
Napster stream API used in android app (no drm)
import requests
from requests.auth import HTTPBasicAuth
import json
from pathlib import Path
apikey = 'ZTJlOWNhZGUtNzlmZS00ZGU2LTkwYjMtZDk1ODRlMDkwODM5' #from the APK
secret = 'MTRjZTVjM2EtOGVlZi00OTU3LWFmNjktNTllODFhNmYyNzI5' #from the APK
def download_file(url, filename):
with requests.get(url, stream=True) as r:
r.raise_for_status()
with open(filename, 'wb') as f:
for chunk in r.iter_content(chunk_size=8192):
# If you have chunk encoded response uncomment if
# and set chunk_size parameter to None.
#if chunk:
f.write(chunk)
def search(query):
headers = {
'apikey': apikey,
'User-Agent': 'okhttp/3.12.1',
}
params = (
('catalog', 'DE'),
('lang', 'de_DE'),
('offset', '0'),
('per_type_limit', '5'),
('query', query),
('rights', '2'),
('type', 'album,artist,track'),
)
response = requests.get('http://api.rhapsody.com/v2.2/search', headers=headers, params=params)
return response.json()
#album_id e.g. alb.XXXXXXXXXXX
def get_album_tracks_info(album_id):
if "alb." != album_id[:len("alb.")]:
raise Exception("not an album id")
headers = {
'apikey': apikey,
'User-Agent': 'okhttp/3.12.1',
}
params = (
('catalog', 'DE'),
('lang', 'de_DE'),
('rights', '2'),
)
response = requests.get(f'http://api.rhapsody.com/v2.2/albums/{album_id}/tracks', headers=headers, params=params)
return response.json()
def auth_user(username, password):
headers = {
'User-Agent': 'okhttp/3.12.1',
}
data = {
'username': username,
'password': password,
'grant_type': 'password'
}
response = requests.post('https://api.rhapsody.com/oauth/token', headers=headers, data=data, auth=HTTPBasicAuth(apikey, secret))
return response.json()["access_token"] # also contains other stuff
def get_audio_stream_info(track_id, access_token, bitrate=44100, format="FLAC"):
if "tra." != track_id[:len("tra.")]:
raise Exception("not an track id")
headers = {
'Accept': 'application/json',
'Authorization': f'Bearer {access_token}',
'Host': 'api.rhapsody.com',
'User-Agent': 'okhttp/3.12.1',
}
params = (
('bitrate', str(bitrate)),
('format', format),
('protocol', ''),
('track', track_id),
)
response = requests.get('https://api.rhapsody.com/v2.2/streams', headers=headers, params=params)
return response.json()
def download_album(album_id, access_token):
album_info = get_album_tracks_info(album_id)
for track in album_info["tracks"]:
stream_info = get_audio_stream_info(track["id"], access_token)
stream_url = stream_info["streams"][0]["url"]
directory = Path("./") / f'{track["artistName"]} - {track["albumName"]}'
directory.mkdir(exist_ok=True, parents=True)
download_file(stream_url, directory / f'{track["index"]}. {track["name"]}.flac')
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment