Exemple #1
0
def getNordVPNUserPass(vpn_provider):
    # Download the opvn file
    try:
        download_url = "https://api.nordvpn.com/v1/users/services/credentials"
        if ifHTTPTrace(): infoTrace("alternativeNord.py", "Getting user credentials " + download_url)
        else: debugTrace("Getting user credentials")
        token = getTokenNordVPN()
        req = Request(download_url)
        req.add_header("Authorization", "token:" + token)
        t_before = now()
        response = urlopen(req, timeout=10)
        user_data = json.load(response)
        t_after = now()
        response.close()
        if ifJSONTrace(): infoTrace("alternativeNord.py", "JSON received is \n" + json.dumps(user_data, indent=4))
        if t_after - t_before > TIME_WARN: infoTrace("alternativeNord.py", "Getting user credentials took " + str(t_after - t_before) + " seconds")
        return user_data["username"], user_data["password"]
    except HTTPError as e:
        errorTrace("alternativeNord.py", "Couldn't get user credentials")
        errorTrace("alternativeNord.py", "API call was " + download_url)
        errorTrace("alternativeNord.py", "Response was " + str(e.code) + " " + e.reason)
        errorTrace("alternativeNord.py", e.read())
        return "", ""
    except Exception as e:
        errorTrace("alternativeNord.py", "Couldn't get user credentials")
        errorTrace("alternativeNord.py", "API call was " + download_url)
        errorTrace("alternativeNord.py", "Response was " + str(type(e)) + " " + str(e))
        return "", ""
Exemple #2
0
def renewNordVPN(renew):
    # Renew a user with the API and store the tokens returned
    response = ""
    try:        
        download_url = "https://api.nordvpn.com/v1/users/tokens/renew"
        download_data = "renewToken=" + renew
        if ifHTTPTrace(): infoTrace("alternativeNord.py", "Renewing authentication using " + download_url + ", " + download_data)
        else: debugTrace("Renewing authentication")
        req = Request(download_url, download_data)
        t_before = now()
        response = urlopen(req, timeout=10)
        user_data = json.load(response)
        t_after = now()
        response.close()
        if ifJSONTrace(): infoTrace("alternativeNord.py", "JSON received is \n" + json.dumps(user_data, indent=4))
        if t_after - t_before > TIME_WARN: infoTrace("alternativeNord.py", "Renewing authentication took " + str(t_after - t_before) + " seconds")
        setTokens(user_data["token"], user_data["renew_token"], None)
        return True
    except HTTPError as e:
        errorTrace("alternativeNord.py", "Couldn't renew user token")
        errorTrace("alternativeNord.py", "API call was " + download_url + ", " + download_data[:download_data.index("renewToken")+11] + "********")
        errorTrace("alternativeNord.py", "Response was " + str(e.code) + " " + e.reason)
        errorTrace("alternativeNord.py", e.read())
    except Exception as e:
        errorTrace("alternativeNord.py", "Couldn't renew user token")
        errorTrace("alternativeNord.py", "API call was " + download_url + ", " + download_data[:download_data.index("renewToken")+11] + "********")
        errorTrace("alternativeNord.py", "Response was " + str(type(e)) + " " + str(e))
    resetTokens()
    return False 
Exemple #3
0
def authenticateNordVPN(vpn_provider, userid, password):
    # Authenticate with the API and store the tokens returned

    # If the same credentials have been used before, don't bother authenticating
    _, _, _, creds = getTokens()
    if creds == vpn_provider + userid + password:
        debugTrace("Previous authentication was good")
        return True

    response = ""
    try:
        download_url = "https://api.nordvpn.com/v1/users/tokens"
        download_data = urllib.urlencode({
            'username': userid,
            'password': password
        })
        if ifHTTPTrace():
            infoTrace(
                "alternativeNord.py", "Authenticating with VPN using " +
                download_url + ", " + download_data)
        else:
            debugTrace("Authenticating with VPN for user " + userid)
        req = urllib2.Request(download_url, download_data)
        t_before = now()
        response = urllib2.urlopen(req, timeout=10)
        user_data = json.load(response)
        t_after = now()
        response.close()
        if ifJSONTrace():
            infoTrace("alternativeNord.py",
                      "JSON received is \n" + json.dumps(user_data, indent=4))
        if t_after - t_before > TIME_WARN:
            infoTrace(
                "alternativeNord.py", "Authenticating with VPN for " + userid +
                " took " + str(t_after - t_before) + " seconds")
        setTokens(user_data["token"], user_data["renew_token"], None)
        setTokens(user_data["token"], user_data["renew_token"],
                  vpn_provider + userid + password)
        return True
    except urllib2.HTTPError as e:
        errorTrace("alternativeNord.py",
                   "Couldn't authenticate with " + vpn_provider)
        errorTrace(
            "alternativeNord.py", "API call was " + download_url + ", " +
            download_data[:download_data.index("&password") + 10] + "********")
        errorTrace("alternativeNord.py",
                   "Response was " + str(e.code) + " " + e.reason)
        errorTrace("alternativeNord.py", e.read())
    except Exception as e:
        errorTrace("alternativeNord.py",
                   "Couldn't authenticate with " + vpn_provider)
        errorTrace(
            "alternativeNord.py", "API call was " + download_url + ", " +
            download_data[:download_data.index("&password") + 10] + "********")
        errorTrace("alternativeNord.py",
                   "Response was " + str(type(e)) + " " + str(e))
    resetTokens()
    return False
Exemple #4
0
def getNordVPNOvpnFile(server, protocol, target_file):
    # Download the opvn file
    try:

        download_url = "https://downloads.nordcdn.com/configs/files/ovpn_" + protocol + "/servers/" + server + "." + protocol + ".ovpn"
        if ifHTTPTrace():
            infoTrace(
                "alternativeNord.py", "Downloading ovpn for " + server +
                ", protocol " + protocol + " using " + download_url)
        else:
            debugTrace("Downloading ovpn for " + server + ", protocol " +
                       protocol)
        token = getTokenNordVPN()
        req = urllib2.Request(download_url)
        req.add_header("Authorization", "token:" + token)
        t_before = now()
        response = urllib2.urlopen(req, timeout=10)
        lines = response.readlines()
        t_after = now()
        response.close()
        if t_after - t_before > TIME_WARN:
            infoTrace(
                "alternativeNord.py",
                "Downloading ovpn for " + server + ", protocol " + protocol +
                " took " + str(t_after - t_before) + " seconds")
    except urllib2.HTTPError as e:
        errorTrace(
            "alternativeNord.py", "Couldn't download the ovpn for server " +
            server + ", protocol " + protocol)
        errorTrace("alternativeNord.py", "API call was " + download_url)
        errorTrace("alternativeNord.py",
                   "Response was " + str(e.code) + " " + e.reason)
        errorTrace("alternativeNord.py", e.read())
        return False
    except Exception as e:
        errorTrace(
            "alternativeNord.py", "Couldn't download the ovpn for server " +
            server + ", protocol " + protocol)
        errorTrace("alternativeNord.py", "API call was " + download_url)
        errorTrace("alternativeNord.py",
                   "Response was " + str(type(e)) + " " + str(e))
        return False

    try:
        debugTrace("Writing ovpn file to " + target_file)
        f = open(target_file, 'w')
        for line in lines:
            line = line.strip(' \t\n\r')
            f.write(line + "\n")
        f.close()
        return True
    except Exception as e:
        errorTrace("alternativeNord.py",
                   "Couldn't write ovpn to " + target_file)
        errorTrace("alternativeNord.py", str(e))
        return False
