|
1
|
|
|
#!/usr/bin/python |
|
2
|
|
|
# -*- coding: UTF-8 -*- |
|
3
|
|
|
|
|
4
|
|
|
import xbmc |
|
5
|
|
|
import interface |
|
6
|
|
|
import json |
|
7
|
|
|
__addon__ = interface.__addon__ |
|
8
|
|
|
def getstr(strid): return interface.getstr(strid) |
|
9
|
|
|
|
|
10
|
|
|
class Engine: |
|
11
|
|
|
def __init__(self, api, player): |
|
12
|
|
|
self.api = api |
|
13
|
|
|
self.player = player |
|
14
|
|
|
player.engine = self |
|
15
|
|
|
player.api = api |
|
16
|
|
|
|
|
17
|
|
|
def synclibrary(self, mode="quick"): |
|
18
|
|
|
""" |
|
19
|
|
|
Fetches the library from Simkl to Kodi |
|
20
|
|
|
Mode can be "quick" or "full" |
|
21
|
|
|
""" |
|
22
|
|
|
xbmc.log("Simkl: Syncing library (Simkl to Kodi)") |
|
23
|
|
|
|
|
24
|
|
|
mode = "full" |
|
25
|
|
|
|
|
26
|
|
|
if mode == "full": |
|
27
|
|
|
todump = { |
|
28
|
|
|
"jsonrpc": "2.0", |
|
29
|
|
|
"method": "VideoLibrary.GetMovies", |
|
30
|
|
|
"params": { |
|
31
|
|
|
"limits": { |
|
32
|
|
|
"start": 0, |
|
33
|
|
|
"end": 1000 |
|
34
|
|
|
}, |
|
35
|
|
|
"properties": [ |
|
36
|
|
|
"playcount", |
|
37
|
|
|
"imdbnumber", |
|
38
|
|
|
"file", |
|
39
|
|
|
"lastplayed", |
|
40
|
|
|
"year" |
|
41
|
|
|
], |
|
42
|
|
|
"sort": { |
|
43
|
|
|
"order": "ascending", |
|
44
|
|
|
"method": "playcount", |
|
45
|
|
|
#"ignorearticle": True |
|
46
|
|
|
} |
|
47
|
|
|
}, |
|
48
|
|
|
"id": "libMovies" |
|
49
|
|
|
} |
|
50
|
|
|
kodilibrary = json.loads(xbmc.executeJSONRPC(json.dumps(todump))) |
|
51
|
|
|
if kodilibrary["result"]["limits"]["total"] > 0: |
|
52
|
|
|
xbmc.log(str(kodilibrary)) |
|
53
|
|
|
progress = interface.SyncProgress("movies", "full") |
|
54
|
|
|
each = float(100) / kodilibrary["result"]["limits"]["total"] |
|
55
|
|
|
for movie in kodilibrary["result"]["movies"]: |
|
56
|
|
|
progress.push(each, "{0} ({1})".format(movie["label"], movie["year"])) |
|
57
|
|
|
if movie["playcount"] == 0: |
|
58
|
|
|
### DOWNLOAD FROM KODI |
|
59
|
|
|
#Separate big list in chunks |
|
60
|
|
|
movie["media"] = "movie" |
|
61
|
|
|
if self.api.check_if_watched(movie): |
|
62
|
|
|
xbmc.log("Simkl: {0}".format(movie)) |
|
63
|
|
|
ret = xbmc.executeJSONRPC(json.dumps({ |
|
64
|
|
|
"jsonrpc": "2.0", |
|
65
|
|
|
"method": "VideoLibrary.SetMovieDetails", |
|
66
|
|
|
"params": { |
|
67
|
|
|
"playcount": 1, |
|
68
|
|
|
#"lastplayed":"", |
|
69
|
|
|
"movieid":movie["movieid"] |
|
70
|
|
|
} |
|
71
|
|
|
})) |
|
72
|
|
|
#xbmc.log(ret) |
|
73
|
|
|
del progress |
|
74
|
|
|
|
|
75
|
|
|
todump["method"] = "VideoLibrary.GetTVShows" |
|
76
|
|
|
todump["params"]["properties"] = ["imdbnumber", "title", "watchedepisodes"] |
|
77
|
|
|
#If watchedepisodes > 0 |
|
78
|
|
|
kodilibrary = xbmc.executeJSONRPC(json.dumps(todump)) |
|
79
|
|
|
kodilibrary = json.loads(kodilibrary) |
|
80
|
|
|
|
|
81
|
|
|
if kodilibrary["result"]["limits"]["total"] > 0: |
|
82
|
|
|
progress = interface.SyncProgress("TV Shows", "full") |
|
83
|
|
|
each = float(100) / kodilibrary["result"]["limits"]["total"] |
|
84
|
|
|
debug_cnt = 0 |
|
85
|
|
|
for tvshow in kodilibrary["result"]["tvshows"]: |
|
86
|
|
|
#if debug_cnt >= 10: break #I have a lot of TV Shows, only for testing |
|
87
|
|
|
progress.push(each, tvshow["label"]) |
|
88
|
|
|
debug_cnt += 1 |
|
89
|
|
|
|
|
90
|
|
|
|
|
91
|
|
|
todump["method"] = "VideoLibrary.GetSeasons" |
|
92
|
|
|
#todump["params"]["Library.Id"] = tvshow["tvshowid"] |
|
93
|
|
|
todump["id"] = tvshow["tvshowid"] |
|
94
|
|
|
todump["params"]["properties"] = ["season", "episode", "watchedepisodes", "showtitle"] |
|
95
|
|
|
seasons = xbmc.executeJSONRPC(json.dumps(todump)) |
|
96
|
|
|
xbmc.log(json.dumps(tvshow)) |
|
97
|
|
|
xbmc.log(seasons) |
|
98
|
|
|
seasons = json.loads(seasons) |
|
99
|
|
|
|
|
100
|
|
|
|
|
101
|
|
|
for season in seasons["result"]["seasons"]: |
|
102
|
|
|
values = [] |
|
103
|
|
|
|
|
104
|
|
|
todump["method"] = "VideoLibrary.GetEpisodes" |
|
105
|
|
|
todump["params"]["tvshowid"] = tvshow["tvshowid"] |
|
106
|
|
|
todump["params"]["season"] = season["season"] |
|
107
|
|
|
todump["params"]["properties"] = ["title", "rating", "playcount", |
|
108
|
|
|
"season", "episode", "showtitle", "lastplayed", "tvshowid"] |
|
109
|
|
|
|
|
110
|
|
|
episodes = xbmc.executeJSONRPC(json.dumps(todump)) |
|
111
|
|
|
xbmc.log(episodes) |
|
112
|
|
|
episodes = json.loads(episodes) |
|
113
|
|
|
|
|
114
|
|
|
if episodes["result"]["limits"]["total"] > 0: |
|
115
|
|
|
for episode in episodes["result"]["episodes"]: |
|
116
|
|
|
values.append({ |
|
117
|
|
|
"type": "tv", |
|
118
|
|
|
"season": episode["season"], |
|
119
|
|
|
"episode": episode["episode"], |
|
120
|
|
|
"title": episode["showtitle"], |
|
121
|
|
|
"tvdb": tvshow["imdbnumber"] |
|
122
|
|
|
}) |
|
123
|
|
|
|
|
124
|
|
|
watched = self.api.check_if_watched(values, False) |
|
125
|
|
|
xbmc.log(json.dumps(watched)) |
|
126
|
|
|
|
|
127
|
|
|
for i, episode in enumerate(episodes["result"]["episodes"]): |
|
128
|
|
|
toupdate = { |
|
129
|
|
|
"jsonrpc": "2.0", |
|
130
|
|
|
"method": "VideoLibrary.SetEpisodeDetails", |
|
131
|
|
|
"params": { |
|
132
|
|
|
"episodeid":episode["episodeid"], |
|
133
|
|
|
"playcount": int(watched[i]["result"]), |
|
134
|
|
|
}, |
|
135
|
|
|
"id": "libMovies" |
|
136
|
|
|
} |
|
137
|
|
|
try: |
|
138
|
|
|
toupdate["params"]["lastplayed"] = watched[i]["last_watched"] |
|
139
|
|
|
except KeyError: |
|
140
|
|
|
toupdate["params"]["lastplayed"] = "" |
|
141
|
|
|
|
|
142
|
|
|
info = xbmc.executeJSONRPC(json.dumps(toupdate)) |
|
143
|
|
|
xbmc.log("Simkl: Info: {0}".format(info)) |
|
144
|
|
|
|
|
145
|
|
|
del todump["params"]["tvshowid"] |
|
146
|
|
|
del todump["params"]["season"] |
|
147
|
|
|
del progress |
|
148
|
|
|
|
|
149
|
|
|
xbmc.log("Simkl: Finished syncing library") |
|
150
|
|
|
interface.notify("Finished syncing library") |
|
151
|
|
|
|
|
152
|
|
|
|
|
153
|
|
|
class Player(xbmc.Player): |
|
154
|
|
|
""" Replaces the Kodi player class """ |
|
155
|
|
|
def __init__(self): |
|
156
|
|
|
xbmc.Player.__init__(self) |
|
157
|
|
|
|
|
158
|
|
|
@staticmethod |
|
159
|
|
|
def getMediaType(): |
|
160
|
|
|
""" Returns the MediaType of the file currently playing """ |
|
161
|
|
|
if xbmc.getCondVisibility('Container.Content(tvshows)'): |
|
162
|
|
|
return "show" |
|
163
|
|
|
elif xbmc.getCondVisibility('Container.Content(seasons)'): |
|
164
|
|
|
return "season" |
|
165
|
|
|
elif xbmc.getCondVisibility('Container.Content(episodes)'): |
|
166
|
|
|
return "episode" |
|
167
|
|
|
elif xbmc.getCondVisibility('Container.Content(movies)'): |
|
168
|
|
|
return "movie" |
|
169
|
|
|
else: |
|
170
|
|
|
return None |
|
171
|
|
|
|
|
172
|
|
|
def onPlayBackStarted(self): |
|
173
|
|
|
""" Activated at start """ |
|
174
|
|
|
#self.onPlayBackStopped() |
|
175
|
|
|
pass |
|
176
|
|
|
def onPlayBackSeek(self, *args): |
|
177
|
|
|
""" Activated on seek """ |
|
178
|
|
|
self.onPlayBackStopped() |
|
179
|
|
|
def onPlayBackResumed(self): |
|
180
|
|
|
""" Activated on resume """ |
|
181
|
|
|
self.onPlayBackStopped() |
|
182
|
|
|
def onPlayBackEnded(self): |
|
183
|
|
|
""" Activated at end """ |
|
184
|
|
|
xbmc.log("Simkl: ONPLAYBACKENDED") |
|
185
|
|
|
self.onPlayBackStopped() |
|
186
|
|
|
|
|
187
|
|
|
def onPlayBackStopped(self): |
|
188
|
|
|
""" Gets the info needed to pass to the api """ |
|
189
|
|
|
try: |
|
190
|
|
|
movie = self.getVideoInfoTag() |
|
191
|
|
|
thing = xbmc.executeJSONRPC(json.dumps({ |
|
192
|
|
|
"jsonrpc": "2.0", |
|
193
|
|
|
"method": "Player.GetItem", |
|
194
|
|
|
"params": { |
|
195
|
|
|
"properties": [ "showtitle", "title", "season", "episode", "file", "imdbnumber", "genre" ], |
|
196
|
|
|
"playerid": 1 }, |
|
197
|
|
|
"id": "VideoGetItem" |
|
198
|
|
|
})) |
|
199
|
|
|
xbmc.log("Simkl: Full: {0}".format(thing)) |
|
200
|
|
|
item = json.loads(thing)["result"]["item"] |
|
201
|
|
|
#imdb = movie.getIMDBNumber().strip(" ") |
|
202
|
|
|
#fname = self.getPlayingFile() |
|
203
|
|
|
imdb = item["imdbnumber"] |
|
204
|
|
|
fname = item["file"] |
|
205
|
|
|
media = item["type"] |
|
206
|
|
|
xbmc.log("Simkl: IMDb: {0}".format(imdb)) |
|
207
|
|
|
xbmc.log("Simkl: Genre: {0}".format(item["genre"])) |
|
208
|
|
|
xbmc.log("Simkl: MediaType: " + str(media)) |
|
209
|
|
|
|
|
210
|
|
|
percentage = 100 * self.getTime() / self.getTotalTime() |
|
211
|
|
|
pctconfig = int(self.addon.getSetting("scr-pct")) |
|
212
|
|
|
|
|
213
|
|
|
if 99 > percentage > pctconfig: |
|
214
|
|
|
bubble = __addon__.getSetting("bubble") |
|
215
|
|
|
xbmc.log("Simkl: Bubble == {0}".format(bubble)) |
|
216
|
|
|
xbmc.log("Percentage: {0}, pctconfig {1}".format(percentage, pctconfig)) |
|
217
|
|
|
|
|
218
|
|
|
xbmc.log("Simkl: Ready to scrobble {0}".format(movie.getTitle())) |
|
219
|
|
|
if imdb == "": |
|
220
|
|
|
#if True: |
|
221
|
|
|
xbmc.log("Simkl: No imdb - Fname: {0}".format(fname)) |
|
222
|
|
|
r = self.api.watched(fname, media, self.getTotalTime()) |
|
223
|
|
|
else: |
|
224
|
|
|
xbmc.log("Simkl: IMDB: " + str(imdb)) |
|
225
|
|
|
r = self.api.watched(imdb, media, self.getTotalTime()) |
|
226
|
|
|
|
|
227
|
|
|
if bubble=="true" and r: |
|
228
|
|
|
if item["label"] in item["file"]: |
|
229
|
|
|
#if True: #For testing purposes |
|
230
|
|
|
xbmc.log("Simkl: Label and file are the same") |
|
231
|
|
|
lstw = self.api.lastwatched |
|
232
|
|
|
if lstw["type"] == "episode": |
|
233
|
|
|
item["showtitle"] = lstw["show"]["title"] |
|
234
|
|
|
item["season"] = lstw["episode"]["season"] |
|
235
|
|
|
item["episode"] = lstw["episode"]["episode"] |
|
236
|
|
|
elif lstw["type"] == "movie": |
|
237
|
|
|
item["title"] = "".join([lstw["movie"]["title"], " (", str(lstw["movie"]["year"]), ")"]) |
|
238
|
|
|
media = lstw["type"] |
|
239
|
|
|
|
|
240
|
|
|
txt = item["label"] |
|
241
|
|
|
title = "" |
|
242
|
|
|
if media == "movie": |
|
243
|
|
|
txt = item["title"] |
|
244
|
|
|
elif media == "episode": |
|
245
|
|
|
txt = item["showtitle"] |
|
246
|
|
|
title = "- S{:02}E{:02}".format(item["season"], item["episode"]) |
|
247
|
|
|
xbmc.log("Simkl: " + "; ".join([media, txt, title])) |
|
248
|
|
|
interface.notify(getstr(32028).format(title), title=txt) |
|
249
|
|
|
r = 0 |
|
250
|
|
|
|
|
251
|
|
|
except RuntimeError: |
|
252
|
|
|
pass |
|
253
|
|
|
except ZeroDivisionError: |
|
254
|
|
|
self.onPlayBackStopped() |
|
255
|
|
|
|