GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.
Passed
Push — master ( a09f1e...f8a689 )
by David
01:26
created

API.watched()   F

Complexity

Conditions 12

Size

Total Lines 58

Duplication

Lines 0
Ratio 0 %

Importance

Changes 3
Bugs 0 Features 0
Metric Value
cc 12
c 3
b 0
f 0
dl 0
loc 58
rs 3.1729

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

Complexity

Complex classes like API.watched() often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

1
#!/usr/bin/python
2
# -*- coding: UTF-8 -*-
3
4
import sys, os, time
5
#import urllib
6
#import request
7
import json
8
9
import xbmc
10
import interface
11
import httplib
12
13
__addon__ = interface.__addon__
14
def getstr(strid): return interface.getstr(strid)
15
16
REDIRECT_URI = "http://simkl.com"
17
USERFILE     = os.path.join(xbmc.translatePath(__addon__.getAddonInfo("profile")).decode("utf-8"), "simkl_key")
18
xbmc.translatePath("special://profile/simkl_key")
19
20
if not os.path.exists(USERFILE):
21
    os.mkdir(os.path.dirname(USERFILE))
22
    with open(USERFILE, "w+") as f:
23
        f.write("")
24
else:
25
    with open(USERFILE, "r") as f:
26
        xbmc.log("Simkl: Userfile " + str(f.read()))
27
28
APIFILE = os.path.join(os.path.dirname(os.path.realpath(__file__)).strip("lib"), "data", "apikey")
29
xbmc.log("Simkl: APIFILE: {0}".format(APIFILE))
30
with open(APIFILE, "r") as f:
31
    rd = f.read()
32
    d = json.loads(rd)
33
    APIKEY = d["apikey"]
34
    SECRET = d["secret"]
35
    xbmc.log("Simkl: {0}".format(rd))
36
    xbmc.log("Simkl: APIKEY: {0}".format(APIKEY))
37
ATOKEN = 0 #Get atoken from file
38
headers = {"Content-Type": "application-json",
39
    "simkl-api-key": APIKEY}
40
41
class API:
42
    def __init__(self):
43
        self.scrobbled_dict = {} #So it doesn't scrobble 5 times the same chapter
44
        #{"Label":expiration_time}
45
        with open(USERFILE, "r") as f:
46
            self.token = f.readline().strip("\n")
47
            headers["authorization"] = "Bearer " + self.token
48
        try:
49
            self.con = httplib.HTTPSConnection("api.simkl.com")
50
            self.con.request("GET", "/users/settings", headers=headers)
51
            self.USERSETTINGS = json.loads(self.con.getresponse().read().decode("utf-8"))
52
            xbmc.log("Simkl: Usersettings: " + str(self.USERSETTINGS))
53
            self.internet = True
54
            if not os.path.exists(USERFILE):
55
                api.login()
56
        except Exception:
57
            xbmc.log("Simkl: {0}".format("No INTERNET"))
58
            interface.notify(getstr(32027))
59
            self.internet = False
60
61
    def login(self):
62
        url = "/oauth/pin?client_id="
63
        url += APIKEY + "&redirect=" + REDIRECT_URI
64
65
        log = httplib.HTTPSConnection("api.simkl.com")
66
        log.request("GET", url, headers=headers)
67
        r = log.getresponse().read().decode("utf-8")
68
        xbmc.log(r)
69
        rdic = json.loads(r)
70
        #interface.loginDialog(rdic["verification_url"],
71
        #  rdic["user_code"], self.check_login, log, rdic["expires_in"],
72
        #  rdic["interval"], self)
73
74
        pin = rdic["user_code"]
75
        url = rdic["verification_url"]
76
        exp = int(rdic["expires_in"])
77
        ntv = int(rdic["interval"])
78
79
        self.logindialog = interface.loginDialog("simkl-LoginDialog.xml",
80
            __addon__.getAddonInfo("path"), pin=pin, url=url,
81
            check_login=self.check_login, log=log, exp=exp, inter=ntv, api=self)
82
        self.logindialog.doModal()
83
        del self.logindialog
84
85
    def set_atoken(self, token):
86
        global ATOKEN
87
        with open(USERFILE, "w") as f:
88
            f.write(token)
89
        ATOKEN = token
90
        headers["authorization"] = "Bearer "+token
91
        self.token = token
92
93
    def check_login(self, ucode, log): #Log is the connection
94
        url = "/oauth/pin/" + ucode + "?client_id=" + APIKEY
95
        log.request("GET", url, headers=headers)
96
        r = json.loads(log.getresponse().read().decode("utf-8"))
97
        xbmc.log("Simkl:" + str(r))
98
        if r["result"] == "OK":
99
            self.set_atoken(r["access_token"])
100
            log.request("GET", "/users/settings", headers=headers)
101
            r = json.loads(log.getresponse().read().decode("utf-8"))
