gmusicapi
gmusicapi copied to clipboard
Mobileclient v2.1 - Station Categories
trafficstars
Mobileclient v2.0w - Station Categories
New API-Url https://mclients.googleapis.com/sj/v2.1/
Listen now content can be retrieved via:
sj_url + browse/stationcategories
sj_url + browse/stations/<station_id> (supports dynamic_param -> location_id)
Original response (stripped-down) -> browse/stationcategories
{
"kind": "sj#getStationCategoriesResponse",
"root": {
"kind": "sj#stationCategory",
"subcategories": [
{
"kind": "sj#stationCategory",
"subcategories": [
{
"kind": "sj#stationCategory",
"display_name": "Dance & Electronic",
"id": "JZC3321"
}
],
"display_name": "Genres",
"id": "JZC3319"
},
{
"kind": "sj#stationCategory",
"subcategories": [
{
"kind": "sj#stationCategory",
"display_name": "Falling Asleep",
"id": "JZC3306"
}
],
"display_name": "Activities",
"id": "JZC3320"
},
{
"kind": "sj#stationCategory",
"subcategories": [
{
"kind": "sj#stationCategory",
"display_name": "Energetic",
"id": "JZC3346"
}
],
"display_name": "Moods",
"id": "JZC3310"
},
{
"kind": "sj#stationCategory",
"subcategories": [
{
"kind": "sj#stationCategory",
"display_name": "1980s",
"id": "JZC3356"
}
],
"display_name": "Decades",
"id": "JZC3311"
}
],
"display_name": "BROWSE_STATIONS_ROOT",
"id": "BROWSE_STATIONS_ROOT"
}
}
Proof-of-Concept implementation
#protocol/mobileclient.py
class GetStationCategories(McCall):
static_params = {'alt': 'json'}
static_method = 'GET'
static_url = sj_url + 'browse/stationcategories'
#clients/mobileclient.py
...
def get_station_categories(self):
res = self._make_call(mobileclient.GetStationCategories)
return res['root']['subcategories']
...
Original response (stripped-down) -> browse/stations/JZC3321 (id picked from Genres -> Dance & Electronic. location_id=en_US)
{
"kind": "sj#getStationsResponse",
"stations": [
{
"kind": "sj#radioStation",
"name": "Relaxed Electronica",
"compositeArtRefs": [
{
"url": "http://lh3.googleusercontent.com/...",
"kind": "sj#imageRef",
"aspectRatio": "2"
}
],
"seed": {
"kind": "sj#radioSeed",
"curatedStationId": "Ltsxgnw2ay732rpoaoqijj5quwu",
"seedType": "9"
},
"skipEventHistory": [],
"stationSeeds": [
{
"kind": "sj#radioSeed",
"curatedStationId": "Ltsxgnw2ay732rpoaoqijj5quwu",
"seedType": "9"
}
],
"imageUrls": [
{
"url": "http://lh5.ggpht.com/...",
"kind": "sj#imageRef",
"aspectRatio": "1",
"autogen": false
}
],
"description": "Relaxed songs for travel, dream or just to chill out."
}
]
}
Proof-of-Concept implementation
#protocol/mobileclient.py
class GetStations(McCall):
static_params = {'alt': 'json'}
static_method = 'GET'
@staticmethod
def dynamic_url(station_id, location_id):
return sj_url + 'browse/stations/' + station_id
@staticmethod
def dynamic_params(station_id, location_id):
return {'hl': location_id}
#clients/mobileclient.py
...
def get_stations(self, station_id, location_id):
res = self._make_call(mobileclient.GetStations, station_id, location_id)
return res['stations']
...
Update: The response of browse/stations/station_id contains a curatedStationId and seedType Therefore mobileclient.create_station() should be extended to support it.