#!/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
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
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([
("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"
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,headers=self.headers2)
if not r:
return content
m = re.search('([^<]+?)
', r, re.DOTALL | re.IGNORECASE)
raidijums = m.group(1) + " - " if m else ""
m = re.search('data-bid="([^"]+)',r)
if m:
url = "https://www.lattelecom.tv/episode-loader.json?bcast_ids=%s"%(m.group(1))
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)
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"]
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