123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466 |
- #!/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.token = ""
- self.api_url = "https://manstv.lattelecom.tv/api/v1.3/get/"
- 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()
-
- 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::tv/channels","","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=="tv/channels":
- 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/[^"]*?)"><div title="([^"]*?)" class="channel-placeholder" style="width: 131px; height: 131px; background-image:url\(/(.+?\.png)\).+?rinfo">([^<]+)</span><span class="info_time">([^<]+)</span>', 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"><div title="([^"]*?)".+?rinfo">(.+?)</span><span class="info_time">(.+?)</span>'%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/[^"]+)".+?<div title="([^"]*?)".+?background-image:url\(/(.+?\.png)\)', r):
- ch = item[0]
- title = item[1]
- data2 = item[0]
- img = "https://m.lattelecom.tv/"+item[2].replace("105x105","150x150")
- desc = "%s 7 dienu arhīvs"%title
- content.append((title,self.name+"::"+data2,img,desc))
- return content
-
- ### Arhīva datumi
- elif clist=="arhivs" and len(data.split("/"))==2:
- ch = data.split("/")[1]
- r= self.call(data)
- m = re.search('class="spac no_select">([^<]+)</span>', 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">([^<]+)</span>', 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"><div class="archive_programm "><div class="chanel_time"><span>([^<]+)</span></div><div class="archive_programm_one"><span>([^<]+)', 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('<div class="name">([^<]+)</div><div class="channell">([^<]+)</div><div class="bcastinfo"><span>([^<]+)</span><span>([^<]+)</span><span>([^<]+)<', 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('<div class="movie_details"><div class="movie_titles"><div class="en">([^<]+?)</div>', r, re.DOTALL | re.IGNORECASE)
- if m:
- raidijums = m.group(1) + " - "
- else:
- raidijums = ""
-
- for item in re.findall('(?si)<a class="elementxxx forward-link[^"]*" href="([^"]+)">.*?<img src="([^"]+)" class="img"><span class="titlez">([^<]+)</span><span class="epizode_number">([^<]+)</span>', 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('<span class="movie">([^<]+)<', 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,params = None, headers=None):
- if not headers: headers = self.headers
- #if not lang: lang = self.country
- url = self.api_url + data
- content = self._http_request(url,params, headers)
- if content:
- try:
- result = json.loads(content)
- if "status" in result and result["status"]=="ok":
- return result
- else:
- return None
- except Exception, ex:
- return None
- else:
- return result
-
- def _http_request(self, url,params = None, headers=None):
- if not headers: headers = self.headers
- try:
- r = urllib2.Request(url, data=params, 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, get token"""
- if not user: user=self.user
- if not password: password = self.password
-
- # Dabūjam tokenu
- url = "https://manstv.lattelecom.tv/api/v1.3/post/user/login"
- params = "uid=7f777e938d35e017&password=%s&username=%s&"%(password,user)
- headers = headers2dict("""
- Content-Type: application/x-www-form-urlencoded; charset=UTF-8
- User-Agent: Dalvik/1.6.0 (Linux; U; Android 4.4.2; SM-G900FD Build/KOT49H)
- Host: manstv.lattelecom.tv
- """ )
- try:
- r = urllib2.Request(url, data=params, headers=headers)
- u = urllib2.urlopen(r)
- content = u.read()
- u.close()
- except Exception as ex:
- return None
- #r = self.call(data, params)
- if r and "token" in content:
- self.token=re.search('"token":"(.+?)"', content).group(1)
- return True
- else:
- return False
-
- def refresh_token(self):
- data = "user/refresh-token//%s"%self.token
- r = self.call(data)
- if 'token' in r:
- self.token = r["token"]
- return True
- else:
- self.token = ""
- return False
-
- def check_logedin(self):
- if not self.token:
- return False
- else:
- if self.refresh_token():
- return True
- else:
- return False
-
- def is_logedin(self):
- if self.token:
- 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/(.*?)"><div title="(.*?)" class="channel-placeholder" style="width: 131px; height: 131px; background-image:url\(/media/imse/105x105s/channels/(.*?)\)', html)
- for i in range(len(channels)):
- channels[i]=[channels[i][0],channels[i][1],"https://m.lattelecom.tv/media/imse/100x100s/channels/"+channels[i][2]]
- return channels
-
- #----------------------------------------------------------------------
- def get_tv_url(self,video_id):
- """Get m3u8 url for given live tv channel"""
- url = "https://m.lattelecom.tv/tiesraide/%s"%video_id
- data = self.get_video_data("tiesraide/%s"%video_id)
- headers = self.headers
- headers["Cookie"] = "%s; %s; _hjIncludedInSample=0; MobBitr=1; MobRentBitr=%s; MobRentLang=%s;"%(self.session_id,self.mobtv_cache,data["quality"],data["language"])
- response = urllib2.urlopen(urllib2.Request(url, headers=headers))
- html = response.read()
- m3u8 = re.search('x-mpegURL" src="(.*?)"', html).group(1) if "x-mpegURL" in html else ""
- return unescape(m3u8)
-
- #----------------------------------------------------------------------
- def get_noma_url(self,video_id,quality="hq",language="lv"):
- """Get m3u8 url for given rental video"""
- video_id1,video_id2=video_id.split("/")
- data = self.get_video_data(video_id)
- url = "https://m.lattelecom.tv/free_origin?show_origin=1&type=4&video_url=%s&bitrate=%s&lng=%s"%(video_id2,data["quality"],data["language"])
- headers = self.headers
- headers["Cookie"] = "%s; %s; MobRentBitr=%s; MobBitr=1; MobRentLang=%s"%(self.session_id,self.mobtv_cache,quality,language)
- response = urllib2.urlopen(urllib2.Request(url, headers=headers))
- m3u8 = response.read()
- return unescape(m3u8)
-
- #----------------------------------------------------------------------
- def get_arhivs_url(self,video_id):
- """Get m3u8 url for given archive video"""
- #data = self.get_video_data("arhivs/%s"%video_id)
- url = "https://m.lattelecom.tv/free_origin?show_origin=1&type=arhivs&event_id=%s&bitrate=mhq"%(video_id) #,data["quality"])
- headers = self.headers
- headers["Cookie"] = "%s; %s; MobBitr=1; "%(self.session_id,self.mobtv_cache)
- response = urllib2.urlopen(urllib2.Request(url, headers=headers))
- m3u8 = response.read()
- return unescape(m3u8)
-
- def get_video_data(self,video_id):
- url = "https://www.lattelecom.tv/xmls/%s.xml"%video_id
- headers = self.headers2
- headers["Cookie"] = self.session_id
- #headers["User-Agent"] = "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.112 Safari/537.36"
- response = urllib2.urlopen(urllib2.Request(url, headers=headers))
- r = response.read()
- data = {}
- data["server"] = re.findall("(?s)<origin>([^<]+)</origin>", r)[1]
- data["language"]=re.findall('(?s)<language code="([^"]+)">', r)
- data["language"]="lv" if "lv" in data["language"] else "ru" if "ru" in data["language"] else "en"
- data["qs"]=re.findall('(?s)<stream quality="([^"]+)">([^<]+)</stream>', 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)<auth_token>([^<]+)</auth_token>", r).group(1)
- data["resource_id"]=re.search("(?s)<resource_id>([^<]+)</resource_id>", 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"])
- return data
-
- 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("<status>(\d+)</status>",r).group(1)
- edge = re.search("<edge>([^<>]+)</edge>",r).group(1)
- return edge
-
- if __name__ == "__main__":
- c = Source()
-
- print c.login("ivars777","kaskade7")
- print c.refresh_token(c.token)
- vid = "animation/ultimate_avengers_ii"
- data = c.get_video_data(vid)
- 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
|