예제 #1
0
    def __init__(self):

        self.nombre_radios_pais = []
        self.url_radios_pais = []
        self.resultado_pais_busqueda_nombre = []
        self.resultado_pais_busqueda_numero = []
        self.resultado_pais_busqueda_abreviado = []

        self.nombre_busqueda_general_radio = []
        self.url_busqueda_general_radio = []

        self.nombre_idioma = []
        self.cantidad_idioma = []
        self.busqueda_nombre_idioma = []
        self.busqueda_cantidad_idioma = []

        self.nombre_tag = []
        self.cantidad_tag = []
        self.busqueda_nombre_tag = []
        self.busqueda_cantidad_tag = []

        self.paises_radio_español = []
        self.paises_radio_abreviado = []
        self.paises_numero_emisoras = []
        self.paises_numero_total_emisoras = ""

        self.rb = RadioBrowser()
        self.datos_pais = self.rb.countries()
예제 #2
0
def cmd_rb_play(bot, user, text, command, parameter):
    global log

    log.debug('cmd: Play a station by ID')
    if not parameter:
        log.debug('rbplay without parameter')
        msg = tr('rb_play_empty')
        bot.send_msg(msg, text)
    else:
        log.debug('cmd: Retreiving url for station ID ' + parameter)
        rb = RadioBrowser()
        rstation = rb.station_by_uuid(parameter)
        stationname = rstation[0]['name']
        country = rstation[0]['countrycode']
        codec = rstation[0]['codec']
        bitrate = rstation[0]['bitrate']
        genre = rstation[0]['tags']
        homepage = rstation[0]['homepage']
        url = rstation[0]['url']
        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>"
        log.debug(f'cmd: Added station to playlist {stationname}')
        bot.send_msg(msg, text)
        if url != "-1":
            log.info('cmd: Found url: ' + url)
            music_wrapper = get_cached_wrapper_from_scrap(type='radio', url=url, name=stationname, user=user)
            var.playlist.append(music_wrapper)
            log.info("cmd: add to playlist: " + music_wrapper.format_debug_string())
            bot.async_download_next()
        else:
            log.info('cmd: No playable url found.')
            msg += "No playable url found for this station, please try another station."
            bot.send_msg(msg, text)
예제 #3
0
	def __init__(self):

		self.nombre_radios_pais = []
		self.url_radios_pais = []
		self.resultado_pais_busqueda_nombre = []
		self.resultado_pais_busqueda_numero = []
		self.resultado_pais_busqueda_abreviado = []

		self.nombre_busqueda_general_radio = []
		self.url_busqueda_general_radio = []

		self.nombre_idioma = []
		self.cantidad_idioma = []
		self.busqueda_nombre_idioma = []
		self.busqueda_cantidad_idioma = []

		self.nombre_tag = []
		self.cantidad_tag = []
		self.busqueda_nombre_tag = []
		self.busqueda_cantidad_tag = []

		self.paises_radio_español = []
		self.paises_radio_abreviado = []
		self.paises_numero_emisoras = []
		self.paises_numero_total_emisoras = ""

		expire_after = timedelta(days=3)
		session = CachedSession(
			cache_name=os.path.join(globalVars.appArgs.configPath, "zRadio", "cache"),
			backend='sqlite',
			expire_after=expire_after)
		self.rb = RadioBrowser(session=session)
		self.datos_pais = self.rb.countries()
예제 #4
0
    def CPS_match_query_phrase(self, phrase):
        # Look for regex matches
        # Play (radio|station|stream) <data>
        match = re.search(self.translate_regex('radio'), phrase)
        try:
            data = re.sub(self.translate_regex('radio'), '', phrase)
            rb = RadioBrowser()
            stations = rb.search(name=data, bitrateMin='128')
            stations != []
            self.log.info('CPS Match (radio): ' + stations[0]['name'] + ' | ' +
                          stations[0]['url'])

            if match:
                return (stations[0]['name'], CPSMatchLevel.EXACT, {
                    "station": stations[0]["name"],
                    "url": stations[0]["url"],
                    "image": stations[0]['favicon']
                })
            else:
                return (stations[0]['name'], CPSMatchLevel.TITLE, {
                    "station": stations[0]["name"],
                    "url": stations[0]["url"],
                    "image": stations[0]['favicon']
                })
        except Exception:
            return None