def sendAPI(command, command_text, api_data, check_response):
    # Common routine to send an API command
    try:
        response = ""
        rc = True
        rest_url = REQUEST_URL + command
        
        auth_token,_,_,_ = getTokens()
        # Login again if the token is blank and the command is not login anyway
        if auth_token == "" and not "=login" in command:
            debugTrace("Logging in again because auth token not valid")
            addon = xbmcaddon.Addon(getID())
            rc = authenticateShellfire(addon.getSetting("vpn_provider"), addon.getSetting("vpn_username"), addon.getSetting("vpn_password"))
            auth_token,_,_,_ = getTokens()
            if auth_token == "" or not rc:
                raise Exception(command_text + " was not authorized")
        
        if ifHTTPTrace(): infoTrace("alternativeShellfire.py", command_text + " " + rest_url)     
        else: debugTrace(command_text)
        
        req = urllib2.Request(rest_url, api_data, REQUEST_HEADERS)
        if not auth_token == "": req.add_header("x-authorization-token", auth_token)
        t_before = now()
        response = urllib2.urlopen(req)
        api_data = json.load(response)   
        t_after = now()    
        response.close()

        # Trace if the command took a long time
        if ifJSONTrace(): infoTrace("alternativeShellfire.py", "JSON received is \n" + json.dumps(api_data, indent=4))
        if t_after - t_before > TIME_WARN: infoTrace("alternativeShellfire.py", command_text + " took " + str(t_after - t_before) + " seconds")
        
        # Check the response and fail if it's bad
        if check_response:
            if not api_data["status"] == "success":
                raise Exception(command_text + " returned bad response, " + api_data["status"])
        
    except urllib2.HTTPError as e:
        errorTrace("alternativeShellfire.py", command_text + " failed")
        errorTrace("alternativeShellfire.py", "API call was " + rest_url)
        if not api_data == "": errorTrace("alternativeShellfire.py", "Data returned was \n" + json.dumps(api_data, indent=4))
        errorTrace("alternativeShellfire.py", "Response was " + str(e.code) + " " + e.reason)
        errorTrace("alternativeShellfire.py", e.read())
        rc = False
    except Exception as e:
        errorTrace("alternativeShellfire.py", command_text + " failed")
        errorTrace("alternativeShellfire.py", "API call was " + rest_url)
        if not api_data == "": errorTrace("alternativeShellfire.py", "Data returned was \n" + json.dumps(api_data, indent=4))
        errorTrace("alternativeShellfire.py", "Response was " + str(type(e)) + " " + str(e))
        rc = False
    
    return rc, api_data
Exemple #6
0
def getTokenNordVPN():
    # Return a token that can be used on API calls
    token, renew, expiry, _ = getTokens()

    # If the expiry time is passed, renew the token
    if expiry.isdigit() and int(expiry) < now():
        if renewNordVPN(renew):
            token, _, _, _ = getTokens()
            return token
        else:
            # Force an authenticate to happen
            token = ""

    # The authentication call is made during connection validation, which will validate everything and fetch
    # the tokens.  If a reboot happens and the tokens disappear, then we need to force an authenticate again
    if token == "":
        addon = xbmcaddon.Addon(getID())
        if authenticateNordVPN(addon.getSetting("vpn_provider_validated"),
                               addon.getSetting("vpn_username_validated"),
                               addon.getSetting("vpn_password_validated")):
            token, _, _, _ = getTokens()
            return token
        else:
            errorTrace("alternativeNord.py",
                       "Couldn't authenticate or renew the user ID")
            resetTokens()
            raise RuntimeError("Couldn't get a user ID token")

    debugTrace("Using existing user ID token")
    return token
Exemple #7
0
def recordAction(action):
    log = getActionLogName(False)
    old_log = getActionLogName(True)
    addon = xbmcaddon.Addon("service.zomboided.tools")
    if addon.getSetting("enable_action_log") == "true":
        try:
            if xbmcvfs.exists(log):
                st = xbmcvfs.Stat(log)
                size = st.st_size()
                if size > 1024000:  # Limit log files to 1MB...this allow for ~10000 entries
                    debugTrace("Action log size is " + str(size) +
                               ", starting new action log")
                    if xbmcvfs.exists(old_log):
                        xbmcvfs.delete(old_log)
                    xbmcvfs.rename(log, old_log)
        except Exception as e:
            errorTrace("common.py", "Couldn't manage existing action log file")
            errorTrace("common.py", str(e))

        try:
            log_file = open(log, 'a+')
            time = datetime.datetime.fromtimestamp(now())
            log_file.write(str(time) + " " + action + "\n")
            log_file.close()
        except Exception as e:
            errorTrace("common.py", "Couldn't record action")
            errorTrace("common.py", str(e))
def getShellfireMessages(vpn_provider, last_time, last_id):
    # Return any message ID and message available from the provider
    
    # Never return a message for a paid account unless a last_time of 0 is being used to force it
    if getAccountType() > 0 and not last_time == 0: return "", ""
    
    # Fetch any available deal
    rc, api_data = sendAPI("?action=getAvailablePricingDeal", "Retrieving messages", "", False)
    # Adding 'Success' to the end of this line will return a test message
    # Check the call worked and that it was successful.  If there's no message, a bad response is returned
    if not rc: return "", ""
    if not api_data["status"] == "success": return "", ""

    try:
        # Extract and format the message
        id = api_data["data"]["pricingDealId"]
        message = api_data["data"]["name"] + " - " + api_data["data"]["description"] + " - Only available until "
        ts = int(api_data["data"]["validUntil"])
        message = message + time.strftime("%b %d", time.gmtime(ts))
        message = message + " - " + api_data["data"]["url"]
        
        # Don't return a message if the same message was displayed < 1 week ago 
        if (not last_time == 0) and (last_time + 604800 > now()) and last_id == id:
            return "", ""
            
    except Exception as e:
        errorTrace("alternativeShellfire.py", "Couldn't format message returned")
        errorTrace("alternativeShellfire.py", "JSON received is \n" + json.dumps(api_data, indent=4))
        return "", ""
    
    return id, message
