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

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