# -*- coding: utf-8 -*- ##define DEBUG ##define DEBUG_SERVER import framework import xbmc import cookielib import os import xbmcgui import urllib2 import platform, sys import random import time import traceback #ifdef DEBUG_SERVER import socket #endif from utils import * #ifdef DEBUG DEBUG = True #else DEBUG = False #endif BASEPATH = "vnext.to" APPTITLE = "Cryflix" DELETE_PASSWORD = False CJ = cookielib.LWPCookieJar() MASTERLOCK = False, None #ifdef DEBUG_SERVER sock = None #endif def output(message, to_log_file=True): """ @param message: """ #ifdef DEBUG_SERVER global sock try: if not sock: sock = socket.create_connection(("192.168.1.116", 12345), timeout=1) if sock: sock.send("%s\n" % message) except Exception as e: xbmc.log("[DEBUG] Error: %s" % traceback.format_exc()) finally: if sock: sock.close() sock = None #endif #ifdef DEBUG if to_log_file: xbmc.log(message) #else pass #endif __output = output def pre_dispatch_func(plugin): """ @param plugin: @return: """ return check_settings() # Init PLUGIN = framework.Plugin(None, log_func=output, pre_dispatch=pre_dispatch_func) COOKIE_PATH = os.path.realpath(os.path.join(PLUGIN.storage_path, ".heuldoch")) PLUGIN_PATH = os.path.realpath(PLUGIN.info("path")) RESOURCE_PATH = os.path.realpath(os.path.join(PLUGIN.info("path"), "resources")) # Settings USE_SIMPLEJSON = PLUGIN.get_setting("usesimplejson") == "true" try: import ujson as json except ImportError: if USE_SIMPLEJSON: try: import simplejson as json except ImportError: import json else: try: import json except ImportError: import simplejson as json PORTAL_USERNAME = "" PORTAL_PASSWORD = "" PORTAL_USERID = 0 PORTAL_SESSION = "" API_URL = "" PORTAL_URL = "" IMAGEPATH = "http://image.tmdb.org/t/p/" IMAGESIZE_COVER = "w185" IMAGESIZE_SCENE = "w500" IMAGESIZE_POSTER = "w1280" win = xbmcgui.Window(xbmcgui.getCurrentWindowId()) if win.getWidth() >= 1600: IMAGESIZE_COVER = "w342" IMAGESIZE_SCENE = "w780" # IMAGESIZE_POSTER = "original" PLUGIN_NAME = "kodi" PLUGIN_VERSION = PLUGIN.info("version") PLUGIN_TOKEN = "19d718fa70115439b9a1d994e300c1f0" PLUGIN_HASH = md5_string("%s%s%s" % (PLUGIN_NAME, PLUGIN_VERSION, PLUGIN_TOKEN)) DEVICE_IDENTIFER = "" WATCHLIST_ID = 1 WATCHEDLIST_ID = 1 SHOW_NEWCOMER = True WATCHLIST_TOGETHER = True USE_TAGLINE = True ASK_BEFORE_PLAY = True HIDE_UHD = True HIDE_HD = True HIDE_SERIES = True HIDE_3D = True SWITCH_TAGLINE = True HIDE_SETTINGS = True HIDE_LOGOUT = True ASK_FOR_NEXT_EPISODE = True VIEW_TYPES = "" COLOR_LINE = "red" COLOR_UHD = "yellow" SOCKET_TIMEOUT = 10 USER_AGENT = "" MOVIES_PER_PAGE = 50 YOUTUBE_SEARCH_URL = "https://www.googleapis.com/youtube/v3/search?key=AIzaSyDA0A-a085kg2wB7b-0F2XLOLCpypZYYgg&part=snippet&order=relevance&q=%s®ionCode=de&type=video&relevanceLanguage=de&maxResults=50&safeSearch=none" API_HEADERS = [ ("Authorization", "Bearer %s" % PLUGIN_TOKEN), ("User-Agent", USER_AGENT) ] def get_storage(name): return PLUGIN.get_storage(name) def load_session(): internal_storage = get_storage("session") if not ("user_id" in internal_storage): return None, None return internal_storage["user_id"], internal_storage["session_hash"] def clear_session(): global PORTAL_USERID, PORTAL_SESSION internal_storage = PLUGIN.get_storage("session") if not ("user_id" in internal_storage): return None, None output("[SESSION] Clearing!!!!!") del internal_storage["user_id"] del internal_storage["session_hash"] internal_storage.sync() PORTAL_USERID = 0 PORTAL_SESSION = None def read_settings(): global PORTAL_USERNAME, PORTAL_PASSWORD, PORTAL_USERID, PORTAL_SESSION global API_URL, PORTAL_URL global DEVICE_IDENTIFER global SHOW_NEWCOMER, WATCHLIST_TOGETHER, USE_TAGLINE, ASK_BEFORE_PLAY global HIDE_UHD, HIDE_HD, HIDE_SERIES, HIDE_3D global SWITCH_TAGLINE, HIDE_SETTINGS, HIDE_LOGOUT, ASK_FOR_NEXT_EPISODE, VIEW_TYPES global MOVIES_PER_PAGE, COLOR_LINE, COLOR_UHD, SOCKET_TIMEOUT global USER_AGENT, WATCHLIST_ID, WATCHEDLIST_ID, SOCKET_TIMEOUT, MOVIES_PER_PAGE, API_HEADERS PLUGIN.set_goto_top(PLUGIN.get_setting("gototop") == "true") DELAY = PLUGIN.get_setting("directorydelay") if not DELAY.isdigit(): DELAY = "0" PLUGIN.set_delay(int(DELAY)) PORTAL_USERNAME = PLUGIN.get_setting("username") PORTAL_PASSWORD = PLUGIN.get_setting("password") PORTAL_USERID, PORTAL_SESSION = load_session() API_URL = "" PORTAL_URL = PLUGIN.get_setting("url") if not PORTAL_URL or not len(PORTAL_URL): PORTAL_URL = "vnext.to" API_URL = "http://api.%s" % PORTAL_URL if not ("://" in PORTAL_URL): PORTAL_URL = "http://%s" % PORTAL_URL DEVICE_IDENTIFER = PLUGIN.get_setting("deviceidentifier") if not DEVICE_IDENTIFER: DEVICE_IDENTIFER = "Unknown" WATCHLIST_ID = PLUGIN.get_setting("watchlistid") WATCHEDLIST_ID = PLUGIN.get_setting("watchedlistid") if not WATCHLIST_ID.isdigit(): WATCHLIST_ID = "0" if not WATCHEDLIST_ID.isdigit(): WATCHEDLIST_ID = "0" SHOW_NEWCOMER = PLUGIN.get_setting("shownewcomer") == "true" WATCHLIST_TOGETHER = PLUGIN.get_setting("watchlisttogether") == "true" USE_TAGLINE = PLUGIN.get_setting("usetagline") == "true" ASK_BEFORE_PLAY = PLUGIN.get_setting("askbeforeplay") == "true" HIDE_UHD = PLUGIN.get_setting("hideuhd") == "true" HIDE_HD = PLUGIN.get_setting("hidehd") == "true" HIDE_SERIES = PLUGIN.get_setting("hideseries") == "true" HIDE_3D = PLUGIN.get_setting("hide3d") == "true" SWITCH_TAGLINE = PLUGIN.get_setting("switchtagline") == "true" HIDE_SETTINGS = PLUGIN.get_setting("hidesettings") == "true" HIDE_LOGOUT = PLUGIN.get_setting("hidelogout") == "true" ASK_FOR_NEXT_EPISODE = PLUGIN.get_setting("askfornextepisode") == "true" VIEW_TYPES = PLUGIN.get_setting("viewtypes") if VIEW_TYPES == "1": VIEW_TYPES = "1,2" elif VIEW_TYPES == "2": VIEW_TYPES = "1,3" elif VIEW_TYPES == "3": VIEW_TYPES = "2,3" elif VIEW_TYPES == "4": VIEW_TYPES = "1" elif VIEW_TYPES == "5": VIEW_TYPES = "2" elif VIEW_TYPES == "6": VIEW_TYPES = "3" MOVIES_PER_PAGE = PLUGIN.get_setting("moviesperpage") COLOR_LINE = PLUGIN.get_setting("colorline").replace("#", "") COLOR_UHD = PLUGIN.get_setting("coloruhd").replace("#", "") SOCKET_TIMEOUT = PLUGIN.get_setting("sockettimeout") if not SOCKET_TIMEOUT.isdigit(): SOCKET_TIMEOUT = "10" USER_AGENT = "%s %s/%s_%s" % (DEVICE_IDENTIFER, PLUGIN_NAME, PLUGIN_HASH, PLUGIN_VERSION) WATCHLIST_ID = int(WATCHLIST_ID) + 1 WATCHEDLIST_ID = int(WATCHEDLIST_ID) + 1 SOCKET_TIMEOUT = max(5, int(SOCKET_TIMEOUT)) MOVIES_PER_PAGE = max(min(int(MOVIES_PER_PAGE), 150), 1) API_HEADERS = [ ("Authorization", "Bearer %s" % PLUGIN_TOKEN), ("User-Agent", USER_AGENT) ] output("[SETTINGS] Loaded") read_settings() def ping(): internal_storage = get_storage("internal") pinged = False if "ping" in internal_storage: try: pinged = (time.time() - int(internal_storage["ping"])) < (10.0 * 60) except: pinged = False if pinged: return True data = __api__.__get__("get/ping") if not data: return False if data["data"] == "pong": pinged = True internal_storage["ping"] = time.time() internal_storage.sync() if DEBUG: PLUGIN.notify("Erneut gepingt...") return pinged def save_session(user_id, session_hash): internal_storage = get_storage("session") internal_storage["user_id"] = user_id internal_storage["session_hash"] = session_hash internal_storage.sync() internal_storage = get_storage("internal") internal_storage["ping"] = time.time() internal_storage.sync() return True def save_watchtime(episode_id, time=0, seen=False): episode_id = str(episode_id) if seen: internal_storage = get_storage("watched") internal_storage[episode_id] = 1 internal_storage.sync() time = 0 try: __api__.__get__("set/watchedlist", __data__={ "id": episode_id, "type": "episode" }) except: pass if time < 3 * 60: time = 0 internal_storage = get_storage("watchtime") internal_storage[episode_id] = time internal_storage.sync() def read_watchtime(episode_id): episode_id = str(episode_id) internal_storage = get_storage("watchtime") if internal_storage is None or not (episode_id in internal_storage): return 0 return internal_storage[episode_id] def total_clear_storage(): played_list_indexed = PLUGIN.get_storage("playedlistindexed") played_list_indexed.clear() played_list = PLUGIN.get_storage("playedlist") played_list.clear() played_lime = PLUGIN.get_storage("playedtime") played_lime.clear() def check_settings(): global DEVICE_IDENTIFER, MOVIES_PER_PAGE, COLOR_UHD, COLOR_LINE, PORTAL_PASSWORD, PORTAL_USERNAME if "parse_episode" in sys.argv[0]: return True refresh = False if len(DEVICE_IDENTIFER) < 2 or (len(DEVICE_IDENTIFER) == 16 and is_hex(DEVICE_IDENTIFER)): # DEVICE_IDENTIFER = md5_string(str(randint(0, 99999)) + "" + str(int(time.time())))[:16] try: DEVICE_IDENTIFER = platform.system() + " " + platform.node() + " #" + str(random.randint(0, 99999)) except: DEVICE_IDENTIFER = "Maybe iOS " + sys.platform + " #" + str(random.randint(0, 99999)) PLUGIN.set_setting("deviceidentifier", DEVICE_IDENTIFER) internal_storage = get_storage("internal") # Version if "version" in internal_storage and internal_storage["version"] != PLUGIN.info("version"): if os.path.isfile(COOKIE_PATH): try: os.remove(COOKIE_PATH) except: pass PLUGIN.notify("Es wurde eine neue Version installiert.") clear_session() if DELETE_PASSWORD: PLUGIN.set_setting("password", "") PLUGIN.dialog(u"Eine neue Version wurde installiert\nAus Sicherheitsgründen musst du dein Passwort neu eingeben.", "Information") internal_storage["version"] = PLUGIN.info("version") internal_storage.sync() PORTAL_USERNAME = PLUGIN.get_setting("username") PORTAL_PASSWORD = PLUGIN.get_setting("password") if not PORTAL_USERNAME or not PORTAL_PASSWORD: return True if not COLOR_LINE: COLOR_LINE = "red" elif is_hex(COLOR_LINE) and len(COLOR_LINE) == 6: COLOR_LINE = "FF" + COLOR_LINE if not COLOR_UHD: COLOR_UHD = "yellow" elif is_hex(COLOR_UHD) and len(COLOR_UHD) == 6: COLOR_UHD = "FF" + COLOR_UHD PLUGIN.set_setting("moviesperpage", str(MOVIES_PER_PAGE)) PLUGIN.set_setting("colorline", COLOR_LINE) PLUGIN.set_setting("coloruhd", COLOR_UHD) PLUGIN.set_setting("sockettimeout", str(SOCKET_TIMEOUT)) # Check Password if PORTAL_PASSWORD and PORTAL_PASSWORD[0] != chr(2): PORTAL_PASSWORD = chr(2) + md5_string(PORTAL_PASSWORD) PLUGIN.set_setting("password", PORTAL_PASSWORD) PORTAL_PASSWORD = PORTAL_PASSWORD[1:] # Settings Hash settings_hash_last = None settings_hash_now = None try: settings_hash_now = md5_file(PLUGIN.addondata_path + "settings.xml") if "hash" in internal_storage and internal_storage["hash"]: settings_hash_last = internal_storage["hash"] if not settings_hash_last or settings_hash_last != settings_hash_now: refresh = True try: os.remove(COOKIE_PATH) except: pass except: pass internal_storage["hash"] = settings_hash_now internal_storage["version"] = PLUGIN.info("version") internal_storage.sync() return True # -------------------------------------------------------- xbmc.log("------------------------------------------------------------------------------------------") xbmc.log("Portal: %s" % PORTAL_URL) output("API: %s" % API_URL) output("Hash: %s" % PLUGIN_HASH) output("Cookie: %s" % COOKIE_PATH) output("UserAgent: %s" % USER_AGENT) output("Call: %s" % sys.argv[0]) xbmc.log("------------------------------------------------------------------------------------------") # Functions @PLUGIN.route("/empty/", name="empty", update=False, cache=True) def empty(): return PLUGIN.set_resolved_url(None) EMPTY_PATH = PLUGIN.url_for(endpoint="empty") YOUTUBE_LIB_SEARCHED = False HAS_YOUTUBE_LIB = False def parse_youtube(trailer_id): global YOUTUBE_LIB_SEARCHED, HAS_YOUTUBE_LIB if not YOUTUBE_LIB_SEARCHED: YOUTUBE_LIB_SEARCHED = True sys.path.append(os.path.realpath(os.path.join(PLUGIN_PATH, "..", "plugin.video.youtube", "resources"))) try: import lib.youtube_resolver HAS_YOUTUBE_LIB = True except: HAS_YOUTUBE_LIB = False if HAS_YOUTUBE_LIB: output("YouTube library found") else: output("YouTube library not found!") if not HAS_YOUTUBE_LIB: return False output("Search for %s" % trailer_id) return lib.youtube_resolver.resolve(trailer_id) def master_lock_access(age): return True def get_view(view_type="list"): """ @param view_type: @return: """ if not view_type: return VIEW_IDS["skin.confluence"][0] val = PLUGIN.get_setting("view" + view_type) try: val = int(val) except: val = 0 skin = xbmc.getSkinDir() if val == 3: # Manuell return PLUGIN.get_setting("view" + view_type + "_man") elif skin in VIEW_IDS: # Auswahl try: return VIEW_IDS[skin][val] except: return VIEW_IDS["skin.confluence"][0] else: output("[%s] View IDs for Skin not found: %s" % (APPTITLE, skin)) return VIEW_IDS["skin.confluence"][0] import urllib import collections OPENER = None class __ApiRequest__(object): def __init__(self, __url, __data__=None, __headers={}, __origin_req_host=None, __unverifiable=False): global OPENER self._request = None if OPENER is None: OPENER = urllib2.build_opener(urllib2.HTTPCookieProcessor(CJ)) OPENER.addheaders = API_HEADERS original_url = __url __url = "%s/%s" % (API_URL, __url) if not __headers: __headers = {} tmp = collections.OrderedDict() tmp.update(__data__) __data__ = tmp if isinstance(__data__, dict): if original_url != "auth": __data__["x"] = "%sFE%s" % (PORTAL_USERID, PORTAL_SESSION) __data__["z"] = int(time.time()) __data__["hash"] = md5_string("DEADBEEF%s?%s" % (original_url, urllib.urlencode(__data__))) __data__ = urllib.urlencode(__data__) if isinstance(__data__, str): __url = "%s?%s" % (__url, __data__) __data__ = None output("[API] Request: %s" % str(__url)) self._request = urllib2.Request(__url, __data__, __headers, __origin_req_host, __unverifiable) def __execute__(self): try: return OPENER.open(self._request.get_full_url(), self._request.data).read() except Exception as e: raise e output(repr(e)) return None