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

euronews.py 12KB

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