Changes in radio.net

This commit is contained in:
MariuszC
2020-10-17 11:58:06 +02:00
parent 3a064d1abb
commit b728e9db3f
8 changed files with 78 additions and 216 deletions

View File

@@ -35,8 +35,6 @@ Mopidy-RadioNet to your Mopidy configuration file::
[radionet] [radionet]
enabled = true enabled = true
username = alice666.9
password = secret
language = pl # or net, de, at, fr, pt, es, dk, se, it language = pl # or net, de, at, fr, pt, es, dk, se, it
min_bitrate = 96 min_bitrate = 96
@@ -50,6 +48,10 @@ Project resources
Changelog Changelog
========= =========
v0.2.1 Changes in radio.net
----------------------------------------
v0.2.0 Python 3 v0.2.0 Python 3
---------------------------------------- ----------------------------------------

View File

@@ -6,7 +6,7 @@ import os
from mopidy import config, ext from mopidy import config, ext
__version__ = '0.2.0' __version__ = '0.2.1'
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@@ -24,8 +24,6 @@ class Extension(ext.Extension):
def get_config_schema(self): def get_config_schema(self):
schema = super(Extension, self).get_config_schema() schema = super(Extension, self).get_config_schema()
schema['username'] = config.String()
schema['password'] = config.Secret()
schema['language'] = config.String() schema['language'] = config.String()
schema['min_bitrate'] = config.String() schema['min_bitrate'] = config.String()
return schema return schema

View File

@@ -26,8 +26,6 @@ class RadioNetBackend(pykka.ThreadingActor, backend.Backend):
self.library = RadioNetLibraryProvider(backend=self) self.library = RadioNetLibraryProvider(backend=self)
self.uri_schemes = ['radionet'] self.uri_schemes = ['radionet']
self.username = config['radionet']['username']
self.password = config['radionet']['password']
self.radionet.min_bitrate = int(config['radionet']['min_bitrate']) self.radionet.min_bitrate = int(config['radionet']['min_bitrate'])
self.radionet.set_lang(str(config['radionet']['language'])) self.radionet.set_lang(str(config['radionet']['language']))
@@ -43,9 +41,6 @@ class RadioNetBackend(pykka.ThreadingActor, backend.Backend):
self.set_update_timeout() self.set_update_timeout()
if force or time.time() > self.update_timeout: if force or time.time() > self.update_timeout:
self.radionet.login(self.username, self.password)
self.radionet.get_bookmarks()
self.radionet.get_my_stations_streams()
self.radionet.get_top_stations() self.radionet.get_top_stations()
self.radionet.get_local_stations() self.radionet.get_local_stations()
self.set_update_timeout() self.set_update_timeout()

View File

@@ -1,6 +1,4 @@
[radionet] [radionet]
enabled = true enabled = true
username = alice666.9
password = secret
language = pl language = pl
min_bitrate = 96 min_bitrate = 96

View File

