Skip to content

Commit f1ebddd

Browse files
committed
a lot of fixed bugs
1 parent aba1bc7 commit f1ebddd

File tree

1 file changed

+63
-35
lines changed

1 file changed

+63
-35
lines changed

service.py

Lines changed: 63 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
import threading
1515
import time
1616
import hashlib
17+
from itertools import ifilter
1718

1819
import SimpleHTTPServer
1920
import SocketServer
@@ -83,7 +84,7 @@ def onScanStarted(self, library):
8384
def onScanFinished(self, library):
8485
xbmc.Monitor.onScanFinished(self, library)
8586
xbmc.log('%s: Library scan \'%s\' finished' % (ADDONID, library))
86-
self.watched_status.sync_status()
87+
self.watched_status.sync_status() # TODO: do in new thread
8788

8889
def onNotification(self, sender, method, data):
8990
xbmc.Monitor.onNotification(self, sender, method, data)
@@ -92,9 +93,9 @@ def onNotification(self, sender, method, data):
9293
if method == 'VideoLibrary.OnUpdate':
9394
params = json.loads(data)
9495
item_type = params['item']['type']
95-
if item_type == 'episode':
96+
if item_type == 'episode' and 'playcount' in params:
9697
item_id = params['item']['id']
97-
playcount = params.get('playcount', 0)
98+
playcount = params['playcount']
9899
self.watched_status.update_server_status(item_id, playcount > 0)
99100
elif method == 'Player.OnStop':
100101
params = json.loads(data)
@@ -147,9 +148,10 @@ def update_server_status(self, episode_id, watched):
147148
episode_key = season + '/' + episode
148149
if show_watched_status.get(episode_key) != watched:
149150
eid = self.get_soap_episode_id(episode_details)
150-
xbmc.log('%s: Updating remote watched status of show \'%s\' season %s episode %s to %s' % (ADDONID, imdb, season, episode, watched))
151-
self.soap_api.mark_watched(eid, watched)
152-
show_watched_status[episode_key] = watched
151+
if eid is not None:
152+
xbmc.log('%s: Updating remote watched status of show \'%s\' season %s episode %s to %s' % (ADDONID, imdb, season, episode, watched))
153+
self.soap_api.mark_watched(eid, watched)
154+
show_watched_status[episode_key] = watched
153155

154156
def sync_status(self):
155157
for show in KodiApi.get_shows():
@@ -165,16 +167,14 @@ def sync_status(self):
165167
episode_key = season + '/' + episode
166168
watched = show_watched_status.get(episode_key)
167169
if kodi_watched != watched:
168-
xbmc.log('%s: Updating locale watched status of show \'%s\' season %s episode %s to %s' % (ADDONID, imdb, season, episode, watched))
170+
xbmc.log('%s: Updating local watched status of show \'%s\' season %s episode %s to %s' % (ADDONID, imdb, season, episode, watched))
169171
episode_id = e['episodeid']
170172
KodiApi.set_watched(episode_id, watched)
171173

172174
@staticmethod
173175
def get_soap_episode_id(episode_details):
174176
url = episode_details['file']
175-
parsed_params = urlparse.urlparse(url)
176-
query_parsed = urlparse.parse_qs(parsed_params.query)
177-
return query_parsed['id'][0]
177+
return WebHandler.get_episode_id(url)
178178

179179

180180
class SoapCache(object):
@@ -491,7 +491,7 @@ def main(self):
491491

492492
def my_shows(self):
493493
data = self.client.request(self.MY_SHOWS_URL, use_cache=True)
494-
# TODO: tvdb_id is used as IMDB because Kodi uses TVDB internaly for imdbnumber key
494+
# TODO: tvdb_id is used as IMDB because Kodi uses TVDB internally for imdbnumber key
495495
return map(lambda row: {'name': row['title'], 'id': row['sid'], 'IMDB': row['tvdb_id'].replace('tt', '')}, data)
496496

497497
def episodes(self, sid, imdb):
@@ -547,6 +547,7 @@ def get_episode_url(self, sid, eid, ehash):
547547
return result['stream']
548548

549549
def mark_watched(self, eid, watched):
550+
# TODO: clean cache for show
550551
url = self.MARK_WATCHED if watched else self.MARK_UNWATCHED
551552
self.client.request(url.format(eid=eid), {'eid': eid})
552553

@@ -626,41 +627,46 @@ def set_watched(episode_id, watched):
626627
xbmc.executeJSONRPC(postdata)
627628

628629

630+
# NOTE: standard ?param=value&param2=value2... notation is not used for url parameters because of
631+
# issue with endless directory scanning by Kodi
632+
# so for folder is used only show name
633+
# and for file name custom prefix containing all required IDs is used
629634
class WebHandler(SimpleHTTPServer.SimpleHTTPRequestHandler):
630635
match = None
631636

632637
def do_GET(self):
633638
# Parse query data & params to find out what was passed
634639
xbmc.log('%s: Serve \'%s\'' % (ADDONID, self.path))
635640
parsed_params = urlparse.urlparse(self.path)
636-
query_parsed = urlparse.parse_qs(parsed_params.query)
637641
path = urllib.unquote(parsed_params.path)
638642

639643
if path == '/':
640644
xbmc.log('%s: Listing shows' % ADDONID)
641645
shows = self.server.api.my_shows()
642646

