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

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274
  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 requests
  13. import datetime, re, sys,os
  14. import ConfigParser
  15. import ssl
  16. if "_create_unverified_context" in dir(ssl):
  17. ssl._create_default_https_context = ssl._create_unverified_context
  18. from SourceBase import SourceBase
  19. import resolver
  20. try:
  21. import util
  22. except:
  23. sys.path.insert(0,'..')
  24. import util
  25. from YouTubeVideoUrl import YouTubeVideoUrl
  26. headers2dict = lambda h: dict([l.strip().split(": ") for l in h.strip().splitlines()])
  27. import HTMLParser
  28. h = HTMLParser.HTMLParser()
  29. class Source(SourceBase):
  30. def __init__(self, country="lv",cfg_path=None):
  31. self.name = "tvplay"
  32. self.title = "TVPlay"
  33. self.img = "tvplay.png"
  34. self.desc = "tvplay.skaties.lv saturs"
  35. self.headers = headers2dict("""
  36. User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; rv:46.0) Gecko/20100101 Firefox/46.0
  37. Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
  38. Accept-Language: en-US,en;q=0.5
  39. """)
  40. self.headers2 = headers2dict("""
  41. User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; rv:46.0) Gecko/20100101 Firefox/46.0
  42. X-Requested-With: XMLHttpRequest
  43. Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
  44. """)
  45. self.url = "http://login.tvplayhome.lt:8081/sb/public/"
  46. self.kategorijas = [
  47. ("zinas", "Ziņas un aktualitātes", 33, "tvplay.png", "Ziņas un aktualitātes"),
  48. ("berniem", "Bērniem", 52, "tvplay.png", "Bērniem"),
  49. ("seriali", "Seriāli", 38, "tvplay.png", "Seriāli"),
  50. ("filmas", "Filmas", 72, "tvplay.png", "Filmas"),
  51. ("izklaide", "Izklaide", 21, "tvplay.png", "Izklaide"),
  52. ("sovi", "Šovi un raidijumi", 44, "tvplay.png", "Šovi un raidijumi"),
  53. ("sports", "Sports", 32, "tvplay.png", "Sports"),
  54. ("rus", "rus.tvplay.lv", 35, "tvplay.png", "Krievu raidijumi"),
  55. ]
  56. ######### Entry point ########
  57. def get_content(self, data):
  58. print "[lmt] get_content:", data
  59. source, data, path, plist, clist, params, qs = self.parse_data(data)
  60. content = []
  61. content.append(("..return", "back","back.png","Return back"))
  62. if clist=="home":
  63. content.extend([
  64. ("Meklēt", "tvplay::meklet/{0}","tvplay.png","Meklēt"),
  65. ("Tiešraides", "tvplay::tiesraides","tvplay.png","Tiešraides"),
  66. ("Jaunākās epizodes", "tvplay::jaunakais/epizodes", "tvplay.png", "Visu kategoriju jaunākie video"),
  67. ("Jaunākie klipi", "tvplay::jaunakais/klipi", "tvplay.png", "Visu kategoriju jaunākie video"),
  68. ("Jaunākais pa kategorijām", "tvplay::jaunakais/kategorijas", "tvplay.png", "Jaunākie video pa kategorijām žanru jaunākie video"),
  69. ("Raidijumi pa kategorijām", "tvplay::raidijumi/kategorijas", "tvplay.png", "Jaunākie video pa kategorijām žanru jaunākie video"),
  70. ])
  71. return content
  72. elif clist in ("meklet"):
  73. term = plist[1]
  74. data = "tvplay::asset/search?size=30&page=0&f_title.title=%s&f_country=LV&f_metadata.contentType=EPISODE&f_country=LV" % term
  75. return self.get_content(data)
  76. elif clist in ("tiesraides"):
  77. data = "tvplay::asset/search?size=30&page=0&f_metadata.contentType=LIVE&f_country=LV"
  78. return self.get_content(data)
  79. elif clist == "jaunakais":
  80. if plist[1] == "epizodes":
  81. data = "tvplay::asset/search?f_title.categories=15004&size=30&page=0&f_metadata.contentType=EPISODE&f_country=LV"
  82. return self.get_content(data)
  83. elif plist[1] == "klipi":
  84. data = "tvplay::asset/search?f_title.categories=15004&size=30&page=0&f_metadata.contentType=CLIP&f_country=LV"
  85. return self.get_content(data)
  86. elif plist[1] == "kategorijas":
  87. for kat in self.kategorijas:
  88. content.append(("Jaunākais - "+kat[1], "tvplay::jaunakais/%s" % kat[0], kat[3], kat[4]))
  89. return content
  90. elif plist[1] in zip(*self.kategorijas)[0]:
  91. for k in self.kategorijas:
  92. if k[0] == plist[1]:
  93. kat_num = k[2]
  94. break
  95. else:
  96. return content
  97. data = "tvplay::asset/search?f_title.categories=%s&size=30&page=0&f_country=LV" % kat_num
  98. return self.get_content(data)
  99. elif clist == "raidijumi":
  100. if plist[1] == "kategorijas":
  101. for kat in self.kategorijas:
  102. content.append(("Raidijumi - "+kat[1], "tvplay::raidijumi/%s" % kat[0], kat[3], kat[4]))
  103. #content.append(kat[1], "tvplay::tvSeries/category/id/%s?type=tvseries&size=500&sort=&descending=true" % kat[2], kat[3], kat[4])
  104. return content
  105. else:
  106. for k in self.kategorijas:
  107. if k[0] == plist[1]:
  108. kat_num = k[2]
  109. break
  110. else:
  111. return content
  112. data = "tvplay::tvSeries/category/id/%s?type=tvseries&size=500&sort=&descending=true&tenantId=2" % kat_num
  113. return self.get_content(data)
  114. elif path == "asset/search":
  115. r = self.call(data)
  116. if not "content" in r:
  117. raise Exception("Error reading items list")
  118. for item in r["content"]:
  119. data2 = "asset/%s" % item["id"]
  120. title, img, desc = self.get_title_desc(item)
  121. content.append((title, self.name+"::"+data2, img, desc))
  122. if "page" in qs and len(r["content"]) == 30:
  123. page = int(qs["page"]) + 1
  124. data2 = re.sub("page=\d+", "page=%s" % page, data)
  125. content.append(("Next page",self.name+"::"+data2,"next.png","Next page"))
  126. return content
  127. elif plist[0] == "tvSeries" and plist[1] == "category":
  128. r = self.call(data)
  129. if not "content" in r:
  130. raise Exception("Error reading items list")
  131. for item in r["content"]:
  132. tvseries = True if "type" in qs and qs["type"] == "tvseries" else False
  133. if tvseries and not "seasonNumber" in item: # tvseries (programma)
  134. #if len(item["seasonIds"]) > 1:
  135. #tvseries_id = item["id"]
  136. #else:
  137. # tvseries_id = item["seasonIds"][0]
  138. data2 = "tvSeries/%s" % item["id"]
  139. title = item["title"]["title"]
  140. img = "http://login.tvplayhome.lt:8081" + item["posterUrl"] if "posterUrl" in item else self.img
  141. desc = []
  142. if "summaryLong" in item["title"]:
  143. desc.append(item["title"]["summaryLong"])
  144. desc = "\n".join(desc)
  145. content.append((title, self.name+"::"+data2, img, desc))
  146. if "page" in qs:
  147. page = int(qs["page"]) + 1
  148. data2 = re.sub("page=\d+", "page=%s" % page, data)
  149. content.append(("Next page",self.name+"::"+data2,"next.png","Next page"))
  150. return content
  151. elif plist[0] == "tvSeries":
  152. item = self.call(data)
  153. if "seasonIds" in item and len(item["seasonIds"]) > 1:
  154. title0 = item["title"]["title"] + ". " + "Visi video"
  155. data2 = "asset/search?f_metadata.tvSeriesId=%s&page=0&size=30" % item["id"]
  156. img = "http://login.tvplayhome.lt:8081" + item["posterUrl"] if "posterUrl" in item else self.img
  157. desc = []
  158. if "summaryShort" in item["title"]:
  159. desc.append(item["title"]["summaryShort"])
  160. if "summaryLong" in item["title"]:
  161. desc.append(item["title"]["summaryLong"])
  162. desc = "\n".join(desc)
  163. content.append((title0, self.name+"::"+data2, img, desc))
  164. for season in item["seasonIds"]:
  165. data2 = "tvSeries/%s" % season
  166. item = self.call(data2)
  167. title = item["title"]["title"]
  168. img = "http://login.tvplayhome.lt:8081" + item["posterUrl"] if "posterUrl" in item else self.img
  169. desc = []
  170. if "summaryShort" in item["title"]:
  171. desc.append(item["title"]["summaryShort"])
  172. if "summaryLong" in item["title"]:
  173. desc.append(item["title"]["summaryLong"])
  174. desc = "\n".join(desc)
  175. content.append((title, self.name+"::"+data2, img, desc))
  176. return content
  177. else:
  178. data1 = item["vodAssetsUrl"].replace("/sb/public/", "")
  179. data1 += "&size=30&page=0"
  180. return self.get_content(data1)
  181. ### kaut kas neparedzets ###
  182. else:
  183. return content
  184. def get_title_desc(self, item):
  185. title = item["title"]["title"]
  186. if "titleBrief" in item["title"]:
  187. title += ". " + item["title"]["titleBrief"]
  188. img = "http://login.tvplayhome.lt:8081" + item["posterUrl"]
  189. desc = []
  190. if "summaryShort" in item["title"]:
  191. desc.append(item["title"]["summaryShort"])
  192. if "summaryLong" in item["title"] and item["title"]["summaryLong"] <> item["title"]["summaryShort"]:
  193. desc.append(item["title"]["summaryLong"])
  194. if "metadata" in item:
  195. if "contentType" in item["metadata"]:
  196. if item["metadata"]["contentType"] == "CLIP":
  197. desc.append("Klips")
  198. #desc.append(item["metadata"]["contentType"])
  199. if "seasonNumber" in item["metadata"]:
  200. desc.append("Season: %s, episode: %s" % (item["metadata"]["seasonNumber"], item["metadata"]["episodeNumber"] if "episodeNumber" in item["metadata"] else ""))
  201. if "displayRunTime" in item:
  202. desc.append("Lenght: %s" % item["displayRunTime"])
  203. if "airDate" in item["metadata"]:
  204. desc.append("Aired: %s" % item["metadata"]["airDate"])
  205. dd = item["metadata"]["airDate"].split("T")[0].split("-")
  206. title = title + " [%s.%s.%s]" % (dd[2], dd[1], dd[0])
  207. if "licensingWindowEnd" in item["metadata"]:
  208. desc.append("Till: %s" %item["metadata"]["licensingWindowEnd"])
  209. desc = "\n".join(desc)
  210. return title, img, desc
  211. def is_video(self,data):
  212. source,data,path,plist,clist,params,qs = self.parse_data(data)
  213. if clist == "asset" and re.search("\d+", plist[1]):
  214. return True
  215. else:
  216. return False
  217. def call(self, data,params=None,headers=None,lang=""):
  218. if not headers: headers = self.headers
  219. url = self.url+data
  220. r = requests.get(url,headers = headers)
  221. result = json.loads(r.content)
  222. #result = self._http_request(url,params,headers=headers)
  223. return result
  224. def get_streams(self,data):
  225. print "[tvplay] get_streams:", data
  226. if not self.is_video(data):
  227. return []
  228. source,data,path,plist,clist,params,qs = self.parse_data(data)
  229. r = self.call(data)
  230. if not ("movie" in r and "contentUrl" in r["movie"]):
  231. return []
  232. data2 = r["movie"]["contentUrl"]
  233. title, img, desc = self.get_title_desc(r)
  234. stream = util.item()
  235. stream["name"] = title
  236. stream["url"] = data2
  237. stream["img"] = img
  238. stream["desc"] = desc
  239. stream["resolver"] = "tvplay"
  240. return [stream]
  241. if __name__ == "__main__":
  242. sys.path.insert(0, os.path.dirname(os.path.dirname(__file__)))
  243. import run
  244. source = Source()
  245. data= sys.argv[1] if len(sys.argv)>1 else source.name+"::home"
  246. if len(sys.argv) > 2:
  247. run.run_cli(source, data)
  248. else:
  249. run.run(source, data)
  250. sys.exit()