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

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