utils.py 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449
  1. # coding=utf-8
  2. import hashlib
  3. import re
  4. import os
  5. import sys
  6. import pprint
  7. import xbmc
  8. import platform
  9. from consts import *
  10. if sys.version_info[0] >= 3:
  11. unicode = str
  12. long = int
  13. def string_str(s):
  14. return s
  15. def md5_string(i):
  16. m = hashlib.md5()
  17. m.update(i.encode("utf-8"))
  18. return m.hexdigest()
  19. def md5_file(fname):
  20. hash_md5 = hashlib.md5()
  21. with open(fname, "rb") as f:
  22. for chunk in iter(lambda: f.read(4096), b""):
  23. hash_md5.update(chunk.encode("utf-8"))
  24. return hash_md5.hexdigest()
  25. def string_to_json(i):
  26. try:
  27. return json.loads(i)
  28. except:
  29. return None
  30. def is_hex(val):
  31. try:
  32. int(val, 16)
  33. return True
  34. except ValueError:
  35. return False
  36. def get_poster_url(link):
  37. """
  38. @param link:
  39. @return:
  40. """
  41. url = ""
  42. if not link or link == "":
  43. return "DefaultVideo.png"
  44. if link.find("http") > -1:
  45. url = link
  46. else:
  47. url = IMAGEPATH + IMAGESIZE_COVER + link
  48. return url
  49. def get_scene_url(link):
  50. """
  51. @param link:
  52. @return:
  53. """
  54. url = ""
  55. if not link or link == "":
  56. return "DefaultVideo.png"
  57. if link.find("http") > -1:
  58. url = link
  59. else:
  60. url = IMAGEPATH + IMAGESIZE_SCENE + link
  61. return url
  62. def get_backdrop_url(link):
  63. """
  64. @param link:
  65. @return:
  66. """
  67. url = ""
  68. if link:
  69. url = IMAGEPATH + IMAGESIZE_POSTER + link
  70. return url
  71. def xor_string(data, key):
  72. s = ""
  73. dl = len(data)
  74. kl = len(key)
  75. for i in range(0, dl):
  76. c = ord(data[i]) ^ ord(key[(i + dl) % kl])
  77. s += chr(c)
  78. return s
  79. def format_seconds_to_hhmmss(seconds):
  80. seconds = int(seconds)
  81. hours = seconds // (60 * 60)
  82. seconds %= (60 * 60)
  83. minutes = seconds // 60
  84. seconds %= 60
  85. return "%02i:%02i:%02i" % (hours, minutes, seconds)
  86. def misc_menu(menu=None, data=None, episode_id=None):
  87. """
  88. @param data:
  89. @param episode_id:
  90. @return:
  91. """
  92. if not menu:
  93. menu = []
  94. if True and episode_id and data:
  95. menu.append(
  96. (
  97. "Als %sgesehen markieren" % ("un" if data["in_watchedlist"] else ""),
  98. 'RunPlugin("%s")' % PLUGIN.url_for(endpoint="mark_as_seen", episodeid=episode_id, seen=int(not data["in_watchedlist"]))
  99. )
  100. )
  101. menu.append(
  102. (
  103. "Zum Listenanfang",
  104. "Action(firstpage)"
  105. )
  106. )
  107. menu.append(
  108. (
  109. u"Zum Hauptmenü",
  110. 'Container.Update("%s",replace)' % PLUGIN.url_for(endpoint="main")
  111. )
  112. )
  113. menu.append(
  114. (
  115. u"Ebene zurück",
  116. 'Action(Back)'
  117. )
  118. )
  119. return menu
  120. def has_played(movie_id=0):
  121. """
  122. @param movie_id:
  123. @return:
  124. """
  125. return False
  126. def get_user_agent():
  127. user_agent = ""
  128. try:
  129. user_agent = xbmc.getUserAgent()
  130. except:
  131. # getUserAgent not supported
  132. build_version = xbmc.getInfoLabel("System.BuildVersion")
  133. matches = re.search(r"([^\s]+)", build_version, re.IGNORECASE)
  134. user_agent = "Kodi/"
  135. if matches:
  136. user_agent += matches.group(1)
  137. else:
  138. user_agent += "00.00"
  139. try:
  140. user_agent += " (%s; %s)" % (platform.system(), platform.machine())
  141. except:
  142. user_agent += " (%s)" % (sys.platform)
  143. user_agent += " Version/" + build_version.replace(" ", "-")
  144. # Kodi 16: Kodi/16.1 (Linux; Android 8.0; BRAVIA 4K GB Build/OPR2.170623.027.S30) Android/8.0.0 Sys_CPU/armv7l App_Bitness/32 Version/16.1-Git:2016-04-24-c327c53
  145. # Kodi 17: Kodi/17.6 (Linux; Android 7.1.2; AFTMM Build/NS6271) Android/7.1.2 Sys_CPU/armv7l App_Bitness/32 Version/17.6-Git:20171114-a9a7a20
  146. # Kodi 18: Kodi/18.6 (Windows NT 10.0.17763; Win64; x64) App_Bitness/64 Version/18.6-Git:20200229-8e967df921
  147. return user_agent
  148. def convert_to_bytes(text, encoding="utf-8"):
  149. if sys.version_info.major < 3:
  150. return text
  151. else:
  152. try:
  153. return text.encode(encoding, "ignore")
  154. except Exception:
  155. return text
  156. def convert_to_str(text, encoding="utf-8"):
  157. if sys.version_info.major < 3:
  158. return text
  159. else:
  160. try:
  161. return text.decode(encoding, "ignore")
  162. except Exception:
  163. return text
  164. def set_thumbnail(item):
  165. if "art" not in item or not isinstance(item["art"], dict):
  166. item["art"] = {}
  167. thumbnail = item.get("thumbnail")
  168. fanart = item.get("properties", {}).get("thumbnail")
  169. if fanart is not None:
  170. item["art"]["fanart"] = fanart
  171. if thumbnail is not None:
  172. item["art"]["thumb"] = thumbnail
  173. item["art"]["landscape"] = item["art"]["thumb"]
  174. item["art"]["icon"] = item["art"]["thumb"]
  175. item["art"]["clearlogo"] = item["art"]["thumb"]
  176. item["art"]["banner"] = item["art"]["thumb"]
  177. """
  178. item["art"]["poster"] = item["art"]["thumb"]
  179. """
  180. return item
  181. def prepare_entry(entry, isfirst=False, prefixed=True):
  182. if not entry["id"]:
  183. return None
  184. trailer_id = None
  185. if entry["trailer"]:
  186. # trailer_id = re.match(r'^[^v]+v[/=](.{3,11}).*', entry["trailer"])
  187. trailer_id = re.search(r"(?:v=|//[^/]+\.be/)(.{3,11})", entry["trailer"])
  188. if trailer_id:
  189. trailer_id = trailer_id.group(1)
  190. fanart_url = get_backdrop_url(entry["backdropurl"])
  191. title = unicode(entry['title'])
  192. if prefixed:
  193. if entry["type"] == 1:
  194. title = "HD: %s" % title
  195. elif entry["type"] == 2:
  196. title = "Serie: %s" % title
  197. elif entry["type"] == 3:
  198. title = "3D: %s" % title
  199. elif entry["type"] == 4:
  200. title = "UHD: %s" % title
  201. elif entry["type"] == 5:
  202. title = "UHD Serie: %s" % title
  203. if entry["isline"]:
  204. title = "[COLOR %s]%s[/COLOR]" % (COLOR_LINE, title)
  205. elif entry["type"] == 4 or entry["type"] == 5:
  206. title = "[COLOR %s]%s[/COLOR]" % (COLOR_UHD, title)
  207. if not "description" in entry and "overview" in entry:
  208. entry["description"] = entry["overview"]
  209. """
  210. if MASTERLOCK[0] and MINIMALMPAA > 0 and (entry["age"] > MINIMALMPAA or not entry["age"]):
  211. title = "* %s" % title
  212. """
  213. menu = [
  214. (
  215. "Informationen",
  216. "Action(Info)"
  217. )
  218. ]
  219. play_trailer = None
  220. if trailer_id:
  221. play_trailer = PLUGIN.url_for(endpoint="play_trailer",
  222. trailer_id=str(trailer_id),
  223. age=entry["age"] if "age" in entry and entry["age"] else "0")
  224. menu.append(
  225. (
  226. "Trailer abspielen",
  227. 'RunPlugin("%s")' % play_trailer
  228. )
  229. )
  230. if True: # and entry["tmdb_id"]:
  231. menu.append(
  232. (
  233. "Schauspieler anzeigen",
  234. 'Container.Update("%s",True)' % PLUGIN.url_for(endpoint="view_actors",
  235. movie_id=entry['id'])
  236. )
  237. )
  238. menu.append(
  239. (
  240. "%sTrailer suchen" % ("weitere " if trailer_id else ""),
  241. 'Container.Update("%s",True)' % PLUGIN.url_for(endpoint="search_trailer",
  242. title=entry['title'] if isinstance(entry["title"], int) else entry['title'].encode("utf-8"),
  243. date="%s" % entry['release_date'],
  244. fanart=fanart_url if fanart_url else "None",
  245. age=entry["age"] if "age" in entry and entry["age"] else "0")
  246. )
  247. )
  248. in_watchlist_view = (PLUGIN.request.url.find("watchlist") > -1)
  249. if True:
  250. menu.append(
  251. (
  252. u"Von der Merkliste entfernen" if in_watchlist_view else u"Zur Merkliste hinzufügen",
  253. 'RunPlugin("%s")' % (PLUGIN.url_for(endpoint="watchlist_action",
  254. movie_id=entry['id'],
  255. action="remove" if in_watchlist_view else "add",
  256. refresh=in_watchlist_view * 1))
  257. )
  258. )
  259. if True: # and entry["tmdb_id"]:
  260. menu.append(
  261. (
  262. u"Ähnliche Einträge",
  263. 'Container.Update("%s",True)' % PLUGIN.url_for(endpoint="search_similars",
  264. movie_id="%s" % entry['id'],
  265. page=0,
  266. type=entry["type"])
  267. )
  268. )
  269. if False and entry["collection"]:
  270. menu.append(
  271. (
  272. "Filmreihe anzeigen",
  273. 'Container.Update("%s",True)' % PLUGIN.url_for(endpoint="search_similars",
  274. movie_id="%s" % entry['id'],
  275. page=0,
  276. type=entry["type"])
  277. )
  278. )
  279. watched = (entry["in_watchedlist"] * 1) if "in_watchedlist" in entry else (has_played(entry['episode_id']) if not entry["has_episodes"] else 0)
  280. item = {
  281. "label": title,
  282. "info_type": "video",
  283. "mime_type": "application/octet-stream",
  284. "thumbnail": get_poster_url(entry['posterurl']),
  285. "is_playable": False,
  286. # "selected": isfirst,
  287. "path": PLUGIN.url_for(endpoint="seasons", movie_id=entry['id']),
  288. "properties": {
  289. "fanart_image": fanart_url
  290. },
  291. "info": {
  292. # "cast": [("lol", "hehe", "http://www.google.com", "http://www.google.com"), u"lol2"],
  293. "count": entry["id"],
  294. # "playcount": hasPlayed(entry['episode_id']) if entry["has_episodes"] == False else 0,
  295. # "watched": hasPlayed(entry['episode_id']) if entry["has_episodes"] == False else 0,
  296. "playcount": watched,
  297. "watched": watched,
  298. "plot": unicode(entry['description']) if entry['description'] else None,
  299. "rating": "%s" % entry["rating"],
  300. "year": entry["year"],
  301. "mpaa": entry["age"] if "age" in entry and entry["age"] else None,
  302. "director": None,
  303. "genre": entry["genres"],
  304. "date": entry["release_date"] if entry["release_date"] else None,
  305. "title": unicode(entry['title']),
  306. "originaltitle": unicode(entry["original_title"]) if entry["original_title"] else None,
  307. "tagline": (u"%s - %s" % (entry["year"], entry["genres"])) if USE_TAGLINE else None,
  308. "trailer": play_trailer,
  309. "duration": ("%s" % (int(entry["runtime"]) * 60)) if entry["runtime"] else None,
  310. "imdbnumber": entry["imdb_id"] if entry["imdb_id"] else None,
  311. "dateadded": entry["updated_at"]
  312. },
  313. "stream_info": {
  314. "video": {
  315. "duration": ("%s" % (int(entry["runtime"]) * 60)) if entry["runtime"] else None,
  316. }
  317. },
  318. "context_menu": misc_menu(menu, data=entry, episode_id=entry['episode_id'] if not entry["has_episodes"] else None),
  319. "replace_context_menu": False,
  320. "art": {}
  321. }
  322. set_thumbnail(item)
  323. return item
  324. def prepare_movies_to_list(data, prefixed=True):
  325. items = []
  326. for i, movie in enumerate(data):
  327. item = prepare_entry(movie, isfirst=(i == 0), prefixed=prefixed)
  328. if not item:
  329. continue
  330. items.append(item)
  331. return items
  332. def show_busy_dialog():
  333. if KODI_VERSION < 18:
  334. xbmc.executebuiltin('ActivateWindow(busydialog)')
  335. else:
  336. xbmc.executebuiltin('ActivateWindow(busydialognocancel)')
  337. def hide_busy_dialog():
  338. if KODI_VERSION < 18:
  339. xbmc.executebuiltin("Dialog.Close(busydialog)")
  340. else:
  341. xbmc.executebuiltin('Dialog.Close(busydialognocancel)')
  342. def logout_kodi():
  343. """
  344. @return:
  345. """
  346. global PORTAL_USERNAME, PORTAL_USERID
  347. try:
  348. os.remove(COOKIE_PATH)
  349. except:
  350. pass
  351. db = PLUGIN.get_storage("movies")
  352. db["id"] = None
  353. db.sync()
  354. PLUGIN.set_setting("username", "")
  355. PLUGIN.set_setting("password", "")
  356. PORTAL_USERID = 0
  357. PORTAL_USERNAME = ""