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
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
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']
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)
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
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
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
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