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

ltc.py 49KB

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