def setTokens(token, renew, creds):
    xbmcgui.Window(10000).setProperty("VPN_Manager_Alternative_Token", token)
    xbmcgui.Window(10000).setProperty("VPN_Manager_Alternative_Renew", renew)
    # Renew time is a day after token creation
    if not renew == "":
        xbmcgui.Window(10000).setProperty("VPN_Manager_Alternative_Expiry",
                                          str(now() + 86400))
    else:
        xbmcgui.Window(10000).setProperty("VPN_Manager_Alternative_Expiry", "")
    if not creds == None:
        xbmcgui.Window(10000).setProperty(
            "VPN_Manager_Alternative_Credentials", creds)
Exemple #10
0
 def runPlaybackEnded(self, caller):
     global playback_timer
     global sleep_timer
     self.playing_file = False
     playback_timer = 0
     t = now()
     self.playlist_ended = t
     self.playlist_count += 1
     debugTrace("Playback ended called from " + caller + ", at " + str(self.playlist_ended) + ", count is " + str(self.playlist_count) + " sleep is " + getSleep())
     if getSleep() == SLEEP_END:
         addAlert()
         sleep_timer = 1
def getShellfireMessages(vpn_provider, last_time, last_id):
    # Return any message ID and message available from the provider

    # Never return a message for a paid account unless a last_time of 0 is being used to force it
    if getAccountType() > 0 and not last_time == 0: return "", ""

    # Fetch any available deal
    rc, api_data = sendAPI("?action=getAvailablePricingDealSuccess",
                           "Retrieving messages", "", False)
    # FIXME Adding 'Success' to the end of this line will return a test message
    # Check the call worked and that it was successful.  If there's no message, a bad response is returned
    if not rc: return "", ""
    if not api_data["status"] == "success": return "", ""

    try:
        # Extract and format the message
        id = api_data["data"]["pricingDealId"]
        message = api_data["data"]["name"] + " - " + api_data["data"][
            "description"] + " - Only available until "
        ts = int(api_data["data"]["validUntil"])
        message = message + time.strftime("%b %d", time.gmtime(ts))
        message = message + " - " + api_data["data"]["url"]

        # Don't return a message if the same message was displayed < 1 week ago
        if (not last_time
                == 0) and (last_time + 604800 > now()) and last_id == id:
            return "", ""

    except Exception as e:
        errorTrace("alternativeShellfire.py",
                   "Couldn't format message returned")
        errorTrace("alternativeShellfire.py",
                   "JSON received is \n" + json.dumps(api_data, indent=4))
        return "", ""

    return id, message
Exemple #12
0
def getNordVPNPreFetch(vpn_provider):
    # Fetch and store country info from the magical interwebz
    filename = getAddonPath(True, vpn_provider + "/" + NORD_LOCATIONS)
    if xbmcvfs.exists(filename):
        try:
            st = xbmcvfs.Stat(filename)
            create_time = int(st.st_ctime())
            t = now()
            # Fetch again if this is more than a day old otherwise use what there is
            if create_time + 86400 < t:
                debugTrace("Create time of " + filename + " is " +
                           str(create_time) + " time now is " + str(t) +
                           ", fetching country data again")
            else:
                debugTrace("Create time of " + filename + " is " +
                           str(create_time) + " time now is " + str(t) +
                           ", using existing data")
                return True
        except Exception as e:
            errorTrace(
                "alternativeNord.py",
                "List of countries exist but couldn't get the time stamp for "
                + filename)
            errorTrace("alternativeNord.py", str(e))
            return False

    # Download the JSON object of countries
    response = ""
    error = True
    try:
        download_url = "https://api.nordvpn.com/v1/servers/countries"
        if ifHTTPTrace():
            infoTrace("alternativeNord.py",
                      "Downloading list of countries using " + download_url)
        else:
            debugTrace("Downloading list of countries")
        token = getTokenNordVPN()
        req = urllib2.Request(download_url)
        req.add_header("Authorization", "token:" + token)
        t_before = now()
        response = urllib2.urlopen(req, timeout=10)
        country_data = json.load(response)
        t_after = now()
        response.close()
        error = False
        if ifJSONTrace():
            infoTrace(
                "alternativeNord.py",
                "JSON received is \n" + json.dumps(country_data, indent=4))
        if t_after - t_before > TIME_WARN:
            infoTrace(
                "alternativeNord.py", "Downloading list of countries took " +
                str(t_after - t_before) + " seconds")
    except urllib2.HTTPError as e:
        errorTrace(
            "alternativeNord.py",
            "Couldn't retrieve the list of countries for " + vpn_provider)
        errorTrace("alternativeNord.py", "API call was " + download_url)
        errorTrace("alternativeNord.py",
                   "Response was " + str(e.code) + " " + e.reason)
        errorTrace("alternativeNord.py", e.read())
    except Exception as e:
        errorTrace(
            "alternativeNord.py",
            "Couldn't retrieve the list of countries for " + vpn_provider)
        errorTrace("alternativeNord.py", "API call was " + download_url)
        errorTrace("alternativeNord.py",
                   "Response was " + str(type(e)) + " " + str(e))

    if error:
        # Use the existing list of countries if there is one as it'll be pretty much up to date
        if xbmcvfs.exists(filename):
            infoTrace("alternativeNord.py", "Using existing list of countries")
            return True
        else:
            return False

    # Parse the JSON to write out the countries and ID
    try:
        debugTrace("Parsing the JSON and writing the list of countries")
        output = open(filename, 'w')
        for item in country_data:
            name = item["name"].replace(",", "")
            output.write(name + "," + str(item["id"]) + "\n")
        output.close()
        return True
    except Exception as e:
        errorTrace(
            "alternativeNord.py", "Couldn't write the list of countries for " +
            vpn_provider + " to " + filename)
        errorTrace("alternativeNord.py", str(e))

    # Delete the country file if the was a problem creating it.  This will force a download next time through
    try:
        if xbmcvfs.exists(filename):
            errorTrace(
                "alternativeNord.py", "Deleting country file " + filename +
                " to clean up after previous error")
            xbmcvfs.delete(filename)
    except Exception as e:
        errorTrace("alternativeNord.py",
                   "Couldn't delete the country file " + filename)
        errorTrace("alternativeNord.py", str(e))
    return False
