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

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088
  1. #!/usr/bin/env python
  2. # coding=utf8
  3. #
  4. # This file is part of PlayStream - enigma2 plugin to play video streams from various sources
  5. # Copyright (c) 2016 ivars777 (ivars777@gmail.com)
  6. # Distributed under the GNU GPL v3. For full terms see http://www.gnu.org/licenses/gpl-3.0.en.html
  7. #
  8. import sys, os, os.path, re, sys
  9. import urllib,urllib2,urlparse
  10. from xml.sax.saxutils import unescape,escape
  11. from urllib import quote, unquote
  12. import datetime
  13. import HTMLParser
  14. import json
  15. import datetime
  16. from SourceBase import SourceBase, stream_type
  17. import util
  18. from collections import OrderedDict
  19. import ssl
  20. if "_create_unverified_context" in dir(ssl):
  21. ssl._create_default_https_context = ssl._create_unverified_context
  22. API_URL = 'https://m.lattelecom.tv/'
  23. user_agent = "Mozilla/5.0 (iPhone; U; CPU iPhone OS 5_1_1 like Mac OS X; da-dk) AppleWebKit/534.46.0 (KHTML, like Gecko) CriOS/19.0.1084.60 Mobile/9B206 Safari/7534.48.3"
  24. headers2dict = lambda h: dict([l.strip().split(": ") for l in h.strip().splitlines()])
  25. h = HTMLParser.HTMLParser()
  26. class Source(SourceBase):
  27. def __init__(self,cfg_path=None):
  28. self.name = "ltc"
  29. self.title = "Shortcut.lv (lattelecom.tv)"
  30. self.img = "picons/shortcut.png"
  31. self.desc = "Shortcut.lv (lattelecom.tv) satura skatīšanās"
  32. self.token = "" # manstv.lattelecom.tv
  33. self.session_id = "" # www.lattelecom.tv
  34. self.api_url = "https://manstv.lattelecom.tv/api/v1.4/get/"
  35. self.api_url2 = "https://www.lattelecom.tv/"
  36. self.headers = headers2dict("""
  37. User-Agent: Dalvik/1.6.0 (Linux; U; Android 4.4.2; SM-G900FD Build/KOT49H)
  38. Host: manstv.lattelecom.tv
  39. Connection: Keep-Alive
  40. """)
  41. self.headers2 = headers2dict("""
  42. Host: www.lattelecom.tv
  43. Connection: keep-alive
  44. Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
  45. User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/50.0.2661.102 Safari/537.36
  46. Accept-Language: en-US,en;q=0.8
  47. """)
  48. self.channels = None
  49. ### specific service info ###
  50. self.ch=[]
  51. self.ch2=[]
  52. self.ch_id={}
  53. self.ch_id2={}
  54. self.ch_name={}
  55. self.epg=[]
  56. self.epg_id={}
  57. self.epg_id2={}
  58. self.epg_date={}
  59. self.epg_ch={}
  60. self.epgdates = []
  61. self.today = datetime.date.today()
  62. self.today2 = self.today.strftime("%d.%m.%Y")
  63. cur_directory = os.path.dirname(os.path.abspath(__file__))
  64. if not cfg_path: cfg_path = cur_directory
  65. self.config_file = os.path.join(cfg_path,self.name+".cfg")
  66. self.options = OrderedDict([("user","lietotajs"),("password","parole")])
  67. self.options_read()
  68. def get_content(self, data):
  69. print "[ltc] get_content:", data
  70. source, data, path, plist, clist, params, qs = self.parse_data(data)
  71. content=[]
  72. content.append(("..return", "back","","Return back"))
  73. if clist=="home":
  74. content.extend([
  75. ("Search TV", "ltc::search/{0}","","Search in TV archive"),
  76. ("Search Video", "ltc::viss/search/?cat=movies&q={0}","","Search in video"),
  77. ("Live streams", "ltc::tiesraide","","TV live streams"),
  78. ("Archive", "ltc::arhivs","","TV live archive"),
  79. ("Video", "ltc::videonoma","","Video on demand"),
  80. ])
  81. return content
  82. ### Meklēt TV (1.4 API)
  83. elif clist == "search": #TODO vod/search/{q}
  84. #r = self.call("vod/"+data)
  85. return content
  86. ### Meklēsana video (www )###
  87. elif path == 'viss/search/': #TODO vod/search/{q}
  88. r = self.call2(data)
  89. if "cat=movies" in data:
  90. result = re.findall(' class="forward-link" href="/([^"]+)"><img src="([^"]+)".+?class="categorie-one-title">([^<]+)<', r)
  91. for item in result:
  92. title = item[2]
  93. data2 = item[0][0:-1]
  94. img = "https://www.lattelecom.tv" + item[1]
  95. desc = title
  96. content.append((title,self.name+"::"+data2,img,desc))
  97. return content
  98. else:
  99. return content
  100. ### Tiešraides kanānālu saraksts ###
  101. elif data=="tiesraide":
  102. r = self.call2(data)
  103. m = re.search("var xprs_ides_array = (.+);", r, re.MULTILINE)
  104. if m:
  105. js=json.loads(m.group(1))
  106. else:
  107. raise Exception("Error reading channel list")
  108. for item in self.get_channels():
  109. if item["live"]=='0':continue
  110. title = item["name"]
  111. data2 = "content/live-streams/%s?include=quality"%item["id"]
  112. if item['xprs_id'] in js:
  113. epg = js[item['xprs_id']]
  114. desc = "%s - %s (%s-%s)"%(title,epg[0]["t"],epg[0]["hs"],epg[0]["he"])
  115. img = "https://www.lattelecom.tv" + epg[0]["p"]
  116. else:
  117. img = "https://manstv.lattelecom.tv/"+ item['broadcast_default_picture']
  118. desc = title
  119. content.append((title,self.name+"::"+data2,img,desc))
  120. return content
  121. ### TV arhīva sākums ###
  122. elif data=="archive" or data=="arhivs":
  123. #self.get_epg()
  124. content.extend([
  125. ("Archive - categories", "ltc::archive/categories","","TV live archive by categories"),
  126. ("Archive - channels", "ltc::archive/channels","","TV live archive by channels"),
  127. #("Archive - dates", "ltc::archive/dates","","TV live archive by dates"),
  128. ])
  129. return content
  130. ### Arhīva kategorijas
  131. elif data=="archive/categories":
  132. #https://manstv.lattelecom.tv/api/v1.3/get/archive/records/?filter[category]=13&limit=10&until_id=1458681019238
  133. #https://manstv.lattelecom.tv/api/v1.3/get/archive/categories/
  134. r = self.call(data)
  135. for item in r["items"]:
  136. title = item["name"]
  137. data2 = "archive/records?filter[category]=%s&limit=40"%item["id"]
  138. img = "https://manstv.lattelecom.tv/"+ item['image']
  139. desc = title
  140. content.append((title,self.name+"::"+data2,img,desc))
  141. return content
  142. ### Arhīva kategoriju video
  143. elif "archive/records" in data:
  144. #https://manstv.lattelecom.tv/api/v1.3/get/archive/records/?filter[category]=13&limit=10&until_id=1458681019238
  145. #https://manstv.lattelecom.tv/api/v1.3/get/archive/categories/
  146. r = self.call(data)
  147. for i,item in enumerate(r["items"]):
  148. #if not item["is_archive"]==u"1":continue # TODO jānočeko, kurs no atributiem apzīmē, ka ir arhīvs
  149. if not self.epg_id.has_key(item["id"]):
  150. item["time_start2"] = datetime.datetime.fromtimestamp(int(item["unix_start"]))
  151. item["time_stop2"] = datetime.datetime.fromtimestamp(int(item["unix_stop"]))
  152. item["date"]=item["time_start2"].strftime("%Y-%m-%d")
  153. self.epg.append(item)
  154. index = self.epg.index(item)
  155. self.epg_id[item["id"]]=index
  156. if not item["date"] in self.epg_date:
  157. self.epg_date[item["date"]]=[]
  158. self.epg_date[item["date"]].append(index)
  159. if not item["channel_id"] in self.epg_ch:
  160. self.epg_ch[item["channel_id"]]=[]
  161. self.epg_ch[item["channel_id"]].append(index)
  162. item = self.get_epg_id(item["id"])
  163. ch = self.get_channel_by_id2(item["channel_id"])
  164. ch_name = ch["name"] if ch else item["channel_id"]
  165. 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"])
  166. #data2 = "archive/get-stream/%s?channelid=%s"%(item["id"],ch["id"])
  167. data2 = "content/record-streams/%s?include=quality"%item["id"]
  168. img = "https://manstv.lattelecom.tv/"+ item["url"]
  169. desc = u"%s - %s\n%s - %s\n%s\n%s"%(ch_name,item["title"],item["time_start"],item["time_stop"],
  170. item["category1"],item["description"])
  171. content.append((title,self.name+"::"+data2,img,desc))
  172. if "until_id" in data:
  173. data2 = re.sub("until_id=\d+","until_id="+item["id"],data)
  174. else:
  175. data2 = data + "&until_id=%s"%item["id"]
  176. content.append(("Next page",self.name+"::"+data2,"","Go to next page"))
  177. return content
  178. ### Arhīva kanānālu saraksts
  179. elif data=="archive/channels":
  180. for item in self.get_channels():
  181. if not item["is_archive"]==u"1":continue
  182. title = item["name"]
  183. data2 = "archive/channel/%s?date=%s"%(item["id"],self.today.strftime("%Y-%m-%d"))
  184. img = "https://manstv.lattelecom.tv/"+ item['broadcast_default_picture']
  185. desc = title
  186. content.append((title,self.name+"::"+data2,img,desc))
  187. return content
  188. ### Arhīva kanānāla video saraksta
  189. elif "archive/channel/" in data:
  190. chid = path.split("/")[2]
  191. for item in self.get_epg_date(qs["date"],chid):
  192. #if item["is_archive"]=='0':continue
  193. ch = self.get_channel_by_id2(item["channel_id"])
  194. ch_name = ch["name"] if ch else item["channel_id"]
  195. 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"])
  196. #data2 = "archive/get-stream/%s?channelid=%s"%(item["id"],ch["id"])
  197. data2 = "content/record-streams/%s?include=quality"%item["id"]
  198. img = "https://manstv.lattelecom.tv/"+ item["url"]
  199. desc = u"%s - %s\n%s - %s\n%s\n%s"%(ch_name,item["title"],item["time_start"],item["time_stop"],
  200. item["category1"],item["description"])
  201. content.append((title,self.name+"::"+data2,img,desc))
  202. date2=datetime.datetime.strptime(qs["date"], '%Y-%m-%d').date()-datetime.timedelta(days=1)
  203. date2 = date2.strftime("%Y-%m-%d")
  204. if "date=" in data:
  205. data2 = re.sub("date=[\d-]+","date="+date2,data)
  206. else:
  207. data2 = data + "&date=%s"%date2
  208. content.append(("Previous day (%s)"%date2,self.name+"::"+data2,"","Go previous day"))
  209. return content
  210. ### Arhīva datumi
  211. elif clist=="arhivs" and len(data.split("/"))==2: # TODO - pasreiz nestrada
  212. ch = data.split("/")[1]
  213. r= self.call(data)
  214. m = re.search('class="spac no_select">([^<]+)</span>', r, re.IGNORECASE)
  215. if m:
  216. ch_name = m.group(1)
  217. else:
  218. ch_name = ""
  219. today = datetime.date.today()
  220. for i in range(7):
  221. date = today-datetime.timedelta(i)
  222. title = ch_name + " - " + date.strftime("%d.%m.%Y")
  223. data2 = "%s/%s"%(data,date.strftime("%Y-%m-%d"))
  224. img = ""
  225. desc = title
  226. content.append((title,self.name+"::"+data2,img,desc))
  227. return content
  228. ### Arhīva dienas raidijumi
  229. elif clist=="arhivs" and len(data.split("/"))==3: # TODO - nestrādā
  230. ch = data.split("/")[1]
  231. date = data.split("/")[2]
  232. r= self.call(data)
  233. m = re.search('class="spac no_select">([^<]+)</span>', r, re.IGNORECASE)
  234. if m:
  235. ch_name = m.group(1)
  236. else:
  237. ch_name = ""
  238. 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):
  239. title = "%s - %s"%(item[1],item[2])
  240. data2 = item[0]
  241. img = ""
  242. desc = "%s (%s)\n%s"%(ch_name,date,title)
  243. content.append((title,self.name+"::"+data2,img,desc))
  244. return content
  245. ### Videonoma galvenā
  246. elif data=="videonoma":
  247. content.extend([
  248. ("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"),
  249. ("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"),
  250. ("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ā"),
  251. ("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"),
  252. ("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"),
  253. ("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"),
  254. ("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"),
  255. ("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"),
  256. ("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"),
  257. ("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"),
  258. ("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"),
  259. ("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"),
  260. ("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"),
  261. ("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"),
  262. ("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"),
  263. ("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"),
  264. ("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"),
  265. ("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"),
  266. ])
  267. return content
  268. ### Videonomas saraksti
  269. elif path == "videonoma":
  270. url = "https://www.lattelecom.tv/movies-snippet.json"+params
  271. r = self._http_request(url,headers=self.headers2)
  272. if not r:
  273. return content
  274. js = json.loads(r,"utf8")
  275. if not r:
  276. return content
  277. for item in js["movies"]:
  278. if not item["title"]:
  279. continue
  280. title = item["title"].encode("utf8")
  281. data2 = item["url"][1:].encode("utf8")
  282. if data2[-1]=="/": data2=data2[:-1]
  283. if "/raidijumi/" in data2:
  284. data2 += "?series" # TODO
  285. img = "https://www.lattelecom.tv"+item["image"].encode("utf8")
  286. desc = "%s\n%s"%(title,item["genre"].encode("utf8"))
  287. content.append((title,self.name+"::"+data2,img,desc))
  288. m = re.search("page=(\d+)",data)
  289. if m:
  290. page = int(m.group(1))
  291. data2 = re.sub("page=\d+","page=%s"%(page+1),data)
  292. content.append(("Next page",self.name+"::"+data2,"","Go to next page"))
  293. return content
  294. ### Sērijas
  295. elif clist=="videonoma" and (params=="?series" or "season_nr" in qs):
  296. url = "https://www.lattelecom.tv/"+path
  297. r = self._http_request(url,headers=self.headers2)
  298. if not r:
  299. return content
  300. m = re.search('<div class="movie_titles"><div class="en">([^<]+)</div>', r)
  301. raidijums = m.group(1) if m else "Series"
  302. img0 = re.search('<meta name="og:image" content="([^"]+)">', r).group(1) if re.search('<meta name="dr:say:img" content="([^"]+)">', r) else ""
  303. m = re.search('season_choice', r)
  304. # Ir sezonas
  305. if m:
  306. result = re.findall(r"""season_choice\('[^']*','[^']*','(\d+)','epizode','([^']*)','','(\d+)',0,0\)">([^<]+)<""", r)
  307. if not result:
  308. raise Exception("No seasons find!")
  309. vid = result[0][1]
  310. if not "season_nr" in qs: # Sezonu saraksts
  311. for s,it in enumerate(result):
  312. title = "%s - %s" % (raidijums, it[3])
  313. data2 = path+"?season_nr=%s"%(it[2])
  314. img = img0
  315. desc = title
  316. content.append((title, self.name + "::" + data2, img, desc))
  317. return content
  318. else: # Sezonas epizožu saraksts
  319. if not "season_nr" in qs:
  320. qs["season_nr"]="0"
  321. # https://www.lattelecom.tv/api/episode-loader-design17/0?chunk_size=4&sorting=epizode&series_id=dora_the_explorer
  322. url = "https://www.lattelecom.tv/api/episode-loader-design17/%s?chunk_size=4&sorting=epizode&series_id=%s" % (qs["season_nr"], vid)
  323. r = self._http_request(url,headers=self.headers2)
  324. try:
  325. js = json.loads(r)
  326. except:
  327. raise Exception("Error getting episode list")
  328. result = re.findall(r'class="" href="([^"]+)".+?image:url\(([^ \)]+)\); "></div><div class="episode_titlez_design17">([^<]+)</div><div class="episode_number_design17">([^<]+)</div></a>', js["data"])
  329. for item in result:
  330. title = "%s - %s(%s)"%(raidijums,item[2],item[3])
  331. data2 = item[0][1:]
  332. img = "https://www.lattelecom.tv"+item[1]
  333. desc = title
  334. content.append((title,self.name+"::"+data2,img,desc))
  335. return content
  336. # Nav sezonu
  337. else:
  338. result = re.findall(r'class="" href="([^"]+)".+?image:url\(([^ \)]+)\).+?class="episode_titlez_design17">([^<]+)</div><div class="episode_number_design17">([^<]+)</div></a>', r)
  339. for item in result:
  340. title = "%s - %s(%s)"%(raidijums,item[2],item[3])
  341. data2 = item[0][1:]
  342. img = "https://www.lattelecom.tv"+item[1]
  343. desc = title
  344. content.append((title,self.name+"::"+data2,img,desc))
  345. return content
  346. ### Videonomas video
  347. elif clist=="videonoma" and len(data.split("/"))>1:
  348. ch = data.split("/")[1]
  349. video_id=data[data.find("/")+1:]
  350. #video_id=data.split("/")[-1]
  351. if not self.is_logedin2():
  352. if not self.login2():
  353. 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 ")
  354. return content
  355. data2 = self.get_noma_url(video_id)
  356. if not data2:
  357. content=("No stream found for '%s'"%data,"","","No stream found")
  358. return content
  359. r = self.call2(data)
  360. m = re.search('<meta name="dr:say:title" content="([^"]+)">', r, re.IGNORECASE)
  361. if m:
  362. title = m.group(1)
  363. else:
  364. title = ""
  365. desc = title
  366. content = (title,data2,"",desc)
  367. return content
  368. else:
  369. return content
  370. def get_streams(self, data):
  371. print "[ltc] get_streams:", data
  372. if "::" in data: data = data.split("::")[1]
  373. if not self.is_video(data):
  374. return []
  375. ### Video nomas strīmus pagaidām dabu no mājas lapas TODO
  376. if data.split("/")[0]=="videonoma" and len(data.split("/"))>1:
  377. #video_id=data.split("/")[-1]
  378. streams = self.get_stream_url2(data)
  379. else:
  380. if not self.is_logedin():
  381. if not self.login():
  382. return []
  383. r = self.call(data)
  384. if not r: return []
  385. if "errors" in r:
  386. return []
  387. self.refresh_token()
  388. token = "&auth_token=app_%s"%(self.token)
  389. vid = data.split("/")[2].split("?")[0]
  390. vtype = data.split("/")[1]
  391. if vtype == "live-streams":
  392. ch = self.get_channel_by_id(vid)
  393. offset = "%2B03%3A00" # TODO - vajag aktuālo laika nobidi no GMS
  394. data2 = "tv/epg-live/%s/?offset=%s"%(ch["xprs_id"],offset)
  395. r2 = self.call(data2)
  396. if r2 and r2["items"]:
  397. title = r2["items"][0]["title"].encode("utf8")
  398. t1 = datetime.datetime.fromtimestamp(int(r2["items"][0]["unix_start"])).strftime('%H:%M')
  399. t2 = datetime.datetime.fromtimestamp(int(r2["items"][0]["unix_stop"])).strftime('%H:%M')
  400. title = "%s (%s-%s)"%(title,t1,t2)
  401. desc = r2["items"][0]["description"]
  402. else:
  403. title = ch["name"]
  404. desc = title
  405. elif vtype == "record-streams":
  406. epg = self.get_epg_id(vid)
  407. if epg:
  408. title = epg["title"].encode("utf8")
  409. t1 = datetime.datetime.fromtimestamp(int(epg["unix_start"])).strftime('%H:%M')
  410. t2 = datetime.datetime.fromtimestamp(int(epg["unix_stop"])).strftime('%H:%M')
  411. date = epg["date"]
  412. title = "%s (%s %s-%s)"%(title,date,t1,t2)
  413. desc = epg["description"]
  414. else:
  415. title = desc = data
  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. self.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_info2(self, data):
  688. # Get movie info (for VOD)
  689. nfo = {}
  690. tt = lambda p,r,d: re.search(p,r).group(1) if re.search(p,r) else d
  691. tt2 = lambda p,r,d: (re.sub("[\.]","",re.search(p,r).group(1))).split(", ") if re.search(p,r) else d
  692. r = self.call2(data)
  693. m = re.search(r'"movie_titles" data-movieid=(\d+)><div class="en">([^<]+)</div><div class="lv translated">([^<]+)</div>', r)
  694. if m:
  695. title1 = m.group(2)
  696. title2 = m.group(3)
  697. else:
  698. m = re.search('<meta name="dr:say:title" content="([^"]+)">', r, re.IGNORECASE)
  699. title1 = title2 = m.group(1) if m else "Video"
  700. nfo["title"] = title2
  701. nfo["originaltitle"] = title1
  702. if nfo["originaltitle"] and not nfo["title"]:
  703. nfo["title"] = nfo["originaltitle"]
  704. if 'episode_switcher_title' in r:
  705. title2 = title2.replace("\xe2\x80\x93", "-")
  706. if " - " in title2:
  707. nfo["set"] = title2.split(" - ")[0]
  708. else:
  709. nfo["set"] = tt('<div class="movie_titles"><div class="en">(.+?)<', r, title2)
  710. m = re.search('<div class="serial_switcher_banner active".+?<div class="episode_titlez_design17">([^<]+)</div><div class="episode_number_design17">([^<]+)</div>', r)
  711. if m:
  712. ep1 = m.group(1)
  713. ep2 = m.group(2)
  714. nfo["title"] = "%s - %s(%s)"%(nfo["set"], ep1, ep2)
  715. nfo["originaltitle"] = nfo["originaltitle"] + "(%s)" % ep2
  716. m = re.search("S(\d+)E(\d+)", ep2)
  717. if m:
  718. nfo["season"] = m.group(1)
  719. nfo["eposode"] = m.group(2)
  720. nfo["thumb"] = tt('<meta name="og:image" content="([^"]+)"', r,"")
  721. nfo["thumb"] = nfo["thumb"].replace("http:", "https:")
  722. nfo["year"] = tt('movie-informatio-title">Gads<.+?content">([^<]+)<', r, "")
  723. nfo["runtime"] = tt('movie-informatio-title">Garums<.+?content">([^<]+)<', r, "")
  724. nfo["quality"] = tt('movie-informatio-title">Kvalitāte<.+?content">([^<]+)<', r, "")
  725. nfo["genre"]=tt('movie-informatio-title">Žanrs<.+?content">([^<]+)<', r, "")
  726. nfo["director"] = tt('movie-informatio-title">Režisors<.+?content">([^<]+)<', r, "")
  727. nfo["actor"] = tt2('movie-informatio-title">Aktieri<.+?content">([^<]+)<', r, "")
  728. nfo["language"] = tt2('movie-informatio-title">Valodas*<.+?content">([^<]+)<', r, "")
  729. nfo["subtitles"] = tt2('movie-informatio-title">Subtitri<.+?content">([^<]+)<', r, "")
  730. nfo["plot"] = tt('movie-informatio-title">Apraksts<.+?content">([^<]+)<', r, "")
  731. nfo["tagline"] = nfo["plot"]
  732. return nfo
  733. def get_stream_url2(self,data):
  734. video_id=data[data.find("/")+1:]
  735. if not self.is_logedin2():
  736. if not self.login2():
  737. return []
  738. #data2 = self.get_noma_url(video_id)
  739. nfo = self.get_info2(data)
  740. title = util.nfo2title(nfo)
  741. desc = util.nfo2desc(nfo)
  742. img = nfo["thumb"]
  743. #xml = util.nfo2xml(nfo)
  744. url = "https://www.lattelecom.tv/xmls/%s.xml"%video_id
  745. headers = self.headers2
  746. headers["Cookie"] = self.session_id
  747. response = urllib2.urlopen(urllib2.Request(url, headers=headers))
  748. r = response.read()
  749. servers = re.findall("(?s)<origin>([^<]+)</origin>", r)
  750. streams_xml = re.findall('<stream quality="\w+">(mp4:\w+(\w\w)_(\w\w).mp4)</stream>',r)
  751. resource_id = re.search("(?s)<resource_id>([^<]+)</resource_id>", r).group(1)
  752. token = re.search("(?s)<auth_token>([^<]+)</auth_token>", r).group(1)
  753. streams=[]
  754. captions = []
  755. llist = ["fr","en","ru","lv"]
  756. for s in re.findall('<subtitles code="([^"]+)">([^<]+)</subtitles>', r, re.DOTALL):
  757. sub = {}
  758. sub["url"] = s[1]
  759. sub["lang"] = s[0]
  760. sub["name"] = "captions (vtt)"
  761. sub["type"] = "vtt"
  762. sub["order"] = llist.index(sub["lang"])*10 if sub["lang"] in llist else 0
  763. captions.append(sub)
  764. captions = sorted(captions,key=lambda item: item["order"],reverse=True)
  765. for s in streams_xml:
  766. for server in servers:
  767. stream = util.item()
  768. server2 = self.load_balancer(server)
  769. url = "http://%s/mobile-vod/%s/playlist.m3u8?resource_id=%s&auth_token=%s"%(server2,s[0],resource_id,token)
  770. # TODO Engima2 gstreamer vajag lai padod playlist nevis chunklist
  771. # r3 = self._http_request(url)
  772. # sss = re.findall(r"#EXT-X-STREAM-INF:.*?BANDWIDTH=(\d+).*?\n(.+?)$", r3, re.IGNORECASE | re.MULTILINE)
  773. # if sss:
  774. # url2 = sss[0][1]
  775. # stream["headers"] = {"Referer":url}
  776. # if url2.startswith("http"):
  777. # url = url2
  778. # else:
  779. # url = util.hls_base(url)+url2
  780. stream["url"]=url
  781. stream["lang"]=s[1]
  782. stream["quality"]=s[2]
  783. stream["name"]=title
  784. stream["desc"]=desc
  785. stream["img"] = img
  786. stream["nfo"] = {"movie":nfo}
  787. stream["type"]="hls" #stream_type(url)
  788. stream["subs"] = []
  789. for c in captions:
  790. c2= c.copy()
  791. #c2["url"] ="http://%s/mobile-vod/%s/%s?resource_id=%s&auth_token=%s"%(server2,s[0],c["url"],resource_id,token)
  792. c2["url"] ="http://%s/mobile-vod/%s/%s"%(server2,s[0],c["url"])
  793. stream["subs"].append(c2)
  794. pass
  795. streams.append(stream)
  796. break # TODO ņem tikai pirmo serveri, varētu pārbaudit, kurš no tiem strādā, kurš ne
  797. return streams
  798. #data = {}
  799. #data["server"] = re.findall("(?s)<origin>([^<]+)</origin>", r)[1]
  800. #data["language"]=re.findall('(?s)<language code="([^"]+)">', r)
  801. #data["language"]="lv" if "lv" in data["language"] else "ru" if "ru" in data["language"] else "en"
  802. #data["qs"]=re.findall('(?s)<stream quality="([^"]+)">([^<]+)</stream>', r)
  803. #data["qs"]=dict(data["qs"])
  804. #qs = data["qs"].keys()
  805. #data["quality"] = "hd" if "hd" in qs else "hq" if "hq" in qs else "mhq" if "mhq" in qs else "lq"
  806. #data["mp4"] = data["qs"][data["quality"]]
  807. #data["token"] = re.search("(?s)<auth_token>([^<]+)</auth_token>", r).group(1)
  808. #data["resource_id"]=re.search("(?s)<resource_id>([^<]+)</resource_id>", r).group(1)
  809. #data["server"]=self.load_balancer(data["server"])
  810. #data["hls"] = "http://%s/mobile-vod/%s/playlist.m3u8?resource_id=%s&auth_token=%s"%(data["server"],data["mp4"],data["resource_id"],data["token"])
  811. ##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"])
  812. ### wwww.lattelecom.tv izsaukumi
  813. def login2(self,user="",password=""):
  814. """Login in to site, create session cookies"""
  815. if not user: user=self.options["user"]
  816. if not password: password = self.options["password"]
  817. url0 = "https://www.lattelecom.tv"
  818. class NoRedirectHandler(urllib2.HTTPRedirectHandler):
  819. def http_error_302(self, req, fp, code, msg, headers):
  820. infourl = urllib.addinfourl(fp, headers, req.get_full_url())
  821. infourl.status = code
  822. infourl.code = code
  823. return infourl
  824. http_error_300 = http_error_302
  825. http_error_301 = http_error_302
  826. http_error_303 = http_error_302
  827. http_error_307 = http_error_302
  828. # Dabūjam sesijas id un url_gif, kas redirektējas uz 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: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
  833. Accept-Language: en-US,en;q=0.5
  834. DNT: 1
  835. Connection: keep-alive
  836. """)
  837. response = urllib2.urlopen(urllib2.Request(url0, headers=headers))
  838. session_id = response.headers["set-cookie"].split(";")[0]
  839. html = response.read()
  840. url_gif = url0 + re.search('(/auth/\d+\.gif)', html).group(1)
  841. # Dabūtjam auth_url
  842. headers = headers2dict("""
  843. Host: www.lattelecom.tv
  844. User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; rv:46.0) Gecko/20100101 Firefox/46.0
  845. Accept: image/png,image/*;q=0.8,*/*;q=0.5
  846. Accept-Language: en-US,en;q=0.5
  847. DNT: 1
  848. Referer: https://www.lattelecom.tv/
  849. """)
  850. headers["Cookie"] = session_id
  851. urllib2.install_opener(urllib2.build_opener(NoRedirectHandler()))
  852. response = urllib2.urlopen(urllib2.Request(url_gif, headers=headers))
  853. if response.code == 302:
  854. url_auth = response.headers["location"]
  855. else:
  856. self.error = u"auth.gif nenostrādāja"
  857. #raise u"auth.gif nenostrādāja"
  858. return False
  859. # Pierakstāmies iekš auth.lattelecom.lv
  860. headers = headers2dict("""
  861. Host: auth.lattelecom.lv
  862. User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; rv:46.0) Gecko/20100101 Firefox/46.0
  863. Accept: image/png,image/*;q=0.8,*/*;q=0.5
  864. Accept-Language: en-US,en;q=0.5
  865. DNT: 1
  866. Referer: https://www.lattelecom.tv/
  867. """)
  868. response = urllib2.urlopen(urllib2.Request(url_auth, headers=headers))
  869. if not response.code == 302:
  870. self.error = u"pierakstīšanās auth.lattelecom.lv nenostrādāja"
  871. return False
  872. #raise "pierakstīšanās auth.lattelecom.lv nenostrādāja"
  873. # Mēģinam ielogoties
  874. headers = headers2dict("""
  875. Host: www.lattelecom.tv
  876. User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; rv:46.0) Gecko/20100101 Firefox/46.0
  877. Accept: text/javascript, application/javascript, application/ecmascript, application/x-ecmascript, */*; q=0.01
  878. Accept-Language: en-US,en;q=0.5
  879. DNT: 1
  880. X-Requested-With: XMLHttpRequest
  881. Referer: https://www.lattelecom.tv/
  882. """)
  883. headers["Cookie"] = session_id
  884. #data = "login=yes&email=%s&passw=%s"%(user,password)
  885. url = "https://www.lattelecom.tv/login.json?callback=jQuery111303344749731668816_1463817318435&username=%s&password=%s&captcha=&sid=&_="%(user,password)
  886. req = urllib2.Request(url, headers=headers)
  887. response = urllib2.urlopen(req)
  888. #with open("auth.htm","w") as f: f.write(response.read())
  889. if not response.code == 200:
  890. #self.error = u"kļūda ielogojoties"
  891. raise Exception(u"kļūda ielogojoties")
  892. html = response.read()
  893. if not '"success":true' in html:
  894. err = re.search('"error":"(.+?)"',html).group(1) if re.search('"error":"(.+?)"',html) else ""
  895. raise Exception(u"Kļūda ielogojoties - %s"%err.decode("utf8"))
  896. self.session_id = session_id
  897. self.headers2["Cookie"] = "%s; "%(self.session_id)
  898. self.error = ""
  899. return True
  900. def check_logedin2(self):
  901. if not self.session_id:
  902. return False
  903. else:
  904. url = "https://www.lattelecom.tv/profils"
  905. response = urllib2.urlopen(urllib2.Request(url, headers=self.headers2))
  906. if response.code == 200:
  907. return True
  908. else:
  909. self.session_id = ""
  910. return False
  911. def is_logedin2(self):
  912. if self.session_id:
  913. return True
  914. else:
  915. return False
  916. def load_balancer(self,server,streams=[]):
  917. headers = headers2dict("""
  918. Connection: keep-alive
  919. User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/50.0.2661.102 Safari/537.36
  920. X-Requested-With: ShockwaveFlash/21.0.0.242
  921. """)
  922. url = "http://%s/loadbalancer"%server
  923. response = urllib2.urlopen(urllib2.Request(url, headers=headers))
  924. r = response.read()
  925. statuss = re.search("<status>(\d+)</status>",r).group(1)
  926. edge = re.search("<edge>([^<>]+)</edge>",r).group(1)
  927. return edge
  928. def test_hls(self,url):
  929. headers = headers2dict("""
  930. Connection: keep-alive
  931. User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/50.0.2661.102 Safari/537.36
  932. """)
  933. try:
  934. response = urllib2.urlopen(urllib2.Request(url, headers=headers))
  935. except Exception as ex:
  936. print "hls failed: %s %s"%(ex.getcode(),url)
  937. return False
  938. if response.code == 200:
  939. html = response.read()
  940. url0 = re.search("(http://[^/]+/)",url).group(1)
  941. chunklist = re.search("(chunklist.+)",html).group(1).strip()
  942. url2 = url.split('/')[:-1]
  943. url2 ="/".join(url2)+"/"+chunklist
  944. try:
  945. response2 = urllib2.urlopen(urllib2.Request(url2, headers=headers))
  946. except Exception as ex:
  947. print "hls chunk failed: %s %s"%(ex.getcode(),url2)
  948. return False
  949. if response2.code == 200:
  950. return True
  951. else:
  952. return False
  953. else:
  954. return False
  955. if __name__ == "__main__":
  956. c = Source()
  957. from subprocess import call
  958. c.get_info2(sys.argv[1])
  959. sys.exit()
  960. if len(sys.argv)>1 and not "ltc::" in sys.argv[1]:
  961. vid = vid2 = sys.argv[1]
  962. password = sys.argv[2]
  963. print "login - %s"%c.login("ivars777",password)
  964. #vid = "1069"
  965. #vid = "1462566072086"
  966. #channelid="101"
  967. #vid = "1350462656767"
  968. #data = c.get_stream_url(vid,"vod")
  969. #call([r"c:\Program Files\VideoLAN\VLC\vlc.exe",data["stream"]])
  970. #pass
  971. print "login2 - %s"%c.login2("ivars777",password)
  972. #vid2 = "animation/ultimate_avengers_ii"
  973. #vid2 = "animation/ice_age"
  974. #vid2 = "tiesraide/ltv1"
  975. #vid2 = "arhivs/1456521417815"
  976. streams = c.get_stream_url2(vid2)
  977. stream = streams[-1]
  978. print
  979. #for s in data:
  980. #call([r"c:\Program Files\VideoLAN\VLC\vlc.exe",stream["url"]])
  981. cmd = ["ffplay.exe",
  982. "-headers","Referer:%s"%(quote(stream["headers"]["Referer"])),
  983. "-headers","Connection:Keep-Alive",
  984. stream["url"]]
  985. print " ".join(cmd)
  986. call(cmd)
  987. pass
  988. else:
  989. if len(sys.argv)>1:
  990. data= sys.argv[1]
  991. else:
  992. data = "ltc::home"
  993. content = c.get_content(data)
  994. for item in content:
  995. print item
  996. #cat = api.get_categories(country)
  997. #chan = api.get_channels("lv")
  998. #prog = api.get_programs(channel=6400)
  999. #prog = api.get_programs(category=55)
  1000. #seas = api.get_seasons(program=6453)
  1001. #str = api.get_streams(660243)
  1002. #res = api.get_videos(802)
  1003. #formats = api.getAllFormats()
  1004. #det = api.detailed("1516")
  1005. #vid = api.getVideos("13170")
  1006. pass