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