#!/usr/bin/env python # coding=utf8 # # This file is part of PlayStream - enigma2 plugin to play video streams from various sources # Copyright (c) 2016 ivars777 (ivars777@gmail.com) # Distributed under the GNU GPL v3. For full terms see http://www.gnu.org/licenses/gpl-3.0.en.html # import sys, os, os.path, re, sys import urllib,urllib2,urlparse #from xml.sax.saxutils import unescape,escape from urllib import quote, unquote import HTMLParser import json from SourceBase import SourceBase, stream_type import util from util import unescape from collections import OrderedDict import ssl if "_create_unverified_context" in dir(ssl): ssl._create_default_https_context = ssl._create_unverified_context import time, datetime, pytz from datetime import datetime as dt dt2ts = lambda dt: int(time.mktime(dt.timetuple())) ts2dt = lambda ts: datetime.datetime.fromtimestamp(ts) user_agent = "User-Agent: Shortcut.lv for Android TV v1.11.5 / Dalvik/2.1.0 (Linux; U; Android 6.0; Android SDK built for x86 Build/MASTER)" headers2dict = lambda h: dict([l.strip().split(": ") for l in h.strip().splitlines()]) h = HTMLParser.HTMLParser() class Source(SourceBase): def __init__(self,cfg_path=None): self.name = "ltc2" self.title = "Shortcut.lv" self.img = "shortcut.png" self.desc = "Shortcut.lv (lattelecom.tv) satura skatīšanās" self.token = "" self.session_id = "" # www.shortcut.lv self.api_url = "https://manstv.lattelecom.tv/api/v1.7/get/content/" self.headers = headers2dict(""" User-Agent: Shortcut.lv for Android TV v1.11.5 / Dalvik/2.1.0 (Linux; U; Android 6.0; Android SDK built for x86 Build/MASTER) Connection: Keep-Alive """) self.headers2 = headers2dict(""" Connection: keep-alive User-Agent: Shortcut.lv for Android TV v1.11.5 / Dalvik/2.1.0 (Linux; U; Android 6.0; Android SDK built for x86 Build/MASTER) Accept-Language: en-US,en;q=0.8 """) self.channels = None ### specific service info ### self.ch = [] self.ch2 = [] self.ch_id={} self.ch_id2={} self.ch_name={} self.today = datetime.date.today() self.today2 = self.today.strftime("%d.%m.%Y") cur_directory = os.path.dirname(os.path.abspath(__file__)) if not cfg_path: cfg_path = cur_directory self.config_file = os.path.join(cfg_path,self.name+".cfg") self.options = OrderedDict([("user","lietotajs"),("password","parole")]) self.options_read() def get_content(self, data): print "[ltc] get_content:", data source, data, path, plist, clist, params, qs = self.parse_data(data) content=[] content.append(("..return", "back","back.png","Return back")) if clist=="home": content.extend([ ("TV tiešraides", "ltc::tiesraide","","TV tiešraides"), ("TV arhīvs", "ltc::pages/archive","","TV arhīvs atseviškiem kanāliem"), ("Bērnu", "ltc::pages/kids","","Videonomas bērnu filmas un seriāli"), ("Filmas", "ltc::pages/films","","Videonomas filmas"), ("Premiere filmas", "ltc::pages/premiere","","Videonomas premiere filmas"), ("Seriāli", "ltc::pages/series","","Videonomas seriāli"), ("360 Play", "ltc::/pages/360-play","","Videonomas lattelecom saturs"), ("Meklēt", "ltc::search/{0}","","Meklēt visā saturā"), #TODO ]) return content ### Meklēt TV (1.7 API) elif clist == "search": #TODO vod/search/{q} q = plist[1] r = self.call("pages/search/?filter[term]=%s&include=items,items.item" % q) # TODO return content ### Tiešraides #### elif data=="tiesraide": now = dt2ts(dt.now()) r = self.call("epgs/?filter[utFrom]=%s&filter[utTo]=%s&include=channel&page[size]=1000" % (now, now)) epgs = r["data"] for item in self.get_channels(): title = item["attributes"]["title"] data2 = "live-streams/%s?include=quality"%item["id"] for epg in epgs: if item["id"] == epg["relationships"]["channel"]["data"]["id"]: epg = epg["attributes"] break else: epg = None if epg: start = ts2dt(int(epg["unix-start"])) start = start.strftime("%H:%M") end = ts2dt(int(epg["unix-stop"])) end = end.strftime("%H:%M") title = "%s - %s [%s-%s]"%(title,epg["title"],start,end) desc = title if epg["description"]: desc += "\n" + epg["description"] img = "https://manstv.lattelecom.tv/"+ epg["poster-url"] else: img = "https://manstv.lattelecom.tv/"+ item["attributes"]["logo-url"] desc = item["attributes"]["description"] content.append((title,self.name+"::"+data2,img,desc)) return content ### Pages ### elif clist=="pages" or data=="arhivs": r = self.call(data+"?page[size]=1000") for item in r["data"]: title = item["attributes"]["title"] data2 = item["links"]["self"][1:] + "?include=items" img = self.img desc = title content.append((title,self.name+"::"+data2,img,desc)) return content ### Kategorija ### elif clist=="categories" and len(plist) > 1: r = self.call(data) for item in r["items"]: title = item["name"] data2 = "archive/records?filter[category]=%s&limit=40"%item["id"] img = "https://manstv.lattelecom.tv/"+ item['image'] desc = title content.append((title,self.name+"::"+data2,img,desc)) return content ### Arhīva kategorijas elif data=="archive/categories": #https://manstv.lattelecom.tv/api/v1.3/get/archive/records/?filter[category]=13&limit=10&until_id=1458681019238 #https://manstv.lattelecom.tv/api/v1.3/get/archive/categories/ r = self.call(data) for item in r["items"]: title = item["name"] data2 = "archive/records?filter[category]=%s&limit=40"%item["id"] img = "https://manstv.lattelecom.tv/"+ item['image'] desc = title content.append((title,self.name+"::"+data2,img,desc)) return content ### Arhīva kategoriju video elif "archive/records" in data: #https://manstv.lattelecom.tv/api/v1.3/get/archive/records/?filter[category]=13&limit=10&until_id=1458681019238 #https://manstv.lattelecom.tv/api/v1.3/get/archive/categories/ r = self.call(data) for i,item in enumerate(r["items"]): #if not item["is_archive"]==u"1":continue # TODO jānočeko, kurs no atributiem apzīmē, ka ir arhīvs #if not self.epg_id.has_key(item["id"]): item["time_start2"] = datetime.datetime.fromtimestamp(int(item["unix_start"])) item["time_stop2"] = datetime.datetime.fromtimestamp(int(item["unix_stop"])) item["date"]=item["time_start2"].strftime("%Y-%m-%d") #self.epg.append(item) #index = self.epg.index(item) #self.epg_id[item["id"]]=index #if not item["date"] in self.epg_date: # self.epg_date[item["date"]]=[] #self.epg_date[item["date"]].append(index) #if not item["channel_id"] in self.epg_ch: # self.epg_ch[item["channel_id"]]=[] #self.epg_ch[item["channel_id"]].append(index) #item = self.get_epg_id(item["id"]) ch = self.get_channel_by_id2(item["channel_id"]) ch_name = ch["name"] if ch else item["channel_id"] title = u"%s (%s-%s)"%(item["title"], item["time_start2"].strftime("%H:%M"),item["time_stop2"].strftime("%H:%M")) #data2 = "archive/get-stream/%s?channelid=%s"%(item["id"],ch["id"]) data2 = "content/record-streams/%s?include=quality"%item["id"] img = "https://manstv.lattelecom.tv/"+ item["url"] desc = u"%s - %s\n%s %s-%s\n%s\n%s"%(ch_name,item["title"], item["date"], item["time_start2"].strftime("%H:%M"),item["time_stop2"].strftime("%H:%M"), item["category1"],item["description"]) content.append((title,self.name+"::"+data2,img,desc)) if "until_id" in data: data2 = re.sub("until_id=\d+","until_id="+item["id"],data) else: data2 = data + "&until_id=%s"%item["id"] content.append(("Next page",self.name+"::"+data2,"next.png","Go to next page")) return content ### Arhīva kanānālu saraksts elif data=="archive/channels": for item in self.get_channels(): if not item["is_archive"]==u"1":continue title = item["name"] data2 = "archive/channel/%s?date=%s"%(item["id"],self.today.strftime("%Y-%m-%d")) img = "https://manstv.lattelecom.tv/"+ item['broadcast_default_picture'] desc = title content.append((title,self.name+"::"+data2,img,desc)) return content ### Arhīva kanānāla video saraksta elif "archive/channel/" in data: chid = path.split("/")[2] for item in self.get_epg_date(qs["date"],chid): if item["is_archive"]=='0':continue if item["time_stop2"] > datetime.datetime.now(): continue ch = self.get_channel_by_id2(item["channel_id"]) ch_name = ch["name"] if ch else item["channel_id"] #title = u"[%s %s-%s] %s - %s"%(item["date"],item["time_start2"].strftime("%H:%M"),item["time_stop2"].strftime("%H:%M"),ch_name,item["title"]) title = u"%s (%s-%s)"%(item["title"], item["time_start2"].strftime("%H:%M"),item["time_stop2"].strftime("%H:%M")) #data2 = "archive/get-stream/%s?channelid=%s"%(item["id"],ch["id"]) data2 = "content/record-streams/%s?include=quality"%item["id"] img = "https://manstv.lattelecom.tv/"+ item["url"] desc = u"%s - %s\n%s %s-%s\n%s\n%s"%(ch_name,item["title"], item["date"], item["time_start2"].strftime("%H:%M"),item["time_stop2"].strftime("%H:%M"), item["category1"],item["description"]) content.append((title,self.name+"::"+data2,img,desc)) #date2=datetime.datetime.strptime(qs["date"], '%Y-%m-%d').date()-datetime.timedelta(days=1) date2 = datetime.date(*tuple(map(int, qs["date"].split("-")))) - datetime.timedelta(days=1) date2 = date2.strftime("%Y-%m-%d") if "date=" in data: data2 = re.sub("date=[\d-]+","date="+date2,data) else: data2 = data + "&date=%s"%date2 content.append(("Previous day (%s)"%date2,self.name+"::"+data2,"","Go previous day")) return content ### Arhīva datumi elif clist=="arhivs" and len(data.split("/"))==2: # TODO - pasreiz nestrada ch = data.split("/")[1] r= self.call(data) m = re.search('class="spac no_select">([^<]+)', r, re.IGNORECASE) if m: ch_name = m.group(1) else: ch_name = "" today = datetime.date.today() for i in range(7): date = today-datetime.timedelta(i) title = ch_name + " - " + date.strftime("%d.%m.%Y") data2 = "%s/%s"%(data,date.strftime("%Y-%m-%d")) img = "" desc = title content.append((title,self.name+"::"+data2,img,desc)) return content ### Arhīva dienas raidijumi elif clist=="arhivs" and len(data.split("/"))==3: # TODO - nestrādā ch = data.split("/")[1] date = data.split("/")[2] r= self.call(data) m = re.search('class="spac no_select">([^<]+)', r, re.IGNORECASE) if m: ch_name = m.group(1) else: ch_name = "" for item in re.findall('(?i)href="/([^"]+?)" id="" class="archive_programm_a">
([^<]+)
([^<]+)', r): title = "%s - %s"%(item[1],item[2]) data2 = item[0] img = "" desc = "%s (%s)\n%s"%(ch_name,date,title) content.append((title,self.name+"::"+data2,img,desc)) return content ### Videonoma galvenā (vecā, vairs nestrada filtri) elif data=="videonoma": content.extend([ ("Filmas - jaunākās", "ltc::videonoma?page=0&genre=all_movies&sorts=laiks&cnt=40&clear=true&filter={}","https://www.shortcut.lv/media/features/2013-12-17/aa3b_videonoma_dropdown_filmas.png","Jaunākās filmas"), ("Filmas - pēc nosaukuma", "ltc::videonoma?page=0&genre=all_movies&sorts=title&cnt=40&clear=true&filter={}","https://www.shortcut.lv/media/features/2013-12-17/aa3b_videonoma_dropdown_filmas.png","Filmas pēc nosaukuma"), ("Filmas - latviski", 'ltc::videonoma?page=0&genre=all_movies&sorts=laiks&cnt=40&clear=true&filter={"valoda":["lv"]}',"https://www.shortcut.lv/media/features/2013-12-17/aa3b_videonoma_dropdown_filmas.png","Filmas latviešu valodā"), ("Filmas - pēc reitinga", "ltc::videonoma?page=0&genre=all_movies&sorts=imbd&cnt=40&clear=true&filter={}","https://www.shortcut.lv/media/features/2013-12-17/aa3b_videonoma_dropdown_filmas.png","Filmas pēc IMBD reitinga"), ("Filmas bērniem - jaunākās", "ltc::videonoma?page=0&genre=3&sorts=laiks&cnt=40&clear=true&filter={}","https://www.shortcut.lv/images/redesign/videonoma_dropdown_berniem.png","Jaunākie bernu video"), ("Filmas bērniem - pēc nosaukuma", "ltc::videonoma?page=0&genre=3&sorts=title&cnt=40&clear=true&filter={}","https://www.shortcut.lv/images/redesign/videonoma_dropdown_berniem.png","Bērnu video pēc nosaukuma"), ("Filmas bērniem - latviski", 'ltc::videonoma?page=0&genre=3&sorts=laiks&cnt=40&clear=true&filter={"valoda":[\"lv\"]}',"https://www.shortcut.lv/images/redesign/videonoma_dropdown_berniem.png","Bērnu video latviski"), ("Filmas bērniem - pēc reitinga", "ltc::videonoma?page=0&genre=3&sorts=imbd&cnt=40&clear=true&filter={}","https://www.shortcut.lv/images/redesign/videonoma_dropdown_berniem.png","Bērnu video pēc IMBD reitinga"), ("Sērijas - jaunākās", "ltc::videonoma?page=0&genre=27&sorts=laiks&cnt=40&clear=true&filter={}","https://www.shortcut.lv/images/redesign/videonoma_dropdown_raidijumi.png","Jaunākās sērijas"), ("Sērijas - pēc nosaukuma", "ltc::videonoma?page=0&genre=27&sorts=title&cnt=40&clear=true&filter={}","https://www.shortcut.lv/images/redesign/videonoma_dropdown_raidijumi.png","Sērijas pēc pēc nosaukuma"), ("Sērijas animācijas - jaunākās", "ltc::videonoma?page=0&genre=27&sorts=laiks&cnt=40&clear=true&filter={\"zanrs\":[\"201\"]}","https://www.shortcut.lv/images/redesign/videonoma_dropdown_raidijumi.png","Animācijas serijas"), ("Sērijas animācijas - pēc nosaukuma", "ltc::videonoma?page=0&genre=27&sorts=title&cnt=40&clear=true&filter={\"zanrs\":[\"201\"]}","https://www.shortcut.lv/images/redesign/videonoma_dropdown_raidijumi.png","Animācijas serijas"), ("Sērijas ģimenes - jaunākās", "ltc::videonoma?page=0&genre=27&sorts=laiks&cnt=40&clear=true&filter={\"zanrs\":[\"195\"]}","https://www.shortcut.lv/images/redesign/videonoma_dropdown_raidijumi.png","Animācijas serijas"), ("Sērijas ģimenes - pēc nosaukuma", "ltc::videonoma?page=0&genre=27&sorts=title&cnt=40&clear=true&filter={\"zanrs\":[\"195\"]}","https://www.shortcut.lv/images/redesign/videonoma_dropdown_raidijumi.png","Animācijas serijas"), ("Sērijas latviski - jaunākās", 'ltc::videonoma?page=0&genre=27&sorts=laiks&cnt=40&clear=true&filter={"valoda":["lv"]}',"https://www.shortcut.lv/images/redesign/videonoma_dropdown_raidijumi.png","Sērijas latviski"), ("Sērijas latviski - pēc nosaukuma", 'ltc::videonoma?page=0&genre=27&sorts=title&cnt=40&clear=true&filter={"valoda":["lv"]}',"https://www.shortcut.lv/images/redesign/videonoma_dropdown_raidijumi.png","Sērijas latviski"), ("Koncerti - jaunākie", "ltc::videonoma?page=0&genre=19&sorts=laiks&cnt=40&clear=true&filter={}","https://www.shortcut.lv/images/redesign/videonoma_dropdown_koncerti.png","Jaunākie koncerti"), ("Koncerti - pēc nosaukuma", "ltc::videonoma?page=0&genre=19&sorts=title&cnt=40&clear=true&filter={}","https://www.shortcut.lv/images/redesign/videonoma_dropdown_koncerti.png","Koncerti pēc pēc nosaukuma"), ]) return content ### Videonomas saraksti (vecie, vairs nestrādā filtri) elif path == "videonoma": url = "https://www.shortcut.lv/movies-snippet.json"+params r = self._http_request(url,headers=self.headers2) if not r: return content js = json.loads(r,"utf8") if not r: return content for item in js["movies"]: if not item["title"]: continue title = item["title"].encode("utf8") data2 = item["url"][1:].encode("utf8") if data2[-1]=="/": data2=data2[:-1] if "/raidijumi/" in data2: data2 += "?series" # TODO img = "https://www.shortcut.lv"+item["image"].encode("utf8") desc = "%s\n%s"%(title,item["genre"].encode("utf8")) if "is_premium" in item and item["is_premium"]: title = title + " [P]" desc = desc + "\nPremium" content.append((title,self.name+"::"+data2,img,desc)) m = re.search("page=(\d+)",data) if m: page = int(m.group(1)) data2 = re.sub("page=\d+","page=%s"%(page+1),data) content.append(("Next page",self.name+"::"+data2,"next.png","Go to next page")) return content ### Filmas galvenā ### elif data == "videonoma/filmas": content.extend([ ("Aktuālās", "ltc::viss/actual_films","","Nesen pievienotas filmas"), ("Komēdijas", "ltc::viss/comedy","","Komēdijas"), ("Detektīvi", "ltc::viss/crime","","Detektivi"), ("Ģimenes", "ltc::viss/family","","Ģimenes filmas"), ("Asa sižeta", "ltc::viss/action","","Asa sižeta filmas"), ("Romantika", "ltc::viss/romance","","Romantiskās filmas"), ("Piedzīvojumu", "ltc::viss/adventure","","Piedzivojumu filmas"), ("Supervaroņi", "ltc::viss/superheros","","Supervaroņu filmas"), ("Fantastika", "ltc::viss/scifi","","Fantastikas filmas"), ("Dokumentalās", "ltc::viss/documentaries","","Dokumentalās filmas"), ("Šausmu", "ltc::viss/horror","","Šausmu filmas"), ("Retro", "ltc::viss/retro_films","","Retro filmas"), ("Koncerti un karaoke", "ltc::viss/concerts_karaoke","","Koncerti un filmas"), ]) ### Sērijas galvenā ### elif data == "videonoma/series": content.extend([ ("Aktuālie seriāli", "ltc::viss/actual_series?series","","Nesen pievienotie seriāli"), ("Aktuālie šovi", "ltc::viss/actual_series?series","","Nesen pievienotie TV šovi"), ("Populārākie seriāli", "ltc::viss/popular_series?series","","Populārākie seriāli"), ("Dokumentalie seriāli", "ltc::viss/documentary?series","","Dokumentalie seriāli"), ("Izklaides pārraides", "ltc::viss/entertainment?series","","Izklaides pārraides"), ("Detektivseriāli", "ltc::viss/Crime_series?series","","Detektivseriāli"), ("Dramas seriāli", "ltc::viss/drama_series?series","","Dramas seriāli"), ("Par dabu", "ltc::viss/nature?series","","Seriāli par dabu"), ("Gardēžiem", "ltc::viss/gourmets?series","","Seriāli gardēžiem"), ("Mistērija", "ltc::viss/mystery_series?series","","Mistērijas seriāli"), ("Oriģinālsaturs", "ltc::viss/originals_series?series","","Oriģinālsatura seriāli"), ("Klasika", "ltc::viss/classic?series","","Klasika"), ]) ### Bērnu galvenā ### elif data == "videonoma/bernu": content.extend([ ("Nesen pievienotais", "ltc::viss/actual_kid","","Nesen pievienotais bernu saturs"), ("Bērnu Premiere", "ltc::viss/kids_premiere","","Bērnu Premiere saturs"), ("Multfilmas", "ltc::viss/animation2","","Multfilmas"), ("Bērnu seriāli", "ltc::viss/kids_series?series","","Bērnu seriāli"), ("Ģimenes filmas", "ltc::viss/family","","Ģimenes filmas"), ("Multfilmas latviski", "ltc::viss/animation_lv","","Multfilmas latviski"), ("Retro multfilmas", "ltc::viss/retro_animation","","Retro multfilmas"), ("Latviešu multfilmas", "ltc::viss/animation","","Latviešu multfilmas"), ("Raidijumi berniem", "ltc::viss/kids_events","","Raidijumi berniem"), ]) ### Filmas premiere galvenā ### elif data == "videonoma/premiere": content.extend([ ("Aktuālās Premiere filmas", "ltc::viss/actual_premiere","","Nesen pievienotās Premiere filmas"), ("Tikko no kinoteātra", "ltc::viss/just_from_cinema","","Filmas tikko no kinoteātra"), ("Bērnu Premiere", "ltc::viss/kids_premiere","","Bērnu Premiere saturs"), ("Komēdijas Premiere", "ltc::viss/comedy_premiere","","Premiere komēdijas filmas"), ("Detektivi Premiere", "ltc::viss/crime_premiere","","Premiere detektivfilmas"), ("Piedzīvojumu Premiere", "ltc::viss/adventure_premiere","","Premiere piedzivojumu filmas"), ("Fantastika Premiere", "ltc::viss/scifi_premiere","","Premiere fantastikas filmas"), ("Šausmu Premiere", "ltc::viss/horror_premiere","","Premiere šausmu filmas"), ]) ### 360 Play galvenā ### elif data == "videonoma/360play": content.extend([ ("Viss", "ltc::viss/bezmaksas?series","","Viss bezmaksas saturs"), ("360TV", "ltc::viss/360_free?series","","360TV bezmaksas saturs"), ("Red Bull", "ltc::viss/Red_bull?series","","Red Bull bezmaksas saturs"), ]) r = self.call ### Videonomas saraksti ### elif plist[0] == "viss" or "load_more" in data: #content.append(("Videonomas saraksts", "", "", "")) if "viss" in data: r = self.call2(data) m = re.search('(
.+?)
', r, re.DOTALL) html = m.group(1) if m else "" else: url = self.api_url2 + path params = data.split("?")[1] r = self._http_request(url, params, headers=self.headers3 ) js = json.loads(r) html = js["data"] if "data" in r else "" result = re.findall("
", html, re.DOTALL) for it in result: title1 = re.search('
(.+?)<', it, re.DOTALL).group(1) title2 = re.search('
(.+?)<', it, re.DOTALL).group(1) if title1 <> title2: title = "%s ~ %s" % (title1, title2) else: title = title1 img = self.api_url2 + re.search('img src="(.+?)"', it).group(1) data2 = re.search('href="/(.+?)/"', it).group(1) if "?series" in data or re.search("e\d+$", data2): data2 += "?series" if "Jaunums" in it: title += " [J]" if "Premiere" in it: title += " [P]" desc = title content.append((title,self.name+"::"+data2,img,desc)) if not "end-reached-box" in r: if "load_more" in data: page = int(qs["pack"]) data2 = re.sub("pack=\d+","pack=%s"%(page+1),data) else: section = re.search('data-section="(\d+)"', r).group(1) data2 = "load_more.json?pack=1§ion=%s" % section content.append(("Next page",self.name+"::"+data2,"next.png","Go to next page")) return content ### Sērijas elif clist=="videonoma" and (params=="?series" or "season_nr" in qs): url = "https://www.shortcut.lv/"+path r = self._http_request(url,headers=self.headers2) if not r: return content m = re.search(r'data-movieid=\d+>
([^<]+)
]+>([^<]+)<', r) if m: title1 = unescape(m.group(1)) title2 = unescape(m.group(2)) else: m = re.search('', r, re.IGNORECASE) title1 = title2 = unescape(m.group(1)) if m else "Video" if 'episode_switcher_title' in r: set1 = title1.replace("\xe2\x80\x93", "-") if " - " in set1: set1 = set1.split(" - ")[0] set2 = title2.replace("\xe2\x80\x93", "-") if " - " in set2: set2 = set2.split(" - ")[0] if set1 <> set2: raidijums = "%s ~ %s" % (set1, set2) else: raidijums = set1 else: m = re.search('
([^<]+)
', r) raidijums = m.group(1) if m else "Series" img0 = re.search('', r).group(1) if re.search('', r) else "" m = re.search('season_choice', r) # Ir sezonas if m: result = re.findall(r"""season_choice\(.+?'epizode','([^']*)',[^,]+,'(\d+)',[^,]+,[^,]+\)">([^<]+)<""", r, re.MULTILINE) if not result: raise Exception("No seasons find!") vid = result[0][0] if not "season_nr" in qs: # Sezonu saraksts for s,it in enumerate(result): title = "%s - %s" % (raidijums, it[2]) data2 = path+"?season_nr=%s"%(it[1]) img = img0 desc = title content.append((title, self.name + "::" + data2, img, desc)) #return content else: # Sezonas epizožu saraksts if not "season_nr" in qs: qs["season_nr"]="0" # https://www.shortcut.lv/api/episode-loader-design17/0?chunk_size=4&sorting=epizode&series_id=dora_the_explorer # https://www.shortcut.lv/api/episode-loader-design17/3?chunk_size=4&sorting=epizode&series_id=dora_the_explorer&movie_id=10161&z360tv=&is_active_season=false HTTP/1.1 # https://www.shortcut.lv/api/episode-loader-design17/3?chunk_size=4&sorting=epizode&series_id=dora_the_explorer url = "https://www.shortcut.lv/api/episode-loader-design17/%s?chunk_size=4&sorting=epizode&series_id=%s" % (qs["season_nr"], vid) r = self._http_request(url,headers=self.headers2) try: js = json.loads(r) except: raise Exception("Error getting episode list") result = re.findall(r'class="" href="([^"]+)".+?image:url\(([^ \)]+)\); ">
([^<]+)
([^<]+)
', js["data"]) for item in result: title = "%s - %s (%s)"%(raidijums,item[2],item[3]) data2 = item[0][1:] img = "https://www.shortcut.lv"+item[1] desc = title content.append((title,self.name+"::"+data2,img,desc)) #return content # Nav sezonu else: result = re.findall(r'class="" href="([^"]+)".+?image:url\(([^ \)]+)\).+?class="episode_titlez_design17">([^<]+)
([^<]+)
', r) for item in result: title = "%s - %s(%s)"%(raidijums,item[2],item[3]) data2 = item[0][1:] img = "https://www.shortcut.lv"+item[1] desc = title content.append((title,self.name+"::"+data2,img,desc)) #return content if not result: # nav ne epizožu, atgriež pats sevi bez ?series title = desc = raidijums img = img0 data2 = path content.append((title,self.name+"::"+data2,img,desc)) return content ### Videonomas video elif clist=="videonoma" and len(data.split("/"))> 2: ch = data.split("/")[1] video_id=data[data.find("/")+1:] #video_id=data.split("/")[-1] if not self.is_logedin2(): if not self.login2(): content=("Can not login\nPlease check lattelecom.tv username/password in\n/usr/lib/enigma2/python/Plugins/Extensions/sources/ltc.cfg file","","","No stream found. Please check lattelecom.tv username/password in sources/ltc.cfg file ") return content data2 = self.get_noma_url(video_id) if not data2: content=("No stream found for '%s'"%data,"","","No stream found") return content r = self.call2(data) m = re.search('', r, re.IGNORECASE) if m: title = m.group(1) else: title = "" desc = title content = (title,data2,"",desc) return content return content def get_streams(self, data): print "[ltc] get_streams:", data if not self.is_video(data): return [] source, data, path, plist, clist, params, qs = self.parse_data(data) #if "::" in data: data = data.split("::")[1] ### Video nomas strīmus pagaidām dabu no mājas lapas TODO if data.split("/")[0]=="videonoma" and len(data.split("/"))>1: #video_id=data.split("/")[-1] streams = self.get_stream_url2(data) else: if not self.is_logedin(): if not self.login(): return [] if plist[1] == "catchup": start = int(qs["start"]) + 1 #url = "https://manstv.lattelecom.tv/api/v1.7/get/content/epgs/?filter[channel]=101&filter[utFrom]=1551551500&include=channel&page[size]=40page[number]=1" data2 = "content/epgs/?filter[channel]=%s&filter[utFrom]=%s&filter[utTo]=%s&include=channel&page[size]=40page[number]=1" % (plist[2], start, start ) r2 = self.call(data2) if "data" in r2: epgid = r2["data"][0]["id"] else: return [] data = "ltc::content/record-streams/%s?include=quality" % epgid source, data, path, plist, clist, params, qs = self.parse_data(data) data = data + "&auth_token=app_" + self.token headers = self.headers headers["Authorization"] = "Bearer " + self.token r = self.call(data, headers=headers) if not r: return [] if "errors" in r: return [] #self.refresh_token() #token = "&auth_token=app_%s"%(self.token) vid = data.split("/")[2].split("?")[0] vtype = data.split("/")[1] if vtype == "live-streams": ch = self.get_channel_by_id(vid) title = ch["attributes"]["title"] now = dt2ts(dt.now()) r2 = self.call("content/epgs/?filter[channel]=%s&filter[utFrom]=%s&filter[utTo]=%s&include=channel" % (vid, now, now)) epg = r2["data"][0]["attributes"] if len(r2["data"]) > 0 else None if epg: start = ts2dt(int(epg["unix-start"])) start = start.strftime("%H:%M") end = ts2dt(int(epg["unix-stop"])) end = end.strftime("%H:%M") title = "%s - %s [%s-%s]"%(title,epg["title"],start,end) desc = title if epg["description"]: desc += "\n" + epg["description"] img = "https://manstv.lattelecom.tv/"+ epg["poster-url"] else: img = "https://manstv.lattelecom.tv/"+ ch["attributes"]["logo-url"] desc = ch["attributes"]["description"] elif vtype == "record-streams": epg = self.get_epg_id(vid) if epg: title = epg["title"].encode("utf8") t1 = datetime.datetime.fromtimestamp(int(epg["unix_start"])).strftime('%H:%M') t2 = datetime.datetime.fromtimestamp(int(epg["unix_stop"])).strftime('%H:%M') date = epg["date"] #title = "%s [%s %s-%s]"%(title,date,t1,t2) desc = title + "\n" + epg["description"].encode("utf8") img = epg["img"].encode("utf8") if "img" in epg else "" else: title = desc = data img = "" streams = [] for s in r["data"]: stream = util.item() stream["url"]=(s["attributes"]["stream-url"]).encode("utf8") stream["name"]=title stream["desc"]=desc stream["img"] = img stream["type"]="hls" m = re.search(".+_(\w\w)_(\w\w)\.\w+",s["id"]) if m: stream["quality"]=m.group(2).encode("utf8") stream["lang"]=m.group(1).encode("utf8") streams.append(stream) ### TODO - sakārtot sarakstu, lai pirmais ir labakais video qlist = ["???","lq","mq","hq","hd"] llist = ["fr","en","ru","lv"] for s in streams: lv = llist.index(s["lang"])*10 if s["lang"] in llist else 0 qv=qlist.index(s["quality"]) if s["quality"] in qlist else 0 s["order"] = lv+qv streams = sorted(streams,key=lambda item: item["order"],reverse=True) return streams def is_video(self,data): source, data, path, plist, clist, params, qs = self.parse_data(data) if "get-stream" in data: return True if clist in ("live-streams","record-streams","vod-streams", "catchup"): return True elif cmd[0]=="arhivs" and len(cmd)==4: return True elif cmd[0]=="videonoma" and len(cmd) >= 3 and not "?" in data: return True else: return False def get_channels(self): if self.ch: return self.ch #if not self.check_logedin(): # self.login() # citādi nerāda TV3, LNT, TV6 r= self.call("channels?page[size]=1000&&filter[state]=1") self.ch=[] for i,item in enumerate(r["data"]): self.ch.append(item) self.ch_id[item["id"]]=i self.ch_name[item["attributes"]["title"]]=i return self.ch def get_channel_by_id(self,chid): if not self.ch: self.get_channels() if not self.ch: return None return self.ch[self.ch_id[chid]] if self.ch_id.has_key(chid) else None def get_channel_by_id2(self,chid): if not self.ch: self.get_channels() if not self.ch: return None return self.ch[self.ch_id2[chid]] if self.ch_id2.has_key(chid) else None def get_channels2(self): if self.ch2: return self.ch2 r= self.call2("tiesraide") self.ch2=[] for item in re.findall(r'
([^<]+)
]+>([^<]+)<', r) if m: title1 = unescape(m.group(1)) title2 = unescape(m.group(2)) else: m = re.search('', r, re.IGNORECASE) title1 = title2 = unescape(m.group(1)) if m else "Video" nfo["title"] = title1 if not title1 == title2: nfo["originaltitle"] = title2 if nfo["originaltitle"] and not nfo["title"]: nfo["title"] = nfo["originaltitle"] if 'episode_switcher_title' in r: set1 = title1.replace("\xe2\x80\x93", "-") if " - " in set1: set1 = set1.split(" - ")[0] set2 = title2.replace("\xe2\x80\x93", "-") if " - " in set2: set2 = set2.split(" - ")[0] if set1 <> set2: nfo["set"] = "%s ~ %s" % (set1, set2) m = re.search(r"
(S(\d+)E(\d+))<", r, re.IGNORECASE | re.DOTALL) if m: #nfo["title"] = nfo["title"] + " (%s)" % m.group(1) #nfo["originaltitle"] = nfo["originaltitle"] + " (%s)" % m.group(1) nfo["season"] = m.group(2) nfo["episode"] = m.group(2) nfo["thumb"] = tt('Gads<.+?content">([^<]+)<', r, "") nfo["runtime"] = tt('movie-informatio-title">Garums<.+?content">([^<]+)<', r, "") nfo["quality"] = tt('movie-informatio-title">Kvalitāte<.+?content">([^<]+)<', r, "") nfo["genre"]=tt('movie-informatio-title">Žanrs<.+?content">([^<]+)<', r, "") nfo["director"] = tt('movie-informatio-title">Režisor.<.+?content">([^<]+)<', r, "") nfo["actor"] = tt2('class="movie-informatio-content actors">([^<]+)<', r, "") nfo["language"] = tt2('movie-informatio-title">Valodas*<.+?content">([^<]+)<', r, "") nfo["subtitles"] = tt2('movie-informatio-title">Subtitri<.+?content">([^<]+)<', r, "") nfo["plot"] = tt('class="movie-informatio-content introduction">([^<]+)<', r, "") nfo["tagline"] = nfo["plot"] return nfo def get_stream_url2(self,data): video_id=data[data.find("/")+1:] if not self.is_logedin2(): if not self.login2(): return [] #data2 = self.get_noma_url(video_id) nfo = self.get_info2(data) title = util.nfo2title(nfo) desc = util.nfo2desc(nfo) img = nfo["thumb"] #xml = util.nfo2xml(nfo) url = "https://www.shortcut.lv/xmls/%s.xml"%video_id headers = self.headers2 headers["Cookie"] = self.session_id response = urllib2.urlopen(urllib2.Request(url, headers=headers)) r = response.read() servers = re.findall("(?s)([^<]+)", r) streams_xml = re.findall('(mp4:\w+(\w\w)_(\w\w).mp4)',r) if not streams_xml: raise Exception("No stream, buy movie?") resource_id = re.search("(?s)([^<]+)", r).group(1) token = re.search("(?s)([^<]+)", r).group(1) streams=[] captions = [] llist = ["fr","en","ru","lv"] for s in re.findall('([^<]+)', r, re.DOTALL): sub = {} sub["url"] = s[1] sub["lang"] = s[0] sub["name"] = "captions (vtt)" sub["type"] = "vtt" sub["order"] = llist.index(sub["lang"])*10 if sub["lang"] in llist else 0 captions.append(sub) captions = sorted(captions,key=lambda item: item["order"],reverse=True) for s in streams_xml: for server in servers: stream = util.item() server2 = self.load_balancer(server) url = "http://%s/mobile-vod/%s/playlist.m3u8?resource_id=%s&auth_token=%s"%(server2,s[0],resource_id,token) # TODO Engima2 gstreamer vajag lai padod playlist nevis chunklist # r3 = self._http_request(url) # sss = re.findall(r"#EXT-X-STREAM-INF:.*?BANDWIDTH=(\d+).*?\n(.+?)$", r3, re.IGNORECASE | re.MULTILINE) # if sss: # url2 = sss[0][1] # stream["headers"] = {"Referer":url} # if url2.startswith("http"): # url = url2 # else: # url = util.hls_base(url)+url2 stream["url"]=url stream["lang"]=s[1] stream["quality"]=s[2] stream["name"]= unescape(title) stream["desc"]= unescape(desc) stream["img"] = img stream["nfo"] = {"movie":nfo} stream["type"]="hls" #stream_type(url) stream["subs"] = [] for c in captions: c2= c.copy() #c2["url"] ="http://%s/mobile-vod/%s/%s?resource_id=%s&auth_token=%s"%(server2,s[0],c["url"],resource_id,token) c2["url"] ="http://%s/mobile-vod/%s/%s"%(server2,s[0],c["url"]) stream["subs"].append(c2) pass streams.append(stream) break # TODO ņem tikai pirmo serveri, varētu pārbaudit, kurš no tiem strādā, kurš ne return streams #data = {} #data["server"] = re.findall("(?s)([^<]+)", r)[1] #data["language"]=re.findall('(?s)', r) #data["language"]="lv" if "lv" in data["language"] else "ru" if "ru" in data["language"] else "en" #data["qs"]=re.findall('(?s)([^<]+)', r) #data["qs"]=dict(data["qs"]) #qs = data["qs"].keys() #data["quality"] = "hd" if "hd" in qs else "hq" if "hq" in qs else "mhq" if "mhq" in qs else "lq" #data["mp4"] = data["qs"][data["quality"]] #data["token"] = re.search("(?s)([^<]+)", r).group(1) #data["resource_id"]=re.search("(?s)([^<]+)", r).group(1) #data["server"]=self.load_balancer(data["server"]) #data["hls"] = "http://%s/mobile-vod/%s/playlist.m3u8?resource_id=%s&auth_token=%s"%(data["server"],data["mp4"],data["resource_id"],data["token"]) ##data["hls"]="http://%s/mobile-vod/mp4:%s/playlist.m3u8?resource_id=%s&auth_token=app_%s"%(data["server"],data["mp4"],data["resource_id"],data["token"]) ### wwww.shortcut.lv izsaukumi def login2(self,user="",password=""): """Login in to site, create session cookies""" if not user: user=self.options["user"] if not password: password = self.options["password"] url0 = "https://www.shortcut.lv" class NoRedirectHandler(urllib2.HTTPRedirectHandler): def http_error_302(self, req, fp, code, msg, headers): infourl = urllib.addinfourl(fp, headers, req.get_full_url()) infourl.status = code infourl.code = code return infourl http_error_300 = http_error_302 http_error_301 = http_error_302 http_error_303 = http_error_302 http_error_307 = http_error_302 # Dabūjam sesijas id un url_gif, kas redirektējas uz auth_url headers = headers2dict(""" User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; rv:46.0) Gecko/20100101 Firefox/46.0 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 Accept-Language: en-US,en;q=0.5 DNT: 1 Connection: keep-alive """) response = urllib2.urlopen(urllib2.Request(url0, headers=headers)) session_id = response.headers["set-cookie"].split(";")[0] html = response.read() url_gif = url0 + re.search('(/auth/\d+\.gif)', html).group(1) # Dabūtjam auth_url headers = headers2dict(""" User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; rv:46.0) Gecko/20100101 Firefox/46.0 Accept: image/png,image/*;q=0.8,*/*;q=0.5 Accept-Language: en-US,en;q=0.5 DNT: 1 Referer: https://www.shortcut.lv/ """) headers["Cookie"] = session_id urllib2.install_opener(urllib2.build_opener(NoRedirectHandler())) response = urllib2.urlopen(urllib2.Request(url_gif, headers=headers)) if response.code == 302: url_auth = response.headers["location"] else: self.error = u"auth.gif nenostrādāja" raise Exception(u"auth.gif nenostrādāja") #return False # Pierakstāmies iekš auth.lattelecom.lv headers = headers2dict(""" User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; rv:46.0) Gecko/20100101 Firefox/46.0 Accept: image/png,image/*;q=0.8,*/*;q=0.5 Accept-Language: en-US,en;q=0.5 DNT: 1 Referer: https://www.shortcut.lv/ """) response = urllib2.urlopen(urllib2.Request(url_auth, headers=headers)) if not response.code == 302: self.error = u"pierakstīšanās auth.lattelecom.lv nenostrādāja" return False #raise "pierakstīšanās auth.lattelecom.lv nenostrādāja" # Mēģinam ielogoties headers = headers2dict(""" User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; rv:46.0) Gecko/20100101 Firefox/46.0 Accept: text/javascript, application/javascript, application/ecmascript, application/x-ecmascript, */*; q=0.01 Accept-Language: en-US,en;q=0.5 DNT: 1 X-Requested-With: XMLHttpRequest Referer: https://www.shortcut.lv/ """) headers["Cookie"] = session_id #data = "login=yes&email=%s&passw=%s"%(user,password) url = "https://www.shortcut.lv/login.json?callback=jQuery111303344749731668816_1463817318435&username=%s&password=%s&captcha=&sid=&_="%(user,password) req = urllib2.Request(url, headers=headers) response = urllib2.urlopen(req) #with open("auth.htm","w") as f: f.write(response.read()) if not response.code == 200: #self.error = u"kļūda ielogojoties" raise Exception(u"kļūda ielogojoties") html = response.read() if not '"success":true' in html: err = re.search('"error":"(.+?)"',html).group(1) if re.search('"error":"(.+?)"',html) else "" raise Exception(u"Kļūda ielogojoties - %s"%err.decode("utf8")) self.session_id = session_id self.headers2["Cookie"] = "%s; "%(self.session_id) self.error = "" return True def check_logedin2(self): if not self.session_id: return False else: url = "https://www.shortcut.lv/profils" response = urllib2.urlopen(urllib2.Request(url, headers=self.headers2)) if response.code == 200: return True else: self.session_id = "" return False def is_logedin2(self): if self.session_id: return True else: return False def load_balancer(self,server,streams=[]): headers = headers2dict(""" Connection: keep-alive User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/50.0.2661.102 Safari/537.36 X-Requested-With: ShockwaveFlash/21.0.0.242 """) url = "http://%s/loadbalancer"%server response = urllib2.urlopen(urllib2.Request(url, headers=headers)) r = response.read() statuss = re.search("(\d+)",r).group(1) edge = re.search("([^<>]+)",r).group(1) return edge def test_hls(self,url): headers = headers2dict(""" Connection: keep-alive User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/50.0.2661.102 Safari/537.36 """) try: response = urllib2.urlopen(urllib2.Request(url, headers=headers)) except Exception as ex: print "hls failed: %s %s"%(ex.getcode(),url) return False if response.code == 200: html = response.read() url0 = re.search("(http://[^/]+/)",url).group(1) chunklist = re.search("(chunklist.+)",html).group(1).strip() url2 = url.split('/')[:-1] url2 ="/".join(url2)+"/"+chunklist try: response2 = urllib2.urlopen(urllib2.Request(url2, headers=headers)) except Exception as ex: print "hls chunk failed: %s %s"%(ex.getcode(),url2) return False if response2.code == 200: return True else: return False else: return False if __name__ == "__main__": sys.path.insert(0, os.path.dirname(os.path.dirname(__file__))) import run source = Source() data= sys.argv[1] if len(sys.argv)>1 else source.name+"::home" run.run(source, data) sys.exit() c.get_info2(sys.argv[1]) if len(sys.argv)>1 and not "ltc::" in sys.argv[1]: vid = vid2 = sys.argv[1] password = sys.argv[2] print "login - %s"%c.login("ivars777",password) #vid = "1069" #vid = "1462566072086" #channelid="101" #vid = "1350462656767" #data = c.get_stream_url(vid,"vod") #call([r"c:\Program Files\VideoLAN\VLC\vlc.exe",data["stream"]]) #pass print "login2 - %s"%c.login2("ivars777",password) #vid2 = "animation/ultimate_avengers_ii" #vid2 = "animation/ice_age" #vid2 = "tiesraide/ltv1" #vid2 = "arhivs/1456521417815" streams = c.get_stream_url2(vid2) stream = streams[-1] print #for s in data: #call([r"c:\Program Files\VideoLAN\VLC\vlc.exe",stream["url"]]) cmd = ["ffplay.exe", "-headers","Referer:%s"%(quote(stream["headers"]["Referer"])), "-headers","Connection:Keep-Alive", stream["url"]] print " ".join(cmd) call(cmd) pass else: if len(sys.argv)>1: data= sys.argv[1] else: data = "ltc::home" content = c.get_content(data) for item in content: print item #cat = api.get_categories(country) #chan = api.get_channels("lv") #prog = api.get_programs(channel=6400) #prog = api.get_programs(category=55) #seas = api.get_seasons(program=6453) #str = api.get_streams(660243) #res = api.get_videos(802) #formats = api.getAllFormats() #det = api.detailed("1516") #vid = api.getVideos("13170") pass