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

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279
  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. #!/usr/bin/env python
  13. # coding=utf8
  14. import urllib2, urllib
  15. import datetime, re, sys
  16. from SourceBase import SourceBase
  17. API_URL = 'http://playapi.mtgx.tv/v3/'
  18. headers2dict = lambda h: dict([l.strip().split(": ") for l in h.strip().splitlines()])
  19. headers0 = headers2dict("""
  20. User-Agent: Mozilla/5.0 (Linux; U; Android 4.4.4; Nexus 5 Build/KTU84P) AppleWebkit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30
  21. """)
  22. REGIONS = [
  23. ("Latvia",None,"lv",""),
  24. ("Estonia",None,"ee",""),
  25. ("Lituania",None,"lt",""),
  26. ("Sweden",None,"se",""),
  27. ("Denmark",None,"dk",""),
  28. ("Norway",None,"no",""),
  29. ("Bulgaria",None,"bg","")
  30. ]
  31. class Source(SourceBase):
  32. def __init__(self,country="lv"):
  33. self.name = "mtgplay"
  34. self.title = "Skaties.lv (TV3)"
  35. self.img = "http://skaties.lv/touch-icon-192x192.png"
  36. self.desc = "MTG skaties.lv satura skatīšanās (LNT,TV3, TV6 u.c.)"
  37. self.country=country
  38. self.pic_size = "327x250" #"1000x765"
  39. def get_content(self, data):
  40. print "[mtgplay] get_content:", data
  41. if "::" in data:
  42. data = data.split("::")[1]
  43. if "/" in data:
  44. citem,cid = data.split("/")
  45. clist = ""
  46. else:
  47. clist = data.split("?")[0]
  48. qs = dict(map(lambda x:x.split("="),re.findall("\w+=\w+",data)))
  49. citem,cid = ("","")
  50. self.country = qs["country"] if "country" in qs else "lv"
  51. content=[]
  52. content.append(("..return", "back","","Return back"))
  53. if clist=="home":
  54. content.extend([
  55. #("Search", "mtgplay::meklet?country=%s&term={0}"%self.country,"","Search videos"), ### TODO
  56. ("TV Live", "mtgplay::videos?country=%s&order=title&type=live"%self.country,"","TV live streams(not always available)"),
  57. ("Last videos", "mtgplay::videos?country=%s&order=-airdate"%self.country,"","Last aired videos"),
  58. ("Categories", "mtgplay::categories?country=%s&order=name"%self.country,"","Categories"),
  59. ("Channels", "mtgplay::channels?country=%s&order=id"%self.country,"","TV channels"),
  60. ("Programs by name", "mtgplay::formats?country=%s&order=-title"%self.country,"","Programs by name"),
  61. ("Programs by popularity", "mtgplay::formats?country=%s&order=-popularity"%self.country,"","Programs by popularity")
  62. ])
  63. return content
  64. r = self.call(data)
  65. if not r:
  66. content.append(("Error", "","","Error reading '%s'"%data))
  67. return content
  68. if clist:
  69. if r["_links"].has_key("prev"):
  70. data2 = r["_links"]["prev"]["href"].replace(API_URL,"")
  71. content.append(("Previous page", self.name+"::"+data2.encode("utf8"),"", "Goto previous page"))
  72. if "_embedded" in r:
  73. for item in r["_embedded"][clist]:
  74. if "title" in item:
  75. title = item["title"]
  76. elif "name" in item:
  77. title = item["name"]
  78. #data2 = self.name+"::"+"%s/%s"%(clist,item["id"])
  79. img = item["_links"]["image"]["href"].replace("{size}",self.pic_size) if "image" in item["_links"] else ""
  80. desc = item["summary"] if "summary" in item and item["summary"] else ""
  81. ### Video ###
  82. if clist=="videos":
  83. data2 = "videos/%s"%item["id"]
  84. summary = item["summary"] if item["summary"] else ""
  85. air_at = item["broadcasts"][0]["air_at"] if "broadcasts" in item and len(item["broadcasts"])>0 and "air_at" in item["broadcasts"][0] else ""
  86. if not air_at:
  87. air_at = item["publish_at"] if "publish_at" in item else ""
  88. air_at = air_at[0:16].replace("T"," ") if air_at else ""
  89. try: playable_to = item["broadcasts"][0]["playable_to"]
  90. except: playable_to =""
  91. playable_to = "(till "+playable_to[0:10].replace("T"," ")+")" if playable_to else ""
  92. duration = item["duration"] if "duration" in item else ""
  93. duration = str(datetime.timedelta(seconds=int(duration))) if duration else ""
  94. try:
  95. views = item["views"]["total"] if "views" in item and "total" in item["views"] else ""
  96. views = views+" views"
  97. except: views = ""
  98. desc = "Aired: %s %s\nDuration: %s %s\n\n%s"%(air_at, playable_to,duration,views,summary)
  99. ### Categories ###
  100. elif clist == "categories":
  101. #data2 = item["_links"]["formats"]["href"].replace(API_URL,"")
  102. data2 = "formats?category=%s"%item["id"]
  103. if "country" in qs: data2 += "&country="+qs["country"]
  104. if "category" in qs: data2 += "&category="+qs["category"]
  105. if "channel" in qs: data2 += "&channel="+qs["channel"]
  106. data2 += "&order=title"
  107. ### Channels ###
  108. elif clist == "channels":
  109. #data2 = item["_links"]["categories"]["href"].replace(API_URL,"")
  110. data2 = "categories?channel=%s"%item["id"]
  111. if "country" in qs: data2 += "&country="+qs["country"]
  112. if "category" in qs: data2 += "&category="+qs["category"]
  113. if "channel" in qs: data2 += "&channel="+qs["channel"]
  114. data2 += "&order=name"
  115. ### Formats (programs) ###
  116. elif clist == "formats":
  117. #data2 = item["_links"]["videos"]["href"].replace(API_URL,"")
  118. data2 = "seasons?format=%s"%item["id"]
  119. #if "country" in qs: data2 += "&country="+qs["country"]
  120. #if "category" in qs: data2 += "&category="+qs["category"]
  121. #if "channel" in qs: data2 += "&channel="+qs["channel"]
  122. data2 += "&order=title"
  123. air_at = item["latest_video"]["publish_at"] if "publish_at" in item["latest_video"] else ""
  124. air_at = air_at[0:16].replace("T"," ") if air_at else ""
  125. if air_at:
  126. desc = "Last video: %s\n"%air_at + desc
  127. ### Seasons ###
  128. elif clist == "seasons":
  129. #data2 = item["_links"]["videos"]["href"].replace(API_URL,"")
  130. data2 = "videos?season=%s"%item["id"]
  131. #if "country" in qs: data2 += "&country="+qs["country"]
  132. #if "category" in qs: data2 += "&category="+qs["category"]
  133. #if "channel" in qs: data2 += "&channel="+qs["channel"]
  134. data2 += "&order=title"
  135. summary = item["summary"] if "summary" in item and item["summary"] else ""
  136. try:
  137. latest_video = item["latest_video"]["publish_at"]
  138. latest_video = latest_video[0:16].replace("T"," ")
  139. except: latest_video = ""
  140. desc = ("%s\nLatest video: %s"%(summary,latest_video))
  141. content.append((title.encode("utf8"),self.name+"::"+data2.encode("utf8"),img.encode("utf8"),desc.encode("utf8")))
  142. if r["_links"].has_key("next"):
  143. data2 = r["_links"]["next"]["href"].replace(API_URL,"").encode("utf8")
  144. content.append(("Next page", self.name+"::"+data2.encode("utf8"),"","Goto next page"))
  145. elif citem:
  146. item = r
  147. if "title" in item:
  148. title = item["title"]
  149. elif "name" in item:
  150. title = r["name"]
  151. #data2 = self.name+"::"+"%s/%s"%(clist,item["id"])
  152. img = item["_links"]["image"]["href"].replace("{size}",self.pic_size) if "image" in item["_links"] else ""
  153. desc = item["summary"] if "summary" in item and item["summary"] else ""
  154. dd = "videos/stream/%s"%cid
  155. r2 = self.call(dd)
  156. if "streams" in r2 and "hls" in r2["streams"]:
  157. data2 = r2["streams"]["hls"]
  158. content = (title.encode("utf8"),data2.encode("utf8"),img.encode("utf8"),desc.encode("utf8"))
  159. elif "msg" in r2:
  160. content = (r2["msg"].encode("utf8"),"","","")
  161. else:
  162. content = ("Error getting stream","","","")
  163. else:
  164. pass
  165. return content
  166. def is_video(self,data):
  167. if "::" in data:
  168. data = data.split("::")[1]
  169. cmd = data.split("/")
  170. if cmd[0]=="videos":
  171. return True
  172. else:
  173. return False
  174. def get_stream(self,id):
  175. dd = "videos/stream/%s"%id
  176. r2 = self.call(dd)
  177. if "streams" in r2 and "hls" in r2["streams"]:
  178. data2 = r2["streams"]["hls"]
  179. else:
  180. data2 = ""
  181. return data2.encode("utf8")
  182. def call_all(self, endpoint, params = None):
  183. url = API_URL % (endpoint)
  184. if params:
  185. url += '?' + params
  186. print "[TVPlay Api] url: ",url
  187. result = []
  188. while True:
  189. content = self._http_request(url)
  190. if content:
  191. try:
  192. content = json.loads(content)
  193. except Exception, ex:
  194. return {" Error " : "in call_api: %s" % ex}
  195. else: break
  196. if content.has_key("_embedded") and content["_embedded"].has_key(endpoint):
  197. result.extend(content["_embedded"][endpoint])
  198. pass
  199. else: break
  200. if content.has_key("_links") and content["_links"].has_key("next"):
  201. url = content["_links"]["next"]["href"]
  202. else: break
  203. return result
  204. def call(self, data,headers=headers0):
  205. url = API_URL + data
  206. #print "[TVPlay Api] url: ",url
  207. result = []
  208. content = self._http_request(url)
  209. if content:
  210. try:
  211. result = json.loads(content)
  212. except Exception, ex:
  213. return None
  214. return result
  215. def _http_request0(self, url,headers=headers0):
  216. try:
  217. r = urllib2.Request(url, headers=headers)
  218. u = urllib2.urlopen(r)
  219. content = u.read()
  220. u.close()
  221. return content
  222. except Exception as ex:
  223. if "read" in ex:
  224. content = ex.read()
  225. else:
  226. content = None
  227. return content
  228. if __name__ == "__main__":
  229. country= "lv"
  230. c = Source(country)
  231. if len(sys.argv)>1:
  232. data= sys.argv[1]
  233. else:
  234. data = "home"
  235. content = c.get_content(data)
  236. for item in content:
  237. print item
  238. #cat = api.get_categories(country)
  239. #chan = api.get_channels("lv")
  240. #prog = api.get_programs(channel=6400)
  241. #prog = api.get_programs(category=55)
  242. #seas = api.get_seasons(program=6453)
  243. #str = api.get_streams(660243)
  244. #res = api.get_videos(802)
  245. #formats = api.getAllFormats()
  246. #det = api.detailed("1516")
  247. #vid = api.getVideos("13170")
  248. pass