Enigma2 plugin to to play various online streams (mostly Latvian).

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096
  1. #!/usr/bin/env python
  2. # coding=utf8
  3. #
  4. # This file is part of PlayStream - enigma2 plugin to play video streams from various sources
  5. # Copyright (c) 2016 ivars777 (ivars777@gmail.com)
  6. # Distributed under the GNU GPL v3. For full terms see http://www.gnu.org/licenses/gpl-3.0.en.html
  7. #
  8. import sys, os, os.path, re, sys
  9. import urllib,urllib2,urlparse
  10. from xml.sax.saxutils import unescape,escape
  11. from urllib import quote, unquote
  12. import datetime
  13. import HTMLParser
  14. import json
  15. import datetime
  16. from SourceBase import SourceBase, stream_type
  17. import util
  18. from collections import OrderedDict
  19. import ssl
  20. if "_create_unverified_context" in dir(ssl):
  21. ssl._create_default_https_context = ssl._create_unverified_context
  22. API_URL = 'https://m.lattelecom.tv/'
  23. 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"
  24. headers2dict = lambda h: dict([l.strip().split(": ") for l in h.strip().splitlines()])
  25. h = HTMLParser.HTMLParser()
  26. class Source(SourceBase):
  27. def __init__(self,cfg_path=None):
  28. self.name = "ltc"
  29. self.title = "Shortcut.lv (lattelecom.tv)"
  30. self.img = "picons/shortcut.png"
  31. self.desc = "Shortcut.lv (lattelecom.tv) satura skatīšanās"
  32. self.token = "" # manstv.lattelecom.tv
  33. self.session_id = "" # www.lattelecom.tv
  34. self.api_url = "https://manstv.lattelecom.tv/api/v1.4/get/"
  35. self.api_url2 = "https://www.lattelecom.tv/"
  36. self.headers = headers2dict("""
  37. User-Agent: Dalvik/1.6.0 (Linux; U; Android 4.4.2; SM-G900FD Build/KOT49H)
  38. Host: manstv.lattelecom.tv
  39. Connection: Keep-Alive
  40. """)
  41. self.headers2 = headers2dict("""
  42. Host: www.lattelecom.tv
  43. Connection: keep-alive
  44. Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
  45. User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/50.0.2661.102 Safari/537.36
  46. Accept-Language: en-US,en;q=0.8
  47. """)
  48. self.channels = None
  49. ### specific service info ###
  50. self.ch=[]
  51. self.ch2=[]
  52. self.ch_id={}
  53. self.ch_id2={}
  54. self.ch_name={}
  55. self.epg=[]
  56. self.epg_id={}
  57. self.epg_id2={}
  58. self.epg_date={}
  59. self.epg_ch={}
  60. self.epgdates = []
  61. self.today = datetime.date.today()
  62. self.today2 = self.today.strftime("%d.%m.%Y")
  63. cur_directory = os.path.dirname(os.path.abspath(__file__))
  64. if not cfg_path: cfg_path = cur_directory
  65. self.config_file = os.path.join(cfg_path,self.name+".cfg")
  66. self.options = OrderedDict([("user","lietotajs"),("password","parole")])
  67. self.options_read()
  68. def get_content(self, data):
  69. print "[ltc] get_content:", data
  70. source, data, path, plist, clist, params, qs = self.parse_data(data)
  71. content=[]
  72. content.append(("..return", "back","","Return back"))
  73. if clist=="home":
  74. content.extend([
  75. ("Search TV", "ltc::search/{0}","","Search in TV archive"),
  76. ("Search Video", "ltc::meklet?q={0}","","Search in video"),
  77. ("Live streams", "ltc::tiesraide","","TV live streams"),
  78. ("Archive", "ltc::arhivs","","TV live archive"),
  79. ("Video", "ltc::videonoma","","Video on demand"),
  80. ])
  81. return content
  82. ### Meklēt TV (1.4 API)
  83. elif clist == "search": #TODO vod/search/{q}
  84. #r = self.call("vod/"+data)
  85. return content
  86. ### Meklēsana video (www )###
  87. elif clist == "meklet": #TODO vod/search/{q}
  88. r = self.call2(data)
  89. for res in re.findall('<div class="(program follow|movie forward)-link">(.+?</div></div>.*?)</div>', r, re.DOTALL):
  90. r2 = res[1]
  91. if "movie" in res[0]:
  92. #if not "permalink" in r2:
  93. #continue
  94. m = re.search('<a class="title" href="([^"]+)/">([^<]+)</a>', r2, re.DOTALL)
  95. if not m: continue
  96. title = m.group(2)
  97. data2 = "videonoma" + m.group(1)
  98. #data2 = "arhivs" + m.group(1)
  99. m = re.search('src="([^"]+)"', r2, re.DOTALL)
  100. img = "https://www.lattelecom.tv/"+m.group(1) if m else ""
  101. m = re.search('<div class="introduction">([^<]+)<', r2, re.DOTALL)
  102. desc = m.group(1) if m else ""
  103. m = re.search('class="genre".+?>([^<]+)<', r2, re.DOTALL)
  104. if m:
  105. desc = m.group(1)+"\n"+desc
  106. else:
  107. m = re.search('<a href="/([^"]+)" class="title">([^<]+)</a>', r2, re.DOTALL)
  108. if not m: continue
  109. title = m.group(2)
  110. data2 = m.group(1)
  111. dd = data2.split("/")
  112. if dd[0]=="arhivs":
  113. ch_name = dd[1]
  114. ch = self.get_channel_by_name(ch_name)
  115. data2 = "archive/get-stream/%s?channelid=%s"%(dd[3],ch["id"]) if ch else ""
  116. #ltc::archive/get-stream/1464120671889?channelid=101
  117. else:
  118. continue
  119. m = re.search(r"url\((.+?)\)", r2, re.DOTALL)
  120. img = "https://www.lattelecom.tv"+m.group(1) if m else ""
  121. m = re.search('<span class="sub">([^<]+)</span>', r2, re.DOTALL)
  122. sub = m.group(1) if m else ""
  123. title = title + " " + sub
  124. desc = title
  125. content.append((title,self.name+"::"+data2,img,desc))
  126. return content
  127. ### Tiešraides kanānālu saraksts ###
  128. elif data=="tiesraide":
  129. r = self.call2(data)
  130. jsdata = re.search("site.program = ([^;]+);",r).group(1)
  131. js=json.loads(jsdata)
  132. for item in self.get_channels():
  133. if item["live"]=='0':continue
  134. title = item["name"]
  135. data2 = "content/live-streams/%s?include=quality"%item["id"]
  136. if item['xprs_id'] in js:
  137. epg = js[item['xprs_id']]
  138. desc = "%s - %s (%s-%s)"%(title,epg[0]["t"],epg[0]["hs"],epg[0]["he"])
  139. img = "https://www.lattelecom.tv" + epg[0]["p"]
  140. else:
  141. img = "https://manstv.lattelecom.tv/"+ item['broadcast_default_picture']
  142. desc = title
  143. content.append((title,self.name+"::"+data2,img,desc))
  144. return content
  145. ### TV arhīva sākums ###
  146. elif data=="archive" or data=="arhivs":
  147. #self.get_epg()
  148. content.extend([
  149. ("Archive - categories", "ltc::archive/categories","","TV live archive by categories"),
  150. ("Archive - channels", "ltc::archive/channels","","TV live archive by channels"),
  151. #("Archive - dates", "ltc::archive/dates","","TV live archive by dates"),
  152. ])
  153. return content
  154. ### Arhīva kategorijas
  155. elif data=="archive/categories":
  156. #https://manstv.lattelecom.tv/api/v1.3/get/archive/records/?filter[category]=13&limit=10&until_id=1458681019238
  157. #https://manstv.lattelecom.tv/api/v1.3/get/archive/categories/
  158. r = self.call(data)
  159. for item in r["items"]:
  160. title = item["name"]
  161. data2 = "archive/records?filter[category]=%s&limit=40"%item["id"]
  162. img = "https://manstv.lattelecom.tv/"+ item['image']
  163. desc = title
  164. content.append((title,self.name+"::"+data2,img,desc))
  165. return content
  166. ### Arhīva kategoriju video
  167. elif "archive/records" in data:
  168. #https://manstv.lattelecom.tv/api/v1.3/get/archive/records/?filter[category]=13&limit=10&until_id=1458681019238
  169. #https://manstv.lattelecom.tv/api/v1.3/get/archive/categories/
  170. r = self.call(data)
  171. for i,item in enumerate(r["items"]):
  172. #if not item["is_archive"]==u"1":continue # TODO jānočeko, kurs no atributiem apzīmē, ka ir arhīvs
  173. if not self.epg_id.has_key(item["id"]):
  174. item["time_start2"] = datetime.datetime.fromtimestamp(int(item["unix_start"]))
  175. item["time_stop2"] = datetime.datetime.fromtimestamp(int(item["unix_stop"]))
  176. item["date"]=item["time_start2"].strftime("%Y-%m-%d")
  177. self.epg.append(item)
  178. index = self.epg.index(item)
  179. self.epg_id[item["id"]]=index
  180. if not item["date"] in self.epg_date:
  181. self.epg_date[item["date"]]=[]
  182. self.epg_date[item["date"]].append(index)
  183. if not item["channel_id"] in self.epg_ch:
  184. self.epg_ch[item["channel_id"]]=[]
  185. self.epg_ch[item["channel_id"]].append(index)
  186. item = self.get_epg_id(item["id"])
  187. ch = self.get_channel_by_id2(item["channel_id"])
  188. ch_name = ch["name"] if ch else item["channel_id"]
  189. 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"])
  190. #data2 = "archive/get-stream/%s?channelid=%s"%(item["id"],ch["id"])
  191. data2 = "content/record-streams/%s?include=quality"%item["id"]
  192. img = "https://manstv.lattelecom.tv/"+ item["url"]
  193. desc = u"%s - %s\n%s - %s\n%s\n%s"%(ch_name,item["title"],item["time_start"],item["time_stop"],
  194. item["category1"],item["description"])
  195. content.append((title,self.name+"::"+data2,img,desc))
  196. if "until_id" in data:
  197. data2 = re.sub("until_id=\d+","until_id="+item["id"],data)
  198. else:
  199. data2 = data + "&until_id=%s"%item["id"]
  200. content.append(("Next page",self.name+"::"+data2,"","Go to next page"))
  201. return content
  202. ### Arhīva kanānālu saraksts
  203. elif data=="archive/channels":
  204. for item in self.get_channels():
  205. if not item["is_archive"]==u"1":continue
  206. title = item["name"]
  207. data2 = "archive/channel/%s?date=%s"%(item["id"],self.today.strftime("%Y-%m-%d"))
  208. img = "https://manstv.lattelecom.tv/"+ item['broadcast_default_picture']
  209. desc = title
  210. content.append((title,self.name+"::"+data2,img,desc))
  211. return content
  212. ### Arhīva kanānāla video saraksta
  213. elif "archive/channel/" in data:
  214. chid = path.split("/")[2]
  215. for item in self.get_epg_date(qs["date"],chid):
  216. #if item["is_archive"]=='0':continue
  217. ch = self.get_channel_by_id2(item["channel_id"])
  218. ch_name = ch["name"] if ch else item["channel_id"]
  219. 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"])
  220. #data2 = "archive/get-stream/%s?channelid=%s"%(item["id"],ch["id"])
  221. data2 = "content/record-streams/%s?include=quality"%item["id"]
  222. img = "https://manstv.lattelecom.tv/"+ item["url"]
  223. desc = u"%s - %s\n%s - %s\n%s\n%s"%(ch_name,item["title"],item["time_start"],item["time_stop"],
  224. item["category1"],item["description"])
  225. content.append((title,self.name+"::"+data2,img,desc))
  226. date2=datetime.datetime.strptime(qs["date"], '%Y-%m-%d').date()-datetime.timedelta(days=1)
  227. date2 = date2.strftime("%Y-%m-%d")
  228. if "date=" in data:
  229. data2 = re.sub("date=[\d-]+","date="+date2,data)
  230. else:
  231. data2 = data + "&date=%s"%date2
  232. content.append(("Previous day (%s)"%date2,self.name+"::"+data2,"","Go previous day"))
  233. return content
  234. ### Arhīva datumi
  235. elif clist=="arhivs" and len(data.split("/"))==2: # TODO - pasreiz nestrada
  236. ch = data.split("/")[1]
  237. r= self.call(data)
  238. m = re.search('class="spac no_select">([^<]+)</span>', r, re.IGNORECASE)
  239. if m:
  240. ch_name = m.group(1)
  241. else:
  242. ch_name = ""
  243. today = datetime.date.today()
  244. for i in range(7):
  245. date = today-datetime.timedelta(i)
  246. title = ch_name + " - " + date.strftime("%d.%m.%Y")
  247. data2 = "%s/%s"%(data,date.strftime("%Y-%m-%d"))
  248. img = ""
  249. desc = title
  250. content.append((title,self.name+"::"+data2,img,desc))
  251. return content
  252. ### Arhīva dienas raidijumi
  253. elif clist=="arhivs" and len(data.split("/"))==3: # TODO - nestrādā
  254. ch = data.split("/")[1]
  255. date = data.split("/")[2]
  256. r= self.call(data)
  257. m = re.search('class="spac no_select">([^<]+)</span>', r, re.IGNORECASE)
  258. if m:
  259. ch_name = m.group(1)
  260. else:
  261. ch_name = ""
  262. 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):
  263. title = "%s - %s"%(item[1],item[2])
  264. data2 = item[0]
  265. img = ""
  266. desc = "%s (%s)\n%s"%(ch_name,date,title)
  267. content.append((title,self.name+"::"+data2,img,desc))
  268. return content
  269. ### Videonoma galvenā
  270. elif data=="videonoma":
  271. content.extend([
  272. ("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"),
  273. ("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"),
  274. ("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ā"),
  275. ("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"),
  276. ("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"),
  277. ("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"),
  278. ("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"),
  279. ("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"),
  280. ("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"),
  281. ("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"),
  282. ("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"),
  283. ("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"),
  284. ("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"),
  285. ("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"),
  286. ("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"),
  287. ("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"),
  288. ("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"),
  289. ("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"),
  290. ])
  291. return content
  292. ### Videonomas saraksti
  293. elif path == "videonoma":
  294. url = "https://www.lattelecom.tv/movies-snippet.json"+params
  295. r = self._http_request(url,headers=self.headers2)
  296. if not r:
  297. return content
  298. js = json.loads(r,"utf8")
  299. if not r:
  300. return content
  301. for item in js["movies"]:
  302. if not item["title"]:
  303. continue
  304. title = item["title"].encode("utf8")
  305. data2 = item["url"][1:].encode("utf8")
  306. if data2[-1]=="/": data2=data2[:-1]
  307. if "/raidijumi/" in data2:
  308. data2 += "?series" # TODO
  309. img = "https://www.lattelecom.tv"+item["image"].encode("utf8")
  310. desc = "%s\n%s"%(title,item["genre"].encode("utf8"))
  311. content.append((title,self.name+"::"+data2,img,desc))
  312. m = re.search("page=(\d+)",data)
  313. if m:
  314. page = int(m.group(1))
  315. data2 = re.sub("page=\d+","page=%s"%(page+1),data)
  316. content.append(("Next page",self.name+"::"+data2,"","Go to next page"))
  317. return content
  318. ### Sērijas
  319. elif clist=="videonoma" and (params=="?series" or "season_nr" in qs):
  320. url = "https://www.lattelecom.tv/"+path
  321. r = self._http_request(url,headers=self.headers2)
  322. if not r:
  323. return content
  324. m = re.search('<div class="movie_details"><div class="movie_titles"><div class="en">([^<]+?)</div>', r, re.DOTALL | re.IGNORECASE)
  325. raidijums = m.group(1) + " - " if m else ""
  326. img0 = re.search('<meta name="og:image" content="([^"]+)">', r).group(1) if re.search('<meta name="dr:say:img" content="([^"]+)">', r) else ""
  327. m = re.search('<ul class="episode_choiser".+?(<li>[^<]+</li>)+</ul>', r)
  328. if m and not "season_nr" in qs: # ir sezonas
  329. for s,it in enumerate(re.findall('<li>([^<]+)</li>', m.group())):
  330. title = "%s%s" % (raidijums, it)
  331. se = re.search("(\d+)",it).group(1)
  332. data2 = path+"?season_nr=%s"%(se)
  333. img = img0
  334. desc = title
  335. content.append((title, self.name + "::" + data2, img, desc))
  336. return content
  337. m = re.search('data-bid="([^"]+)',r)
  338. if m:
  339. if not "season_nr" in qs:
  340. qs["season_nr"]="0"
  341. url = "https://www.lattelecom.tv/episode-loader.json?bcast_ids=%s&season_nr=%s"%(m.group(1),qs["season_nr"])
  342. r = self._http_request(url,headers=self.headers2)
  343. i1 = r.find('{"total":')
  344. i2 = r.find('}<div class=')
  345. js = json.loads(r[i1:i2+1])
  346. for item in js["episodes"]:
  347. title = "%s%s (%s)"%(raidijums,item["title"],item["episode_nr"])
  348. data2 = item["url"][1:]
  349. img = "https://www.lattelecom.tv"+item["img"]
  350. desc = title
  351. content.append((title,self.name+"::"+data2,img,desc))
  352. else:
  353. 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):
  354. title = "%s%s (%s)"%(raidijums,item[2],item[3])
  355. data2 = item[0][1:]
  356. img = "https://www.lattelecom.tv"+item[1]
  357. desc = title
  358. content.append((title,self.name+"::"+data2,img,desc))
  359. return content
  360. ### Videonomas video
  361. elif clist=="videonoma" and len(data.split("/"))>1:
  362. ch = data.split("/")[1]
  363. video_id=data[data.find("/")+1:]
  364. #video_id=data.split("/")[-1]
  365. if not self.is_logedin2():
  366. if not self.login2():
  367. 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 ")
  368. return content
  369. data2 = self.get_noma_url(video_id)
  370. if not data2:
  371. content=("No stream found for '%s'"%data,"","","No stream found")
  372. return content
  373. r = self.call2(data)
  374. m = re.search('<meta name="dr:say:title" content="([^"]+)">', r, re.IGNORECASE)
  375. if m:
  376. title = m.group(1)
  377. else:
  378. title = ""
  379. desc = title
  380. content = (title,data2,"",desc)
  381. return content
  382. else:
  383. return content
  384. def get_streams(self, data):
  385. print "[ltc] get_streams:", data
  386. if "::" in data: data = data.split("::")[1]
  387. if not self.is_video(data):
  388. return []
  389. ### Video nomas strīmus pagaidām dabu no mājas lapas TODO
  390. if data.split("/")[0]=="videonoma" and len(data.split("/"))>1:
  391. #video_id=data.split("/")[-1]
  392. streams = self.get_stream_url2(data)
  393. else:
  394. if not self.is_logedin():
  395. if not self.login():
  396. return []
  397. r = self.call(data)
  398. if not r: return []
  399. if "errors" in r:
  400. return []
  401. self.refresh_token()
  402. token = "&auth_token=app_%s"%(self.token)
  403. vid = data.split("/")[2].split("?")[0]
  404. vtype = data.split("/")[1]
  405. if vtype == "live-streams":
  406. ch = self.get_channel_by_id(vid)
  407. offset = "%2B03%3A00" # TODO - vajag aktuālo laika nobidi no GMS
  408. data2 = "tv/epg-live/%s/?offset=%s"%(ch["xprs_id"],offset)
  409. r2 = self.call(data2)
  410. if r2 and r2["items"]:
  411. title = r2["items"][0]["title"].encode("utf8")
  412. t1 = datetime.datetime.fromtimestamp(int(r2["items"][0]["unix_start"])).strftime('%H:%M')
  413. t2 = datetime.datetime.fromtimestamp(int(r2["items"][0]["unix_stop"])).strftime('%H:%M')
  414. title = "%s (%s-%s)"%(title,t1,t2)
  415. desc = r2["items"][0]["description"]
  416. else:
  417. title = ch["name"]
  418. desc = title
  419. elif vtype == "record-streams":
  420. epg = self.get_epg_id(vid)
  421. if epg:
  422. title = epg["title"].encode("utf8")
  423. t1 = datetime.datetime.fromtimestamp(int(epg["unix_start"])).strftime('%H:%M')
  424. t2 = datetime.datetime.fromtimestamp(int(epg["unix_stop"])).strftime('%H:%M')
  425. date = epg["date"]
  426. title = "%s (%s %s-%s)"%(title,date,t1,t2)
  427. desc = epg["description"]
  428. else:
  429. title = desc = data
  430. streams = []
  431. for s in r["data"]:
  432. stream = util.item()
  433. stream["url"]=(s["attributes"]["stream-url"]+token.encode("utf8")).encode("utf8")
  434. stream["name"]=title
  435. stream["desc"]=desc
  436. stream["type"]="hls"
  437. m=re.search(".+_(\w\w)_(\w\w)\.\w+",s["id"])
  438. if m:
  439. stream["quality"]=m.group(2).encode("utf8")
  440. stream["lang"]=m.group(1).encode("utf8")
  441. streams.append(stream)
  442. ### TODO - sakārtot sarakstu, lai pirmais ir labakais video
  443. qlist = ["???","lq","mq","hq","hd"]
  444. llist = ["fr","en","ru","lv"]
  445. for s in streams:
  446. lv = llist.index(s["lang"])*10 if s["lang"] in llist else 0
  447. qv=qlist.index(s["quality"]) if s["quality"] in qlist else 0
  448. s["order"] = lv+qv
  449. streams = sorted(streams,key=lambda item: item["order"],reverse=True)
  450. return streams
  451. def is_video(self,data):
  452. if "::" in data:
  453. data = data.split("::")[1]
  454. cmd = data.split("/")
  455. if "get-stream" in data:
  456. return True
  457. elif cmd[0] in ("content") and cmd[1] in ("live-streams","record-streams","vod-streams"):
  458. return True
  459. elif cmd[0]=="arhivs" and len(cmd)==4:
  460. return True
  461. elif cmd[0]=="videonoma" and len(cmd)==3 and not "?" in data:
  462. return True
  463. else:
  464. return False
  465. def get_channels(self):
  466. if self.ch:
  467. return self.ch
  468. if not self.check_logedin():
  469. self.login() # citādi nerāda TV3, LNT, TV6
  470. r= self.call("tv/channels")
  471. self.ch=[]
  472. for i,item in enumerate(r["items"]):
  473. self.ch.append(item)
  474. self.ch_id[item["id"]]=i
  475. self.ch_id2[item["xprs_id"]]=i
  476. self.ch_name[item["name"]]=i
  477. return self.ch
  478. def get_channel_by_id(self,chid):
  479. if not self.ch:
  480. self.get_channels()
  481. if not self.ch:
  482. return None
  483. return self.ch[self.ch_id[chid]] if self.ch_id.has_key(chid) else None
  484. def get_channel_by_id2(self,chid):
  485. if not self.ch:
  486. self.get_channels()
  487. if not self.ch:
  488. return None
  489. return self.ch[self.ch_id2[chid]] if self.ch_id2.has_key(chid) else None
  490. def get_channels2(self):
  491. if self.ch2:
  492. return self.ch2
  493. r= self.call2("tiesraide")
  494. self.ch2=[]
  495. for item in re.findall(r'<div class="entry forward-link.+?data-xprs="(\d+)".+?title="([^"]+)" href="/tiesraide/([^"]+)"', r, re.DOTALL):
  496. ch={}
  497. ch["id2"]=item[0]
  498. ch["name"]=item[2]
  499. ch["title"]=item[1]
  500. self.ch2.append(ch)
  501. return self.ch2
  502. def get_channel_by_name2(self,name):
  503. if not self.ch2:
  504. self.get_channels2()
  505. for c in self.ch2:
  506. if c["name"]==name:
  507. return c
  508. return None
  509. def get_channel_by_name(self,name):
  510. if not self.ch:
  511. self.get_channels()
  512. ch2 = self.get_channel_by_name2(name)
  513. if not ch2:
  514. return None
  515. ch = self.get_channel_by_id2(ch2["id2"])
  516. return ch
  517. def get_epg(self,date=None,update=False):
  518. #https://manstv.lattelecom.tv/api/v1.3/get/tv/epg/?daynight=2016-05-19
  519. today=datetime.date.today()
  520. if not date:
  521. date=datetime.date.today().strftime("%Y-%m-%d")
  522. if update:
  523. self.epg=[]
  524. self.epg_id={}
  525. self.epg_id2={}
  526. self.epg_date={}
  527. self.epg_ch={}
  528. self.epg_cat={}
  529. if not date in self.epgdates:
  530. r=self.call("tv/epg/?daynight=%s"%date)
  531. for item in r["items"]:
  532. if item["id"] in self.epg_id: continue
  533. else:
  534. item["time_start2"] = datetime.datetime.fromtimestamp(int(item["unix_start"]))
  535. item["time_stop2"] = datetime.datetime.fromtimestamp(int(item["unix_stop"]))
  536. item["date"]=item["time_start2"].strftime("%Y-%m-%d")
  537. self.epg.append(item)
  538. index = self.epg.index(item)
  539. self.epg_id[item["id"]]=index
  540. if not item["date"] in self.epg_date:
  541. self.epg_date[item["date"]]=[]
  542. self.epg_date[item["date"]].append(index)
  543. if not item["channel_id"] in self.epg_ch:
  544. self.epg_ch[item["channel_id"]]=[]
  545. self.epg_ch[item["channel_id"]].append(index)
  546. if not date in self.epgdates:
  547. self.epgdates.append(date)
  548. def get_epg_id(self,epgid):
  549. if not self.epg:
  550. return None
  551. #self.get_epg()
  552. if epgid in self.epg_id:
  553. return self.epg[self.epg_id[epgid]]
  554. return None
  555. def get_epg_date(self,date,chid):
  556. if not date in self.epgdates:
  557. self.get_epg(date)
  558. items = []
  559. ch = self.get_channel_by_id(chid)
  560. for it in self.epg_date[date]:
  561. item = self.epg[it]
  562. if item["channel_id"]==ch["xprs_id"]:
  563. items.append(item)
  564. return items
  565. def call(self, data,params = None, headers=None):
  566. if not headers: headers = self.headers
  567. #if not lang: lang = self.country
  568. url = self.api_url + data
  569. content = self._http_request(url,params, headers)
  570. if content:
  571. try:
  572. result = json.loads(content)
  573. return result
  574. except Exception, ex:
  575. return None
  576. else:
  577. return None
  578. def call2(self, data,params = None, headers=None):
  579. if not headers: headers = self.headers2
  580. #if not lang: lang = self.country
  581. url = self.api_url2 + data
  582. content = self._http_request(url,params, headers)
  583. return content
  584. def _http_request0(self, url,params = None, headers=None):
  585. if not headers: headers = self.headers
  586. try:
  587. r = urllib2.Request(url, data=params, headers=headers)
  588. u = urllib2.urlopen(r)
  589. content = u.read()
  590. u.close()
  591. return content
  592. except Exception as ex:
  593. return None
  594. def login(self,user="",password=""):
  595. """Login in to site, get token"""
  596. self.options_read()
  597. if not user: user=self.options["user"]
  598. if not password: password = self.options["password"]
  599. # Dabūjam tokenu
  600. url = "https://manstv.lattelecom.tv/api/v1.3/post/user/login"
  601. params = "uid=7f777e938d35e017&password=%s&username=%s&"%(password,user)
  602. headers = headers2dict("""
  603. Content-Type: application/x-www-form-urlencoded; charset=UTF-8
  604. User-Agent: Dalvik/1.6.0 (Linux; U; Android 4.4.2; SM-G900FD Build/KOT49H)
  605. Host: manstv.lattelecom.tv
  606. """ )
  607. try:
  608. r = urllib2.Request(url, data=params, headers=headers)
  609. u = urllib2.urlopen(r)
  610. content = u.read()
  611. u.close()
  612. except Exception as ex:
  613. return None
  614. #r = self.call(data, params)
  615. if r and "token" in content:
  616. self.token=re.search('"token":"(.+?)"', content).group(1)
  617. return True
  618. else:
  619. return False
  620. def refresh_token(self):
  621. data = "user/refresh-token//%s"%self.token
  622. r = self.call(data)
  623. if 'token' in r:
  624. self.token = r["token"]
  625. return True
  626. else:
  627. self.token = ""
  628. return False
  629. def check_logedin(self):
  630. if not self.token:
  631. return False
  632. else:
  633. if self.refresh_token():
  634. return True
  635. else:
  636. return False
  637. def is_logedin(self):
  638. if self.token:
  639. return True
  640. else:
  641. return False
  642. #----------------------------------------------------------------------
  643. def get_tv_url(self,video_id):
  644. """Get m3u8 url for given live tv channel"""
  645. url = "https://m.lattelecom.tv/tiesraide/%s"%video_id
  646. data = self.get_stream_url2("tiesraide/%s"%video_id)
  647. #headers = self.headers
  648. #headers["Cookie"] = "%s; %s; _hjIncludedInSample=0; MobBitr=1; MobRentBitr=%s; MobRentLang=%s;"%(self.session_id,self.mobtv_cache,data["quality"],data["language"])
  649. #response = urllib2.urlopen(urllib2.Request(url, headers=headers))
  650. #html = response.read()
  651. #m3u8 = re.search('x-mpegURL" src="(.*?)"', html).group(1) if "x-mpegURL" in html else ""
  652. return data["stream"] if data else None
  653. #----------------------------------------------------------------------
  654. def get_noma_url(self,video_id,quality="hq",language="lv"):
  655. """Get m3u8 url for given rental video"""
  656. video_id1,video_id2=video_id.split("/")
  657. data = self.get_stream_url2(video_id)
  658. #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"])
  659. #headers = self.headers
  660. #headers["Cookie"] = "%s; %s; MobRentBitr=%s; MobBitr=1; MobRentLang=%s"%(self.session_id,self.mobtv_cache,quality,language)
  661. #response = urllib2.urlopen(urllib2.Request(url, headers=headers))
  662. #m3u8 = response.read()
  663. return data["stream"] if data else None
  664. #----------------------------------------------------------------------
  665. def get_arhivs_url(self,video_id):
  666. """Get m3u8 url for given archive video"""
  667. data = self.get_video_data(video_id)
  668. #url = "https://m.lattelecom.tv/free_origin?show_origin=1&type=arhivs&event_id=%s&bitrate=mhq"%(video_id) #,data["quality"])
  669. #headers = self.headers
  670. #headers["Cookie"] = "%s; %s; MobBitr=1; "%(self.session_id,self.mobtv_cache)
  671. #response = urllib2.urlopen(urllib2.Request(url, headers=headers))
  672. #m3u8 = response.read()
  673. return data["stream"] if data else None
  674. def get_stream_url(self,video_id,type="vod",chid=""):
  675. "Get stream urls (hls) using manstv api"
  676. if type=="vod":
  677. data = "vod/get-stream/%s"%video_id
  678. elif type=="tv":
  679. data = "tv/get-stream?id=%s"%video_id
  680. elif type=="archive":
  681. if not chid: return None
  682. data="archive/get-stream/%s?channelid=%s"%(video_id,chid)
  683. else:
  684. return None
  685. if not self.is_logedin():
  686. if not self.login():
  687. return None
  688. r = self.call(data)
  689. if not r:
  690. return None
  691. self.refresh_token()
  692. token = "&auth_token=app_%s"%(self.token)
  693. hls={}
  694. hls["stream"]=r["stream"]+token
  695. hls["streams"]=[]
  696. if "items" in r:
  697. for s in r["items"]["streams"]:
  698. s["stream"] += token
  699. hls["streams"].append(s)
  700. return hls
  701. def get_stream_url2(self,data):
  702. video_id=data[data.find("/")+1:]
  703. if not self.is_logedin2():
  704. if not self.login2():
  705. return []
  706. #data2 = self.get_noma_url(video_id)
  707. r = self.call2(data)
  708. m = re.search('<meta name="dr:say:title" content="([^"]+)">', r, re.IGNORECASE)
  709. nfo = {}
  710. tt = lambda p,r,d: re.search(p,r).group(1) if re.search(p,r) else d
  711. tt2 = lambda p,r,d: (re.sub("<.+?>","",re.search(p,r).group(1))).split(",") if re.search(p,r) else d
  712. r2 = r[r.find('<div class="movie_details">'):]
  713. nfo["title"] = tt('<div class="lv">([^<]+)</div>', r2,"")
  714. nfo["originaltitle"] = tt('<div class="en">([^<]+)</div>', r2,"")
  715. if nfo["originaltitle"] and not nfo["title"]:
  716. nfo["title"] = nfo["originaltitle"]
  717. #nfo["originaltitle"] = ""
  718. if "raidijumi" in data:
  719. nfo["set"] = nfo["title"]
  720. m = re.search('class="movie_informatio">(.+?)<br>(.+?)<br>', r)
  721. ep2,ep1 = m.groups()
  722. #nfo["title"]
  723. s_nr = tt('<span id="current_season_nr">(\d+)</span>',r,"")
  724. for it in re.findall(r'<span class="epizode_number">(\d+)</span>.+?<span class="titlez">(.+?)</span>', r):
  725. if it[1] == ep1:
  726. ep_nr = it[0]
  727. break
  728. else:
  729. ep_nr=""
  730. if s_nr:
  731. nfo["season"] = s_nr
  732. if ep_nr:
  733. nfo["eposode"] = ep_nr
  734. se = "S%02i"%int(s_nr) if s_nr else ""
  735. se += "E%02i"%int(ep_nr) if ep_nr else ""
  736. nfo["title"] += " - %s"%ep1 if ep1 else ""
  737. nfo["originaltitle"] += " - %s"%ep2 if ep2 else ""
  738. nfo["title"] += "(%s)"%se if se else ""
  739. nfo["originaltitle"] += "(%s)"%se if se else ""
  740. nfo["thumb"] = tt('<meta name="og:image" content="([^"]+)"', r,"")
  741. nfo["year"] = tt("Gads: ([^<]+)<", r2, "")
  742. nfo["runtime"] = tt("Garums: ([^<]+)<", r2, "")
  743. nfo["quality"] = tt("Kvalitāte: ([^<]+)<", r2, "")
  744. nfo["genre"]=tt2("Žanr.: (.+?)<br", r2, "")
  745. nfo["director"] = tt("Režisors: ([^<]+)<", r2, "")
  746. nfo["actor"] = tt2("Lomās: ([^<]+)<", r2, "")
  747. nfo["language"] = tt2("Valodas: ([^<]+)<", r2, "")
  748. nfo["subtitles"] = tt2("Subtitri: ([^<]+)<", r2, "")
  749. nfo["plot"] = tt('"introduction">(.+?)<', r2,"")
  750. nfo["tagline"] = nfo["plot"]
  751. title = util.nfo2title(nfo)
  752. desc = util.nfo2desc(nfo)
  753. img = nfo["thumb"]
  754. #xml = util.nfo2xml(nfo)
  755. url = "https://www.lattelecom.tv/xmls/%s.xml"%video_id
  756. headers = self.headers2
  757. headers["Cookie"] = self.session_id
  758. response = urllib2.urlopen(urllib2.Request(url, headers=headers))
  759. r = response.read()
  760. servers = re.findall("(?s)<origin>([^<]+)</origin>", r)
  761. streams_xml = re.findall('<stream quality="\w+">(mp4:\w+(\w\w)_(\w\w).mp4)</stream>',r)
  762. resource_id = re.search("(?s)<resource_id>([^<]+)</resource_id>", r).group(1)
  763. token = re.search("(?s)<auth_token>([^<]+)</auth_token>", r).group(1)
  764. streams=[]
  765. captions = []
  766. llist = ["fr","en","ru","lv"]
  767. for s in re.findall('<subtitles code="([^"]+)">([^<]+)</subtitles>', r, re.DOTALL):
  768. sub = {}
  769. sub["url"] = s[1]
  770. sub["lang"] = s[0]
  771. sub["name"] = "captions (vtt)"
  772. sub["type"] = "vtt"
  773. sub["order"] = llist.index(sub["lang"])*10 if sub["lang"] in llist else 0
  774. captions.append(sub)
  775. captions = sorted(captions,key=lambda item: item["order"],reverse=True)
  776. for s in streams_xml:
  777. for server in servers:
  778. stream = util.item()
  779. server2 = self.load_balancer(server)
  780. url = "http://%s/mobile-vod/%s/playlist.m3u8?resource_id=%s&auth_token=%s"%(server2,s[0],resource_id,token)
  781. # TODO Engima2 gstreamer vajag lai padod playlist nevis chunklist
  782. # r3 = self._http_request(url)
  783. # sss = re.findall(r"#EXT-X-STREAM-INF:.*?BANDWIDTH=(\d+).*?\n(.+?)$", r3, re.IGNORECASE | re.MULTILINE)
  784. # if sss:
  785. # url2 = sss[0][1]
  786. # stream["headers"] = {"Referer":url}
  787. # if url2.startswith("http"):
  788. # url = url2
  789. # else:
  790. # url = util.hls_base(url)+url2
  791. stream["url"]=url
  792. stream["lang"]=s[1]
  793. stream["quality"]=s[2]
  794. stream["name"]=title
  795. stream["desc"]=desc
  796. stream["img"] = img
  797. stream["nfo"] = {"movie":nfo}
  798. stream["type"]="hls" #stream_type(url)
  799. stream["subs"] = []
  800. for c in captions:
  801. c2= c.copy()
  802. #c2["url"] ="http://%s/mobile-vod/%s/%s?resource_id=%s&auth_token=%s"%(server2,s[0],c["url"],resource_id,token)
  803. c2["url"] ="http://%s/mobile-vod/%s/%s"%(server2,s[0],c["url"])
  804. stream["subs"].append(c2)
  805. pass
  806. streams.append(stream)
  807. break # TODO ņem tikai pirmo serveri, varētu pārbaudit, kurš no tiem strādā, kurš ne
  808. return streams
  809. #data = {}
  810. #data["server"] = re.findall("(?s)<origin>([^<]+)</origin>", r)[1]
  811. #data["language"]=re.findall('(?s)<language code="([^"]+)">', r)
  812. #data["language"]="lv" if "lv" in data["language"] else "ru" if "ru" in data["language"] else "en"
  813. #data["qs"]=re.findall('(?s)<stream quality="([^"]+)">([^<]+)</stream>', r)
  814. #data["qs"]=dict(data["qs"])
  815. #qs = data["qs"].keys()
  816. #data["quality"] = "hd" if "hd" in qs else "hq" if "hq" in qs else "mhq" if "mhq" in qs else "lq"
  817. #data["mp4"] = data["qs"][data["quality"]]
  818. #data["token"] = re.search("(?s)<auth_token>([^<]+)</auth_token>", r).group(1)
  819. #data["resource_id"]=re.search("(?s)<resource_id>([^<]+)</resource_id>", r).group(1)
  820. #data["server"]=self.load_balancer(data["server"])
  821. #data["hls"] = "http://%s/mobile-vod/%s/playlist.m3u8?resource_id=%s&auth_token=%s"%(data["server"],data["mp4"],data["resource_id"],data["token"])
  822. ##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"])
  823. ### wwww.lattelecom.tv izsaukumi
  824. def login2(self,user="",password=""):
  825. """Login in to site, create session cookies"""
  826. if not user: user=self.options["user"]
  827. if not password: password = self.options["password"]
  828. url0 = "https://www.lattelecom.tv"
  829. class NoRedirectHandler(urllib2.HTTPRedirectHandler):
  830. def http_error_302(self, req, fp, code, msg, headers):
  831. infourl = urllib.addinfourl(fp, headers, req.get_full_url())
  832. infourl.status = code
  833. infourl.code = code
  834. return infourl
  835. http_error_300 = http_error_302
  836. http_error_301 = http_error_302
  837. http_error_303 = http_error_302
  838. http_error_307 = http_error_302
  839. # Dabūjam sesijas id un url_gif, kas redirektējas uz auth_url
  840. headers = headers2dict("""
  841. Host: www.lattelecom.tv
  842. User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; rv:46.0) Gecko/20100101 Firefox/46.0
  843. Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
  844. Accept-Language: en-US,en;q=0.5
  845. DNT: 1
  846. Connection: keep-alive
  847. """)
  848. response = urllib2.urlopen(urllib2.Request(url0, headers=headers))
  849. session_id = response.headers["set-cookie"].split(";")[0]
  850. html = response.read()
  851. url_gif = url0 + re.search('(/auth/\d+\.gif)', html).group(1)
  852. # Dabūtjam auth_url
  853. headers = headers2dict("""
  854. Host: www.lattelecom.tv
  855. User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; rv:46.0) Gecko/20100101 Firefox/46.0
  856. Accept: image/png,image/*;q=0.8,*/*;q=0.5
  857. Accept-Language: en-US,en;q=0.5
  858. DNT: 1
  859. Referer: https://www.lattelecom.tv/
  860. """)
  861. headers["Cookie"] = session_id
  862. urllib2.install_opener(urllib2.build_opener(NoRedirectHandler()))
  863. response = urllib2.urlopen(urllib2.Request(url_gif, headers=headers))
  864. if response.code == 302:
  865. url_auth = response.headers["location"]
  866. else:
  867. self.error = u"auth.gif nenostrādāja"
  868. #raise u"auth.gif nenostrādāja"
  869. return False
  870. # Pierakstāmies iekš auth.lattelecom.lv
  871. headers = headers2dict("""
  872. Host: auth.lattelecom.lv
  873. User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; rv:46.0) Gecko/20100101 Firefox/46.0
  874. Accept: image/png,image/*;q=0.8,*/*;q=0.5
  875. Accept-Language: en-US,en;q=0.5
  876. DNT: 1
  877. Referer: https://www.lattelecom.tv/
  878. """)
  879. response = urllib2.urlopen(urllib2.Request(url_auth, headers=headers))
  880. if not response.code == 302:
  881. self.error = u"pierakstīšanās auth.lattelecom.lv nenostrādāja"
  882. return False
  883. #raise "pierakstīšanās auth.lattelecom.lv nenostrādāja"
  884. # Mēģinam ielogoties
  885. headers = headers2dict("""
  886. Host: www.lattelecom.tv
  887. User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; rv:46.0) Gecko/20100101 Firefox/46.0
  888. Accept: text/javascript, application/javascript, application/ecmascript, application/x-ecmascript, */*; q=0.01
  889. Accept-Language: en-US,en;q=0.5
  890. DNT: 1
  891. X-Requested-With: XMLHttpRequest
  892. Referer: https://www.lattelecom.tv/
  893. """)
  894. headers["Cookie"] = session_id
  895. #data = "login=yes&email=%s&passw=%s"%(user,password)
  896. url = "https://www.lattelecom.tv/login.json?callback=jQuery111303344749731668816_1463817318435&username=%s&password=%s&captcha=&sid=&_="%(user,password)
  897. req = urllib2.Request(url, headers=headers)
  898. response = urllib2.urlopen(req)
  899. #with open("auth.htm","w") as f: f.write(response.read())
  900. if not response.code == 200:
  901. #self.error = u"kļūda ielogojoties"
  902. raise Exception(u"kļūda ielogojoties")
  903. html = response.read()
  904. if not '"success":true' in html:
  905. err = re.search('"error":"(.+?)"',html).group(1) if re.search('"error":"(.+?)"',html) else ""
  906. raise Exception(u"Kļūda ielogojoties - %s"%err.decode("utf8"))
  907. self.session_id = session_id
  908. self.headers2["Cookie"] = "%s; "%(self.session_id)
  909. self.error = ""
  910. return True
  911. def check_logedin2(self):
  912. if not self.session_id:
  913. return False
  914. else:
  915. url = "https://www.lattelecom.tv/profils"
  916. response = urllib2.urlopen(urllib2.Request(url, headers=self.headers2))
  917. if response.code == 200:
  918. return True
  919. else:
  920. self.session_id = ""
  921. return False
  922. def is_logedin2(self):
  923. if self.session_id:
  924. return True
  925. else:
  926. return False
  927. def load_balancer(self,server,streams=[]):
  928. headers = headers2dict("""
  929. Connection: keep-alive
  930. User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/50.0.2661.102 Safari/537.36
  931. X-Requested-With: ShockwaveFlash/21.0.0.242
  932. """)
  933. url = "http://%s/loadbalancer"%server
  934. response = urllib2.urlopen(urllib2.Request(url, headers=headers))
  935. r = response.read()
  936. statuss = re.search("<status>(\d+)</status>",r).group(1)
  937. edge = re.search("<edge>([^<>]+)</edge>",r).group(1)
  938. return edge
  939. def test_hls(self,url):
  940. headers = headers2dict("""
  941. Connection: keep-alive
  942. User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/50.0.2661.102 Safari/537.36
  943. """)
  944. try:
  945. response = urllib2.urlopen(urllib2.Request(url, headers=headers))
  946. except Exception as ex:
  947. print "hls failed: %s %s"%(ex.getcode(),url)
  948. return False
  949. if response.code == 200:
  950. html = response.read()
  951. url0 = re.search("(http://[^/]+/)",url).group(1)
  952. chunklist = re.search("(chunklist.+)",html).group(1).strip()
  953. url2 = url.split('/')[:-1]
  954. url2 ="/".join(url2)+"/"+chunklist
  955. try:
  956. response2 = urllib2.urlopen(urllib2.Request(url2, headers=headers))
  957. except Exception as ex:
  958. print "hls chunk failed: %s %s"%(ex.getcode(),url2)
  959. return False
  960. if response2.code == 200:
  961. return True
  962. else:
  963. return False
  964. else:
  965. return False
  966. if __name__ == "__main__":
  967. c = Source()
  968. from subprocess import call
  969. if len(sys.argv)>1 and not "ltc::" in sys.argv[1]:
  970. vid = vid2 = sys.argv[1]
  971. password = sys.argv[2]
  972. print "login - %s"%c.login("ivars777",password)
  973. #vid = "1069"
  974. #vid = "1462566072086"
  975. #channelid="101"
  976. #vid = "1350462656767"
  977. #data = c.get_stream_url(vid,"vod")
  978. #call([r"c:\Program Files\VideoLAN\VLC\vlc.exe",data["stream"]])
  979. #pass
  980. print "login2 - %s"%c.login2("ivars777",password)
  981. #vid2 = "animation/ultimate_avengers_ii"
  982. #vid2 = "animation/ice_age"
  983. #vid2 = "tiesraide/ltv1"
  984. #vid2 = "arhivs/1456521417815"
  985. streams = c.get_stream_url2(vid2)
  986. stream = streams[-1]
  987. print
  988. #for s in data:
  989. #call([r"c:\Program Files\VideoLAN\VLC\vlc.exe",stream["url"]])
  990. cmd = ["ffplay.exe",
  991. "-headers","Referer:%s"%(quote(stream["headers"]["Referer"])),
  992. "-headers","Connection:Keep-Alive",
  993. stream["url"]]
  994. print " ".join(cmd)
  995. call(cmd)
  996. pass
  997. else:
  998. if len(sys.argv)>1:
  999. data= sys.argv[1]
  1000. else:
  1001. data = "ltc::home"
  1002. content = c.get_content(data)
  1003. for item in content:
  1004. print item
  1005. #cat = api.get_categories(country)
  1006. #chan = api.get_channels("lv")
  1007. #prog = api.get_programs(channel=6400)
  1008. #prog = api.get_programs(category=55)
  1009. #seas = api.get_seasons(program=6453)
  1010. #str = api.get_streams(660243)
  1011. #res = api.get_videos(802)
  1012. #formats = api.getAllFormats()
  1013. #det = api.detailed("1516")
  1014. #vid = api.getVideos("13170")
  1015. pass