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

ltc.py 50KB

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