def get_channels(self, url):
        cache = Cache(self.__settings['path'], minutes=180)
        epg = EPG(self.__settings)

        # Busca los canales en cache
        channels = cache.load(url)
        if channels:
            # Actualiza la EPG de los canales
            epg.update_metadata(channels)
            return channels

        # No están en cache, los obtiene
        channels = []

        # GET url
        page = tools.get_web_page(url)

        # Obtiene los nombres y urls de los canales
        chs = re.findall(r'#EXTINF:.*,(.*)<br\s/>\s(http[s]?://.*)<', page,
                         re.U)
        if not chs:
            raise WebSiteError(
                u'Problema en Movistar+',
                u'No se han encontrado canales en la lista seleccionada',
                time=self.__settings['notify_secs'])

        # Añade los canales encontrados a la lista
        for ch in chs:
            ch_name = tools.str_sanitize(ch[0])
            ch_link = tools.str_sanitize(ch[1])
            if not (ch_link.endswith('.m3u8') or ch_link.endswith('.m3u')):
                channels.append({
                    'name':
                    ch_name,
                    'video':
                    ch_link,
                    'icon':
                    tools.build_path(
                        self.__settings['path'],
                        'bein.png' if self.__sports else 'movistar.png'),
                    'fanart':
                    tools.build_path(
                        self.__settings['path'], 'bein_art.jpg'
                        if self.__sports else 'movistar_art.jpg')
                })

        if len(channels) == 0:
            raise WebSiteError(
                u'No hay canales',
                u'La lista no contiene canales que se puedan reproducir',
                time=self.__settings['notify_secs'])

        # Añade la EPG a los canales
        if not self.__sports:
            epg.add_metadata(channels)

        # Guarda los canales en caché y los devuelve
        cache.save(url, channels)
        return channels
    def get_menu(self):
        """
        Get MovistarTV channel lists

        :return: The list of MovistarTV channel lists
        :rtype: list
        """
        cache = Cache(self.__settings['path'], minutes=60)

        # Busca las listas de canales en cache
        ch_lists = cache.load(
            self.__sports_url if self.__sports else self.__channels_url)
        if ch_lists:
            return ch_lists

        # No están en cache, los obtiene
        ch_lists = []

        # GET http://iptv.filmover.com/category/spain/
        page = tools.get_web_page(
            self.__sports_url if self.__sports else self.__channels_url)

        # Busca todas URL de listas de canales
        # Una por día, la primera es la lista más reciente
        urls = re.findall(
            r'<h2\s*class="entry-tit.*le">\s*<a href="(.*)"\s*rel="bookmark">(.*)</a></h2>',
            page, re.U)
        if not (urls and type(urls) == list and len(urls) > 0):
            raise WebSiteError(u'Lista de canales no encontrada',
                               u'Los de Movistar+ han hecho cambios en la Web',
                               time=self.__settings['notify_secs'])

        for url in urls:
            ch_lists.append({
                'name':
                tools.str_sanitize(url[1]),
                'channel_url':
                tools.str_sanitize(url[0]),
                'icon':
                tools.build_path(
                    self.__settings['path'],
                    'bein.png' if self.__sports else 'movistar.png'),
                'fanart':
                tools.build_path(
                    self.__settings['path'],
                    'bein_art.jpg' if self.__sports else 'movistar_art.jpg')
            })

        if len(ch_lists) == 0:
            raise WebSiteError(
                u'Problema en Movistar+',
                u'No se han encontrado listas de canales en la Web',
                time=self.__settings['notify_secs'])

        cache.save(self.__sports_url if self.__sports else self.__channels_url,
                   ch_lists)
        return ch_lists
