pyradio implementation

fix #138
This commit is contained in:
Azlux 2020-06-01 15:34:10 +02:00
parent 67b72af2de
commit 9263e647fd
8 changed files with 62 additions and 303 deletions

View File

@ -11,7 +11,7 @@ import interface
import media.system import media.system
import util import util
import variables as var import variables as var
from librb import radiobrowser from pyradios import RadioBrowser
from database import SettingsDatabase, MusicDatabase, Condition from database import SettingsDatabase, MusicDatabase, Condition
from media.item import item_id_generators, dict_to_item, dicts_to_items from media.item import item_id_generators, dict_to_item, dicts_to_items
from media.cache import get_cached_wrapper_from_scrap, get_cached_wrapper_by_id, get_cached_wrappers_by_tags, \ from media.cache import get_cached_wrapper_from_scrap, get_cached_wrapper_by_id, get_cached_wrappers_by_tags, \
@ -74,8 +74,8 @@ def register_all_commands(bot):
bot.register_command(constants.commands('change_user_password'), cmd_user_password, no_partial_match=True) bot.register_command(constants.commands('change_user_password'), cmd_user_password, no_partial_match=True)
# Just for debug use # Just for debug use
bot.register_command('rtrms', cmd_real_time_rms, True) bot.register_command('rtrms', cmd_real_time_rms, True)
#bot.register_command('loop', cmd_loop_state, True) # bot.register_command('loop', cmd_loop_state, True)
#bot.register_command('item', cmd_item, True) # bot.register_command('item', cmd_item, True)
def send_multi_lines(bot, lines, text, linebreak="<br />"): def send_multi_lines(bot, lines, text, linebreak="<br />"):
@ -86,7 +86,7 @@ def send_multi_lines(bot, lines, text, linebreak="<br />"):
for newline in lines: for newline in lines:
msg += br msg += br
br = linebreak br = linebreak
if bot.mumble.get_max_message_length()\ if bot.mumble.get_max_message_length() \
and (len(msg) + len(newline)) > (bot.mumble.get_max_message_length() - 4): # 4 == len("<br>") and (len(msg) + len(newline)) > (bot.mumble.get_max_message_length() - 4): # 4 == len("<br>")
bot.send_msg(msg, text) bot.send_msg(msg, text)
msg = "" msg = ""
@ -338,11 +338,10 @@ def cmd_play_playlist(bot, user, text, command, parameter):
pass pass
url = util.get_url_from_input(parameter) url = util.get_url_from_input(parameter)
log.debug("cmd: fetching media info from playlist url %s" % url) log.debug(f"cmd: fetching media info from playlist url {url}")
items = get_playlist_info(url=url, start_index=offset, user=user) items = get_playlist_info(url=url, start_index=offset, user=user)
if len(items) > 0: if len(items) > 0:
items = var.playlist.extend(list(map( items = var.playlist.extend(list(map(lambda item: get_cached_wrapper_from_scrap(**item), items)))
lambda item: get_cached_wrapper_from_scrap(**item), items)))
for music in items: for music in items:
log.info("cmd: add to playlist: " + music.format_debug_string()) log.info("cmd: add to playlist: " + music.format_debug_string())
else: else:
@ -386,24 +385,22 @@ def cmd_rb_query(bot, user, text, command, parameter):
bot.send_msg(msg, text) bot.send_msg(msg, text)
else: else:
log.debug('cmd: Found query parameter: ' + parameter) log.debug('cmd: Found query parameter: ' + parameter)
# bot.send_msg('Searching for stations - this may take some seconds...', text) rb = RadioBrowser()
rb_stations = radiobrowser.getstations_byname(parameter) rb_stations = rb.search(name=parameter, name_exact=False)
msg = constants.strings('rb_query_result') msg = constants.strings('rb_query_result')
msg += '\n<table><tr><th>!rbplay ID</th><th>Station Name</th><th>Genre</th><th>Codec/Bitrate</th><th>Country</th></tr>' msg += '\n<table><tr><th>!rbplay ID</th><th>Station Name</th><th>Genre</th><th>Codec/Bitrate</th><th>Country</th></tr>'
if not rb_stations: if not rb_stations:
log.debug('cmd: No matches found for rbquery ' + parameter) log.debug(f"cmd: No matches found for rbquery {parameter}")
bot.send_msg('Radio-Browser found no matches for ' + parameter, text) bot.send_msg(f"Radio-Browser found no matches for {parameter}", text)
else: else:
for s in rb_stations: for s in rb_stations:
stationid = s['id'] station_id = s['stationuuid']
stationname = s['stationname'] station_name = s['name']
country = s['country'] country = s['countrycode']
codec = s['codec'] codec = s['codec']
bitrate = s['bitrate'] bitrate = s['bitrate']
genre = s['genre'] genre = s['tags']
# msg += f'<tr><td>{stationid}</td><td>{stationname}</td><td>{genre}</td><td>{codec}/{bitrate}</td><td>{country}</td></tr>' msg += f"<tr><td>{station_id}</td><td>{station_name}</td><td>{genre}</td><td>{codec}/{bitrate}</td><td>{country}</td></tr>"
msg += '<tr><td>%s</td><td>%s</td><td>%s</td><td>%s/%s</td><td>%s</td></tr>' % (
stationid, stationname, genre, codec, bitrate, country)
msg += '</table>' msg += '</table>'
# Full message as html table # Full message as html table
if len(msg) <= 5000: if len(msg) <= 5000:
@ -414,10 +411,9 @@ def cmd_rb_query(bot, user, text, command, parameter):
msg = constants.strings('rb_query_result') + ' (shortened L1)' msg = constants.strings('rb_query_result') + ' (shortened L1)'
msg += '\n<table><tr><th>!rbplay ID</th><th>Station Name</th></tr>' msg += '\n<table><tr><th>!rbplay ID</th><th>Station Name</th></tr>'
for s in rb_stations: for s in rb_stations:
stationid = s['id'] station_id = s['stationuuid']
stationname = s['stationname'] station_name = s['name']
# msg += f'<tr><td>{stationid}</td><td>{stationname}</td>' msg += f'<tr><td>{station_id}</td><td>{station_name}</td>'
msg += '<tr><td>%s</td><td>%s</td>' % (stationid, stationname)
msg += '</table>' msg += '</table>'
if len(msg) <= 5000: if len(msg) <= 5000:
bot.send_msg(msg, text) bot.send_msg(msg, text)
@ -427,16 +423,14 @@ def cmd_rb_query(bot, user, text, command, parameter):
msg = constants.strings('rb_query_result') + ' (shortened L2)' msg = constants.strings('rb_query_result') + ' (shortened L2)'
msg += '!rbplay ID - Station Name' msg += '!rbplay ID - Station Name'
for s in rb_stations: for s in rb_stations:
stationid = s['id'] station_id = s['stationuuid']
stationname = s['stationname'][:12] station_name = s['name'][:12]
# msg += f'{stationid} - {stationname}' msg += f'{station_id} - {station_name}'
msg += '%s - %s' % (stationid, stationname)
if len(msg) <= 5000: if len(msg) <= 5000:
bot.send_msg(msg, text) bot.send_msg(msg, text)
# Message still too long # Message still too long
else: else:
bot.send_msg('Query result too long to post (> 5000 characters), please try another query.', bot.send_msg('Query result too long to post (> 5000 characters), please try another query.', text)
text)
def cmd_rb_play(bot, user, text, command, parameter): def cmd_rb_play(bot, user, text, command, parameter):
@ -449,22 +443,21 @@ def cmd_rb_play(bot, user, text, command, parameter):
bot.send_msg(msg, text) bot.send_msg(msg, text)
else: else:
log.debug('cmd: Retreiving url for station ID ' + parameter) log.debug('cmd: Retreiving url for station ID ' + parameter)
rstation = radiobrowser.getstationname_byid(parameter) rb = RadioBrowser()
rstation = rb.station_by_uuid(parameter)
stationname = rstation[0]['name'] stationname = rstation[0]['name']
country = rstation[0]['country'] country = rstation[0]['countrycode']
codec = rstation[0]['codec'] codec = rstation[0]['codec']
bitrate = rstation[0]['bitrate'] bitrate = rstation[0]['bitrate']
genre = rstation[0]['tags'] genre = rstation[0]['tags']
homepage = rstation[0]['homepage'] homepage = rstation[0]['homepage']
url = rstation[0]['url']
msg = 'Radio station added to playlist:' msg = 'Radio station added to playlist:'
# msg += '<table><tr><th>ID</th><th>Station Name</th><th>Genre</th><th>Codec/Bitrate</th><th>Country</th><th>Homepage</th></tr>' + \
# f'<tr><td>{parameter}</td><td>{stationname}</td><td>{genre}</td><td>{codec}/{bitrate}</td><td>{country}</td><td>{homepage}</td></tr></table>'
msg += '<table><tr><th>ID</th><th>Station Name</th><th>Genre</th><th>Codec/Bitrate</th><th>Country</th><th>Homepage</th></tr>' + \ msg += '<table><tr><th>ID</th><th>Station Name</th><th>Genre</th><th>Codec/Bitrate</th><th>Country</th><th>Homepage</th></tr>' + \
'<tr><td>%s</td><td>%s</td><td>%s</td><td>%s/%s</td><td>%s</td><td>%s</td></tr></table>' \ f"<tr><td>{parameter}</td><td>{stationname}</td><td>{genre}</td><td>{codec}/{bitrate}</td><td>{country}</td><td>{homepage}</td></tr></table>"
% (parameter, stationname, genre, codec, bitrate, country, homepage) log.debug(f'cmd: Added station to playlist {stationname}')
log.debug('cmd: Added station to playlist %s' % stationname)
bot.send_msg(msg, text) bot.send_msg(msg, text)
url = radiobrowser.geturl_byid(parameter)
if url != "-1": if url != "-1":
log.info('cmd: Found url: ' + url) log.info('cmd: Found url: ' + url)
music_wrapper = get_cached_wrapper_from_scrap(type='radio', url=url, name=stationname, user=user) music_wrapper = get_cached_wrapper_from_scrap(type='radio', url=url, name=stationname, user=user)
@ -517,7 +510,7 @@ def cmd_yt_search(bot, user, text, command, parameter):
def _yt_format_result(results, start, count): def _yt_format_result(results, start, count):
msg = '<table><tr><th width="10%">Index</th><th>Title</th><th width="20%">Uploader</th></tr>' msg = '<table><tr><th width="10%">Index</th><th>Title</th><th width="20%">Uploader</th></tr>'
for index, item in enumerate(results[start:start+count]): for index, item in enumerate(results[start:start + count]):
msg += '<tr><td>{index:d}</td><td>{title}</td><td>{uploader}</td></tr>'.format( msg += '<tr><td>{index:d}</td><td>{title}</td><td>{uploader}</td></tr>'.format(
index=index + 1, title=item[1], uploader=item[2]) index=index + 1, title=item[1], uploader=item[2])
msg += '</table>' msg += '</table>'
@ -602,10 +595,9 @@ def cmd_volume(bot, user, text, command, parameter):
# The volume is a percentage # The volume is a percentage
if parameter and parameter.isdigit() and 0 <= int(parameter) <= 100: if parameter and parameter.isdigit() and 0 <= int(parameter) <= 100:
bot.volume_set = float(float(parameter) / 100) bot.volume_set = float(float(parameter) / 100)
bot.send_msg(constants.strings('change_volume', bot.send_msg(constants.strings('change_volume', volume=int(bot.volume_set * 100), user=bot.mumble.users[text.actor]['name']), text)
volume=int(bot.volume_set * 100), user=bot.mumble.users[text.actor]['name']), text)
var.db.set('bot', 'volume', str(bot.volume_set)) var.db.set('bot', 'volume', str(bot.volume_set))
log.info('cmd: volume set to %d' % (bot.volume_set * 100)) log.info(f'cmd: volume set to {bot.volume_set * 100}')
else: else:
bot.send_msg(constants.strings('current_volume', volume=int(bot.volume_set * 100)), text) bot.send_msg(constants.strings('current_volume', volume=int(bot.volume_set * 100)), text)
@ -618,8 +610,7 @@ def cmd_ducking(bot, user, text, command, parameter):
var.db.set('bot', 'ducking', True) var.db.set('bot', 'ducking', True)
bot.ducking_volume = var.config.getfloat("bot", "ducking_volume", fallback=0.05) bot.ducking_volume = var.config.getfloat("bot", "ducking_volume", fallback=0.05)
bot.ducking_threshold = var.config.getint("bot", "ducking_threshold", fallback=5000) bot.ducking_threshold = var.config.getint("bot", "ducking_threshold", fallback=5000)
bot.mumble.callbacks.set_callback(pymumble.constants.PYMUMBLE_CLBK_SOUNDRECEIVED, bot.mumble.callbacks.set_callback(pymumble.constants.PYMUMBLE_CLBK_SOUNDRECEIVED, bot.ducking_sound_received)
bot.ducking_sound_received)
bot.mumble.set_receive_sound(True) bot.mumble.set_receive_sound(True)
log.info('cmd: ducking is on') log.info('cmd: ducking is on')
msg = "Ducking on." msg = "Ducking on."
@ -639,10 +630,10 @@ def cmd_ducking_threshold(bot, user, text, command, parameter):
if parameter and parameter.isdigit(): if parameter and parameter.isdigit():
bot.ducking_threshold = int(parameter) bot.ducking_threshold = int(parameter)
var.db.set('bot', 'ducking_threshold', str(bot.ducking_threshold)) var.db.set('bot', 'ducking_threshold', str(bot.ducking_threshold))
msg = "Ducking threshold set to %d." % bot.ducking_threshold msg = f"Ducking threshold set to {bot.ducking_threshold}."
bot.send_msg(msg, text) bot.send_msg(msg, text)
else: else:
msg = "Current ducking threshold is %d." % bot.ducking_threshold msg = f"Current ducking threshold is {bot.ducking_threshold}."
bot.send_msg(msg, text) bot.send_msg(msg, text)
@ -652,11 +643,9 @@ def cmd_ducking_volume(bot, user, text, command, parameter):
# The volume is a percentage # The volume is a percentage
if parameter and parameter.isdigit() and 0 <= int(parameter) <= 100: if parameter and parameter.isdigit() and 0 <= int(parameter) <= 100:
bot.ducking_volume = float(float(parameter) / 100) bot.ducking_volume = float(float(parameter) / 100)
bot.send_msg(constants.strings('change_ducking_volume', bot.send_msg(constants.strings('change_ducking_volume', volume=int(bot.ducking_volume * 100), user=bot.mumble.users[text.actor]['name']), text)
volume=int(bot.ducking_volume * 100), user=bot.mumble.users[text.actor]['name']), text)
# var.db.set('bot', 'volume', str(bot.volume_set))
var.db.set('bot', 'ducking_volume', str(bot.ducking_volume)) var.db.set('bot', 'ducking_volume', str(bot.ducking_volume))
log.info('cmd: volume on ducking set to %d' % (bot.ducking_volume * 100)) log.info(f'cmd: volume on ducking set to {bot.ducking_volume * 100}')
else: else:
bot.send_msg(constants.strings('current_ducking_volume', volume=int(bot.ducking_volume * 100)), text) bot.send_msg(constants.strings('current_ducking_volume', volume=int(bot.ducking_volume * 100)), text)
@ -826,7 +815,7 @@ def cmd_mode(bot, user, text, command, parameter):
else: else:
var.db.set('playlist', 'playback_mode', parameter) var.db.set('playlist', 'playback_mode', parameter)
var.playlist = media.playlist.get_playlist(parameter, var.playlist) var.playlist = media.playlist.get_playlist(parameter, var.playlist)
log.info("command: playback mode changed to %s." % parameter) log.info(f"command: playback mode changed to {parameter}.")
bot.send_msg(constants.strings("change_mode", mode=var.playlist.mode, bot.send_msg(constants.strings("change_mode", mode=var.playlist.mode,
user=bot.mumble.users[text.actor]['name']), text) user=bot.mumble.users[text.actor]['name']), text)
if parameter == "random": if parameter == "random":
@ -878,8 +867,7 @@ def cmd_add_tag(bot, user, text, command, parameter):
if tags[0]: if tags[0]:
if index.isdigit() and 1 <= int(index) <= len(var.playlist): if index.isdigit() and 1 <= int(index) <= len(var.playlist):
var.playlist[int(index) - 1].add_tags(tags) var.playlist[int(index) - 1].add_tags(tags)
log.info("cmd: add tags %s to song %s" % (", ".join(tags), log.info(f"cmd: add tags {', '.join(tags)} to song {var.playlist[int(index) - 1].format_debug_string()}")
var.playlist[int(index) - 1].format_debug_string()))
bot.send_msg(constants.strings("added_tags", bot.send_msg(constants.strings("added_tags",
tags=", ".join(tags), tags=", ".join(tags),
song=var.playlist[int(index) - 1].format_title()), text) song=var.playlist[int(index) - 1].format_title()), text)
@ -888,8 +876,7 @@ def cmd_add_tag(bot, user, text, command, parameter):
elif index == "*": elif index == "*":
for item in var.playlist: for item in var.playlist:
item.add_tags(tags) item.add_tags(tags)
log.info("cmd: add tags %s to song %s" % (", ".join(tags), log.info(f"cmd: add tags {', '.join(tags)} to song {item.format_debug_string()}")
item.format_debug_string()))
bot.send_msg(constants.strings("added_tags_to_all", tags=", ".join(tags)), text) bot.send_msg(constants.strings("added_tags_to_all", tags=", ".join(tags)), text)
return return
@ -917,15 +904,14 @@ def cmd_remove_tag(bot, user, text, command, parameter):
if index.isdigit() and 1 <= int(index) <= len(var.playlist): if index.isdigit() and 1 <= int(index) <= len(var.playlist):
if tags[0] != "*": if tags[0] != "*":
var.playlist[int(index) - 1].remove_tags(tags) var.playlist[int(index) - 1].remove_tags(tags)
log.info("cmd: remove tags %s from song %s" % (", ".join(tags), log.info(f"cmd: remove tags {', '.join(tags)} from song {var.playlist[int(index) - 1].format_debug_string()}")
var.playlist[int(index) - 1].format_debug_string()))
bot.send_msg(constants.strings("removed_tags", bot.send_msg(constants.strings("removed_tags",
tags=", ".join(tags), tags=", ".join(tags),
song=var.playlist[int(index) - 1].format_title()), text) song=var.playlist[int(index) - 1].format_title()), text)
return return
else: else:
var.playlist[int(index) - 1].clear_tags() var.playlist[int(index) - 1].clear_tags()
log.info("cmd: clear tags from song %s" % (var.playlist[int(index) - 1].format_debug_string())) log.info(f"cmd: clear tags from song {var.playlist[int(index) - 1].format_debug_string()}")
bot.send_msg(constants.strings("cleared_tags", bot.send_msg(constants.strings("cleared_tags",
song=var.playlist[int(index) - 1].format_title()), text) song=var.playlist[int(index) - 1].format_title()), text)
return return
@ -934,14 +920,13 @@ def cmd_remove_tag(bot, user, text, command, parameter):
if tags[0] != "*": if tags[0] != "*":
for item in var.playlist: for item in var.playlist:
item.remove_tags(tags) item.remove_tags(tags)
log.info("cmd: remove tags %s from song %s" % (", ".join(tags), log.info(f"cmd: remove tags {', '.join(tags)} from song {item.format_debug_string()}")
item.format_debug_string()))
bot.send_msg(constants.strings("removed_tags_from_all", tags=", ".join(tags)), text) bot.send_msg(constants.strings("removed_tags_from_all", tags=", ".join(tags)), text)
return return
else: else:
for item in var.playlist: for item in var.playlist:
item.clear_tags() item.clear_tags()
log.info("cmd: clear tags from song %s" % (item.format_debug_string())) log.info(f"cmd: clear tags from song {item.format_debug_string()}")
bot.send_msg(constants.strings("cleared_tags_from_all"), text) bot.send_msg(constants.strings("cleared_tags_from_all"), text)
return return
@ -969,7 +954,7 @@ def cmd_find_tagged(bot, user, text, command, parameter):
count += 1 count += 1
if count > ITEMS_PER_PAGE: if count > ITEMS_PER_PAGE:
break break
msgs.append("<li><b>{:d}</b> - <b>{}</b> (<i>{}</i>)</li>".format(i+1, item.title, ", ".join(item.tags))) msgs.append("<li><b>{:d}</b> - <b>{}</b> (<i>{}</i>)</li>".format(i + 1, item.title, ", ".join(item.tags)))
if count != 0: if count != 0:
msgs.append("</ul>") msgs.append("</ul>")
@ -1210,7 +1195,7 @@ def cmd_web_user_add(bot, user, text, command, parameter):
if parameter not in web_users: if parameter not in web_users:
web_users.append(parameter) web_users.append(parameter)
var.db.set("privilege", "web_access", json.dumps(web_users)) var.db.set("privilege", "web_access", json.dumps(web_users))
bot.send_msg(constants.strings('web_user_list', users=", ". join(web_users)), text) bot.send_msg(constants.strings('web_user_list', users=", ".join(web_users)), text)
else: else:
bot.send_msg(constants.strings('command_disabled', command=command), text) bot.send_msg(constants.strings('command_disabled', command=command), text)
@ -1227,7 +1212,7 @@ def cmd_web_user_remove(bot, user, text, command, parameter):
if parameter in web_users: if parameter in web_users:
web_users.remove(parameter) web_users.remove(parameter)
var.db.set("privilege", "web_access", json.dumps(web_users)) var.db.set("privilege", "web_access", json.dumps(web_users))
bot.send_msg(constants.strings('web_user_list', users=", ". join(web_users)), text) bot.send_msg(constants.strings('web_user_list', users=", ".join(web_users)), text)
else: else:
bot.send_msg(constants.strings('command_disabled', command=command), text) bot.send_msg(constants.strings('command_disabled', command=command), text)
@ -1237,7 +1222,7 @@ def cmd_web_user_list(bot, user, text, command, parameter):
if auth_method == 'password': if auth_method == 'password':
web_users = json.loads(var.db.get("privilege", "web_access", fallback='[]')) web_users = json.loads(var.db.get("privilege", "web_access", fallback='[]'))
bot.send_msg(constants.strings('web_user_list', users=", ". join(web_users)), text) bot.send_msg(constants.strings('web_user_list', users=", ".join(web_users)), text)
else: else:
bot.send_msg(constants.strings('command_disabled', command=command), text) bot.send_msg(constants.strings('command_disabled', command=command), text)