def sendAPI(command, command_text, api_data, check_response):
    # Common routine to send an API command
    try:
        response = ""
        rc = True
        rest_url = REQUEST_URL + command

        auth_token, _, _, _ = getTokens()
        # Login again if the token is blank and the command is not login anyway
        if auth_token == "" and not "=login" in command:
            debugTrace("Logging in again because auth token not valid")
            addon = xbmcaddon.Addon(getID())
            rc = authenticateShellfire(addon.getSetting("vpn_provider"),
                                       addon.getSetting("vpn_username"),
                                       addon.getSetting("vpn_password"))
            auth_token, _, _, _ = getTokens()
            if auth_token == "" or not rc:
                raise Exception(command_text + " was not authorized")

        if ifHTTPTrace():
            infoTrace("alternativeShellfire.py", command_text + " " + rest_url)
        else:
            debugTrace(command_text)

        req = urllib2.Request(rest_url, api_data, REQUEST_HEADERS)
        if not auth_token == "":
            req.add_header("x-authorization-token", auth_token)
        t_before = now()
        response = urllib2.urlopen(req)
        api_data = json.load(response)
        t_after = now()
        response.close()

        # Trace if the command took a long time
        if ifJSONTrace():
            infoTrace("alternativeShellfire.py",
                      "JSON received is \n" + json.dumps(api_data, indent=4))
        if t_after - t_before > TIME_WARN:
            infoTrace(
                "alternativeShellfire.py",
                command_text + " took " + str(t_after - t_before) + " seconds")

        # Check the response and fail if it's bad
        if check_response:
            if not api_data["status"] == "success":
                raise Exception(command_text + " returned bad response, " +
                                api_data["status"])

    except urllib2.HTTPError as e:
        errorTrace("alternativeShellfire.py", command_text + " failed")
        errorTrace("alternativeShellfire.py", "API call was " + rest_url)
        if not api_data == "":
            errorTrace("alternativeShellfire.py",
                       "Data returned was \n" + json.dumps(api_data, indent=4))
        errorTrace("alternativeShellfire.py",
                   "Response was " + str(e.code) + " " + e.reason)
        errorTrace("alternativeShellfire.py", e.read())
        rc = False
    except Exception as e:
        errorTrace("alternativeShellfire.py", command_text + " failed")
        errorTrace("alternativeShellfire.py", "API call was " + rest_url)
        if not api_data == "":
            errorTrace("alternativeShellfire.py",
                       "Data returned was \n" + json.dumps(api_data, indent=4))
        errorTrace("alternativeShellfire.py",
                   "Response was " + str(type(e)) + " " + str(e))
        rc = False

    return rc, api_data
def getShellfirePreFetch(vpn_provider):
    # Fetch and store location info
    filename = getAddonPath(True, vpn_provider + "/" + SHELLFIRE_LOCATIONS)
    if xbmcvfs.exists(filename):
        try:
            st = xbmcvfs.Stat(filename)
            create_time = int(st.st_ctime())
            t = now()
            # Fetch again if this is more than a day old otherwise use what there is
            if create_time + 86400 < t:
                debugTrace("Create time of " + filename + " is " +
                           str(create_time) + " time now is " + str(t) +
                           ", fetching location data again")
            else:
                debugTrace("Create time of " + filename + " is " +
                           str(create_time) + " time now is " + str(t) +
                           ", using existing data")
                # Less than a day old, so using the existing file
                return True
        except Exception as e:
            errorTrace(
                "alternativeShellfire.py",
                "List of countries exist but couldn't get the time stamp for "
                + filename)
            errorTrace("alternativeShellfire.py", str(e))
            return False

    # Download the list of locations
    error = True
    try:
        response = ""
        api_data = ""
        rest_url = "https://www.shellfire.de/webservice/serverlist.php"

        if ifHTTPTrace():
            infoTrace("alternativeShellfire.py",
                      "Downloading list of locations using " + rest_url)
        else:
            debugTrace("Downloading list of locations")

        # This is not a JSON call, a header and servers are returned in a ; separated list
        req = urllib2.Request(rest_url, "", REQUEST_HEADERS)
        t_before = now()
        response = urllib2.urlopen(req)
        api_data = response.read()
        t_after = now()
        response.close()

        if ifJSONTrace():
            infoTrace("alternativeShellfire.py",
                      "Text received is \n" + api_data)
        if t_after - t_before > TIME_WARN:
            infoTrace(
                "alternativeShellfire.py",
                "Retrieving list of locations took " +
                str(t_after - t_before) + " seconds")

    except urllib2.HTTPError as e:
        errorTrace("alternativeShellfire.py",
                   "Couldn't retrieve the list of locations")
        errorTrace("alternativeShellfire.py", "API call was " + rest_url)
        if not api_data == "":
            errorTrace("alternativeShellfire.py",
                       "Data returned was \n" + api_data)
        errorTrace("alternativeShellfire.py",
                   "Response was " + str(e.code) + " " + e.reason)
        errorTrace("alternativeShellfire.py", e.read())
        return False
    except Exception as e:
        errorTrace("alternativeShellfire.py",
                   "Couldn't retrieve the list of locations")
        errorTrace("alternativeShellfire.py", "API call was " + rest_url)
        if not api_data == "":
            errorTrace("alternativeShellfire.py",
                       "Data returned was \n" + api_data)
        errorTrace("alternativeShellfire.py",
                   "Response was " + str(type(e)) + " " + str(e))
        return False

    # The first line has the headers, so find the position of the information that's interesting
    api_table = api_data.split("\n")
    headers = api_table[0].split(";")
    id_pos = headers.index("iVpnServerId")
    country_pos = headers.index("Country")
    city_pos = headers.index("sCity")
    host_pos = headers.index("sHost")
    type_pos = headers.index("eServerType")
    debugTrace("Header decoded.  ID is " + str(id_pos) + ", Country is " +
               str(country_pos) + ", City is " + str(city_pos) + ", Host is " +
               str(host_pos) + ", Type is " + str(type_pos))
    api_table[0] = ""

    try:
        line = ""
        cleaned_data = []
        debugTrace(
            "Parsing the text and extracting the country, server and type")
        for line in api_table:
            server_data = line.split(";")
            # Avoid parsing empty lines, or lines where there's not enough data
            if len(server_data) > 5:
                cleaned_data.append(server_data[country_pos] + " - " +
                                    server_data[city_pos] + " (S" +
                                    server_data[id_pos] + ")," +
                                    server_data[host_pos] + "," +
                                    server_data[type_pos] + "," +
                                    server_data[id_pos] + "\n")
    except Exception as e:
        errorTrace("alternativeShellfire`.py",
                   "Couldn't parse the list of locations for " + vpn_provider)
        if not server_data == "":
            errorTrace("alternativeShellfire.py", "Processing line " + line)
        errorTrace("alternativeShellfire.py", str(e))
        return False

    # Sort the locations alphabetically
    cleaned_data.sort()

    try:
        line = ""
        debugTrace("Parsing the text and writing the list of locations")
        output = open(filename, 'w')
        # Parse the data and create list containing the stuff we care about
        for line in cleaned_data:
            output.write(line)
        output.close()
        return True
    except Exception as e:
        errorTrace(
            "alternativeShellfire`.py",
            "Couldn't write the list of locations for " + vpn_provider +
            " to " + filename)
        if not server_data == "":
            errorTrace("alternativeShellfire.py", "Processing server " + line)
        errorTrace("alternativeShellfire.py", str(e))

    # Delete the location file if the was a problem creating it.  This will force a download next time through
    try:
        if xbmcvfs.exists(filename):
            errorTrace(
                "alternativeShellfire.py", "Deleting location file " +
                filename + " to clean up after previous error")
            xbmcvfs.delete(filename)
    except Exception as e:
        errorTrace("alternativeShellfire.py",
                   "Couldn't delete the location file " + filename)
        errorTrace("alternativeShellfire.py", str(e))
    return False
