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

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268
  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 requests
  13. import datetime, re, sys,os
  14. import ConfigParser
  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. import resolver
  20. try:
  21. import util
  22. except:
  23. sys.path.insert(0,'..')
  24. import util
  25. from YouTubeVideoUrl import YouTubeVideoUrl
  26. headers2dict = lambda h: dict([l.strip().split(": ") for l in h.strip().splitlines()])
  27. import HTMLParser
  28. h = HTMLParser.HTMLParser()
  29. class Source(SourceBase):
  30. def __init__(self, country="",cfg_path=None):
  31. self.name = "lmt"
  32. self.title = "LMT straume"
  33. self.img = "lmt.png"
  34. self.desc = "LMT straume - dažādi video latviesu valodā"
  35. self.headers = headers2dict("""
  36. User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; rv:46.0) Gecko/20100101 Firefox/46.0
  37. Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
  38. Accept-Language: en-US,en;q=0.5
  39. """)
  40. self.headers2 = headers2dict("""
  41. User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; rv:46.0) Gecko/20100101 Firefox/46.0
  42. X-Requested-With: XMLHttpRequest
  43. Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
  44. """)
  45. self.url = "http://straume.lmt.lv/lv/"
  46. ######### Entry point ########
  47. def get_content(self, data):
  48. print "[lmt] get_content:", data
  49. source, data, path, plist, clist, params, qs = self.parse_data(data)
  50. content = []
  51. content.append(("..return", "back","back.png","Return back"))
  52. if clist=="home":
  53. content.extend([
  54. ("Meklēt", "lmt::meklet?q={0}","","Meklēt"),
  55. ("Straumes", "lmt::straumes","","Tiešraides un aktuāli video"),
  56. #("TV", "lmt::tv","","TV tiešraides (tikai LMT tīklā)"),
  57. ("Jaunākie", "lmt::video/jaunakie?videoPage=1", "", "Visu žanru jaunākie video"),
  58. ("Bērniem", "lmt::video/berniem?videoPage=1", "", "Sports"),
  59. ("Sports", "lmt::video/sports?videoPage=1", "", "Sports"),
  60. ("Kultūra un māksla", "lmt::video/kultura?videoPage=1", "", "Kultūra un māksla"),
  61. ("Konferences", "lmt::video/konferences?videoPage=1", "", "Konferences"),
  62. ("Raidījumi", "lmt::video/raidijumi?videoPage=1", "", "Raidījumi"),
  63. ("Notikumi", "lmt::video/notikumi?videoPage=1", "", "Notikumi"),
  64. ("Filmas un seriāli", "lmt::video/filmas?videoPage=1", "", "Filmas un seriāli"),
  65. ("Dažādi video", "lmt::video/dazadi?videoPage=1", "", "Dažādi video"),
  66. ("Viedtelevīzija", "lmt::video/viedtelevizija?videoPage=1", "", "Viedtelevīzija"),
  67. ])
  68. return content
  69. elif clist in ("meklet","video", "straumes","video-saraksts"):
  70. r=self.call(data)
  71. result = re.findall('<a class="video-picture" (.+?)</li>', r, re.IGNORECASE | re.MULTILINE)
  72. for r2 in result:
  73. m = re.search('<a class="video-title" href="/lv/([^"]+)">([^<]+)<', r2)
  74. title = m.group(2)
  75. data2 = m.group(1)
  76. m = re.search("([^ ]+) 2x", r2)
  77. if m:
  78. img = m.group(1)
  79. else:
  80. m = re.search('<img src="([^"]+)', r2)
  81. img = m.group(1) if m else ""
  82. if img.startswith("//"):
  83. img = "http:" + img
  84. m = re.search('<span class="playlist-overlay">([^<]+)</span>', r2)
  85. overlay = m.group(1) if m else ""
  86. m = re.search('<span class="badge badge-[^>]+>([^<]+)(<[^>]+>([^<]+))*</span>', r2, re.IGNORECASE)
  87. badge = ""
  88. if m:
  89. badge = m.group(1)
  90. if m.group(3):
  91. badge = badge + m.group(3)
  92. categories = re.findall('<span class="category-title">([^<]+)</span>', r2)
  93. categories = "".join(categories)
  94. if overlay:
  95. title = "%s [%s]"%(title,overlay)
  96. if badge:
  97. title = "%s [%s]"%(title,badge)
  98. desc = title
  99. if categories:
  100. desc = desc + "\n"+ categories
  101. content.append((title,self.name+"::"+data2,img,desc))
  102. m = re.search("videoPage=(\d+)",data)
  103. if m:
  104. page = int(m.group(1))+1
  105. data2 = re.sub(r"videoPage=\d+", r"videoPage=%s"%page, data)
  106. content.append(("Next page",self.name+"::"+data2,"next.png","Next page"))
  107. #print content
  108. return content
  109. ### kaut kas neparedzets ###
  110. else:
  111. return content
  112. def is_video(self,data):
  113. source,data,path,plist,clist,params,qs = self.parse_data(data)
  114. if not clist in ("meklet","video", "straumes","video-saraksts","home"):
  115. return True
  116. def call(self, data,params=None,headers=None,lang=""):
  117. if not headers: headers = self.headers
  118. url = self.url+data
  119. r = requests.get(url,headers = headers)
  120. return r.content
  121. #result = self._http_request(url,params,headers=headers)
  122. # return result
  123. def get_streams(self,data):
  124. print "[lmt] get_streams:", data
  125. if not self.is_video(data):
  126. return []
  127. source,data,path,plist,clist,params,qs = self.parse_data(data)
  128. r = self.call(path)
  129. title = re.search("<h1>(.+?)</h1", r, re.IGNORECASE).group(1)
  130. m = re.search('<a class="category-title".+?[^>]+>([^<]+)<', r, re.IGNORECASE | re.DOTALL)
  131. categories = m.group(1) if m else ""
  132. m = re.search('<span class="category-title">([^<]+)</span>.+?</p>', r, re.IGNORECASE | re.DOTALL)
  133. if m:
  134. categories = categories + m.group(1)
  135. if categories:
  136. tite = "%s [%s]"%(title,categories)
  137. img = re.search('<meta property="twitter:image" content="([^"]+)">', r, re.IGNORECASE | re.DOTALL).group(1)
  138. if img.startswith("//"):
  139. img = "http:" + img
  140. desc = title + "\n" + re.search('<meta property="og:description" content="([^"]+)">', r, re.IGNORECASE | re.DOTALL).group(1)
  141. m = re.search('file: "([^"]+)"', r, re.IGNORECASE)
  142. if m:
  143. # LMT file
  144. data2 = m.group(1)
  145. if not data2.startswith("http"):
  146. data2 = "http:" + data2
  147. stream = util.item()
  148. stream["name"] = title
  149. stream["url"] = data2
  150. stream["img"] = img
  151. stream["desc"] = desc
  152. stream["resolver"] = "lmt"
  153. return [stream]
  154. elif re.search(r'src="(http*:)*//www.youtube.com/embed/([\w-]+).*"', r):
  155. # Youtube
  156. m = re.search(r'src="(http*:)*//www.youtube.com/embed/([\w-]+).*"', r)
  157. video_id = m.group(2)
  158. #http://www.youtube.com/embed/RUyQ_JJ6A84?rel=0&fs=1&wmode=transparent
  159. data2 = YouTubeVideoUrl().extract(video_id)
  160. s = util.item()
  161. s["name"] = title
  162. s["url"] = data2
  163. s["desc"] = desc
  164. s["img"] = img
  165. s["resolver"] = "lmt"
  166. return [s]
  167. elif 'src="http://cdn.tiesraides.lv/lmtstraume.lv/' in r:
  168. m = re.search('src="(http://cdn\.tiesraides\.lv/[^"]+)"',r)
  169. url = m.group(1)
  170. # src="http://cdn.tiesraides.lv/lmtstraume.lv/live-record2-ip/40?c=614127284dcd58d8a84afcf498a3ac7a&v=1405"
  171. r = self._http_request(url)
  172. #http://edge-telia2.tiesraides.lv/live-record2/lmtstraume.lv.40_1/manifest.f4m
  173. m = re.search("'(http://.+?\.m3u8)'",r)
  174. data2 = m.group(1) if m else ""
  175. s = util.item()
  176. s["name"] = title
  177. s["url"] = data2
  178. s["desc"] = desc
  179. s["img"] = img
  180. s["resolver"] = "lmt"
  181. return [s]
  182. elif "//live.tiesraides.lv/lmtstraume.lv" in r:
  183. m = re.search('<div class="single-video-item video-picture">.+?src="([^"]+)"', r, re.DOTALL)
  184. url = "http:" + m.group(1)
  185. # src="http://cdn.tiesraides.lv/lmtstraume.lv/live-record2-ip/40?c=614127284dcd58d8a84afcf498a3ac7a&v=1405"
  186. r = self._http_request(url)
  187. #http://edge-telia2.tiesraides.lv/live-record2/lmtstraume.lv.40_1/manifest.f4m
  188. m = re.search("'(http://.+?\.m3u8)'",r)
  189. data2 = m.group(1) if m else ""
  190. s = util.item()
  191. s["name"] = title
  192. s["url"] = data2
  193. s["desc"] = desc
  194. s["img"] = img
  195. s["resolver"] = "lmt"
  196. return [s]
  197. elif "embed.php?salt=" in r:
  198. m = re.search('embed\.php\?salt=([^"]+)"', r)
  199. url = "http://g1.delphi.lv/vfe/data.php?video_id=%s" % m.group(1)
  200. r2 = self._http_request(url)
  201. js = json.loads(r2)
  202. s = util.item()
  203. s["name"] = js["data"]["title"]
  204. s["desc"] = re.sub("<.+?>", "", js["data"]["description"])
  205. s["img"] = js["data"]["poster"]
  206. s["resolver"] = "lmt"
  207. vers = js["data"]["versions"].keys()
  208. ver = "HD" if "HD" in vers else "SD" if "SD" in vers else None
  209. if not ver:
  210. raise Exception("No stream found")
  211. sdata = js["data"]["versions"][ver]
  212. s["url"] = "http:" + sdata[1]["src"]
  213. return [s]
  214. elif re.search('src="(https://www.facebook.com/plugins/video.php[^"]+)', r):
  215. m = re.search('src="(https://www.facebook.com/plugins/video.php[^"]+)', r)
  216. url = m.group(1)
  217. r2 = self._http_request(url)
  218. if not r2:
  219. raise Exception("No stream found")
  220. streams = []
  221. for it in re.findall('"(sd|hd)_src":"([^"]+)', r2):
  222. s = util.item()
  223. s["name"] = tite
  224. s["desc"] = desc
  225. s["img"] = img
  226. s["resolver"] = "lmt"
  227. s["url"] = it[1].replace("\\", "")
  228. s["quality"] = it[0]
  229. return [s]
  230. else:
  231. raise Exception("No stream found")
  232. # streams = resolver.resolve(url)
  233. # for s in streams:
  234. # s["name"] = title
  235. # s["desc"] = desc
  236. # s["img"] = img
  237. # streams.append(s)
  238. # return streams
  239. if __name__ == "__main__":
  240. sys.path.insert(0, os.path.dirname(os.path.dirname(__file__)))
  241. import run
  242. source = Source()
  243. data= sys.argv[1] if len(sys.argv)>1 else source.name+"::home"
  244. if len(sys.argv) > 2:
  245. run.run_cli(source, data)
  246. else:
  247. run.run(source, data)
  248. sys.exit()