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

tvdom.py 13KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286
  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. try:
  9. import json
  10. except:
  11. import simplejson as json
  12. import urllib2, urllib
  13. import datetime, re, sys,os
  14. from collections import OrderedDict
  15. import ssl
  16. if "_create_unverified_context" in dir(ssl):
  17. ssl._create_default_https_context = ssl._create_unverified_context
  18. from SourceBase import SourceBase
  19. API_URL = 'http://replay.lsm.lv/'
  20. headers2dict = lambda h: dict([l.strip().split(": ") for l in h.strip().splitlines()])
  21. headers0 = headers2dict("""
  22. User-Agent: Mozilla/5.0 (Linux; U; Android 4.4.4; Nexus 5 Build/KTU84P) AppleWebkit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30
  23. """)
  24. import HTMLParser
  25. h = HTMLParser.HTMLParser()
  26. class Source(SourceBase):
  27. def __init__(self,country="lv",cfg_path=None):
  28. self.name = "tvdom"
  29. self.title = "TVDom.tv"
  30. self.img = "https://tvdom.tv/front/assets/images/logo.png"
  31. self.desc = "TVDom.tv portāla satura skatīšanās"
  32. self.headers = headers0
  33. self.country=country
  34. self.session = None
  35. self.token = None
  36. cur_directory = os.path.dirname(os.path.abspath(__file__))
  37. if not cfg_path: cfg_path = cur_directory
  38. self.config_file = os.path.join(cfg_path,self.name+".cfg")
  39. self.options = OrderedDict([("user","lietotajs"),("password","parole")])
  40. self.options_read()
  41. def login(self,user="",password=""):
  42. self.options_read()
  43. if not user: user=self.options["user"]
  44. if not password: password = self.options["password"]
  45. headers = headers2dict("""
  46. User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; rv:49.0) Gecko/20100101 Firefox/49.0
  47. Accept: */*
  48. Accept-Language: en-US,en;q=0.5
  49. Accept-Encoding: gzip, deflate, br
  50. Content-Type: application/x-www-form-urlencoded; charset=UTF-8
  51. X-Requested-With: XMLHttpRequest
  52. Referer: https://tvdom.tv/
  53. """)
  54. url = "https://tvdom.tv/infinity/on_register_user"
  55. params = "email=%s&password=%s&remember=false&auth_type=login"%(user,password)
  56. import requests
  57. try:
  58. from requests.packages.urllib3.exceptions import InsecureRequestWarning
  59. requests.packages.urllib3.disable_warnings(InsecureRequestWarning)
  60. except:
  61. pass
  62. r = requests.post(url, data=params, headers=headers)
  63. js = json.loads(r.content)
  64. if 'success' in r.content:
  65. self.token = js["access_token"]
  66. if 'PHPSESSID' in r.cookies:
  67. self.session = r.cookies["PHPSESSID"]
  68. return True
  69. else:
  70. raise Exception(js["error"])
  71. def get_content(self, data):
  72. print "[tvdom] get_content:", data
  73. source,data,path,plist,clist,params,qs = self.parse_data(data)
  74. lang = qs["lang"] if "lang" in qs else self.country
  75. content=[]
  76. content.append(("..return", "back","","Return back"))
  77. if clist=="home":
  78. content.extend([
  79. ("Live stream", "tvdom::tiesraides","","TV live streams"),
  80. ("Archive - categories", "tvdom::arhivs","","Video archive by categories"),
  81. ("Search", "tvdom::search/?srch-term={0}","","Search archive"),
  82. #("Archive - all", "tvdom::arhivs_all","","Video archive all"),
  83. ])
  84. return content
  85. ### Tiesraides kanalu saraksts ###
  86. elif data=="tiesraides":
  87. ch_name = {"49":"Дом Кино","50":"Карусель","51":"Время","52":"Музыка Первого","53":"Телекафе"}
  88. url = "https://tvdom.tv/"
  89. r = self._http_request(url)
  90. #channels1 = re.findall(r'data-xprs_status="\d" data-href="/tiesraides/([^/]+)/[^"]+">.+?src="([^"]+)" alt="([^"]+)">', r, re.DOTALL)
  91. channels2 = re.findall(r'<a class="channel-name">([^<]*)</a>\s+<div class="redirect-to-url" data-href="/tiesraides/([^/]+)/[^"]*">.+?<img style="width:100%;" src="([^"]+)".+?<h3>([^<]+)</h3>.+?<p class="unix">([^<]+)</p>', r, re.DOTALL)
  92. channels = {}
  93. for item in channels2:
  94. title = item[0]
  95. title = h.unescape(title.decode("utf8")).encode("utf8")
  96. img = "https://tvdom.tv"+item[2]
  97. data2 = "tiesraides/%s/"%item[1]
  98. desc = "%s\n%s\n%s"%(title,item[3],item[4])
  99. channels[item[1]]={"title":title,"img":img,"desc":desc}
  100. #content.append((title,self.name+"::"+data2,img,desc))
  101. for r2 in re.findall(r'<div class="thumbnail-menu pull-left updater"(.+?)</div>\s+</div>', r, re.DOTALL):
  102. ch = re.search('data-href="/tiesraides/([^/]+)/[^"]*"', r2, re.DOTALL).group(1)
  103. data2 = "tiesraides/"+ch
  104. m = re.search('src="(.+?)" alt="(.+?)">', r2, re.DOTALL)
  105. title = m.group(2)
  106. img = m.group(1)
  107. desc = title
  108. if ch in channels:
  109. img = channels[ch]["img"]
  110. desc = channels[ch]["desc"]
  111. else:
  112. m = re.search('<img src="([^"]+)" alt="aaaaaa([^"]+)"><h3>.+<p class="unix">([^<]+)</p>', r2, re.DOTALL)
  113. if m:
  114. desc = "%s\n%s\n%s"%(title,m.group(1),m.group(3))
  115. img = m.group(2)
  116. content.append((title,self.name+"::"+data2,img,desc))
  117. return content
  118. elif clist == "tiesraides":
  119. if not self.session:
  120. self.login()
  121. url = "https://tvdom.tv/" + data
  122. headers = self.headers
  123. headers["Cookie"] = "PHPSESSID=%s; neverending_story=1;"%self.session
  124. r = self._http_request(url,headers=headers)
  125. m = re.search("var streamConnectionUrl = '([^']+)'", r, re.DOTALL)
  126. if m:
  127. data2 = m.group(1)
  128. else:
  129. return ("No stream found %s"%data,"","","No stream found")
  130. m = re.search('title: "([^"]+)"', r, re.DOTALL)
  131. title = m.group(1) if m else data2
  132. m = re.search('<div id="panel">([^<]+)<', r, re.DOTALL)
  133. desc = m.group(1) if m else title
  134. m = re.search('<div id="panel">([^<]+)<', r, re.DOTALL)
  135. desc = m.group(1) if m else title
  136. m = re.search('var promo_image *= "([^"]+)', r, re.DOTALL)
  137. img = m.group(1) if m else ""
  138. return (title,data2,img,desc)
  139. ### Search ###
  140. elif clist=="search":
  141. url = "https://tvdom.tv/" + data
  142. r = self._http_request(url)
  143. for item in re.findall(r'<li data-xprs-search="\d+" data-href="([^"]+)".*?<img class="img-responsive" src="([^"]+)".*?<h3>([^<]+)</h3>.*?<h5>([^<]+)</h5>', r, re.DOTALL):
  144. title = item[2] + " "+ item[3]
  145. title = h.unescape(title.decode("utf8")).encode("utf8")
  146. img = "https://tvdom.tv" + item[1]
  147. data2 = item[0][1:]
  148. desc = title
  149. content.append((title,self.name+"::"+data2,img,desc))
  150. return content
  151. ### Arhīva kategorijas ###
  152. elif data=="arhivs":
  153. url = "https://tvdom.tv/"+data
  154. r = self._http_request(url)
  155. for item in re.findall('pointer" href="/([^"]+)">([^<]+)</a>', r, re.DOTALL):
  156. title = item[1]
  157. title = h.unescape(title.decode("utf8")).encode("utf8")
  158. img = ""
  159. data2 = item[0]
  160. desc = title
  161. content.append((title,self.name+"::"+data2,img,desc))
  162. return content
  163. ### Arhīva kategorijas programmas ###
  164. elif clist=="arhivs":
  165. url = "https://tvdom.tv/"+data
  166. r = self._http_request(url)
  167. for item in re.findall(r"""<li><div class="thumbnail pull-left" onclick="location\.href='([^']+)'" data-toggle="popover" title="([^"]+)" data-content="([^"]*)".+?<img class="img-responsive archive-image" src="([^"]+)""", r, re.DOTALL):
  168. #for item in re.findall(r"""<li><div class="thumbnail pull-left" onclick="location\.href='([^']+)'" data-toggle="popover" title="([^"]+)" data-content="([^"]+)".+?<img class="img-responsive archive-image" src="([^"]+)""", r, re.DOTALL):
  169. title = item[1].replace("&lt;br&gt;"," - ")
  170. title = h.unescape(title.decode("utf8")).encode("utf8")
  171. img = "https://tvdom.tv"+item[3]
  172. data2 = item[0][1:]
  173. desc = item[2]
  174. content.append((title,self.name+"::"+data2,img,desc))
  175. return content
  176. ### Arhīva programmas video saraksts ###
  177. elif clist=="play_arhivs" and len(data.split("/"))==3 and not re.search("_\d+",plist[2]):
  178. url = "https://tvdom.tv/"+data
  179. r = self._http_request(url)
  180. vid=re.search(r"id:(\d+), type: type", r, re.DOTALL).group(1)
  181. data2 = data+"_"+vid
  182. m = re.search('program_title = "([^"]+)"', r, re.DOTALL)
  183. title = m.group(1) if m else data2
  184. m = re.search('<a class="episode">Pārraides laiks ēterā: <span>([^<]+)</span></a>', r, re.DOTALL)
  185. datums = m.group(1) if m else ""
  186. title = title + " " + datums
  187. m = re.search('<div id="panel">([^<]+)<', r, re.DOTALL)
  188. desc = m.group(1) if m else title
  189. m = re.search('<div id="panel">([^<]+)<', r, re.DOTALL)
  190. desc = m.group(1) if m else title
  191. m = re.search('var share_image *= "([^"]+)', r, re.DOTALL)
  192. img = m.group(1) if m else ""
  193. content.append((title,self.name+"::"+data2,img,desc))
  194. i = r.find('<span class="slider-top-title"')
  195. if i>0: r = r[:i]
  196. for item in re.findall('<div class="col-md-9 redirect-to-url same-event" data-href="/([^"]+)">.+?image" src="([^"]+)".+?<h3 class="same-title">([^<]+)</h3>.*?<h5 class="same-online">([^<]+)</h5>', r, re.DOTALL):
  197. title = item[2] + " " + item[3]
  198. title = h.unescape(title.decode("utf8")).encode("utf8")
  199. img = "https://tvdom.tv"+item[1]
  200. data2 = item[0]
  201. desc = title # TODO
  202. content.append((title,self.name+"::"+data2,img,desc))
  203. return content
  204. ### Arhīva video
  205. elif clist=="play_arhivs" and len(data.split("/"))==3 and re.search("_\d+",plist[2]):
  206. url = "https://tvdom.tv/" + data
  207. headers = self.headers
  208. headers["Cookie"] = "PHPSESSID=%s; neverending_story=1;"%self.session
  209. r = self._http_request(url,headers=headers)
  210. m = re.search('var streamConnectionUrl = "([^"]+)"', r, re.DOTALL)
  211. if m:
  212. data2 = m.group(1)
  213. else:
  214. return ("No stream found %s"%data,"","","No stream found")
  215. m = re.search('program_title = "([^"]+)"', r, re.DOTALL)
  216. title = m.group(1) if m else data2
  217. m = re.search('<a class="episode">Pārraides laiks ēterā: <span>([^<]+)</span></a>', r, re.DOTALL)
  218. datums = m.group(1) if m else ""
  219. title = title + " " + datums
  220. m = re.search('<div id="panel">([^<]+)<', r, re.DOTALL)
  221. desc = m.group(1) if m else title
  222. m = re.search('<div id="panel">([^<]+)<', r, re.DOTALL)
  223. desc = m.group(1) if m else title
  224. m = re.search('var share_image *= "([^"]+)', r, re.DOTALL)
  225. img = m.group(1) if m else ""
  226. return (title,data2,img,desc)
  227. def is_video(self,data):
  228. source,data,path,plist,clist,params,qs = self.parse_data(data)
  229. cmd = data.split("/")
  230. if cmd[0] in ("tiesraides") and len(cmd)>1:
  231. return True
  232. elif cmd[0]=="play_arhivs" and len(cmd)==3 and re.search("_\d+",plist[2]):
  233. return True
  234. else:
  235. return False
  236. def call(self, data,headers=headers0,lang=""):
  237. if not lang: lang = self.country
  238. url = API_URL%lang + data
  239. #print "[TVPlay Api] url: ",url
  240. result = []
  241. content = self._http_request(url)
  242. return content
  243. if __name__ == "__main__":
  244. country= "lv"
  245. c = Source(country)
  246. if len(sys.argv)>1:
  247. data= sys.argv[1]
  248. else:
  249. data = "home"
  250. content = c.get_content(data)
  251. for item in content:
  252. print item
  253. #cat = api.get_categories(country)
  254. #chan = api.get_channels("lv")
  255. #prog = api.get_programs(channel=6400)
  256. #prog = api.get_programs(category=55)
  257. #seas = api.get_seasons(program=6453)
  258. #str = api.get_streams(660243)
  259. #res = api.get_videos(802)
  260. #formats = api.getAllFormats()
  261. #det = api.detailed("1516")
  262. #vid = api.getVideos("13170")
  263. pass