Пример #3
0
    def __get_all_events(self):
        """
        Get all Torrent-TV.ru events

        :return: The list of Torrent-TV.ru events
        :rtype: list
        """
        cache = Cache(self.__settings['path'])

        # Busca la agenda en cache
        events = cache.load(self.__agenda_url)
        if events:
            return events

        # No está en cache, la obtiene
        events = []

        # GET http://super-pomoyka.us.to/trash/ttv-list/ttv.json
        channels = tools.get_web_page(self.__agenda_url)

        # Busca todas las etiquetas name, url y cat
        # y las guarda en una lista de tuplas ('etiqueta', 'valor')
        data = re.findall(r'(name|url|cat)":"([^"]*)"', channels, re.U)
        if not (data and type(data) == list and len(data) > 0):
            raise WebSiteError(
                u'Lista de canales no encontrada',
                u'Los de TorrentTV.ru han hecho cambios en la Web',
                time=self.__settings['notify_secs'])

        # Recorre la lista de 3 en 3
        for x in range(0, len(data) / 3):
            name = data[x * 3][1]
            url = data[x * 3 + 1][1]
            cat = data[x * 3 + 2][1]
            events.append({'name': name, 'url': url, 'cat': cat})

        if len(events) == 0:
            raise WebSiteError(u'Problema en TorrentTV',
                               u'No hay canales o no hay enlaces en la Web',
                               time=self.__settings['notify_secs'])

        cache.save(self.__agenda_url, events)
        return events
def get_hashlink(url, settings, minutes=10):
    # ¿La URL contiene el hashlink?
    if 'http' not in url:
        ace_hash = re.findall(r'([a-f0-9]{40})', url, re.U)
        if ace_hash:
            return url[12:]
        else:
            write_log("URL mal formada: '%s'" % url, xbmc.LOGERROR)
            raise WebSiteError(u'Enlace mal formado',
                               u'Puede que hayan hecho cambios en la Web',
                               time=settings['notify_secs'])

    # Busca el hash en cache
    cache = Cache(settings['path'], minutes=minutes)
    c_hash = cache.load(url)
    if c_hash:
        return c_hash['hash']

    # No está en cache, lo obtiene
    page = get_web_page(url)

    # Busca el hash de acestream
    ace_hash = find_hash(page)
    if not ace_hash:
        # No lo ha encontrado, busca una URL que pueda contener el hash
        hash_url = find_hash_url(page)
        if hash_url:
            # Hay URL, busca el hash en la nueva página
            page = get_web_page(hash_url)
            ace_hash = find_hash(page)

    if not ace_hash:
        write_log("Hashlink no encontrado en '%s'" % url, xbmc.LOGERROR)
        raise WebSiteError(
            u'Enlace no encontrado',
            u'El enlace está en otra página y no se puede llegar a él',
            time=settings['notify_secs'])

    # Guarda el hash en caché
    cache.save(url, {"hash": ace_hash})

    return ace_hash
Пример #5
0
    def get_channels(self, name, date, time):
        """
        Get Arenavision event channels by a given event name, date and time

        :param name: The event name
        :type: name: str
        :param date: The event date
        :type: date: str
        :param time: The event time
        :type: time: str
        :return: The list of Arenavision event channels
        :rtype: list
        """
        events = self.get_all_events()

        for event in events:
            if name.decode('utf-8') == event['name'] and date == event[
                    'date'] and time == event['time']:
                if len(event['channels']) == 0:
                    raise WebSiteError(u'Problema en la agenda',
                                       u'No hay enlaces para %s' %
                                       event['name'],
                                       time=self.__settings['notify_secs'])
                return event['channels']