View File

View File

@ -1,33 +0,0 @@
from librb.rbRadios import RadioBrowser
rb = RadioBrowser()
def getstations_byname(query):
results = rb.stations_byname(query)
stations = []
for st in results:
try:
station = {'stationname': st['name'], 'id': st['id'], 'codec': st['codec'], 'bitrate': st['bitrate'], 'country': st['country'], 'homepage': st['homepage'], 'genre': st['tags']}
stations.append(station)
except:
pass
return stations
def geturl_byid(id):
url = rb.playable_station(id)['url']
if url is not None:
return url
else:
return "-1"
def getstationname_byid(id):
return rb.stations_byid(id)
if __name__ == "__main__":
r = getstations_byname('r.sh')
stationinfo = getstationname_byid(96748)
pass

View File

@ -1,16 +0,0 @@
BASE_URL = "http://www.radio-browser.info/webservice/"
endpoints = {
"countries": {1: "{fmt}/countries", 2: "{fmt}/countries/{filter}"},
"codecs": {1: "{fmt}/codecs", 2: "{fmt}/codecs/{filter}"},
"states": {
1: "{fmt}/states",
2: "{fmt}/states/{filter}",
3: "{fmt}/states/{country}/{filter}",
},
"languages": {1: "{fmt}/languages", 2: "{fmt}/languages/{filter}"},
"tags": {1: "{fmt}/tags", 2: "{fmt}/tags/{filter}"},
"stations": {1: "{fmt}/stations", 3: "{fmt}/stations/{by}/{search_term}"},
"playable_station": {3: "{ver}/{fmt}/url/{station_id}"},
"station_search": {1: "{fmt}/stations/search"},
}

