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

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262
  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
  14. from SourceBase import SourceBase
  15. import ssl
  16. if "_create_unverified_context" in dir(ssl):
  17. ssl._create_default_https_context = ssl._create_unverified_context
  18. API_URL = 'http://www.filmon.com/'
  19. headers2dict = lambda h: dict([l.strip().split(": ") for l in h.strip().splitlines()])
  20. #User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; rv:46.0) Gecko/20100101 Firefox/46.0
  21. headers0 = headers2dict("""
  22. User-Agent: Mozilla/5.0 (iPhone; CPU iPhone OS 9_2 like Mac OS X) AppleWebKit/601.1 (KHTML, like Gecko) CriOS/47.0.2526.70 Mobile/13C71 Safari/601.1.46
  23. Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
  24. Accept-Language: en-US,en;q=0.5
  25. Accept-Encoding: deflate
  26. Connection: keep-alive
  27. """)
  28. import HTMLParser
  29. h = HTMLParser.HTMLParser()
  30. class Source(SourceBase):
  31. def __init__(self,country="lv",cfg_path=None):
  32. #self.hidden = True
  33. self.name = "filmon"
  34. self.title = "FilmOn"
  35. self.img = "filmon.png"
  36. self.desc = "FilmOn portāla satura skatīšanās"
  37. self.headers = headers0
  38. self.country=country
  39. self.jstv = None
  40. self.session_key = None
  41. self.cookie = None
  42. def get_content(self, data):
  43. print "[filmon] get_content:", data
  44. if "::" in data:
  45. data = data.split("::")[1]
  46. path = data.split("?")[0]
  47. clist = path.split("/")[0]
  48. params = data[data.find("?"):] if "?" in data else ""
  49. qs = dict(map(lambda x:x.split("="),re.findall("\w+=\w+",params)))
  50. lang = qs["lang"] if "lang" in qs else self.country
  51. if not self.jstv:
  52. self.jstv = self.get_tv_channels()
  53. #if not self.session_key: # TODO izskatās, ka strādā bez, vismaz ja nelogojas iekšā, jānočeko
  54. # html = self._http_request("http://www.filmon.com/api/init")
  55. # js = json.loads(html)
  56. # self.session_key = js["session_key"]
  57. content=[]
  58. content.append(("..return", "back","back.png","Return back"))
  59. if clist=="home":
  60. content.extend([
  61. ("Live streams", "filmon::tv","","TV live streams"),
  62. ("Video on demand", "filmon::vod","","Last videos"),
  63. ])
  64. return content
  65. ### TV Groups ###
  66. elif clist in ("tv","home"):
  67. for gr in self.jstv:
  68. title = gr["name"].encode("utf8")
  69. data2 = "group?id=%s"%gr["id"]
  70. img = gr["logo_148x148_uri"].encode("utf8")
  71. desc = gr["description"].encode("utf8")
  72. content.append((title,self.name+"::"+data2,img,desc))
  73. return content
  74. ### TV group channels ###
  75. elif clist=="group":
  76. if "id" in qs:
  77. group_id = qs["id"]
  78. else:
  79. return content
  80. group = None
  81. for gr in self.jstv:
  82. if gr["id"]==group_id:
  83. group = gr
  84. break
  85. if not group:
  86. return content
  87. for ch in group["channels"]:
  88. title = ch["title"].encode("utf8")
  89. data2 = "channel?id=%s"%ch["id"]
  90. img = ch["big_logo"].encode("utf8")
  91. desc = ch["description"].encode("utf8") if ch["description"] else title
  92. content.append((title,self.name+"::"+data2,img,desc))
  93. return content
  94. ### TV Channel ###
  95. elif clist == "channel" or clist == "video":
  96. if "id" in qs:
  97. ch_id = qs["id"]
  98. else:
  99. return ("No stream found %s"%data,"","","No stream found")
  100. ch = self.get_tv_channel_info(ch_id)
  101. if ch["now_playing"]:
  102. current_event = ch["now_playing"]["programme_name"] if "programme_name" in ch["now_playing"] else ""
  103. else:
  104. current_event = ""
  105. title = u"%s - %s"%(ch["title"],current_event)
  106. title = title.encode("utf8")
  107. if current_event:
  108. desc = ch["now_playing"]["programme_description"].encode("utf8")
  109. else:
  110. desc = title
  111. data2 = ""
  112. for t in ("SD","HD"):
  113. for s in ch["streams"]:
  114. if s["name"]==t:
  115. data2 = s["url"].encode("utf8")
  116. break
  117. if data2: break
  118. return (title,data2,"",desc)
  119. ### VOD genres ###
  120. elif path in ("vod","vod/genres"):
  121. data = "vod/genres"
  122. js = self.call(data)
  123. for gr in js["response"]:
  124. title = gr["name"].encode("utf8")
  125. data2 = "vod/search?genre=%s&max_results=30&no_episode=true&start_index=0"%(gr["slug"].encode("utf8"))
  126. img = gr["images"][0]["url"].encode("utf8")
  127. desc = gr["description"].encode("utf8") if gr["description"] else title
  128. content.append((title,self.name+"::"+data2,img,desc))
  129. return content
  130. ### VOD genre videos ###
  131. elif path == "vod/search":
  132. js = self.call(data)
  133. for vid in js["response"]:
  134. title = vid["title"].encode("utf8")
  135. if vid["type"]=="series":
  136. title = "[Series] "+title
  137. data2 = "vod/movie?id=%s&type=%s"%(vid["id"],vid["type"].encode("utf8"))
  138. img = "http://static.filmon.com/assets/"+vid["poster"]["couchdb_url"].encode("utf8")
  139. desc = vid["description"].encode("utf8") if vid["description"] else title
  140. content.append((title,self.name+"::"+data2,img,desc))
  141. start_index = int(qs["start_index"]) if "start_index" in qs else 0
  142. if start_index+js["total"]<js["total_found"]:
  143. start_index += 30
  144. data2 = re.sub("start_index=\d+","start_index=%s"%start_index,data) if "start_index" in qs else data +"&start_index=30"
  145. content.append(("Next page",self.name+"::"+data2,"","Next page"))
  146. return content
  147. ### VOD video sigle/series ###
  148. elif path == "vod/movie":
  149. js = self.call(data)
  150. if js["response"]["type"] == "series":
  151. ids = ",".join(js["response"]["episodes"])
  152. data2 = "vod/movies?ids=%s"%ids
  153. js2 = self.call(data2)
  154. for vid in js2["response"]:
  155. title = vid["title"].encode("utf8")
  156. if vid["type"]=="series":
  157. title = "[Series] "+title
  158. data2 = "vod/movie?id=%s&type=%s"%(vid["id"],vid["type"].encode("utf8"))
  159. img = "http://static.filmon.com/assets/"+vid["poster"]["couchdb_url"].encode("utf8")
  160. desc = vid["description"].encode("utf8") if vid["description"] else title
  161. content.append((title,self.name+"::"+data2,img,desc))
  162. return content
  163. else:
  164. title = js["response"]["title"].encode("utf8")
  165. desc = js["response"]["description"].encode("utf8") if js["response"]["description"] else title
  166. data2 = js["response"]["streams"]["low"]["url"].encode("utf8")
  167. return (title,data2,"",desc)
  168. def is_video(self,data):
  169. if "::" in data:
  170. data = data.split("::")[1]
  171. cmd = data.split("?")
  172. if cmd[0] in ("video","channel"):
  173. return True
  174. elif cmd[0] == "vod/movie" and "type=movie" in data:
  175. return True
  176. else:
  177. return False
  178. def call(self, data,headers=headers0,lang=""):
  179. if not lang: lang = self.country
  180. url = "http://www.filmon.com/api/" + data
  181. #if not "?" in url: url += "?session_key=%s"%self.session_key
  182. #if not "session_key=" in url: url += "&session_key=%s"%self.session_key
  183. #print "[TVPlay Api] url: ",url
  184. result = []
  185. content = self._http_request(url)
  186. if content:
  187. try:
  188. result = json.loads(content)
  189. except Exception, ex:
  190. return None
  191. return result
  192. #----------------------------------------------------------------------
  193. def get_tv_channel_info(self,id):
  194. url = "http://www.filmon.com/ajax/getChannelInfo"
  195. headers = headers2dict("""
  196. Host: www.filmon.com
  197. User-Agent: Mozilla/5.0 (Windows NT 6.1; rv:41.0) Gecko/20100101 Firefox/41.0
  198. Accept: application/json, text/javascript, */*; q=0.01
  199. Accept-Language: en-US,en;q=0.5
  200. Accept-Encoding: deflate
  201. DNT: 1
  202. Content-Type: application/x-www-form-urlencoded; charset=UTF-8
  203. X-Requested-With: XMLHttpRequest
  204. Referer: http://www.filmon.com/tv/live
  205. Connection: keep-alive
  206. Pragma: no-cache
  207. Cache-Control: no-cache
  208. """)
  209. headers["Cookie"] = self.cookie
  210. data = "channel_id=%s&quality=low"%id
  211. response = urllib2.urlopen(urllib2.Request(url, headers=headers,data=data))
  212. html = response.read()
  213. js = json.loads(html)
  214. return js
  215. #----------------------------------------------------------------------
  216. def get_tv_channels(self):
  217. """Get tv channels list"""
  218. headers = headers2dict("""
  219. Host: www.filmon.com
  220. User-Agent: Mozilla/5.0 (Windows NT 6.1; rv:41.0) Gecko/20100101 Firefox/41.0
  221. Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
  222. Accept-Language: en-US,en;q=0.5
  223. Accept-Encoding: deflate
  224. DNT: 1
  225. Connection: keep-alive
  226. """)
  227. url = "http://www.filmon.com/tv"
  228. response = urllib2.urlopen(urllib2.Request(url, headers=headers))
  229. if "set-cookie" in response.headers:
  230. self.cookie = response.headers["set-cookie"]
  231. html = response.read()
  232. s = re.search("(?i)var groups = (.*);", html).groups(1)[0]
  233. js = json.loads(s)
  234. return js
  235. if __name__ == "__main__":
  236. sys.path.insert(0, os.path.dirname(os.path.dirname(__file__)))
  237. import run
  238. source = Source()
  239. data= sys.argv[1] if len(sys.argv)>1 else source.name+"::home"
  240. run.run(source, data)
  241. sys.exit()