643-
self.out_folders(shows,
644-
lambda s: s['name'] + '/',
645-
lambda s: urllib.quote(s['name']) + '/?id=' + s['id'] + '&IMDB=' + s['IMDB'])
647+
self.out_folders(map(lambda s: s['name'], shows))
646648
elif self.matches('^/(.*)/$', path):
647649
show = self.match.group(1)
648-
sid = query_parsed['id'][0]
649-
imdb = query_parsed['IMDB'][0]
650-
651-
xbmc.log('%s: Listing episodes of \'%s\'' % (ADDONID, show))
652-
episodes = self.server.api.episodes(sid, imdb)
653-
654-
self.out_files(episodes,
655-
lambda e: 'S' + e['season'] + 'E' + e['episode'] + '.avi',
656-
lambda e: 'S' + e['season'] + 'E' + e['episode'] + '.avi?sid=' + sid + '&id=' + e['id'] + '&hash=' + e['hash'])
657-
elif self.matches('^/(.*)/S(\d+)E(\d+).avi$', path):
650+
show_details = self.find_show(show)
651+
if show_details is not None:
652+
sid = show_details['id']
653+
imdb = show_details['IMDB']
654+
655+
xbmc.log('%s: Listing episodes of \'%s\'' % (ADDONID, show))
656+
episodes = self.server.api.episodes(sid, imdb)
657+
658+
# format parsable by TVDB scraper
659+
name_lambda = lambda e: sid + '_' + e['id'] + '_' + e['hash'] + '_S' + e['season'] + 'E' + e['episode'] + '.avi'
660+
self.out_files(map(name_lambda, episodes))
661+
else:
662+
xbmc.log('%s: ERROR: Show \'%s\' not found' % (ADDONID, show))
663+
elif self.matches('^/(.*)/(\d+)_(\d+)_([0-9a-f]+)_S(\d+)E(\d+).avi$', path):
658664
show = self.match.group(1)
659-
season = self.match.group(2)
660-
episode = self.match.group(3)
661-
sid = query_parsed['sid'][0]
662-
eid = query_parsed['id'][0]
663-
ehash = query_parsed['hash'][0]
665+
sid = self.match.group(2)
666+
eid = self.match.group(3)
667+
ehash = self.match.group(4)
668+
season = self.match.group(5)
669+
episode = self.match.group(6)
664670

665671
xbmc.log('%s: Requested episode %s from season %s of \'%s\'' % (ADDONID, episode, season, show))
666672
url = self.server.api.get_episode_url(sid, eid, ehash)
@@ -678,11 +684,29 @@ def matches(self, regexp, s):
678684
self.match = re.match(regexp, s, re.M | re.I)
679685
return self.match is not None
680686

681-
def out_folders(self, folders, name_lambda, url_lambda):
682-
self.out_elements(map(lambda f: " <tr><td valign=\"top\"><img src=\"/icons/folder.gif\" alt=\"[DIR]\"></td><td><a href=\"%s\">%s</a></td><td align=\"right\">2016-11-01 23:18</td><td align=\"right\"> - </td><td>&nbsp;</td></tr>\n" % (url_lambda(f), name_lambda(f)), folders))
683-
684-
def out_files(self, files, name_lambda, url_lambda):
685-
self.out_elements(map(lambda f: " <tr><td valign=\"top\"><img src=\"/icons/movie.gif\" alt=\"[VID]\"></td><td><a href=\"%s\">%s</a></td><td align=\"right\">2016-11-01 23:08</td><td align=\"right\"> 0 </td><td>&nbsp;</td></tr>\n" % (url_lambda(f), name_lambda(f)), files))
687+
@staticmethod
688+
def get_episode_id(url):
689+
parsed_params = urlparse.urlparse(url)
690+
file_name = os.path.basename(parsed_params.path)
691+
return file_name.split('_')[1]
692+
693+
def out_folders(self, folders):
694+
self.out_elements(map(lambda f: "<tr>"
695+
" <td valign=\"top\"><img src=\"/icons/folder.gif\" alt=\"[DIR]\"></td>"
696+
" <td><a href=\"%s/\">%s</a></td>"
697+
" <td align=\"right\">2016-11-01 23:18</td>"
698+
" <td align=\"right\"> - </td>"
699+
" <td>&nbsp;</td>"
700+
"</tr>\n" % (urllib.quote(f), f), folders))
701+
702+
def out_files(self, files):
703+
self.out_elements(map(lambda f: "<tr> "
704+
" <td valign=\"top\"><img src=\"/icons/movie.gif\" alt=\"[VID]\"></td>"
705+
" <td><a href=\"%s\">%s</a></td>"
706+
" <td align=\"right\">2016-11-01 23:08</td>"
707+
" <td align=\"right\"> 0 </td>"
708+
" <td>&nbsp;</td>"
709+
"</tr>\n" % (f, f), files))
686710

687711
def out_elements(self, elements):
688712
self.send_response(200)
@@ -706,6 +730,10 @@ def out_elements(self, elements):
706730
self.wfile.write("</body></html>\n")
707731
self.wfile.close()
708732

733+
def find_show(self, show):
734+
shows = self.server.api.my_shows() # should be cached
735+
return next(ifilter(lambda s: show == s['name'], shows), None)
736+
709737

710738
if __name__ == "__main__":
711739
xbmc.log('%s: Version %s started' % (ADDONID, ADDONVERSION))

0 commit comments

Comments
 (0)