View File

@ -1,179 +0,0 @@
import requests
from librb.rbConstants import endpoints, BASE_URL
def request(endpoint, **kwargs):
fmt = kwargs.get("format", "json")
if fmt == "xml":
content_type = "application/%s" % fmt
else:
content_type = "application/%s" % fmt
headers = {"content-type": content_type, "User-Agent": "pyradios/dev"}
params = kwargs.get("params", {})
url = BASE_URL + endpoint
resp = requests.get(url, headers=headers, params=params)
if resp.status_code == 200:
if fmt == "xml":
return resp.text
return resp.json()
return resp.raise_for_status()
class EndPointBuilder:
def __init__(self, fmt="json"):
self.fmt = fmt
self._option = None
self._endpoint = None
@property
def endpoint(self):
return endpoints[self._endpoint][self._option]
def produce_endpoint(self, **parts):
self._option = len(parts)
self._endpoint = parts["endpoint"]
parts.update({"fmt": self.fmt})
return self.endpoint.format(**parts)
class RadioBrowser:
def __init__(self, fmt="json"):
self.fmt = fmt
self.builder = EndPointBuilder(fmt=self.fmt)
def countries(self, filter=""):
endpoint = self.builder.produce_endpoint(endpoint="countries")
return request(endpoint)
def codecs(self, filter=""):
endpoint = self.builder.produce_endpoint(endpoint="codecs")
return request(endpoint)
def states(self, country="", filter=""):
endpoint = self.builder.produce_endpoint(
endpoint="states", country=country, filter=filter
)
return request(endpoint)
def languages(self, filter=""):
endpoint = self.builder.produce_endpoint(endpoint="languages", filter=filter)
return request(endpoint)
def tags(self, filter=""):
endpoint = self.builder.produce_endpoint(endpoint="tags", filter=filter)
return request(endpoint)
def stations(self, **params):
endpoint = self.builder.produce_endpoint(endpoint="stations")
kwargs = {}
if params:
kwargs.update({"params": params})
return request(endpoint, **kwargs)
def stations_byid(self, id):
endpoint = self.builder.produce_endpoint(
endpoint="stations", by="byid", search_term=id
)
return request(endpoint)
def stations_byuuid(self, uuid):
endpoint = self.builder.produce_endpoint(
endpoint="stations", by="byuuid", search_term=uuid
)
return request(endpoint)
def stations_byname(self, name):
endpoint = self.builder.produce_endpoint(
endpoint="stations", by="byname", search_term=name
)
return request(endpoint)
def stations_bynameexact(self, nameexact):
endpoint = self.builder.produce_endpoint(
endpoint="stations", by="bynameexact", search_term=nameexact
)
return request(endpoint)
def stations_bycodec(self, codec):
endpoint = self.builder.produce_endpoint(
endpoint="stations", by="bycodec", search_term=codec
)
return request(endpoint)
def stations_bycodecexact(self, codecexact):
endpoint = self.builder.produce_endpoint(
endpoint="stations", by="bycodecexact", search_term=codecexact
)
return request(endpoint)
def stations_bycountry(self, country):
endpoint = self.builder.produce_endpoint(
endpoint="stations", by="bycountry", search_term=country
)
return request(endpoint)
def stations_bycountryexact(self, countryexact):
endpoint = self.builder.produce_endpoint(
endpoint="stations", by="bycountryexact", search_term=countryexact
)
return request(endpoint)
def stations_bystate(self, state):
endpoint = self.builder.produce_endpoint(
endpoint="stations", by="bystate", search_term=state
)
return request(endpoint)
def stations_bystateexact(self, stateexact):
endpoint = self.builder.produce_endpoint(
endpoint="stations", by="bystateexact", search_term=stateexact
)
return request(endpoint)
#
def stations_bylanguage(self, language):
endpoint = self.builder.produce_endpoint(
endpoint="stations", by="bylanguage", search_term=language
)
return request(endpoint)
def stations_bylanguageexact(self, languageexact):
endpoint = self.builder.produce_endpoint(
endpoint="stations", by="bylanguageexact", search_term=languageexact
)
return request(endpoint)
def stations_bytag(self, tag):
endpoint = self.builder.produce_endpoint(
endpoint="stations", by="bytag", search_term=tag
)
return request(endpoint)
def stations_bytagexact(self, tagexact):
endpoint = self.builder.produce_endpoint(
endpoint="stations", by="bytagexact", search_term=tagexact
)
return request(endpoint)
def playable_station(self, station_id):
endpoint = self.builder.produce_endpoint(
endpoint="playable_station", station_id=station_id, ver="v2"
)
return request(endpoint)
def station_search(self, params, **kwargs):
# http://www.radio-browser.info/webservice#Advanced_station_search
assert isinstance(params, dict), "params is not a dict"
kwargs["params"] = params
endpoint = self.builder.produce_endpoint(endpoint="station_search")
return request(endpoint, **kwargs)