Пример #6
0
    def get_all_events(self):
        """
        Get all Arenavision events

        :return: The list of Arenavision events
        :rtype: list
        """
        cache = Cache(self.__settings['path'])

        # Busca la URI de la agenda y los enlaces de los canales en caché
        page = cache.load(self.web_url, False)
        if page:
            # La URI de la agenda está en caché, busca también los eventos
            events = cache.load(page['agenda'])
            if events:
                for event in events:
                    event['name'] = self.__get_event_name(
                        event['event'], event['date'], event['time'],
                        event['competition'])
                return events

        # La URI de la agenda y los enlaces no están en cache
        # Vuelve a obtener la agenda, los enlaces a los canales y los eventos
        events = []

        # GET arenavision.in
        page = tools.get_web_page(self.web_url)

        # Averigua la URI de la agenda y los enlaces de los canales
        # buscando en todas las URL de la página principal:
        # 'av*1' para los canales AV1, AV2...
        # 'sc' para la agenda
        urls = self.__get_urls(page)
        if not urls:
            raise WebSiteError(
                u'Agenda no encontrada',
                u'Los de Arenavision han hecho cambios en la Web',
                time=self.__settings['notify_secs'])

        # Guarda la URI de la agenda y los enlaces de los canales en caché
        cache.save(self.web_url, urls)

        # GET agenda
        agenda = tools.get_web_page(urls['agenda'])

        # Obtiene la tabla de eventos
        soup = BeautifulSoup(agenda, 'html5lib')
        table = soup.find('table', attrs={'class': 'auto-style1'})

        for row in table.findAll("tr")[1:-2]:
            cells = row.findAll("td")
            links = self.__get_links(tools.str_sanitize(cells[5].get_text()),
                                     urls['channels'])
            if links and len(links) > 0:
                time_e = re.findall(r'([0-2][0-9]:[0-5][0-9])',
                                    cells[1].get_text(), re.U)
                time_e = time_e[0] if time_e else '00:00'
                competition_art = self.__get_competition_art(
                    cells[2].get_text(), cells[3].get_text())
                events.append({
                    'date':
                    tools.str_sanitize(cells[0].get_text()),
                    'time':
                    tools.str_sanitize(time_e),
                    'sport':
                    tools.str_sanitize(cells[2].get_text()),
                    'competition':
                    tools.str_sanitize(cells[3].get_text()),
                    'event':
                    tools.str_sanitize(cells[4].get_text()),
                    'channels':
                    links,
                    'name':
                    self.__get_event_name(
                        tools.str_sanitize(cells[4].get_text()),
                        tools.str_sanitize(cells[0].get_text()),
                        tools.str_sanitize(time_e),
                        tools.str_sanitize(cells[3].get_text())),
                    'icon':
                    competition_art['icon'],
                    'fanart':
                    competition_art['fanart']
                })

        if len(events) == 0:
            raise WebSiteError(u'Problema en la agenda',
                               u'No hay eventos, ve a la Web y compruébalo',
                               time=self.__settings['notify_secs'])

        # Guarda los eventos en caché
        cache.save(urls['agenda'], events)

        return events
