#!/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 datetime import HTMLParser import json import datetime from SourceBase import SourceBase, stream_type import util from collections import OrderedDict import ssl if "_create_unverified_context" in dir(ssl): ssl._create_default_https_context = ssl._create_unverified_context API_URL = 'https://m.lattelecom.tv/' user_agent = "Mozilla/5.0 (iPhone; U; CPU iPhone OS 5_1_1 like Mac OS X; da-dk) AppleWebKit/534.46.0 (KHTML, like Gecko) CriOS/19.0.1084.60 Mobile/9B206 Safari/7534.48.3" 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 = "ltc" self.title = "Shortcut.lv (lattelecom.tv)" self.img = "picons/shortcut.png" self.desc = "Shortcut.lv (lattelecom.tv) satura skatīšanās" self.token = "" # manstv.lattelecom.tv self.session_id = "" # www.lattelecom.tv self.api_url = "https://manstv.lattelecom.tv/api/v1.4/get/" self.api_url2 = "https://www.lattelecom.tv/" self.headers = headers2dict(""" User-Agent: Dalvik/1.6.0 (Linux; U; Android 4.4.2; SM-G900FD Build/KOT49H) Host: manstv.lattelecom.tv Connection: Keep-Alive """) self.headers2 = headers2dict(""" Host: www.lattelecom.tv Connection: keep-alive Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8 User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/50.0.2661.102 Safari/537.36 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.epg=[] self.epg_id={} self.epg_id2={} self.epg_date={} self.epg_ch={} self.epgdates = [] 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","","Return back")) if clist=="home": content.extend([ ("Search TV", "ltc::search/{0}","","Search in TV archive"), ("Search Video", "ltc::meklet?q={0}","","Search in video"), ("Live streams", "ltc::tiesraide","","TV live streams"), ("Archive", "ltc::arhivs","","TV live archive"), ("Video", "ltc::videonoma","","Video on demand"), ]) return content ### Meklēt TV (1.4 API) elif clist == "search": #TODO vod/search/{q} #r = self.call("vod/"+data) return content ### Meklēsana video (www )### elif clist == "meklet": #TODO vod/search/{q} r = self.call2(data) for res in re.findall('.*?)', r, re.DOTALL): r2 = res[1] if "movie" in res[0]: #if not "permalink" in r2: #continue m = re.search('([^<]+)', r2, re.DOTALL) if not m: continue title = m.group(2) data2 = "videonoma" + m.group(1) #data2 = "arhivs" + m.group(1) m = re.search('src="([^"]+)"', r2, re.DOTALL) img = "https://www.lattelecom.tv/"+m.group(1) if m else "" m = re.search('
([^<]+)<', r2, re.DOTALL) desc = m.group(1) if m else "" m = re.search('class="genre".+?>([^<]+)<', r2, re.DOTALL) if m: desc = m.group(1)+"\n"+desc else: m = re.search('([^<]+)', r2, re.DOTALL) if not m: continue title = m.group(2) data2 = m.group(1) dd = data2.split("/") if dd[0]=="arhivs": ch_name = dd[1] ch = self.get_channel_by_name(ch_name) data2 = "archive/get-stream/%s?channelid=%s"%(dd[3],ch["id"]) if ch else "" #ltc::archive/get-stream/1464120671889?channelid=101 else: continue m = re.search(r"url\((.+?)\)", r2, re.DOTALL) img = "https://www.lattelecom.tv"+m.group(1) if m else "" m = re.search('([^<]+)', r2, re.DOTALL) sub = m.group(1) if m else "" title = title + " " + sub desc = title content.append((title,self.name+"::"+data2,img,desc)) return content ### Tiešraides kanānālu saraksts ### elif data=="tiesraide": r = self.call2(data) jsdata = re.search("site.program = ([^;]+);",r).group(1) js=json.loads(jsdata) for item in self.get_channels(): if item["live"]=='0':continue title = item["name"] data2 = "content/live-streams/%s?include=quality"%item["id"] if item['xprs_id'] in js: epg = js[item['xprs_id']] desc = "%s - %s (%s-%s)"%(title,epg[0]["t"],epg[0]["hs"],epg[0]["he"]) img = "https://www.lattelecom.tv" + epg[0]["p"] else: img = "https://manstv.lattelecom.tv/"+ item['broadcast_default_picture'] desc = title content.append((title,self.name+"::"+data2,img,desc)) return content ### TV arhīva sākums ### elif data=="archive" or data=="arhivs": #self.get_epg() content.extend([ ("Archive - categories", "ltc::archive/categories","","TV live archive by categories"), ("Archive - channels", "ltc::archive/channels","","TV live archive by channels"), #("Archive - dates", "ltc::archive/dates","","TV live archive by dates"), ]) 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] %s - %s"%(item["date"],item["time_start2"].strftime("%H:%M"),item["time_stop2"].strftime("%H:%M"),ch_name,item["title"]) #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\n%s\n%s"%(ch_name,item["title"],item["time_start"],item["time_stop"], 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,"","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 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"]) #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\n%s\n%s"%(ch_name,item["title"],item["time_start"],item["time_stop"], 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 = 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ā 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.lattelecom.tv/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.lattelecom.tv/media/features/2013-12-17/aa3b_videonoma_dropdown_filmas.png","Filmas pēc nosaukuma"), ("Filmas - latviski", 'ltc::videonoma?page=0&genre=all_movies&sorts=title&cnt=40&clear=true&filter={"valoda":["lv"]}',"https://www.lattelecom.tv/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.lattelecom.tv/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.lattelecom.tv/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.lattelecom.tv/images/redesign/videonoma_dropdown_berniem.png","Bērnu video pēc nosaukuma"), ("Filmas bērniem - latviski", 'ltc::videonoma?page=0&genre=3&sorts=title&cnt=40&clear=true&filter={"valoda":[\"lv\"]}',"https://www.lattelecom.tv/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.lattelecom.tv/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.lattelecom.tv/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.lattelecom.tv/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.lattelecom.tv/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.lattelecom.tv/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.lattelecom.tv/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.lattelecom.tv/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.lattelecom.tv/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.lattelecom.tv/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.lattelecom.tv/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.lattelecom.tv/images/redesign/videonoma_dropdown_koncerti.png","Koncerti pēc pēc nosaukuma"), ]) return content ### Videonomas saraksti elif path == "videonoma": url = "https://www.lattelecom.tv/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.lattelecom.tv"+item["image"].encode("utf8") desc = "%s\n%s"%(title,item["genre"].encode("utf8")) 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,"","Go to next page")) return content ### Sērijas elif clist=="videonoma" and (params=="?series" or "season_nr" in qs): url = "https://www.lattelecom.tv/"+path r = self._http_request(url,headers=self.headers2) if not r: return content m = re.search('
([^<]+?)
', r, re.DOTALL | re.IGNORECASE) raidijums = m.group(1) + " - " if m else "" img0 = re.search('', r).group(1) if re.search('', r) else "" m = re.search('
    [^<]+)+
', r) if m and not "season_nr" in qs: # ir sezonas for s,it in enumerate(re.findall('
  • ([^<]+)
  • ', m.group())): title = "%s%s" % (raidijums, it) se = re.search("(\d+)",it).group(1) data2 = path+"?season_nr=%s"%(se) img = img0 desc = title content.append((title, self.name + "::" + data2, img, desc)) return content m = re.search('data-bid="([^"]+)',r) if m: if not "season_nr" in qs: qs["season_nr"]="0" url = "https://www.lattelecom.tv/episode-loader.json?bcast_ids=%s&season_nr=%s"%(m.group(1),qs["season_nr"]) r = self._http_request(url,headers=self.headers2) i1 = r.find('{"total":') i2 = r.find('}
    .*?([^<]+)([^<]+)', r): title = "%s%s (%s)"%(raidijums,item[2],item[3]) data2 = item[0][1:] img = "https://www.lattelecom.tv"+item[1] desc = title content.append((title,self.name+"::"+data2,img,desc)) return content ### Videonomas video elif clist=="videonoma" and len(data.split("/"))>1: 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 else: return content def get_streams(self, data): print "[ltc] get_streams:", data if "::" in data: data = data.split("::")[1] if not self.is_video(data): return [] ### 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 [] r = self.call(data) 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) offset = "%2B03%3A00" # TODO - vajag aktuālo laika nobidi no GMS data2 = "tv/epg-live/%s/?offset=%s"%(ch["xprs_id"],offset) r2 = self.call(data2) if r2 and r2["items"]: title = r2["items"][0]["title"].encode("utf8") t1 = datetime.datetime.fromtimestamp(int(r2["items"][0]["unix_start"])).strftime('%H:%M') t2 = datetime.datetime.fromtimestamp(int(r2["items"][0]["unix_stop"])).strftime('%H:%M') title = "%s (%s-%s)"%(title,t1,t2) desc = r2["items"][0]["description"] else: title = ch["name"] desc = title 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 = epg["description"] else: title = desc = data streams = [] for s in r["data"]: stream = util.item() stream["url"]=(s["attributes"]["stream-url"]+token.encode("utf8")).encode("utf8") stream["name"]=title stream["desc"]=desc 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): if "::" in data: data = data.split("::")[1] cmd = data.split("/") if "get-stream" in data: return True elif cmd[0] in ("content") and cmd[1] in ("live-streams","record-streams","vod-streams"): 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("tv/channels") self.ch=[] for i,item in enumerate(r["items"]): self.ch.append(item) self.ch_id[item["id"]]=i self.ch_id2[item["xprs_id"]]=i self.ch_name[item["name"]]=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, re.IGNORECASE) nfo = {} tt = lambda p,r,d: re.search(p,r).group(1) if re.search(p,r) else d tt2 = lambda p,r,d: (re.sub("<.+?>","",re.search(p,r).group(1))).split(",") if re.search(p,r) else d r2 = r[r.find('
    '):] nfo["title"] = tt('
    ([^<]+)
    ', r2,"") nfo["originaltitle"] = tt('
    ([^<]+)
    ', r2,"") if nfo["originaltitle"] and not nfo["title"]: nfo["title"] = nfo["originaltitle"] #nfo["originaltitle"] = "" if "raidijumi" in data: nfo["set"] = nfo["title"] m = re.search('class="movie_informatio">(.+?)
    (.+?)
    ', r) ep2,ep1 = m.groups() #nfo["title"] s_nr = tt('(\d+)',r,"") for it in re.findall(r'(\d+).+?(.+?)', r): if it[1] == ep1: ep_nr = it[0] break else: ep_nr="" if s_nr: nfo["season"] = s_nr if ep_nr: nfo["eposode"] = ep_nr se = "S%02i"%int(s_nr) if s_nr else "" se += "E%02i"%int(ep_nr) if ep_nr else "" nfo["title"] += " - %s"%ep1 if ep1 else "" nfo["originaltitle"] += " - %s"%ep2 if ep2 else "" nfo["title"] += "(%s)"%se if se else "" nfo["originaltitle"] += "(%s)"%se if se else "" nfo["thumb"] = tt('(.+?)<', r2,"") nfo["tagline"] = nfo["plot"] title = util.nfo2title(nfo) desc = util.nfo2desc(nfo) img = nfo["thumb"] #xml = util.nfo2xml(nfo) url = "https://www.lattelecom.tv/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) 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"]=title stream["desc"]=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.lattelecom.tv 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.lattelecom.tv" 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(""" Host: www.lattelecom.tv 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(""" Host: www.lattelecom.tv 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.lattelecom.tv/ """) 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 u"auth.gif nenostrādāja" return False # Pierakstāmies iekš auth.lattelecom.lv headers = headers2dict(""" Host: auth.lattelecom.lv 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.lattelecom.tv/ """) 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(""" Host: www.lattelecom.tv 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.lattelecom.tv/ """) headers["Cookie"] = session_id #data = "login=yes&email=%s&passw=%s"%(user,password) url = "https://www.lattelecom.tv/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.lattelecom.tv/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__": c = Source() from subprocess import call 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