View File

@ -35,7 +35,7 @@ class MumbleBot:
def __init__(self, args): def __init__(self, args):
self.log = logging.getLogger("bot") self.log = logging.getLogger("bot")
self.log.info("bot: botamusique version %s, starting..." % self.version) self.log.info(f"bot: botamusique version {self.version}, starting...")
signal.signal(signal.SIGINT, self.ctrl_caught) signal.signal(signal.SIGINT, self.ctrl_caught)
self.cmd_handle = {} self.cmd_handle = {}
self.volume_set = var.config.getfloat('bot', 'volume') self.volume_set = var.config.getfloat('bot', 'volume')
@ -184,8 +184,8 @@ class MumbleBot:
new_version = util.new_release_version() new_version = util.new_release_version()
if version.parse(new_version) > version.parse(self.version): if version.parse(new_version) > version.parse(self.version):
changelog = util.fetch_changelog() changelog = util.fetch_changelog()
self.log.info("update: new version %s found, current installed version %s." % (new_version, self.version)) self.log.info(f"update: new version {new_version} found, current installed version {self.version}.")
self.log.info("update: changelog: " + changelog) self.log.info(f"update: changelog: {changelog}")
changelog = changelog.replace("\n", "<br>") changelog = changelog.replace("\n", "<br>")
self.send_channel_msg(constants.strings('new_version_found', new_version=new_version, changelog=changelog)) self.send_channel_msg(constants.strings('new_version_found', new_version=new_version, changelog=changelog))
else: else:
@ -303,7 +303,7 @@ class MumbleBot:
except: except:
error_traceback = traceback.format_exc() error_traceback = traceback.format_exc()
error = error_traceback.rstrip().split("\n")[-1] error = error_traceback.rstrip().split("\n")[-1]
self.log.error("bot: command %s failed with error: %s\n" % (command_exc, error_traceback)) self.log.error(f"bot: command {command_exc} failed with error: {error_traceback}\n")
self.send_msg(constants.strings('error_executing_command', command=command_exc, error=error), text) self.send_msg(constants.strings('error_executing_command', command=command_exc, error=error), text)
def send_msg(self, msg, text): def send_msg(self, msg, text):
@ -406,7 +406,7 @@ class MumbleBot:
def async_download(self, item): def async_download(self, item):
th = threading.Thread( th = threading.Thread(
target=self._download, name="Prepare-" + item.id[:7], args=(item,)) target=self._download, name="Prepare-" + item.id[:7], args=(item,))
self.log.info("bot: start preparing item in thread: %s" % item.format_debug_string()) self.log.info(f"bot: start preparing item in thread: {item.format_debug_string()}")
th.daemon = True th.daemon = True
th.start() th.start()
return th return th
@ -441,7 +441,7 @@ class MumbleBot:
while self.thread and self.mumble.sound_output.get_buffer_size() > 0.5 and not self.exit: while self.thread and self.mumble.sound_output.get_buffer_size() > 0.5 and not self.exit:
# If the buffer isn't empty, I cannot send new music part, so I wait # If the buffer isn't empty, I cannot send new music part, so I wait
self._loop_status = 'Wait for buffer %.3f' % self.mumble.sound_output.get_buffer_size() self._loop_status = f'Wait for buffer {self.mumble.sound_output.get_buffer_size():.3f}'
time.sleep(0.01) time.sleep(0.01)
if self.thread: if self.thread:
@ -627,7 +627,7 @@ class MumbleBot:
self.song_start_at = -1 self.song_start_at = -1
if len(var.playlist) > 0: if len(var.playlist) > 0:
self.pause_at_id = var.playlist.current_item().id self.pause_at_id = var.playlist.current_item().id
self.log.info("bot: music paused at %.2f seconds." % self.playhead) self.log.info(f"bot: music paused at {self.playhead:.2f} seconds.")
def resume(self): def resume(self):
self.is_pause = False self.is_pause = False
@ -785,7 +785,7 @@ if __name__ == '__main__':
if playback_mode in ["one-shot", "repeat", "random", "autoplay"]: if playback_mode in ["one-shot", "repeat", "random", "autoplay"]:
var.playlist = media.playlist.get_playlist(playback_mode) var.playlist = media.playlist.get_playlist(playback_mode)
else: else:
raise KeyError("Unknown playback mode '%s'" % playback_mode) raise KeyError(f"Unknown playback mode '{playback_mode}'")
# ====================== # ======================
# Create bot instance # Create bot instance

View File

@ -8,3 +8,4 @@ mutagen
requests requests
packaging packaging
pymumble pymumble
pyradios

View File

@ -283,7 +283,7 @@
</div> </div>
</div> </div>
<div class="btn-group" role="group" class="mb-2"> <div class="btn-group mb-2" role="group">
<button type="submit" class="btn btn-secondary mr-1" onclick="addAllResults()"><i class="fas fa-plus" <button type="submit" class="btn btn-secondary mr-1" onclick="addAllResults()"><i class="fas fa-plus"
aria-hidden="true"></i> Add All aria-hidden="true"></i> Add All
</button> </button>
@ -553,6 +553,7 @@
<script src="static/js/bootstrap.min.js"></script> <script src="static/js/bootstrap.min.js"></script>
<script src="static/js/fontawesome.all.min.js"></script> <script src="static/js/fontawesome.all.min.js"></script>
<script src="static/js/custom.js"></script> <script src="static/js/custom.js"></script>
</div>
</body> </body>
</html> </html>