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

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291
  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, time,re, sys,os
  14. from collections import OrderedDict
  15. from SourceBase import SourceBase
  16. import util
  17. import ssl
  18. ssl._create_default_https_context = ssl._create_unverified_context
  19. headers2dict = lambda h: dict([l.strip().split(": ") for l in h.strip().splitlines()])
  20. import HTMLParser
  21. h = HTMLParser.HTMLParser()
  22. class Source(SourceBase):
  23. def __init__(self,language="en",cfg_path=None):
  24. self.name = "euronews"
  25. self.title = "Euronews"
  26. self.img = "http://pbs.twimg.com/profile_images/732665354242150400/tZsCnjuh_400x400.jpg"
  27. self.desc = "Euronews live and archive"
  28. self.headers = headers2dict("""
  29. User-Agent: Euronews/4.0.126
  30. Content-Type: application/json
  31. Connection: keep-alive
  32. """)
  33. #self.language=language
  34. cur_directory = os.path.dirname(os.path.abspath(__file__))
  35. if not cfg_path: cfg_path = cur_directory
  36. self.config_file = os.path.join(cfg_path,self.name+".cfg")
  37. self.options = OrderedDict([("language","en")])
  38. self.options_read()
  39. self.vid={"1": "News", "2": "European Affairs", "3": "Lifestyle", "4": "Knowledge"}
  40. self.languages = []
  41. try:
  42. self.get_languages()
  43. except:
  44. pass
  45. def login(self,user="",password=""):
  46. return True
  47. def get_content(self, data):
  48. print "[%s] get_content:"%self.name, data
  49. source,data,path,plist,clist,params,qs = self.parse_data(data)
  50. #lang = qs["lang"] if "lang" in qs else self.language
  51. lang = self.options["language"]
  52. if not lang in self.get_languages():
  53. raise Exception("Not valid default language - '%s'"%lang)
  54. content=[]
  55. content.append(("..return", "back","","Return back"))
  56. if clist=="home":
  57. content.extend([
  58. ("Search", "euronews::content/getSearch?lang=%s&byPage=40&page=1&text={0}"%lang,self.img,"Top stories timeline"),
  59. ("Live stream", "euronews::live?lang=%s"%lang,self.img,"Euronews live stream"),
  60. ("Just in", "euronews::content/getTimeline?lang=%s&byPage=40&page=1"%lang,self.img,"News timeline"),
  61. ("Top stories", "euronews::content/getTopStories?lang=%s"%lang,self.img,"Top stories timeline"),
  62. ("Category - News", "euronews::content/getVertical?lang=%s&byPage=40&page=1&vId=1"%lang,self.img,"Category - News"),
  63. ("Category - European Affairs", "euronews::content/getVertical?lang=%s&byPage=40&page=1&vId=2"%lang,self.img,"Category - European Affairs"),
  64. ("Category - Lifestyle", "euronews::content/getVertical?lang=%s&byPage=40&page=1&vId=3"%lang,self.img,"Category - Lifestyle"),
  65. ("Category - Knowledge", "euronews::content/getVertical?lang=%s&byPage=40&page=1&vId=4"%lang,self.img,"Category - Knowledge"),
  66. ("Latest programs", "euronews::content/getLatestPrograms?lang=%s&byPage=40&page=1"%lang,self.img,"Latest programs"),
  67. ("Programs list", "euronews::content/getPrograms?lang=%s"%lang,self.img,"Programs list"),
  68. ])
  69. return content
  70. ### Video arhīvs ###
  71. elif clist=="content":
  72. if "lang" in qs:
  73. del qs["lang"]
  74. params = json.dumps(qs)
  75. req = '{"methodName":"content.%s","apiKey":"androidPhoneEuronews-1.0","params":%s,"language":"%s"}'%(plist[1],params,lang)
  76. r = self.call(req)
  77. if not r:
  78. return content
  79. lst = r["timeline"] if "timeline" in r else\
  80. r["topstorieslist"] if "topstorieslist" in r else\
  81. r["programs"] if "programs" in r else\
  82. r["programDetailsList"] if "programDetailsList" in r else\
  83. r["programlist"] if "programlist" in r else\
  84. r["articlelist"] if "articlelist" in r else\
  85. r["verticals"] if "verticals" in r else\
  86. []
  87. if not lst:
  88. return content
  89. for item in lst:
  90. if plist[1] in ("getTimeline"):
  91. article = item["article"]
  92. atype = item["type"]
  93. #if item["type"] == "wire":
  94. #continue # TODO
  95. else:
  96. article = item
  97. atype = "article"
  98. if plist[1]=="getPrograms":
  99. title = article["title"]
  100. id = article["pId"]
  101. desc = title
  102. img = "http://static.euronews.com/articles/programs/533x360_%s"%article["img"]
  103. data2 = "content/getProgramDetails?lang=%s&byPage=40&page=1&pId=%s"%(lang,id)
  104. content.append((title,self.name+"::"+data2,img,desc))
  105. else:
  106. title = article["title"] if "title" in article else article["text"] if "text" in article else "No title"
  107. if atype <> "article":
  108. title = "[%s] %s"%(atype,title)
  109. atime = datetime.datetime.fromtimestamp(int(article["uts"]))
  110. #atime = datetime.datetime.fromtimestamp(int(article["uts"])-time.altzone)
  111. atime = atime.strftime("%Y-%m-%d %H:%M")
  112. vert = self.vid[article["vId"]] if "vId" in article else ""
  113. ptitle = article["pTitle"] if "pTitle" in article else ""
  114. id = article["id"]
  115. desc = "%s\n%s\n%s %s"%(title,atime,vert,ptitle)
  116. img = "http://static.euronews.com/articles/%s/399x225_%s.jpg"%(id,id)
  117. if not atype in ("breakingnews","wire"):
  118. data2 = "content/getArticle?lang=%s&id=%s"%(lang,id)
  119. else:
  120. data2 = ""
  121. content.append((title,self.name+"::"+data2,img,desc))
  122. if "page=" in data:
  123. data2 = re.sub("page=\d+","page=%s"%(int(qs["page"])+1),data)
  124. content.append(("Next page",self.name+"::"+data2,self.img,"Next page"))
  125. return content
  126. def is_video(self,data):
  127. source,data,path,plist,clist,params,qs = self.parse_data(data)
  128. if path == "live":
  129. return True
  130. elif clist=="content" and plist[1]=="getArticle":
  131. return True
  132. else:
  133. return False
  134. def get_streams(self, data):
  135. print "[euronews] get_streams:", data
  136. if not self.is_video(data):
  137. return []
  138. source,data,path,plist,clist,params,qs = self.parse_data(data)
  139. #lang = qs["lang"] if "lang" in qs else self.language
  140. lang = self.options["language"]
  141. if not lang in self.get_languages():
  142. raise Exception("Not valid default language - '%s'"%lang)
  143. streams = []
  144. if path == "live":
  145. url = "http://www.euronews.com/api/watchlive.json"
  146. r = self._http_request(url)
  147. try:
  148. js = json.loads(r)
  149. url = js["url"]
  150. except:
  151. raise Exception("No live stream found")
  152. r = self._http_request(url)
  153. try:
  154. js = json.loads(r)
  155. if not js["status"]=="ok":
  156. raise Exception("No live stream found")
  157. except:
  158. raise Exception("No live stream found")
  159. slist = js["primary"]
  160. for l in slist:
  161. stream = util.item()
  162. stream["url"]=slist[l]["hls"]
  163. stream["lang"]=l
  164. stream["quality"]="variant"
  165. stream["name"]="Euronews live [%s]"%l
  166. stream["desc"]=stream["name"]
  167. stream["type"]="hls" #stream_type(url)
  168. streams.append(stream)
  169. elif clist=="content" and plist[1] == "getArticle":
  170. if "lang" in qs:
  171. del qs["lang"]
  172. languages = self.get_languages()
  173. for lang in languages:
  174. id = qs["id"]
  175. req = '{"methodName":"content.getArticle","apiKey":"androidPhoneEuronews-1.0","params":{"id":"%s"},"language":"%s"}'%(id,lang)
  176. r = self.call(req)
  177. if not r:
  178. raise Exception("No live stream found")
  179. if not "articlelist" in r:
  180. msg = r["label"] if "label" in r else "No article finde"
  181. raise Exception(msg)
  182. article = r["articlelist"]
  183. stream = util.item()
  184. stream["url"]=article["videoUri"] if "videoUri" in article else ""
  185. if not stream["url"]:
  186. return []
  187. stream["lang"]=lang
  188. stream["quality"]="?"
  189. stream["name"]= article["title"]
  190. stream["desc"]=article["text"] if "text" in article else article["title"]
  191. stream["type"]="http" #stream_type(url)
  192. streams.append(stream)
  193. else:
  194. raise Exception("No live stream found")
  195. ### TODO - sakārtot sarakstu, lai pirmais ir labakais video
  196. qlist = ["???","lq","mq","hq","hd","variant"]
  197. llist = ["fr","en","ru","lv"]
  198. for s in streams:
  199. if s["lang"]==self.options["language"]:
  200. s["order"] = 10000
  201. continue
  202. lv = llist.index(s["lang"])*10 if s["lang"] in llist else 0
  203. qv=qlist.index(s["quality"]) if s["quality"] in qlist else 0
  204. s["order"] = lv+qv
  205. streams = sorted(streams,key=lambda item: item["order"],reverse=True)
  206. return streams
  207. def get_languages(self):
  208. if self.languages: return self.languages
  209. url = "http://www.euronews.com/api/watchlive.json"
  210. r = self._http_request(url)
  211. try:
  212. js = json.loads(r)
  213. url = js["url"]
  214. except:
  215. raise Exception("Can not get languages list")
  216. r = self._http_request(url)
  217. try:
  218. js = json.loads(r)
  219. if not js["status"]=="ok":
  220. raise Exception("Can not get languages list")
  221. except:
  222. raise Exception("Can not get languages list")
  223. slist = js["primary"]
  224. self.languages=slist.keys()
  225. return self.languages
  226. def call(self, data,params = None, headers=None):
  227. if not headers: headers = self.headers
  228. #if not lang: lang = self.country
  229. url = "http://api.euronews.com/ipad/"
  230. headers = headers2dict("""
  231. User-Agent: Euronews/4.0.126
  232. Content-Type: multipart/form-data, boundary=AaB03xBounDaRy; charset=UTF-8
  233. Host: api.euronews.com
  234. Connection: Keep-Alive
  235. """)
  236. params = """
  237. --AaB03xBounDaRy
  238. content-disposition: form-data; name=request
  239. %s
  240. --AaB03xBounDaRy--
  241. """%data
  242. content = self._http_request(url, params, headers)
  243. if content:
  244. try:
  245. result = json.loads(content)
  246. return result
  247. except Exception, ex:
  248. return None
  249. else:
  250. return None
  251. if __name__ == "__main__":
  252. language= "en"
  253. c = Source(language)
  254. data = '{"methodName":"content.getTimeline","apiKey":"androidPhoneEuronews-1.0","params":{"page":"1","byPage":"30"},"language":"en"}'
  255. r = c.call(data)
  256. if len(sys.argv)>1:
  257. data= sys.argv[1]
  258. else:
  259. data = "home"
  260. content = c.get_content(data)
  261. for item in content:
  262. print item
  263. pass