#!/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 from xml.sax.saxutils import unescape,escape from urllib import quote, unquote import datetime import HTMLParser import json import ConfigParser import datetime 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(object): def __init__(self): self.name = "ltc" self.mobtv_cache = "" self.session_id = "" cur_directory = os.path.dirname(os.path.abspath(__file__)) config_file = os.path.join(cur_directory,"ltc.cfg") config = ConfigParser.ConfigParser() if os.path.exists(config_file): config.read(config_file) self.user = config.get("ltc","user") self.password = config.get("ltc","password") else: self.user = "" self.password = "" #self.login() self.headers = headers2dict(""" Host: m.lattelecom.tv User-Agent: Mozilla/5.0 (iPhone; CPU iPhone OS 8_0_2 like Mac OS X) AppleWebKit/600.1.4 (KHTML, like Gecko) Version/8.0 Mobile Safari/600.1.4 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 Accept-Language: en-US,en;q=0.5 Connection: keep-alive """) self.headers2 = headers2dict(""" Host: www.lattelecom.tv Accept: application/json, text/javascript, */*; q=0.01 X-Requested-With: XMLHttpRequest User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.112 Safari/537.36 Referer: https://www.lattelecom.tv/videonoma/360tv """) def get_content(self, data): print "[ltc] get_content:", data if "::" in data: data = data.split("::")[1] path = data.split("?")[0] clist = path.split("/")[0] params = data[data.find("?"):] if "?" in data else "" qs = dict(map(lambda x:x.split("="),re.findall("\w+=\w+",params))) #lang = qs["lang"] if "lang" in qs else self.country content=[] content.append(("..return", "back","","Return back")) if clist=="home": content.extend([ ("Live streams", "ltc::tiesraide","","TV live streams"), ("Archive", "ltc::arhivs","","TV live archive"), ("Video", "ltc::videonoma","","Video on demand"), ]) return content ### Tiešraides kanānālu saraksts elif data=="tiesraide": if not self.check_logedin(): self.login() # citādi nerāda TV3, LNT, TV6 r= self.call(data) for item in re.findall(r'(?i)/(tiesraide/[^"]*?)">
([^<]+)([^<]+)', r): ch = item[0] title = item[1] data2 = item[0] img = "https://m.lattelecom.tv/"+item[2].replace("105x105","150x150") desc = "%s\n%s"%(item[3],item[4]) content.append((title,self.name+"::"+data2,img,desc)) return content ### Kanāla tiesraide elif clist == "tiesraide" and "/" in data: ch = data.split("/")[1] if not self.check_logedin(): if not self.login(): 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 r = self.call("tiesraide") m = re.search('/%s">
(.+?)(.+?)'%data, r, re.IGNORECASE) if m: title = "%s - %s (%s)"%(m.group(1),m.group(2),m.group(3)) else: title = ch.upper() desc = title data2 = self.get_tv_url(ch) if not data2: content=("No stream found for '%s'"%data,"","","No stream found") return content content = (title,data2,"",desc) return content ### Arhīva kanānālu saraksts elif data=="arhivs": r= self.call(data) for item in re.findall(r'(?i)/(arhivs/[^"]+)".+?
([^<]+)', 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: 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 ### Arhīva video elif clist=="arhivs" and len(data.split("/"))==4: ch = data.split("/")[1] video_id=data.split("/")[-1] if not self.check_logedin(): if not self.login(): 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_arhivs_url(video_id) if not data2: content=("No stream found for '%s'"%data,"","","No stream found") return content r = self.call(data) m = re.search('
([^<]+)
([^<]+)
([^<]+)([^<]+)([^<]+)<', r, re.IGNORECASE) if m: title = "%s (%s %s %s %s)"%(m.group(1),m.group(2),m.group(3),m.group(4),m.group(5)) else: title = "" desc = title content = (title,data2,"",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"), ("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"), ("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"), ("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"), ("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 - animācijas", "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 - 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 - latviski", '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,self.headers2) if not r: return content js = json.loads(r,"utf8") if not r: return content for item in js["movies"]: title = item["title"].encode("utf8") data2 = item["url"][1:].encode("utf8") if data2[-1]=="/": data2=data2[:-1] if "/raidijumi/" in data2: data2 += "?series" 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": url = "https://www.lattelecom.tv/"+path r = self._http_request(url,self.headers2) if not r: return content m = re.search('
([^<]+?)
', r, re.DOTALL | re.IGNORECASE) if m: raidijums = m.group(1) + " - " else: raidijums = "" for item in re.findall('(?si).*?([^<]+)([^<]+)', 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.check_logedin(): if not self.login(): 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.call(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 is_video(self,data): if "::" in data: data = data.split("::")[1] cmd = data.split("/") if cmd[0] in ("tiesraide") and "/" in data: 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 call(self, data,headers=None): if not headers: headers = self.headers #if not lang: lang = self.country url = API_URL + data content = self._http_request(url,headers) return content def _http_request(self, url,headers=None): if not headers: headers = self.headers try: r = urllib2.Request(url, headers=headers) u = urllib2.urlopen(r) content = u.read() u.close() return content except Exception as ex: return None def login(self,user="",password=""): """Login in to site, create session cookies""" self.mobtv_cache = "" if not user: user=self.user if not password: password = self.password url0 = "https://m.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: m.lattelecom.tv User-Agent: Mozilla/5.0 (iPhone; CPU iPhone OS 8_0_2 like Mac OS X) AppleWebKit/600.1.4 (KHTML, like Gecko) Version/8.0 Mobile Safari/600.1.4 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+"/authorization", 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: m.lattelecom.tv User-Agent: Mozilla/5.0 (iPhone; CPU iPhone OS 8_0_2 like Mac OS X) AppleWebKit/600.1.4 (KHTML, like Gecko) Version/8.0 Mobile Safari/600.1.4 Accept: image/png,image/*;q=0.8,*/*;q=0.5 Accept-Language: en-US,en;q=0.5 Accept-Encoding: gzip, deflate DNT: 1 Referer: https://m.lattelecom.tv/authorization Connection: keep-alive """) 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 (iPhone; U; CPU iPhone OS 4_0 like Mac OS X; en-us) AppleWebKit/532.9 (KHTML, like Gecko) Version/4.0.5 Mobile/8A293 Safari/6531.22.7 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 Accept-Language: en-US,en;q=0.5 Accept-Encoding: gzip, deflate DNT: 1 Referer: http://m.lattelecom.tv/authorization Connection: keep-alive """) 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" # nolasām auth_gif ## headers = headers2dict(""" ## Host: m.lattelecom.tv ## User-Agent: Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_0 like Mac OS X; en-us) AppleWebKit/532.9 (KHTML, like Gecko) Version/4.0.5 Mobile/8A293 Safari/6531.22.7 ## Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 ## Accept-Language: en-US,en;q=0.5 ## Accept-Encoding: gzip, deflate ## DNT: 1 ## Referer: http://m.lattelecom.tv/authorization ## """) ## headers["Cookie"] = session_id ## response = urllib2.urlopen(urllib2.Request(url_gif, headers=headers)) ## if not response.code == 200: ## raise u"kļūda lasot auth_gif" # Mēģinam ielogoties headers = headers2dict(""" Host: m.lattelecom.tv User-Agent: Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_0 like Mac OS X; en-us) AppleWebKit/532.9 (KHTML, like Gecko) Version/4.0.5 Mobile/8A293 Safari/6531.22.7 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 Accept-Language: en-US,en;q=0.5 Accept-Encoding: deflate DNT: 1 Referer: http://m.lattelecom.tv/authorization Connection: keep-alive Content-Type: application/x-www-form-urlencoded""") headers["Cookie"] = session_id data = "login=yes&email=%s&passw=%s"%(user,password) req = urllib2.Request(url0+"/authorization", data, headers) response = urllib2.urlopen(req) #with open("auth.htm","w") as f: f.write(response.read()) if not response.code == 302: self.error = u"kļūda ielogojoties" #raise u"kļūda ielogojoties" return False mobtv = response.headers["set-cookie"].split(";")[0] if not mobtv.split("=")[0]=="mobtv_cache": #raise "nav mobtv cookie!" self.error = "nav mobtv cookie!" return False # atveram /account ## headers = headers2dict(""" ## Host: m.lattelecom.tv ## User-Agent: Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_0 like Mac OS X; en-us) AppleWebKit/532.9 (KHTML, like Gecko) Version/4.0.5 Mobile/8A293 Safari/6531.22.7 ## Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 ## Accept-Language: en-US,en;q=0.5 ## Accept-Encoding: deflate ## DNT: 1 ## Referer: http://m.lattelecom.tv/authorization ## Connection: keep-alive """) ## headers["Cookie"] = "%s; %s"%(session_id,mobtv) ## response = urllib2.urlopen(urllib2.Request(url0+"/account", headers=headers)) ## if not response.code == 302: ## raise u"kļūda atverot /account" # atveram /profils ## headers = headers2dict(""" ## Host: m.lattelecom.tv ## User-Agent: Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_0 like Mac OS X; en-us) AppleWebKit/532.9 (KHTML, like Gecko) Version/4.0.5 Mobile/8A293 Safari/6531.22.7 ## Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 ## Accept-Language: en-US,en;q=0.5 ## Accept-Encoding: deflate ## DNT: 1 ## Referer: http://m.lattelecom.tv/authorization ## Connection: keep-alive ## """) ## headers["Cookie"] = "%s; %s"%(session_id,mobtv) ## response = urllib2.urlopen(urllib2.Request(url0+"/profils", headers=headers)) ## if not response.code == 200: ## raise u"kļūda atverot /profils" ## with open("profils.htm","w") as f: f.write(response.read()) self.mobtv_cache = mobtv self.session_id = session_id self.headers["Cookie"] = "%s; %s; MobBitr=1; "%(self.session_id,self.mobtv_cache) self.error = "" return True def check_logedin(self): if not self.mobtv_cache: return False else: #return True url = "https://m.lattelecom.tv/profils" headers = self.headers headers["Cookie"] = "%s; %s; MobBitr=1; "%(self.session_id,self.mobtv_cache) response = urllib2.urlopen(urllib2.Request(url, headers=self.headers)) if response.code == 200: return True else: self.mobtv_cache = "" return False def is_logedin(self): if self.mobtv_cache: return True else: return False def get_tv_channels(self,): """Get tv channels list""" url = "https://m.lattelecom.tv/tiesraide" response = urllib2.urlopen(urllib2.Request(url, headers=self.headers)) html = response.read() channels = re.findall(r'(?si)data-url="/tiesraide/(.*?)">
([^<]+)", 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["hls]"] = "http://%s/mobile-vod/%s/playlist.m3u8?resource_id=%s&auth_token=%s"%(data["server"],data["mp4"],data["resource_id"],data["token"]) return data if __name__ == "__main__": c = Source() c.login("ivars777","kaskade7") data = c.get_video_data("hd/hd_anonymous") #print data print data["hls"] if len(sys.argv)>1: data= sys.argv[1] else: data = "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