102
            self.USERSETTINGS = r
103
            return True
104
        elif r["result"] == "KO":
105
            return False
106
107
    def is_user_logged(self):
108
        """ Checks if user is logged in """
109
        failed = False
110
        if "error" in self.USERSETTINGS.keys(): failed = self.USERSETTINGS["error"]
111
        if self.token == "" or failed == "user_token_failed":
112
            xbmc.log("Simkl: User not logged in")
113
            interface.login(0)
114
            return False
115
        else:
116
            #interface.login(self.USERSETTINGS["user"]["name"])
117
            interface.login(1)
118
            return True
119
120
    ### SCROBBLING OR CHECKIN
121
    def lock(self, fname, duration):
122
        xbmc.log("Duration: %s" %duration)
123
        exp = self.scrobbled_dict
124
        exp[fname] = int(time.time() + (105 - float(__addon__.getSetting("scr-pct"))) / 100 * duration)
125
        xbmc.log("Simkl: Locking {0}".format(exp))
126
        self.scrobbled_dict = {fname:exp[fname]} #So there is always only one entry on the dict
127
128
    def is_locked(self, fname):
129
        exp = self.scrobbled_dict
130
        if not (fname in exp.keys()): return 0
131
        xbmc.log("Time: {0}, exp: {1}, Dif: {2}".format(int(time.time()), exp[fname], int(exp[fname]-time.time())))
132
        #When Dif reaches 0, scrobble.
133
        if time.time() < exp[fname]:
134
            xbmc.log("Simkl: Can't scrobble, file locked (alredy scrobbled)")
135
            xbmc.log(str(exp))
136
            return 1
137
        else:
138
            del exp[fname]
139
            return 0
140
141
    def watched(self, item, duration, date=time.strftime('%Y-%m-%d %H:%M:%S'), cnt=0): #OR IDMB, member: only works with movies
142
        filename = item["file"].replace("\\", "/")
143
        if self.is_user_logged() and not self.is_locked(filename):
144
            try:
145
                con = httplib.HTTPSConnection("api.simkl.com")
146
                mediadict = {"movie": "movies", "episode":"shows", "show":"shows"}
147
148
                if item["imdbnumber"] != "":
149
                    if item["type"] == "movie": toappend = {"ids":{"imdb": item["imdbnumber"]}, "watched_at":date}
150
                    elif item["type"] == "episode":
151
                        toappend = {"ids":{"tvdb":item["imdbnumber"]}, "watched_at":date,
152
                        "seasons":[{
153
                            "number":item["season"],
154
                            "episodes":[{"number":item["episode"]}]}]}
155
                    media = mediadict[item["type"]]
156
                else:
157
                    xbmc.log("Simkl: Filename - {0}".format(filename))
158
                    values = json.dumps({"file":filename})
159
                    xbmc.log("Simkl: Query: {0}".format(values))
160
                    con.request("GET", "/search/file/", body=values, headers=headers)
161
                    r1 = con.getresponse().read()#.decode("utf-8")
162
                    xbmc.log("Simkl: Response: {0}".format(r1))
163
                    r = json.loads(str(r1))
164
                    self.lastwatched = r
165
                    if r == []:
166
                        xbmc.log("Simkl: Couldn't scrobble: Null Response")
167
                        return 0
168
                    media = mediadict[r["type"]]
169
                    toappend = {"ids": r[r["type"]]["ids"], "watched_at":date}
170
171
                tosend = {}
172
                tosend[media] = []
173
                tosend[media].append(toappend)
174
                tosend = json.dumps(tosend)
175
176
                xbmc.log("Simkl: values {0}".format(tosend))
177
                con.request("GET", "/sync/history/", body=tosend, headers=headers)
178
                r = con.getresponse().read().decode("utf-8")
179
                xbmc.log("Simkl: {0}".format(r))
180
181
                success = max(json.loads(r)["added"].values())
182
                if success:
183
                    self.scrobbled_dict
184
                    self.lock(filename, duration)
185
                return success
186
187
            except httplib.BadStatusLine:
188
                xbmc.log("Simkl: {0}".format("ERROR: httplib.BadStatusLine"))
189
            except SSLError: #Fix #8
190
                xbmc.log("Simkl: ERROR: SSLError, retrying?")
191
                if cnt == 0: interface.notify(getstr(32029).format(cnt+1))
192
                if cnt <= 3:
193
                    self.watched(filename, mediatype, duration, date=date, cnt=cnt+1)
194
                else: interface.notify("SSLError")
195
196
        else:
197
            xbmc.log("Simkl: Can't scrobble. User not logged in or file locked")
198
            return 0
199
200
api = API()
201
if __name__ == "__main__":
202
    if sys.argv[1] == "login":
203
        xbmc.log("Logging in", level=xbmc.LOGDEBUG)
204
        api.login()
205