diff --git a/README.md b/README.md index 9b2d921b..16e630af 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,7 @@ # Kodi On Demand ### Un fork italiano di [Alfa](https://github.com/alfa-addon) Ognuno è libero (anzi, invitato!) a collaborare, per farlo è possibile utilizzare i pull request. +KOD funziona con Kodi fino alla versione 18 (Python 2). KOD, come Alfa, è sotto licenza GPL v3, pertanto siete liberi di utilizzare parte del codice, a patto di rispettare i termini di suddetta licenza, che si possono riassumere in: diff --git a/addon.xml b/addon.xml index 08ef47c0..4550f759 100644 --- a/addon.xml +++ b/addon.xml @@ -1,4 +1,4 @@ - + @@ -19,9 +19,10 @@ resources/media/themes/ss/2.png resources/media/themes/ss/3.png - - nuovo metodo di override DNS -- aggiunta opzione nascondi server, se usi l'autoplay -- migliorie al codice e fix vari + - A grande richiesta, è ora possibile riprodurre in automatico l'episodio successivo di una serie in libreria +- aggiunta la possibilità di nascondere la lista dei server, quando si usa l'autoplay +- aggiunto canale pufimovies.com +- fix vari Naviga velocemente sul web e guarda i contenuti presenti [COLOR red]The owners and submitters to this addon do not host or distribute any of the content displayed by these addons nor do they have any affiliation with the content providers.[/COLOR] [COLOR yellow]Kodi © is a registered trademark of the XBMC Foundation. We are not connected to or in any other way affiliated with Kodi, Team Kodi, or the XBMC Foundation. Furthermore, any software, addons, or products offered by us will receive no support in official Kodi channels, including the Kodi forums and various social networks.[/COLOR] diff --git a/channels.json b/channels.json index 6e027a09..3f9214aa 100644 --- a/channels.json +++ b/channels.json @@ -2,18 +2,19 @@ "altadefinizione01": "https://www.altadefinizione01.tel", "altadefinizione01_link": "https://altadefinizione01.cam", "animeforce": "https://ww1.animeforce.org", - "animeleggendari": "https://animepertutti.com", + "animeleggendari": "https://animepertutti.com", + "animesaturn": "https://animesaturn.com", "animestream": "https://www.animeworld.it", "animesubita": "http://www.animesubita.org", "animetubeita": "http://www.animetubeita.com", - "animeworld": "https://www1.animeworld.tv", - "casacinema": "https://www.casacinema.cloud", + "animeworld": "https://www.animeworld.cc", + "animeunity": "https://www.animeunity.it", + "casacinema": "https://www.casacinema.biz", "casacinemaInfo": "https://casacinema.kim", - "cb01anime": "https://www.cineblog01.ink", - "cinemalibero": "https://www.cinemalibero.live", + "cb01anime": "https://www.cineblog01.ink", "cinetecadibologna": "http://cinestore.cinetecadibologna.it", "documentaristreamingda": "https://documentari-streaming-da.com", - "dreamsub": "https://www.dreamsub.stream", + "dreamsub": "https://dreamsub.stream", "fastsubita": "https://fastsubita.com", "filmgratis": "https://www.filmaltadefinizione.org", "filmigratis": "https://filmigratis.org", @@ -26,9 +27,10 @@ "ilgeniodellostreaming": "https://igds.one", "italiaserie": "https://italiaserie.org", "mondoserietv": "https://mondoserietv.com", - "netfreex": "https://www.netfreex.online", + "netfreex": "https://www.netfreex.icu", "piratestreaming": "https://www.piratestreaming.gratis", "polpotv": "https://polpo.tv", + "pufimovies": "https://pufimovies.com", "seriehd": "https://www.seriehd.watch", "serietvonline": "https://serietvonline.monster", "serietvsubita": "http://serietvsubita.xyz", diff --git a/channels/altadefinizione01.json b/channels/altadefinizione01.json index 8f0d698a..f7589d50 100644 --- a/channels/altadefinizione01.json +++ b/channels/altadefinizione01.json @@ -4,8 +4,8 @@ "language": ["ita", "sub-ita"], "active": true, "adult": false, - "thumbnail": "https://raw.githubusercontent.com/Zanzibar82/images/master/posters/altadefinizione01.png", - "banner": "https://raw.githubusercontent.com/Zanzibar82/images/master/posters/altadefinizione01.png", + "thumbnail": "altadefinizione01.png", + "banner": "altadefinizione01.png", "categories": ["movie", "vos"], "settings": [] } diff --git a/channels/altadefinizione01.py b/channels/altadefinizione01.py index afc6e518..ab2f9e1f 100644 --- a/channels/altadefinizione01.py +++ b/channels/altadefinizione01.py @@ -28,7 +28,7 @@ def findhost(): host = config.get_channel_url(findhost) headers = [['Referer', host]] -list_servers = ['verystream','openload','rapidvideo','streamango'] +list_servers = ['mixdrop','vidoza','cloudvideo','vup','supervideo','gounlimited'] list_quality = ['default'] @support.menu diff --git a/channels/altadefinizione01_link.py b/channels/altadefinizione01_link.py index c0c451a8..a73bde31 100644 --- a/channels/altadefinizione01_link.py +++ b/channels/altadefinizione01_link.py @@ -26,7 +26,7 @@ __channel__ = "altadefinizione01_link" host = config.get_channel_url() headers = [['Referer', host]] -list_servers = ['supervideo', 'streamcherry','rapidvideo', 'streamango', 'openload'] +list_servers = ['mixdrop', 'vup', 'supervideo'] list_quality = ['default'] # =========== home menu =================== diff --git a/channels/altadefinizioneclick.json b/channels/altadefinizioneclick.json index d5190e8c..8ca67198 100644 --- a/channels/altadefinizioneclick.json +++ b/channels/altadefinizioneclick.json @@ -4,8 +4,8 @@ "active": true, "adult": false, "language": ["ita","sub-ita"], - "thumbnail": "https:\/\/raw.githubusercontent.com\/Zanzibar82\/images\/master\/posters\/altadefinizioneclick.png", - "bannermenu": "https:\/\/raw.githubusercontent.com\/Zanzibar82\/images\/master\/posters\/altadefinizioneciclk.png", + "thumbnail": "altadefinizioneclick.png", + "bannermenu": "altadefinizioneciclk.png", "categories": ["movie","vos"], "settings": [] } diff --git a/channels/altadefinizioneclick.py b/channels/altadefinizioneclick.py index fd7a2da1..48631174 100644 --- a/channels/altadefinizioneclick.py +++ b/channels/altadefinizioneclick.py @@ -28,9 +28,8 @@ def findhost(): host = config.get_channel_url(findhost) headers = [['Referer', host]] -list_servers = ['verystream', 'rapidvideo', 'openload', 'streamango', 'vidoza', - 'vidcloud', 'thevideo', 'okru', 'hdload', 'youtube'] -list_quality = ['1080p', '720', '360'] +list_servers = ['mixdrop', 'vidcloud', 'vidoza', 'supervideo', 'hdload', 'mystream'] +list_quality = ['1080p', '720p', '360p'] @support.menu def mainlist(item): diff --git a/channels/animeforce.py b/channels/animeforce.py index cf2dccfc..565e395c 100644 --- a/channels/animeforce.py +++ b/channels/animeforce.py @@ -3,14 +3,11 @@ # Canale per AnimeForce # ------------------------------------------------------------ -from servers.decrypters import adfly from core import support host = support.config.get_channel_url() -IDIOMAS = {'Italiano': 'IT'} -list_language = IDIOMAS.values() -list_servers = ['directo', 'openload', 'vvvvid'] +list_servers = ['directo', 'vvvvid'] list_quality = ['default'] @@ -45,47 +42,40 @@ def newest(categoria): return itemlist -@support.scrape def search(item, texto): - # debug = True - search = texto + support.log(texto) + item.args = 'noorder' + item.url = host + '/?s=' + texto + '&cat=6010' item.contentType = 'tvshow' - patron = r'\s*]+>(?P[^<]+)<' - action = 'episodios' - return locals() + try: + return peliculas(item) + # Continua la ricerca in caso di errore + except: + import sys + for line in sys.exc_info(): + support.logger.error("%s" % line) + return [] @support.scrape def peliculas(item): anime = True action = 'episodios' - - if item.args == 'newest': - patron = r'<a href="(?P<url>[^"]+)">\s*<img src="(?P<thumb>[^"]+)" alt="(?P<title>.*?)(?: Sub| sub| SUB|")' - action = 'findvideos' - - elif item.args == 'last': - patron = r'<a href="(?P<url>[^"]+)">\s*<img src="(?P<thumb>[^"]+)" alt="(?P<title>.*?)(?: Sub| sub| SUB|")' - + if not item.args: + pagination = '' + patron = r'<a\s*href="(?P<url>[^"]+)"\s*title="(?P<title>[^"]+)">' elif item.args == 'corso': pagination = '' patron = r'<strong><a href="(?P<url>[^"]+)">(?P<title>.*?) [Ss][Uu][Bb]' else: - pagination = '' - patron = r'<a href="(?P<url>[^"]+)">\s*<strong[^>]+>(?P<title>[^<]+)<' + patron = r'<a href="(?P<url>[^"]+)"[^>]+>\s*<img src="(?P<thumb>[^"]+)" alt="(?P<title>.*?)(?: Sub| sub| SUB|")' + + if item.args == 'newest': item.action = 'findvideos' def itemHook(item): if 'sub-ita' in item.url: if item.args != 'newest': item.title = item.title + support.typo('Sub-ITA','_ [] color kod') item.contentLanguage = 'Sub-ITA' - if item.args == 'newest': - url = support.match(item, '<a href="([^"]+)" title="[^"]+" target="[^"]+" class="btn', headers=headers)[0] - item.url = url[0] if url else '' - delete = support.scrapertools.find_single_match(item.fulltitle, r'( Episodi.*)') - episode = support.scrapertools.find_single_match(item.title, r'Episodi(?:o)? (?:\d+÷)?(\d+)') - item.title = support.typo(episode + ' - ','bold') + item.title.replace(delete,'') - item.fulltitle = item.show = item.title.replace(delete,'') - item.episode = episode return item return locals() @@ -94,9 +84,15 @@ def peliculas(item): @support.scrape def episodios(item): anime = True - patron = r'<td style[^>]+>\s*.*?(?:<span[^>]+)?<strong>(?P<title>[^<]+)<\/strong>.*?<td style[^>]+>\s*<a href="(?P<url>[^"]+)"[^>]+>' + data = support.match(item, headers=headers).data + if '<h6>Streaming</h6>' in data: + patron = r'<td style[^>]+>\s*.*?(?:<span[^>]+)?<strong>(?P<title>[^<]+)<\/strong>.*?<td style[^>]+>\s*<a href="(?P<url>[^"]+)"[^>]+>' + else: + patron = r'<a\s*href="(?P<url>[^"]+)"\s*title="(?P<title>[^"]+)"\s*class="btn btn-dark mb-1">' def itemHook(item): - item.url = item.url.replace(host, '') + support.log(item) + if item.url.startswith('//'): item.url= 'https:' + item.url + elif item.url.startswith('/'): item.url= 'https:/' + item.url return item action = 'findvideos' return locals() @@ -104,38 +100,81 @@ def episodios(item): def findvideos(item): support.log(item) - + # try: + # from urlparse import urljoin + # except: + # from urllib.parse import urljoin + # support.dbg() itemlist = [] - - if item.episode: - from lib import unshortenit - url, c = unshortenit.unshorten(item.url) - url = support.match(item, r'<a href="([^"]+)"[^>]*>', patronBlock=r'Episodio %s(.*?)</tr>' % item.episode ,url=url)[0] - item.url = url[0] if url else '' - if 'vvvvid' in item.url: - item.action = 'play' - itemlist.append(item) + import requests + from lib import vvvvid_decoder + + if support.match(item.url, string=True, patron=r'(\d+/\d+)').match: + item.action = 'play' + itemlist.append(item) + else: + # VVVVID vars + vvvvid_host = 'https://www.vvvvid.it/vvvvid/ondemand/' + vvvvid_headers = {'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64; rv:62.0) Gecko/20100101 Firefox/62.0'} - if 'http' not in item.url: - if '//' in item.url[:2]: - item.url = 'http:' + item.url - elif host not in item.url: - item.url = host + item.url + # VVVVID session + current_session = requests.Session() + login_page = 'https://www.vvvvid.it/user/login' + conn_id = current_session.get(login_page, headers=vvvvid_headers).json()['data']['conn_id'] + payload = {'conn_id': conn_id} + + + # collect parameters + show_id = support.match(item.url, string=True, patron=r'(\d+)').match + ep_number = support.match(item.title, patron=r'(\d+)').match + json_file = current_session.get(vvvvid_host + show_id + '/seasons/', headers=vvvvid_headers, params=payload).json() + season_id = str(json_file['data'][0]['season_id']) + json_file = current_session.get(vvvvid_host + show_id + '/season/' + season_id +'/', headers=vvvvid_headers, params=payload).json() + + # select the correct episode + for episode in json_file['data']: + support.log('Number',int(episode['number']),int(ep_number)) + if int(episode['number']) == int(ep_number): + url = vvvvid_decoder.dec_ei(episode['embed_info'] or episode['embed_info']) + if 'youtube' in url: item.url = url + item.url = url.replace('manifest.f4m','master.m3u8').replace('http://','https://').replace('/z/','/i/') + if 'https' not in item.url: + url = support.match(item, url='https://or01.top-ix.org/videomg/_definst_/mp4:' + item.url + '/playlist.m3u')[1] + url = url.split()[-1] + itemlist.append( + support.Item(action= 'play', + url= 'https://or01.top-ix.org/videomg/_definst_/mp4:' + item.url + '/' + url, + server= 'directo')) + + elif 'adf.ly' in item.url: + from servers.decrypters import adfly + url = adfly.get_long_url(item.url) - if 'adf.ly' in item.url: - item.url = adfly.get_long_url(item.url) elif 'bit.ly' in item.url: - item.url = support.httptools.downloadpage(item.url, only_headers=True, follow_redirects=False).headers.get("location") + url = support.httptools.downloadpage(item.url, only_headers=True, follow_redirects=False).headers.get("location") + + else: + url = host + for u in item.url.split('/'): + # support.log(i) + if u and 'animeforce' not in u and 'http' not in u: + url += '/' + u + + if 'php?' in url: + url = support.httptools.downloadpage(url, only_headers=True, follow_redirects=False).headers.get("location") + url = support.match(url, patron=r'class="button"><a href=(?:")?([^" ]+)', headers=headers).match + else: + url = support.match(url, patron=[r'<source src=(?:")?([^" ]+)',r'name="_wp_http_referer" value="([^"]+)"']).match + if url.startswith('//'): url = 'https:' + url + elif url.startswith('/'): url = 'https:/' + url - matches = support.match(item, r'button"><a href="([^"]+)"')[0] - for video in matches: itemlist.append( support.Item(channel=item.channel, action="play", - title='diretto', - url=video, + title='Diretto', + url=url, server='directo')) return support.server(item, itemlist=itemlist) diff --git a/channels/animeleggendari.py b/channels/animeleggendari.py index f3fd8b00..a26e8314 100644 --- a/channels/animeleggendari.py +++ b/channels/animeleggendari.py @@ -74,10 +74,10 @@ def peliculas(item): @support.scrape def episodios(item): - data = support.match(item, headers=headers)[1] - if not any(x in data for x in ['Lista Episodi', 'Movie Parte']): + data = support.match(item, headers=headers, patronBlock=r'entry-content clearfix">(.*?)class="mh-widget mh-posts-2 widget_text').block + if not 'pagination clearfix' in data: support.log('NOT IN DATA') - patron = r'(?:iframe src|str)="(?P<url>[^"]+)"' + patron = r'<iframe.*?src="(?P<url>[^"]+)"' title = item.title def fullItemlistHook(itemlist): url = '' @@ -107,7 +107,7 @@ def episodios(item): return locals() def check(item): - data = support.match(item, headers=headers)[1] + data = support.match(item, headers=headers).data if 'Lista Episodi' not in data: item.data = data return findvideos(item) @@ -120,7 +120,7 @@ def findvideos(item): if item.data: data = item.data else: - matches = support.match(item, '(?:str="([^"]+)"|iframe src="([^"]+)")')[0] + matches = support.match(item, patron=r'<iframe.*?src="(?P<url>[^"]+)"').matches data = '' if matches: for match in matches: diff --git a/channels/animesaturn.json b/channels/animesaturn.json index c2e68a8a..e409d3c4 100644 --- a/channels/animesaturn.json +++ b/channels/animesaturn.json @@ -7,79 +7,5 @@ "thumbnail": "animesaturn.png", "banner": "animesaturn.png", "categories": ["anime"], - "settings": [ - { - "id": "modo_grafico", - "type": "bool", - "label": "Cerca informazioni extra", - "default": true, - "enabled": true, - "visible": true - }, - { - "id": "channel_host", - "type": "text", - "label": "Host del canale", - "default": "https://www.animesaturn.com", - "enabled": true, - "visible": true - }, - { - "id": "include_in_global_search", - "type": "bool", - "label": "Includi ricerca globale", - "default": true, - "enabled": true, - "visible": true - }, - { - "id": "include_in_newest_anime", - "type": "bool", - "label": "Includi in Novità - Anime", - "default": true, - "enabled": true, - "visible": true - }, - { - "id": "include_in_newest_italiano", - "type": "bool", - "label": "Includi in Novità - Italiano", - "default": true, - "enabled": true, - "visible": true - }, - { - "id": "checklinks", - "type": "bool", - "label": "Verifica se i link esistono", - "default": false, - "enabled": true, - "visible": true - }, - { - "id": "checklinks_number", - "type": "list", - "label": "Numero de link da verificare", - "default": 1, - "enabled": true, - "visible": "eq(-1,true)", - "lvalues": [ "1", "3", "5", "10" ] - }, - { - "id": "autorenumber", - "type": "bool", - "label": "@70712", - "default": false, - "enabled": true, - "visible": true - }, - { - "id": "autorenumber_mode", - "type": "bool", - "label": "@70688", - "default": false, - "enabled": true, - "visible": "eq(-1,true)" - } - ] + "settings": [] } diff --git a/channels/animesaturn.py b/channels/animesaturn.py index fd51ec44..cf528b3d 100644 --- a/channels/animesaturn.py +++ b/channels/animesaturn.py @@ -6,13 +6,13 @@ from core import support -__channel__ = "animesaturn" -host = support.config.get_setting("channel_host", __channel__) +# __channel__ = "animesaturn" +# host = support.config.get_setting("channel_host", __channel__) +host = support.config.get_channel_url() headers={'X-Requested-With': 'XMLHttpRequest'} -IDIOMAS = {'Italiano': 'ITA'} -list_language = IDIOMAS.values() -list_servers = ['openload', 'fembed', 'animeworld'] + +list_servers = ['directo', 'fembed', 'animeworld'] list_quality = ['default', '480p', '720p', '1080p'] @support.menu @@ -33,6 +33,9 @@ def search(item, texto): anime = True patron = r'href="(?P<url>[^"]+)"[^>]+>[^>]+>(?P<title>[^<|(]+)(?:(?P<lang>\(([^\)]+)\)))?<|\)' action = 'check' + def itemHook(item): + item.url = item.url.replace('www.','') + return item return locals() @@ -58,6 +61,9 @@ def newest(categoria): def menu(item): patronMenu = r'u>(?P<title>[^<]+)<u>(?P<url>.*?)</div> </div>' action = 'peliculas' + def itemHook(item): + item.url = item.url.replace('www.','') + return item return locals() @@ -67,7 +73,7 @@ def peliculas(item): deflang= 'Sub-ITA' if item.args == 'updated': post = "page=" + str(item.page if item.page else 1) if item.page > 1 else None - page, data = support.match(item, r'data-page="(\d+)" title="Next">', post=post, headers=headers) + page= support.match(item, patron=r'data-page="(\d+)" title="Next">', post=post, headers=headers).match patron = r'<img alt="[^"]+" src="(?P<thumb>[^"]+)" [^>]+></div></a>\s*<a href="(?P<url>[^"]+)"><div class="testo">(?P<title>[^\(<]+)(?:(?P<lang>\(([^\)]+)\)))?</div></a>\s*<a href="[^"]+"><div class="testo2">[^\d]+(?P<episode>\d+)</div></a>' if page: nextpage = page item.contentType='episode' @@ -78,17 +84,20 @@ def peliculas(item): action = 'check' else: pagination = '' - if item.args == 'incorso': patron = r'"slider_title" href="(?P<url>[^"]+)"><img src="(?P<thumb>[^"]+)"[^>]+>(?P<title>[^\(<]+)(?:\((?P<year>\d+)\))?</a>' + if item.args == 'incorso': patron = r'"slider_title"\s*href="(?P<url>[^"]+)"><img src="(?P<thumb>[^"]+)"[^>]+>(?P<title>[^\(<]+)(?:\((?P<year>\d+)\))?</a>' else: patron = r'href="(?P<url>[^"]+)"[^>]+>[^>]+>(?P<title>.+?)(?:\((?P<lang>ITA)\))?(?:(?P<year>\((\d+)\)))?</span>' action = 'check' + def itemHook(item): + item.url = item.url.replace('www.','') + return item return locals() def check(item): - movie, data = support.match(item, r'Episodi:</b> (\d*) Movie') - anime_id = support.match(data, r'anime_id=(\d+)')[0][0] + movie = support.match(item, patron=r'Episodi:</b> (\d*) Movie') + anime_id = support.match(movie.data, patron=r'anime_id=(\d+)').match item.url = host + "/loading_anime?anime_id=" + anime_id - if movie: + if movie.match: item.contentType = 'movie' episodes = episodios(item) if len(episodes) > 0: item.url = episodes[0].url @@ -102,16 +111,20 @@ def check(item): def episodios(item): if item.contentType != 'movie': anime = True patron = r'<strong" style="[^"]+">(?P<title>[^<]+)</b></strong></td>\s*<td style="[^"]+"><a href="(?P<url>[^"]+)"' + def itemHook(item): + item.url = item.url.replace('www.','') + return item return locals() def findvideos(item): support.log() itemlist = [] - urls = support.match(item, r'<a href="([^"]+)"><div class="downloadestreaming">', headers=headers)[0] + # support.dbg() + urls = support.match(item, patron=r'<a href="([^"]+)"><div class="downloadestreaming">', headers=headers, debug=False).matches if urls: - links = support.match(item, r'(?:<source type="[^"]+"\s*src=|file:\s*)"([^"]+)"', url=urls[0], headers=headers)[0] - for link in links: + links = support.match(urls[0].replace('www.',''), patron=r'(?:<source type="[^"]+"\s*src=|file:\s*)"([^"]+)"', headers=headers, debug=False) + for link in links.matches: itemlist.append( support.Item(channel=item.channel, action="play", @@ -123,7 +136,7 @@ def findvideos(item): show=item.show, contentType=item.contentType, folder=False)) - return support.server(item, itemlist=itemlist) + return support.server(item, links, itemlist=itemlist) diff --git a/channels/animesubita.py b/channels/animesubita.py index 488f06d8..0df2dc84 100644 --- a/channels/animesubita.py +++ b/channels/animesubita.py @@ -34,7 +34,7 @@ def newest(categoria): if itemlist[-1].action == "ultimiep": itemlist.pop() - # Continua l'esecuzione in caso di errore + # Continua l'esecuzione in caso di errore except: import sys for line in sys.exc_info(): @@ -50,7 +50,7 @@ def search(item, texto): item.args = 'alt' try: return peliculas(item) - # Continua la ricerca in caso di errore + # Continua la ricerca in caso di errore except: import sys for line in sys.exc_info(): @@ -67,10 +67,9 @@ def genres(item): @support.scrape -def peliculas(item): +def peliculas(item): anime = True if item.args == 'updated': - #patron = r'<div class="post-thumbnail">\s*<a href="(?P<url>[^"]+)" title="(?P<title>.*?)\s*(?P<episode>Episodio \d+)[^"]+"[^>]*>\s*<img[^src]+src="(?P<thumb>[^"]+)"' patron = r'<div class="post-thumbnail">\s*<a href="(?P<url>[^"]+)" title="(?P<title>.*?)\s*Episodio (?P<episode>\d+) (?P<lang>[a-zA-Z-\s]+)[^"]*"> <img[^src]+src="(?P<thumb>[^"]+)"' patronNext = r'<link rel="next" href="([^"]+)"\s*/>' action = 'findvideos' @@ -98,32 +97,27 @@ def findvideos(item): itemlist = [] if item.args == 'updated': - ep = support.match(item.fulltitle,r'(Episodio\s*\d+)')[0][0] - item.url = support.re.sub(r'episodio-\d+-|oav-\d+-', '',item.url) + ep = support.match(item.fulltitle, patron=r'(\d+)').match + item.url = support.re.sub(r'episodio-\d+-|oav-\d+-'+ep, '',item.url) if 'streaming' not in item.url: item.url = item.url.replace('sub-ita','sub-ita-streaming') - item.url = support.match(item, r'<a href="([^"]+)"[^>]+>', ep + '(.*?)</tr>', )[0][0] + item.url = support.match(item, patron= ep + r'[^>]+>[^>]+>[^>]+><a href="([^"]+)"').match - urls = support.match(item.url, r'(episodio\d*.php.*)')[0] - for url in urls: - url = host + '/' + url - headers['Referer'] = url - data = support.match(item, headers=headers, url=url)[1] - cookies = "" - matches = support.re.compile('(.%s.*?)\n' % host.replace("http://", "").replace("www.", ""), support.re.DOTALL).findall(support.config.get_cookie_data()) - for cookie in matches: - cookies += cookie.split('\t')[5] + "=" + cookie.split('\t')[6] + ";" + # post + url = host + '/' + support.match(item.url, patron=r'(episodio\d*.php.*?)"').match.replace('%3F','?').replace('%3D','=') + headers['Referer'] = url + cookies = "" + matches = support.re.compile('(.%s.*?)\n' % host.replace("http://", "").replace("www.", ""), support.re.DOTALL).findall(support.config.get_cookie_data()) + for cookie in matches: + cookies += cookie.split('\t')[5] + "=" + cookie.split('\t')[6] + ";" + headers['Cookie'] = cookies[:-1] - headers['Cookie'] = cookies[:-1] - - url = support.match(data, r'<source src="([^"]+)"[^>]+>')[0][0] + '|' + support.urllib.urlencode(headers) - itemlist.append( - support.Item(channel=item.channel, - action="play", - title='diretto', - quality='', - url=url, - server='directo', - fulltitle=item.fulltitle, - show=item.show)) + url = support.match(url, patron=r'<source src="([^"]+)"[^>]+>').match - return support.server(item,url,itemlist) + itemlist.append( + support.Item(channel=item.channel, + action="play", + title='Diretto', + url=url + '|' + support.urllib.urlencode(headers), + server='directo')) + + return support.server(item,itemlist=itemlist) \ No newline at end of file diff --git a/channels/animetubeita.py b/channels/animetubeita.py index 12c5c283..63db64e6 100644 --- a/channels/animetubeita.py +++ b/channels/animetubeita.py @@ -98,11 +98,11 @@ def episodios(item): def findvideos(item): itemlist=[] if item.args == 'last': - match = support.match(item, r'href="(?P<url>[^"]+)"[^>]+><strong>DOWNLOAD & STREAMING</strong>', url=item.url)[0] + match = support.match(item, patron=r'href="(?P<url>[^"]+)"[^>]+><strong>DOWNLOAD & STREAMING</strong>').match if match: patronBlock = r'<h6>Episodio</h6>(?P<block>.*?)(?:<!--|</table>)' patron = r'<a href="http://link\.animetubeita\.com/2361078/(?P<url>[^"]+)"' - match = support.match(item, patron, patronBlock, headers, match[0])[0] + match = support.match(match, patron=patron, patronBlock=patronBlock, headers=headers).match else: return itemlist if match: item.url = match[-1] diff --git a/channels/animeunity.json b/channels/animeunity.json new file mode 100644 index 00000000..99dc0fe0 --- /dev/null +++ b/channels/animeunity.json @@ -0,0 +1,11 @@ +{ + "id": "animeunity", + "name": "AnimeUnity", + "active": true, + "adult": false, + "language": ["ita", "sub-ita"], + "thumbnail": "animeunity.png", + "banner": "animeunity.png", + "categories": ["anime"], + "settings": [] +} diff --git a/channels/animeunity.py b/channels/animeunity.py new file mode 100644 index 00000000..09a628ad --- /dev/null +++ b/channels/animeunity.py @@ -0,0 +1,123 @@ +# -*- coding: utf-8 -*- +# ------------------------------------------------------------ +# Canale per AnimeUnity +# ------------------------------------------------------------ + +from core import support + +host = support.config.get_channel_url() + +list_servers = ['mixdrop', 'wstream', 'vupplayer', 'supervideo', 'cloudvideo', 'gounlimited'] +list_quality = ['default','1080p', '720p', '480p', '360p'] + +headers = [['Referer', host]] + + +@support.menu +def mainlist(item): + anime = ['/anime.php?c=archive&page=*', + ('In Corso',['/anime.php?c=onair', 'peliculas']), + ('Ultimi Episodi', ['', 'peliculas', 'news']), + ('Ultimi Aggiunti', ['', 'peliculas', 'last']) + ] + return locals() + + +@support.scrape +def menu(item): + action = 'peliculas' + patronBlock = item.args + r' Categorie</a>\s*<ul(?P<block>.*?)</ul>' + patronMenu = r'<a href="(?P<url>[^"]+)"[^>]+>(?P<title>[^>]+)<' + return locals() + + +def search(item, text): + support.log('search', item) + item.url = host + '/anime.php?c=archive&page=*' + item.search = text + try: + return peliculas(item) + # Continua la ricerca in caso di errore + except: + import sys + for line in sys.exc_info(): + support.log('search log:', line) + return [] + + +def newest(categoria): + support.log(categoria) + itemlist = [] + item = support.Item() + item.url = host + item.args = 'news' + item.action = 'peliculas' + try: + itemlist = peliculas(item) + + if itemlist[-1].action == 'peliculas': + itemlist.pop() + # Continua la ricerca in caso di errore + except: + import sys + for line in sys.exc_info(): + support.log({0}.format(line)) + return [] + + return itemlist + + +@support.scrape +def peliculas(item): + # debug = True + pagination = 20 + anime = True + if item.args == 'news': + patron = r'col-lg-3 col-md-6 col-sm-6 col-xs-6 mobile-col">\s*<a href="(?P<url>[^"]+)">[^>]+>[^>]+>[^>]+>[^>]+>[^>]+>\s*<img class="[^"]+" src="(?P<thumb>[^"]+)"[^>]+>[^>]+>[^>]+>[^>]+>(?P<title>[^-]+)\D+Episodio\s*(?P<episode>\d+)' + patronNext = r'page-link" href="([^"]+)">' + elif item.args == 'last': + patronBlock = r'ULTIME AGGIUNTE[^>]+>[^>]+>[^>]+>[^>]+>[^>]+>(?P<block>.*?)<div class="row"' + patron = r'<img class="[^"]+" src="(?P<thumb>[^"]+)"[^>]+>[^>]+>[^>]+>\s*<a class="[^"]+" href="(?P<url>[^"]+)"\s*>(?P<title>[^<]+)</a>' + else: + search = item.search + patron = r'<div class="card-img-top archive-card-img"> <a href="(?P<url>[^"]+)"> <img class="[^"]+" src="(?P<thumb>[^"]+)"[^>]+>[^>]+>[^>]+>[^>]+>[^>]+>[^>]+>[^>]+>[^>]+>[^>]+>(?P<title>[^<\(]+)(?:\((?P<lang>[^\)]+)\))?' + return locals() + + +@support.scrape +def episodios(item): + # debug = True + data = item.data + anime = True + pagination = 50 + patron = r'<a href="(?P<url>[^"]+)" class="\D+ep-button">(?P<episode>\d+)' + def itemHook(item): + item.title = item.title + support.typo(item.fulltitle,'-- bold') + return item + return locals() + + +def findvideos(item): + support.log() + html = support.match(item, patron=r'TIPO:\s*</b>\s*([A-Za-z]+)') + if html.match == 'TV' and item.contentType != 'episode': + item.contentType = 'tvshow' + item.data = html.data + return episodios(item) + else: + itemlist = [] + if item.contentType != 'episode': item.contentType = 'movie' + video = support.match(html.data, patron=r'<source src="([^"]+)"').match + itemlist.append( + support.Item( + channel=item.channel, + action="play", + title='Diretto', + quality='', + url=video, + server='directo', + fulltitle=item.fulltitle, + show=item.show, + contentType=item.contentType, + folder=False)) + return support.server(item, itemlist=itemlist) diff --git a/channels/animeworld.py b/channels/animeworld.py index 4fb56587..e9b26a4c 100644 --- a/channels/animeworld.py +++ b/channels/animeworld.py @@ -10,7 +10,7 @@ headers = [['Referer', host]] __channel__ = 'animeworld' -list_servers = ['animeworld', 'verystream', 'streamango', 'openload', 'directo'] +list_servers = ['directo', 'animeworld', 'vvvvid'] list_quality = ['default', '480p', '720p', '1080p'] @@ -34,7 +34,7 @@ def mainlist(item): def genres(item): support.log() itemlist = [] - matches = support.match(item, r'<input.*?name="([^"]+)" value="([^"]+)"\s*>[^>]+>([^<]+)<\/label>' , r'<button class="btn btn-sm btn-default dropdown-toggle" data-toggle="dropdown"> Generi <span.[^>]+>(.*?)</ul>', headers=headers)[0] + matches = support.match(item, patron=r'<input.*?name="([^"]+)" value="([^"]+)"\s*>[^>]+>([^<]+)<\/label>' , patronBlock=r'<button class="btn btn-sm btn-default dropdown-toggle" data-toggle="dropdown"> Generi <span.[^>]+>(.*?)</ul>', headers=headers).matches for name, value, title in matches: support.menuItem(itemlist, __channel__, support.typo(title, 'bold'), 'peliculas', host + '/filter?' + name + '=' + value + '&sort=' + order(), 'tvshow', args='sub') return itemlist @@ -44,7 +44,7 @@ def build_menu(item): support.log() itemlist = [] support.menuItem(itemlist, __channel__, 'Tutti bold', 'peliculas', item.url , 'tvshow' , args=item.args) - matches = support.match(item,r'<button class="btn btn-sm btn-default dropdown-toggle" data-toggle="dropdown"> (.*?) <span.[^>]+>(.*?)</ul>',r'<form class="filters.*?>(.*?)</form>', headers=headers)[0] + matches = support.match(item, patron=r'<button class="btn btn-sm btn-default dropdown-toggle" data-toggle="dropdown"> (.*?) <span.[^>]+>(.*?)</ul>', patronBlock=r'<form class="filters.*?>(.*?)</form>', headers=headers).matches for title, html in matches: if title not in 'Lingua Ordine': support.menuItem(itemlist, __channel__, title + ' submenu bold', 'build_sub_menu', html, 'tvshow', args=item.args) @@ -127,7 +127,7 @@ def peliculas(item): def episodios(item): anime=True pagination = 50 - data = support.match(item, headers=headers)[1] + data = support.match(item, headers=headers).data if 'VVVVID' in data: patronBlock= r'<div class="server\s*active\s*"(?P<block>.*?)</ul>' else: patronBlock= r'server active(?P<block>.*?)server hidden ' patron = r'<li><a [^=]+="[^"]+"[^=]+="[^"]+"[^=]+="[^"]+"[^=]+="[^"]+"[^=]+="[^"]+" href="(?P<url>[^"]+)"[^>]+>(?P<episode>[^<]+)<' @@ -143,9 +143,11 @@ def findvideos(item): import time support.log(item) itemlist = [] - matches, data = support.match(item, r'class="tab.*?data-name="([0-9]+)">', headers=headers) + matches = support.match(item, patron=r'class="tab.*?data-name="([0-9]+)">', headers=headers) + data = matches.data + matches = matches.matches videoData = '' - + for serverid in matches: if not item.number: item.number = support.scrapertools.find_single_match(item.title, r'(\d+) -') block = support.scrapertools.find_multiple_matches(data, 'data-id="' + serverid + '">(.*?)<div class="server') @@ -153,7 +155,7 @@ def findvideos(item): support.log('ID= ',serverid) if id: if serverid == '26': - matches = support.match(item, r'<a href="([^"]+)"', url='%s/ajax/episode/serverPlayer?id=%s' % (host, item.url.split('/')[-1]))[0] + matches = support.match('%s/ajax/episode/serverPlayer?id=%s' % (host, item.url.split('/')[-1]), patron=r'<a href="([^"]+)"', ).matches for url in matches: videoData += '\n' + url else: @@ -162,7 +164,7 @@ def findvideos(item): json = jsontools.load(dataJson) support.log(json) if 'keepsetsu' in json['grabber']: - matches = support.match(item, r'<iframe\s*src="([^"]+)"', url=json['grabber'])[0] + matches = support.match(json['grabber'], patron=r'<iframe\s*src="([^"]+)"'),matches for url in matches: videoData += '\n' + url else: diff --git a/channels/casacinema.py b/channels/casacinema.py index 361aa152..c4046df0 100644 --- a/channels/casacinema.py +++ b/channels/casacinema.py @@ -2,34 +2,12 @@ # ------------------------------------------------------------ # Canale per 'casacinema' # ------------------------------------------------------------ -""" - - Problemi noti che non superano il test del canale: - - Nella ricerca globale non sono presenti le voci: - - "Aggiungi in videoteca" - - "Scarica film/serie" - presenti però quando si entra nella pagina - - Avvisi: - Novità: - - Film, SerieTv - - Ulteriori info: - -""" -import re from core import support -from platformcode import config - -# in caso di necessità -from core import scrapertools, httptools -from core.item import Item -##### fine import -host = config.get_channel_url() +host = support.config.get_channel_url() headers = [['Referer', host]] list_servers = ['verystream', 'openload', 'wstream', 'speedvideo'] @@ -37,9 +15,6 @@ list_quality = ['HD', 'SD'] @support.menu def mainlist(item): - support.log(item) -## support.dbg() - film = ['/category/film', ('Generi', ['', 'genres', 'genres']), ('Sub-ITA', ['/category/sub-ita/', 'peliculas', 'sub']) @@ -53,24 +28,90 @@ def mainlist(item): return locals() + +@support.scrape +def genres(item): + action = 'peliculas' + blacklist = ['PRIME VISIONI', 'ULTIME SERIE TV', 'ULTIMI FILM'] + patronMenu = r'<li><a href="(?P<url>[^"]+)">(?P<title>[^<>]+)</a></li>' + patronBlock = r'<div class="container home-cats">(?P<block>.*?)<div class="clear">' + return locals() + + +def select(item): + item.data = support.match(item).data + if 'continua con il video' in item.data.lower(): + support.log('select = ### è un film ###') + item.contentType = 'movie' + return findvideos(item) + else: + support.log('select = ### è una serie ###') + item.contentType = 'tvshow' + return episodios(item) + + +def search(item, text): + support.log(text) + text = text.replace(' ', '+') + item.url = host + '/?s=' + text + item.args = 'search' + try: + item.contentType = '' # non fa uscire le voci nel context menu + return peliculas(item) + + except: + import sys + for line in sys.exc_info(): + support.log('search log:', line) + return [] + + +def newest(categoria): + itemlist = [] + item = support.Item() + item.args = 'newest' + + try: + if categoria == 'series': + item.contentType = 'tvshow' + item.url = host+'/aggiornamenti-serie-tv' + + else: + item.contentType = 'movie' + item.url = host+'/category/film' + + item.action = 'peliculas' + itemlist = peliculas(item) + + if itemlist[-1].action == 'peliculas': + itemlist.pop() + + # Continua la ricerca in caso di errore + except: + import sys + for line in sys.exc_info(): + support.log('newest log: ', {0}.format(line)) + return [] + + return itemlist + + @support.scrape def peliculas(item): - support.log(item) -## support.dbg() # decommentare per attivare web_pdb - if item.contentType == 'movie': action = 'findvideos' elif item.contentType == 'tvshow': action = 'episodios' pagination = '' else: - # è una ricerca action = 'select' - blacklist = [''] - patron = r'<li><a href="(?P<url>[^"]+)"[^=]+="(?P<thumb>[^"]+)"><div> <div[^>]+>(?P<title>.*?)[ ]?(?:\[(?P<quality1>HD)\])?[ ]?(?:\(|\[)?(?P<lang>Sub-ITA)?(?:\)|\])?[ ]?(?:\[(?P<quality>.+?)\])?[ ]?(?:\((?P<year>\d+)\))?<(?:[^>]+>.+?(?:title="Nuovi episodi">(?P<episode>\d+x\d+)[ ]?(?P<lang2>Sub-Ita)?|title="IMDb">(?P<rating>[^<]+)))?' - patronBlock = r'<h1>.+?</h1>(?P<block>.*?)<aside>' - patronNext = '<a href="([^"]+)" >Pagina' + if item.args == 'newest': + patron = r'<li><a href="(?P<url>[^"]+)"[^=]+="(?P<thumb>[^"]+)"><div> <div[^>]+>(?P<title>[^\(\[<]+)(?:\[(?P<quality1>HD)\])?[ ]?(?:\(|\[)?(?P<lang>Sub-ITA)?(?:\)|\])?[ ]?(?:\[(?P<quality>.+?)\])?[ ]?(?:\((?P<year>\d+)\))?<(?:[^>]+>.+?(?:title="Nuovi episodi">(?P<episode>\d+x\d+)[ ]?(?P<lang2>Sub-Ita)?|title="IMDb">(?P<rating>[^<]+)))?' + else: + patron = r'<li><a href="(?P<url>[^"]+)"[^=]+="(?P<thumb>[^"]+)"><div> <div[^>]+>(?P<title>[^\(\[<]+)(?:\[(?P<quality1>HD)\])?[ ]?(?:\(|\[)?(?P<lang>Sub-ITA)?(?:\)|\])?[ ]?(?:\[(?P<quality>.+?)\])?[ ]?(?:\((?P<year>\d+)\))?<' + + patronNext = r'<a href="([^"]+)" >Pagina' def itemHook(item): if item.quality1: @@ -82,125 +123,31 @@ def peliculas(item): if item.args == 'novita': item.title = item.title return item - -## debug = True # True per testare le regex sul sito return locals() + @support.scrape def episodios(item): - support.log(item) - #dbg - if item.data1: - data = item.data1 + if item.data: + data = item.data action = 'findvideos' item.contentType = 'tvshow' blacklist = [''] patron = r'(?P<episode>\d+(?:×|×)?\d+\-\d+|\d+(?:×|×)\d+)[;]?(?:(?P<title>[^<]+)<(?P<url>.*?)|(\2[ ])(?:<(\3.*?)))(?:<br />|</p>)' patronBlock = r'<strong>(?P<block>(?:.+?Stagione*.+?(?P<lang>[Ii][Tt][Aa]|[Ss][Uu][Bb][\-]?[iI][tT][aA]))?(?:.+?|</strong>)(/?:</span>)?</p>.*?</p>)' - -## debug = True return locals() -# Questa def è utilizzata per generare il menu 'Generi' del canale -# per genere, per anno, per lettera, per qualità ecc ecc -@support.scrape -def genres(item): - support.log(item) - #dbg - - action = 'peliculas' - blacklist = ['PRIME VISIONI', 'ULTIME SERIE TV', 'ULTIMI FILM'] - patron = r'<li><a href="(?P<url>[^"]+)">(?P<title>[^<>]+)</a></li>' - patronBlock = r'<div class="container home-cats">(?P<block>.*?)<div class="clear">' - - #debug = True - return locals() - -def select(item): - support.log('select --->', item) -## debug = True - #support.dbg() - data = httptools.downloadpage(item.url, headers=headers).data - data = re.sub('\n|\t', ' ', data) - data = re.sub(r'>\s+<', '> <', data) - if 'continua con il video' in data.lower(): -## block = scrapertools.find_single_match(data, r'<div class="col-md-8 bg-white rounded-left p-5"><div>(.*?)<div style="margin-left: 0.5%; color: #FFF;">') -## if re.findall('rel="category tag">serie', data, re.IGNORECASE): - support.log('select = ### è un film ###') - return findvideos(Item(channel=item.channel, - title=item.title, - fulltitle=item.fulltitle, - url=item.url, - #args='serie', - contentType='movie', - data1 = data - )) - else: - support.log('select = ### è una serie ###') - return episodios(Item(channel=item.channel, - title=item.title, - fulltitle=item.fulltitle, - url=item.url, - #args='serie', - contentType='tvshow', - data1 = data - )) - -############## Fondo Pagina - -def search(item, text): - support.log('search ->', item) - itemlist = [] - text = text.replace(' ', '+') - item.url = host + '/?s=' + text - item.args = 'search' - try: - item.contentType = 'episode' # non fa uscire le voci nel context menu - return peliculas(item) - # Se captura la excepcion, para no interrumpir al buscador global si un canal falla - except: - import sys - for line in sys.exc_info(): - support.log('search log:', line) - return [] - -def newest(categoria): - support.log('newest ->', categoria) - itemlist = [] - item = Item() - - try: - if categoria == 'series': - item.contentType = 'tvshow' - item.url = host+'/aggiornamenti-serie-tv' - item.args = 'novita' - else: - item.contentType = 'movie' - item.url = host+'/category/film' - - item.action = 'peliculas' - itemlist = peliculas(item) - - if itemlist[-1].action == 'peliculas': - itemlist.pop() - # Continua la ricerca in caso di errore - except: - import sys - for line in sys.exc_info(): - support.log('newest log: ', {0}.format(line)) - return [] - - return itemlist def findvideos(item): - support.log('findvideos ->', item) - itemlist = [] if item.contentType != 'movie': - return support.server(item, item.url) + links = support.match(item.url, patron=r'href="([^"]+)"').matches else: - links = str(support.match(item, r'SRC="([^"]+)"', patronBlock=r'<div class="col-md-10">(.+?)<div class="swappable" id="links">')[0]) - if links: - links = links.replace('#', 'speedvideo.net') - return support.server(item, links) - else: - return support.server(item) + matchData = item.data if item.data else item + links = support.match(matchData, patron=r'(?:SRC|href)="([^"]+)"', patronBlock=r'<div class="col-md-10">(.+?)<div class="ads">').matches + data = '' + from lib.unshortenit import unshorten_only + for link in links: + support.log('URL=',link) + url, c = unshorten_only(link.replace('#', 'speedvideo.net')) + data += url + '\n' + return support.server(item, data) diff --git a/channels/cb01anime.py b/channels/cb01anime.py index d08c70b2..9e892298 100644 --- a/channels/cb01anime.py +++ b/channels/cb01anime.py @@ -59,7 +59,7 @@ def peliculas(item): blacklist = Blacklist item.contentType = 'tvshow' if item.args == 'newest': - data = support.match(item)[1] + # data = support.match(item).data patron = r'<div id="blockvids"><ul><li><a href="(?P<url>[^"]+)"[^>]+><img src="(?P<thumb>[^"]+)"[^>]+>[^>]+>[^>]+>[^>]+>[^>]+>(?P<title>[^\[]+)\[(?P<lang>[^\]]+)\]' else: patron = r'<div class="span4">\s*<a href="(?P<url>[^"]+)"><img src="(?P<thumb>[^"]+)"[^>]+><\/a>[^>]+>[^>]+>[^>]+>[^>]+>[^>]+>[^>]+>[^>]+> <h1>(?P<title>[^<\[]+)(?:\[(?P<lang>[^\]]+)\])?</h1></a>.*?-->(?:.*?<br />)?\s*(?P<plot>[^<]+)' @@ -68,7 +68,7 @@ def peliculas(item): return locals() def check(item): - item.url = support.match(item,r'(?:<p>|/>)(.*?)(?:<br|</td>|</p>)', r'Streaming:(.*?)</tr>')[0] + item.url = support.match(item, patron=r'(?:<p>|/>)(.*?)(?:<br|</td>|</p>)', patronBlock=r'Streaming:(.*?)</tr>').matches if 'Episodio' in str(item.url): item.contentType = 'tvshow' return episodios(item) @@ -87,14 +87,14 @@ def episodios(item): sp = 0 for match in item.url: if 'stagione' in match.lower(): - find_season = support.match(match, r'Stagione\s*(\d+)')[0] - season = int(find_season[0]) if find_season else season + 1 if 'prima' not in match.lower() else season + find_season = support.match(match, patron=r'Stagione\s*(\d+)').match + season = int(find_season) if find_season else season + 1 if 'prima' not in match.lower() else season else: - try: title = support.match(match,'<a[^>]+>([^<]+)</a>')[0][0] + try: title = support.match(match, patron=r'<a[^>]+>([^<]+)</a>').match except: title = '' if title: if 'episodio' in title.lower(): - ep = support.match(match, r'Episodio ((?:\d+.\d|\d+|\D+))')[0][0] + ep = support.match(match, patron=r'Episodio ((?:\d+.\d|\d+|\D+))').match check = ep.isdigit() if check or '.' in ep: if '.' in ep: diff --git a/channels/cineblog01.py b/channels/cineblog01.py index b4c23f11..64a82ac5 100644 --- a/channels/cineblog01.py +++ b/channels/cineblog01.py @@ -22,7 +22,7 @@ def findhost(): host = config.get_channel_url(findhost) headers = [['Referer', host]] -list_servers = ['verystream', 'openload', 'streamango', 'wstream'] +list_servers = ['mixdrop', 'akstream', 'wstream', 'backin'] list_quality = ['HD', 'SD', 'default'] checklinks = config.get_setting('checklinks', 'cineblog01') diff --git a/channels/cinemalibero.py b/channels/cinemalibero.py index 01859ef6..a237bab1 100644 --- a/channels/cinemalibero.py +++ b/channels/cinemalibero.py @@ -12,7 +12,11 @@ from platformcode import config list_servers = ['akstream', 'wstream', 'backin', 'clipwatching', 'cloudvideo', 'verystream', 'onlystream', 'mixdrop'] list_quality = ['default'] -host = config.get_channel_url() +def findhost(): + permUrl = httptools.downloadpage('https://www.cinemalibero.online/', follow_redirects=False).headers + return 'https://www.' + permUrl['location'].replace('https://www.google.com/search?q=site:', '') + +host = config.get_channel_url(findhost) headers = [['Referer', host]] @support.menu diff --git a/channels/cinetecadibologna.py b/channels/cinetecadibologna.py index 892c3a19..9bf10c08 100644 --- a/channels/cinetecadibologna.py +++ b/channels/cinetecadibologna.py @@ -73,7 +73,7 @@ def findvideos(item): support.log() itemlist = [] - matches = support.match(item, 'filename: "(.*?)"')[0] + matches = support.match(item, patron=r'filename: "(.*?)"').matches for url in matches: itemlist.append( diff --git a/channels/dreamsub.json b/channels/dreamsub.json index ba8bf611..d0d39ea9 100644 --- a/channels/dreamsub.json +++ b/channels/dreamsub.json @@ -7,6 +7,5 @@ "thumbnail": "dreamsub.png", "banner": "dreamsub.png", "categories": ["anime", "vos"], - "not_active": ["include_in_newest"], "settings": [] } diff --git a/channels/dreamsub.py b/channels/dreamsub.py index e5ac914c..a9c0889f 100644 --- a/channels/dreamsub.py +++ b/channels/dreamsub.py @@ -2,214 +2,54 @@ # ------------------------------------------------------------ # Canale per 'dreamsub' # ------------------------------------------------------------ -# ------------------------------------------------------------ -""" - - Problemi noti che non superano il test del canale: - - Nessuno noto! - - Avvisi per i tester: - 1. Gli episodi sono divisi per pagine di 20 - 2. In Novità->Anime, cliccare sulla home il bottone "Ultime inserite" - Se avete più titoli in KOD, ridimensiona il browser in modo che si vedano i titoli - a gruppi di 3 e ricontrollare, è un problema del sito. - - 3.Passaggi per Aggiungere in videoteca e/o scaricare Serie: - 1. sul titolo -> menu contestuale -> Rinumerazione - Solo dopo questo passaggio appariranno le voci, sul titolo -> menu contestuale ->: - - Aggiungi in videoteca (senza rinumerazione non appare - la voce) - - Scarica Serie e Scarica Stagione ( Se download Abilitato! ) - - 4. ### PIù IMPORTANTE!!! ### - #### NON E' DA CONSIDERARE ERRORE NEL TEST QUANTO RIPORTATO DI SEGUITO!!!! #### - 1. Il sito permette un filtro tra anime e film, tramite url. - Se nell'url c'è /anime/, sul titolo e proseguendo fino alla pagina del video, saranno - presenti le voci: - - 'Rinumerazione', prima, e dopo: 'Aggiungi in videoteca', 'Scarica Serie' etc... - Tutto il resto è trattato come film e si avranno le voci solite: - AD eccezione per quei "FILM" che hanno 2 o più titoli all'interno, in questo caso: - 1. Non apparirà nessuna voce tra "Aggiungi in videoteca" e "Scarica Film" e nemmeno "rinumerazione" - 2. Dopo essere entrato nella pagina del Titolo Principale, troverai una lista di titoli dove sarà possibile scaricare - il filmato (chiamato EPISODIO) stessa cosa accedendo alla pagina ultima del video - 3. Questi TITOLI NON POSSONO ESSERE AGGIUNTI IN VIDEOTECA - le voci "Scarica FILM" si avranno dopo. - - Es: - https://www.dreamsub.stream/movie/5-centimetri-al-secondo -> film ma ha 3 titoli - - Il Canale NON è presente nelle novità(globale) -> Anime - - -""" -# Qui gli import -import re from core import support -from platformcode import config -from core import scrapertools, httptools, servertools, tmdb -from core.item import Item -##### fine import -host = config.get_channel_url() +host = support.config.get_channel_url() headers = [['Referer', host]] -# server di esempio... -list_servers = ['directo', 'verystream', 'streamango', 'openload'] -# quality di esempio -list_quality = ['default'] - -#### Inizio delle def principali ### - @support.menu def mainlist(item): support.log(item) - anime = ['/anime', -## ('Novità', ['']), -## ('OAV', ['/search/oav', 'peliculas', 'oav']), -## ('OVA', ['/search/ova', 'peliculas', 'ova']), - ('Movie', ['/search/movie', 'peliculas', '', 'movie']), - ('Film', ['/search/film', 'peliculas', '', 'movie']), - ('Categorie', ['/filter?genere=','genres']), -## ('Ultimi Episodi', ['', 'last']) + anime = ['/search?typeY=tv', + ('Movie', ['/search?typeY=movie', 'peliculas', '', 'movie']), + ('OAV', ['/search?typeY=oav', 'peliculas', '', 'tvshow']), + ('Spinoff', ['/search?typeY=spinoff', 'peliculas', '', 'tvshow']), + ('Generi', ['','menu','Generi']), + ('Stato', ['','menu','Stato']), + ('Ultimi Episodi', ['', 'peliculas', ['last', 'episodiRecenti']]), + ('Ultimi Aggiornamenti', ['', 'peliculas', ['last', 'episodiNuovi']]) ] return locals() -@support.scrape -def peliculas(item): - support.log(item) - #dbg # decommentare per attivare web_pdb - - anime = True - if item.args == 'newest': - patronBlock = r'<div class="showRoomGoLeft" sr="ultime"></div>(?P<block>.*?)<div class="showRoomGoRight" sr="ultime">' - else: - patronBlock = r'<input type="submit" value="Vai!" class="blueButton">(?P<block>.*?)<div class="footer">' - -## patron = r'<div class="showStreaming"> <b>(?P<title>[^<]+).+?Stato streaming: '\ -## '(?:[^<]+)<.*?Lingua:[ ](?P<lang1>ITA\/JAP|ITA|JAP)?(?:[ ])?'\ -## '(?P<lang2>SUB ITA)?<br>.+?href="(?P<url>[^"]+)".+?'\ -## 'background: url\((?P<thumb>[^"]+)\).+?<div class="tvTitle">.+?'\ -## '<strong>Anno di inizio</strong>: (?P<year>\d+)<br>' - - patron = r'<div class="showStreaming"> <b>(?P<title>[^<]+).+?Stato streaming: (?:[^<]+)<.*?Lingua:[ ](?P<lang1>ITA\/JAP|ITA|JAP)?(?:[ ])?(?P<lang2>SUB ITA)?<br>.+?href="(?P<url>[^"]+)".+?background: url\((?P<thumb>[^"]+)\).+?<div class="tvTitle">.+?Episodi[^>]+>.\s?(?P<nep>\d+).+?<strong>Anno di inizio</strong>: (?P<year>\d+)<br>' - patronNext = '<li class="currentPage">[^>]+><li[^<]+<a href="([^"]+)">' - - def itemHook(item): - support.log("ITEMHOOK -> ", item) - item = language(item) - - if 'anime' in item.url: - item.contentType = 'tvshow' - item.action = 'episodios' - #item.args = 'anime' - else: - if item.nep == '1': - item.contentType = 'movie' - item.action = 'findvideos' - else: - item.contentType = 'episode' - item.args = '' - item.nep = item.nep - item.action = 'findmovie' - return item - - #debug = True - return locals() @support.scrape -def episodios(item): - support.log(item) - #support.dbg() - - action = 'findvideos' - patronBlock = r'<div class="seasonEp">(?P<block>.*?)<div class="footer">' - patron = r'<li><a href="(?P<url>[^"]+)"[^<]+<b>(?:.+?)[ ](?P<episode>\d+)<\/b>[^>]+>(?P<title>[^<]+)<\/i>[ ]\(?(?P<lang1>ITA|Sub ITA)?\s?.?\s?(?P<lang2>Sub ITA)?.+?\)?<\/a>' - - def itemHook(item): - item = language(item) - return item - - pagination = '' - - #debug = True - return locals() - -@support.scrape -def genres(item): - support.log(item) - #dbg - +def menu(item): item.contentType = '' action = 'peliculas' - blacklist = ['tutti'] - patron = r'<option value="(?P<title>[^"]+)">' - patronBlock = r'<select name="genere" id="genere" class="selectInput">(?P<block>.*?)</select>' + + patronBlock = r'<div class="filter-header"><b>%s</b>(?P<block>.*?)<div class="filter-box">' % item.args + patronMenu = r'<a class="[^"]+" data-state="[^"]+" (?P<other>[^>]+)>[^>]+></i>[^>]+></i>[^>]+></i>(?P<title>[^>]+)</a>' def itemHook(item): - item.contentTitle = item.contentTitle.replace(' ', '+') - item.url = host+'/filter?genere='+item.contentTitle + support.log(item.type) + for Type, ID in support.match(item.other, patron=r'data-type="([^"]+)" data-id="([^"]+)"').matches: + item.url = host + '/search?' + Type + 'Y=' + ID return item - - #debug = True return locals() -@support.scrape -def findmovie(item): - support.log(item) - - patronBlock = r'<div class="seasonEp">(?P<block>.*?)<div class="footer">' - item.contentType = 'episode' - item.nep = 2 - patron = r'<li><a href="(?P<url>[^"]+)"[^>]+>.(?P<title2>.+?)-.+?-[ ]<b>(?P<title>.+?)</b>\s+\(?(?P<lang1>ITA)?\s?(?P<lang2>Sub ITA)?.+?\)?' - - def itemHook(item): - item = language(item) - return item - - #debug = True - return locals() - - -def language(item): - lang = [] - - if item.lang1: - if item.lang1.lower() == 'ita/jap' or item.lang1.lower() == 'ita': - lang.append('ITA') - - if item.lang1.lower() == 'jap' and item.lang1.lower() == 'sub ita': - lang.append('Sub-ITA') - - if item.lang2: - if item.lang2.lower() == 'sub ita': - lang.append('Sub-ITA') - - item.contentLanguage = lang - - if len(lang) ==2: - item.title += support.typo(lang[0], '_ [] color kod') + support.typo(lang[1], '_ [] color kod') - #item.show += support.typo(lang[0], '_ [] color kod') + support.typo(lang[1], '_ [] color kod') - elif len(lang) == 1: - item.title += support.typo(lang[0], '_ [] color kod') - #item.show += support.typo(lang[0], '_ [] color kod') - - return item - - def search(item, text): - support.log('search', item) - itemlist = [] + support.log(text) text = text.replace(' ', '+') item.url = host + '/search/' + text item.args = 'search' try: return peliculas(item) - # Se captura la excepcion, para no interrumpir al buscador global si un canal falla + # Continua la ricerca in caso di errore except: import sys for line in sys.exc_info(): @@ -217,77 +57,88 @@ def search(item, text): return [] -# da adattare... ( support.server ha vari parametri ) -#support.server(item, data='', itemlist=[], headers='', AutoPlay=True, CheckLinks=True) +def newest(categoria): + support.log(categoria) + item = support.Item() + try: + if categoria == "anime": + item.url = host + item.args = ['last', 'episodiNuovi'] + return peliculas(item) + # Continua la ricerca in caso di errore + except: + import sys + for line in sys.exc_info(): + support.logger.error("{0}".format(line)) + return [] + + + +@support.scrape +def peliculas(item): + anime = True + if 'movie' in item.url: + item.contentType = 'movie' + action = 'findvideos' + else: + item.contentType = 'tvshow' + action = 'episodios' + + if len(item.args) > 1 and item.args[0] == 'last': + patronBlock = r'<div id="%s"[^>]+>(?P<block>.*?)<div class="vistaDettagliata"' % item.args[1] + patron = r'<li>\s*<a href="(?P<url>[^"]+)" title="(?P<title>[^"]+)" class="thumb">[^>]+>[^>]+>[^>]+>\s*[EePp]+\s*(?P<episode>\d+)[^>]+>[^>]+>[^>]+>(?P<lang>[^<]*)<[^>]+>[^>]+>\s<img src="(?P<thumb>[^"]+)"' + else: + patron = r'<div class="showStreaming"> <b>(?P<title>[^<]+)[^>]+>[^>]+>\s*Stato streaming: (?:[^<]+)<[^>]+>[^>]+>\s*Lingua:[ ](?P<lang>ITA\/JAP|ITA|JAP|SUB ITA)?[^>]+>[^>]+>\s*<a href="(?P<url>[^"]+)"[^>]+>[^>]+>[^>]+>[^>]+>[^>]+>[^>]+>[^>]+>[^>]+>[^>]+>[^>]+>[^>]+>\s*<div class="[^"]+" style="background: url\((?P<thumb>[^\)]+)\)' + patronNext = '<li class="currentPage">[^>]+><li[^<]+<a href="([^"]+)">' + + return locals() + + +@support.scrape +def episodios(item): + anime = True + pagination = 100 + + if item.data: + data = item.data + + patron = r'<div class="sli-name">\s*<a href="(?P<url>[^"]+)"[^>]+>(?P<title>[^<]+)<' + + return locals() + + def findvideos(item): - support.log("ITEM ---->", item) itemlist = [] + support.log() - data = httptools.downloadpage(item.url).data - data = re.sub(r'\n|\t', ' ', data) - data = re.sub(r'>\s\s*<', '><', data) - patronBlock = r'LINK STREAMING(?P<block>.*?)LINK DOWNLOAD' - patron = r'href="(.+?)"' - block = scrapertools.find_single_match(data, patronBlock) - urls = scrapertools.find_multiple_matches(block, patron) - #support.regexDbg(item, patron, headers, data=data) + matches = support.match(item, patron=r'<a href="([^"]+)"', patronBlock=r'<div style="white-space: (.*?)<div id="main-content"') - for url in urls: - titles = item.infoLabels['title'] - lang = '' - if 'sub_ita' in url.lower(): - lang = 'Sub-ITA' - else: - lang = 'ITA' + if not matches.matches: + item.data = matches.data + item.contentType = 'tvshow' + return episodios(item) - if 'keepem.online' in data: - urls = scrapertools.find_multiple_matches(data, r'(https://keepem\.online/f/[^"]+)"') - for url in urls: - url = httptools.downloadpage(url).url - itemlist += servertools.find_video_items(data=url) + # matches.matches.sort() - elif 'keepsetsu' in url.lower() or 'woof' in url.lower(): - if 'keepsetsu' in url.lower(): - support.log("keepsetsu url -> ", url ) - data = httptools.downloadpage(url).url - support.log("LINK-DATA :", data) - - data = httptools.downloadpage(data).data - support.log("LINK-DATA2 :", data) - video_urls = scrapertools.find_single_match(data, r'<meta name="description" content="([^"]+)"') - - else: - - data = httptools.downloadpage(url).data - #host_video = scrapertools.find_single_match(data, r'var thisPageUrl = "(http[s]\:\/\/[^\/]+).+?"') - host_video = scrapertools.find_single_match(data, r'(?:let|var) thisPageUrl = "(http[s]\:\/\/[^\/]+).+?"') - link = scrapertools.find_single_match(data, r'<video src="([^"]+)"') - video_urls = host_video+link - - title_show = support.typo(titles,'_ bold') + support.typo(lang,'_ [] color kod') + for url in matches.matches: + lang = url.split('/')[-2] + if 'ita' in lang.lower(): + language = 'ITA' + if 'sub' in lang.lower(): + language = 'Sub-' + language + quality = url.split('/')[-1] itemlist.append( support.Item(channel=item.channel, action="play", contentType=item.contentType, - title=title_show, - fulltitle=item.fulltitle, - show=item.fulltitle, - url=link if 'http' in link else video_urls, - infoLabels = item.infoLabels, - thumbnail=item.thumbnail, - contentSerieName= item.fulltitle, - contentTitle=title_show, - contentLanguage = 'ITA' if lang == [] else lang, - args=item.args, + title=language, + url=url, + contentLanguage = language, + quality = quality, + order = quality.replace('p','').zfill(4), server='directo', )) - if item.contentType != 'episode' and int(item.nep) < 2 : - # Link Aggiungi alla Libreria - if config.get_videolibrary_support() and len(itemlist) > 0 and item.extra != 'findservers': - support.videolibrary(itemlist, item) - # link per scaricare - if config.get_setting('downloadenabled'): - support.download(itemlist, item) - return itemlist + itemlist.sort(key=lambda x: (x.title, x.order), reverse=False) + return support.server(item, itemlist=itemlist) \ No newline at end of file diff --git a/channels/fastsubita.py b/channels/fastsubita.py index b022c94e..b96af5e8 100644 --- a/channels/fastsubita.py +++ b/channels/fastsubita.py @@ -145,7 +145,9 @@ def findvideos(item): itemlist = [] patronBlock = '<div class="entry-content">(?P<block>.*)<footer class="entry-footer">' patron = r'<a href="([^"]+)">' - matches, data = support.match(item, patron, patronBlock, headers) + html = support.match(item, patron=patron, patronBlock=patronBlock, headers=headers) + matches = html.matches + data= html.data if item.args != 'episodios': item.infoLabels['mediatype'] = 'episode' @@ -156,7 +158,7 @@ def findvideos(item): itemlist += support.server(item, data) - data = httptools.downloadpage(item.url).data + data = support.match(item.url).data patron = r'>Posted in <a href="https?://fastsubita.com/serietv/([^/]+)/(?:[^"]+)?"' series = scrapertools.find_single_match(data, patron) titles = support.typo(series.upper().replace('-', ' '), 'bold color kod') diff --git a/channels/filmpertutti.py b/channels/filmpertutti.py index 33fc088b..ca967ebf 100644 --- a/channels/filmpertutti.py +++ b/channels/filmpertutti.py @@ -2,19 +2,7 @@ # ------------------------------------------------------------ # Canale per filmpertutti.py # ------------------------------------------------------------ -""" - Questi sono commenti per i beta-tester. - Su questo canale, nella categoria 'Ricerca Globale' - non saranno presenti le voci 'Aggiungi alla Videoteca' - e 'Scarica Film'/'Scarica Serie', dunque, - la loro assenza, nel Test, NON dovrà essere segnalata come ERRORE. - - Novità (globale). Indicare in quale/i sezione/i è presente il canale: - - film, serie - - I titoli in questa sezione a gruppi di 20 - -""" import re from core import scrapertools, httptools, support @@ -24,7 +12,7 @@ from platformcode import config host = config.get_channel_url() headers = [['Referer', host]] -list_servers = ['speedvideo', 'verystream', 'openload', 'streamango', 'wstream', 'akvideo'] +list_servers = ['mixdrop', 'akvideo', 'wstream', 'onlystream', 'speedvideo'] list_quality = ['HD', 'SD'] @support.menu @@ -74,16 +62,11 @@ def peliculas(item): @support.scrape def episodios(item): - data = httptools.downloadpage(item.url, headers=headers).data - data = re.sub('\n|\t', ' ', data) - data = re.sub(r'>\s+<', '> <', data) - support.log('SERIES DATA= ',data) + data = support.match(item.url, headers=headers).data if 'accordion-item' in data: patronBlock = r'<span class="season[^>]*>\d+[^>]+>[^>]+>[^>]+>[^>]+>\D*(?:STAGIONE|Stagione)[ -]+(?P<lang>[a-zA-Z\- ]+)[^<]*</span>(?P<block>.*?)<div id="(?:season|disqus)' - patron = r'<img src="(?P<thumb>[^"]+)">.*?<li class="season-no">(?P<episode>[^<]+)<\/li>(?P<url>.*?javascript:;">)(?P<title>[^<]+)' + patron = r'<img src="(?P<thumb>[^"]+)">.*?<li class="season-no">(?P<episode>[^<]+)<\/li>(?P<url>.*?javascript:;">(?P<title>[^<]+).*?</tbody>)' else: - # patronBlock = r'<div id="info" class="pad">(?P<block>.*?)<div id="disqus_thread">' - # deflang='Sub-ITA' patronBlock = r'(?:STAGIONE|Stagione)(?:<[^>]+>)?\s*(?:(?P<lang>[A-Za-z- ]+))?(?P<block>.*?)(?: |<strong>|<div class="addtoany)' patron = r'(?:/>|p>)\s*(?P<season>\d+)(?:×|×|x)(?P<episode>\d+)[^<]+(?P<url>.*?)(?:<br|</p)' def itemHook(item): @@ -104,17 +87,16 @@ def genres(item): action = 'peliculas' patronBlock = r'<select class="cats">(?P<block>.*?)<\/select>' - patronMenu = r'<option data-src="(?P<url>[^"]+)">(?P<title>.*?)<\/option>' + patronMenu = r'<option data-src="(?P<url>[^"]+)">(?P<title>[^<]+)<\/option>' return locals() def select(item): support.log() - - data = httptools.downloadpage(item.url, headers=headers).data - patronBlock = scrapertools.find_single_match(data, r'class="taxonomy category" ><span property="name">(.*?)</span></a><meta property="position" content="2">') - if patronBlock.lower() != 'film': + patron=r'class="taxonomy category" ><span property="name">([^>]+)</span></a><meta property="position" content="2">' + block = support.match(item.url, patron=patron,headers=headers).match + if block.lower() != 'film': support.log('select = ### è una serie ###') item.contentType='tvshow' return episodios(item) diff --git a/channels/ilgeniodellostreaming.py b/channels/ilgeniodellostreaming.py index 3cbb560e..2c7fb457 100644 --- a/channels/ilgeniodellostreaming.py +++ b/channels/ilgeniodellostreaming.py @@ -213,7 +213,9 @@ def findvideos(item): log() itemlist =[] - matches, data = support.match(item, '<iframe class="metaframe rptss" src="([^"]+)"[^>]+>',headers=headers) + html = support.match(item, patron='<iframe class="metaframe rptss" src="([^"]+)"[^>]+>',headers=headers) + matches = html.matches + data = html.data for url in matches: html = httptools.downloadpage(url, headers=headers).data data += str(scrapertools.find_multiple_matches(html, '<meta name="og:url" content="([^"]+)">')) @@ -224,7 +226,7 @@ def findvideos(item): data = httptools.downloadpage(item.url).data patron = r'<div class="item"><a href="'+host+'/serietv/([^"\/]+)\/"><i class="icon-bars">' - series = scrapertools.find_single_match(data, patron) + series = support.match(data, patron=patron).matches titles = support.typo(series.upper().replace('-', ' '), 'bold color kod') goseries = support.typo("Vai alla Serie:", ' bold') itemlist.append( diff --git a/channels/italiaserie.json b/channels/italiaserie.json index fe68c5c1..a8d184b6 100644 --- a/channels/italiaserie.json +++ b/channels/italiaserie.json @@ -4,8 +4,8 @@ "active": true, "adult": false, "language": ["ita","sub-ita"], - "thumbnail": "https:\/\/raw.githubusercontent.com\/Zanzibar82\/images\/master\/posters\/italiaserie.png", - "bannermenu": "https:\/\/raw.githubusercontent.com\/Zanzibar82\/images\/master\/posters\/italiaserie.png", + "thumbnail": "italiaserie.png", + "bannermenu": "italiaserie.png", "categories": ["tvshow", "vos"], "not_active": ["include_in_newest_peliculas", "include_in_newest_anime"], "settings": [] diff --git a/channels/piratestreaming.py b/channels/piratestreaming.py index c8b797a3..92aa9418 100644 --- a/channels/piratestreaming.py +++ b/channels/piratestreaming.py @@ -99,7 +99,7 @@ def findvideos(item): if item.contentType == 'episode': data = item.url else: - data = support.match(item)[1] + data = support.match(item).data if 'link-episode' in data: item.data = data return episodios(item) diff --git a/channels/pufimovies.json b/channels/pufimovies.json new file mode 100644 index 00000000..5ded05f3 --- /dev/null +++ b/channels/pufimovies.json @@ -0,0 +1,11 @@ +{ + "id": "pufimovies", + "name": "PufiMovies", + "active": true, + "adult": false, + "language": ["ita", "sub-ita"], + "thumbnail": "pufimovies.png", + "banner": "pufimovies.png", + "categories": ["movie","tvshow"], + "settings": [] +} diff --git a/channels/pufimovies.py b/channels/pufimovies.py new file mode 100644 index 00000000..9600c9fe --- /dev/null +++ b/channels/pufimovies.py @@ -0,0 +1,111 @@ +# -*- coding: utf-8 -*- +# ------------------------------------------------------------ +# Canale per PufiMovies +# ------------------------------------------------------------ + +from core import support + +host = support.config.get_channel_url() + +list_servers = ['mixdrop', 'wstream', 'vupplayer', 'supervideo', 'cloudvideo', 'gounlimited'] +list_quality = ['default','1080p', '720p', '480p', '360p'] + +headers = [['Referer', host]] + + +@support.menu +def mainlist(item): + film = [ + ('Generi', ['', 'menu', 'Film']), + ('Più Visti', ['','peliculas', 'most']) + ] + + tvshow = ['', + ('Generi', ['', 'menu', 'Serie Tv']), + ('Ultimi Episodi', ['','peliculas', 'last']) + ] + + search = '' + return locals() + + +@support.scrape +def menu(item): + action = 'peliculas' + patronBlock = item.args + r' Categorie</a>\s*<ul(?P<block>.*?)</ul>' + patronMenu = r'<a href="(?P<url>[^"]+)"[^>]+>(?P<title>[^>]+)<' + return locals() + + +def search(item, text): + support.log('search', item) + + text = text.replace(' ', '+') + item.url = host + '/search/keyword/' + text + try: + item.args = 'search' + return peliculas(item) + # Continua la ricerca in caso di errore + except: + import sys + for line in sys.exc_info(): + support.log('search log:', line) + return [] + + +def newest(categoria): + support.log(categoria) + itemlist = [] + item = support.Item() + item.url = host + item.action = 'peliculas' + try: + if categoria == 'peliculas': + item.contentType = 'movie' + itemlist = peliculas(item) + else: + item.args = 'last' + item.contentType = 'tvshow' + itemlist = peliculas(item) + + if itemlist[-1].action == 'peliculas': + itemlist.pop() + # Continua la ricerca in caso di errore + except: + import sys + for line in sys.exc_info(): + support.log({0}.format(line)) + return [] + + return itemlist + + +@support.scrape +def peliculas(item): + if item.contentType == 'tvshow' and not item.args: + action = 'episodios' + patron = r'<div class="movie-box">\s*<a href="(?P<url>[^"]+)">[^>]+>[^>]+>\D+Streaming\s(?P<lang>[^"]+)[^>]+>[^>]+>[^>]+>(?P<quality>[^<]+)[^>]+>[^>]+>[^>]+>\s*<img src="(?P<thumb>[^"]+)"[^>]+>[^>]+>[^>]+>[^>]+>(?P<rating>[^<]+)<[^>]+>[^>]+>[^>]+>[^>]+>[^>]+>[^>]+>(?P<title>[^<]+)[^>]+>[^>]+>[^>]+>\s*(?P<year>\d+)' + elif item.contentType == 'movie' and not item.args: + patron = r'<div class="existing_item col-6 col-lg-3 col-sm-4 col-xl-4">\s*<div class="movie-box">\s*<a href="(?P<url>(?:http(?:s)://[^/]+)?/(?P<type>[^/]+)/[^"]+)">[^>]+>[^>]+>\D+Streaming\s*(?P<lang>[^"]+)">[^>]+>[^>]+>(?P<quality>[^<]+)<[^>]+>[^>]+>[^>]+>\s*<img src="(?P<thumb>[^"]+)"[^>]+>[^>]+>[^>]+>[^>]+>(?P<rating>[^<]+)<[^>]+>[^>]+>[^>]+>[^>]+>[^>]+>[^>]+>[^>]+>(?P<title>[^<]+)[^>]+>[^>]+>[^>]+>\s*(?:(?P<year>\d+))?[^>]+>[^>]+>[^>]+>[^>]+>(?P<plot>[^<]*)<' + elif item.args == 'last': + patron = r'<div class="episode-box">[^>]+>[^>]+>[^>]+>\D+Streaming\s(?P<lang>[^"]+)">[^>]+>[^>]+>(?P<quality>[^<]+)<[^>]+>[^>]+>[^>]+>[^^>]+>[^>]+>\s*<img src="(?P<thumb>[^"]+)"[^[^>]+>[^>]+>[^>]+>[^>]+>[^>]+>[^>]+>[^>]+>[^>]+>[^>]+>\s*<a href="(?P<url>[^"]+)"[^>]+>[^>]+>(?P<title>[^<]+)<[^>]+>[^>]+>[^>]+>\D*(?P<season>\d+)[^>]+>\D*(?P<episode>\d+)' + elif item.args == 'most': + patron =r'div class="sm-113 item">\s*<a href="(?P<url>[^"]+)">[^>]+>[^>]+>[^>]+>[^>]+>[^>]+>\s<img src="(?P<thumb>[^"]+)"[^>]+>[^>]+>[^>]+>[^>]+>[^>]+>\s*(?P<title>[^<]+)' + else: + patron = r'<div class="movie-box">\s*<a href="(?P<url>(?:http(?:s)://[^/]+)?/(?P<type>[^/]+)/[^"]+)">[^>]+>[^>]+>\D+Streaming\s*(?P<lang>[^"]+)">[^>]+>[^>]+>(?P<quality>[^<]+)<[^>]+>[^>]+>[^>]+>\s*<img src="(?P<thumb>[^"]+)"[^>]+>[^>]+>[^>]+>[^>]+>(?P<rating>[^<]+)<[^>]+>[^>]+>[^>]+>[^>]+>[^>]+>[^>]+>[^>]+>(?P<title>[^<]+)[^>]+>[^>]+>[^>]+>\s*(?:(?P<year>\d+))?[^>]+>[^>]+>[^>]+>[^>]+>(?P<plot>[^<]*)<' + typeActionDict = {'findvideos':['movie'], 'episodios':['tvshow']} + typeContentDict = {'movie':['movie'], 'tvshow':['tvshow']} + patronNext = r'<a href="([^"]+)"[^>]+>»' + return locals() + + +@support.scrape +def episodios(item): + patron = r'<div class="episode-box">[^>]+>[^>]+>[^>]+>\D+Streaming\s(?P<lang>[^"]+)">[^>]+>[^>]+>(?P<quality>[^<]+)<[^>]+>[^>]+>[^>]+>\s*<img src="(?P<thumb>[^"]+)"[^[^>]+>[^>]+>[^>]+>[^>]+>[^>]+>[^>]+>[^>]+>[^>]+>[^>]+>\s*<a href="(?P<url>[^"]+)"[^>]+>[^>]+>(?P<title>[^<]+)<[^>]+>[^>]+>[^>]+>\D*(?P<season>\d+)[^>]+>\D*(?P<episode>\d+)' + return locals() + + +def findvideos(item): + support.log() + # match = support.match(item, patron='wstream', debug=True) + return support.server(item) diff --git a/channels/seriehd.py b/channels/seriehd.py index a60c691e..95536858 100644 --- a/channels/seriehd.py +++ b/channels/seriehd.py @@ -34,11 +34,11 @@ def peliculas(item): @support.scrape def episodios(item): data ='' - url = support.match(item, patronBlock=r'<iframe width=".+?" height=".+?" src="([^"]+)" allowfullscreen frameborder="0">')[1] - seasons = support.match(item, r'<a href="([^"]+)">(\d+)<', r'<h3>STAGIONE</h3><ul>(.*?)</ul>', headers, url)[0] + url = support.match(item, patron=r'<iframe width=".+?" height=".+?" src="([^"]+)" allowfullscreen frameborder="0">').match + seasons = support.match(url, patron=r'<a href="([^"]+)">(\d+)<', patronBlock=r'<h3>STAGIONE</h3><ul>(.*?)</ul>', headers=headers).matches for season_url, season in seasons: season_url = support.urlparse.urljoin(url, season_url) - episodes = support.match(item, r'<a href="([^"]+)">(\d+)<', '<h3>EPISODIO</h3><ul>(.*?)</ul>', headers, season_url)[0] + episodes = support.match(season_url, patron=r'<a href="([^"]+)">(\d+)<', patronBlock=r'<h3>EPISODIO</h3><ul>(.*?)</ul>', headers=headers).matches for episode_url, episode in episodes: episode_url = support.urlparse.urljoin(url, episode_url) title = season + "x" + episode.zfill(2) + ' - ' + item.fulltitle diff --git a/channels/serietvsubita.py b/channels/serietvsubita.py index 1345fffa..47cb8850 100644 --- a/channels/serietvsubita.py +++ b/channels/serietvsubita.py @@ -108,7 +108,7 @@ def lista_serie(item): else: # Extrae las entradas patron = r'<li class="cat-item cat-item-\d+"><a href="([^"]+)"\s?>([^<]+)</a>' - matches = support.match(item, patron, headers=headers)[0] + matches = support.match(item, patron=patron, headers=headers).matches for i, (scrapedurl, scrapedtitle) in enumerate(matches): scrapedplot = "" scrapedthumbnail = "" @@ -148,7 +148,9 @@ def episodios(item, itemlist=[]): patron += r'<p><a href="([^"]+)">' - matches, data = support.match(item, patron, headers=headers) + html = support.match(item, patron=patron, headers=headers) + matches = html.matches + data = html.data for scrapedurl, scrapedtitle, scrapedthumbnail in matches: scrapedplot = "" @@ -224,7 +226,9 @@ def peliculas_tv(item): patron = '<div class="post-meta">\s*<a href="([^"]+)"\s*title="([^"]+)"\s*class=".*?"></a>' - matches, data = support.match(item, patron, headers=headers) + html = support.match(item, patron=patron, headers=headers) + matches = html.matches + data = html.data for scrapedurl, scrapedtitle in matches: if scrapedtitle in ["FACEBOOK", "RAPIDGATOR", "WELCOME!"]: @@ -298,7 +302,7 @@ def search(item, texto): itemlist = [] patron = '<li class="cat-item cat-item-\d+"><a href="([^"]+)"\s?>([^<]+)</a>' - matches = support.match(item, patron, headers=headers)[0] + matches = support.match(item, patron=patron, headers=headers).matches for i, (scrapedurl, scrapedtitle) in enumerate(matches): if texto.upper() in scrapedtitle.upper(): scrapedthumbnail = "" @@ -333,7 +337,7 @@ def list_az(item): alphabet = dict() patron = '<li class="cat-item cat-item-\d+"><a href="([^"]+)"\s?>([^<]+)</a>' - matches = support.match(item, patron, headers=headers)[0] + matches = support.match(item, patron=patron, headers=headers).matches for i, (scrapedurl, scrapedtitle) in enumerate(matches): letter = scrapedtitle[0].upper() if letter not in alphabet: diff --git a/channels/serietvu.py b/channels/serietvu.py index c4c9bd2f..9c9a92db 100644 --- a/channels/serietvu.py +++ b/channels/serietvu.py @@ -35,7 +35,6 @@ def mainlist(item): def peliculas(item): patronBlock = r'<div class="wrap">\s*<h.>.*?</h.>(?P<block>.*?)<footer>' - if item.args != 'update': action = 'episodios' patron = r'<div class="item">\s*<a href="(?P<url>[^"]+)" data-original="(?P<thumb>[^"]+)" class="lazy inner">[^>]+>[^>]+>[^>]+>[^>]+>(?P<title>[^<]+)<' @@ -50,14 +49,15 @@ def peliculas(item): @support.scrape def episodios(item): - seasons, data = support.match(item, r'<option value="(\d+)"[^>]*>\D+(\d+)') + seasons = support.match(item, patron=r'<option value="(\d+)"[^>]*>\D+(\d+)').matches patronBlock = r'</select><div style="clear:both"></div></h2>(?P<block>.*?)<div id="trailer" class="tab">' - patron = r'(?:<div class="list (?:active)?" data-id="(?P<season>\d+)">[^>]+>)?\s*<a data-id="(?P<episode>\d+)(?:[ ](?P<lang>[SuUbBiItTaA\-]+))?"(?P<url>[^>]+)>[^>]+>[^>]+>(?P<title>.+?)(?:\sSub-ITA)?<' + patron = r'(?:<div class="list (?:active)?")?\s*<a data-id="\d+(?:[ ](?P<lang>[SuUbBiItTaA\-]+))?"(?P<other>[^>]+)>.*?Episodio [0-9]+\s?(?:<br>(?P<title>[^<]+))?.*?Stagione (?P<season>[0-9]+) , Episodio - (?P<episode>[0-9]+).*?<(?P<url>.*?<iframe)' def itemHook(item): for value, season in seasons: log(value) log(season) item.title = item.title.replace(value+'x',season+'x') + item.url += '\n' + item.other return item return locals() @@ -110,7 +110,11 @@ def newest(categoria): def findvideos(item): log() if item.args != 'update': - return support.server(item, data=item.url) + data = item.url + toUnshorten = scrapertools.find_multiple_matches(data, 'https?://buckler.link/[a-zA-Z0-9]+') + for link in toUnshorten: + data += '\n' + httptools.downloadpage(link, follow_redirects=False).headers["Location"] + return support.server(item, data=data) else: itemlist = [] item.infoLabels['mediatype'] = 'episode' diff --git a/channels/streamtime.py b/channels/streamtime.py index 3aad1040..e32056f3 100644 --- a/channels/streamtime.py +++ b/channels/streamtime.py @@ -149,15 +149,15 @@ def findvideos(item): id = item.args['id'] season = str(item.args['season']) episode = str(item.args['episode']) - res = support.match(item, 'src="([^"]+)"[^>]*></video>', url=url, headers=[['Referer', domain]]) + res = support.match(url, patron='src="([^"]+)"[^>]*></video>', headers=[['Referer', domain]]).match itemlist = [] - if res[0]: + if res: itemlist.append( Item(channel=item.channel, action="play", title='contentful', - url=res[0][0], + url=res, server='directo', fulltitle=item.fulltitle, thumbnail=item.thumbnail, diff --git a/channels/tantifilm.py b/channels/tantifilm.py index 9b17b2d8..6582b3d9 100644 --- a/channels/tantifilm.py +++ b/channels/tantifilm.py @@ -124,7 +124,7 @@ def anime(item): log() itemlist = [] - seasons = support.match(item, r'<div class="sp-body[^"]+">(.*?)<\/div>')[0] + seasons = support.match(item, patron=r'<div class="sp-body[^"]+">(.*?)<\/div>').matches for season in seasons: episodes = scrapertools.find_multiple_matches(season, r'<a.*?href="([^"]+)"[^>]+>([^<]+)<\/a>(.*?)<(:?br|\/p)') for url, title, urls, none in episodes: @@ -208,7 +208,7 @@ def newest(categoria): item = Item() item.url = host +'/aggiornamenti/' - matches = support.match(item, r'mediaWrapAlt recomended_videos"[^>]+>\s*<a href="([^"]+)" title="([^"]+)" rel="bookmark">\s*<img[^s]+src="([^"]+)"[^>]+>')[0] + matches = support.match(item, patron=r'mediaWrapAlt recomended_videos"[^>]+>\s*<a href="([^"]+)" title="([^"]+)" rel="bookmark">\s*<img[^s]+src="([^"]+)"[^>]+>').matches for url, title, thumb in matches: title = scrapertools.decodeHtmlentities(title).replace("Permalink to ", "").replace("streaming", "") @@ -236,11 +236,11 @@ def findvideos(item): ## data = item.url ## else: ## data = httptools.downloadpage(item.url, headers=headers).data - data = httptools.downloadpage(item.url, headers=headers).data + data = support.match(item.url, headers=headers).data data = re.sub('\n|\t', ' ', data) data = re.sub(r'>\s+<', '> <', data) - check = scrapertools.find_single_match(data, r'<div class="category-film">\s+<h3>\s+(.*?)\s+</h3>\s+</div>') + check = support.match(data, patron=r'<div class="category-film">\s+<h3>\s+(.*?)\s+</h3>\s+</div>').match if 'sub' in check.lower(): item.contentLanguage = 'Sub-ITA' support.log("CHECK : ", check) diff --git a/channels/toonitalia.py b/channels/toonitalia.py index 7736f26d..5f6dbef2 100644 --- a/channels/toonitalia.py +++ b/channels/toonitalia.py @@ -104,7 +104,7 @@ def peliculas(item): @support.scrape def episodios(item): anime = True - data = support.match(item, headers=headers)[1] + data = support.match(item, headers=headers).data if 'https://vcrypt.net' in data: patron = r'(?:<br /> |<p>)(?P<title>[^<]+)<a href="(?P<url>[^"]+)"' else: diff --git a/channels/vedohd.json b/channels/vedohd.json index 2109a2b1..e21ccead 100644 --- a/channels/vedohd.json +++ b/channels/vedohd.json @@ -4,33 +4,8 @@ "language": ["ita"], "active": true, "adult": false, - "thumbnail": "https://vedohd.pw/wp-content/uploads/2018/12/imgpsh_fullsize.png", - "banner": "https://vedohd.pw/wp-content/uploads/2018/12/imgpsh_fullsize.png", + "thumbnail": "vedohd.png", + "banner": "vedohd.png", "categories": ["movie"], - "settings": [ - { - "id": "include_in_global_search", - "type": "bool", - "label": "Includi in Ricerca Globale", - "default": true, - "enabled": true, - "visible": true - }, - { - "id": "include_in_newest_peliculas", - "type": "bool", - "label": "Includi in Novità - Film", - "default": true, - "enabled": true, - "visible": true - }, - { - "id": "include_in_newest_italiano", - "type": "bool", - "label": "Includi in Novità - Italiano", - "default": true, - "enabled": true, - "visible": true - } - ] + "settings": [] } diff --git a/channels/vvvvid.py b/channels/vvvvid.py index 7c4975ef..02e8dce1 100644 --- a/channels/vvvvid.py +++ b/channels/vvvvid.py @@ -131,7 +131,7 @@ def peliculas(item): elif '=' in item.args: json_file = current_session.get(item.url + 'channels', headers=headers, params=payload).json() - Filter = support.match(item.args,r'\?([^=]+)=')[0][0] + Filter = support.match(item.args, patron=r'\?([^=]+)=').match keys = [i[Filter] for i in json_file['data'] if Filter in i][0] for key in keys: if key not in ['1','2']: @@ -162,7 +162,7 @@ def episodios(item): for episode in episodes: for key in episode: if 'stagione' in key['title'].encode('utf8').lower(): - match = support.match(key['title'].encode('utf8'), r'[Ss]tagione\s*(\d+) - [Ee]pisodio\s*(\d+)')[0][0] + match = support.match(key['title'].encode('utf8'), patron=r'[Ss]tagione\s*(\d+) - [Ee]pisodio\s*(\d+)').match title = match[0]+'x'+match[1] + ' - ' + item.fulltitle make_item = True elif int(key['season_id']) == int(season_id): @@ -206,7 +206,7 @@ def findvideos(item): if 'youtube' in url: item.url = url item.url = url.replace('manifest.f4m','master.m3u8').replace('http://','https://').replace('/z/','/i/') if 'https' not in item.url: - url = support.match(item, url='https://or01.top-ix.org/videomg/_definst_/mp4:' + item.url + '/playlist.m3u')[1] + url = support.match('https://or01.top-ix.org/videomg/_definst_/mp4:' + item.url + '/playlist.m3u') url = url.split()[-1] itemlist.append( Item(action= 'play', diff --git a/channelselector.py b/channelselector.py index 080c73c8..ebc672a2 100644 --- a/channelselector.py +++ b/channelselector.py @@ -313,8 +313,8 @@ def set_channel_info(parameters): else: content = config.get_localized_category(cat) - info = '[COLOR yellow]' + config.get_localized_string(70567) + ' [/COLOR]' + content + '\n\n' - info += '[COLOR yellow]' + config.get_localized_string(70568) + ' [/COLOR] ' + language + info = '[B]' + config.get_localized_string(70567) + ' [/B]' + content + '\n\n' + info += '[B]' + config.get_localized_string(70568) + ' [/B] ' + language return info diff --git a/core/scraper.py b/core/scraper.py index 73bef114..5d3c9f95 100644 --- a/core/scraper.py +++ b/core/scraper.py @@ -123,7 +123,7 @@ def cuadro_completar(item): global dict_default dict_default = {} - COLOR = ["0xFF8A4B08", "0xFFF7BE81"] + COLOR = ["0xFF65B3DA", "0xFFFFFFFF"] # Creamos la lista de campos del infoLabel controls = [("title", "text", config.get_localized_string(60230)), ("originaltitle", "text", config.get_localized_string(60231)), diff --git a/core/support.py b/core/support.py index b706e3de..dc44f8ab 100755 --- a/core/support.py +++ b/core/support.py @@ -180,7 +180,7 @@ def scrapeBlock(item, args, block, patron, headers, action, pagination, debug, t if debug: regexDbg(item, patron, headers, block) - known_keys = ['url', 'title', 'title2', 'season', 'episode', 'thumb', 'quality', 'year', 'plot', 'duration', 'genere', 'rating', 'type', 'lang'] + known_keys = ['url', 'title', 'title2', 'season', 'episode', 'thumb', 'quality', 'year', 'plot', 'duration', 'genere', 'rating', 'type', 'lang', 'other'] # Legenda known_keys per i groups nei patron # known_keys = ['url', 'title', 'title2', 'season', 'episode', 'thumb', 'quality', # 'year', 'plot', 'duration', 'genere', 'rating', 'type', 'lang'] @@ -201,8 +201,8 @@ def scrapeBlock(item, args, block, patron, headers, action, pagination, debug, t stagione = '' # per quei siti che hanno la stagione nel blocco ma non nelle puntate for i, match in enumerate(matches): - if pagination and (pag - 1) * pagination > i: continue # pagination - if pagination and i >= pag * pagination: break # pagination + if pagination and (pag - 1) * pagination > i and not search: continue # pagination + if pagination and i >= pag * pagination and not search: break # pagination listGroups = match.keys() match = match.values() @@ -214,12 +214,12 @@ def scrapeBlock(item, args, block, patron, headers, action, pagination, debug, t for kk in known_keys: val = match[listGroups.index(kk)] if kk in listGroups else '' if val and (kk == "url" or kk == 'thumb') and 'http' not in val: - val = scrapertools.find_single_match(item.url, 'https?://[a-z0-9.-]+') + val + val = scrapertools.find_single_match(item.url, 'https?://[a-z0-9.-]+') + (val if val.startswith('/') else '/' + val) scraped[kk] = val if scraped['season']: stagione = scraped['season'] - episode = scraped['season'] +'x'+ scraped['episode'] + episode = scraped['season'] +'x'+ scraped['episode'].zfill(2) elif item.season: episode = item.season +'x'+ scraped['episode'] elif item.contentType == 'tvshow' and (scraped['episode'] == '' and scraped['season'] == '' and stagione == ''): @@ -295,13 +295,14 @@ def scrapeBlock(item, args, block, patron, headers, action, pagination, debug, t quality=quality, url=scraped["url"], infoLabels=infolabels, - thumbnail=item.thumbnail if function == 'episodios' else scraped["thumb"] , + thumbnail=item.thumbnail if function == 'episodios' and not scraped["thumb"] else scraped["thumb"] , args=item.args, contentSerieName= scraped['title'] if item.contentType or CT != 'movie' and function != 'episodios' else item.fulltitle if function == 'episodios' else '', contentTitle= scraped['title'] if item.contentType or CT == 'movie' else '', contentLanguage = lang1, contentEpisodeNumber=episode if episode else '', - news= item.news if item.news else '' + news= item.news if item.news else '', + other = scraped['other'] if scraped['other'] else '' ) for lg in list(set(listGroups).difference(known_keys)): @@ -445,7 +446,7 @@ def scrape(func): if anime: if function == 'episodios' or item.action == 'episodios': autorenumber.renumber(itemlist, item, 'bold') else: autorenumber.renumber(itemlist) - if anime and autorenumber.check(item) == False and not scrapertools.find_single_match(itemlist[0].title, r'(\d+.\d+)'): + if anime and autorenumber.check(item) == False and len(itemlist)>0 and not scrapertools.find_single_match(itemlist[0].title, r'(\d+.\d+)'): pass else: if addVideolibrary and (item.infoLabels["title"] or item.fulltitle): @@ -637,8 +638,9 @@ def menu(func): item = args['item'] host = func.__globals__['host'] - list_servers = func.__globals__['list_servers'] if 'list_servers' in func.__globals__ else 'directo' - list_quality = func.__globals__['list_quality'] if 'list_quality' in func.__globals__ else 'default' + list_servers = func.__globals__['list_servers'] if 'list_servers' in func.__globals__ else ['directo'] + list_quality = func.__globals__['list_quality'] if 'list_quality' in func.__globals__ else ['default'] + log('LIST QUALITY', list_quality) filename = func.__module__.split('.')[1] global_search = False # listUrls = ['film', 'filmSub', 'tvshow', 'tvshowSub', 'anime', 'animeSub', 'search', 'top', 'topSub'] @@ -772,31 +774,91 @@ def typo(string, typography=''): return string -def match(item, patron='', patronBlock='', headers='', url='', post=''): +def match(item_url_string, **args): + ''' + match is a function that combines httptools and scraper tools: + ''' + log(item_url_string) + matches = [] - if type(item) == str: - data = item + url = None + # arguments allowed for scrape + patron = args.get('patron', None) + patronBlock = args.get('patronBlock', None) + patronBlocks = args.get('patronBlock', None) + debug = args.get('debug', False) + debugBlock = args.get('debugBlock', False) + string = args.get('string', False) + # remove scrape arguments + args = dict([(key, val) for key, val in args.items() if key not in ['patron', 'patronBlock', 'patronBlocks', 'debug', 'debugBlock', 'string']]) + # dbg() + # check type of item_url_string + if type(item_url_string) == str: + if item_url_string.startswith('http') and not string: url = item_url_string + else : data = item_url_string else: - url = url if url else item.url - if post: - data = httptools.downloadpage(url, headers=headers, ignore_response_code=True, post=post).data.replace("'", '"') - else: - data = httptools.downloadpage(url, headers=headers, ignore_response_code=True).data.replace("'", '"') + # if item_url_string is an item use item.url as url + url = item_url_string.url + + # if there is a url, download the page + if url: + if args.get('ignore_response_code', None) is None: + args['ignore_response_code'] = True + data = httptools.downloadpage(url, **args).data.replace("'", '"') + + # format page data data = re.sub(r'\n|\t', ' ', data) data = re.sub(r'>\s\s*<', '><', data) - log('DATA= ', data) + # collect blocks of a page if patronBlock: - block = scrapertools.find_single_match(data, patronBlock) - log('BLOCK= ',block) + blocks = [scrapertools.find_single_match(data, patronBlock)] + elif patronBlocks: + blocks = scrapertools.find_multiple_matches(data, patronBlock) else: - block = data + blocks = [data] + # match if patron: - matches = scrapertools.find_multiple_matches(block, patron) - log('MATCHES= ',matches) + if type(patron) == str: patron = [patron] + for b in blocks: + for p in patron: + matches += scrapertools.find_multiple_matches(b, p) - return matches, block + # debug mode + if config.dev_mode(): + if debugBlock: + match_dbg(data, patronBlock) + if debug: + for block in blocks: + for p in patron: + match_dbg(block, p) + + # create a item + item = Item(data=data, + blocks=blocks, + block=blocks[0] if len(blocks) > 0 else '', + matches=matches, + match=matches[0] if len(matches) > 0 else '') + + return item + + +def match_dbg(data, patron): + import json, urllib2, webbrowser + url = 'https://regex101.com' + headers = {'content-type': 'application/json'} + data = { + 'regex': patron, + 'flags': 'gm', + 'testString': data, + 'delimiter': '"""', + 'flavor': 'python' + } + r = urllib2.Request(url + '/api/regex', json.dumps(data, encoding='latin1'), headers=headers) + r = urllib2.urlopen(r).read() + permaLink = json.loads(r)['permalinkFragment'] + webbrowser.open(url + "/r/" + permaLink) def download(itemlist, item, typography='', function_level=1, function=''): @@ -981,7 +1043,7 @@ def controls(itemlist, item, AutoPlay=True, CheckLinks=True, down_load=True): channel_node = autoplay_node.get(item.channel, {}) settings_node = channel_node.get('settings', {}) AP = get_setting('autoplay') or settings_node['active'] - APS = get_setting('autoplay_server_list') + HS = config.get_setting('hide_servers') if CL and not AP: if get_setting('checklinks', item.channel): @@ -994,7 +1056,7 @@ def controls(itemlist, item, AutoPlay=True, CheckLinks=True, down_load=True): checklinks_number = get_setting('checklinks_number') itemlist = servertools.check_list_links(itemlist, checklinks_number) - if AutoPlay == True and not 'downloads' in inspect.stack()[3][1] + inspect.stack()[4][1] and item.contentChannel != 'videolibrary': + if AutoPlay == True and not 'downloads' in inspect.stack()[3][1] + inspect.stack()[4][1]: autoplay.start(itemlist, item) if item.contentChannel != 'videolibrary': videolibrary(itemlist, item, function_level=3) @@ -1010,7 +1072,7 @@ def controls(itemlist, item, AutoPlay=True, CheckLinks=True, down_load=True): VL = True except: pass - if not AP or VL or not APS: + if not AP or VL or not HS: return itemlist def filterLang(item, itemlist): diff --git a/core/tmdb.py b/core/tmdb.py index 65c6ff0b..a369f6d0 100644 --- a/core/tmdb.py +++ b/core/tmdb.py @@ -160,7 +160,7 @@ def cache_response(fn): conn = sqlite3.connect(fname, timeout=15) c = conn.cursor() url = re.sub('&year=-', '', args[0]) - logger.error('la url %s' % url) + # logger.error('la url %s' % url) url_base64 = base64.b64encode(url) c.execute("SELECT response, added FROM tmdb_cache WHERE url=?", (url_base64,)) row = c.fetchone() @@ -185,7 +185,7 @@ def cache_response(fn): # error al obtener los datos except Exception, ex: message = "An exception of type %s occured. Arguments:\n%s" % (type(ex).__name__, repr(ex.args)) - logger.error("error en: %s" % message) + logger.error("error in: %s" % message) return result @@ -214,10 +214,10 @@ def set_infoLabels(source, seekTmdb=True, idioma_busqueda=def_lang, forced=False start_time = time.time() if type(source) == list: ret = set_infoLabels_itemlist(source, seekTmdb, idioma_busqueda) - logger.debug("Se han obtenido los datos de %i enlaces en %f segundos" % (len(source), time.time() - start_time)) + logger.debug("The data of %i links were obtained in %f seconds" % (len(source), time.time() - start_time)) else: ret = set_infoLabels_item(source, seekTmdb, idioma_busqueda) - logger.debug("Se han obtenido los datos del enlace en %f segundos" % (time.time() - start_time)) + logger.debug("The data of %i links were obtained in %f seconds" % (time.time() - start_time)) return ret @@ -242,6 +242,7 @@ def set_infoLabels_itemlist(item_list, seekTmdb=False, idioma_busqueda=def_lang, negativo en caso contrario. @rtype: list """ + if not config.get_setting('tmdb_active') and not forced: return import threading @@ -314,7 +315,7 @@ def set_infoLabels_item(item, seekTmdb=True, idioma_busqueda=def_lang, lock=None try: numtemporada = int(item.infoLabels['season']) except ValueError: - logger.debug("El numero de temporada no es valido") + logger.debug("The season number is not valid.") return -1 * len(item.infoLabels) if lock: @@ -340,7 +341,7 @@ def set_infoLabels_item(item, seekTmdb=True, idioma_busqueda=def_lang, lock=None try: episode = int(item.infoLabels['episode']) except ValueError: - logger.debug("El número de episodio (%s) no es valido" % repr(item.infoLabels['episode'])) + logger.debug("The episode number (%s) is not valid" % repr(item.infoLabels['episode'])) return -1 * len(item.infoLabels) # Tenemos numero de temporada y numero de episodio validos... @@ -847,7 +848,7 @@ class Tmdb(object): self.__discover() else: - logger.debug("Creado objeto vacio") + logger.debug("Created empty object") @staticmethod @cache_response @@ -879,7 +880,7 @@ class Tmdb(object): # error al obtener los datos except Exception, ex: message = "An exception of type %s occured. Arguments:\n%s" % (type(ex).__name__, repr(ex.args)) - logger.error("error en: %s" % message) + logger.error("error in: %s" % message) dict_data = {} return dict_data @@ -895,7 +896,7 @@ class Tmdb(object): url = ('http://api.themoviedb.org/3/genre/%s/list?api_key=a1ab8b8669da03637a4b98fa39c39228&language=%s' % (tipo, idioma)) try: - logger.info("[Tmdb.py] Rellenando dicionario de generos") + logger.info("[Tmdb.py] Filling in dictionary of genres") resultado = cls.get_json(url) lista_generos = resultado["genres"] @@ -903,7 +904,7 @@ class Tmdb(object): for i in lista_generos: cls.dic_generos[idioma][tipo][str(i["id"])] = i["name"] except: - logger.error("Error generando diccionarios") + logger.error("Error generating dictionaries") def __by_id(self, source='tmdb'): @@ -923,7 +924,7 @@ class Tmdb(object): '&language=%s' % (self.busqueda_id, source, self.busqueda_idioma)) buscando = "%s: %s" % (source.capitalize(), self.busqueda_id) - logger.info("[Tmdb.py] Buscando %s:\n%s" % (buscando, url)) + logger.info("[Tmdb.py] Searching %s:\n%s" % (buscando, url)) resultado = self.get_json(url) if resultado: @@ -940,8 +941,8 @@ class Tmdb(object): else: # No hay resultados de la busqueda - msg = "La busqueda de %s no dio resultados." % buscando - logger.debug(msg) + msg = "The search of %s gave no results" % buscando + # logger.debug(msg) def __search(self, index_results=0, page=1): self.result = ResultDictDefault() @@ -963,7 +964,7 @@ class Tmdb(object): url += '&year=%s' % self.busqueda_year buscando = self.busqueda_texto.capitalize() - logger.info("[Tmdb.py] Buscando %s en pagina %s:\n%s" % (buscando, page, url)) + logger.info("[Tmdb.py] Searching %s on page %s:\n%s" % (buscando, page, url)) resultado = self.get_json(url) total_results = resultado.get("total_results", 0) @@ -984,7 +985,7 @@ class Tmdb(object): if index_results >= len(results): # Se ha solicitado un numero de resultado mayor de los obtenidos logger.error( - "La busqueda de '%s' dio %s resultados para la pagina %s\nImposible mostrar el resultado numero %s" + "The search for '%s' gave %s results for the page %s \n It is impossible to show the result number %s" % (buscando, len(results), page, index_results)) return 0 @@ -997,7 +998,7 @@ class Tmdb(object): else: # No hay resultados de la busqueda - msg = "La busqueda de '%s' no dio resultados para la pagina %s" % (buscando, page) + msg = "The search for '%s' gave no results for page %s" % (buscando, page) logger.error(msg) return 0 @@ -1021,7 +1022,7 @@ class Tmdb(object): url = ('http://api.themoviedb.org/3/%s?api_key=a1ab8b8669da03637a4b98fa39c39228&%s' % (type_search, "&".join(params))) - logger.info("[Tmdb.py] Buscando %s:\n%s" % (type_search, url)) + logger.info("[Tmdb.py] Searcing %s:\n%s" % (type_search, url)) resultado = self.get_json(url) total_results = resultado.get("total_results", -1) @@ -1045,7 +1046,7 @@ class Tmdb(object): if index_results >= len(results): logger.error( - "La busqueda de '%s' no dio %s resultados" % (type_search, index_results)) + "The search for '%s' did not give %s results" % (type_search, index_results)) return 0 # Retornamos el numero de resultados de esta pagina @@ -1061,7 +1062,7 @@ class Tmdb(object): return len(self.results) else: # No hay resultados de la busqueda - logger.error("La busqueda de '%s' no dio resultados" % type_search) + logger.error("The search for '%s' gave no results" % type_search) return 0 def load_resultado(self, index_results=0, page=1): @@ -1311,20 +1312,20 @@ class Tmdb(object): url = "http://api.themoviedb.org/3/tv/%s/season/%s?api_key=a1ab8b8669da03637a4b98fa39c39228&language=%s" \ "&append_to_response=credits" % (self.result["id"], numtemporada, self.busqueda_idioma) - buscando = "id_Tmdb: " + str(self.result["id"]) + " temporada: " + str(numtemporada) + "\nURL: " + url - logger.info("[Tmdb.py] Buscando " + buscando) + buscando = "id_Tmdb: " + str(self.result["id"]) + " season: " + str(numtemporada) + "\nURL: " + url + logger.info("[Tmdb.py] Searcing " + buscando) try: self.temporada[numtemporada] = self.get_json(url) except: - logger.error("No se ha podido obtener la temporada") + logger.error("Unable to get the season") self.temporada[numtemporada] = {"status_code": 15, "status_message": "Failed"} self.temporada[numtemporada] = {"episodes": {}} if "status_code" in self.temporada[numtemporada]: #Se ha producido un error msg = config.get_localized_string(70496) + buscando + config.get_localized_string(70497) - msg += "\nError de tmdb: %s %s" % ( + msg += "\nTmdb error: %s %s" % ( self.temporada[numtemporada]["status_code"], self.temporada[numtemporada]["status_message"]) logger.debug(msg) self.temporada[numtemporada] = {} @@ -1351,7 +1352,7 @@ class Tmdb(object): capitulo = int(capitulo) numtemporada = int(numtemporada) except ValueError: - logger.debug("El número de episodio o temporada no es valido") + logger.debug("The episode or season number is not valid") return {} temporada = self.get_temporada(numtemporada) @@ -1361,7 +1362,7 @@ class Tmdb(object): if len(temporada["episodes"]) == 0 or len(temporada["episodes"]) < capitulo: # Se ha producido un error - logger.error("Episodio %d de la temporada %d no encontrado." % (capitulo, numtemporada)) + logger.error("Episode %d of the season %d not found." % (capitulo, numtemporada)) return {} ret_dic = dict() diff --git a/lib/cloudscraper/__init__.py b/lib/cloudscraper/__init__.py index 541b32cf..f4e584e5 100644 --- a/lib/cloudscraper/__init__.py +++ b/lib/cloudscraper/__init__.py @@ -1,4 +1,3 @@ -# https://github.com/VeNoMouS/cloudscraper import logging import re import sys @@ -38,7 +37,7 @@ except ImportError: # ------------------------------------------------------------------------------- # -__version__ = '1.2.16' +__version__ = '1.2.19' # ------------------------------------------------------------------------------- # @@ -163,7 +162,6 @@ class CloudScraper(Session): def request(self, method, url, *args, **kwargs): # pylint: disable=E0203 - if kwargs.get('proxies') and kwargs.get('proxies') != self.proxies: self.proxies = kwargs.get('proxies') @@ -198,6 +196,7 @@ class CloudScraper(Session): else: if not resp.is_redirect and resp.status_code not in [429, 503]: self._solveDepthCnt = 0 + return resp # ------------------------------------------------------------------------------- # @@ -243,7 +242,7 @@ class CloudScraper(Session): return False # ------------------------------------------------------------------------------- # - # check if the response contains a valid Cloudflare reCaptcha challenge + # check if the response contains Firewall 1020 Error # ------------------------------------------------------------------------------- # @staticmethod @@ -270,10 +269,7 @@ class CloudScraper(Session): def is_Challenge_Request(self, resp): if self.is_Firewall_Blocked(resp): sys.tracebacklimit = 0 - raise RuntimeError( - 'Cloudflare has a restriction on your IP (Code 1020 Detected), ' - 'you are BLOCKED.' - ) + raise RuntimeError('Cloudflare has blocked this request (Code 1020 Detected).') if self.is_reCaptcha_Challenge(resp) or self.is_IUAM_Challenge(resp): return True @@ -434,6 +430,7 @@ class CloudScraper(Session): # ------------------------------------------------------------------------------- # if submit_url: + def updateAttr(obj, name, newValue): try: obj[name].update(newValue) @@ -450,13 +447,18 @@ class CloudScraper(Session): 'data', submit_url['data'] ) + + urlParsed = urlparse(resp.url) cloudflare_kwargs['headers'] = updateAttr( cloudflare_kwargs, 'headers', - {'Referer': resp.url} + { + 'Origin': '{}://{}'.format(urlParsed.scheme, urlParsed.netloc), + 'Referer': resp.url + } ) - ret = self.request( + challengeSubmitResponse = self.request( 'POST', submit_url['url'], **cloudflare_kwargs @@ -464,13 +466,44 @@ class CloudScraper(Session): # ------------------------------------------------------------------------------- # # Return response if Cloudflare is doing content pass through instead of 3xx + # else request with redirect URL also handle protocol scheme change http -> https # ------------------------------------------------------------------------------- # - if not ret.is_redirect: - return ret + if not challengeSubmitResponse.is_redirect: + return challengeSubmitResponse + else: + cloudflare_kwargs = deepcopy(kwargs) + + if not urlparse(challengeSubmitResponse.headers['Location']).netloc: + cloudflare_kwargs['headers'] = updateAttr( + cloudflare_kwargs, + 'headers', + {'Referer': '{}://{}'.format(urlParsed.scheme, urlParsed.netloc)} + ) + return self.request( + resp.request.method, + '{}://{}{}'.format( + urlParsed.scheme, + urlParsed.netloc, + challengeSubmitResponse.headers['Location'] + ), + **cloudflare_kwargs + ) + else: + redirectParsed = urlparse(challengeSubmitResponse.headers['Location']) + cloudflare_kwargs['headers'] = updateAttr( + cloudflare_kwargs, + 'headers', + {'Referer': '{}://{}'.format(redirectParsed.scheme, redirectParsed.netloc)} + ) + return self.request( + resp.request.method, + challengeSubmitResponse.headers['Location'], + **cloudflare_kwargs + ) # ------------------------------------------------------------------------------- # - # Cloudflare is doing http 3xx instead of pass through again.... + # We shouldn't be here... # Re-request the original query and/or process again.... # ------------------------------------------------------------------------------- # @@ -554,6 +587,17 @@ class CloudScraper(Session): # ------------------------------------------------------------------------------- # +if ssl.OPENSSL_VERSION_INFO < (1, 1, 1): + print( + "DEPRECATION: The OpenSSL being used by this python install ({}) does not meet the minimum supported " + "version (>= OpenSSL 1.1.1) in order to support TLS 1.3 required by Cloudflare, " + "You may encounter an unexpected reCaptcha or cloudflare 1020 blocks.".format( + ssl.OPENSSL_VERSION + ) + ) + +# ------------------------------------------------------------------------------- # + create_scraper = CloudScraper.create_scraper get_tokens = CloudScraper.get_tokens get_cookie_string = CloudScraper.get_cookie_string diff --git a/lib/unshortenit.py b/lib/unshortenit.py index f87e4297..224e5adf 100644 --- a/lib/unshortenit.py +++ b/lib/unshortenit.py @@ -37,7 +37,7 @@ class UnshortenIt(object): _rapidcrypt_regex = r'rapidcrypt\.net' _cryptmango_regex = r'cryptmango|xshield\.net' _vcrypt_regex = r'vcrypt\.net' - _linkup_regex = r'linkup\.pro' + _linkup_regex = r'linkup\.pro|buckler.link' _maxretries = 5 diff --git a/platformcode/launcher.py b/platformcode/launcher.py index 31f604c0..c89d7a7d 100644 --- a/platformcode/launcher.py +++ b/platformcode/launcher.py @@ -429,6 +429,7 @@ def limit_itemlist(itemlist): def play_from_library(item): + itemlist=[] """ Los .strm al reproducirlos desde kodi, este espera que sea un archivo "reproducible" asi que no puede contener más items, como mucho se puede colocar un dialogo de seleccion. @@ -440,12 +441,13 @@ def play_from_library(item): @param item: elemento con información """ logger.info() - #logger.debug("item: \n" + item.tostring('\n')) + # logger.debug("item: \n" + item.tostring('\n')) import xbmcgui import xbmcplugin import xbmc - from time import sleep + from time import sleep, time + from specials import nextep # Intentamos reproducir una imagen (esto no hace nada y ademas no da error) xbmcplugin.setResolvedUrl(int(sys.argv[1]), True, @@ -458,8 +460,10 @@ def play_from_library(item): # modificamos el action (actualmente la videoteca necesita "findvideos" ya que es donde se buscan las fuentes item.action = "findvideos" + check_next_ep = nextep.check(item) - window_type = config.get_setting("window_type", "videolibrary") + + window_type = 1 if check_next_ep else config.get_setting("window_type", "videolibrary") # y volvemos a lanzar kodi if xbmc.getCondVisibility('Window.IsMedia') and not window_type == 1: @@ -467,66 +471,85 @@ def play_from_library(item): xbmc.executebuiltin("Container.Update(" + sys.argv[0] + "?" + item.tourl() + ")") else: + # Ventana emergente - from specials import videolibrary + item.show_server = True + + from specials import videolibrary, autoplay p_dialog = platformtools.dialog_progress_bg(config.get_localized_string(20000), config.get_localized_string(70004)) p_dialog.update(0, '') itemlist = videolibrary.findvideos(item) + if check_next_ep and autoplay.is_active(item.contentChannel): + p_dialog.update(100, '') + sleep(0.5) + p_dialog.close() + item = nextep.return_item(item) + if item.next_ep: + return play_from_library(item) - while platformtools.is_playing(): - # Ventana convencional - sleep(5) - p_dialog.update(50, '') + else: + while platformtools.is_playing(): + # Ventana convencional + sleep(5) + p_dialog.update(50, '') - '''# Se filtran los enlaces segun la lista negra - if config.get_setting('filter_servers', "servers"): - itemlist = servertools.filter_servers(itemlist)''' + it = item + if item.show_server or not check_next_ep: - # Se limita la cantidad de enlaces a mostrar - if config.get_setting("max_links", "videolibrary") != 0: - itemlist = limit_itemlist(itemlist) + '''# Se filtran los enlaces segun la lista negra + if config.get_setting('filter_servers', "servers"): + itemlist = servertools.filter_servers(itemlist)''' - # Se "limpia" ligeramente la lista de enlaces - if config.get_setting("replace_VD", "videolibrary") == 1: - itemlist = reorder_itemlist(itemlist) + # Se limita la cantidad de enlaces a mostrar + if config.get_setting("max_links", "videolibrary") != 0: + itemlist = limit_itemlist(itemlist) + + # Se "limpia" ligeramente la lista de enlaces + if config.get_setting("replace_VD", "videolibrary") == 1: + itemlist = reorder_itemlist(itemlist) - import time - p_dialog.update(100, '') - time.sleep(0.5) - p_dialog.close() + p_dialog.update(100, '') + sleep(0.5) + p_dialog.close() - if len(itemlist) > 0: - while not xbmc.Monitor().abortRequested(): - # El usuario elige el mirror - opciones = [] - for item in itemlist: - opciones.append(item.title) + if len(itemlist) > 0: + while not xbmc.Monitor().abortRequested(): + # El usuario elige el mirror + opciones = [] + for item in itemlist: + opciones.append(item.title) - # Se abre la ventana de seleccion - if (item.contentSerieName != "" and - item.contentSeason != "" and - item.contentEpisodeNumber != ""): - cabecera = ("%s - %sx%s -- %s" % - (item.contentSerieName, - item.contentSeason, - item.contentEpisodeNumber, - config.get_localized_string(30163))) - else: - cabecera = config.get_localized_string(30163) + # Se abre la ventana de seleccion + if (item.contentSerieName != "" and + item.contentSeason != "" and + item.contentEpisodeNumber != ""): + cabecera = ("%s - %sx%s -- %s" % + (item.contentSerieName, + item.contentSeason, + item.contentEpisodeNumber, + config.get_localized_string(30163))) + else: + cabecera = config.get_localized_string(30163) - seleccion = platformtools.dialog_select(cabecera, opciones) - if seleccion == -1: - return - else: - item = videolibrary.play(itemlist[seleccion])[0] - item.play_from = 'window' - platformtools.play_video(item) + seleccion = platformtools.dialog_select(cabecera, opciones) + + if seleccion == -1: + return + else: + item = videolibrary.play(itemlist[seleccion])[0] + item.play_from = 'window' + platformtools.play_video(item) + + if (platformtools.is_playing() and item.action) or item.server == 'torrent' or autoplay.is_active(item.contentChannel): + break + + if it.show_server and check_next_ep: + nextep.run(it) + sleep(0.5) + p_dialog.close() - from specials import autoplay - if (platformtools.is_playing() and item.action) or item.server == 'torrent' or autoplay.is_active(item.contentChannel): - break diff --git a/platformcode/platformtools.py b/platformcode/platformtools.py index dd81d461..937573f0 100644 --- a/platformcode/platformtools.py +++ b/platformcode/platformtools.py @@ -12,7 +12,7 @@ import os import sys import urllib -import config +# import config import xbmc import xbmcaddon import xbmcgui @@ -22,7 +22,7 @@ from channelselector import get_thumb from core import channeltools from core import trakt_tools, scrapertools from core.item import Item -from platformcode import logger, keymaptools +from platformcode import logger, keymaptools, config from platformcode import unify addon = xbmcaddon.Addon('plugin.video.kod') @@ -683,8 +683,8 @@ def is_playing(): def play_video(item, strm=False, force_direct=False, autoplay=False): logger.info() - if item.play_from == 'window': - force_direct=True + # if item.play_from == 'window': + # force_direct=True # logger.debug(item.tostring('\n')) logger.debug('item play: %s'%item) xbmc_player = XBMCPlayer() @@ -726,8 +726,8 @@ def play_video(item, strm=False, force_direct=False, autoplay=False): mediaurl, view, mpd = get_video_seleccionado(item, seleccion, video_urls) if mediaurl == "": return - # no certificate verification - mediaurl = mediaurl.replace('https://', 'http://') + # # no certificate verification + # mediaurl = mediaurl.replace('https://', 'http://') # se obtiene la información del video. if not item.contentThumbnail: @@ -1079,7 +1079,7 @@ def get_video_seleccionado(item, seleccion, video_urls): def set_player(item, xlistitem, mediaurl, view, strm): logger.info() - logger.debug("item:\n" + item.tostring('\n')) + # logger.debug("item:\n" + item.tostring('\n')) # Movido del conector "torrent" aqui if item.server == "torrent": @@ -1101,7 +1101,7 @@ def set_player(item, xlistitem, mediaurl, view, strm): download_and_play.download_and_play(mediaurl, "download_and_play.mp4", config.get_setting("downloadpath")) return - elif config.get_setting("player_mode") == 0 or \ + elif config.get_setting("player_mode") == 0 or item.play_from == 'window' or\ (config.get_setting("player_mode") == 3 and mediaurl.startswith("rtmp")): # Añadimos el listitem a una lista de reproducción (playlist) playlist = xbmc.PlayList(xbmc.PLAYLIST_VIDEO) diff --git a/platformcode/subtitletools.py b/platformcode/subtitletools.py index fa55ddb7..bd30ff93 100644 --- a/platformcode/subtitletools.py +++ b/platformcode/subtitletools.py @@ -251,7 +251,7 @@ def searchSubtitle(item): def saveSubtitleName(item): - if item.show in item.title: + if not item.show or item.show in item.title: title = item.title else: title = item.show + " - " + item.title diff --git a/platformcode/updater.py b/platformcode/updater.py index be72a0d2..26570c2e 100644 --- a/platformcode/updater.py +++ b/platformcode/updater.py @@ -132,8 +132,12 @@ def check(): urllib.urlretrieve(file['raw_url'], os.path.join(addonDir, file['filename'])) else: # è un file NON testuale, lo devo scaricare # se non è già applicato - if not (filetools.isfile(addonDir + file['filename']) and getSha(addonDir + file['filename']) == file['sha']): - urllib.urlretrieve(file['raw_url'], os.path.join(addonDir, file['filename'])) + filename = os.path.join(addonDir, file['filename']) + dirname = os.path.dirname(filename) + if not (filetools.isfile(addonDir + file['filename']) and getSha(filename) == file['sha']): + if not os.path.exists(dirname): + os.makedirs(dirname) + urllib.urlretrieve(file['raw_url'], filename) alreadyApplied = False elif file['status'] == 'removed': remove(addonDir+file["filename"]) diff --git a/resources/language/English/strings.po b/resources/language/English/strings.po index c2ccc5db..a31357a3 100644 --- a/resources/language/English/strings.po +++ b/resources/language/English/strings.po @@ -5702,7 +5702,39 @@ msgid "Enter another year..." msgstr "" msgctxt "#70746" -msgid "Hide server selection from Autoplay" +msgid "When playback ends" +msgstr "" + +msgctxt "#70747" +msgid "Hide server selection" +msgstr "" + +msgctxt "#70748" +msgid "Go to the next episode" +msgstr "" + +msgctxt "#70749" +msgid "Seconds before notification" +msgstr "" + +msgctxt "#70750" +msgid "Next Episode in" +msgstr "" + +msgctxt "#70751" +msgid "seconds" +msgstr "" + +msgctxt "#70752" +msgid "Do nothing" +msgstr "" + +msgctxt "#70753" +msgid "Playback" +msgstr "" + +msgctxt "#70754" +msgid "Compact mode" msgstr "" # DNS start [ settings and declaration ] diff --git a/resources/language/Italian/strings.po b/resources/language/Italian/strings.po index adc60e7a..7e9473f7 100644 --- a/resources/language/Italian/strings.po +++ b/resources/language/Italian/strings.po @@ -5706,8 +5706,40 @@ msgid "Enter another year..." msgstr "Inserisci un altro anno..." msgctxt "#70746" -msgid "Hide server selection from Autoplay" -msgstr "Nascondi la selezione del server da Autoplay" +msgid "When playback ends" +msgstr "Al termine della riproduzione" + +msgctxt "#70747" +msgid "Hide server selection" +msgstr "Nascondi la selezione del server" + +msgctxt "#70748" +msgid "Go to the next episode" +msgstr "Vai all'episodio successivo" + +msgctxt "#70749" +msgid "Seconds before notification" +msgstr "Secondi prima della notifica" + +msgctxt "#70750" +msgid "Next Episode in" +msgstr "Episodio Successivo fra" + +msgctxt "#70751" +msgid "seconds" +msgstr "secondi" + +msgctxt "#70752" +msgid "Do nothing" +msgstr "Non fare nulla" + +msgctxt "#70753" +msgid "Playback" +msgstr "Riproduzione" + +msgctxt "#70754" +msgid "Compact mode" +msgstr "Modalità compatta" # DNS start [ settings and declaration ] msgctxt "#707401" diff --git a/resources/settings.xml b/resources/settings.xml index 8bca2334..b40e95e4 100644 --- a/resources/settings.xml +++ b/resources/settings.xml @@ -2,17 +2,12 @@ <settings> <!-- General --> <category label="70168"> - <setting id="player_mode" type="enum" values="Direct|SetResolvedUrl|Built-In|Download and Play" label="30044" default="1"/> - <setting id="default_action" type="enum" lvalues="30006|30007|30008" label="30005" default="0"/> - <setting id="autoplay" type="bool" label="70562" default="false" visible="true"/> -<!-- <setting id="autoplay_next" type="bool" label="Riproduci episodio successivo" default="false" visible="true"/>--> - <setting id="autoplay_server_list" type="bool" label="70746" default="false" visible="true"/> - <setting id="checklinks" type="bool" label="30020" default="false"/> - <setting id="checklinks_number" type="enum" values="5|10|15|20" label="30021" default="0" visible="eq(-1,true)"/> + <setting id="thumbnail_type" type="enum" lvalues="30011|30012|30200" label="30010" default="2"/> <setting id="channel_language" type="labelenum" values="auto|all|ita" label="30019" default="all"/> <setting id="trakt_sync" type="bool" label="70109" default="false"/> <setting id="forceview" type="bool" label="30043" default="false"/> + <setting id="faster_item_serialization" type="bool" label="30300" default="false"/> <setting id="resolver_dns" type="bool" label="707408" default="true" enable="true" visible="true"/> <setting id="debug" type="bool" label="30003" default="false"/> <setting label="70169" type="lsep"/> @@ -40,6 +35,16 @@ <setting id="enable_library_menu" label="30131" type="bool" default="true"/> </category> + <!-- Playback --> + <category label="70753"> + <setting id="player_mode" type="enum" values="Direct|SetResolvedUrl|Built-In|Download and Play" label="30044" default="1"/> + <setting id="default_action" type="enum" lvalues="30006|30007|30008" label="30005" default="0"/> + <setting id="autoplay" type="bool" label="70562" default="false" visible="true"/> + <setting id="hide_servers" type="bool" label="70747" default="false" visible="eq(-1,true)"/> + <setting id="checklinks" type="bool" label="30020" default="false"/> + <setting id="checklinks_number" type="enum" values="5|10|15|20" label="30021" default="0" visible="eq(-1,true)"/> + </category> + <!-- Videolibrary --> <category label="30131"> <!-- <setting id="downloadpath" type="folder" label="30017" default=""/> @@ -53,6 +58,9 @@ <setting id="videolibrary_kodi_force" type="bool" label="" default="false" visible="false"/> <setting id="videolibrary_kodi" type="bool" label="70120" enable="lt(-1,2)+eq(0,false)" default="false"/> <setting id="videolibrary_max_quality" type="bool" label="70729" default="false" visible="true"/> + <setting id="next_ep" type="enum" label="70746" lvalues="70752|70747|70748" default="0"/> + <setting id="next_ep_type" type="bool" label="70754" default="false" visible="eq(-1,2)"/> + <setting id="next_ep_seconds" type="enum" values="20|30|40|50|60" label="70749" default="2" visible="!eq(-2,0)"/> </category> @@ -70,61 +78,8 @@ <setting id="custom_theme" type="folder" label="70565" default="" visible="eq(-1,true)"/> <setting id="infoplus_set" type="labelenum" label="70128" lvalues="70129|70130" default="70129"/> <setting id="video_thumbnail_type" type="enum" label="70131" lvalues="70132|70133" default="0"/> - <!-- <setting label="70167" type="lsep"/> - <setting id="unify" type="bool" label="70134" default="false"/> - <setting id="title_color" type="bool" label="70135" default="false" visible="eq(-1,true)"/> - <setting id="movie_color" type="labelenum" label="70137" - values="[COLOR white]white[/COLOR]|[COLOR cyan]cyan[/COLOR]|[COLOR deepskyblue]deepskyblue[/COLOR]|[COLOR firebrick]firebrick[/COLOR]|[COLOR gold]gold[/COLOR]|[COLOR goldenrod]goldenrod[/COLOR]|[COLOR hotpink]hotpink[/COLOR]|[COLOR limegreen]limegreen[/COLOR]|[COLOR orange]orange[/COLOR]|[COLOR orchid]orchid[/COLOR]|[COLOR red]red[/COLOR]|[COLOR salmon]salmon[/COLOR]|[COLOR yellow]yellow[/COLOR]" - default="white" visible="eq(-1,true)+eq(-2,true)"/> - <setting id="tvshow_color" type="labelenum" label="30123" - values="[COLOR white]white[/COLOR]|[COLOR cyan]cyan[/COLOR]|[COLOR deepskyblue]deepskyblue[/COLOR]|[COLOR firebrick]firebrick[/COLOR]|[COLOR gold]gold[/COLOR]|[COLOR goldenrod]goldenrod[/COLOR]|[COLOR hotpink]hotpink[/COLOR]|[COLOR limegreen]limegreen[/COLOR]|[COLOR orange]orange[/COLOR]|[COLOR orchid]orchid[/COLOR]|[COLOR red]red[/COLOR]|[COLOR salmon]salmon[/COLOR]|[COLOR yellow]yellow[/COLOR]" - default="white" visible="eq(-2,true)+eq(-3,true)"/> - <setting id="year_color" type="labelenum" label="60232" - values="[COLOR white]white[/COLOR]|[COLOR cyan]cyan[/COLOR]|[COLOR deepskyblue]deepskyblue[/COLOR]|[COLOR firebrick]firebrick[/COLOR]|[COLOR gold]gold[/COLOR]|[COLOR goldenrod]goldenrod[/COLOR]|[COLOR hotpink]hotpink[/COLOR]|[COLOR limegreen]limegreen[/COLOR]|[COLOR orange]orange[/COLOR]|[COLOR orchid]orchid[/COLOR]|[COLOR red]red[/COLOR]|[COLOR salmon]salmon[/COLOR]|[COLOR yellow]yellow[/COLOR]" - default="white" visible="eq(-3,true)+eq(-4,true)"/> - <setting id="rating_1_color" type="labelenum" label="70138" - values="[COLOR white]white[/COLOR]|[COLOR cyan]cyan[/COLOR]|[COLOR deepskyblue]deepskyblue[/COLOR]|[COLOR firebrick]firebrick[/COLOR]|[COLOR gold]gold[/COLOR]|[COLOR goldenrod]goldenrod[/COLOR]|[COLOR hotpink]hotpink[/COLOR]|[COLOR limegreen]limegreen[/COLOR]|[COLOR orange]orange[/COLOR]|[COLOR orchid]orchid[/COLOR]|[COLOR red]red[/COLOR]|[COLOR salmon]salmon[/COLOR]|[COLOR yellow]yellow[/COLOR]" - default="white" visible="eq(-4,true)+eq(-5,true)"/> - <setting id="rating_2_color" type="labelenum" label="70139" - values="[COLOR white]white[/COLOR]|[COLOR cyan]cyan[/COLOR]|[COLOR deepskyblue]deepskyblue[/COLOR]|[COLOR firebrick]firebrick[/COLOR]|[COLOR gold]gold[/COLOR]|[COLOR goldenrod]goldenrod[/COLOR]|[COLOR hotpink]hotpink[/COLOR]|[COLOR limegreen]limegreen[/COLOR]|[COLOR orange]orange[/COLOR]|[COLOR orchid]orchid[/COLOR]|[COLOR red]red[/COLOR]|[COLOR salmon]salmon[/COLOR]|[COLOR yellow]yellow[/COLOR]" - default="white" visible="eq(-5,true)+eq(-6,true)"/> - <setting id="rating_3_color" type="labelenum" label="70140" - values="[COLOR white]white[/COLOR]|[COLOR cyan]cyan[/COLOR]|[COLOR deepskyblue]deepskyblue[/COLOR]|[COLOR firebrick]firebrick[/COLOR]|[COLOR gold]gold[/COLOR]|[COLOR goldenrod]goldenrod[/COLOR]|[COLOR hotpink]hotpink[/COLOR]|[COLOR limegreen]limegreen[/COLOR]|[COLOR orange]orange[/COLOR]|[COLOR orchid]orchid[/COLOR]|[COLOR red]red[/COLOR]|[COLOR salmon]salmon[/COLOR]|[COLOR yellow]yellow[/COLOR]" - default="white" visible="eq(-6,true)+eq(-7,true)"/> - <setting id="quality_color" type="labelenum" label="70141" - values="[COLOR white]white[/COLOR]|[COLOR cyan]cyan[/COLOR]|[COLOR deepskyblue]deepskyblue[/COLOR]|[COLOR firebrick]firebrick[/COLOR]|[COLOR gold]gold[/COLOR]|[COLOR goldenrod]goldenrod[/COLOR]|[COLOR hotpink]hotpink[/COLOR]|[COLOR limegreen]limegreen[/COLOR]|[COLOR orange]orange[/COLOR]|[COLOR orchid]orchid[/COLOR]|[COLOR red]red[/COLOR]|[COLOR salmon]salmon[/COLOR]|[COLOR yellow]yellow[/COLOR]" - default="white" visible="eq(-7,true)+eq(-8,true)"/> - <setting id="cast_color" type="labelenum" label="59980" - values="[COLOR white]white[/COLOR]|[COLOR cyan]cyan[/COLOR]|[COLOR deepskyblue]deepskyblue[/COLOR]|[COLOR firebrick]firebrick[/COLOR]|[COLOR gold]gold[/COLOR]|[COLOR goldenrod]goldenrod[/COLOR]|[COLOR hotpink]hotpink[/COLOR]|[COLOR limegreen]limegreen[/COLOR]|[COLOR orange]orange[/COLOR]|[COLOR orchid]orchid[/COLOR]|[COLOR red]red[/COLOR]|[COLOR salmon]salmon[/COLOR]|[COLOR yellow]yellow[/COLOR]" - default="white" visible="eq(-8,true)+eq(-9,true)"/> - <setting id="lat_color" type="labelenum" label="59981" - values="[COLOR white]white[/COLOR]|[COLOR cyan]cyan[/COLOR]|[COLOR deepskyblue]deepskyblue[/COLOR]|[COLOR firebrick]firebrick[/COLOR]|[COLOR gold]gold[/COLOR]|[COLOR goldenrod]goldenrod[/COLOR]|[COLOR hotpink]hotpink[/COLOR]|[COLOR limegreen]limegreen[/COLOR]|[COLOR orange]orange[/COLOR]|[COLOR orchid]orchid[/COLOR]|[COLOR red]red[/COLOR]|[COLOR salmon]salmon[/COLOR]|[COLOR yellow]yellow[/COLOR]" - default="white" visible="eq(-9,true)+eq(-10,true)"/> - <setting id="vose_color" type="labelenum" label="70142" - values="[COLOR white]white[/COLOR]|[COLOR cyan]cyan[/COLOR]|[COLOR deepskyblue]deepskyblue[/COLOR]|[COLOR firebrick]firebrick[/COLOR]|[COLOR gold]gold[/COLOR]|[COLOR goldenrod]goldenrod[/COLOR]|[COLOR hotpink]hotpink[/COLOR]|[COLOR limegreen]limegreen[/COLOR]|[COLOR orange]orange[/COLOR]|[COLOR orchid]orchid[/COLOR]|[COLOR red]red[/COLOR]|[COLOR salmon]salmon[/COLOR]|[COLOR yellow]yellow[/COLOR]" - default="white" visible="eq(-10,true)+eq(-11,true)"/> - <setting id="sub-ita_color" type="labelenum" label="70566" - values="[COLOR white]white[/COLOR]|[COLOR cyan]cyan[/COLOR]|[COLOR deepskyblue]deepskyblue[/COLOR]|[COLOR firebrick]firebrick[/COLOR]|[COLOR gold]gold[/COLOR]|[COLOR goldenrod]goldenrod[/COLOR]|[COLOR hotpink]hotpink[/COLOR]|[COLOR limegreen]limegreen[/COLOR]|[COLOR orange]orange[/COLOR]|[COLOR orchid]orchid[/COLOR]|[COLOR red]red[/COLOR]|[COLOR salmon]salmon[/COLOR]|[COLOR yellow]yellow[/COLOR]" - default="white" visible="eq(-11,true)+eq(-12,true)"/> - <setting id="vos_color" type="labelenum" label="70143" - values="[COLOR white]white[/COLOR]|[COLOR cyan]cyan[/COLOR]|[COLOR deepskyblue]deepskyblue[/COLOR]|[COLOR firebrick]firebrick[/COLOR]|[COLOR gold]gold[/COLOR]|[COLOR goldenrod]goldenrod[/COLOR]|[COLOR hotpink]hotpink[/COLOR]|[COLOR limegreen]limegreen[/COLOR]|[COLOR orange]orange[/COLOR]|[COLOR orchid]orchid[/COLOR]|[COLOR red]red[/COLOR]|[COLOR salmon]salmon[/COLOR]|[COLOR yellow]yellow[/COLOR]" - default="white" visible="eq(-12,true)+eq(-13,true)"/> - <setting id="vo_color" type="labelenum" label="70144" - values="[COLOR white]white[/COLOR]|[COLOR cyan]cyan[/COLOR]|[COLOR deepskyblue]deepskyblue[/COLOR]|[COLOR firebrick]firebrick[/COLOR]|[COLOR gold]gold[/COLOR]|[COLOR goldenrod]goldenrod[/COLOR]|[COLOR hotpink]hotpink[/COLOR]|[COLOR limegreen]limegreen[/COLOR]|[COLOR orange]orange[/COLOR]|[COLOR orchid]orchid[/COLOR]|[COLOR red]red[/COLOR]|[COLOR salmon]salmon[/COLOR]|[COLOR yellow]yellow[/COLOR]" - default="white" visible="eq(-13,true)+eq(-14,true)"/> - <setting id="server_color" type="labelenum" label="70145" - values="[COLOR white]white[/COLOR]|[COLOR cyan]cyan[/COLOR]|[COLOR deepskyblue]deepskyblue[/COLOR]|[COLOR firebrick]firebrick[/COLOR]|[COLOR gold]gold[/COLOR]|[COLOR goldenrod]goldenrod[/COLOR]|[COLOR hotpink]hotpink[/COLOR]|[COLOR limegreen]limegreen[/COLOR]|[COLOR orange]orange[/COLOR]|[COLOR orchid]orchid[/COLOR]|[COLOR red]red[/COLOR]|[COLOR salmon]salmon[/COLOR]|[COLOR yellow]yellow[/COLOR]" - default="white" visible="eq(-14,true)+eq(-15,true)"/> - <setting id="library_color" type="labelenum" label="70146" - values="[COLOR white]white[/COLOR]|[COLOR cyan]cyan[/COLOR]|[COLOR deepskyblue]deepskyblue[/COLOR]|[COLOR firebrick]firebrick[/COLOR]|[COLOR gold]gold[/COLOR]|[COLOR goldenrod]goldenrod[/COLOR]|[COLOR hotpink]hotpink[/COLOR]|[COLOR limegreen]limegreen[/COLOR]|[COLOR orange]orange[/COLOR]|[COLOR orchid]orchid[/COLOR]|[COLOR red]red[/COLOR]|[COLOR salmon]salmon[/COLOR]|[COLOR yellow]yellow[/COLOR]" - default="white" visible="eq(-15,true)+eq(-16,true)"/> - <setting id="update_color" type="labelenum" label="70147" - values="[COLOR white]white[/COLOR]|[COLOR cyan]cyan[/COLOR]|[COLOR deepskyblue]deepskyblue[/COLOR]|[COLOR firebrick]firebrick[/COLOR]|[COLOR gold]gold[/COLOR]|[COLOR goldenrod]goldenrod[/COLOR]|[COLOR hotpink]hotpink[/COLOR]|[COLOR limegreen]limegreen[/COLOR]|[COLOR orange]orange[/COLOR]|[COLOR orchid]orchid[/COLOR]|[COLOR red]red[/COLOR]|[COLOR salmon]salmon[/COLOR]|[COLOR yellow]yellow[/COLOR]" - default="white" visible="eq(-16,true)+eq(-17,true)"/> - <setting id="no_update_color" type="labelenum" label="70148" - values="[COLOR white]white[/COLOR]|[COLOR cyan]cyan[/COLOR]|[COLOR deepskyblue]deepskyblue[/COLOR]|[COLOR firebrick]firebrick[/COLOR]|[COLOR gold]gold[/COLOR]|[COLOR goldenrod]goldenrod[/COLOR]|[COLOR hotpink]hotpink[/COLOR]|[COLOR limegreen]limegreen[/COLOR]|[COLOR orange]orange[/COLOR]|[COLOR orchid]orchid[/COLOR]|[COLOR red]red[/COLOR]|[COLOR salmon]salmon[/COLOR]|[COLOR yellow]yellow[/COLOR]" - default="white" visible="eq(-17,true)+eq(-18,true)"/> --> </category> + <!-- Other --> <category label="70149"> <setting label="70150" type="lsep"/> @@ -137,6 +92,7 @@ <setting type="sep"/> <setting label="70154" type="lsep"/> + <setting id="tmdb_active" default="true" visible="false"/> <setting id="tmdb_threads" type="labelenum" values="5|10|15|20|25|30" label="70155" default="20"/> <setting id="tmdb_plus_info" type="bool" label="70156" default="false"/> <setting id="tmdb_cache" type="bool" label="70157" default="true"/> @@ -155,9 +111,6 @@ <setting label="Lista activa" type="text" id="lista_activa" default="kodfavorites-default.json" visible="false"/> - <!-- <setting type="sep"/> - <setting label="70583" type="lsep"/> - <setting id="addon_quasar_update" type="bool" label="70584" default="false"/> --> </category> <!-- Custom Start --> <category label="70121"> @@ -172,5 +125,4 @@ </category> - </settings> diff --git a/resources/skins/Default/720p/NextDialog.xml b/resources/skins/Default/720p/NextDialog.xml new file mode 100644 index 00000000..2455d71d --- /dev/null +++ b/resources/skins/Default/720p/NextDialog.xml @@ -0,0 +1,88 @@ +<?xml version="1.0" encoding="UTF-8"?> +<window> + <defaultcontrol always="true">20</defaultcontrol> + <onload>Dialog.Close(fullscreeninfo,true)</onload> + <onload>Dialog.Close(videoosd,true)</onload> + <controls> + <control type="group"> + <animation type="WindowOpen" reversible="false"> + <effect type="fade" start="0" end="100" time="600" /> + <effect type="slide" start="115,0" end="0,0" time="600" /> + </animation> + <animation type="WindowClose" reversible="false"> + <effect type="fade" start="100" end="0" time="400" /> + <effect type="slide" start="0,0" end="115,0" time="400" /> + </animation> + <control type="group"> + <right>0</right> + <top>15</top> + <height>40</height> + <width>100%</width> + <!-- Background --> + <control type="image"> + <top>0</top> + <width>100%</width> + <height>40</height> + <texture colordiffuse="00111111">NextDialog/background-diffuse.png</texture> + </control> + <control type="group"> + <top>0</top> + <right>0</right> + <width>100%</width> + <!-- buttons --> + <control type="button" id="3012"> + <left>-1000</left> + <top>-1000</top> + <height>1</height> + <width>1</width> + </control> + <control type="grouplist" id="20"> + <orientation>horizontal</orientation> + <height>40</height> + <itemgap>0</itemgap> + <align>right</align> + <control type="button" id="11"> + <label>$ADDON[plugin.video.kod 70750] $INFO[Player.TimeRemaining(ss),,] $ADDON[plugin.video.kod 70751]</label> + <onclick>SendClick(3012)</onclick> + <height>40</height> + <width min="50">auto</width> + <font>font30_title</font> + <textoffsetx>20</textoffsetx> + <textcolor>80FFFFFF</textcolor> + <focusedcolor>FFFFFFFF</focusedcolor> + <selectedcolor>80FFFFFF</selectedcolor> + <shadowcolor>22000000</shadowcolor> + <aligny>center</aligny> + <align>center</align> + <texturefocus border="10" colordiffuse="88232323">NextDialog/background-diffuse.png</texturefocus> + <texturenofocus border="10" colordiffuse="88232323">NextDialog/background-diffuse.png</texturenofocus> + <pulseonselect>no</pulseonselect> + </control> + <control type="button" id="3013"> + <label>$ADDON[plugin.video.kod 60396]</label> + <height>40</height> + <width min="50">auto</width> + <font>font30_title</font> + <textoffsetx>20</textoffsetx> + <textcolor>80FFFFFF</textcolor> + <focusedcolor>FFFFFFFF</focusedcolor> + <selectedcolor>80FFFFFF</selectedcolor> + <shadowcolor>22000000</shadowcolor> + <aligny>center</aligny> + <align>center</align> + <texturefocus border="10" colordiffuse="88232323">NextDialog/background-diffuse.png</texturefocus> + <texturenofocus border="10" colordiffuse="88232323">NextDialog/background-diffuse.png</texturenofocus> + <pulseonselect>no</pulseonselect> + </control> + <control type="image"> + <top>0</top> + <width>30</width> + <height>40</height> + <texture colordiffuse="88232323">NextDialog/background-diffuse.png</texture> + </control> + </control> + </control> + </control> + </control> + </controls> +</window> \ No newline at end of file diff --git a/resources/skins/Default/720p/NextDialogCompact.xml b/resources/skins/Default/720p/NextDialogCompact.xml new file mode 100644 index 00000000..2164ace3 --- /dev/null +++ b/resources/skins/Default/720p/NextDialogCompact.xml @@ -0,0 +1,89 @@ +<?xml version="1.0" encoding="UTF-8"?> +<window> + <defaultcontrol always="true">20</defaultcontrol> + <onload>Dialog.Close(fullscreeninfo,true)</onload> + <onload>Dialog.Close(videoosd,true)</onload> + <controls> + <control type="group"> + <animation type="WindowOpen" reversible="false"> + <effect type="fade" start="0" end="100" time="600" /> + <effect type="slide" start="115,0" end="0,0" time="600" /> + </animation> + <animation type="WindowClose" reversible="false"> + <effect type="fade" start="100" end="0" time="400" /> + <effect type="slide" start="0,0" end="115,0" time="400" /> + </animation> + <control type="group"> + <right>0</right> + <top>15</top> + <height>50</height> + <width>100%</width> + <!-- Background --> + <control type="image"> + <top>0</top> + <width>100%</width> + <height>40</height> + <!-- <texture colordiffuse="00111111">NextDialog/button-bg.png</texture> --> + </control> + <control type="group"> + <top>0</top> + <right>0</right> + <width>100%</width> + <!-- buttons --> + <control type="button" id="3012"> + <left>-1000</left> + <top>-1000</top> + <height>1</height> + <width>1</width> + </control> + <control type="grouplist" id="20"> + <orientation>horizontal</orientation> + <height>40</height> + <itemgap>0</itemgap> + <align>right</align> + <control type="button" id="11"> + <label>[B]$INFO[Player.TimeRemaining(ss),,][/B]</label> + <onclick>SendClick(3012)</onclick> + <!-- <visible>!Integer.IsGreater(Player.TimeRemaining,59)</visible> --> + <height>40</height> + <width>65</width> + <font>font30_title</font> + <textoffsetx>12</textoffsetx> + <textcolor>80FFFFFF</textcolor> + <focusedcolor>FFFFFFFF</focusedcolor> + <selectedcolor>80FFFFFF</selectedcolor> + <shadowcolor>22000000</shadowcolor> + <aligny>center</aligny> + <align>left</align> + <texturefocus border="10">NextDialog/play-fo.png</texturefocus> + <texturenofocus border="10">NextDialog/play-nf.png</texturenofocus> + <pulseonselect>no</pulseonselect> + </control> + <control type="button" id="3013"> + <label></label> + <height>40</height> + <width>40</width> + <font>font30_title</font> + <textoffsetx>30</textoffsetx> + <textcolor>80FFFFFF</textcolor> + <focusedcolor>FFFFFFFF</focusedcolor> + <selectedcolor>80FFFFFF</selectedcolor> + <shadowcolor>22000000</shadowcolor> + <aligny>center</aligny> + <align>center</align> + <texturefocus border="10">NextDialog/close-fo.png</texturefocus> + <texturenofocus border="10">NextDialog/close-nf.png</texturenofocus> + <pulseonselect>no</pulseonselect> + </control> + <control type="image"> + <top>0</top> + <width>20</width> + <height>40</height> + <texture>NextDialog/background.png</texture> + </control> + </control> + </control> + </control> + </control> + </controls> +</window> \ No newline at end of file diff --git a/resources/skins/Default/media/NextDialog/background-diffuse.png b/resources/skins/Default/media/NextDialog/background-diffuse.png new file mode 100644 index 00000000..f6368603 Binary files /dev/null and b/resources/skins/Default/media/NextDialog/background-diffuse.png differ diff --git a/resources/skins/Default/media/NextDialog/background.png b/resources/skins/Default/media/NextDialog/background.png new file mode 100644 index 00000000..bdd2689e Binary files /dev/null and b/resources/skins/Default/media/NextDialog/background.png differ diff --git a/resources/skins/Default/media/NextDialog/close-fo.png b/resources/skins/Default/media/NextDialog/close-fo.png new file mode 100644 index 00000000..b6e4ece7 Binary files /dev/null and b/resources/skins/Default/media/NextDialog/close-fo.png differ diff --git a/resources/skins/Default/media/NextDialog/close-nf.png b/resources/skins/Default/media/NextDialog/close-nf.png new file mode 100644 index 00000000..aa61c1eb Binary files /dev/null and b/resources/skins/Default/media/NextDialog/close-nf.png differ diff --git a/resources/skins/Default/media/NextDialog/play-fo.png b/resources/skins/Default/media/NextDialog/play-fo.png new file mode 100644 index 00000000..969dfd90 Binary files /dev/null and b/resources/skins/Default/media/NextDialog/play-fo.png differ diff --git a/resources/skins/Default/media/NextDialog/play-nf.png b/resources/skins/Default/media/NextDialog/play-nf.png new file mode 100644 index 00000000..1c12b92e Binary files /dev/null and b/resources/skins/Default/media/NextDialog/play-nf.png differ diff --git a/resources/skins/Default/media/Shortcut - Copia/close.png b/resources/skins/Default/media/Shortcut - Copia/close.png new file mode 100644 index 00000000..0a144666 Binary files /dev/null and b/resources/skins/Default/media/Shortcut - Copia/close.png differ diff --git a/resources/skins/Default/media/Shortcut - Copia/dialog-bg-solid-white.png b/resources/skins/Default/media/Shortcut - Copia/dialog-bg-solid-white.png new file mode 100644 index 00000000..225aae63 Binary files /dev/null and b/resources/skins/Default/media/Shortcut - Copia/dialog-bg-solid-white.png differ diff --git a/resources/skins/Default/media/Shortcut - Copia/dialog-bg-solid.png b/resources/skins/Default/media/Shortcut - Copia/dialog-bg-solid.png new file mode 100644 index 00000000..e8c13ebd Binary files /dev/null and b/resources/skins/Default/media/Shortcut - Copia/dialog-bg-solid.png differ diff --git a/resources/skins/Default/media/Shortcut - Copia/logo.png b/resources/skins/Default/media/Shortcut - Copia/logo.png new file mode 100644 index 00000000..d8a680fe Binary files /dev/null and b/resources/skins/Default/media/Shortcut - Copia/logo.png differ diff --git a/resources/skins/Default/media/Shortcut - Copia/white.png b/resources/skins/Default/media/Shortcut - Copia/white.png new file mode 100644 index 00000000..528c66f6 Binary files /dev/null and b/resources/skins/Default/media/Shortcut - Copia/white.png differ diff --git a/resources/skins/Default/media/Shortcut - Copia/white70.png b/resources/skins/Default/media/Shortcut - Copia/white70.png new file mode 100644 index 00000000..d428a73a Binary files /dev/null and b/resources/skins/Default/media/Shortcut - Copia/white70.png differ diff --git a/servers/akstream.py b/servers/akstream.py index 72fb5ddb..cb0dfd7a 100644 --- a/servers/akstream.py +++ b/servers/akstream.py @@ -37,7 +37,7 @@ def get_video_url(page_url, premium=False, user="", password="", video_password= i = 0 for media_url in matches: # URL del vídeo - video_urls.append([vres[i] + " mp4 [Akvideo] ", media_url + '|' + _headers]) + video_urls.append([vres[i] + " mp4 [Akvideo] ", media_url.replace('https://', 'http://') + '|' + _headers]) i = i + 1 for video_url in video_urls: diff --git a/servers/cloudvideo.py b/servers/cloudvideo.py index ef66b57f..d664b88b 100644 --- a/servers/cloudvideo.py +++ b/servers/cloudvideo.py @@ -9,8 +9,10 @@ from platformcode import logger def test_video_exists(page_url): logger.info("(page_url='%s')" % page_url) - data = httptools.downloadpage(page_url) - if data.code == 404: + html = httptools.downloadpage(page_url) + global data + data = html.data + if html.code == 404: return False, config.get_localized_string(70292) % "CloudVideo" return True, "" @@ -18,7 +20,8 @@ def test_video_exists(page_url): def get_video_url(page_url, premium=False, user="", password="", video_password=""): logger.info("url=" + page_url) video_urls = [] - data = httptools.downloadpage(page_url).data + global data + # data = httptools.downloadpage(page_url).data # enc_data = scrapertools.find_single_match(data, "text/javascript">(.+?)</script>") # dec_data = jsunpack.unpack(enc_data) sources = scrapertools.find_single_match(data, "<source(.*?)</source") diff --git a/servers/decrypters/zcrypt.py b/servers/decrypters/zcrypt.py index c0e944fc..d5181352 100644 --- a/servers/decrypters/zcrypt.py +++ b/servers/decrypters/zcrypt.py @@ -20,11 +20,12 @@ def get_video_url(page_url, premium=False, user="", password="", video_password= patronvideos = [ r'(https?://(gestyy|rapidteria|sprysphere)\.com/[a-zA-Z0-9]+)', r'(https?://(?:www\.)?(vcrypt|linkup)\.[^/]+/[^/]+/[a-zA-Z0-9_]+)', - r'(https?://(?:www\.)?(bit)\.ly/[a-zA-Z0-9]+)', + r'(https?://(?:www\.)?(bit|buckler)\.[^/]+/[a-zA-Z0-9]+)', r'(https?://(?:www\.)?(xshield)\.[^/]+/[^/]+/[^/]+/[a-zA-Z0-9_\.]+)' ] for patron in patronvideos: + # from core.support import dbg; dbg() logger.info(" find_videos #" + patron + "#") matches = re.compile(patron).findall(page_url) @@ -51,9 +52,10 @@ def get_video_url(page_url, premium=False, user="", password="", video_password= continue else: from lib import unshortenit - data, status = unshortenit.unshorten(url) + sh = unshortenit.UnshortenIt() + data, status = sh.unshorten(url) logger.info("Data - Status zcrypt vcrypt.net: [%s] [%s] " %(data, status)) - elif 'linkup' in url or 'bit.ly' in url: + elif 'linkup' in url or 'bit.ly' in url or 'buckler' in url: logger.info("DATA LINK {}".format(url)) if '/tv/' in url: url = url.replace('/tv/','/tva/') diff --git a/servers/mixdrop.json b/servers/mixdrop.json index 6d39077a..6977131e 100644 --- a/servers/mixdrop.json +++ b/servers/mixdrop.json @@ -4,7 +4,7 @@ "ignore_urls": [], "patterns": [ { - "pattern": "mixdrop.co/(?:f|e)/([a-z0-9]+)", + "pattern": "mixdrop.[^/]+/(?:f|e)/([a-z0-9]+)", "url": "https://mixdrop.co/e/\\1" } ] diff --git a/servers/supervideo.py b/servers/supervideo.py index 4ef07daa..20410941 100644 --- a/servers/supervideo.py +++ b/servers/supervideo.py @@ -9,7 +9,7 @@ import ast def test_video_exists(page_url): logger.info("(page_url='%s')" % page_url) - + global data data = httptools.downloadpage(page_url, cookies=False).data if 'File Not Found' in data: return False, config.get_localized_string(70449) % "SuperVideo" @@ -20,27 +20,35 @@ def test_video_exists(page_url): def get_video_url(page_url, premium=False, user="", password="", video_password=""): logger.info("url=" + page_url) video_urls = [] - data = httptools.downloadpage(page_url).data - logger.info('SUPER DATA= '+data) + # data = httptools.downloadpage(page_url).data + global data + code_data = scrapertools.find_single_match(data, "<script type='text/javascript'>(eval.*)") if code_data: code = jsunpack.unpack(code_data) + + # corrections + if 'file' in code and not '"file"'in code: code = code.replace('file','"file"') + if 'label' in code and not '"label"'in code: code = code.replace('label','"label"') + match = scrapertools.find_single_match(code, r'sources:(\[[^]]+\])') lSrc = ast.literal_eval(match) - lQuality = ['360p', '720p', '1080p', '4k'][:len(lSrc)-1] - lQuality.reverse() + # lQuality = ['360p', '720p', '1080p', '4k'][:len(lSrc)-1] + # lQuality.reverse() + + for source in lSrc: + quality = source['label'] if source.has_key('label') else 'auto' + video_urls.append(['.' + source['file'].split('.')[-1] + ' [' + quality + '] [SuperVideo]', source['file']]) - for n, source in enumerate(lSrc): - quality = 'auto' if n==0 else lQuality[n-1] - video_urls.append(['.' + source.split('.')[-1] + '(' + quality + ') [SuperVideo]', source]) else: logger.info('ELSE!') matches = scrapertools.find_multiple_matches(data, r'src:\s*"([^"]+)",\s*type:\s*"[^"]+"(?:\s*, res:\s(\d+))?') for url, quality in matches: if url.split('.')[-1] != 'm3u8': - video_urls.append([url.split('.')[-1] + ' [' + quality + ']', url]) + video_urls.append([url.split('.')[-1] + ' [' + quality + '] [SuperVideo]', url]) else: video_urls.append([url.split('.')[-1], url]) - video_urls.sort(key=lambda x: x[0].split()[-1]) + + video_urls.sort(key=lambda x: x[0].split()[-2]) return video_urls diff --git a/servers/vidoza.py b/servers/vidoza.py index 9ec0ccad..f9806ec5 100644 --- a/servers/vidoza.py +++ b/servers/vidoza.py @@ -8,6 +8,7 @@ from platformcode import logger def test_video_exists(page_url): logger.info("(page_url='%s')" % page_url) + global data data = httptools.downloadpage(page_url).data if "Page not found" in data or "File was deleted" in data: return False, "[vidoza] El archivo no existe o ha sido borrado" @@ -19,7 +20,7 @@ def test_video_exists(page_url): def get_video_url(page_url, premium=False, user="", password="", video_password=""): logger.info("(page_url='%s')" % page_url) - data = httptools.downloadpage(page_url).data + global data video_urls = [] s = scrapertools.find_single_match(data, r'sourcesCode\s*:\s*(\[\{.*?\}\])') @@ -30,8 +31,8 @@ def get_video_url(page_url, premium=False, user="", password="", video_password= if 'src' in enlace or 'file' in enlace: url = enlace['src'] if 'src' in enlace else enlace['file'] tit = '' - if 'label' in enlace: tit += '[%s]' % enlace['label'] - if 'res' in enlace: tit += '[%s]' % enlace['res'] + if 'label' in enlace: tit += ' [%s]' % enlace['label'] + if 'res' in enlace: tit += ' [%s]' % enlace['res'] if tit == '' and 'type' in enlace: tit = enlace['type'] if tit == '': tit = '.mp4' diff --git a/servers/vup.json b/servers/vup.json deleted file mode 100644 index 4c468694..00000000 --- a/servers/vup.json +++ /dev/null @@ -1,42 +0,0 @@ -{ - "active": true, - "find_videos": { - "ignore_urls": [], - "patterns": [ - { - "pattern": "(https://vup.to/embed-[A-z0-9]+.html)", - "url": "\\1" - } - ] - }, - "free": true, - "id": "vup", - "name": "VUP", - "settings": [ - { - "default": false, - "enabled": true, - "id": "black_list", - "label": "@60654", - "type": "bool", - "visible": true - }, - { - "default": 0, - "enabled": true, - "id": "favorites_servers_list", - "label": "@60655", - "lvalues": [ - "No", - "1", - "2", - "3", - "4", - "5" - ], - "type": "list", - "visible": false - } - ], - "thumbnail": "server_vupplayer.png" -} diff --git a/servers/vup.py b/servers/vup.py deleted file mode 100644 index 9eba027d..00000000 --- a/servers/vup.py +++ /dev/null @@ -1,28 +0,0 @@ -# -*- coding: utf-8 -*- -# -------------------------------------------------------- -# Conector vup By Alfa development Group -# -------------------------------------------------------- - -from core import httptools -from core import scrapertools -from platformcode import logger - - -def test_video_exists(page_url): - logger.info("(page_url='%s')" % page_url) - data = httptools.downloadpage(page_url).data - if "no longer exists" in data or "to copyright issues" in data: - return False, "[vup] El video ha sido borrado" - return True, "" - - -def get_video_url(page_url, user="", password="", video_password=""): - logger.info("(page_url='%s')" % page_url) - data = httptools.downloadpage(page_url).data - bloque = scrapertools.find_single_match(data, 'sources:.*?\]') - video_urls = [] - videourl = scrapertools.find_multiple_matches(bloque, '"(http[^"]+)') - for video in videourl: - video_urls.append([".MP4 [vup]", video]) - video_urls = video_urls[::-1] - return video_urls diff --git a/servers/vupplayer.py b/servers/vupplayer.py index 113a30e9..e348a184 100644 --- a/servers/vupplayer.py +++ b/servers/vupplayer.py @@ -7,6 +7,8 @@ from platformcode import logger, config def test_video_exists(page_url): logger.info("(page_url='%s')" % page_url) data = httptools.downloadpage(page_url) + global data + data = data.data if data.code == 404: return False, config.get_localized_string(70449) return True, "" @@ -15,8 +17,7 @@ def test_video_exists(page_url): def get_video_url(page_url, premium=False, user="", password="", video_password=""): logger.info("url=" + page_url) video_urls = [] - data = httptools.downloadpage(page_url).data - logger.info('VUP DATA= '+ data) + global data patron = r'sources:\s*\[\{src:\s*"([^"]+)"' matches = scrapertools.find_multiple_matches(data, patron) for url in matches: diff --git a/servers/wstream.json b/servers/wstream.json index 99428674..72b1acbb 100644 --- a/servers/wstream.json +++ b/servers/wstream.json @@ -7,7 +7,7 @@ "find_videos": { "patterns": [ { - "pattern": "wstream\\.video.*?(?<!api)(?:=|/)(?:embed-)?(?<!streaming\\.php\\?id=)([a-z0-9A-Z]+)(?:[^/_.a-z0-9A-Z]|$)", + "pattern": "wstream\\.video(?!<).*?(?<!api)(?:=|/)(?:embed-)?(?<!streaming\\.php\\?id=)([a-z0-9A-Z]+)(?:[^/_.a-z0-9A-Z]|$)", "url": "https://wstream.video/video.php?file_code=\\1" }, { diff --git a/servers/wstream.py b/servers/wstream.py index 4993fb75..f903e8b7 100644 --- a/servers/wstream.py +++ b/servers/wstream.py @@ -11,8 +11,21 @@ headers = [['User-Agent', 'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:54.0) Gecko/20 def test_video_exists(page_url): logger.info("(page_url='%s')" % page_url) + resp = httptools.downloadpage(page_url) global data - data = httptools.downloadpage(page_url).data + data = resp.data + page_url = resp.url + if '/streaming.php' in page_url in page_url: + code = httptools.downloadpage(page_url, headers=headers, follow_redirects=False).headers['location'].split('/')[-1].replace('.html','') + logger.info('WCODE='+code) + page_url = 'https://wstream.video/video.php?file_code=' + code + data = httptools.downloadpage(page_url, headers=headers, follow_redirects=True).data + + ID, code = scrapertools.find_single_match(data, r"""input\D*id=(?:'|")([^'"]+)(?:'|").*?value='([a-z0-9]+)""") + post = urllib.urlencode({ID: code}) + + data = httptools.downloadpage(page_url, headers=headers, post=post, follow_redirects=True).data + if "Not Found" in data or "File was deleted" in data: return False, config.get_localized_string(70449) % 'Wstream' return True, "" @@ -24,20 +37,7 @@ def get_video_url(page_url, premium=False, user="", password="", video_password= video_urls = [] global data - if '/streaming.php' in page_url or 'html' in page_url: - try: - code = httptools.downloadpage(page_url, headers=headers, follow_redirects=False).headers['location'].split('/')[-1].replace('.html','') - logger.info('WCODE='+code) - page_url = 'https://wstream.video/video.php?file_code=' + code - data = httptools.downloadpage(page_url, headers=headers, follow_redirects=True).data - except: - pass - code = page_url.split('=')[-1] - ID = scrapertools.find_single_match(data, r'''input\D*id=(?:'|")([^'"]+)(?:'|")''') - post = urllib.urlencode({ID: code}) - - data = httptools.downloadpage(page_url, headers=headers, post=post, follow_redirects=True).data headers.append(['Referer', page_url]) _headers = urllib.urlencode(dict(headers)) diff --git a/specials/community.py b/specials/community.py index 9dacf7f6..4eaf0532 100644 --- a/specials/community.py +++ b/specials/community.py @@ -547,11 +547,9 @@ def episodios(item): if pagination and i >= pag * pagination: break # pagination match = [] if episode.has_key('number'): - match = support.match(episode['number'], r'(?P<season>\d+)x(?P<episode>\d+)')[0] - if match: - match = match[0] + match = support.match(episode['number'], patron=r'(?P<season>\d+)x(?P<episode>\d+)').match if not match and episode.has_key('title'): - match = support.match(episode['title'], r'(?P<season>\d+)x(?P<episode>\d+)')[0] + match = support.match(episode['title'], patron=r'(?P<season>\d+)x(?P<episode>\d+)').match if match: match = match[0] if match: episode_number = match[1] @@ -561,7 +559,7 @@ def episodios(item): season_number = episode['season'] if episode.has_key('season') else season if season else 1 episode_number = episode['number'] if episode.has_key('number') else '' if not episode_number.isdigit(): - episode_number = support.match(episode['title'], r'(?P<episode>\d+)')[0][0] + episode_number = support.match(episode['title'], patron=r'(?P<episode>\d+)').match ep = int(episode_number) if episode_number else ep if not episode_number: episode_number = str(ep).zfill(2) diff --git a/specials/nextep.py b/specials/nextep.py new file mode 100644 index 00000000..e2403011 --- /dev/null +++ b/specials/nextep.py @@ -0,0 +1,180 @@ +# -*- coding: utf-8 -*- +import xbmc, xbmcgui, os +from platformcode import config, platformtools, logger +from time import time, sleep +from core import scrapertools +from core import jsontools, filetools +from lib.concurrent import futures + +PLAYER_STOP = 13 +ND = 'NextDialogCompact.xml' if config.get_setting('next_ep_type') else 'NextDialog.xml' + +def check(item): + return True if config.get_setting('next_ep') > 0 and item.contentType != 'movie' else False + + +def return_item(item): + logger.info() + with futures.ThreadPoolExecutor() as executor: + future = executor.submit(next_ep, item) + item = future.result() + return item + +def run(item): + logger.info() + with futures.ThreadPoolExecutor() as executor: + future = executor.submit(next_ep, item) + item = future.result() + if item.next_ep: + from platformcode.launcher import play_from_library + return play_from_library(item) + + +def videolibrary(item): + from threading import Thread + item.videolibrary = True + Thread(target=next_ep, args=[item]).start() + + +def next_ep(item): + logger.info() + condition = config.get_setting('next_ep') + item.next_ep = False + item.show_server = True + + VL = True if item.videolibrary else False + + time_over = False + time_limit = time() + 30 + time_steps = [20,30,40,50,60] + TimeFromEnd = time_steps[config.get_setting('next_ep_seconds')] + + # wait until the video plays + while not platformtools.is_playing() and time() < time_limit: + sleep(1) + + while platformtools.is_playing() and time_over == False: + try: + Total = xbmc.Player().getTotalTime() + Actual = xbmc.Player().getTime() + Difference = Total - Actual + if Total > TimeFromEnd >= Difference: + time_over = True + except: + break + + if time_over: + if condition == 1: # hide server afther x second + item.show_server = False + elif condition == 2: # play next fileif exist + + # check i next file exist + current_filename = os.path.basename(item.strm_path) + base_path = os.path.basename(os.path.normpath(os.path.dirname(item.strm_path))) + path = filetools.join(config.get_videolibrary_path(), config.get_setting("folder_tvshows"),base_path) + fileList = [] + for file in os.listdir(path): + if file.endswith('.strm'): + fileList.append(file) + + fileList.sort() + + nextIndex = fileList.index(current_filename) + 1 + if nextIndex == 0 or nextIndex == len(fileList): + next_file = None + else: + next_file = fileList[nextIndex] + + # start next episode window afther x time + if next_file: + from core.item import Item + season_ep = next_file.split('.')[0] + season = season_ep.split('x')[0] + episode = season_ep.split('x')[1] + next_ep = '%sx%s' % (season, episode) + item = Item( + action= 'play_from_library', + channel= 'videolibrary', + contentEpisodeNumber= episode, + contentSeason= season, + contentTitle= next_ep, + contentType= 'tvshow', + infoLabels= {'episode': episode, 'mediatype': 'tvshow', 'season': season, 'title': next_ep}, + strm_path= filetools.join(base_path, next_file)) + + global ITEM + ITEM = item + + nextDialog = NextDialog(ND, config.get_runtime_path()) + nextDialog.show() + while platformtools.is_playing() and not nextDialog.is_still_watching(): + xbmc.sleep(100) + pass + + nextDialog.close() + logger.info('Next Episode: ' +str(nextDialog.stillwatching)) + + if nextDialog.stillwatching or nextDialog.continuewatching: + item.next_ep = True + xbmc.Player().stop() + if VL: + sleep(1) + xbmc.executebuiltin('Action(Back)') + sleep(0.5) + from platformcode.launcher import play_from_library + return play_from_library(item) + else: + item.show_server = False + if VL: + sleep(1) + xbmc.executebuiltin('Action(Back)') + sleep(0.5) + return None + + return item + + +class NextDialog(xbmcgui.WindowXMLDialog): + item = None + cancel = False + stillwatching = False + continuewatching = True + + def __init__(self, *args, **kwargs): + logger.info() + self.action_exitkeys_id = [10, 13] + self.progress_control = None + self.item = ITEM + + def set_still_watching(self, stillwatching): + self.stillwatching = stillwatching + + def set_continue_watching(self, continuewatching): + self.continuewatching = continuewatching + + def is_still_watching(self): + return self.stillwatching + + def onFocus(self, controlId): + pass + + def doAction(self): + pass + + def closeDialog(self): + self.close() + + def onClick(self, controlId): + if controlId == 3012: # Still watching + self.set_still_watching(True) + self.set_continue_watching(False) + self.close() + elif controlId == 3013: # Cancel + self.set_continue_watching(False) + self.close() + + def onAction(self, action): + logger.info() + if action == PLAYER_STOP: + self.set_continue_watching(False) + self.close() diff --git a/specials/resolverdns.py b/specials/resolverdns.py index 3f99eda2..ec244237 100644 --- a/specials/resolverdns.py +++ b/specials/resolverdns.py @@ -40,7 +40,7 @@ class CipherSuiteAdapter(host_header_ssl.HostHeaderSSLAdapter): def __init__(self, domain, CF=False, *args, **kwargs): self.conn = sql.connect(db) self.cur = self.conn.cursor() - self.ssl_context = CustomContext(ssl.PROTOCOL_TLS, domain) + self.ssl_context = CustomContext(ssl.PROTOCOL_TLS if 'PROTOCOL_TLS' in ssl.__dict__ else ssl.PROTOCOL_SSLv3, domain) self.CF = CF # if cloudscrape is in action self.cipherSuite = kwargs.pop('cipherSuite', ssl._DEFAULT_CIPHERS) @@ -99,7 +99,7 @@ class CipherSuiteAdapter(host_header_ssl.HostHeaderSSLAdapter): domain = parse.netloc else: raise requests.exceptions.URLRequired - self.ssl_context = CustomContext(ssl.PROTOCOL_TLS, domain) + self.ssl_context = CustomContext(ssl.PROTOCOL_TLS if 'PROTOCOL_TLS' in ssl.__dict__ else ssl.PROTOCOL_SSLv3, domain) if self.CF: self.ssl_context.options |= (ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3 | ssl.OP_NO_TLSv1 | ssl.OP_NO_TLSv1_1) self.ssl_context.set_ciphers(self.cipherSuite) diff --git a/specials/videolibrary.py b/specials/videolibrary.py index 55793688..ec50021f 100644 --- a/specials/videolibrary.py +++ b/specials/videolibrary.py @@ -558,6 +558,7 @@ def findvideos(item): server.channel = "videolibrary" server.nfo = item.nfo server.strm_path = item.strm_path + server.play_from = item.play_from #### Compatibilidad con Kodi 18: evita que se quede la ruedecedita dando vueltas en enlaces Directos if server.action == 'play': @@ -576,7 +577,10 @@ def findvideos(item): # return sorted(itemlist, key=lambda it: it.title.lower()) autoplay.play_multi_channel(item, itemlist) - + from inspect import stack + from specials import nextep + if nextep.check(item) and stack()[1][3] == 'run': + nextep.videolibrary(item) return itemlist