def get_web_page(url, cfduid=None, cookie=None, agent=None):
    try:
        req = urllib2.Request(url)
        user_agent = agent if agent else random_agent()
        req.add_header('User-Agent', user_agent)
        if cookie or cfduid:
            req.add_header('Host', url.split('/')[2])
            req.add_header('Connection', 'keep-alive')
            req.add_header('Cache-Control', 'max-age=0')
            req.add_header('Upgrade-Insecure-Requests', 1)
            req.add_header(
                'Accept',
                'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8'
            )
            req.add_header('DNT', 1)
            req.add_header('Referer', url)
            req.add_header('Accept-Language', 'es-ES,es;q=0.8')
            req.add_header('Cookie', cookie if cookie else cfduid)
        response = urllib2.urlopen(req)
        headers = response.headers.dict
        content = response.read().decode(
            response.headers.getparam('charset') or 'utf-8')
        response.close()
        if response.getcode() == 200:
            if not cookie and 'server' in headers and 'cloudflare' in headers[
                    'server']:
                write_log('GET %i CloudFlare %s' % (response.getcode(), url))
                cfduid = re.findall(r'__cfduid=[\w\d]+', headers['set-cookie'],
                                    re.U)
                cookie = re.findall(r'document.cookie=[\'"]?([^;,\'" ]+)',
                                    content, re.U)
                if not cfduid or not cookie:
                    return content
                return get_web_page(url, cfduid[0],
                                    '%s; %s' % (cfduid[0], cookie[0]),
                                    user_agent)
            else:
                write_log('GET %i %s' % (response.getcode(), url))
                return content
        else:
            raise urllib2.HTTPError
    except urllib2.HTTPError, e:
        if e.code == 404:
            write_log('HTTPError 404 on GET %s' % url, xbmc.LOGERROR)
            raise WebSiteError(
                u'La página no existe',
                u'Seguramente estén actualizando la agenda. Inténtalo más tarde...',
                time=5000)
        cf = Cloudflare({
            'url':
            url,
            'data':
            e.read().decode(e.headers.getparam('charset') or 'utf-8'),
            'headers':
            e.headers.dict
        })
        if cf.is_cloudflare:
            return get_web_page(cf.get_auth_url(), cf.get_cfduid())
        else:
            write_log('HTTPError %i on GET %s' % (e.code, url), xbmc.LOGERROR)
            raise WebSiteError(u'Error de conexión',
                               u'La web se ha caído, inténtalo en otra',
                               time=5000)
            'data':
            e.read().decode(e.headers.getparam('charset') or 'utf-8'),
            'headers':
            e.headers.dict
        })
        if cf.is_cloudflare:
            return get_web_page(cf.get_auth_url(), cf.get_cfduid())
        else:
            write_log('HTTPError %i on GET %s' % (e.code, url), xbmc.LOGERROR)
            raise WebSiteError(u'Error de conexión',
                               u'La web se ha caído, inténtalo en otra',
                               time=5000)
    except urllib2.URLError, e:
        write_log('URL error on GET %s: %s' % (url, e), xbmc.LOGERROR)
        raise WebSiteError(
            u'Error de conexión',
            u'No hay conexión a Internet o la Web ya no existe...',
            time=5000)
    except ValueError, e:
        write_log(
            'Value error on GET %s: %s -> %s' %
            (url, e, traceback.format_exc()), xbmc.LOGERROR)
        raise WebSiteError(
            u'URL mal formada',
            u'Han hecho cambios en la Web, inténtalo en otra...',
            time=5000)


def get_hashlink(url, settings, minutes=10):
    # ¿La URL contiene el hashlink?
    if 'http' not in url:
        ace_hash = re.findall(r'([a-f0-9]{40})', url, re.U)
Пример #9
0
    def get_channels(self, event_url):
        """
        Get LiveFootbalLOL channels by a given event URL

        :param event_url: The event URL
        :type: event_url: str
        :return: The list of LiveFootbalLOL event links
        :rtype: list
        """
        cache = Cache(self.__settings['path'], minutes=10)

        # Monta la URL del evento
        e_url = '%s%s' % (self.__web_url[:-1] if event_url.startswith('/') else
                          self.__web_url, event_url)

        # Busca los canales del evento en caché
        channels = cache.load(e_url, True)
        if channels:
            return channels

        # Los datos de los canales no están en cache
        # Vuelve a obtenerlos
        channels = []

        # GET e_url
        page = tools.get_web_page(e_url)

        # Busca la jornada
        # match_week = re.findall(r'[Mm][Aa][Tt][Cc][Hh]\s[Ww][Ee]{2}[Kk]</td>\s*<td>([0-9]+)</td>', page, re.U)

        # Obtiene la tabla de datos de los canales
        soup = BeautifulSoup(page, 'html5lib')
        table = soup.find(
            'table',
            attrs={'class': 'uk-table uk-table-hover uk-table-striped'})

        # Obtiene los datos de los canales
        prev_lang = None
        for row in table.findAll("tr")[2:]:
            cells = row.findAll("td")

            # Obtiene los datos generales del canal
            ch_name = tools.str_sanitize(cells[1].get_text())
            ch_lang = tools.str_sanitize(cells[0].get_text())

            # ¿Hay ya enlaces?
            if 'will be here' in ch_name:
                match = re.findall(
                    r'[Mm][Aa][Tt][Cc][Hh]</td>\s*<td><strong>(.*)</strong></td>',
                    page, re.U)
                if len(channels) > 0:
                    break
                else:
                    raise WebSiteError(
                        match[0] if match else u'LiveFootbalLOL',
                        u'Todavía no se han publicado los enlaces del partido',
                        time=self.__settings['notify_secs'])

            # Si no es un enlace acestream continua
            ch_link = tools.str_sanitize(cells[1].find('a').get('href'))
            if not ch_link or 'acestream' not in ch_name.lower():
                continue

            # Obtiene el idioma
            if not ch_lang or not re.findall(r'(\[[A-Z]{2}\])', ch_lang, re.U):
                ch_lang = prev_lang if prev_lang else '[--]'
            prev_lang = ch_lang if ch_lang else '[--]'

            # Obtiene los datos extendidos y los hashlinks del canal
            channel_data = self.__get_channel_data(cache, ch_link)
            if channel_data:
                for link in channel_data['links']:
                    channels.append({
                        'name':
                        self.__get_channel_name(channel_data['name'],
                                                channel_data['bitrate'],
                                                link['hd'], ch_lang),
                        'icon':
                        art.get_channel_icon(channel_data['name'],
                                             self.__settings['path']),
                        'fanart':
                        tools.build_path(self.__settings['path'],
                                         'lfol_art.jpg'),
                        'hash':
                        link['hash']
                    })

        if len(channels) == 0:
            match = re.findall(
                r'[Mm][Aa][Tt][Cc][Hh]</td>\s*<td><strong>(.*)</strong></td>',
                page, re.U)
            raise WebSiteError(
                u'%s' % (match[0]) if match else u'LiveFootbalLOL.me',
                u'Hay enlaces del partido pero no son de acestream. Inténtalo más tarde...',
                time=self.__settings['notify_secs'])

        # Guarda los eventos en caché
        cache.save(e_url, channels)

        return channels