예제 #5
0
def match_genre(phrase):
    """Takes the user utterance and attempts to match a genre of station,
    returning the most popular of that genre.

    :param phrase: User utterance
    :type phrase: str

    :return: A tuple containing the original phrase, the CPS.MatchLevel,
    and a dictionary containing the resolved stream URL.
    :rtype: tuple
    """
    # Strip 'a' and 'station' from phrases like 'Play a jazz station.'.
    stripped_phrase = phrase.lower().replace("a ", "").replace(" station", "")
    try:
        rb = RadioBrowser()
    except Exception as e:
        LOG.exception("Failed to load pyradios" + repr(e))
    LOG.info(f"Searching for a {stripped_phrase} station")
    results = rb.search(tag=stripped_phrase, order="votes")
    parsed = json.loads(json.dumps(results))

    if len(parsed) > 0:
        LOG.info(f"Found {parsed[0]['name']} ({parsed[0]['url_resolved']})")
        return phrase, CPSMatchLevel.EXACT, {"url": parsed[0]["url_resolved"]}
    else:
        match_station_name(phrase)
예제 #6
0
def cmd_rb_query(bot, user, text, command, parameter):
    global log

    log.info('cmd: Querying radio stations')
    if not parameter:
        log.debug('rbquery without parameter')
        msg = tr('rb_query_empty')
        bot.send_msg(msg, text)
    else:
        log.debug('cmd: Found query parameter: ' + parameter)
        rb = RadioBrowser()
        rb_stations = rb.search(name=parameter, name_exact=False)
        msg = tr('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>'
        if not rb_stations:
            log.debug(f"cmd: No matches found for rbquery {parameter}")
            bot.send_msg(f"Radio-Browser found no matches for {parameter}",
                         text)
        else:
            for s in rb_stations:
                station_id = s['stationuuid']
                station_name = s['name']
                country = s['countrycode']
                codec = s['codec']
                bitrate = s['bitrate']
                genre = s['tags']
                msg += f"<tr><td>{station_id}</td><td>{station_name}</td><td>{genre}</td><td>{codec}/{bitrate}</td><td>{country}</td></tr>"
            msg += '</table>'
            # Full message as html table
            if len(msg) <= 5000:
                bot.send_msg(msg, text)
            # Shorten message if message too long (stage I)
            else:
                log.debug('Result too long stage I')
                msg = tr('rb_query_result') + ' (shortened L1)'
                msg += '\n<table><tr><th>!rbplay ID</th><th>Station Name</th></tr>'
                for s in rb_stations:
                    station_id = s['stationuuid']
                    station_name = s['name']
                    msg += f'<tr><td>{station_id}</td><td>{station_name}</td>'
                msg += '</table>'
                if len(msg) <= 5000:
                    bot.send_msg(msg, text)
                # Shorten message if message too long (stage II)
                else:
                    log.debug('Result too long stage II')
                    msg = tr('rb_query_result') + ' (shortened L2)'
                    msg += '!rbplay ID - Station Name'
                    for s in rb_stations:
                        station_id = s['stationuuid']
                        station_name = s['name'][:12]
                        msg += f'{station_id} - {station_name}'
                    if len(msg) <= 5000:
                        bot.send_msg(msg, text)
                    # Message still too long
                    else:
                        bot.send_msg(
                            'Query result too long to post (> 5000 characters), please try another query.',
                            text)
예제 #7
0
def match_station_name(phrase):
    """Takes the user utterance and attempts to match a specific station

    :param phrase: User utterance
    :type phrase: str

    :return: A tuple containing the original phrase, the CPS.MatchLevel,
    and a dictionary containing the resolved stream URL.
    :rtype: tuple
    """
    numbers_regex = r"\b(one|two|three|four|five|six|seven|eight|nine)\b"
    try:
        rb = RadioBrowser()
    except Exception as e:
        LOG.exception("Failed to load pyradios" + repr(e))
    LOG.info(f"Searching for {phrase}")
    results = rb.search(name=phrase)
    parsed = json.loads(json.dumps(results))

    if len(parsed) > 0:
        # If an exatch match has been found return.
        LOG.info(f"Found {parsed[0]['name']} ({parsed[0]['url_resolved']})")
        return phrase, CPSMatchLevel.EXACT, {"url": parsed[0]["url_resolved"]}
    elif re.search(" [0-9]+ ", phrase):
        # If no match has been found, replace any digits (1,2,3) with text
        # (one, two, three) and repeat search.
        num = re.findall("[0-9]+", phrase)
        inf_eng = inflect.engine()
        for number in num:
            phrase = phrase.replace(num, inf_eng.number_to_words(number))
        match_station_name(phrase)
    elif re.search(numbers_regex, phrase):
        # As above but reversed: change strings to ints and repeat search.
        num = re.findall(numbers_regex, phrase)
        for number in num:
            phrase = phrase.replace(number, str(w2n.word_to_num(number)))
        match_station_name(phrase)
    else:
        return None
예제 #8
0
class Handler:
    def __init__(self):
        self.API = None
        self.response = None
        self.target_station = None

        self.API = RadioBrowser()

    def station_validator(self):
        if len(self.response) == 0:
            log.error("No stations found by the name")
            sys.exit(0)
        if len(self.response) > 1:
            log.info("Multiple stations found by the name")
            stations_name = ""
            for station in self.response:
                # stations_name = stations_name + "," + station["name"]
                log.info("name: {} | id: {} | country: {}".format(
                    station["name"], station["stationuuid"],
                    station["country"]))

            log.info(stations_name)
            sys.exit(0)
        if len(self.response) == 1:
            log.info("Station found: {}".format(self.response[0]["name"]))
            log.debug(self.response[0])
            self.target_station = self.response[0]
            self.API.click_counter(self.target_station["stationuuid"])

    def play_by_station_name(self, _name=None):
        print(_name)
        self.response = self.API.search(name=_name, name_exact=False)
        self.station_validator()

    def play_by_station_uuid(self, _uuid):
        print(_uuid)
        # Pyradios by default don't let you search by uuid
        # a trick is to call click_counter(uuid) directly to get the statioon info
        is_ok = "false"
        try:
            self.target_station = self.API.click_counter(_uuid)
            log.debug(self.target_station)
            is_ok = self.target_station["ok"]
        except Exception as e:
            log.error("Could not find a station by the UUID")
            sys.exit(0)

        self.API.search(name=self.target_station["name"], name_exact=True)
        # againg register a valid click
        if is_ok == "false":
            res = self.API.click_counter(self.target_station["stationuuid"])
            log.debug(res)
예제 #9
0
class Raspado_Radios():
    def __init__(self):

        self.nombre_radios_pais = []
        self.url_radios_pais = []
        self.resultado_pais_busqueda_nombre = []
        self.resultado_pais_busqueda_numero = []
        self.resultado_pais_busqueda_abreviado = []

        self.nombre_busqueda_general_radio = []
        self.url_busqueda_general_radio = []

        self.nombre_idioma = []
        self.cantidad_idioma = []
        self.busqueda_nombre_idioma = []
        self.busqueda_cantidad_idioma = []

        self.nombre_tag = []
        self.cantidad_tag = []
        self.busqueda_nombre_tag = []
        self.busqueda_cantidad_tag = []

        self.paises_radio_español = []
        self.paises_radio_abreviado = []
        self.paises_numero_emisoras = []
        self.paises_numero_total_emisoras = ""

        self.rb = RadioBrowser()
        self.datos_pais = self.rb.countries()

    def Paises_Español(self):
        claves = Raspado_Radios.keys_only(diccionario)
        valores = Raspado_Radios.values_only(diccionario)

        for i in range(len(self.datos_pais)):
            self.paises_radio_abreviado.append(self.datos_pais[i]["name"])

        for i in self.paises_radio_abreviado:
            try:
                indice = valores.index(i.upper())
                self.paises_radio_español.append(claves[indice])
            except:
                pass

    def Paises_Bandera(self):
        for i in range(len(self.datos_pais)):
            self.paises_radio_abreviado.append(self.datos_pais[i]["name"])

    def Paises_Cantidad_Emisoras(self):
        for i in range(len(self.datos_pais)):
            self.paises_numero_emisoras.append(
                self.datos_pais[i]["stationcount"])

    def Suma_Total_Emisoras_Paises(self):
        self.temporal = []
        for i in range(len(self.datos_pais)):
            self.temporal.append(self.datos_pais[i]["stationcount"])
        self.paises_numero_total_emisoras = 0
        for i in self.temporal:
            self.paises_numero_total_emisoras = self.paises_numero_total_emisoras + i

    def Actualizar_Pais(self):
        self.paises_radio_español = []
        self.paises_radio_abreviado = []
        self.paises_numero_emisoras = []
        self.paises_numero_total_emisoras = ""
        Raspado_Radios.Paises_Español(self)
        Raspado_Radios.Paises_Bandera(self)
        Raspado_Radios.Paises_Cantidad_Emisoras(self)
        Raspado_Radios.Suma_Total_Emisoras_Paises(self)

    def Buscar_Pais(self, valor):
        self.resultado_pais_busqueda_nombre = []
        self.resultado_pais_busqueda_numero = []
        self.resultado_pais_busqueda_abreviado = []
        for item in self.paises_radio_español:
            if valor.lower() in item.lower():
                self.resultado_pais_busqueda_nombre.append(item)

        for i in self.resultado_pais_busqueda_nombre:
            posicion = self.paises_radio_español.index(i)
            self.resultado_pais_busqueda_numero.append(
                self.paises_numero_emisoras[posicion])
            self.resultado_pais_busqueda_abreviado.append(
                self.paises_radio_abreviado[posicion])

    def Resultado_Paises(self, valor):
        datos_frame = self.rb.stations_by_countrycode(valor)
        self.nombre_radios_pais = []
        self.url_radios_pais = []
        for i in range(0, len(datos_frame)):
            self.nombre_radios_pais.append(datos_frame[i]["name"])
            self.url_radios_pais.append(datos_frame[i]["url"])

    def Buscar_Radio_General(self, valor, valor1=True):
        datos_frame = self.rb.search(name=valor, name_exact=valor1)
        self.nombre_busqueda_general_radio = []
        self.url_busqueda_general_radio = []
        for i in range(0, len(datos_frame)):
            self.nombre_busqueda_general_radio.append(datos_frame[i]["name"])
            self.url_busqueda_general_radio.append(datos_frame[i]["url"])

    def Resultado_Idioma(self):
        datos_lenguaje = self.rb.languages()
        self.nombre_idioma = []
        self.cantidad_idioma = []
        for i in range(len(datos_lenguaje)):
            self.nombre_idioma.append(datos_lenguaje[i]["name"])
            self.cantidad_idioma.append(datos_lenguaje[i]["stationcount"])

    def Buscar_Idioma(self, valor):
        datos_lenguaje = self.rb.languages()
        temp_name = []
        temp_count = []
        for i in range(len(datos_lenguaje)):
            temp_name.append(datos_lenguaje[i]["name"])
            temp_count.append(datos_lenguaje[i]["stationcount"])
        self.busqueda_nombre_idioma = []
        self.busqueda_cantidad_idioma = []
        for item in temp_name:
            if valor.lower() in item.lower():
                self.busqueda_nombre_idioma.append(item)
        for i in self.busqueda_nombre_idioma:
            posicion = temp_name.index(i)
            self.busqueda_cantidad_idioma.append(temp_count[posicion])

    def Resultado_Idioma_Global(self, valor):
        pandas_radio_lenguaje = self.rb.stations_by_language(valor)
        self.nombre_radios_pais = []
        self.url_radios_pais = []
        for i in range(0, len(pandas_radio_lenguaje)):
            self.nombre_radios_pais.append(pandas_radio_lenguaje[i]["name"])
            self.url_radios_pais.append(pandas_radio_lenguaje[i]["url"])

    def Resultado_Tag(self):
        datos_genero = self.rb.tags()
        self.nombre_tag = []
        self.cantidad_tag = []
        for i in range(len(datos_genero)):
            self.nombre_tag.append(datos_genero[i]["name"])
            self.cantidad_tag.append(datos_genero[i]["stationcount"])

    def Buscar_Tag(self, valor):
        datos_genero = self.rb.tags()
        temp_name = []
        temp_count = []
        for i in range(len(datos_genero)):
            temp_name.append(datos_genero[i]["name"])
            temp_count.append(datos_genero[i]["stationcount"])
        self.busqueda_nombre_tag = []
        self.busqueda_cantidad_tag = []
        for item in temp_name:
            if valor.lower() in item.lower():
                self.busqueda_nombre_tag.append(item)
        for i in self.busqueda_nombre_tag:
            posicion = temp_name.index(i)
            self.busqueda_cantidad_tag.append(temp_count[posicion])

    def Resultado_Tag_Global(self, valor):
        pandas_tag = self.rb.stations_by_tag(valor)
        self.nombre_radios_pais = []
        self.url_radios_pais = []
        for i in range(0, len(pandas_tag)):
            self.nombre_radios_pais.append(pandas_tag[i]["name"])
            self.url_radios_pais.append(pandas_tag[i]["url"])

    def saber_pais_conexion(self):
        url = 'http://ipinfo.io/json'
        response = urlopen(url)
        data = json.load(response)

        IP = data['ip']
        org = data['org']
        city = data['city']
        country = data['country']
        region = data['region']
        return country

    def load_obj(name):
        with open(name, 'rb') as f:
            return pickle.load(f)

    def save_obj(obj, name):
        with open(name, 'wb') as f:
            pickle.dump(obj, f, pickle.HIGHEST_PROTOCOL)

    def keys_only(flat_dict):
        return [k for k, v in flat_dict.items()]

    def values_only(flat_dict):
        return [v for k, v in flat_dict.items()]
예제 #10
0
from pyradios import RadioBrowser
rb = RadioBrowser()


def get_radio(radio_title):
    stantions = rb.stations_by_name(radio_title)
    if stantions == []:
        return {}
    stantion = sorted(stantions, key=lambda k: k['votes'], reverse=True)[0]
    return {
        "title": stantion['name'],
        "duration": "radio",
        "file": stantion['url_resolved'],
        "cover": stantion.get("favicon")
    }
예제 #11
0
    def __init__(self):
        self.API = None
        self.response = None
        self.target_station = None

        self.API = RadioBrowser()
예제 #12
0
def rb():
    return RadioBrowser(base_url=BASE_URL)
예제 #13
0
    def init(self, settings, q):
        self.module_path = os.path.dirname(os.path.abspath(__file__))

        try:
            lang = gettext.translation('pext_module_radio',
                                       localedir=os.path.join(
                                           self.module_path, 'locale'),
                                       languages=[settings['_locale']])
        except FileNotFoundError:
            lang = gettext.NullTranslations()
            print("No {} translation available for pext_module_radio".format(
                settings['_locale']))

        lang.install()

        self.rb = RadioBrowser()

        self.settings = settings
        self.q = q

        self.favourites = []
        try:
            with open(os.path.join(self.module_path, "_user_favourites.txt"),
                      "r") as favourites_file:
                for favourite in favourites_file:
                    self.favourites.append(favourite.strip())
        except IOError:
            pass

        self.cached = {
            'countries': {
                'time': 0
            },
            'codecs': {
                'time': 0
            },
            'languages': {
                'time': 0
            },
            'tags': {
                'time': 0
            }
        }

        self.cachedStations = {
            '_favourites': {
                'time': 0
            },
            'countries': {},
            'codecs': {},
            'languages': {},
            'tags': {},
            'topvote': {
                'time': 0
            },
            'topclick': {
                'time': 0
            },
            'lastclick': {
                'time': 0
            },
            'lastchange': {
                'time': 0
            }
        }

        self.nowPlaying = None

        if not which("ffplay"):
            self.q.put([
                Action.critical_error,
                _("ffplay is not installed, please install it.")
            ])
            return

        self._get_entries()
예제 #14
0
class Module(ModuleBase):
    def init(self, settings, q):
        self.module_path = os.path.dirname(os.path.abspath(__file__))

        try:
            lang = gettext.translation('pext_module_radio',
                                       localedir=os.path.join(
                                           self.module_path, 'locale'),
                                       languages=[settings['_locale']])
        except FileNotFoundError:
            lang = gettext.NullTranslations()
            print("No {} translation available for pext_module_radio".format(
                settings['_locale']))

        lang.install()

        self.rb = RadioBrowser()

        self.settings = settings
        self.q = q

        self.favourites = []
        try:
            with open(os.path.join(self.module_path, "_user_favourites.txt"),
                      "r") as favourites_file:
                for favourite in favourites_file:
                    self.favourites.append(favourite.strip())
        except IOError:
            pass

        self.cached = {
            'countries': {
                'time': 0
            },
            'codecs': {
                'time': 0
            },
            'languages': {
                'time': 0
            },
            'tags': {
                'time': 0
            }
        }

        self.cachedStations = {
            '_favourites': {
                'time': 0
            },
            'countries': {},
            'codecs': {},
            'languages': {},
            'tags': {},
            'topvote': {
                'time': 0
            },
            'topclick': {
                'time': 0
            },
            'lastclick': {
                'time': 0
            },
            'lastchange': {
                'time': 0
            }
        }

        self.nowPlaying = None

        if not which("ffplay"):
            self.q.put([
                Action.critical_error,
                _("ffplay is not installed, please install it.")
            ])
            return

        self._get_entries()

    def _cache_expired(self, cache):
        return cache['time'] < time.time() - 600

    def _entry_depth(self, text):
        if self._menu_to_type(text) in self.cached:
            return 2
        else:
            return 1

    def _menu_to_type(self, text):
        if text == _('Favourites'):
            return '_favourites'
        elif text == _('By Country'):
            return 'countries'
        elif text == _('By Codec'):
            return 'codecs'
        elif text == _('By Language'):
            return 'languages'
        elif text == _('By Tags'):
            return 'tags'
        elif text == _('By Votes'):
            return 'topvote'
        elif text == _('By Most Tune-Ins'):
            return 'topclick'
        elif text == _('By Most Recent Listener'):
            return 'lastclick'
        elif text == _('By Most Recent Change'):
            return 'lastchange'
        else:
            raise ValueError("Invalid text")

    def _get_stations_by_menu_type(self, search_type):
        if search_type == 'countries':
            return self.rb.countries()
        elif search_type == 'codecs':
            return self.rb.codecs()
        elif search_type == 'languages':
            return self.rb.languages()
        elif search_type == 'tags':
            return self.rb.tags()
        else:
            return self._search_stations_by_type(search_type)

    def _search_stations_by_type(self, search_type, search_term=None):
        if search_type == 'countries':
            return self.rb.stations_by_country(search_term, True)
        elif search_type == 'codecs':
            return self.rb.stations_by_codec(search_term, True)
        elif search_type == 'languages':
            return self.rb.stations_by_language(search_term, True)
        elif search_type == 'tags':
            return self.rb.stations_by_tag(search_term, True)
        elif search_type == 'topvote':
            return self.rb.stations(order='votes')
        elif search_type == 'topclick':
            return self.rb.stations(order='clickcount')
        elif search_type == 'lastclick':
            return self.rb.stations(order='clicktimestamp')
        elif search_type == 'lastchange':
            return self.rb.stations(order='lastchangetime')
        else:
            raise ValueError("Invalid type")

    def _get_entries(self):
        if self.favourites:
            self.q.put([Action.add_entry, _('Favourites')])
        self.q.put([Action.add_entry, _('By Country')])
        self.q.put([Action.add_entry, _('By Codec')])
        self.q.put([Action.add_entry, _('By Language')])
        self.q.put([Action.add_entry, _('By Tags')])
        self.q.put([Action.add_entry, _('By Votes')])
        self.q.put([Action.add_entry, _('By Most Tune-Ins')])
        self.q.put([Action.add_entry, _('By Most Recent Listener')])
        self.q.put([Action.add_entry, _('By Most Recent Change')])
        if self.settings['_api_version'] < [0, 11, 0] and self.nowPlaying:
            if self.nowPlaying['process']:
                self.q.put([Action.add_command, _('mute')])
            else:
                self.q.put([Action.add_command, _('unmute')])

            self.q.put([Action.add_command, _('stop')])
            self.q.put([Action.add_command, _('vote')])

    def _get_list(self, path):
        self.q.put([Action.replace_entry_list, []])

        if self._cache_expired(self.cached[path]):
            self.cached[path] = {
                'time': time.time(),
                'data': self._get_stations_by_menu_type(path)
            }

        for entry in self.cached[path]['data']:
            self.q.put([
                Action.add_entry,
                _('{} ({} stations)').format(entry['name'],
                                             entry['stationcount'])
            ])

    def _get_stations(self, search_type, search_term):
        if search_type == '_favourites':
            if self._cache_expired(self.cachedStations[search_type]):
                data = []
                for favourite in self.favourites:
                    station_data = self.rb.station_by_uuid(favourite)
                    if station_data:
                        data.append(station_data[0])

                self.cachedStations[search_type] = {
                    'time': time.time(),
                    'data': data
                }

            return self.cachedStations[search_type]

        if search_term:
            if search_term not in self.cachedStations[
                    search_type] or self._cache_expired(
                        self.cachedStations[search_type][search_term]):
                self.cachedStations[search_type][search_term] = {
                    'time': time.time(),
                    'data':
                    self._search_stations_by_type(search_type, search_term)
                }

            return self.cachedStations[search_type][search_term]

        if self._cache_expired(self.cachedStations[search_type]):
            self.cachedStations[search_type] = {
                'time': time.time(),
                'data': self._search_stations_by_type(search_type)
            }

        return self.cachedStations[search_type]

    def _list_stations(self, search_type, search_term):
        self.q.put([Action.replace_entry_list, []])

        cache = self._get_stations(search_type, search_term)

        for entry in cache['data']:
            self.q.put([Action.add_entry, entry['name']])
            if self.settings['_api_version'] >= [0, 3, 1]:
                self.q.put([
                    Action.set_entry_info, entry['name'],
                    _("<b>{}</b><br/><br/><b>Bitrate: </b>{} kbps<br/><b>Codec: </b>{}<br/><b>Language: </b>{}<br/><b>Location: </b>{}<br/><b>Tags: </b>{}<br/><b>Homepage: </b><a href='{}'>{}</a>"
                      ).format(
                          html.escape(entry['name']),
                          html.escape(str(entry['bitrate'])),
                          html.escape(entry['codec']),
                          html.escape(entry['language']),
                          "{}, {}".format(html.escape(entry['state']),
                                          html.escape(entry['country']))
                          if entry['state'] else html.escape(entry['country']),
                          html.escape(", ".join(entry['tags'].split(","))
                                      if entry['tags'] else "None"),
                          html.escape(entry['homepage']),
                          html.escape(entry['homepage']))
                ])
            if self.settings['_api_version'] >= [
                    0, 6, 0
            ] and search_type == '_favourites':
                self.q.put([
                    Action.set_entry_context, entry['name'],
                    [_("Unfavourite")]
                ])

    def _play_station(self, byType, searchTerm, stationName):
        self._stop_playing()

        if searchTerm:
            cache = self.cachedStations[byType][searchTerm]
        else:
            cache = self.cachedStations[byType]

        for station in cache['data']:
            if station['name'] == stationName:
                station_uuid = station['stationuuid']
                station_info = station
                break

        response = self.rb.click_counter(station_uuid)

        if response['ok'] == 'false':
            self.q.put([Action.add_error, response['message']])
            return False

        # TODO: Replace ffplay with something more easily scriptable that
        # preferably notifies us of song changes on the station.
        self.nowPlaying = {
            'id': station_uuid,
            'name': stationName,
            'url': response['url'],
            'process': None
        }

        if self.settings['_api_version'] >= [0, 6, 0]:
            self.q.put([
                Action.set_base_info,
                _("<b>Tuned into:</b><br/>{}<br/><br/><b>Bitrate: </b>{} kbps<br/><b>Codec: </b>{}<br/><b>Language: </b>{}<br/><b>Location: </b>{}<br/><b>Tags: </b>{}<br/><b>Homepage: </b><a href='{}'>{}</a>"
                  ).format(
                      html.escape(station_info['name']),
                      html.escape(str(station_info['bitrate'])),
                      html.escape(station_info['codec']),
                      html.escape(station_info['language']),
                      "{}, {}".format(html.escape(station_info['state']),
                                      html.escape(station_info['country']))
                      if station_info['state'] else html.escape(
                          station_info['country']),
                      html.escape(", ".join(station_info['tags'].split(","))
                                  if station_info['tags'] else "None"),
                      html.escape(station_info['homepage']),
                      html.escape(station_info['homepage']))
            ])

        self._toggle_mute()

        return True

    def _toggle_mute(self):
        """Toggle mute.

        While this function technically disconnects or connects to the
        station, instead of just muting, it is simpler code-wise and has
        the added benefit of saving bandwidth.

        TODO: Replace this with an actual mute function.
        """
        if self.nowPlaying:
            if self.nowPlaying['process']:
                os.kill(self.nowPlaying['process'].pid, SIGTERM)
                self.nowPlaying['process'] = None
                self.q.put([
                    Action.set_header,
                    _('Tuned into {} (muted)').format(self.nowPlaying['name'])
                ])
                if self.settings['_api_version'] >= [0, 6, 0]:
                    self.q.put([
                        Action.set_base_context,
                        [_("Unmute"),
                         _("Stop"),
                         _("Favourite"),
                         _("Vote up")]
                    ])
            else:
                self.q.put([
                    Action.set_header,
                    _('Tuned into {}').format(self.nowPlaying['name'])
                ])
                self.nowPlaying['process'] = Popen([
                    'ffplay', '-nodisp', '-nostats', '-loglevel', '0',
                    self.nowPlaying['url']
                ])
                if self.settings['_api_version'] >= [0, 6, 0]:
                    self.q.put([
                        Action.set_base_context,
                        [_("Mute"),
                         _("Stop"),
                         _("Favourite"),
                         _("Vote up")]
                    ])

    def _stop_playing(self):
        if self.nowPlaying:
            if self.nowPlaying['process']:
                os.kill(self.nowPlaying['process'].pid, SIGTERM)
            self.nowPlaying = None
            self.q.put([Action.set_header])
            if self.settings['_api_version'] >= [0, 6, 0]:
                self.q.put([Action.set_base_info])
                self.q.put([Action.set_base_context])

    def _add_to_favourites(self, station_id):
        with open(os.path.join(self.module_path, "_user_favourites.txt"),
                  "a") as favourites_file:
            favourites_file.write('{}\n'.format(station_id))
            self.favourites.append(station_id)
            self.cachedStations['_favourites'] = {'time': 0}

    def _remove_from_favourites(self, station_name):
        for station in self._get_stations('_favourites', '')['data']:
            if station['name'] == station_name:
                self.favourites.remove(station['stationuuid'])
                with open(
                        os.path.join(self.module_path, "_user_favourites.txt"),
                        "w") as favourites_file:
                    for favourite in self.favourites:
                        favourites_file.write('{}\n'.format(favourite))

                self.cachedStations['_favourites'] = {'time': 0}
                return

        self.q.put([
            Action.add_error,
            _('Could not find {} in favourites').format(station_name)
        ])

    def _vote_station(self):
        result = self.rb.client.get('vote/{}'.format(self.nowPlaying['id']))
        if result['ok']:
            self.q.put([
                Action.add_message,
                _('Voted for station {}').format(self.nowPlaying['name'])
            ])
        else:
            self.q.put([
                Action.add_error,
                _('Failed to vote for {}: {}').format(self.nowPlaying['name'],
                                                      result['message'])
            ])

    def stop(self):
        self._stop_playing()

    def selection_made(self, selection):
        if self.settings['_api_version'] >= [
                0, 6, 0
        ] and len(selection) > 0 and selection[-1]['context_option']:
            if selection[-1]['type'] == SelectionType.none:
                if selection[-1]['context_option'] in [_('Mute'), _('Unmute')]:
                    self._toggle_mute()
                elif selection[-1]['context_option'] == _('Stop'):
                    self._stop_playing()
                elif selection[-1]['context_option'] == _('Favourite'):
                    self._add_to_favourites(self.nowPlaying['id'])
                elif selection[-1]['context_option'] == _('Vote up'):
                    self._vote_station()
            elif selection[-1]['context_option'] == _("Unfavourite"):
                self._remove_from_favourites(selection[-1]['value'])
                if not self.favourites:
                    self.q.put([Action.set_selection, []])
                    return

            self.q.put([Action.set_selection, selection[:-1]])
            return

        self.q.put([Action.replace_command_list, []])
        if len(selection) == 0:
            self.q.put([Action.replace_entry_list, []])
            self._get_entries()
        elif len(selection) == 1:
            # Force station list when no subcategories
            if self._entry_depth(selection[0]['value']) == 1:
                self._list_stations(self._menu_to_type(selection[0]['value']),
                                    '')
                return

            menu_text = selection[0]['value']
            self._get_list(self._menu_to_type(menu_text))
        elif len(selection) == 2:
            # Force playing when no subcategories
            if self._entry_depth(selection[0]['value']) == 1:
                if self._play_station(
                        self._menu_to_type(selection[0]['value']), '',
                        selection[1]['value']):
                    self.q.put([Action.close])
                else:
                    self.q.put([Action.set_selection, selection[:-1]])

                return

            # Remove station count from search term
            search_term = selection[1]['value'][:selection[1]['value'].
                                                rfind('(')].rstrip()

            self._list_stations(self._menu_to_type(selection[0]['value']),
                                search_term)
        elif len(selection) == 3:
            # Remove station count from search term
            search_term = selection[1]['value'][:selection[1]['value'].
                                                rfind('(')].rstrip()

            if self._play_station(self._menu_to_type(selection[0]['value']),
                                  search_term, selection[2]['value']):
                self.q.put([Action.close])
            else:
                self.q.put([Action.set_selection, selection[:-1]])
        else:
            self.q.put([
                Action.critical_error,
                _('Unexpected selection_made value: {}').format(selection)
            ])

    def process_response(self, response):
        pass
예제 #15
0
def rb():
    _rb = RadioBrowser()
    return _rb
예제 #16
0
def rb():
    _rb = RadioBrowser()
    _rb.base_url = BASE_URL
    return _rb