Python module (submodule repositary), which provides content (video streams) from various online stream sources to corresponding Enigma2, Kodi, Plex plugins

euronews.py 13KB

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