Exemple #15
0
def getNordVPNLocation(vpn_provider, location, server_count, just_name):
    # Return friendly name and .ovpn file name
    # Given the location, find the country ID of the servers
    addon = xbmcaddon.Addon(getID())

    filename = getAddonPath(True, vpn_provider + "/" + NORD_LOCATIONS)
    # If the list of countries doesn't exist (this can happen after a reinstall)
    # then go and do the pre-fetch first.  Otherwise this shouldn't be necessary
    try:
        if not xbmcvfs.exists(filename):
            getNordVPNPreFetch(vpn_provider)
    except Exception as e:
        errorTrace(
            "alternativeNord.py",
            "Couldn't download the list of countries to get ID for " +
            vpn_provider + " from " + filename)
        errorTrace("alternativeNord.py", str(e))
        return "", "", "", False

    try:
        locations_file = open(filename, 'r')
        locations = locations_file.readlines()
        locations_file.close()
        id = ""
        for l in locations:
            country, id = l.split(",")
            id = id.strip(' \t\n\r')
            if location == country:
                break
        if id == "":
            errorTrace(
                "alternativeNord.py", "Couldn't retrieve location " +
                location + " for " + vpn_provider + " from " + filename)
            return "", "", "", False
    except Exception as e:
        errorTrace(
            "alternativeNord.py",
            "Couldn't read the list of countries to get ID for " +
            vpn_provider + " from " + filename)
        errorTrace("alternativeNord.py", str(e))
        return "", "", "", False

    # Generate the file name from the location
    location_filename = getNordVPNLocationName(vpn_provider, location)

    if just_name: return location, location_filename, "", False

    # Download the JSON object of servers
    response = ""
    error = True
    try:
        if "UDP" in addon.getSetting("vpn_protocol"): protocol = "udp"
        else: protocol = "tcp"
        download_url = "https://api.nordvpn.com/v1/servers/recommendations?filters[servers_technologies][identifier]=openvpn_" + protocol + "&filters[country_id]=" + id + "&filters[servers_groups][identifier]=legacy_standard"
        if ifHTTPTrace():
            infoTrace(
                "alternativeNord.py",
                "Downloading server info for " + location + " with ID " + id +
                " and protocol " + protocol + " using " + download_url)
        else:
            debugTrace("Downloading server info for " + location +
                       " with ID " + id + " and protocol " + protocol)
        token = getTokenNordVPN()
        req = urllib2.Request(download_url)
        req.add_header("Authorization", "token:" + token)
        t_before = now()
        response = urllib2.urlopen(req, timeout=10)
        server_data = json.load(response)
        t_after = now()
        response.close()
        error = False
        if ifJSONTrace():
            infoTrace(
                "alternativeNord.py",
                "JSON received is \n" + json.dumps(server_data, indent=4))
        if t_after - t_before > TIME_WARN:
            infoTrace(
                "alternativeNord.py", "Downloading server info for " +
                location + " with ID " + id + " and protocol " + protocol +
                " took " + str(t_after - t_before) + " seconds")
    except urllib2.HTTPError as e:
        errorTrace(
            "alternativeNord.py", "Couldn't retrieve the server info for " +
            vpn_provider + " location " + location + ", ID " + id)
        errorTrace("alternativeNord.py", "API call was " + download_url)
        errorTrace("alternativeNord.py",
                   "Response was " + str(e.code) + " " + e.reason)
        errorTrace("alternativeNord.py", e.read())
    except Exception as e:
        errorTrace(
            "alternativeNord.py", "Couldn't retrieve the server info for " +
            vpn_provider + " location " + location + ", ID " + id)
        errorTrace("alternativeNord.py", "API call was " + download_url)
        errorTrace("alternativeNord.py",
                   "Response was " + str(type(e)) + " " + str(e))

    if error:
        # If there's an API connectivity issue but a location file exists then use that
        # Won't have the latest best location in it though
        if xbmcvfs.exists(location_filename):
            infoTrace("alternativeNord.py",
                      "Using existing " + location + " file")
            return location, location_filename, "", False
        else:
            return "", "", "", False

    # First server is the best one, but if it didn't connect last time then skip it.  The last attempted server
    # will be cleared on a restart, or a successful connection.  If there are no more connections to try, then
    # it will try the first connection again.  However, if this is > 4th attempt to connect outside of the
    # validation then it'll always default to the best as it's likely there's a network rather than server problem
    last = getVPNRequestedServer()
    if not last == "" and server_count < 5:
        debugTrace(
            "Server " + last +
            " didn't connect last time so will be skipping to the next server."
        )
        last_found = False
    else:
        last = ""
        last_found = True
    first_server = ""
    for item in server_data:
        name = item["name"]
        server = item["hostname"]
        status = item["status"]
        load = str(item["load"])
        #debugTrace("Next is " + name + ", " + server + ", " + status + ". Load is " + load)
        if status == "online":
            if first_server == "": first_server = server
            if last_found:
                debugTrace("Using " + name + ", " + server +
                           ", online. Load is " + load)
                break
            if server == last: last_found = True
        server = ""
    if server == "": server = first_server
    setVPNRequestedServer(server)
    setVPNURL(server)

    # Fetch the ovpn file for the server
    if not server == "":
        if not getNordVPNOvpnFile(server, protocol, location_filename):
            if not xbmcvfs.exists(location_filename):
                return "", "", "", False
        return location, location_filename, "", False
    else:
        return "", "", "", False