Пример #10
0
    def get_all_events(self):
        """
        Get all LiveFootbalLOL events

        :return: The list of LiveFootbalLOL events
        :rtype: list
        """
        cache = Cache(self.__settings['path'])

        # Busca la URI de la agenda y los enlaces de los canales en caché
        page = cache.load(self.__web_url, False)
        if page:
            # La URI de la agenda está en caché, busca también los eventos
            events = cache.load(page['agenda'])
            if events:
                for event in events:
                    event['name'] = self.__get_event_name(
                        event['event'], event['date'], event['time'],
                        event['competition'])
                return events

        # La URI de la agenda no está en cache
        # Vuelve a obtener la agenda y los eventos
        events = []

        # GET livefootballol.in
        page = tools.get_web_page(self.__web_url)

        # Averigua la URI de la agenda
        urls = self.__get_urls(page)
        if not urls:
            raise WebSiteError(
                u'Agenda no encontrada',
                u'Los de LiveFootbalLOL han hecho cambios en la Web',
                time=self.__settings['notify_secs'])

        # Guarda la URI de la agenda en caché
        cache.save(self.__web_url, urls)

        # GET agenda
        agenda = tools.get_web_page(urls['agenda'])

        # Obtiene la tabla de eventos
        a_events = re.findall(
            r'([0-9]{1,2}:[0-9]{2})\s*<a href=[\'"]?(/streaming/(.*)/[0-9]{2}-[0-9]{2}-[0-9]{4}-.*)[\'"]>(.*)</a>',
            agenda, re.U)

        # Obtiene las ligas
        a_leagues = re.findall(
            r'<b>(.*)</b></li>\s*<li>[0-9]{1,2}:[0-9]{2}\s*'
            r'<a href=[\'"]?/streaming/(.*)/[0-9]{2}-[0-9]{2}-[0-9]{4}-.*[\'"]>',
            agenda, re.U)

        for a_event in a_events:
            league = self.__get_competition_name(a_event[2], a_leagues)
            competition_art = self.__get_competition_art(league)
            c_date = re.findall(r'([0-9]{2}-[0-9]{2}-[0-9]{4})-',
                                tools.str_sanitize(a_event[1]), re.U)
            if c_date:
                events.append({
                    'date':
                    c_date[0],
                    'time':
                    tools.str_sanitize(a_event[0]),
                    'competition':
                    tools.str_sanitize(league),
                    'event':
                    tools.str_sanitize(a_event[3]),
                    'channel_url':
                    a_event[1],
                    'name':
                    self.__get_event_name(tools.str_sanitize(a_event[3]),
                                          c_date[0],
                                          tools.str_sanitize(a_event[0]),
                                          tools.str_sanitize(league)),
                    'icon':
                    competition_art['icon'],
                    'fanart':
                    competition_art['fanart']
                })

        if len(events) == 0:
            raise WebSiteError(
                u'Problema en la agenda',
                u'Está vacía o no hay enlaces, puedes comprobarlo en la Web',
                time=self.__settings['notify_secs'])

        # Guarda los eventos en caché
        cache.save(urls['agenda'], events)

        return events
