Python module (submodule repositary), which provides content (video streams) from various online stream sources to corresponding Enigma2, Kodi, Plex plugins

ltc.py 50KB

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