Exemple #16
0
        try:
            api = VPNAPI()
            debugTrace("Found VPN Manager")
        except Exception as e:
            errorTrace("service.py", "Couldn't connect to the VPN Mgr API")
            errorTrace("service.py", str(e))
            api = None
    
    # Initialise some variables we'll be using repeatedly    
    addon = xbmcaddon.Addon()
    
    allowUpdates(False)
    addon.setSetting("boot_time", time.strftime('%Y-%m-%d %H:%M:%S'))
    allowUpdates(True)
    
    last_boot = now()
    
    updateSettings("main initialisation", True)
    
    # Initialise a bunch of variables
    delay = 10
    delay_loop = 6

    file_timer = 0
    last_file_check = 0
    action_number_f = 0
    addon_timer = 0
    last_addon_check = 0
    action_number_a = 0
    last_sleep = SLEEP_OFF
    sleep_timer = 0
Exemple #17
0
 def onPlayBackStarted(self, *arg):
     global playback_timer
     
     addon = xbmcaddon.Addon()
     
     # Deal with endPlayback not being called previously
     if self.playing_file: self.runPlaybackEnded()
     self.playing_file = True
     
     t = now()
     
     try:
         infoTrace("service.py", "Playing " + self.getPlayingFile())
         recordAction("Playing " + self.getPlayingFile())
     except:
         pass
     
     # Determine the end time if there's a play back limit
     d_timer = 0
     t_timer = 0
     playback_timer = 0
     
     if playback_duration_check: d_timer = t + (playback_duration_minutes * 60)
     if playback_time_check: t_timer = parseTimer("Play back timer", "Daily", playback_time, "", "", "", 0)
     if not d_timer == 0 and (d_timer < t_timer or t_timer == 0): playback_timer = d_timer
     if not t_timer == 0 and (t_timer < d_timer or d_timer == 0): playback_timer = t_timer
     if playback_timer: debugTrace("Time is " + str(t) + " playing until " + str(playback_timer) + ". Duration was " + str(playback_duration_minutes) + ", time was " + playback_time)
     
     # If playback ended some time ago, this isn't a playlist
     if self.playlist_playing and t - self.playlist_ended > playlist_detection_delay:
         debugTrace("Playlist is over")
         debugTrace("Ended because time between videos was " + str(t-self.playlist_ended) + " seconds, max is " + str(playlist_detection_delay))
         self.resetPlaybackCounts()
     
     if not self.playlist_playing:
         # If a playlist isn't active, this is the first video in a playlist (or otherwise)
         updateSettings("onPlayBackStarted", True)
         self.playlist_playing = True
         self.playlist_max = t + (playlist_max_minutes * 60)
         self.playlist_count = 1
         debugTrace("Detected playback starting")
         debugTrace("Max playback time is " + str(playlist_max_minutes))
         debugTrace("Max playback videos is " + str(playlist_max_count))
         debugTrace("Time is " + str(t) + " max time is " + str(self.playlist_max))
     else:
         # This is not the first video in a playlist
         if playlist_count_check: debugTrace("Count is " + str(self.playlist_count) + ", max is " + str(playlist_max_count) + ", min is " + str(playlist_min_count))
         if playlist_time_check: debugTrace("Time is " + str(t) + ", timeout is " + str(self.playlist_max))
         if playlist_count_check and self.playlist_count >= playlist_max_count:
             xbmc.Player().stop()
             infoTrace("service.py", "Stopping playlist after playing " + str(playlist_max_count) + " videos.")
             self.resetPlaybackCounts()
         elif playlist_time_check and t > self.playlist_max and self.playlist_count >= playlist_min_count:
             xbmc.Player().stop()
             infoTrace("service.py", "Stopping playlist after reaching maximum time period")
             self.resetPlaybackCounts()
     
     if addon.getSetting("auto_sleep") == "true" and t > auto_sleep_start and t < auto_sleep_end:
         if getSleep() == SLEEP_OFF:
             debugTrace("Setting auto sleep")
             setSleepReq("End")
             setSleepReqTime(t-SLEEP_DELAY_TIME)
             xbmcgui.Dialog().notification("Sleeping at end of video." , "", "", 2000, False)
             addAlert()
Exemple #18
0
def parseTimer(type, freq, rtime, day, date, period, begin):
    debugTrace("Parsing " + type + ". Frequency is " + freq + ", time is + " + rtime + ", day is " + day + ", date is " + date + ", period is " + period + ", begin is " + str(begin))
    if freq == "" or freq == "Off": 
        return 0
    else:
        # Assume timer is today at the defined reboot time
        timer = time.strftime("%d %m %Y") + " " + rtime
        # Parse the timer starting from a given time, or now
        if begin > 0:
            t = begin
        else:
            t = now()
                    
        # Make some datetime objects representing now, last boot time and the timer
        current_dt = datetime.datetime.fromtimestamp(t)
        last_dt = datetime.datetime.fromtimestamp(last_boot)
        #xbmc.sleep(1000)
        #try:
        #    timer_dt = datetime.datetime.strptime(timer, "%d %m %Y %H:%M")
        #except:
        timer_dt = datetime.datetime(*(time.strptime(timer, "%d %m %Y %H:%M")[0:6]))
        # Adjust timer based on the frequency
        if freq == "Daily":
            # If the timer is in the past, add a day
            if timer_dt < current_dt and not begin == TODAY: 
                d = datetime.timedelta(days = 1)
                timer_dt = timer_dt + d
        elif freq == "Weekly":
            # Calculate the next boot day
            current_day = current_dt.weekday()
            timer_day = days.index(day)
            if current_day > timer_day:
                adjust_day = 7 - (current_day - timer_day)
            elif current_day < timer_day:
                adjust_day = timer_day - current_day
            else:
                # Same day, if it's in the past, add a week
                if timer_dt < current_dt: adjust_day = 7
                else: adjust_day = 0
            # Adjust the timer the required number of days
            if adjust_day > 0:
                d = datetime.timedelta(days = adjust_day)
                timer_dt = timer_dt + d
        elif freq == "Monthly":
            new_day = int(date)
            if (current_dt.day > new_day) or (current_dt.day == new_day and timer_dt < current_dt):
                if current_dt.month == 12:
                    timer_dt = timer_dt.replace(month = 1)
                    timer_dt = timer_dt.replace(year = timer_dt.year + 1)
                else:
                    timer_dt = timer_dt.replace(month = timer_dt.month + 1)
            _, max_day = calendar.monthrange(timer_dt.year, timer_dt.month)
            if new_day > max_day: new_day = max_day 
            timer_dt = timer_dt.replace(day = new_day)
        elif freq == "Periodically":
            timer_dt == datetime.datetime.combine(last_dt.date(), timer_dt.timetz())
            d = datetime.timedelta(days = int(period))
            timer_dt = timer_dt + d
        else:
            errorTrace("service.py", "Couldn't parse timer, no timer set")
            return 0
        # Calculate the difference between the dates and return the timer value in epoch seconds
        debugTrace("Starting time is " + str(current_dt) + ", last reboot is " + str(last_dt) + ", timer is " + str(timer_dt))
        diff_seconds = int((timer_dt - current_dt).total_seconds())
        return (t + diff_seconds)