Пример #11
0
    def get_all_events(self):
        """
        Get all LiveFootballVideo events

        :return: The list of LiveFootballVideo events
        :rtype: list
        """
        cache = Cache(self.__settings['path'])
        agenda_url = '%sstreaming' % self.__web_url

        # Busca los eventos en cache
        events = cache.load(agenda_url)
        if events:
            for event in events:
                event['name'] = self.__get_event_name(event)
            return events

        # Los eventos no están en cache, vuelve a obtenerlos
        web_events = []
        events = []

        # GET livefootballvideo.com/streaming
        page = tools.get_web_page(agenda_url)

        # Obtiene el número de páginas de la agenda
        total_pages = self.__get_number_of_pages(page)
        if not total_pages:
            total_pages = 1

        # Obtiene la tabla de eventos
        for page_number in range(0, total_pages):
            # GET livefootballvideo.com/streaming/page/{page_number}
            page = tools.get_web_page(
                '%s/page/%i' %
                (agenda_url, page_number + 1)) if page_number > 0 else page
            e = re.findall(
                '<li\s*(?:class="odd")?>\s*<div\s*class="leaguelogo\s*column">\s*<img.+?src=".+?"\s*alt=".+?"/>'
                +
                '\s*</div>\s*<div\s*class="league\s*column">\s*<a\s*href=".+?"\s*title=".+?">(.+?)</a>\s*</div>'
                +
                '\s*<div\s*class="date_time\s*column"><span\s*class="starttime\s*time"\s*rel="(.+?)">.+?</span>'
                +
                '\s*-\s*<span\s*class="endtime\s*time"\s*rel="(.+?)">.+?</span></div>\s*<div\s*class="team'
                +
                '\s*column"><img.+?alt="(.+?)"\s*src=".+?"><span>.+?</span></div>\s*<div\s*class="versus'
                +
                '\s*column">vs.</div>\s*<div\s*class="team\s*away\s*column"><span>(.+?)</span><img.+?alt=".+?"'
                +
                '\s*src=".+?"></div>\s*<div\s*class="live_btn\s*column">\s*<a\s*(class="online")?\s*href="(.+?)">',
                page)
            if e:
                web_events.extend(map(list, e))

        if len(web_events) == 0:
            raise WebSiteError(u'Problema en la agenda',
                               u'No hay eventos, puedes comprobarlo en la Web',
                               time=self.__settings['notify_secs'])

        for event in web_events:
            competition = tools.str_sanitize(event[0])
            competition_art = self.__get_competition_art(event[0])
            start = float(tools.str_sanitize(event[1]))
            end = float(tools.str_sanitize(event[2]))
            team1 = tools.str_sanitize(event[3])
            team2 = tools.str_sanitize(event[4])
            events.append({
                'start':
                start,
                'end':
                end,
                'date':
                datetime.datetime.fromtimestamp(start).strftime('%d/%m/%y'),
                'time':
                datetime.datetime.fromtimestamp(start).strftime('%H:%M'),
                'competition':
                competition,
                'team1':
                team1,
                'team2':
                team2,
                'channel_url':
                tools.str_sanitize(event[6]),
                'name':
                self.__get_event_name({
                    'start': start,
                    'end': end,
                    'competition': competition,
                    'team1': team1,
                    'team2': team2
                }),
                'icon':
                competition_art['icon'],
                'fanart':
                competition_art['fanart']
            })

        if len(events) == 0:
            raise WebSiteError(
                u'Problema en la agenda',
                u'Está vacía o no hay enlaces, puedes comprobarlo en la Web',
                time=self.__settings['notify_secs'])

        # Guarda los eventos en caché
        cache.save(agenda_url, events)

        return events
