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.

Player._detect_item()   F
last analyzed

Complexity

Conditions 16

Size

Total Lines 60

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 1 Features 0
Metric Value
cc 16
c 1
b 1
f 0
dl 0
loc 60
rs 2.4

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 Player._detect_item() 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 os
5
import xbmc
6
import json
7
import threading
8
9
from interface import notify
10
from utils import log
11
from utils import get_setting
12
from utils import get_str
13
14
class Player(xbmc.Player):
15
    def __init__(self, api):
16
        xbmc.Player.__init__(self)
17
        self._api = api
18
        self._tracker = None
19
        self._playback_lock = threading.Event()
20
21
    def onPlayBackStarted(self):
22
        self._stop_tracker()
23
        if self._api.isLoggedIn:
24
            self._detect_item()
25
26
    def onPlayBackStopped(self):
27
        log("Stop clear")
28
        self._stop_tracker()
29
30
    def onPlayBackEnded(self):
31
        log("End clear")
32
        self._stop_tracker()
33
34
    def _detect_item(self):
35
        self._item = {}
36
        _data = json.loads(xbmc.executeJSONRPC(json.dumps({
37
            "jsonrpc": "2.0", "method": "Player.GetItem",
38
            "params": {
39
                "properties": ["showtitle", "title", "season", "episode", "file", "tvshowid", "imdbnumber","genre" ,"year"],
40
                "playerid": 1},
41
            "id": "VideoGetItem"})))["result"]["item"]
42
        is_tv = _data["tvshowid"] != -1 and _data["season"] > 0 and _data["episode"] > 0
43
        if is_tv:
44
            _data["imdbnumber"] = json.loads(xbmc.executeJSONRPC(json.dumps({
45
                "jsonrpc": "2.0", "method": "VideoLibrary.GetTVShowDetails",
46
                "params": {"tvshowid": _data["tvshowid"], "properties": ["imdbnumber"]},
47
                "id": 1
48
            })))["result"]["tvshowdetails"]["imdbnumber"]
49
50
        log("Full: {0}".format(_data))
51
        if ("imdbnumber" not in _data or _data["imdbnumber"] == '') and _data['file']:
52
            _r = self._api.detect_by_file(filename=_data['file'])
53
            if isinstance(_r, dict) and "type" in _r:
54
                if _r["type"] == "episode":
55
                    # TESTED
56
                    if "episode" in _r:
57
                        self._item = {
58
                            "type": "episodes",
59
                            "title": _r["show"]["title"],
60
                            "simkl": _r["episode"]["ids"]["simkl"],
61
                            "season": _r["episode"]["season"],
62
                            "episode": _r["episode"]["episode"]
63
                        }
64
                elif _r["type"] == "movie" and "movie" in _r:
65
                    # TESTED
66
                    self._item = {
67
                        "type": "movies",
68
                        "title": _r["movie"]["title"],
69
                        "year": _r["movie"]["year"],
70
                        "simkl": _r["movie"]["ids"]["simkl"]
71
                    }
72
73
        if not self._item and (_data["title"] or _data["showtitle"]):
74
            if is_tv:
75
                # TESTED
76
                self._item = {
77
                    "type": "shows",
78
                    "title": _data["showtitle"],
79
                    "tvdb": _data["imdbnumber"],
80
                    "season": _data["season"],
81
                    "episode": _data["episode"]
82
                }
83
            else:
84
                # TESTED
85
                self._item = {
86
                    "type": "movies",
87
                    "title": _data["title"],
88
                    "year": _data["year"],
89
                    "imdb": _data["imdbnumber"],
90
                }
91
92
        if self._item:
93
            self._run_tracker()
94
95
    def _run_tracker(self):
96
        self._playback_lock.set()
97
        self._tracker = threading.Thread(target=self._thread_tracker)
98
        self._tracker.start()
99
100
    def _stop_tracker(self):
101
        if hasattr(self, '_playback_lock'): self._playback_lock.clear()
102
        if not hasattr(self, '_tracker'): return
103
        if self._tracker is None: return
104
        if self._tracker.isAlive(): self._tracker.join()
105
        self._tracker = None
106
107
    def _thread_tracker(self):
108
        log("in tracker thread")
109
        total_time = self.getTotalTime()
110
        total_time_min = int(get_setting("min-length"))
111
        perc_mark = int(get_setting("scr-pct"))
112
        self._is_detected = True
113
        timeout = 1000
114
        # if total_time set and is lower than total_time_min then we do not start the loop at all and stop the thread,
115
        if total_time <= 0 or total_time > total_time_min:
116
            while self._playback_lock.isSet() and not xbmc.abortRequested:
117
                try:
118
                    # The max() assures that the total time is over two minutes
119
                    # preventing it from scrobbling while buffering and solving #31
120
                    if min(99, 100 * self.getTime() / max(120, total_time)) >= perc_mark:
121
                        success = self._api.mark_as_watched(self._item)
122
                        if not success:
123
                            if timeout == 1000:
124
                                log("Failed to scrobble")
125
                                notify(get_str(32080))
126
                                timeout = 30000
127
                            elif (self.getTime() / total_time) > 0.95:
128
                                log("Stopped scrobbling")
129
                                notify(get_str(32081))
130
                                break
131
                            else:
132
                                log("Retrying")
133
134
                        elif success and bool(get_setting("bubble")):
135
                            self._show_bubble(self._item)
136
                            break
137
                except:
138
                    pass
139
                xbmc.sleep(timeout)
140
        log('track stop')
141
142
    def _show_bubble(self, item):
143
        log("in bubble")
144
        if "title" in item:
145
            txt = ''
146
            title = item["title"]
147
            if "episode" in item:
148
                txt = "- S{:02}E{:02}".format(item["season"], item["episode"])
149
            elif "year" in item:
150
                title = "".join([title, " (", str(item["year"]), ")"])
151
152
            log("Show Bubble")
153
            notify(get_str(32028).format(txt), title=title)
154
155
    @staticmethod
156
    def getMediaType():
157
        if xbmc.getCondVisibility('Container.Content(tvshows)'):
158
            return "show"
159
        elif xbmc.getCondVisibility('Container.Content(seasons)'):
160
            return "season"
161
        elif xbmc.getCondVisibility('Container.Content(episodes)'):
162
            return "episode"
163
        elif xbmc.getCondVisibility('Container.Content(movies)'):
164
            return "movie"
165
        else:
166
            return None