Exemple #19
0
def updateSettings(caller, wait):
    global playback_duration_check
    global playback_duration_minutes
    global playback_time_check
    global playback_time
    global playlist_detection_delay
    global playlist_time_check
    global playlist_max_minutes
    global playlist_count_check
    global playlist_max_count
    global playlist_min_count
    global action_timer
    global action_timer_number
    global addon_timer
    global addon_timer_start
    global addon_timer_end
    global addon_check_freq
    global file_timer
    global file_timer_start
    global file_timer_end
    global file_check_freq
    global refresh_timer
    global refresh_check_freq
    global auto_sleep_start
    global auto_sleep_end
    
    if not updatesAllowed() and not wait: return
    
    # Wait for 60 seconds, then carry on anyway
    for i in range(1, 60):
        if updatesAllowed(): break
        xbmc.sleep(1000)
        if i == 59: errorTrace("service.py", "updateSettings was called from " + caller + " with wait, but could not get a lock to update after 60 seconds")
    
    debugTrace("updateSettings called from " + caller)
    refresh_timer = 0
    allowUpdates(False)
    
    addon = xbmcaddon.Addon()
    
    # Refresh the play limit settings
    if addon.getSetting("stop_playback_duration") == "true": playback_duration_check = True
    else: playback_duration_check = False
    playback_duration_minutes = int(addon.getSetting("stop_playback_mins"))
    if addon.getSetting("stop_playback_after") == "true": playback_time_check = True
    else: playback_time_check = False
    playback_time = addon.getSetting("stop_playback_time")
    
    # Refresh the playlist settings
    if addon.getSetting("stop_playlist_time") == "true": playlist_time_check = True
    else: playlist_time_check = False
    playlist_max_minutes = int(addon.getSetting("stop_playlist_mins"))
    if addon.getSetting("stop_playlist_videos") == "true": playlist_count_check = True
    else: playlist_count_check = False
    playlist_max_count = int(addon.getSetting("stop_playlist_count"))
    playlist_min_count = int(addon.getSetting("detect_playlist_minimum"))
    playlist_detection_delay = int(addon.getSetting("detect_playlist_gap"))
    
    # The warning timers should be 10 second increments so fix if it's not
    for i in range(1, (ACTION_COUNT + 1)):
        fixWarnTime("action_warn_" + str(i))
    fixWarnTime("sleep_warn")
    addon = xbmcaddon.Addon()
        
    # Refresh the action settings
    action_timer = 0
    action_timer_number = 0
    for i in range(0, ACTION_COUNT):
        # Check the timer settings
        j = str(i+1)
        
        # Start counting periodical timers from the time they were set.  If it's not
        # a periodical timer, then reset it so it starts from now next time it's set
        if addon.getSetting("action_timer_freq_" + j) == "Periodically":
            if addon.getSetting("action_period_last_" + j) == "":
                addon.setSetting("action_period_last_" + j, str(now()))
            begin = int(addon.getSetting("action_period_last_" + j))
        else:
            addon.setSetting("action_period_last_" + j, "")
            begin = 0
        
        next_action_timer = parseTimer("Action Timer " + j,
                                       addon.getSetting("action_timer_freq_" + j),
                                       addon.getSetting("action_time_" + j),
                                       addon.getSetting("action_day_" + j),
                                       addon.getSetting("action_date_" + j),
                                       addon.getSetting("action_period_" + j),                                       
                                       begin)
        # Determine if this time is the nearest one and use it if it is
        if (action_timer == 0 and not next_action_timer == 0) or (next_action_timer > 0 and next_action_timer < action_timer):
            action_timer_number = i + 1
            action_timer = next_action_timer
            
        if addon.getSetting("action_addon_enabled_" + j) == "true":
            selected = addon.getSetting("action_addon_" + j)
            last = addon.getSetting("addon_name_" + j)
            if not selected == last: addon_timer = addon_check_freq + 1
        
    t = now()
    
    # Frequency add-ons are checked
    addon_check_freq = int(addon.getSetting("addon_check"))*60
    addon_timer_start, addon_timer_end = parseTimePeriod(t, "Addon Check", addon.getSetting("addon_check_start"), addon.getSetting("addon_check_end"))
    
    # Frequency files are checked
    file_check_freq = int(addon.getSetting("file_check"))*60
    file_timer_start, file_timer_end = parseTimePeriod(t, "File Check", addon.getSetting("file_check_start"), addon.getSetting("file_check_end"))

    # Auto sleep timers
    auto_sleep_start, auto_sleep_end = parseTimePeriod(t, "Auto Sleep", addon.getSetting("auto_sleep_start"), addon.getSetting("auto_sleep_end"))

    # Settings get refreshed infrequently, just in case...
    refresh_check_freq = int(addon.getSetting("refresh_check"))*60
    
    if not action_timer_number == 0:
        debugTrace("Action timer " + str(action_timer_number) + " is the first timer with " + str(action_timer))
    else:
        debugTrace("No action timers are set")
        
    # Create the buttons file and make it autostart
    getButtonCommands()
    addon = xbmcaddon.Addon()
    if makeButtonsFile():
        debugTrace("Created a new button file")
        if fixAutostart(): debugTrace("Updated autostart to run zbutton.py")
    
    allowUpdates(True)