@@ -12,6 +12,9 @@ logger = logging.getLogger(__name__)
class RadioNetLibraryProvider(backend.LibraryProvider): class RadioNetLibraryProvider(backend.LibraryProvider):
root_directory = Ref.directory(uri='radionet:root', name='Radio.net') root_directory = Ref.directory(uri='radionet:root', name='Radio.net')
def __init__(self, backend):
super().__init__(backend)
def lookup(self, uri): def lookup(self, uri):
if not uri.startswith('radionet:'): if not uri.startswith('radionet:'):
@@ -38,7 +41,6 @@ class RadioNetLibraryProvider(backend.LibraryProvider):
genre=radio_data.genres, genre=radio_data.genres,
comment=radio_data.description, comment=radio_data.description,
uri=radio_data.stream_url) uri=radio_data.stream_url)
return [track] return [track]
return [] return []
@@ -50,11 +52,6 @@ class RadioNetLibraryProvider(backend.LibraryProvider):
tracks = [] tracks = []
variant, identifier = self.parse_uri(uri) variant, identifier = self.parse_uri(uri)
if variant == 'root': if variant == 'root':
if self.backend.radionet.fav_stations:
directories.append(
self.ref_directory(
"radionet:category:favstations", "My stations")
)
if self.backend.radionet.local_stations: if self.backend.radionet.local_stations:
directories.append( directories.append(
self.ref_directory( self.ref_directory(
@@ -65,24 +62,20 @@ class RadioNetLibraryProvider(backend.LibraryProvider):
self.ref_directory( self.ref_directory(
"radionet:category:top100", "Top 100") "radionet:category:top100", "Top 100")
) )
return directories
elif variant == 'category' and identifier: elif variant == 'category' and identifier:
if identifier == "favstations":
for station in self.backend.radionet.fav_stations:
tracks.append(self.station_to_ref(station))
if identifier == "localstations": if identifier == "localstations":
for station in self.backend.radionet.local_stations: for station in self.backend.radionet.local_stations:
tracks.append(self.station_to_ref(station)) tracks.append(self.station_to_ref(station))
if identifier == "top100": if identifier == "top100":
for station in self.backend.radionet.top_stations: for station in self.backend.radionet.top_stations:
tracks.append(self.station_to_ref(station)) tracks.append(self.station_to_ref(station))
tracks.sort(key=lambda ref: ref.name)
return tracks
else: else:
logger.debug('Unknown URI: %s', uri) logger.debug('Unknown URI: %s', uri)
return [] return []
tracks.sort(key=lambda ref: ref.name)
return directories + tracks
def search(self, query=None, uris=None, exact=False): def search(self, query=None, uris=None, exact=False):
result = [] result = []
@@ -104,7 +97,8 @@ class RadioNetLibraryProvider(backend.LibraryProvider):
def station_to_track(self, station): def station_to_track(self, station):
ref = self.station_to_ref(station) ref = self.station_to_ref(station)
return Track(uri=ref.uri, name=ref.name) return Track(uri=ref.uri, name=ref.name, album=Album(uri=ref.uri, name=ref.name),
artists=[Artist(uri=ref.uri, name=ref.name)])
def ref_directory(self, uri, name): def ref_directory(self, uri, name):
return Ref.directory(uri=uri, name=name) return Ref.directory(uri=uri, name=name)

View File

@@ -10,7 +10,6 @@ from mopidy import httpclient
import requests import requests
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@@ -28,27 +27,23 @@ class Station(object):
class RadioNetClient(object): class RadioNetClient(object):
base_url = 'https://radio.net/' base_url = 'https://radio.net/'
api_base_url = 'https://api.radio.net/info/v2/'
session = requests.Session() session = requests.Session()
api_key = None api_key = None
user_login = None api_prefix = None
min_bitrate = 96 min_bitrate = 96
max_top_stations = 100 max_top_stations = 100
station_bookmarks = None station_bookmarks = None
fav_stations = [] stations_images = []
top_stations = [] top_stations = []
local_stations = [] local_stations = []
search_results = [] search_results = []
username = None
password = None
def __init__(self, proxy_config=None, user_agent=None): def __init__(self, proxy_config=None, user_agent=None):
super(RadioNetClient, self).__init__() super(RadioNetClient, self).__init__()
self.session = requests.Session() self.session = requests.Session()
if proxy_config is not None: if proxy_config is not None:
proxy = httpclient.format_proxy(proxy_config) proxy = httpclient.format_proxy(proxy_config)
@@ -62,12 +57,10 @@ class RadioNetClient(object):
langs = ['net', 'de', 'at', 'fr', 'pt', 'es', 'dk', 'se', 'it', 'pl'] langs = ['net', 'de', 'at', 'fr', 'pt', 'es', 'dk', 'se', 'it', 'pl']
if lang in langs: if lang in langs:
self.base_url = self.base_url.replace(".net", "." + lang) self.base_url = self.base_url.replace(".net", "." + lang)
self.api_base_url = self.api_base_url.replace(".net", "." + lang)
else: else:
logging.error("Radio.net not supported language: " - str(lang)) logging.error("Radio.net not supported language: %s", str(lang))
def flush(self): def flush(self):
self.fav_stations = []
self.top_stations = [] self.top_stations = []
self.local_stations = [] self.local_stations = []
self.search_results = [] self.search_results = []
@@ -79,14 +72,16 @@ class RadioNetClient(object):
if self.api_key is not None: if self.api_key is not None:
return return
try:
tmp_str = self.session.get(self.base_url) tmp_str = self.session.get(self.base_url)
m = re.search('apiKey ?= ?[\'|"](.*)[\'|"];', tmp_str.content.decode())
self.api_key = m.group(1) apiprefix_search = re.search('apiPrefix ?: ?\'(.*)\',?', tmp_str.content.decode())
self.api_prefix = apiprefix_search.group(1)
apikey_search = re.search('apiKey ?: ?[\'|"](.*)[\'|"],?', tmp_str.content.decode())
self.api_key = apikey_search.group(1)
logger.info('Radio.net: APIPREFIX %s' % self.api_prefix)
logger.info('Radio.net: APIKEY %s' % self.api_key) logger.info('Radio.net: APIKEY %s' % self.api_key)
except Exception:
logger.error('Radio.net: Failed to connect %s retrying'
' on next browse.' % self.base_url)
def do_post(self, api_sufix, url_params=None, payload=None): def do_post(self, api_sufix, url_params=None, payload=None):
self.get_api_key() self.get_api_key()
@@ -94,8 +89,9 @@ class RadioNetClient(object):
if 'apikey' in url_params.keys(): if 'apikey' in url_params.keys():
url_params['apikey'] = self.api_key url_params['apikey'] = self.api_key
response = self.session.post(self.api_base_url + api_sufix, response = self.session.post(self.api_prefix + api_sufix,
params=url_params, data=payload) params=url_params, data=payload)
return response return response
def do_get(self, api_sufix, url_params=None): def do_get(self, api_sufix, url_params=None):
@@ -104,123 +100,14 @@ class RadioNetClient(object):
if 'apikey' in url_params.keys(): if 'apikey' in url_params.keys():
url_params['apikey'] = self.api_key url_params['apikey'] = self.api_key
response = self.session.get(self.api_base_url + api_sufix, response = self.session.get(self.api_prefix + api_sufix,
params=url_params) params=url_params)
return response return response
def check_auth(self):
url_params = {
'apikey': self.api_key,
'_': self.current_milli_time(),
}
logger.debug('Radio.net: Check auth.')
api_sufix = 'user/account'
response = self.do_post(api_sufix, url_params)
json = response.json()
self.user_login = json['login']
if len(self.user_login) == 0:
self.auth = False
else:
self.auth = True
def login(self, username, password):
self.check_auth()
if self.auth:
return
self.username = username
self.password = password
url_params = {
'apikey': self.api_key,
'_': self.current_milli_time(),
}
logger.debug('Radio.net: Login.')
api_sufix = 'user/login'
payload = {
'login': username,
'password': password,
}
response = self.do_post(api_sufix, url_params, payload)
if response.status_code is not 200:
logger.error('Radio.net: Login error. ' + response.text)
else:
json = response.json()
self.user_login = json['login']
if self.user_login == username:
logger.debug('Radio.net: Login successful.')
def logout(self):
url_params = {
'apikey': self.api_key,
'_': self.current_milli_time(),
}
api_sufix = 'user/logout'
response = self.do_post(api_sufix, url_params)
if response.status_code is not 200:
logger.error('Radio.net: Error logout.')
else:
json = response.json()
if len(json['login']) > 0:
logger.error('Radio.net: Error logout.')
else:
logger.info('Radio.net: Logout successful.')
self.session.close()
def get_bookmarks(self):
self.station_bookmarks = None
url_params = {
'apikey': self.api_key,
'_': self.current_milli_time(),
'list': 'STATION',
}
api_sufix = 'user/bookmarks'
response = self.do_post(api_sufix, url_params)
if response.status_code is not 200:
logger.error('Radio.net: ' + response.text)
else:
logger.debug('Radio.net: Done get bookmarks')
json = response.json()
self.station_bookmarks = json['stationBookmarks']
def __get_stream_url(self, stream_json, bitrate):
stream_url = None
for stream in stream_json:
if int(stream['bitRate']) >= bitrate and \
stream['streamStatus'] == 'VALID':
stream_url = stream['streamUrl']
break
if stream_url is None and len(stream_json) > 0:
stream_url = stream_json[0]['streamUrl']
return stream_url
def get_my_stations_streams(self):
self.fav_stations = []
for station_item in self.station_bookmarks['pageItems']:
station = self.get_station_by_id(station_item['id'])
if station.playable:
self.fav_stations.append(station)
logger.info('Radio.net: Loaded ' + str(len(self.fav_stations)) +
' my stations.')
def get_station_by_id(self, station_id): def get_station_by_id(self, station_id):
api_sufix = 'search/station' api_suffix = '/search/station'
url_params = { url_params = {
'apikey': self.api_key, 'apikey': self.api_key,
@@ -228,7 +115,7 @@ class RadioNetClient(object):
'station': station_id, 'station': station_id,
} }
response = self.do_get(api_sufix, url_params) response = self.do_get(api_suffix, url_params)
if response.status_code is not 200: if response.status_code is not 200:
logger.error('Radio.net: Error on get station by id ' + logger.error('Radio.net: Error on get station by id ' +
@@ -238,26 +125,26 @@ class RadioNetClient(object):
logger.debug('Radio.net: Done get top stations list') logger.debug('Radio.net: Done get top stations list')
json = response.json() json = response.json()
tmpStation = Station() station = Station()
tmpStation.id = json['id'] station.id = json['id']
tmpStation.continent = json['continent'] station.continent = json['continent']
tmpStation.country = json['country'] station.country = json['country']
tmpStation.city = json['city'] station.city = json['city']
tmpStation.genres = ', '.join(json["genres"]) station.genres = ', '.join(json["genres"])
tmpStation.name = json['name'] station.name = json['name']
tmpStation.stream_url = self.__get_stream_url( station.stream_url = self.get_stream_url(
json['streamUrls'], self.min_bitrate) json['streamUrls'], self.min_bitrate)
tmpStation.image = json['logo300x300'] station.image = json['logo100x100']
tmpStation.description = json['shortDescription'] station.description = json['shortDescription']
if json['playable'] == 'PLAYABLE': if json['playable'] == 'PLAYABLE':
tmpStation.playable = True station.playable = True
return tmpStation return station
def get_local_stations(self): def get_local_stations(self):
self.local_stations = [] self.local_stations = []
api_sufix = 'search/localstations' api_suffix = '/search/localstations'
url_params = { url_params = {
'apikey': self.api_key, 'apikey': self.api_key,
@@ -266,7 +153,7 @@ class RadioNetClient(object):
'sizeperpage': 100, 'sizeperpage': 100,
} }
response = self.do_post(api_sufix, url_params) response = self.do_post(api_suffix, url_params)
if response.status_code is not 200: if response.status_code is not 200:
logger.error('Radio.net: Get local stations error. ' + logger.error('Radio.net: Get local stations error. ' +
@@ -285,7 +172,7 @@ class RadioNetClient(object):
def get_top_stations(self): def get_top_stations(self):
self.top_stations = [] self.top_stations = []
api_sufix = 'search/topstations' api_suffix = '/search/topstations'
url_params = { url_params = {
'apikey': self.api_key, 'apikey': self.api_key,
@@ -294,7 +181,7 @@ class RadioNetClient(object):
'sizeperpage': 100, 'sizeperpage': 100,
} }
response = self.do_post(api_sufix, url_params) response = self.do_post(api_suffix, url_params)
if response.status_code is not 200: if response.status_code is not 200:
logger.error('Radio.net: Get top stations error. ' + response.text) logger.error('Radio.net: Get top stations error. ' + response.text)
@@ -314,7 +201,7 @@ class RadioNetClient(object):
if page_index == 1: if page_index == 1:
self.search_results = [] self.search_results = []
api_sufix = 'search/stationsonly' api_suffix = '/search/stationsonly'
url_params = { url_params = {
'apikey': self.api_key, 'apikey': self.api_key,
'_': self.current_milli_time(), '_': self.current_milli_time(),
@@ -322,7 +209,7 @@ class RadioNetClient(object):
'pageindex': page_index, 'pageindex': page_index,
} }
response = self.do_post(api_sufix, url_params) response = self.do_post(api_suffix, url_params)
if response.status_code is not 200: if response.status_code is not 200:
logger.error('Radio.net: Search error ' + response.text) logger.error('Radio.net: Search error ' + response.text)
@@ -340,3 +227,17 @@ class RadioNetClient(object):
else: else:
logger.info('Radio.net: Found ' + logger.info('Radio.net: Found ' +
str(len(self.search_results)) + ' stations.') str(len(self.search_results)) + ' stations.')
def get_stream_url(self, stream_json, bit_rate):
stream_url = None
for stream in stream_json:
if int(stream['bitRate']) >= bit_rate and \
stream['streamStatus'] == 'VALID':
stream_url = stream['streamUrl']
break
if stream_url is None and len(stream_json) > 0:
stream_url = stream_json[0]['streamUrl']
return stream_url

View File

@@ -17,7 +17,5 @@ def test_get_config_schema():
schema = ext.get_config_schema() schema = ext.get_config_schema()
assert 'username' in schema
assert 'password' in schema
assert 'language' in schema assert 'language' in schema
assert 'min_bitrate' in schema assert 'min_bitrate' in schema

View File

@@ -5,48 +5,24 @@ from mopidy_radionet.radionet import RadioNetClient
class RadioNetClientTest(unittest.TestCase): class RadioNetClientTest(unittest.TestCase):
username = 'alice666.9'
password = 'secret'
def test_get_api_key(self): def test_get_api_key(self):
radionet = RadioNetClient() radionet = RadioNetClient()
radionet.get_api_key() radionet.get_api_key()
self.assertIsNotNone(radionet.api_key) self.assertIsNotNone(radionet.api_key)
def test_login(self):
radionet = RadioNetClient()
radionet.login(self.username, self.password)
self.assertEqual(radionet.user_login, self.username)
def test_get_bookmarks(self):
radionet = RadioNetClient()
radionet.login(self.username, self.password)
radionet.get_bookmarks()
self.assertIsNotNone(radionet.station_bookmarks)
def test_get_bookmarks_station_streams(self):
radionet = RadioNetClient()
radionet.login(self.username, self.password)
radionet.get_bookmarks()
radionet.get_my_stations_streams()
self.assertGreater(len(radionet.fav_stations), 0)
def test_get_top_stations(self): def test_get_top_stations(self):
radionet = RadioNetClient() radionet = RadioNetClient()
radionet.login(self.username, self.password)
radionet.get_top_stations() radionet.get_top_stations()
self.assertGreater(len(radionet.top_stations), 0) self.assertGreater(len(radionet.top_stations), 0)
def test_get_local_stations(self): def test_get_local_stations(self):
radionet = RadioNetClient() radionet = RadioNetClient()
radionet.login(self.username, self.password)
radionet.get_local_stations() radionet.get_local_stations()
self.assertGreater(len(radionet.local_stations), 0) self.assertGreater(len(radionet.local_stations), 0)
def test_do_search(self): def test_do_search(self):
radionet = RadioNetClient() radionet = RadioNetClient()
radionet.login(self.username, self.password)
radionet.do_search("radio ram") radionet.do_search("radio ram")
self.assertGreater(len(radionet.search_results), 0) self.assertGreater(len(radionet.search_results), 0)