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

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275
  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, os
  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 = "tvplay.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","back.png","Return back"))
  56. if clist=="home":
  57. content.extend([
  58. ("Search", "mtgplay::search?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. if clist == "search":
  77. clist = "formats"
  78. for item in r["_embedded"][clist]:
  79. if "title" in item:
  80. title = item["title"]
  81. elif "name" in item:
  82. title = item["name"]
  83. #data2 = self.name+"::"+"%s/%s"%(clist,item["id"])
  84. img = item["_links"]["image"]["href"].replace("{size}",self.pic_size) \
  85. if "image" in item["_links"] and \
  86. "href" in item["_links"]["image"] and item["_links"]["image"]["href"]\
  87. else ""
  88. desc = item["summary"] if "summary" in item and item["summary"] else ""
  89. ### Video ###
  90. if clist=="videos":
  91. data2 = "videos/%s"%item["id"]
  92. summary = item["summary"] if item["summary"] else ""
  93. air_at = item["broadcasts"][0]["air_at"] if "broadcasts" in item and len(item["broadcasts"])>0 and "air_at" in item["broadcasts"][0] else ""
  94. if not air_at:
  95. air_at = item["publish_at"] if "publish_at" in item else ""
  96. air_at = air_at[0:16].replace("T"," ") if air_at else ""
  97. try: playable_to = item["broadcasts"][0]["playable_to"]
  98. except: playable_to =""
  99. playable_to = "(till "+playable_to[0:10].replace("T"," ")+")" if playable_to else ""
  100. duration = item["duration"] if "duration" in item else ""
  101. duration = str(datetime.timedelta(seconds=int(duration))) if duration else ""
  102. try:
  103. views = item["views"]["total"] if "views" in item and "total" in item["views"] else ""
  104. views = views+" views"
  105. except: views = ""
  106. desc = "Aired: %s %s\nDuration: %s %s\n\n%s"%(air_at, playable_to,duration,views,summary)
  107. ### Categories ###
  108. elif clist == "categories":
  109. #data2 = item["_links"]["formats"]["href"].replace(API_URL,"")
  110. data2 = "formats?category=%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=title"
  115. ### Channels ###
  116. elif clist == "channels":
  117. #data2 = item["_links"]["categories"]["href"].replace(API_URL,"")
  118. data2 = "categories?channel=%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=name"
  123. ### Formats (programs) ###
  124. elif clist == "formats":
  125. #data2 = item["_links"]["videos"]["href"].replace(API_URL,"")
  126. data2 = "seasons?format=%s"%item["id"]
  127. #if "country" in qs: data2 += "&country="+qs["country"]
  128. #if "category" in qs: data2 += "&category="+qs["category"]
  129. #if "channel" in qs: data2 += "&channel="+qs["channel"]
  130. data2 += "&order=-id"
  131. if "lastest_video" in item:
  132. air_at = item["latest_video"]["publish_at"] if "publish_at" in item["latest_video"] else ""
  133. air_at = air_at[0:16].replace("T"," ") if air_at else ""
  134. if air_at:
  135. desc = "Last video: %s\n"%air_at + desc
  136. ### Seasons ###
  137. elif clist == "seasons":
  138. #data2 = item["_links"]["videos"]["href"].replace(API_URL,"")
  139. data2 = "videos?season=%s"%item["id"]
  140. #if "country" in qs: data2 += "&country="+qs["country"]
  141. #if "category" in qs: data2 += "&category="+qs["category"]
  142. #if "channel" in qs: data2 += "&channel="+qs["channel"]
  143. data2 += "&order=-id"
  144. summary = item["summary"] if "summary" in item and item["summary"] else ""
  145. try:
  146. latest_video = item["latest_video"]["publish_at"]
  147. latest_video = latest_video[0:16].replace("T"," ")
  148. except: latest_video = ""
  149. desc = ("%s\nLatest video: %s"%(summary,latest_video))
  150. content.append((title.encode("utf8"),self.name+"::"+data2.encode("utf8"),img.encode("utf8"),desc.encode("utf8")))
  151. if r["_links"].has_key("next"):
  152. data2 = r["_links"]["next"]["href"].replace(API_URL,"").encode("utf8")
  153. content.append(("Next page", self.name+"::"+data2.encode("utf8"),"","Goto next page"))
  154. elif citem:
  155. item = r
  156. if "title" in item:
  157. title = item["title"]
  158. elif "name" in item:
  159. title = r["name"]
  160. #data2 = self.name+"::"+"%s/%s"%(clist,item["id"])
  161. img = item["_links"]["image"]["href"].replace("{size}",self.pic_size) if "image" in item["_links"] else ""
  162. desc = item["summary"] if "summary" in item and item["summary"] else ""
  163. dd = "videos/stream/%s"%cid
  164. r2 = self.call(dd)
  165. if "streams" in r2 and "hls" in r2["streams"]:
  166. data2 = r2["streams"]["hls"]
  167. content = (title.encode("utf8"),data2.encode("utf8"),img.encode("utf8"),desc.encode("utf8"))
  168. elif "msg" in r2:
  169. content = (r2["msg"].encode("utf8"),"","","")
  170. else:
  171. content = ("Error getting stream","","","")
  172. else:
  173. pass
  174. return content
  175. def is_video(self,data):
  176. if "::" in data:
  177. data = data.split("::")[1]
  178. cmd = data.split("/")
  179. if cmd[0]=="videos":
  180. return True
  181. else:
  182. return False
  183. def get_stream(self,id):
  184. dd = "videos/stream/%s"%id
  185. r2 = self.call(dd)
  186. if "streams" in r2 and "hls" in r2["streams"]:
  187. data2 = r2["streams"]["hls"]
  188. else:
  189. data2 = ""
  190. return data2.encode("utf8")
  191. def call_all(self, endpoint, params = None):
  192. url = API_URL % (endpoint)
  193. if params:
  194. url += '?' + params
  195. print "[TVPlay Api] url: ",url
  196. result = []
  197. while True:
  198. content = self._http_request(url)
  199. if content:
  200. try:
  201. content = json.loads(content)
  202. except Exception, ex:
  203. return {" Error " : "in call_api: %s" % ex}
  204. else: break
  205. if content.has_key("_embedded") and content["_embedded"].has_key(endpoint):
  206. result.extend(content["_embedded"][endpoint])
  207. pass
  208. else: break
  209. if content.has_key("_links") and content["_links"].has_key("next"):
  210. url = content["_links"]["next"]["href"]
  211. else: break
  212. return result
  213. def call(self, data,headers=headers0):
  214. url = API_URL + data
  215. #print "[TVPlay Api] url: ",url
  216. result = []
  217. content = self._http_request(url)
  218. if content:
  219. try:
  220. result = json.loads(content)
  221. except Exception, ex:
  222. return None
  223. return result
  224. def _http_request0(self, url,headers=headers0):
  225. try:
  226. r = urllib2.Request(url, headers=headers)
  227. u = urllib2.urlopen(r)
  228. content = u.read()
  229. u.close()
  230. return content
  231. except Exception as ex:
  232. if "read" in ex:
  233. content = ex.read()
  234. else:
  235. content = None
  236. return content
  237. if __name__ == "__main__":
  238. sys.path.insert(0, os.path.dirname(os.path.dirname(__file__)))
  239. import run
  240. source = Source()
  241. data= sys.argv[1] if len(sys.argv)>1 else source.name+"::home"
  242. run.run(source, data)
  243. sys.exit()