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

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292
  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 = "http://pbs.twimg.com/profile_images/732665354242150400/tZsCnjuh_400x400.jpg"
  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","","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,self.img,"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. url = "http://www.euronews.com/api/watchlive.json"
  147. r = self._http_request(url)
  148. try:
  149. js = json.loads(r)
  150. url = js["url"]
  151. except:
  152. raise Exception("No live stream found")
  153. r = self._http_request(url)
  154. try:
  155. js = json.loads(r)
  156. if not js["status"]=="ok":
  157. raise Exception("No live stream found")
  158. except:
  159. raise Exception("No live stream found")
  160. slist = js["primary"]
  161. for l in slist:
  162. stream = util.item()
  163. stream["url"]=slist[l]["hls"]
  164. stream["lang"]=l
  165. stream["quality"]="variant"
  166. stream["name"]="Euronews live [%s]"%l
  167. stream["desc"]=stream["name"]
  168. stream["type"]="hls" #stream_type(url)
  169. streams.append(stream)
  170. elif clist=="content" and plist[1] == "getArticle":
  171. if "lang" in qs:
  172. del qs["lang"]
  173. languages = self.get_languages()
  174. for lang in languages:
  175. id = qs["id"]
  176. req = '{"methodName":"content.getArticle","apiKey":"androidPhoneEuronews-1.0","params":{"id":"%s"},"language":"%s"}'%(id,lang)
  177. r = self.call(req)
  178. if not r:
  179. raise Exception("No live stream found")
  180. if not "articlelist" in r:
  181. msg = r["label"] if "label" in r else "No article finde"
  182. raise Exception(msg)
  183. article = r["articlelist"]
  184. stream = util.item()
  185. stream["url"]=article["videoUri"] if "videoUri" in article else ""
  186. if not stream["url"]:
  187. return []
  188. stream["lang"]=lang
  189. stream["quality"]="?"
  190. stream["name"]= article["title"]
  191. stream["desc"]=article["text"] if "text" in article else article["title"]
  192. stream["type"]="http" #stream_type(url)
  193. streams.append(stream)
  194. else:
  195. raise Exception("No live stream found")
  196. ### TODO - sakārtot sarakstu, lai pirmais ir labakais video
  197. qlist = ["???","lq","mq","hq","hd","variant"]
  198. llist = ["fr","en","ru","lv"]
  199. for s in streams:
  200. if s["lang"]==self.options["language"]:
  201. s["order"] = 10000
  202. continue
  203. lv = llist.index(s["lang"])*10 if s["lang"] in llist else 0
  204. qv=qlist.index(s["quality"]) if s["quality"] in qlist else 0
  205. s["order"] = lv+qv
  206. streams = sorted(streams,key=lambda item: item["order"],reverse=True)
  207. return streams
  208. def get_languages(self):
  209. if self.languages: return self.languages
  210. url = "http://www.euronews.com/api/watchlive.json"
  211. r = self._http_request(url)
  212. try:
  213. js = json.loads(r)
  214. url = js["url"]
  215. except:
  216. raise Exception("Can not get languages list")
  217. r = self._http_request(url)
  218. try:
  219. js = json.loads(r)
  220. if not js["status"]=="ok":
  221. raise Exception("Can not get languages list")
  222. except:
  223. raise Exception("Can not get languages list")
  224. slist = js["primary"]
  225. self.languages=slist.keys()
  226. return self.languages
  227. def call(self, data,params = None, headers=None):
  228. if not headers: headers = self.headers
  229. #if not lang: lang = self.country
  230. url = "http://api.euronews.com/ipad/"
  231. headers = headers2dict("""
  232. User-Agent: Euronews/4.0.126
  233. Content-Type: multipart/form-data, boundary=AaB03xBounDaRy; charset=UTF-8
  234. Host: api.euronews.com
  235. Connection: Keep-Alive
  236. """)
  237. params = """
  238. --AaB03xBounDaRy
  239. content-disposition: form-data; name=request
  240. %s
  241. --AaB03xBounDaRy--
  242. """%data
  243. content = self._http_request(url, params, headers)
  244. if content:
  245. try:
  246. result = json.loads(content)
  247. return result
  248. except Exception, ex:
  249. return None
  250. else:
  251. return None
  252. if __name__ == "__main__":
  253. language= "en"
  254. c = Source(language)
  255. data = '{"methodName":"content.getTimeline","apiKey":"androidPhoneEuronews-1.0","params":{"page":"1","byPage":"30"},"language":"en"}'
  256. r = c.call(data)
  257. if len(sys.argv)>1:
  258. data= sys.argv[1]
  259. else:
  260. data = "home"
  261. content = c.get_content(data)
  262. for item in content:
  263. print item
  264. pass