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

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