Пример #12
0
    def get_channels(self, event_url):
        """
        Get LiveFootballVideo channels by a given event URL

        :param event_url: The event URL
        :type: event_url: str
        :return: The list of LiveFootballVideo event links
        :rtype: list
        """
        cache = Cache(self.__settings['path'], minutes=10)

        # Busca los canales del evento en caché
        channels = cache.load(event_url, True)
        if channels:
            return channels

        # Los datos de los canales no están en cache
        # Vuelve a obtenerlos
        channels = []

        # GET event_url
        page = tools.get_web_page(event_url)

        # Obtiene el bloque que contiene la tabla de enlaces acestream
        soup = BeautifulSoup(page, 'html5lib')
        div = soup.find('div', attrs={'id': 'livelist'})
        if not div:
            raise WebSiteError(
                u'No hay enlaces',
                u'Los de LiveFootballVideo han hecho cambios en la Web',
                time=self.__settings['notify_secs'])

        # Obtiene la tabla de datos de los canales
        table = div.find('table', attrs={'class': 'streamtable'})
        if not table:
            # No hay enlaces
            match = re.findall(r'class="thick">(.*)</h3>', page, re.U)
            raise WebSiteError(
                u'%s - %s' %
                (match[0], match[1]) if match else u'LiveFootballVideo.com',
                u'El partido ya ha terminado, no hay enlaces' if re.findall(
                    r'game was ended', page, re.U) else
                u'Todavía no se han publicado los enlaces del partido',
                time=self.__settings['notify_secs'])

        # Obtiene los datos de los canales
        for row in table.findAll("tr")[1:-1]:
            cells = row.findAll("td")

            # Datos del canal
            ch_name = tools.str_sanitize(cells[1].get_text())
            ch_type = tools.str_sanitize(cells[0].find('a').get('title'))
            ch_lang = tools.str_sanitize(cells[2].get_text())
            ch_rate = tools.str_sanitize(cells[3].get_text())
            ch_link = tools.str_sanitize(cells[4].find('a').get('href'))

            if ch_link.startswith('http://arenavision.'):
                ch_link = '%s%s' % (Arenavision.web_url,
                                    re.findall(r'http://.*/([0-3][0-9]).*',
                                               ch_link, re.U)[0])

            # Si no es un enlace acestream continua
            if not tools.str_sanitize(ch_type).lower(
            ) == 'acestream' and 'acestream' not in ch_link:
                continue

            # Prepara el idioma
            ch_lang = '--' if not ch_lang or '-' in ch_lang else ch_lang

            # Prepara el bitrate
            ch_rate = 'desconocido' if not ch_rate or '-' in ch_rate else ch_rate

            channels.append({
                'name':
                self.__get_channel_name(ch_name, ch_rate, ch_lang),
                'icon':
                art.get_channel_icon(ch_name, self.__settings['path']),
                'fanart':
                tools.build_path(self.__settings['path'], 'lfv_art.jpg'),
                'link':
                ch_link
            })

        if len(channels) == 0:
            match = re.findall(r'class="thick">(.*)</h3>', page, re.U)
            raise WebSiteError(
                u'%s - %s' %
                (match[0], match[1]) if match else u'LiveFootballVideo.com',
                u'Hay enlaces del partido pero no son de acestream. Inténtalo más tarde...',
                time=self.__settings['notify_secs'])

        # Guarda los eventos en caché
        cache.save(event_url, channels)

        return channels