2019-07-09 16:44:56 +00:00
|
|
|
import requests
|
2019-08-14 14:06:07 +00:00
|
|
|
import logging
|
2019-07-09 16:44:56 +00:00
|
|
|
|
2019-08-18 12:11:38 +00:00
|
|
|
from ycast import __version__
|
2019-07-17 13:44:35 +00:00
|
|
|
import ycast.vtuner as vtuner
|
2019-08-18 11:50:38 +00:00
|
|
|
import ycast.generic as generic
|
2019-07-17 13:44:35 +00:00
|
|
|
|
2020-10-10 13:20:22 +00:00
|
|
|
API_ENDPOINT = "http://all.api.radio-browser.info"
|
2019-07-09 16:44:56 +00:00
|
|
|
MINIMUM_COUNT_GENRE = 5
|
|
|
|
MINIMUM_COUNT_COUNTRY = 5
|
2019-08-19 13:00:48 +00:00
|
|
|
MINIMUM_COUNT_LANGUAGE = 5
|
2019-08-17 21:56:51 +00:00
|
|
|
DEFAULT_STATION_LIMIT = 200
|
2019-08-18 11:50:38 +00:00
|
|
|
SHOW_BROKEN_STATIONS = False
|
2019-08-19 11:57:35 +00:00
|
|
|
ID_PREFIX = "RB"
|
2019-07-09 16:44:56 +00:00
|
|
|
|
|
|
|
|
|
|
|
def get_json_attr(json, attr):
|
|
|
|
try:
|
|
|
|
return json[attr]
|
|
|
|
except:
|
|
|
|
return None
|
|
|
|
|
|
|
|
|
|
|
|
class Station:
|
|
|
|
def __init__(self, station_json):
|
2020-10-10 13:20:22 +00:00
|
|
|
self.id = generic.generate_stationid_with_prefix(get_json_attr(station_json, 'stationuuid'), ID_PREFIX)
|
2019-07-09 16:44:56 +00:00
|
|
|
self.name = get_json_attr(station_json, 'name')
|
|
|
|
self.url = get_json_attr(station_json, 'url')
|
|
|
|
self.icon = get_json_attr(station_json, 'favicon')
|
|
|
|
self.tags = get_json_attr(station_json, 'tags').split(',')
|
2020-10-10 13:20:22 +00:00
|
|
|
self.countrycode = get_json_attr(station_json, 'countrycode')
|
2019-07-09 16:44:56 +00:00
|
|
|
self.language = get_json_attr(station_json, 'language')
|
|
|
|
self.votes = get_json_attr(station_json, 'votes')
|
|
|
|
self.codec = get_json_attr(station_json, 'codec')
|
|
|
|
self.bitrate = get_json_attr(station_json, 'bitrate')
|
|
|
|
|
2019-07-17 13:44:35 +00:00
|
|
|
def to_vtuner(self):
|
|
|
|
return vtuner.Station(self.id, self.name, ', '.join(self.tags), self.url, self.icon,
|
2020-10-10 13:20:22 +00:00
|
|
|
self.tags[0], self.countrycode, self.codec, self.bitrate, None)
|
2019-07-17 13:44:35 +00:00
|
|
|
|
2019-08-26 18:39:36 +00:00
|
|
|
def get_playable_url(self):
|
|
|
|
try:
|
|
|
|
playable_url_json = request('url/' + generic.get_stationid_without_prefix(self.id))[0]
|
|
|
|
self.url = playable_url_json['url']
|
|
|
|
except (IndexError, KeyError):
|
|
|
|
logging.error("Could not retrieve first playlist item for station with id '%s'", self.id)
|
|
|
|
|
2019-07-09 16:44:56 +00:00
|
|
|
|
|
|
|
def request(url):
|
2019-08-18 11:50:38 +00:00
|
|
|
logging.debug("Radiobrowser API request: %s", url)
|
2019-08-18 12:11:38 +00:00
|
|
|
headers = {'content-type': 'application/json', 'User-Agent': generic.USER_AGENT + '/' + __version__}
|
2019-08-20 21:43:32 +00:00
|
|
|
try:
|
2020-10-10 13:20:22 +00:00
|
|
|
response = requests.get(API_ENDPOINT + '/json/' + url, headers=headers)
|
2019-08-20 21:43:32 +00:00
|
|
|
except requests.exceptions.ConnectionError as err:
|
|
|
|
logging.error("Connection to Radiobrowser API failed (%s)", err)
|
|
|
|
return {}
|
2019-07-09 16:44:56 +00:00
|
|
|
if response.status_code != 200:
|
2019-08-20 21:43:32 +00:00
|
|
|
logging.error("Could not fetch data from Radiobrowser API (HTML status %s)", response.status_code)
|
2019-08-14 14:06:07 +00:00
|
|
|
return {}
|
2019-07-09 16:44:56 +00:00
|
|
|
return response.json()
|
|
|
|
|
|
|
|
|
|
|
|
def get_station_by_id(uid):
|
2020-11-29 11:20:17 +00:00
|
|
|
station_json = request('stations/byuuid/' + str(uid))
|
2019-08-19 11:57:35 +00:00
|
|
|
if station_json and len(station_json):
|
|
|
|
return Station(station_json[0])
|
|
|
|
else:
|
|
|
|
return None
|
2019-07-09 16:44:56 +00:00
|
|
|
|
|
|
|
|
2019-08-17 21:59:50 +00:00
|
|
|
def search(name, limit=DEFAULT_STATION_LIMIT):
|
2019-07-09 16:44:56 +00:00
|
|
|
stations = []
|
2019-08-18 11:50:38 +00:00
|
|
|
stations_json = request('stations/search?order=name&reverse=false&limit=' + str(limit) + '&name=' + str(name))
|
2019-07-09 16:44:56 +00:00
|
|
|
for station_json in stations_json:
|
2020-10-10 13:20:22 +00:00
|
|
|
if SHOW_BROKEN_STATIONS or get_json_attr(station_json, 'lastcheckok') == 1:
|
2019-08-18 11:50:38 +00:00
|
|
|
stations.append(Station(station_json))
|
2019-07-09 16:44:56 +00:00
|
|
|
return stations
|
|
|
|
|
|
|
|
|
2019-08-18 11:50:38 +00:00
|
|
|
def get_country_directories():
|
|
|
|
country_directories = []
|
|
|
|
apicall = 'countries'
|
|
|
|
if not SHOW_BROKEN_STATIONS:
|
|
|
|
apicall += '?hidebroken=true'
|
|
|
|
countries_raw = request(apicall)
|
2019-07-09 16:44:56 +00:00
|
|
|
for country_raw in countries_raw:
|
2019-07-10 11:58:09 +00:00
|
|
|
if get_json_attr(country_raw, 'name') and get_json_attr(country_raw, 'stationcount') and \
|
|
|
|
int(get_json_attr(country_raw, 'stationcount')) > MINIMUM_COUNT_COUNTRY:
|
2019-08-18 11:50:38 +00:00
|
|
|
country_directories.append(generic.Directory(get_json_attr(country_raw, 'name'),
|
|
|
|
get_json_attr(country_raw, 'stationcount')))
|
|
|
|
return country_directories
|
2019-07-09 16:44:56 +00:00
|
|
|
|
|
|
|
|
2019-08-19 13:00:48 +00:00
|
|
|
def get_language_directories():
|
|
|
|
language_directories = []
|
|
|
|
apicall = 'languages'
|
|
|
|
if not SHOW_BROKEN_STATIONS:
|
|
|
|
apicall += '?hidebroken=true'
|
|
|
|
languages_raw = request(apicall)
|
|
|
|
for language_raw in languages_raw:
|
|
|
|
if get_json_attr(language_raw, 'name') and get_json_attr(language_raw, 'stationcount') and \
|
|
|
|
int(get_json_attr(language_raw, 'stationcount')) > MINIMUM_COUNT_LANGUAGE:
|
|
|
|
language_directories.append(generic.Directory(get_json_attr(language_raw, 'name'),
|
2020-10-10 14:36:44 +00:00
|
|
|
get_json_attr(language_raw, 'stationcount'),
|
|
|
|
get_json_attr(language_raw, 'name').title()))
|
2019-08-19 13:00:48 +00:00
|
|
|
return language_directories
|
|
|
|
|
|
|
|
|
2019-08-18 11:50:38 +00:00
|
|
|
def get_genre_directories():
|
|
|
|
genre_directories = []
|
|
|
|
apicall = 'tags'
|
|
|
|
if not SHOW_BROKEN_STATIONS:
|
|
|
|
apicall += '?hidebroken=true'
|
|
|
|
genres_raw = request(apicall)
|
2019-07-09 16:44:56 +00:00
|
|
|
for genre_raw in genres_raw:
|
2019-07-10 11:58:09 +00:00
|
|
|
if get_json_attr(genre_raw, 'name') and get_json_attr(genre_raw, 'stationcount') and \
|
|
|
|
int(get_json_attr(genre_raw, 'stationcount')) > MINIMUM_COUNT_GENRE:
|
2019-08-18 11:50:38 +00:00
|
|
|
genre_directories.append(generic.Directory(get_json_attr(genre_raw, 'name'),
|
2020-10-10 14:36:44 +00:00
|
|
|
get_json_attr(genre_raw, 'stationcount'),
|
|
|
|
get_json_attr(genre_raw, 'name').capitalize()))
|
2019-08-18 11:50:38 +00:00
|
|
|
return genre_directories
|
2019-07-09 16:44:56 +00:00
|
|
|
|
|
|
|
|
2019-07-21 17:45:52 +00:00
|
|
|
def get_stations_by_country(country):
|
2019-07-09 16:44:56 +00:00
|
|
|
stations = []
|
2019-08-18 11:50:38 +00:00
|
|
|
stations_json = request('stations/search?order=name&reverse=false&countryExact=true&country=' + str(country))
|
2019-07-09 16:44:56 +00:00
|
|
|
for station_json in stations_json:
|
2020-10-10 13:20:22 +00:00
|
|
|
if SHOW_BROKEN_STATIONS or get_json_attr(station_json, 'lastcheckok') == 1:
|
2019-08-18 11:50:38 +00:00
|
|
|
stations.append(Station(station_json))
|
2019-07-09 16:44:56 +00:00
|
|
|
return stations
|
|
|
|
|
|
|
|
|
2019-08-19 13:00:48 +00:00
|
|
|
def get_stations_by_language(language):
|
|
|
|
stations = []
|
|
|
|
stations_json = request('stations/search?order=name&reverse=false&languageExact=true&language=' + str(language))
|
|
|
|
for station_json in stations_json:
|
2020-10-10 13:20:22 +00:00
|
|
|
if SHOW_BROKEN_STATIONS or get_json_attr(station_json, 'lastcheckok') == 1:
|
2019-08-19 13:00:48 +00:00
|
|
|
stations.append(Station(station_json))
|
|
|
|
return stations
|
|
|
|
|
|
|
|
|
2019-07-21 17:45:52 +00:00
|
|
|
def get_stations_by_genre(genre):
|
2019-07-09 16:44:56 +00:00
|
|
|
stations = []
|
2019-08-18 11:50:38 +00:00
|
|
|
stations_json = request('stations/search?order=name&reverse=false&tagExact=true&tag=' + str(genre))
|
2019-07-09 16:44:56 +00:00
|
|
|
for station_json in stations_json:
|
2020-10-10 13:20:22 +00:00
|
|
|
if SHOW_BROKEN_STATIONS or get_json_attr(station_json, 'lastcheckok') == 1:
|
2019-08-18 11:50:38 +00:00
|
|
|
stations.append(Station(station_json))
|
2019-07-09 16:44:56 +00:00
|
|
|
return stations
|
|
|
|
|
|
|
|
|
2019-07-21 17:45:52 +00:00
|
|
|
def get_stations_by_votes(limit=DEFAULT_STATION_LIMIT):
|
2019-07-09 16:44:56 +00:00
|
|
|
stations = []
|
|
|
|
stations_json = request('stations?order=votes&reverse=true&limit=' + str(limit))
|
|
|
|
for station_json in stations_json:
|
2020-10-10 13:20:22 +00:00
|
|
|
if SHOW_BROKEN_STATIONS or get_json_attr(station_json, 'lastcheckok') == 1:
|
2019-08-18 11:50:38 +00:00
|
|
|
stations.append(Station(station_json))
|
2019-07-09 16:44:56 +00:00
|
|
|
return stations
|