def getShellfirePreFetch(vpn_provider):
    # Fetch and store location info
    filename = getAddonPath(True, vpn_provider + "/" + SHELLFIRE_LOCATIONS)
    if xbmcvfs.exists(filename):
        try:
            st = xbmcvfs.Stat(filename)
            create_time = int(st.st_ctime())
            t = now()
            # Fetch again if this is more than a day old otherwise use what there is
            if create_time + 86400 < t:
                debugTrace("Create time of " + filename + " is " + str(create_time) + " time now is " + str(t) + ", fetching location data again")
            else:
                debugTrace("Create time of " + filename + " is " + str(create_time) + " time now is " + str(t) + ", using existing data")
                # Less than a day old, so using the existing file
                return True
        except Exception as e:
            errorTrace("alternativeShellfire.py", "List of countries exist but couldn't get the time stamp for " + filename)
            errorTrace("alternativeShellfire.py", str(e))
            return False

    # Download the list of locations
    error = True
    try:
        response = ""
        api_data = ""
        rest_url = "https://www.shellfire.de/webservice/serverlist.php"
        
        if ifHTTPTrace(): infoTrace("alternativeShellfire.py", "Downloading list of locations using " + rest_url)
        else: debugTrace("Downloading list of locations")
        
        # This is not a JSON call, a header and servers are returned in a ; separated list
        req = urllib2.Request(rest_url, "", REQUEST_HEADERS)
        t_before = now()
        response = urllib2.urlopen(req)
        api_data = response.read()
        t_after = now()    
        response.close()

        if ifJSONTrace(): infoTrace("alternativeShellfire.py", "Text received is \n" + api_data)
        if t_after - t_before > TIME_WARN: infoTrace("alternativeShellfire.py", "Retrieving list of locations took " + str(t_after - t_before) + " seconds")
        
    except urllib2.HTTPError as e:
        errorTrace("alternativeShellfire.py", "Couldn't retrieve the list of locations")
        errorTrace("alternativeShellfire.py", "API call was " + rest_url)
        if not api_data == "": errorTrace("alternativeShellfire.py", "Data returned was \n" + api_data)
        errorTrace("alternativeShellfire.py", "Response was " + str(e.code) + " " + e.reason)
        errorTrace("alternativeShellfire.py", e.read())
        return False
    except Exception as e:
        errorTrace("alternativeShellfire.py", "Couldn't retrieve the list of locations")
        errorTrace("alternativeShellfire.py", "API call was " + rest_url)
        if not api_data == "": errorTrace("alternativeShellfire.py", "Data returned was \n" + api_data)
        errorTrace("alternativeShellfire.py", "Response was " + str(type(e)) + " " + str(e))
        return False
            
    # The first line has the headers, so find the position of the information that's interesting
    api_table = api_data.split("\n") 
    headers = api_table[0].split(";")
    id_pos = headers.index("iVpnServerId")
    country_pos = headers.index("Country")
    city_pos = headers.index("sCity")
    host_pos = headers.index("sHost")
    type_pos = headers.index("eServerType")    
    debugTrace("Header decoded.  ID is " + str(id_pos) + ", Country is " + str(country_pos) + ", City is " + str(city_pos) + ", Host is " + str(host_pos) + ", Type is " + str(type_pos))
    api_table[0] = ""
    
    try:
        line = ""
        cleaned_data = []
        debugTrace("Parsing the text and extracting the country, server and type")
        for line in api_table:       
            server_data = line.split(";")
            # Avoid parsing empty lines, or lines where there's not enough data
            if len(server_data) > 5:
                cleaned_data.append(server_data[country_pos] + " - " + server_data[city_pos] + " (S" + server_data[id_pos] + ")," + server_data[host_pos] + "," + server_data[type_pos] + "," + server_data[id_pos] + "\n")
    except Exception as e:
        errorTrace("alternativeShellfire`.py", "Couldn't parse the list of locations for " + vpn_provider)
        if not server_data == "": errorTrace("alternativeShellfire.py", "Processing line " + line)
        errorTrace("alternativeShellfire.py", str(e))
        return False
        
    # Sort the locations alphabetically
    cleaned_data.sort()    
        
    try:
        line = ""
        debugTrace("Parsing the text and writing the list of locations")
        output = open(filename, 'w')
        # Parse the data and create list containing the stuff we care about
        for line in cleaned_data:       
            output.write(line)
        output.close()
        return True
    except Exception as e:
        errorTrace("alternativeShellfire`.py", "Couldn't write the list of locations for " + vpn_provider + " to " + filename)
        if not server_data == "": errorTrace("alternativeShellfire.py", "Processing server " + line)
        errorTrace("alternativeShellfire.py", str(e))

    # Delete the location file if the was a problem creating it.  This will force a download next time through
    try:
        if xbmcvfs.exists(filename): 
            errorTrace("alternativeShellfire.py", "Deleting location file " + filename + " to clean up after previous error")
            xbmcvfs.delete(filename)
    except Exception as e:
        errorTrace("alternativeShellfire.py", "Couldn't delete the location file " + filename)
        errorTrace("alternativeShellfire.py", str(e))
    return False
Exemple #21
0
def requestSleep():

    # Don't know where this was called from so using plugin name to get addon handle
    addon = xbmcaddon.Addon("service.zomboided.tools")
    addon_name = addon.getAddonInfo("name")

    # Don't sleep if we can't get a lock
    if getSleepLock():
        t = now()
        remain = getSleepRemaining()
        if t - getSleepReqTime() < SLEEP_DELAY_TIME:
            # The last time sleep was requested was very recently so move to next value
            current = getSleepReq()
            if current == "": current = getSleep()
            if current == SLEEP_OFF:
                current = "End"
            elif current == SLEEP_END:
                current = addon.getSetting("sleep_inc")
            elif current.isdigit():
                current_int = int(current)
                if getSleepReq() == "" and remain.isdigit():
                    # This deals with the case where a timer is running already
                    current_int = int(remain)
                sleep_max = int(addon.getSetting("sleep_max"))
                sleep_inc = int(addon.getSetting("sleep_inc"))
                if current_int >= sleep_max:
                    current = SLEEP_OFF
                else:
                    if current_int + sleep_inc > sleep_max:
                        current = addon.getSetting("sleep_max")
                    else:
                        current = str(
                            ((current_int / sleep_inc) + 1) * sleep_inc)
            else:
                current == SLEEP_OFF
            setSleepReq(current)
            debugTrace("Repeat sleep request, " + current + ", remain is " +
                       "")
        else:
            # Otherwise get the value of the current sleep state and display it
            if remain == "":
                current = getSleep()
            else:
                current = remain
            debugTrace("New sleep request, " + current + ", remain is " + "")

        if current.isdigit():
            if current == "0":
                xbmcgui.Dialog().notification("Sleeping in less than a minute",
                                              "", "", 2000, False)
            elif current == "1":
                xbmcgui.Dialog().notification("Sleeping in 1 minute", "", "",
                                              2000, False)
            else:
                xbmcgui.Dialog().notification(
                    "Sleeping in " + current + " minutes", "", "", 2000, False)
        else:
            if current == SLEEP_END:
                xbmcgui.Dialog().notification("Sleeping at end of video", "",
                                              "", 2000, False)
            else:
                xbmcgui.Dialog().notification("Sleep is off", "", "", 2000,
                                              False)

        addAlert()
        setSleepReqTime(t)
        xbmc.sleep(1000)
        freeSleepLock()