The branch, eden has been updated
via c6547f54a486386b7752233b5950d71e250db4a6 (commit)
from 9d918ed08573e2b57c55ccb5909a497b9f217ccb (commit)
- Log -----------------------------------------------------------------
http://xbmc.git.sourceforge.net/git/gitweb.cgi?p=xbmc/scripts;a=commit;h=c6547f54a486386b7752233b5950d71e250db4a6
commit c6547f54a486386b7752233b5950d71e250db4a6
Author: amet <[email protected]>
Date: Fri Aug 31 08:21:36 2012 +0400
[script.trakt] -v 1.0.1
- code optimization (thanks seadog!)
- use tvdb_id for much improved matching and international support
- hide error notifications during playback
diff --git a/script.trakt/README.md b/script.trakt/README.md
index 11b8504..831ccb3 100644
--- a/script.trakt/README.md
+++ b/script.trakt/README.md
@@ -4,17 +4,18 @@ trakt.tv TV and movie scrobbler for XBMC Eden
Automatically scrobble all TV episodes and movies you are watching to
trakt.tv! Keep a comprehensive history of everything you've watched and be part
of a global community of TV and movie enthusiasts. Sign up for a free account
at http://trakt.tv and get a ton of features including:
* automatically scrobble what you're watching
-* mobile apps for iPhone, iPad, Android, Windows Phone, Blackberry, and Symbian
+* [mobile apps](http://trakt.tv/downloads) for iPhone, iPad, Android, Windows
Phone, Blackberry, and Symbian
* share what you're watching (in real time) and rating to facebook, twitter,
and tumblr
* use watchlists so you don't forget to what to watch
* track your media collections and impress your friends
-* create custom lists around any topics you choose
+* create custom [lists](http://trakt.tv/lists) around any topics you choose
* easily track your TV show progress across all seasons and episodes
+* track your progress against industry lists such as the [IMDb Top
250](http://trakt.tv/lists/imdb/top-250)
* discover new shows and movies based on your viewing habits
###What can be scrobbled?
-This plugin will scrobble local media and most remote streaming content. Local
content should be played in XBMC library mode and you should use TVDb (for tv
shows) and TMDb (for movies) as your scrapers. TV shows are identified using
their TVDb ID. Movies are identified using the IMDB ID. This helps trakt match
up the correct show or movie regardless of the title and improves accuracy a
lot.
+This plugin will scrobble local media and most remote streaming content. Local
content should be played in XBMC library mode and you should use
[TVDb](http://thetvdb.com/) (for tv shows) and [TMDb](http://themoviedb.org)
(for movies) as your scrapers. TV shows are identified using their TVDb ID.
Movies are identified using the IMDb ID. This helps trakt match up the correct
show or movie regardless of the title and improves accuracy a lot.
Remote streaming content will scrobble assuming the metadata is correctly set
in XBMC. The various streaming plugins need to correctly identify TV episodes
and movies with as much metadata as they can for trakt to know what you're
watching.
@@ -24,6 +25,7 @@ Remote streaming content will scrobble assuming the metadata
is correctly set in
* PleXBMC
* Amazon (bluecop repo)
* CBS (bluecop repo)
+* South Park
###Installation
@@ -37,4 +39,4 @@ Remote streaming content will scrobble assuming the metadata
is correctly set in
###Thanks
-Special thanks to the trakt utilities team! This plugin is essentially their
code with a few additions.
\ No newline at end of file
+Special thanks to the [trakt
utilities](https://github.com/Manromen/script.traktutilities) team! This plugin
is essentially their code with some additions.
\ No newline at end of file
diff --git a/script.trakt/addon.xml b/script.trakt/addon.xml
index 62ae937..675d798 100644
--- a/script.trakt/addon.xml
+++ b/script.trakt/addon.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
-<addon id="script.trakt" name="trakt" version="1.0.0" provider-name="trakt.tv">
+<addon id="script.trakt" name="trakt" version="1.0.1" provider-name="trakt.tv">
<requires>
<import addon="xbmc.python" version="2.0"/>
<import addon="script.module.simplejson" version="2.0.10"/>
@@ -19,6 +19,7 @@
- track your media collections and impress your friends
- create custom lists around any topics you choose
- easily track your TV show progress across all seasons and episodes
+- track your progress against industry lists such as the IMDb Top 250
- discover new shows and movies based on your viewing habits
Special thanks to the trakt utilities team! This plugin is essentially their
code with a few additions.</description>
diff --git a/script.trakt/changelog.txt b/script.trakt/changelog.txt
index 83cb21e..e4eb23a 100644
--- a/script.trakt/changelog.txt
+++ b/script.trakt/changelog.txt
@@ -1,3 +1,8 @@
+version 1.0.1
+ - code optimization (thanks seadog!)
+ - use tvdb_id for much improved matching and international support
+ - hide error notifications during playback
+
version 1.0.0
- initial release
- tv episode and movie scrobbling
diff --git a/script.trakt/notification_service.py
b/script.trakt/notification_service.py
index 8e86942..b95e118 100644
--- a/script.trakt/notification_service.py
+++ b/script.trakt/notification_service.py
@@ -1,85 +1,81 @@
# -*- coding: utf-8 -*-
-#
+""" Handles notifications from XBMC via its own thread and forwards them on to
the scrobbler """
-import xbmc, xbmcaddon, xbmcgui
-import telnetlib, time
+import xbmc
+import telnetlib
+import socket
-try: import simplejson as json
-except ImportError: import json
+import simplejson as json
import threading
-from utilities import *
+from utilities import Debug
from scrobbler import Scrobbler
-__settings__ = xbmcaddon.Addon("script.trakt")
-__language__ = __settings__.getLocalizedString
-
-# Receives XBMC notifications and passes them off as needed
class NotificationService(threading.Thread):
- abortRequested = False
- def run(self):
+ """ Receives XBMC notifications and passes them off as needed """
+
+ TELNET_ADDRESS = 'localhost'
+ TELNET_PORT = 9090
+
+ _abortRequested = False
+ _scrobbler = None
+ _notificationBuffer = ""
+
+
+ def _forward(self, notification):
+ """ Fowards the notification recieved to a function on the
scrobbler """
+ if not ('method' in notification and 'params' in notification
and 'sender' in notification['params'] and notification['params']['sender'] ==
'xbmc'):
+ return
+
+ if notification['method'] == 'Player.OnStop':
+ self._scrobbler.playbackEnded()
+ elif notification['method'] == 'Player.OnPlay':
+ if 'data' in notification['params'] and 'item' in
notification['params']['data'] and 'type' in
notification['params']['data']['item']:
+
self._scrobbler.playbackStarted(notification['params']['data'])
+ elif notification['method'] == 'Player.OnPause':
+ self._scrobbler.playbackPaused()
+ elif notification['method'] == 'System.OnQuit':
+ self._abortRequested = True
+
+
+ def _readNotification(self, telnet):
+ """ Read a notification from the telnet connection, blocks
until the data is available, or else raises an EOFError if the connection is
lost """
+ while True:
+ try:
+ addbuffer = telnet.read_some()
+ except socket.timeout:
+ continue
+
+ if addbuffer == "":
+ raise EOFError
+
+ self._notificationBuffer += addbuffer
+ try:
+ data, offset =
json.JSONDecoder().raw_decode(self._notificationBuffer)
+ self._notificationBuffer =
self._notificationBuffer[offset:]
+ except ValueError:
+ continue
+
+ return data
+
+
+ def run(self):
#while xbmc is running
- scrobbler = Scrobbler()
- scrobbler.start()
-
- while (not (self.abortRequested or xbmc.abortRequested)):
- time.sleep(1)
+ self._scrobbler = Scrobbler()
+ self._scrobbler.start()
+ telnet = telnetlib.Telnet(self.TELNET_ADDRESS, self.TELNET_PORT)
+
+ while not (self._abortRequested or xbmc.abortRequested):
try:
- tn = telnetlib.Telnet('localhost', 9090, 10)
- except IOError as (errno, strerror):
- #connection failed, try again soon
- Debug("[Notification Service] Telnet too soon?
("+str(errno)+") "+strerror)
- time.sleep(1)
+ data = self._readNotification(telnet)
+ except EOFError:
+ telnet = telnetlib.Telnet(self.TELNET_ADDRESS,
self.TELNET_PORT)
+ self._notificationBuffer = ""
continue
-
- Debug("[Notification Service] Waiting~");
- bCount = 0
-
- while (not (self.abortRequested or
xbmc.abortRequested)):
- try:
- if bCount == 0:
- notification = ""
- inString = False
- [index, match, raw] =
tn.expect(["(\\\\)|(\\\")|[{\"}]"], 0.2) #note, pre-compiled regex might be
faster here
- notification += raw
- if index == -1: # Timeout
- continue
- if index == 0: # Found escaped quote
- match = match.group(0)
- if match == "\"":
- inString = not inString
- continue
- if match == "{":
- bCount += 1
- if match == "}":
- bCount -= 1
- if bCount > 0:
- continue
- if bCount < 0:
- bCount = 0
- except EOFError:
- break #go out to the other loop to
restart the connection
-
- Debug("[Notification Service] message: " +
str(notification))
-
- # Parse recieved notification
- data = json.loads(notification)
-
- # Forward notification to functions
- if 'method' in data and 'params' in data and
'sender' in data['params'] and data['params']['sender'] == 'xbmc':
- if data['method'] == 'Player.OnStop':
- scrobbler.playbackEnded()
- elif data['method'] == 'Player.OnPlay':
- if 'data' in data['params'] and
'item' in data['params']['data'] and 'type' in data['params']['data']['item']:
-
scrobbler.playbackStarted(data['params']['data'])
- elif data['method'] == 'Player.OnPause':
- scrobbler.playbackPaused()
- elif data['method'] == 'System.OnQuit':
- self.abortRequested = True
- try:
- tn.close()
- except:
- Debug("[NotificationService] Error attempting to close
the telnet connection")
- raise
- scrobbler.abortRequested = True
- Debug("Notification service stopping")
\ No newline at end of file
+
+ Debug("[Notification Service] message: " + str(data))
+ self._forward(data)
+
+ telnet.close()
+ self._scrobbler.abortRequested = True
+ Debug("Notification service stopping")
diff --git a/script.trakt/resources/language/Portuguese (Brazil)/strings.xml
b/script.trakt/resources/language/Portuguese (Brazil)/strings.xml
index abafee0..506a2a3 100644
--- a/script.trakt/resources/language/Portuguese (Brazil)/strings.xml
+++ b/script.trakt/resources/language/Portuguese (Brazil)/strings.xml
@@ -6,7 +6,7 @@
<string id="1012">Chave API (encontre em trakt --> Settings -->
API)</string>
<string id="1013">Usuário</string>
<string id="1014">Senha</string>
- <string id="1016">Use secure connection (HTTPS)</string>
+ <string id="1016">Usar conexão segura (HTTPS)</string>
<string id="1020">Auto Sincronia</string>
<string id="1021">Auto atualizar Coleção de Filmes ao iniciar</string>
diff --git a/script.trakt/scrobbler.py b/script.trakt/scrobbler.py
index 869fcaa..66d59f9 100644
--- a/script.trakt/scrobbler.py
+++ b/script.trakt/scrobbler.py
@@ -1,12 +1,14 @@
# -*- coding: utf-8 -*-
-#
+#
-import os
-import xbmc, xbmcaddon, xbmcgui
+import xbmc
+import xbmcaddon
+import sys
import threading
import time
-from utilities import *
+import utilities
+from utilities import Debug
# read settings
__settings__ = xbmcaddon.Addon("script.trakt")
@@ -17,10 +19,11 @@ class Scrobbler(threading.Thread):
watchedTime = 0
startTime = 0
curVideo = None
+ curVideoData = None
pinging = False
playlistLength = 1
abortRequested = False
-
+
def run(self):
# When requested ping trakt to say that the user is still
watching the item
count = 0
@@ -29,18 +32,18 @@ class Scrobbler(threading.Thread):
if self.pinging:
count += 1
self.watchedTime = xbmc.Player().getTime()
- if count>=100:
+ if count >= 100:
self.startedWatching()
count = 0
else:
count = 0
-
+
Debug("Scrobbler stopping")
-
+
def playbackStarted(self, data):
self.curVideo = data['item']
self.curVideoData = data
- if self.curVideo <> None:
+ if self.curVideo != None:
#
{"jsonrpc":"2.0","method":"Player.OnPlay","params":{"data":{"item":{"type":"movie"},"player":{"playerid":1,"speed":1},"title":"Shooter","year":2007},"sender":"xbmc"}}
#
{"jsonrpc":"2.0","method":"Player.OnPlay","params":{"data":{"episode":3,"item":{"type":"episode"},"player":{"playerid":1,"speed":1},"season":4,"showtitle":"24","title":"9:00
A.M. - 10:00 A.M."},"sender":"xbmc"}}
if 'type' in self.curVideo: #and 'id' in self.curVideo:
@@ -59,7 +62,7 @@ class Scrobbler(threading.Thread):
self.totalTime = 30
else:
self.totalTime = 1
- self.playlistLength =
getPlaylistLengthFromXBMCPlayer(data['player']['playerid'])
+ self.playlistLength =
utilities.getPlaylistLengthFromXBMCPlayer(data['player']['playerid'])
if (self.playlistLength == 0):
Debug("[Scrobbler] Warning:
Cant find playlist length?!, assuming that this item is by itself")
self.playlistLength = 1
@@ -76,32 +79,32 @@ class Scrobbler(threading.Thread):
self.startTime = 0
def playbackPaused(self):
- if self.startTime <> 0:
+ if self.startTime != 0:
self.watchedTime += time.time() - self.startTime
Debug("[Scrobbler] Paused after:
"+str(self.watchedTime))
self.startTime = 0
def playbackEnded(self):
- if self.startTime <> 0:
+ if self.startTime != 0:
if self.curVideo == None:
Debug("[Scrobbler] Warning: Playback ended but
video forgotten")
return
self.watchedTime += time.time() - self.startTime
self.pinging = False
- if self.watchedTime <> 0:
+ if self.watchedTime != 0:
if 'type' in self.curVideo: #and 'id' in
self.curVideo:
self.check()
self.watchedTime = 0
self.startTime = 0
-
+
def startedWatching(self):
scrobbleMovieOption = __settings__.getSetting("scrobble_movie")
scrobbleEpisodeOption =
__settings__.getSetting("scrobble_episode")
-
+
if self.curVideo['type'] == 'movie' and scrobbleMovieOption ==
'true':
match = None
if 'id' in self.curVideo:
- match =
getMovieDetailsFromXbmc(self.curVideo['id'], ['imdbnumber','title','year'])
+ match =
utilities.getMovieDetailsFromXbmc(self.curVideo['id'], ['imdbnumber', 'title',
'year'])
elif 'title' in self.curVideoData and 'year' in
self.curVideoData:
match = {}
match['imdbnumber'] = ''
@@ -109,45 +112,47 @@ class Scrobbler(threading.Thread):
match['year'] = self.curVideoData['year']
if match == None:
return
- response = watchingMovieOnTrakt(match['imdbnumber'],
match['title'], match['year'], self.totalTime/60,
int(100*self.watchedTime/self.totalTime))
+ response =
utilities.watchingMovieOnTrakt(match['imdbnumber'], match['title'],
match['year'], self.totalTime/60, int(100*self.watchedTime/self.totalTime))
if response != None:
- Debug("[Scrobbler] Watch response:
"+str(response));
+ Debug("[Scrobbler] Watch response:
"+str(response))
elif self.curVideo['type'] == 'episode' and
scrobbleEpisodeOption == 'true':
match = None
if 'id' in self.curVideo:
- match =
getEpisodeDetailsFromXbmc(self.curVideo['id'], ['showtitle', 'season',
'episode'])
+ match =
utilities.getEpisodeDetailsFromXbmc(self.curVideo['id'], ['showtitle',
'season', 'episode', 'tvshowid'])
elif 'showtitle' in self.curVideoData and 'season' in
self.curVideoData and 'episode' in self.curVideoData:
match = {}
+ match['tvdb_id'] = None
+ match['year'] = None
match['showtitle'] =
self.curVideoData['showtitle']
match['season'] = self.curVideoData['season']
match['episode'] = self.curVideoData['episode']
if match == None:
return
- response = watchingEpisodeOnTrakt(None,
match['showtitle'], None, match['season'], match['episode'], self.totalTime/60,
int(100*self.watchedTime/self.totalTime))
+ response =
utilities.watchingEpisodeOnTrakt(match['tvdb_id'], match['showtitle'],
match['year'], match['season'], match['episode'], self.totalTime/60,
int(100*self.watchedTime/self.totalTime))
if response != None:
- Debug("[Scrobbler] Watch response:
"+str(response));
-
+ Debug("[Scrobbler] Watch response:
"+str(response))
+
def stoppedWatching(self):
scrobbleMovieOption = __settings__.getSetting("scrobble_movie")
scrobbleEpisodeOption =
__settings__.getSetting("scrobble_episode")
-
+
if self.curVideo['type'] == 'movie' and scrobbleMovieOption ==
'true':
- response = cancelWatchingMovieOnTrakt()
+ response = utilities.cancelWatchingMovieOnTrakt()
if response != None:
- Debug("[Scrobbler] Cancel watch response:
"+str(response));
+ Debug("[Scrobbler] Cancel watch response:
"+str(response))
elif self.curVideo['type'] == 'episode' and
scrobbleEpisodeOption == 'true':
- response = cancelWatchingEpisodeOnTrakt()
+ response = utilities.cancelWatchingEpisodeOnTrakt()
if response != None:
- Debug("[Scrobbler] Cancel watch response:
"+str(response));
-
+ Debug("[Scrobbler] Cancel watch response:
"+str(response))
+
def scrobble(self):
scrobbleMovieOption = __settings__.getSetting("scrobble_movie")
scrobbleEpisodeOption =
__settings__.getSetting("scrobble_episode")
-
+
if self.curVideo['type'] == 'movie' and scrobbleMovieOption ==
'true':
match = None
if 'id' in self.curVideo:
- match =
getMovieDetailsFromXbmc(self.curVideo['id'], ['imdbnumber','title','year'])
+ match =
utilities.getMovieDetailsFromXbmc(self.curVideo['id'], ['imdbnumber', 'title',
'year'])
elif 'title' in self.curVideoData and 'year' in
self.curVideoData:
match = {}
match['imdbnumber'] = ''
@@ -155,30 +160,32 @@ class Scrobbler(threading.Thread):
match['year'] = self.curVideoData['year']
if match == None:
return
- response = scrobbleMovieOnTrakt(match['imdbnumber'],
match['title'], match['year'], self.totalTime/60,
int(100*self.watchedTime/self.totalTime))
+ response =
utilities.scrobbleMovieOnTrakt(match['imdbnumber'], match['title'],
match['year'], self.totalTime/60, int(100*self.watchedTime/self.totalTime))
if response != None:
- Debug("[Scrobbler] Scrobble response:
"+str(response));
+ Debug("[Scrobbler] Scrobble response:
"+str(response))
elif self.curVideo['type'] == 'episode' and
scrobbleEpisodeOption == 'true':
match = None
if 'id' in self.curVideo:
- match =
getEpisodeDetailsFromXbmc(self.curVideo['id'], ['showtitle', 'season',
'episode'])
+ match =
utilities.getEpisodeDetailsFromXbmc(self.curVideo['id'], ['showtitle',
'season', 'episode', 'tvshowid'])
elif 'showtitle' in self.curVideoData and 'season' in
self.curVideoData and 'episode' in self.curVideoData:
match = {}
+ match['tvdb_id'] = None
+ match['year'] = None
match['showtitle'] =
self.curVideoData['showtitle']
match['season'] = self.curVideoData['season']
match['episode'] = self.curVideoData['episode']
if match == None:
return
- response = scrobbleEpisodeOnTrakt(None,
match['showtitle'], None, match['season'], match['episode'], self.totalTime/60,
int(100*self.watchedTime/self.totalTime))
+ response =
utilities.scrobbleEpisodeOnTrakt(match['tvdb_id'], match['showtitle'],
match['year'], match['season'], match['episode'], self.totalTime/60,
int(100*self.watchedTime/self.totalTime))
if response != None:
- Debug("[Scrobbler] Scrobble response:
"+str(response));
+ Debug("[Scrobbler] Scrobble response:
"+str(response))
def check(self):
__settings__ = xbmcaddon.Addon("script.trakt") #read settings
again, encase they have changed
scrobbleMinViewTimeOption =
__settings__.getSetting("scrobble_min_view_time")
-
- Debug("watched: " + str(self.watchedTime) + " / " +
str(self.totalTime));
+
+ Debug("watched: " + str(self.watchedTime) + " / " +
str(self.totalTime))
if
(self.watchedTime/self.totalTime)*100>=float(scrobbleMinViewTimeOption):
self.scrobble()
else:
- self.stoppedWatching()
\ No newline at end of file
+ self.stoppedWatching()
diff --git a/script.trakt/service.py b/script.trakt/service.py
index ea5cc64..03ddade 100644
--- a/script.trakt/service.py
+++ b/script.trakt/service.py
@@ -1,9 +1,9 @@
# -*- coding: utf-8 -*-
-#
+#
-#import xbmc,xbmcaddon,xbmcgui
-from utilities import *
-from notification_service import *
+import xbmcaddon
+from utilities import Debug, checkSettings
+from notification_service import NotificationService
__settings__ = xbmcaddon.Addon("script.trakt")
__language__ = __settings__.getLocalizedString
@@ -14,7 +14,7 @@ Debug("loading " + __settings__.getAddonInfo("id") + "
version " + __settings__.
def autostart():
if checkSettings(True):
notificationThread = NotificationService()
- notificationThread.start()
+ notificationThread.start()
notificationThread.join()
-autostart()
\ No newline at end of file
+autostart()
diff --git a/script.trakt/utilities.py b/script.trakt/utilities.py
index 0729ca1..d7cc63d 100644
--- a/script.trakt/utilities.py
+++ b/script.trakt/utilities.py
@@ -1,23 +1,22 @@
# -*- coding: utf-8 -*-
-#
+#
-import os, sys
-import xbmc, xbmcaddon, xbmcgui
+import xbmc
+import xbmcaddon
+import xbmcgui
+import nbconnection
import time, socket
+import math
-try: import simplejson as json
-except ImportError: import json
+try:
+ import simplejson as json
+except ImportError:
+ import json
-from nbhttpconnection import *
-from nbhttpsconnection import *
-
-import urllib, re
-
-try: import http.client as httplib # Python 3.0 +
-except ImportError: import httplib # Python 2.7 and earlier
-
-try: from hashlib import sha as sha # Python 2.6 +
-except ImportError: import sha # Python 2.5 and earlier
+try:
+ from hashlib import sha as sha # Python 2.6 +
+except ImportError:
+ import sha # Python 2.5 and earlier
# read settings
__settings__ = xbmcaddon.Addon("script.trakt")
@@ -31,10 +30,12 @@ debug = __settings__.getSetting("debug")
def Debug(msg, force = False):
if(debug == 'true' or force):
- try: print "[trakt] " + msg
- except UnicodeEncodeError: print "[trakt] " + msg.encode(
"utf-8", "ignore" )
-
-def notification( header, message, time=5000, icon=__settings__.getAddonInfo(
"icon" ) ):
+ try:
+ print "[trakt] " + msg
+ except UnicodeEncodeError:
+ print "[trakt] " + msg.encode( "utf-8", "ignore" )
+
+def notification( header, message, time=5000,
icon=__settings__.getAddonInfo("icon")):
xbmc.executebuiltin( "XBMC.Notification(%s,%s,%i,%s)" % ( header,
message, time, icon ) )
def checkSettings(daemon=False):
@@ -63,15 +64,15 @@ def checkSettings(daemon=False):
return False
return True
-
+
# get a connection to trakt
def getTraktConnection():
https = __settings__.getSetting('https')
try:
if (https == 'true'):
- conn = NBHTTPSConnection('api.trakt.tv')
+ conn = nbconnection.NBConnection('api.trakt.tv',
https=True)
else:
- conn = NBHTTPConnection('api.trakt.tv')
+ conn = nbconnection.NBConnection('api.trakt.tv')
except socket.timeout:
Debug("getTraktConnection: can't connect to trakt - timeout")
notification("trakt", __language__(1108).encode( "utf-8",
"ignore" ) + " (timeout)") # can't connect to trakt
@@ -87,9 +88,9 @@ def getTraktConnection():
# use to customise error notifications
# anon: anonymous (dont send username/password), default:False
# connection: default it to make a new connection but if you want to keep the
same one alive pass it here
-# silent: default is False, when true it disable any error notifications (but
not debug messages)
+# silent: default is True, when true it disable any error notifications (but
not debug messages)
# passVersions: default is False, when true it passes extra version
information to trakt to help debug problems
-def traktJsonRequest(method, req, args={}, returnStatus=False, anon=False,
conn=False, silent=False, passVersions=False):
+def traktJsonRequest(method, req, args={}, returnStatus=False, anon=False,
conn=False, silent=True, passVersions=False):
closeConnection = False
if conn == False:
conn = getTraktConnection()
@@ -103,8 +104,8 @@ def traktJsonRequest(method, req, args={},
returnStatus=False, anon=False, conn=
return None
try:
- req = req.replace("%%API_KEY%%",apikey)
- req = req.replace("%%USERNAME%%",username)
+ req = req.replace("%%API_KEY%%", apikey)
+ req = req.replace("%%USERNAME%%", username)
if method == 'POST':
if not anon:
args['username'] = username
@@ -122,12 +123,13 @@ def traktJsonRequest(method, req, args={},
returnStatus=False, anon=False, conn=
Debug("json url: "+req)
except socket.error:
Debug("traktQuery: can't connect to trakt")
- if not silent: notification("trakt", __language__(1108).encode(
"utf-8", "ignore" )) # can't connect to trakt
+ if not silent:
+ notification("trakt", __language__(1108).encode(
"utf-8", "ignore" )) # can't connect to trakt
if returnStatus:
data = {}
data['status'] = 'failure'
data['error'] = 'Socket error, unable to connect to
trakt'
- return data;
+ return data
return None
conn.go()
@@ -139,7 +141,7 @@ def traktJsonRequest(method, req, args={},
returnStatus=False, anon=False, conn=
data = {}
data['status'] = 'failure'
data['error'] = 'Abort requested, not waiting
for response'
- return data;
+ return data
return None
if conn.hasResult():
break
@@ -159,24 +161,27 @@ def traktJsonRequest(method, req, args={},
returnStatus=False, anon=False, conn=
data['status'] = 'failure'
data['error'] = 'Bad response from trakt'
return data
- if not silent: notification("trakt", __language__(1109).encode(
"utf-8", "ignore" ) + ": Bad response from trakt") # Error
+ if not silent:
+ notification("trakt", __language__(1109).encode(
"utf-8", "ignore" ) + ": Bad response from trakt") # Error
return None
if 'status' in data:
if data['status'] == 'failure':
Debug("traktQuery: Error: " + str(data['error']))
if returnStatus:
- return data;
- if not silent: notification("trakt",
__language__(1109).encode( "utf-8", "ignore" ) + ": " + str(data['error'])) #
Error
+ return data
+ if not silent:
+ notification("trakt",
__language__(1109).encode( "utf-8", "ignore" ) + ": " + str(data['error'])) #
Error
return None
return data
# get a single episode from xbmc given the id
def getEpisodeDetailsFromXbmc(libraryId, fields):
- rpccmd = json.dumps({'jsonrpc': '2.0', 'method':
'VideoLibrary.GetEpisodeDetails','params':{'episodeid': libraryId,
'properties': fields}, 'id': 1})
+ rpccmd = json.dumps({'jsonrpc': '2.0', 'method':
'VideoLibrary.GetEpisodeDetails', 'params':{'episodeid': libraryId,
'properties': fields}, 'id': 1})
result = xbmc.executeJSONRPC(rpccmd)
+ Debug('[VideoLibrary.GetEpisodeDetails] ' + result)
result = json.loads(result)
# check for error
@@ -188,6 +193,17 @@ def getEpisodeDetailsFromXbmc(libraryId, fields):
pass # no error
try:
+ # get tvdb id
+ rpccmd_show = json.dumps({'jsonrpc': '2.0', 'method':
'VideoLibrary.GetTVShowDetails', 'params':{'tvshowid':
result['result']['episodedetails']['tvshowid'], 'properties': ['year',
'imdbnumber']}, 'id': 1})
+
+ result_show = xbmc.executeJSONRPC(rpccmd_show)
+ Debug('[VideoLibrary.GetTVShowDetails] ' + result_show)
+ result_show = json.loads(result_show)
+
+ # add to episode data
+ result['result']['episodedetails']['tvdb_id'] =
result_show['result']['tvshowdetails']['imdbnumber']
+ result['result']['episodedetails']['year'] =
result_show['result']['tvshowdetails']['year']
+
return result['result']['episodedetails']
except KeyError:
Debug("getEpisodeDetailsFromXbmc: KeyError:
result['result']['episodedetails']")
@@ -195,9 +211,10 @@ def getEpisodeDetailsFromXbmc(libraryId, fields):
# get a single movie from xbmc given the id
def getMovieDetailsFromXbmc(libraryId, fields):
- rpccmd = json.dumps({'jsonrpc': '2.0', 'method':
'VideoLibrary.GetMovieDetails','params':{'movieid': libraryId, 'properties':
fields}, 'id': 1})
+ rpccmd = json.dumps({'jsonrpc': '2.0', 'method':
'VideoLibrary.GetMovieDetails', 'params':{'movieid': libraryId, 'properties':
fields}, 'id': 1})
result = xbmc.executeJSONRPC(rpccmd)
+ Debug('[VideoLibrary.GetMovieDetails] ' + result)
result = json.loads(result)
# check for error
@@ -221,7 +238,7 @@ def getPlaylistLengthFromXBMCPlayer(playerid):
if playerid < 0 or playerid > 2:
Debug("[Util] getPlaylistLengthFromXBMCPlayer, invalid
playerid: "+str(playerid))
return 0
- rpccmd = json.dumps({'jsonrpc': '2.0', 'method':
'Player.GetProperties','params':{'playerid': playerid,
'properties':['playlistid']}, 'id': 1})
+ rpccmd = json.dumps({'jsonrpc': '2.0', 'method':
'Player.GetProperties', 'params':{'playerid': playerid,
'properties':['playlistid']}, 'id': 1})
result = xbmc.executeJSONRPC(rpccmd)
result = json.loads(result)
# check for error
@@ -233,7 +250,7 @@ def getPlaylistLengthFromXBMCPlayer(playerid):
pass # no error
playlistid = result['result']['playlistid']
- rpccmd = json.dumps({'jsonrpc': '2.0', 'method':
'Playlist.GetProperties','params':{'playlistid': playlistid, 'properties':
['size']}, 'id': 1})
+ rpccmd = json.dumps({'jsonrpc': '2.0', 'method':
'Playlist.GetProperties', 'params':{'playlistid': playlistid, 'properties':
['size']}, 'id': 1})
result = xbmc.executeJSONRPC(rpccmd)
result = json.loads(result)
# check for error
@@ -245,21 +262,21 @@ def getPlaylistLengthFromXBMCPlayer(playerid):
pass # no error
return result['result']['size']
-
+
###############################
##### Scrobbling to trakt #####
###############################
#tell trakt that the user is watching a movie
def watchingMovieOnTrakt(imdb_id, title, year, duration, percent):
- response = traktJsonRequest('POST', '/movie/watching/%%API_KEY%%',
{'imdb_id': imdb_id, 'title': title, 'year': year, 'duration': duration,
'progress': percent}, passVersions=True)
+ response = traktJsonRequest('POST', '/movie/watching/%%API_KEY%%',
{'imdb_id': imdb_id, 'title': title, 'year': year, 'duration':
math.ceil(duration), 'progress': math.ceil(percent)}, passVersions=True)
if response == None:
Debug("Error in request from 'watchingMovieOnTrakt()'")
return response
#tell trakt that the user is watching an episode
def watchingEpisodeOnTrakt(tvdb_id, title, year, season, episode, duration,
percent):
- response = traktJsonRequest('POST', '/show/watching/%%API_KEY%%',
{'tvdb_id': tvdb_id, 'title': title, 'year': year, 'season': season, 'episode':
episode, 'duration': duration, 'progress': percent}, passVersions=True)
+ response = traktJsonRequest('POST', '/show/watching/%%API_KEY%%',
{'tvdb_id': tvdb_id, 'title': title, 'year': year, 'season': season, 'episode':
episode, 'duration': math.ceil(duration), 'progress': math.ceil(percent)},
passVersions=True)
if response == None:
Debug("Error in request from 'watchingEpisodeOnTrakt()'")
return response
@@ -280,14 +297,14 @@ def cancelWatchingEpisodeOnTrakt():
#tell trakt that the user has finished watching an movie
def scrobbleMovieOnTrakt(imdb_id, title, year, duration, percent):
- response = traktJsonRequest('POST', '/movie/scrobble/%%API_KEY%%',
{'imdb_id': imdb_id, 'title': title, 'year': year, 'duration': duration,
'progress': percent}, passVersions=True)
+ response = traktJsonRequest('POST', '/movie/scrobble/%%API_KEY%%',
{'imdb_id': imdb_id, 'title': title, 'year': year, 'duration':
math.ceil(duration), 'progress': math.ceil(percent)}, passVersions=True)
if response == None:
Debug("Error in request from 'scrobbleMovieOnTrakt()'")
return response
#tell trakt that the user has finished watching an episode
def scrobbleEpisodeOnTrakt(tvdb_id, title, year, season, episode, duration,
percent):
- response = traktJsonRequest('POST', '/show/scrobble/%%API_KEY%%',
{'tvdb_id': tvdb_id, 'title': title, 'year': year, 'season': season, 'episode':
episode, 'duration': duration, 'progress': percent}, passVersions=True)
+ response = traktJsonRequest('POST', '/show/scrobble/%%API_KEY%%',
{'tvdb_id': tvdb_id, 'title': title, 'year': year, 'season': season, 'episode':
episode, 'duration': math.ceil(duration), 'progress': math.ceil(percent)},
passVersions=True)
if response == None:
Debug("Error in request from 'scrobbleEpisodeOnTrakt()'")
- return response
\ No newline at end of file
+ return response
-----------------------------------------------------------------------
Summary of changes:
script.trakt/README.md | 10 +-
script.trakt/addon.xml | 3 +-
script.trakt/changelog.txt | 5 +
script.trakt/nbconnection.py | 49 +++++++
script.trakt/nbhttpconnection.py | 49 -------
script.trakt/nbhttpsconnection.py | 49 -------
script.trakt/notification_service.py | 144 ++++++++++----------
.../language/Portuguese (Brazil)/strings.xml | 2 +-
script.trakt/scrobbler.py | 83 ++++++-----
script.trakt/service.py | 12 +-
script.trakt/utilities.py | 101 ++++++++------
11 files changed, 243 insertions(+), 264 deletions(-)
create mode 100644 script.trakt/nbconnection.py
delete mode 100644 script.trakt/nbhttpconnection.py
delete mode 100644 script.trakt/nbhttpsconnection.py
hooks/post-receive
--
Scripts
------------------------------------------------------------------------------
Live Security Virtual Conference
Exclusive live event will cover all the ways today's security and
threat landscape has changed and how IT managers can respond. Discussions
will include endpoint security, mobile security and the latest in malware
threats. http://www.accelacomm.com/jaw/sfrnl04242012/114/50122263/
_______________________________________________
Xbmc-addons mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/xbmc-addons