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

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