Remove unicode strings

This commit is contained in:
JonnyWong16 2019-11-23 14:37:26 -08:00
parent 1c18e72539
commit c279057f91
28 changed files with 834 additions and 847 deletions

View file

@ -1,8 +1,4 @@
#!/bin/sh #!/usr/bin/env python
''''which python >/dev/null 2>&1 && exec python "$0" "$@" # '''
''''which python2 >/dev/null 2>&1 && exec python2 "$0" "$@" # '''
''''which python2.7 >/dev/null 2>&1 && exec python2.7 "$0" "$@" # '''
''''exec echo "Error: Python not found!" # '''
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
@ -21,6 +17,8 @@
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with Tautulli. If not, see <http://www.gnu.org/licenses/>. # along with Tautulli. If not, see <http://www.gnu.org/licenses/>.
from __future__ import unicode_literals
import os import os
import sys import sys
@ -122,7 +120,7 @@ def main():
if args.dev: if args.dev:
plexpy.DEV = True plexpy.DEV = True
logger.debug(u"Tautulli is running in the dev environment.") logger.debug("Tautulli is running in the dev environment.")
if args.daemon: if args.daemon:
if sys.platform == 'win32': if sys.platform == 'win32':

View file

@ -137,8 +137,7 @@ def initialize(config_file):
return False return False
if CONFIG.HTTP_PORT < 21 or CONFIG.HTTP_PORT > 65535: if CONFIG.HTTP_PORT < 21 or CONFIG.HTTP_PORT > 65535:
plexpy.logger.warn( plexpy.logger.warn("HTTP_PORT out of bounds: 21 < %s < 65535", CONFIG.HTTP_PORT)
u"HTTP_PORT out of bounds: 21 < %s < 65535", CONFIG.HTTP_PORT)
CONFIG.HTTP_PORT = 8181 CONFIG.HTTP_PORT = 8181
if not CONFIG.HTTPS_CERT: if not CONFIG.HTTPS_CERT:
@ -155,26 +154,26 @@ def initialize(config_file):
logger.initLogger(console=not QUIET, log_dir=CONFIG.LOG_DIR if log_writable else None, logger.initLogger(console=not QUIET, log_dir=CONFIG.LOG_DIR if log_writable else None,
verbose=VERBOSE) verbose=VERBOSE)
logger.info(u"Starting Tautulli {}".format( logger.info("Starting Tautulli {}".format(
common.RELEASE common.RELEASE
)) ))
logger.info(u"{}{} {} ({}{})".format( logger.info("{}{} {} ({}{})".format(
'[Docker] ' if DOCKER else '', common.PLATFORM, common.PLATFORM_RELEASE, common.PLATFORM_VERSION, '[Docker] ' if DOCKER else '', common.PLATFORM, common.PLATFORM_RELEASE, common.PLATFORM_VERSION,
' - {}'.format(common.PLATFORM_LINUX_DISTRO) if common.PLATFORM_LINUX_DISTRO else '' ' - {}'.format(common.PLATFORM_LINUX_DISTRO) if common.PLATFORM_LINUX_DISTRO else ''
)) ))
logger.info(u"{} (UTC{})".format( logger.info("{} (UTC{})".format(
plexpy.SYS_TIMEZONE.zone, plexpy.SYS_UTC_OFFSET plexpy.SYS_TIMEZONE.zone, plexpy.SYS_UTC_OFFSET
)) ))
logger.info(u"Python {}".format( logger.info("Python {}".format(
sys.version sys.version
)) ))
logger.info(u"Program Dir: {}".format( logger.info("Program Dir: {}".format(
PROG_DIR PROG_DIR
)) ))
logger.info(u"Config File: {}".format( logger.info("Config File: {}".format(
CONFIG_FILE CONFIG_FILE
)) ))
logger.info(u"Database File: {}".format( logger.info("Database File: {}".format(
DB_FILE DB_FILE
)) ))
@ -186,18 +185,18 @@ def initialize(config_file):
CONFIG.NEWSLETTER_DIR, os.path.join(DATA_DIR, 'newsletters'), 'newsletters') CONFIG.NEWSLETTER_DIR, os.path.join(DATA_DIR, 'newsletters'), 'newsletters')
# Initialize the database # Initialize the database
logger.info(u"Checking if the database upgrades are required...") logger.info("Checking if the database upgrades are required...")
try: try:
dbcheck() dbcheck()
except Exception as e: except Exception as e:
logger.error(u"Can't connect to the database: %s" % e) logger.error("Can't connect to the database: %s" % e)
# Perform upgrades # Perform upgrades
logger.info(u"Checking if configuration upgrades are required...") logger.info("Checking if configuration upgrades are required...")
try: try:
upgrade() upgrade()
except Exception as e: except Exception as e:
logger.error(u"Could not perform upgrades: %s" % e) logger.error("Could not perform upgrades: %s" % e)
# Add notifier configs to logger blacklist # Add notifier configs to logger blacklist
newsletters.blacklist_logger() newsletters.blacklist_logger()
@ -206,19 +205,19 @@ def initialize(config_file):
# Check if Tautulli has a uuid # Check if Tautulli has a uuid
if CONFIG.PMS_UUID == '' or not CONFIG.PMS_UUID: if CONFIG.PMS_UUID == '' or not CONFIG.PMS_UUID:
logger.debug(u"Generating UUID...") logger.debug("Generating UUID...")
CONFIG.PMS_UUID = generate_uuid() CONFIG.PMS_UUID = generate_uuid()
CONFIG.write() CONFIG.write()
# Check if Tautulli has an API key # Check if Tautulli has an API key
if CONFIG.API_KEY == '': if CONFIG.API_KEY == '':
logger.debug(u"Generating API key...") logger.debug("Generating API key...")
CONFIG.API_KEY = generate_uuid() CONFIG.API_KEY = generate_uuid()
CONFIG.write() CONFIG.write()
# Check if Tautulli has a jwt_secret # Check if Tautulli has a jwt_secret
if CONFIG.JWT_SECRET == '' or not CONFIG.JWT_SECRET or CONFIG.JWT_UPDATE_SECRET: if CONFIG.JWT_SECRET == '' or not CONFIG.JWT_SECRET or CONFIG.JWT_UPDATE_SECRET:
logger.debug(u"Generating JWT secret...") logger.debug("Generating JWT secret...")
CONFIG.JWT_SECRET = generate_uuid() CONFIG.JWT_SECRET = generate_uuid()
CONFIG.JWT_UPDATE_SECRET = False CONFIG.JWT_UPDATE_SECRET = False
CONFIG.write() CONFIG.write()
@ -231,7 +230,7 @@ def initialize(config_file):
with open(version_lock_file, "r") as fp: with open(version_lock_file, "r") as fp:
prev_version = fp.read() prev_version = fp.read()
except IOError as e: except IOError as e:
logger.error(u"Unable to read previous version from file '%s': %s" % logger.error("Unable to read previous version from file '%s': %s" %
(version_lock_file, e)) (version_lock_file, e))
else: else:
prev_version = 'cfd30996264b7e9fe4ef87f02d1cc52d1ae8bfca' prev_version = 'cfd30996264b7e9fe4ef87f02d1cc52d1ae8bfca'
@ -248,7 +247,7 @@ def initialize(config_file):
with open(version_lock_file, "w") as fp: with open(version_lock_file, "w") as fp:
fp.write(CURRENT_VERSION) fp.write(CURRENT_VERSION)
except IOError as e: except IOError as e:
logger.error(u"Unable to write current version to file '%s': %s" % logger.error("Unable to write current version to file '%s': %s" %
(version_lock_file, e)) (version_lock_file, e))
# Check for new versions # Check for new versions
@ -256,7 +255,7 @@ def initialize(config_file):
try: try:
versioncheck.check_update() versioncheck.check_update()
except: except:
logger.exception(u"Unhandled exception") logger.exception("Unhandled exception")
LATEST_VERSION = CURRENT_VERSION LATEST_VERSION = CURRENT_VERSION
else: else:
LATEST_VERSION = CURRENT_VERSION LATEST_VERSION = CURRENT_VERSION
@ -269,7 +268,7 @@ def initialize(config_file):
with open(release_file, "r") as fp: with open(release_file, "r") as fp:
PREV_RELEASE = fp.read() PREV_RELEASE = fp.read()
except IOError as e: except IOError as e:
logger.error(u"Unable to read previous release from file '%s': %s" % logger.error("Unable to read previous release from file '%s': %s" %
(release_file, e)) (release_file, e))
elif prev_version == 'cfd30996264b7e9fe4ef87f02d1cc52d1ae8bfca': # Commit hash for v1.4.25 elif prev_version == 'cfd30996264b7e9fe4ef87f02d1cc52d1ae8bfca': # Commit hash for v1.4.25
PREV_RELEASE = 'v1.4.25' PREV_RELEASE = 'v1.4.25'
@ -285,7 +284,7 @@ def initialize(config_file):
with open(release_file, "w") as fp: with open(release_file, "w") as fp:
fp.write(common.RELEASE) fp.write(common.RELEASE)
except IOError as e: except IOError as e:
logger.error(u"Unable to write current release to file '%s': %s" % logger.error("Unable to write current release to file '%s': %s" %
(release_file, e)) (release_file, e))
# Get the real PMS urls for SSL and remote access # Get the real PMS urls for SSL and remote access
@ -311,7 +310,7 @@ def initialize(config_file):
def daemonize(): def daemonize():
if threading.activeCount() != 1: if threading.activeCount() != 1:
logger.warn( logger.warn(
u"There are %r active threads. Daemonizing may cause" "There are %r active threads. Daemonizing may cause"
" strange behavior.", " strange behavior.",
threading.enumerate()) threading.enumerate())
@ -352,10 +351,10 @@ def daemonize():
os.dup2(se.fileno(), sys.stderr.fileno()) os.dup2(se.fileno(), sys.stderr.fileno())
pid = os.getpid() pid = os.getpid()
logger.info(u"Daemonized to PID: %d", pid) logger.info("Daemonized to PID: %d", pid)
if CREATEPID: if CREATEPID:
logger.info(u"Writing PID %d to %s", pid, PIDFILE) logger.info("Writing PID %d to %s", pid, PIDFILE)
with file(PIDFILE, 'w') as fp: with file(PIDFILE, 'w') as fp:
fp.write("%s\n" % pid) fp.write("%s\n" % pid)
@ -373,7 +372,7 @@ def launch_browser(host, port, root):
try: try:
webbrowser.open('%s://%s:%i%s' % (protocol, host, port, root)) webbrowser.open('%s://%s:%i%s' % (protocol, host, port, root))
except Exception as e: except Exception as e:
logger.error(u"Could not launch browser: %s" % e) logger.error("Could not launch browser: %s" % e)
def win_system_tray(): def win_system_tray():
@ -411,13 +410,13 @@ def win_system_tray():
('Update', None, tray_update, None), ('Update', None, tray_update, None),
('Restart', None, tray_restart, None)) ('Restart', None, tray_restart, None))
logger.info(u"Launching system tray icon.") logger.info("Launching system tray icon.")
try: try:
plexpy.WIN_SYS_TRAY_ICON = SysTrayIcon(icon, hover_text, menu_options, on_quit=tray_quit) plexpy.WIN_SYS_TRAY_ICON = SysTrayIcon(icon, hover_text, menu_options, on_quit=tray_quit)
plexpy.WIN_SYS_TRAY_ICON.start() plexpy.WIN_SYS_TRAY_ICON.start()
except Exception as e: except Exception as e:
logger.error(u"Unable to launch system tray icon: %s." % e) logger.error("Unable to launch system tray icon: %s." % e)
plexpy.WIN_SYS_TRAY_ICON = None plexpy.WIN_SYS_TRAY_ICON = None
@ -509,15 +508,15 @@ def schedule_job(func, name, hours=0, minutes=0, seconds=0, args=None):
if job: if job:
if hours == 0 and minutes == 0 and seconds == 0: if hours == 0 and minutes == 0 and seconds == 0:
SCHED.remove_job(name) SCHED.remove_job(name)
logger.info(u"Removed background task: %s", name) logger.info("Removed background task: %s", name)
elif job.trigger.interval != datetime.timedelta(hours=hours, minutes=minutes): elif job.trigger.interval != datetime.timedelta(hours=hours, minutes=minutes):
SCHED.reschedule_job(name, trigger=IntervalTrigger( SCHED.reschedule_job(name, trigger=IntervalTrigger(
hours=hours, minutes=minutes, seconds=seconds, timezone=pytz.UTC), args=args) hours=hours, minutes=minutes, seconds=seconds, timezone=pytz.UTC), args=args)
logger.info(u"Re-scheduled background task: %s", name) logger.info("Re-scheduled background task: %s", name)
elif hours > 0 or minutes > 0 or seconds > 0: elif hours > 0 or minutes > 0 or seconds > 0:
SCHED.add_job(func, id=name, trigger=IntervalTrigger( SCHED.add_job(func, id=name, trigger=IntervalTrigger(
hours=hours, minutes=minutes, seconds=seconds, timezone=pytz.UTC), args=args) hours=hours, minutes=minutes, seconds=seconds, timezone=pytz.UTC), args=args)
logger.info(u"Scheduled background task: %s", name) logger.info("Scheduled background task: %s", name)
def start(): def start():
@ -561,7 +560,7 @@ def start():
def sig_handler(signum=None, frame=None): def sig_handler(signum=None, frame=None):
if signum is not None: if signum is not None:
logger.info(u"Signal %i caught, saving and exiting...", signum) logger.info("Signal %i caught, saving and exiting...", signum)
shutdown() shutdown()
@ -781,7 +780,7 @@ def dbcheck():
try: try:
c_db.execute('SELECT started FROM sessions') c_db.execute('SELECT started FROM sessions')
except sqlite3.OperationalError: except sqlite3.OperationalError:
logger.debug(u"Altering database. Updating database table sessions.") logger.debug("Altering database. Updating database table sessions.")
c_db.execute( c_db.execute(
'ALTER TABLE sessions ADD COLUMN started INTEGER' 'ALTER TABLE sessions ADD COLUMN started INTEGER'
) )
@ -802,7 +801,7 @@ def dbcheck():
try: try:
c_db.execute('SELECT title FROM sessions') c_db.execute('SELECT title FROM sessions')
except sqlite3.OperationalError: except sqlite3.OperationalError:
logger.debug(u"Altering database. Updating database table sessions.") logger.debug("Altering database. Updating database table sessions.")
c_db.execute( c_db.execute(
'ALTER TABLE sessions ADD COLUMN title TEXT' 'ALTER TABLE sessions ADD COLUMN title TEXT'
) )
@ -826,7 +825,7 @@ def dbcheck():
try: try:
c_db.execute('SELECT ip_address FROM sessions') c_db.execute('SELECT ip_address FROM sessions')
except sqlite3.OperationalError: except sqlite3.OperationalError:
logger.debug(u"Altering database. Updating database table sessions.") logger.debug("Altering database. Updating database table sessions.")
c_db.execute( c_db.execute(
'ALTER TABLE sessions ADD COLUMN ip_address TEXT' 'ALTER TABLE sessions ADD COLUMN ip_address TEXT'
) )
@ -907,7 +906,7 @@ def dbcheck():
try: try:
c_db.execute('SELECT buffer_count FROM sessions') c_db.execute('SELECT buffer_count FROM sessions')
except sqlite3.OperationalError: except sqlite3.OperationalError:
logger.debug(u"Altering database. Updating database table sessions.") logger.debug("Altering database. Updating database table sessions.")
c_db.execute( c_db.execute(
'ALTER TABLE sessions ADD COLUMN buffer_count INTEGER DEFAULT 0' 'ALTER TABLE sessions ADD COLUMN buffer_count INTEGER DEFAULT 0'
) )
@ -919,7 +918,7 @@ def dbcheck():
try: try:
c_db.execute('SELECT last_paused FROM sessions') c_db.execute('SELECT last_paused FROM sessions')
except sqlite3.OperationalError: except sqlite3.OperationalError:
logger.debug(u"Altering database. Updating database table sessions.") logger.debug("Altering database. Updating database table sessions.")
c_db.execute( c_db.execute(
'ALTER TABLE sessions ADD COLUMN last_paused INTEGER' 'ALTER TABLE sessions ADD COLUMN last_paused INTEGER'
) )
@ -928,7 +927,7 @@ def dbcheck():
try: try:
c_db.execute('SELECT section_id FROM sessions') c_db.execute('SELECT section_id FROM sessions')
except sqlite3.OperationalError: except sqlite3.OperationalError:
logger.debug(u"Altering database. Updating database table sessions.") logger.debug("Altering database. Updating database table sessions.")
c_db.execute( c_db.execute(
'ALTER TABLE sessions ADD COLUMN section_id INTEGER' 'ALTER TABLE sessions ADD COLUMN section_id INTEGER'
) )
@ -937,7 +936,7 @@ def dbcheck():
try: try:
c_db.execute('SELECT stopped FROM sessions') c_db.execute('SELECT stopped FROM sessions')
except sqlite3.OperationalError: except sqlite3.OperationalError:
logger.debug(u"Altering database. Updating database table sessions.") logger.debug("Altering database. Updating database table sessions.")
c_db.execute( c_db.execute(
'ALTER TABLE sessions ADD COLUMN stopped INTEGER' 'ALTER TABLE sessions ADD COLUMN stopped INTEGER'
) )
@ -946,7 +945,7 @@ def dbcheck():
try: try:
c_db.execute('SELECT transcode_key FROM sessions') c_db.execute('SELECT transcode_key FROM sessions')
except sqlite3.OperationalError: except sqlite3.OperationalError:
logger.debug(u"Altering database. Updating database table sessions.") logger.debug("Altering database. Updating database table sessions.")
c_db.execute( c_db.execute(
'ALTER TABLE sessions ADD COLUMN transcode_key TEXT' 'ALTER TABLE sessions ADD COLUMN transcode_key TEXT'
) )
@ -955,7 +954,7 @@ def dbcheck():
try: try:
c_db.execute('SELECT write_attempts FROM sessions') c_db.execute('SELECT write_attempts FROM sessions')
except sqlite3.OperationalError: except sqlite3.OperationalError:
logger.debug(u"Altering database. Updating database table sessions.") logger.debug("Altering database. Updating database table sessions.")
c_db.execute( c_db.execute(
'ALTER TABLE sessions ADD COLUMN write_attempts INTEGER DEFAULT 0' 'ALTER TABLE sessions ADD COLUMN write_attempts INTEGER DEFAULT 0'
) )
@ -964,7 +963,7 @@ def dbcheck():
try: try:
c_db.execute('SELECT transcode_decision FROM sessions') c_db.execute('SELECT transcode_decision FROM sessions')
except sqlite3.OperationalError: except sqlite3.OperationalError:
logger.debug(u"Altering database. Updating database table sessions.") logger.debug("Altering database. Updating database table sessions.")
c_db.execute( c_db.execute(
'ALTER TABLE sessions ADD COLUMN transcode_decision TEXT' 'ALTER TABLE sessions ADD COLUMN transcode_decision TEXT'
) )
@ -994,7 +993,7 @@ def dbcheck():
try: try:
c_db.execute('SELECT raw_stream_info FROM sessions') c_db.execute('SELECT raw_stream_info FROM sessions')
except sqlite3.OperationalError: except sqlite3.OperationalError:
logger.debug(u"Altering database. Updating database table sessions.") logger.debug("Altering database. Updating database table sessions.")
c_db.execute( c_db.execute(
'ALTER TABLE sessions ADD COLUMN product TEXT' 'ALTER TABLE sessions ADD COLUMN product TEXT'
) )
@ -1084,7 +1083,7 @@ def dbcheck():
try: try:
c_db.execute('SELECT video_height FROM sessions') c_db.execute('SELECT video_height FROM sessions')
except sqlite3.OperationalError: except sqlite3.OperationalError:
logger.debug(u"Altering database. Updating database table sessions.") logger.debug("Altering database. Updating database table sessions.")
c_db.execute( c_db.execute(
'ALTER TABLE sessions ADD COLUMN video_height INTEGER' 'ALTER TABLE sessions ADD COLUMN video_height INTEGER'
) )
@ -1093,7 +1092,7 @@ def dbcheck():
try: try:
c_db.execute('SELECT subtitles FROM sessions') c_db.execute('SELECT subtitles FROM sessions')
except sqlite3.OperationalError: except sqlite3.OperationalError:
logger.debug(u"Altering database. Updating database table sessions.") logger.debug("Altering database. Updating database table sessions.")
c_db.execute( c_db.execute(
'ALTER TABLE sessions ADD COLUMN subtitles INTEGER' 'ALTER TABLE sessions ADD COLUMN subtitles INTEGER'
) )
@ -1102,7 +1101,7 @@ def dbcheck():
try: try:
c_db.execute('SELECT synced_version_profile FROM sessions') c_db.execute('SELECT synced_version_profile FROM sessions')
except sqlite3.OperationalError: except sqlite3.OperationalError:
logger.debug(u"Altering database. Updating database table sessions.") logger.debug("Altering database. Updating database table sessions.")
c_db.execute( c_db.execute(
'ALTER TABLE sessions ADD COLUMN synced_version_profile TEXT' 'ALTER TABLE sessions ADD COLUMN synced_version_profile TEXT'
) )
@ -1114,7 +1113,7 @@ def dbcheck():
try: try:
c_db.execute('SELECT transcode_hw_decoding FROM sessions') c_db.execute('SELECT transcode_hw_decoding FROM sessions')
except sqlite3.OperationalError: except sqlite3.OperationalError:
logger.debug(u"Altering database. Updating database table sessions.") logger.debug("Altering database. Updating database table sessions.")
c_db.execute( c_db.execute(
'ALTER TABLE sessions ADD COLUMN transcode_hw_decoding INTEGER' 'ALTER TABLE sessions ADD COLUMN transcode_hw_decoding INTEGER'
) )
@ -1126,7 +1125,7 @@ def dbcheck():
try: try:
c_db.execute('SELECT watched FROM sessions') c_db.execute('SELECT watched FROM sessions')
except sqlite3.OperationalError: except sqlite3.OperationalError:
logger.debug(u"Altering database. Updating database table sessions.") logger.debug("Altering database. Updating database table sessions.")
c_db.execute( c_db.execute(
'ALTER TABLE sessions ADD COLUMN watched INTEGER DEFAULT 0' 'ALTER TABLE sessions ADD COLUMN watched INTEGER DEFAULT 0'
) )
@ -1135,7 +1134,7 @@ def dbcheck():
try: try:
c_db.execute('SELECT live FROM sessions') c_db.execute('SELECT live FROM sessions')
except sqlite3.OperationalError: except sqlite3.OperationalError:
logger.debug(u"Altering database. Updating database table sessions.") logger.debug("Altering database. Updating database table sessions.")
c_db.execute( c_db.execute(
'ALTER TABLE sessions ADD COLUMN live INTEGER' 'ALTER TABLE sessions ADD COLUMN live INTEGER'
) )
@ -1147,7 +1146,7 @@ def dbcheck():
try: try:
c_db.execute('SELECT session_id FROM sessions') c_db.execute('SELECT session_id FROM sessions')
except sqlite3.OperationalError: except sqlite3.OperationalError:
logger.debug(u"Altering database. Updating database table sessions.") logger.debug("Altering database. Updating database table sessions.")
c_db.execute( c_db.execute(
'ALTER TABLE sessions ADD COLUMN session_id TEXT' 'ALTER TABLE sessions ADD COLUMN session_id TEXT'
) )
@ -1156,7 +1155,7 @@ def dbcheck():
try: try:
c_db.execute('SELECT original_title FROM sessions') c_db.execute('SELECT original_title FROM sessions')
except sqlite3.OperationalError: except sqlite3.OperationalError:
logger.debug(u"Altering database. Updating database table sessions.") logger.debug("Altering database. Updating database table sessions.")
c_db.execute( c_db.execute(
'ALTER TABLE sessions ADD COLUMN original_title TEXT' 'ALTER TABLE sessions ADD COLUMN original_title TEXT'
) )
@ -1165,7 +1164,7 @@ def dbcheck():
try: try:
c_db.execute('SELECT secure FROM sessions') c_db.execute('SELECT secure FROM sessions')
except sqlite3.OperationalError: except sqlite3.OperationalError:
logger.debug(u"Altering database. Updating database table sessions.") logger.debug("Altering database. Updating database table sessions.")
c_db.execute( c_db.execute(
'ALTER TABLE sessions ADD COLUMN secure INTEGER' 'ALTER TABLE sessions ADD COLUMN secure INTEGER'
) )
@ -1177,7 +1176,7 @@ def dbcheck():
try: try:
c_db.execute('SELECT rating_key_websocket FROM sessions') c_db.execute('SELECT rating_key_websocket FROM sessions')
except sqlite3.OperationalError: except sqlite3.OperationalError:
logger.debug(u"Altering database. Updating database table sessions.") logger.debug("Altering database. Updating database table sessions.")
c_db.execute( c_db.execute(
'ALTER TABLE sessions ADD COLUMN rating_key_websocket TEXT' 'ALTER TABLE sessions ADD COLUMN rating_key_websocket TEXT'
) )
@ -1186,7 +1185,7 @@ def dbcheck():
try: try:
c_db.execute('SELECT video_scan_type FROM sessions') c_db.execute('SELECT video_scan_type FROM sessions')
except sqlite3.OperationalError: except sqlite3.OperationalError:
logger.debug(u"Altering database. Updating database table sessions.") logger.debug("Altering database. Updating database table sessions.")
c_db.execute( c_db.execute(
'ALTER TABLE sessions ADD COLUMN video_scan_type TEXT' 'ALTER TABLE sessions ADD COLUMN video_scan_type TEXT'
) )
@ -1204,7 +1203,7 @@ def dbcheck():
try: try:
c_db.execute('SELECT reference_id FROM session_history') c_db.execute('SELECT reference_id FROM session_history')
except sqlite3.OperationalError: except sqlite3.OperationalError:
logger.debug(u"Altering database. Updating database table session_history.") logger.debug("Altering database. Updating database table session_history.")
c_db.execute( c_db.execute(
'ALTER TABLE session_history ADD COLUMN reference_id INTEGER DEFAULT 0' 'ALTER TABLE session_history ADD COLUMN reference_id INTEGER DEFAULT 0'
) )
@ -1227,7 +1226,7 @@ def dbcheck():
try: try:
c_db.execute('SELECT bandwidth FROM session_history') c_db.execute('SELECT bandwidth FROM session_history')
except sqlite3.OperationalError: except sqlite3.OperationalError:
logger.debug(u"Altering database. Updating database table session_history.") logger.debug("Altering database. Updating database table session_history.")
c_db.execute( c_db.execute(
'ALTER TABLE session_history ADD COLUMN platform_version TEXT' 'ALTER TABLE session_history ADD COLUMN platform_version TEXT'
) )
@ -1254,7 +1253,7 @@ def dbcheck():
try: try:
c_db.execute('SELECT secure FROM session_history') c_db.execute('SELECT secure FROM session_history')
except sqlite3.OperationalError: except sqlite3.OperationalError:
logger.debug(u"Altering database. Updating database table session_history.") logger.debug("Altering database. Updating database table session_history.")
c_db.execute( c_db.execute(
'ALTER TABLE session_history ADD COLUMN secure INTEGER' 'ALTER TABLE session_history ADD COLUMN secure INTEGER'
) )
@ -1266,7 +1265,7 @@ def dbcheck():
try: try:
c_db.execute('SELECT full_title FROM session_history_metadata') c_db.execute('SELECT full_title FROM session_history_metadata')
except sqlite3.OperationalError: except sqlite3.OperationalError:
logger.debug(u"Altering database. Updating database table session_history_metadata.") logger.debug("Altering database. Updating database table session_history_metadata.")
c_db.execute( c_db.execute(
'ALTER TABLE session_history_metadata ADD COLUMN full_title TEXT' 'ALTER TABLE session_history_metadata ADD COLUMN full_title TEXT'
) )
@ -1275,7 +1274,7 @@ def dbcheck():
try: try:
c_db.execute('SELECT tagline FROM session_history_metadata') c_db.execute('SELECT tagline FROM session_history_metadata')
except sqlite3.OperationalError: except sqlite3.OperationalError:
logger.debug(u"Altering database. Updating database table session_history_metadata.") logger.debug("Altering database. Updating database table session_history_metadata.")
c_db.execute( c_db.execute(
'ALTER TABLE session_history_metadata ADD COLUMN tagline TEXT' 'ALTER TABLE session_history_metadata ADD COLUMN tagline TEXT'
) )
@ -1284,7 +1283,7 @@ def dbcheck():
try: try:
c_db.execute('SELECT section_id FROM session_history_metadata') c_db.execute('SELECT section_id FROM session_history_metadata')
except sqlite3.OperationalError: except sqlite3.OperationalError:
logger.debug(u"Altering database. Updating database table session_history_metadata.") logger.debug("Altering database. Updating database table session_history_metadata.")
c_db.execute( c_db.execute(
'ALTER TABLE session_history_metadata ADD COLUMN section_id INTEGER' 'ALTER TABLE session_history_metadata ADD COLUMN section_id INTEGER'
) )
@ -1293,7 +1292,7 @@ def dbcheck():
try: try:
c_db.execute('SELECT labels FROM session_history_metadata') c_db.execute('SELECT labels FROM session_history_metadata')
except sqlite3.OperationalError: except sqlite3.OperationalError:
logger.debug(u"Altering database. Updating database table session_history_metadata.") logger.debug("Altering database. Updating database table session_history_metadata.")
c_db.execute( c_db.execute(
'ALTER TABLE session_history_metadata ADD COLUMN labels TEXT' 'ALTER TABLE session_history_metadata ADD COLUMN labels TEXT'
) )
@ -1302,7 +1301,7 @@ def dbcheck():
try: try:
c_db.execute('SELECT original_title FROM session_history_metadata') c_db.execute('SELECT original_title FROM session_history_metadata')
except sqlite3.OperationalError: except sqlite3.OperationalError:
logger.debug(u"Altering database. Updating database table session_history_metadata.") logger.debug("Altering database. Updating database table session_history_metadata.")
c_db.execute( c_db.execute(
'ALTER TABLE session_history_metadata ADD COLUMN original_title TEXT' 'ALTER TABLE session_history_metadata ADD COLUMN original_title TEXT'
) )
@ -1311,7 +1310,7 @@ def dbcheck():
try: try:
c_db.execute('SELECT transcode_decision FROM session_history_media_info') c_db.execute('SELECT transcode_decision FROM session_history_media_info')
except sqlite3.OperationalError: except sqlite3.OperationalError:
logger.debug(u"Altering database. Updating database table session_history_media_info.") logger.debug("Altering database. Updating database table session_history_media_info.")
c_db.execute( c_db.execute(
'ALTER TABLE session_history_media_info ADD COLUMN transcode_decision TEXT' 'ALTER TABLE session_history_media_info ADD COLUMN transcode_decision TEXT'
) )
@ -1326,7 +1325,7 @@ def dbcheck():
try: try:
c_db.execute('SELECT subtitles FROM session_history_media_info') c_db.execute('SELECT subtitles FROM session_history_media_info')
except sqlite3.OperationalError: except sqlite3.OperationalError:
logger.debug(u"Altering database. Updating database table session_history_media_info.") logger.debug("Altering database. Updating database table session_history_media_info.")
c_db.execute( c_db.execute(
'ALTER TABLE session_history_media_info ADD COLUMN video_bit_depth INTEGER' 'ALTER TABLE session_history_media_info ADD COLUMN video_bit_depth INTEGER'
) )
@ -1446,7 +1445,7 @@ def dbcheck():
try: try:
c_db.execute('SELECT subtitle_codec FROM session_history_media_info') c_db.execute('SELECT subtitle_codec FROM session_history_media_info')
except sqlite3.OperationalError: except sqlite3.OperationalError:
logger.debug(u"Altering database. Updating database table session_history_media_info.") logger.debug("Altering database. Updating database table session_history_media_info.")
c_db.execute( c_db.execute(
'ALTER TABLE session_history_media_info ADD COLUMN subtitle_codec TEXT ' 'ALTER TABLE session_history_media_info ADD COLUMN subtitle_codec TEXT '
) )
@ -1455,7 +1454,7 @@ def dbcheck():
try: try:
c_db.execute('SELECT synced_version_profile FROM session_history_media_info') c_db.execute('SELECT synced_version_profile FROM session_history_media_info')
except sqlite3.OperationalError: except sqlite3.OperationalError:
logger.debug(u"Altering database. Updating database table session_history_media_info.") logger.debug("Altering database. Updating database table session_history_media_info.")
c_db.execute( c_db.execute(
'ALTER TABLE session_history_media_info ADD COLUMN synced_version_profile TEXT ' 'ALTER TABLE session_history_media_info ADD COLUMN synced_version_profile TEXT '
) )
@ -1467,7 +1466,7 @@ def dbcheck():
try: try:
c_db.execute('SELECT transcode_hw_decoding FROM session_history_media_info') c_db.execute('SELECT transcode_hw_decoding FROM session_history_media_info')
except sqlite3.OperationalError: except sqlite3.OperationalError:
logger.debug(u"Altering database. Updating database table session_history_media_info.") logger.debug("Altering database. Updating database table session_history_media_info.")
c_db.execute( c_db.execute(
'ALTER TABLE session_history_media_info ADD COLUMN transcode_hw_decoding INTEGER ' 'ALTER TABLE session_history_media_info ADD COLUMN transcode_hw_decoding INTEGER '
) )
@ -1483,7 +1482,7 @@ def dbcheck():
result = c_db.execute('SELECT stream_container FROM session_history_media_info ' result = c_db.execute('SELECT stream_container FROM session_history_media_info '
'WHERE stream_container IS NULL').fetchall() 'WHERE stream_container IS NULL').fetchall()
if len(result) > 0: if len(result) > 0:
logger.debug(u"Altering database. Removing NULL values from session_history_media_info table.") logger.debug("Altering database. Removing NULL values from session_history_media_info table.")
c_db.execute( c_db.execute(
'UPDATE session_history_media_info SET stream_container = "" WHERE stream_container IS NULL ' 'UPDATE session_history_media_info SET stream_container = "" WHERE stream_container IS NULL '
) )
@ -1497,13 +1496,13 @@ def dbcheck():
'UPDATE session_history_media_info SET stream_subtitle_codec = "" WHERE stream_subtitle_codec IS NULL ' 'UPDATE session_history_media_info SET stream_subtitle_codec = "" WHERE stream_subtitle_codec IS NULL '
) )
except sqlite3.OperationalError: except sqlite3.OperationalError:
logger.warn(u"Unable to remove NULL values from session_history_media_info table.") logger.warn("Unable to remove NULL values from session_history_media_info table.")
# Upgrade session_history_media_info table from earlier versions # Upgrade session_history_media_info table from earlier versions
try: try:
c_db.execute('SELECT video_scan_type FROM session_history_media_info') c_db.execute('SELECT video_scan_type FROM session_history_media_info')
except sqlite3.OperationalError: except sqlite3.OperationalError:
logger.debug(u"Altering database. Updating database table session_history_media_info.") logger.debug("Altering database. Updating database table session_history_media_info.")
c_db.execute( c_db.execute(
'ALTER TABLE session_history_media_info ADD COLUMN video_scan_type TEXT' 'ALTER TABLE session_history_media_info ADD COLUMN video_scan_type TEXT'
) )
@ -1542,7 +1541,7 @@ def dbcheck():
try: try:
c_db.execute('SELECT do_notify FROM users') c_db.execute('SELECT do_notify FROM users')
except sqlite3.OperationalError: except sqlite3.OperationalError:
logger.debug(u"Altering database. Updating database table users.") logger.debug("Altering database. Updating database table users.")
c_db.execute( c_db.execute(
'ALTER TABLE users ADD COLUMN do_notify INTEGER DEFAULT 1' 'ALTER TABLE users ADD COLUMN do_notify INTEGER DEFAULT 1'
) )
@ -1551,7 +1550,7 @@ def dbcheck():
try: try:
c_db.execute('SELECT keep_history FROM users') c_db.execute('SELECT keep_history FROM users')
except sqlite3.OperationalError: except sqlite3.OperationalError:
logger.debug(u"Altering database. Updating database table users.") logger.debug("Altering database. Updating database table users.")
c_db.execute( c_db.execute(
'ALTER TABLE users ADD COLUMN keep_history INTEGER DEFAULT 1' 'ALTER TABLE users ADD COLUMN keep_history INTEGER DEFAULT 1'
) )
@ -1560,7 +1559,7 @@ def dbcheck():
try: try:
c_db.execute('SELECT custom_avatar_url FROM users') c_db.execute('SELECT custom_avatar_url FROM users')
except sqlite3.OperationalError: except sqlite3.OperationalError:
logger.debug(u"Altering database. Updating database table users.") logger.debug("Altering database. Updating database table users.")
c_db.execute( c_db.execute(
'ALTER TABLE users ADD COLUMN custom_avatar_url TEXT' 'ALTER TABLE users ADD COLUMN custom_avatar_url TEXT'
) )
@ -1569,7 +1568,7 @@ def dbcheck():
try: try:
c_db.execute('SELECT deleted_user FROM users') c_db.execute('SELECT deleted_user FROM users')
except sqlite3.OperationalError: except sqlite3.OperationalError:
logger.debug(u"Altering database. Updating database table users.") logger.debug("Altering database. Updating database table users.")
c_db.execute( c_db.execute(
'ALTER TABLE users ADD COLUMN deleted_user INTEGER DEFAULT 0' 'ALTER TABLE users ADD COLUMN deleted_user INTEGER DEFAULT 0'
) )
@ -1578,7 +1577,7 @@ def dbcheck():
try: try:
c_db.execute('SELECT allow_guest FROM users') c_db.execute('SELECT allow_guest FROM users')
except sqlite3.OperationalError: except sqlite3.OperationalError:
logger.debug(u"Altering database. Updating database table users.") logger.debug("Altering database. Updating database table users.")
c_db.execute( c_db.execute(
'ALTER TABLE users ADD COLUMN allow_guest INTEGER DEFAULT 0' 'ALTER TABLE users ADD COLUMN allow_guest INTEGER DEFAULT 0'
) )
@ -1593,7 +1592,7 @@ def dbcheck():
try: try:
c_db.execute('SELECT shared_libraries FROM users') c_db.execute('SELECT shared_libraries FROM users')
except sqlite3.OperationalError: except sqlite3.OperationalError:
logger.debug(u"Altering database. Updating database table users.") logger.debug("Altering database. Updating database table users.")
c_db.execute( c_db.execute(
'ALTER TABLE users ADD COLUMN shared_libraries TEXT' 'ALTER TABLE users ADD COLUMN shared_libraries TEXT'
) )
@ -1617,7 +1616,7 @@ def dbcheck():
try: try:
c_db.execute('SELECT is_admin FROM users') c_db.execute('SELECT is_admin FROM users')
except sqlite3.OperationalError: except sqlite3.OperationalError:
logger.debug(u"Altering database. Updating database table users.") logger.debug("Altering database. Updating database table users.")
c_db.execute( c_db.execute(
'ALTER TABLE users ADD COLUMN is_admin INTEGER DEFAULT 0' 'ALTER TABLE users ADD COLUMN is_admin INTEGER DEFAULT 0'
) )
@ -1626,7 +1625,7 @@ def dbcheck():
try: try:
c_db.execute('SELECT poster_url FROM notify_log') c_db.execute('SELECT poster_url FROM notify_log')
except sqlite3.OperationalError: except sqlite3.OperationalError:
logger.debug(u"Altering database. Updating database table notify_log.") logger.debug("Altering database. Updating database table notify_log.")
c_db.execute( c_db.execute(
'ALTER TABLE notify_log ADD COLUMN poster_url TEXT' 'ALTER TABLE notify_log ADD COLUMN poster_url TEXT'
) )
@ -1635,7 +1634,7 @@ def dbcheck():
try: try:
c_db.execute('SELECT timestamp FROM notify_log') c_db.execute('SELECT timestamp FROM notify_log')
except sqlite3.OperationalError: except sqlite3.OperationalError:
logger.debug(u"Altering database. Updating database table notify_log.") logger.debug("Altering database. Updating database table notify_log.")
c_db.execute( c_db.execute(
'CREATE TABLE IF NOT EXISTS notify_log_temp (id INTEGER PRIMARY KEY AUTOINCREMENT, timestamp INTEGER, ' 'CREATE TABLE IF NOT EXISTS notify_log_temp (id INTEGER PRIMARY KEY AUTOINCREMENT, timestamp INTEGER, '
'session_key INTEGER, rating_key INTEGER, parent_rating_key INTEGER, grandparent_rating_key INTEGER, ' 'session_key INTEGER, rating_key INTEGER, parent_rating_key INTEGER, grandparent_rating_key INTEGER, '
@ -1673,7 +1672,7 @@ def dbcheck():
try: try:
c_db.execute('SELECT notifier_id FROM notify_log') c_db.execute('SELECT notifier_id FROM notify_log')
except sqlite3.OperationalError: except sqlite3.OperationalError:
logger.debug(u"Altering database. Updating database table notify_log.") logger.debug("Altering database. Updating database table notify_log.")
c_db.execute( c_db.execute(
'ALTER TABLE notify_log ADD COLUMN notifier_id INTEGER' 'ALTER TABLE notify_log ADD COLUMN notifier_id INTEGER'
) )
@ -1682,7 +1681,7 @@ def dbcheck():
try: try:
c_db.execute('SELECT success FROM notify_log') c_db.execute('SELECT success FROM notify_log')
except sqlite3.OperationalError: except sqlite3.OperationalError:
logger.debug(u"Altering database. Updating database table notify_log.") logger.debug("Altering database. Updating database table notify_log.")
c_db.execute( c_db.execute(
'ALTER TABLE notify_log ADD COLUMN success INTEGER DEFAULT 0' 'ALTER TABLE notify_log ADD COLUMN success INTEGER DEFAULT 0'
) )
@ -1694,7 +1693,7 @@ def dbcheck():
try: try:
c_db.execute('SELECT start_time FROM newsletter_log') c_db.execute('SELECT start_time FROM newsletter_log')
except sqlite3.OperationalError: except sqlite3.OperationalError:
logger.debug(u"Altering database. Updating database table newsletter_log.") logger.debug("Altering database. Updating database table newsletter_log.")
c_db.execute( c_db.execute(
'ALTER TABLE newsletter_log ADD COLUMN start_time INTEGER' 'ALTER TABLE newsletter_log ADD COLUMN start_time INTEGER'
) )
@ -1706,7 +1705,7 @@ def dbcheck():
try: try:
c_db.execute('SELECT filename FROM newsletter_log') c_db.execute('SELECT filename FROM newsletter_log')
except sqlite3.OperationalError: except sqlite3.OperationalError:
logger.debug(u"Altering database. Updating database table newsletter_log.") logger.debug("Altering database. Updating database table newsletter_log.")
c_db.execute( c_db.execute(
'ALTER TABLE newsletter_log ADD COLUMN filename TEXT' 'ALTER TABLE newsletter_log ADD COLUMN filename TEXT'
) )
@ -1715,7 +1714,7 @@ def dbcheck():
try: try:
c_db.execute('SELECT email_msg_id FROM newsletter_log') c_db.execute('SELECT email_msg_id FROM newsletter_log')
except sqlite3.OperationalError: except sqlite3.OperationalError:
logger.debug(u"Altering database. Updating database table newsletter_log.") logger.debug("Altering database. Updating database table newsletter_log.")
c_db.execute( c_db.execute(
'ALTER TABLE newsletter_log ADD COLUMN email_msg_id TEXT' 'ALTER TABLE newsletter_log ADD COLUMN email_msg_id TEXT'
) )
@ -1724,7 +1723,7 @@ def dbcheck():
try: try:
c_db.execute('SELECT id_name FROM newsletters') c_db.execute('SELECT id_name FROM newsletters')
except sqlite3.OperationalError: except sqlite3.OperationalError:
logger.debug(u"Altering database. Updating database table newsletters.") logger.debug("Altering database. Updating database table newsletters.")
c_db.execute( c_db.execute(
'ALTER TABLE newsletters ADD COLUMN id_name TEXT NOT NULL DEFAULT ""' 'ALTER TABLE newsletters ADD COLUMN id_name TEXT NOT NULL DEFAULT ""'
) )
@ -1733,7 +1732,7 @@ def dbcheck():
try: try:
result = c_db.execute('SELECT SQL FROM sqlite_master WHERE type="table" AND name="library_sections"').fetchone() result = c_db.execute('SELECT SQL FROM sqlite_master WHERE type="table" AND name="library_sections"').fetchone()
if 'section_id INTEGER UNIQUE' in result[0]: if 'section_id INTEGER UNIQUE' in result[0]:
logger.debug(u"Altering database. Removing unique constraint on section_id from library_sections table.") logger.debug("Altering database. Removing unique constraint on section_id from library_sections table.")
c_db.execute( c_db.execute(
'CREATE TABLE library_sections_temp (id INTEGER PRIMARY KEY AUTOINCREMENT, ' 'CREATE TABLE library_sections_temp (id INTEGER PRIMARY KEY AUTOINCREMENT, '
'server_id TEXT, section_id INTEGER, section_name TEXT, section_type TEXT, ' 'server_id TEXT, section_id INTEGER, section_name TEXT, section_type TEXT, '
@ -1757,7 +1756,7 @@ def dbcheck():
'ALTER TABLE library_sections_temp RENAME TO library_sections' 'ALTER TABLE library_sections_temp RENAME TO library_sections'
) )
except sqlite3.OperationalError: except sqlite3.OperationalError:
logger.warn(u"Unable to remove section_id unique constraint from library_sections.") logger.warn("Unable to remove section_id unique constraint from library_sections.")
try: try:
c_db.execute( c_db.execute(
'DROP TABLE library_sections_temp' 'DROP TABLE library_sections_temp'
@ -1769,18 +1768,18 @@ def dbcheck():
try: try:
result = c_db.execute('SELECT * FROM library_sections WHERE server_id = ""').fetchall() result = c_db.execute('SELECT * FROM library_sections WHERE server_id = ""').fetchall()
if len(result) > 0: if len(result) > 0:
logger.debug(u"Altering database. Removing duplicate libraries from library_sections table.") logger.debug("Altering database. Removing duplicate libraries from library_sections table.")
c_db.execute( c_db.execute(
'DELETE FROM library_sections WHERE server_id = ""' 'DELETE FROM library_sections WHERE server_id = ""'
) )
except sqlite3.OperationalError: except sqlite3.OperationalError:
logger.warn(u"Unable to remove duplicate libraries from library_sections table.") logger.warn("Unable to remove duplicate libraries from library_sections table.")
# Upgrade library_sections table from earlier versions # Upgrade library_sections table from earlier versions
try: try:
c_db.execute('SELECT agent FROM library_sections') c_db.execute('SELECT agent FROM library_sections')
except sqlite3.OperationalError: except sqlite3.OperationalError:
logger.debug(u"Altering database. Updating database table library_sections.") logger.debug("Altering database. Updating database table library_sections.")
c_db.execute( c_db.execute(
'ALTER TABLE library_sections ADD COLUMN agent TEXT' 'ALTER TABLE library_sections ADD COLUMN agent TEXT'
) )
@ -1789,7 +1788,7 @@ def dbcheck():
try: try:
result = c_db.execute('SELECT SQL FROM sqlite_master WHERE type="table" AND name="users"').fetchone() result = c_db.execute('SELECT SQL FROM sqlite_master WHERE type="table" AND name="users"').fetchone()
if 'username TEXT NOT NULL UNIQUE' in result[0]: if 'username TEXT NOT NULL UNIQUE' in result[0]:
logger.debug(u"Altering database. Removing unique constraint on username from users table.") logger.debug("Altering database. Removing unique constraint on username from users table.")
c_db.execute( c_db.execute(
'CREATE TABLE users_temp (id INTEGER PRIMARY KEY AUTOINCREMENT, ' 'CREATE TABLE users_temp (id INTEGER PRIMARY KEY AUTOINCREMENT, '
'user_id INTEGER DEFAULT NULL UNIQUE, username TEXT NOT NULL, friendly_name TEXT, ' 'user_id INTEGER DEFAULT NULL UNIQUE, username TEXT NOT NULL, friendly_name TEXT, '
@ -1811,7 +1810,7 @@ def dbcheck():
'ALTER TABLE users_temp RENAME TO users' 'ALTER TABLE users_temp RENAME TO users'
) )
except sqlite3.OperationalError: except sqlite3.OperationalError:
logger.warn(u"Unable to remove username unique constraint from users.") logger.warn("Unable to remove username unique constraint from users.")
try: try:
c_db.execute( c_db.execute(
'DROP TABLE users_temp' 'DROP TABLE users_temp'
@ -1823,7 +1822,7 @@ def dbcheck():
try: try:
result = c_db.execute('SELECT SQL FROM sqlite_master WHERE type="table" AND name="mobile_devices"').fetchone() result = c_db.execute('SELECT SQL FROM sqlite_master WHERE type="table" AND name="mobile_devices"').fetchone()
if 'device_token TEXT NOT NULL UNIQUE' in result[0]: if 'device_token TEXT NOT NULL UNIQUE' in result[0]:
logger.debug(u"Altering database. Dropping and recreating mobile_devices table.") logger.debug("Altering database. Dropping and recreating mobile_devices table.")
c_db.execute( c_db.execute(
'DROP TABLE mobile_devices' 'DROP TABLE mobile_devices'
) )
@ -1832,14 +1831,14 @@ def dbcheck():
'device_id TEXT NOT NULL UNIQUE, device_token TEXT, device_name TEXT, friendly_name TEXT)' 'device_id TEXT NOT NULL UNIQUE, device_token TEXT, device_name TEXT, friendly_name TEXT)'
) )
except sqlite3.OperationalError: except sqlite3.OperationalError:
logger.warn(u"Failed to recreate mobile_devices table.") logger.warn("Failed to recreate mobile_devices table.")
pass pass
# Upgrade mobile_devices table from earlier versions # Upgrade mobile_devices table from earlier versions
try: try:
c_db.execute('SELECT last_seen FROM mobile_devices') c_db.execute('SELECT last_seen FROM mobile_devices')
except sqlite3.OperationalError: except sqlite3.OperationalError:
logger.debug(u"Altering database. Updating database table mobile_devices.") logger.debug("Altering database. Updating database table mobile_devices.")
c_db.execute( c_db.execute(
'ALTER TABLE mobile_devices ADD COLUMN last_seen INTEGER' 'ALTER TABLE mobile_devices ADD COLUMN last_seen INTEGER'
) )
@ -1848,7 +1847,7 @@ def dbcheck():
try: try:
c_db.execute('SELECT custom_conditions FROM notifiers') c_db.execute('SELECT custom_conditions FROM notifiers')
except sqlite3.OperationalError: except sqlite3.OperationalError:
logger.debug(u"Altering database. Updating database table notifiers.") logger.debug("Altering database. Updating database table notifiers.")
c_db.execute( c_db.execute(
'ALTER TABLE notifiers ADD COLUMN custom_conditions TEXT' 'ALTER TABLE notifiers ADD COLUMN custom_conditions TEXT'
) )
@ -1860,7 +1859,7 @@ def dbcheck():
try: try:
c_db.execute('SELECT on_change FROM notifiers') c_db.execute('SELECT on_change FROM notifiers')
except sqlite3.OperationalError: except sqlite3.OperationalError:
logger.debug(u"Altering database. Updating database table notifiers.") logger.debug("Altering database. Updating database table notifiers.")
c_db.execute( c_db.execute(
'ALTER TABLE notifiers ADD COLUMN on_change INTEGER DEFAULT 0' 'ALTER TABLE notifiers ADD COLUMN on_change INTEGER DEFAULT 0'
) )
@ -1875,7 +1874,7 @@ def dbcheck():
try: try:
c_db.execute('SELECT rating_key FROM tvmaze_lookup') c_db.execute('SELECT rating_key FROM tvmaze_lookup')
except sqlite3.OperationalError: except sqlite3.OperationalError:
logger.debug(u"Altering database. Updating database table tvmaze_lookup.") logger.debug("Altering database. Updating database table tvmaze_lookup.")
c_db.execute( c_db.execute(
'ALTER TABLE tvmaze_lookup ADD COLUMN rating_key INTEGER' 'ALTER TABLE tvmaze_lookup ADD COLUMN rating_key INTEGER'
) )
@ -1890,7 +1889,7 @@ def dbcheck():
try: try:
c_db.execute('SELECT rating_key FROM themoviedb_lookup') c_db.execute('SELECT rating_key FROM themoviedb_lookup')
except sqlite3.OperationalError: except sqlite3.OperationalError:
logger.debug(u"Altering database. Updating database table themoviedb_lookup.") logger.debug("Altering database. Updating database table themoviedb_lookup.")
c_db.execute( c_db.execute(
'ALTER TABLE themoviedb_lookup ADD COLUMN rating_key INTEGER' 'ALTER TABLE themoviedb_lookup ADD COLUMN rating_key INTEGER'
) )
@ -1905,7 +1904,7 @@ def dbcheck():
try: try:
c_db.execute('SELECT success FROM user_login') c_db.execute('SELECT success FROM user_login')
except sqlite3.OperationalError: except sqlite3.OperationalError:
logger.debug(u"Altering database. Updating database table user_login.") logger.debug("Altering database. Updating database table user_login.")
c_db.execute( c_db.execute(
'ALTER TABLE user_login ADD COLUMN success INTEGER DEFAULT 1' 'ALTER TABLE user_login ADD COLUMN success INTEGER DEFAULT 1'
) )
@ -1914,7 +1913,7 @@ def dbcheck():
result = c_db.execute('SELECT agent_label FROM notifiers ' result = c_db.execute('SELECT agent_label FROM notifiers '
'WHERE agent_label = "XBMC" OR agent_label = "OSX Notify"').fetchone() 'WHERE agent_label = "XBMC" OR agent_label = "OSX Notify"').fetchone()
if result: if result:
logger.debug(u"Altering database. Renaming notifiers.") logger.debug("Altering database. Renaming notifiers.")
c_db.execute( c_db.execute(
'UPDATE notifiers SET agent_label = "Kodi" WHERE agent_label = "XBMC"' 'UPDATE notifiers SET agent_label = "Kodi" WHERE agent_label = "XBMC"'
) )
@ -1925,7 +1924,7 @@ def dbcheck():
# Add "Local" user to database as default unauthenticated user. # Add "Local" user to database as default unauthenticated user.
result = c_db.execute('SELECT id FROM users WHERE username = "Local"') result = c_db.execute('SELECT id FROM users WHERE username = "Local"')
if not result.fetchone(): if not result.fetchone():
logger.debug(u"User 'Local' does not exist. Adding user.") logger.debug("User 'Local' does not exist. Adding user.")
c_db.execute('INSERT INTO users (user_id, username) VALUES (0, "Local")') c_db.execute('INSERT INTO users (user_id, username) VALUES (0, "Local")')
# Create table indices # Create table indices
@ -1948,7 +1947,7 @@ def dbcheck():
result = db.select('SELECT SQL FROM sqlite_master WHERE type="table" AND name="poster_urls"') result = db.select('SELECT SQL FROM sqlite_master WHERE type="table" AND name="poster_urls"')
if result: if result:
result = db.select('SELECT * FROM poster_urls') result = db.select('SELECT * FROM poster_urls')
logger.debug(u"Altering database. Updating database table imgur_lookup.") logger.debug("Altering database. Updating database table imgur_lookup.")
data_factory = datafactory.DataFactory() data_factory = datafactory.DataFactory()
@ -1990,31 +1989,31 @@ def shutdown(restart=False, update=False, checkout=False):
CONFIG.write() CONFIG.write()
if not restart and not update and not checkout: if not restart and not update and not checkout:
logger.info(u"Tautulli is shutting down...") logger.info("Tautulli is shutting down...")
if update: if update:
logger.info(u"Tautulli is updating...") logger.info("Tautulli is updating...")
try: try:
versioncheck.update() versioncheck.update()
except Exception as e: except Exception as e:
logger.warn(u"Tautulli failed to update: %s. Restarting." % e) logger.warn("Tautulli failed to update: %s. Restarting." % e)
if checkout: if checkout:
logger.info(u"Tautulli is switching the git branch...") logger.info("Tautulli is switching the git branch...")
try: try:
versioncheck.checkout_git_branch() versioncheck.checkout_git_branch()
except Exception as e: except Exception as e:
logger.warn(u"Tautulli failed to switch git branch: %s. Restarting." % e) logger.warn("Tautulli failed to switch git branch: %s. Restarting." % e)
if CREATEPID: if CREATEPID:
logger.info(u"Removing pidfile %s", PIDFILE) logger.info("Removing pidfile %s", PIDFILE)
os.remove(PIDFILE) os.remove(PIDFILE)
if WIN_SYS_TRAY_ICON: if WIN_SYS_TRAY_ICON:
WIN_SYS_TRAY_ICON.shutdown() WIN_SYS_TRAY_ICON.shutdown()
if restart: if restart:
logger.info(u"Tautulli is restarting...") logger.info("Tautulli is restarting...")
exe = sys.executable exe = sys.executable
args = [exe, FULL_PATH] args = [exe, FULL_PATH]
@ -2088,7 +2087,7 @@ def analytics_event(category, action, label=None, value=None, **kwargs):
try: try:
TRACKER.send('event', data) TRACKER.send('event', data)
except Exception as e: except Exception as e:
logger.warn(u"Failed to send analytics event for category '%s', action '%s': %s" % (category, action, e)) logger.warn("Failed to send analytics event for category '%s', action '%s': %s" % (category, action, e))
def check_folder_writable(folder, fallback, name): def check_folder_writable(folder, fallback, name):
@ -2099,17 +2098,17 @@ def check_folder_writable(folder, fallback, name):
try: try:
os.makedirs(folder) os.makedirs(folder)
except OSError as e: except OSError as e:
logger.error(u"Could not create %s dir '%s': %s" % (name, folder, e)) logger.error("Could not create %s dir '%s': %s" % (name, folder, e))
if folder != fallback: if folder != fallback:
logger.warn(u"Falling back to %s dir '%s'" % (name, fallback)) logger.warn("Falling back to %s dir '%s'" % (name, fallback))
return check_folder_writable(None, fallback, name) return check_folder_writable(None, fallback, name)
else: else:
return folder, None return folder, None
if not os.access(folder, os.W_OK): if not os.access(folder, os.W_OK):
logger.error(u"Cannot write to %s dir '%s'" % (name, folder)) logger.error("Cannot write to %s dir '%s'" % (name, folder))
if folder != fallback: if folder != fallback:
logger.warn(u"Falling back to %s dir '%s'" % (name, fallback)) logger.warn("Falling back to %s dir '%s'" % (name, fallback))
return check_folder_writable(None, fallback, name) return check_folder_writable(None, fallback, name)
else: else:
return folder, False return folder, False

View file

@ -107,7 +107,7 @@ class ActivityHandler(object):
if not session: if not session:
return return
logger.debug(u"Tautulli ActivityHandler :: Session %s started by user %s (%s) with ratingKey %s (%s)." logger.debug("Tautulli ActivityHandler :: Session %s started by user %s (%s) with ratingKey %s (%s)."
% (str(session['session_key']), str(session['user_id']), session['username'], % (str(session['session_key']), str(session['user_id']), session['username'],
str(session['rating_key']), session['full_title'])) str(session['rating_key']), session['full_title']))
@ -124,7 +124,7 @@ class ActivityHandler(object):
def on_stop(self, force_stop=False): def on_stop(self, force_stop=False):
if self.is_valid_session(): if self.is_valid_session():
logger.debug(u"Tautulli ActivityHandler :: Session %s %sstopped." logger.debug("Tautulli ActivityHandler :: Session %s %sstopped."
% (str(self.get_session_key()), 'force ' if force_stop else '')) % (str(self.get_session_key()), 'force ' if force_stop else ''))
# Set the session last_paused timestamp # Set the session last_paused timestamp
@ -149,7 +149,7 @@ class ActivityHandler(object):
schedule_callback('session_key-{}'.format(self.get_session_key()), remove_job=True) schedule_callback('session_key-{}'.format(self.get_session_key()), remove_job=True)
# Remove the session from our temp session table # Remove the session from our temp session table
logger.debug(u"Tautulli ActivityHandler :: Removing sessionKey %s ratingKey %s from session queue" logger.debug("Tautulli ActivityHandler :: Removing sessionKey %s ratingKey %s from session queue"
% (str(self.get_session_key()), str(self.get_rating_key()))) % (str(self.get_session_key()), str(self.get_rating_key())))
ap.delete_session(row_id=row_id) ap.delete_session(row_id=row_id)
delete_metadata_cache(self.get_session_key()) delete_metadata_cache(self.get_session_key())
@ -162,7 +162,7 @@ class ActivityHandler(object):
def on_pause(self, still_paused=False): def on_pause(self, still_paused=False):
if self.is_valid_session(): if self.is_valid_session():
if not still_paused: if not still_paused:
logger.debug(u"Tautulli ActivityHandler :: Session %s paused." % str(self.get_session_key())) logger.debug("Tautulli ActivityHandler :: Session %s paused." % str(self.get_session_key()))
# Set the session last_paused timestamp # Set the session last_paused timestamp
ap = activity_processor.ActivityProcessor() ap = activity_processor.ActivityProcessor()
@ -179,7 +179,7 @@ class ActivityHandler(object):
def on_resume(self): def on_resume(self):
if self.is_valid_session(): if self.is_valid_session():
logger.debug(u"Tautulli ActivityHandler :: Session %s resumed." % str(self.get_session_key())) logger.debug("Tautulli ActivityHandler :: Session %s resumed." % str(self.get_session_key()))
# Set the session last_paused timestamp # Set the session last_paused timestamp
ap = activity_processor.ActivityProcessor() ap = activity_processor.ActivityProcessor()
@ -195,7 +195,7 @@ class ActivityHandler(object):
def on_change(self): def on_change(self):
if self.is_valid_session(): if self.is_valid_session():
logger.debug(u"Tautulli ActivityHandler :: Session %s has changed transcode decision." % str(self.get_session_key())) logger.debug("Tautulli ActivityHandler :: Session %s has changed transcode decision." % str(self.get_session_key()))
# Update the session state and viewOffset # Update the session state and viewOffset
self.update_db_session() self.update_db_session()
@ -208,7 +208,7 @@ class ActivityHandler(object):
def on_buffer(self): def on_buffer(self):
if self.is_valid_session(): if self.is_valid_session():
logger.debug(u"Tautulli ActivityHandler :: Session %s is buffering." % self.get_session_key()) logger.debug("Tautulli ActivityHandler :: Session %s is buffering." % self.get_session_key())
ap = activity_processor.ActivityProcessor() ap = activity_processor.ActivityProcessor()
db_stream = ap.get_session_by_key(session_key=self.get_session_key()) db_stream = ap.get_session_by_key(session_key=self.get_session_key())
@ -217,7 +217,7 @@ class ActivityHandler(object):
# Get our current buffer count # Get our current buffer count
current_buffer_count = ap.get_session_buffer_count(self.get_session_key()) current_buffer_count = ap.get_session_buffer_count(self.get_session_key())
logger.debug(u"Tautulli ActivityHandler :: Session %s buffer count is %s." % logger.debug("Tautulli ActivityHandler :: Session %s buffer count is %s." %
(self.get_session_key(), current_buffer_count)) (self.get_session_key(), current_buffer_count))
# Get our last triggered time # Get our last triggered time
@ -228,7 +228,7 @@ class ActivityHandler(object):
time_since_last_trigger = None time_since_last_trigger = None
if buffer_last_triggered: if buffer_last_triggered:
logger.debug(u"Tautulli ActivityHandler :: Session %s buffer last triggered at %s." % logger.debug("Tautulli ActivityHandler :: Session %s buffer last triggered at %s." %
(self.get_session_key(), buffer_last_triggered)) (self.get_session_key(), buffer_last_triggered))
time_since_last_trigger = int(time.time()) - int(buffer_last_triggered) time_since_last_trigger = int(time.time()) - int(buffer_last_triggered)
@ -318,7 +318,7 @@ class ActivityHandler(object):
} }
if progress_percent >= watched_percent.get(db_session['media_type'], 101): if progress_percent >= watched_percent.get(db_session['media_type'], 101):
logger.debug(u"Tautulli ActivityHandler :: Session %s watched." logger.debug("Tautulli ActivityHandler :: Session %s watched."
% str(self.get_session_key())) % str(self.get_session_key()))
ap.set_watched(session_key=self.get_session_key()) ap.set_watched(session_key=self.get_session_key())
@ -413,7 +413,7 @@ class TimelineHandler(object):
RECENTLY_ADDED_QUEUE[rating_key] = set([grandparent_rating_key]) RECENTLY_ADDED_QUEUE[rating_key] = set([grandparent_rating_key])
logger.debug(u"Tautulli TimelineHandler :: Library item '%s' (%s, grandparent %s) added to recently added queue." logger.debug("Tautulli TimelineHandler :: Library item '%s' (%s, grandparent %s) added to recently added queue."
% (title, str(rating_key), str(grandparent_rating_key))) % (title, str(rating_key), str(grandparent_rating_key)))
# Schedule a callback to clear the recently added queue # Schedule a callback to clear the recently added queue
@ -432,7 +432,7 @@ class TimelineHandler(object):
parent_set.add(rating_key) parent_set.add(rating_key)
RECENTLY_ADDED_QUEUE[parent_rating_key] = parent_set RECENTLY_ADDED_QUEUE[parent_rating_key] = parent_set
logger.debug(u"Tautulli TimelineHandler :: Library item '%s' (%s , parent %s) added to recently added queue." logger.debug("Tautulli TimelineHandler :: Library item '%s' (%s , parent %s) added to recently added queue."
% (title, str(rating_key), str(parent_rating_key))) % (title, str(rating_key), str(parent_rating_key)))
# Schedule a callback to clear the recently added queue # Schedule a callback to clear the recently added queue
@ -445,7 +445,7 @@ class TimelineHandler(object):
queue_set = RECENTLY_ADDED_QUEUE.get(rating_key, set()) queue_set = RECENTLY_ADDED_QUEUE.get(rating_key, set())
RECENTLY_ADDED_QUEUE[rating_key] = queue_set RECENTLY_ADDED_QUEUE[rating_key] = queue_set
logger.debug(u"Tautulli TimelineHandler :: Library item '%s' (%s) added to recently added queue." logger.debug("Tautulli TimelineHandler :: Library item '%s' (%s) added to recently added queue."
% (title, str(rating_key))) % (title, str(rating_key)))
# Schedule a callback to clear the recently added queue # Schedule a callback to clear the recently added queue
@ -459,13 +459,13 @@ class TimelineHandler(object):
state_type == 5 and metadata_state is None and queue_size is None and \ state_type == 5 and metadata_state is None and queue_size is None and \
rating_key in RECENTLY_ADDED_QUEUE: rating_key in RECENTLY_ADDED_QUEUE:
logger.debug(u"Tautulli TimelineHandler :: Library item '%s' (%s) done processing metadata." logger.debug("Tautulli TimelineHandler :: Library item '%s' (%s) done processing metadata."
% (title, str(rating_key))) % (title, str(rating_key)))
# An item was deleted, make sure it is removed from the queue # An item was deleted, make sure it is removed from the queue
elif state_type == 9 and metadata_state == 'deleted': elif state_type == 9 and metadata_state == 'deleted':
if rating_key in RECENTLY_ADDED_QUEUE and not RECENTLY_ADDED_QUEUE[rating_key]: if rating_key in RECENTLY_ADDED_QUEUE and not RECENTLY_ADDED_QUEUE[rating_key]:
logger.debug(u"Tautulli TimelineHandler :: Library item %s removed from recently added queue." logger.debug("Tautulli TimelineHandler :: Library item %s removed from recently added queue."
% str(rating_key)) % str(rating_key))
del_keys(rating_key) del_keys(rating_key)
@ -505,7 +505,7 @@ def force_stop_stream(session_key, title, user):
if row_id: if row_id:
# If session is written to the database successfully, remove the session from the session table # If session is written to the database successfully, remove the session from the session table
logger.info(u"Tautulli ActivityHandler :: Removing stale stream with sessionKey %s ratingKey %s from session queue" logger.info("Tautulli ActivityHandler :: Removing stale stream with sessionKey %s ratingKey %s from session queue"
% (session['session_key'], session['rating_key'])) % (session['session_key'], session['rating_key']))
ap.delete_session(row_id=row_id) ap.delete_session(row_id=row_id)
delete_metadata_cache(session_key) delete_metadata_cache(session_key)
@ -514,7 +514,7 @@ def force_stop_stream(session_key, title, user):
session['write_attempts'] += 1 session['write_attempts'] += 1
if session['write_attempts'] < plexpy.CONFIG.SESSION_DB_WRITE_ATTEMPTS: if session['write_attempts'] < plexpy.CONFIG.SESSION_DB_WRITE_ATTEMPTS:
logger.warn(u"Tautulli ActivityHandler :: Failed to write stream with sessionKey %s ratingKey %s to the database. " \ logger.warn("Tautulli ActivityHandler :: Failed to write stream with sessionKey %s ratingKey %s to the database. " \
"Will try again in 30 seconds. Write attempt %s." "Will try again in 30 seconds. Write attempt %s."
% (session['session_key'], session['rating_key'], str(session['write_attempts']))) % (session['session_key'], session['rating_key'], str(session['write_attempts'])))
ap.increment_write_attempts(session_key=session_key) ap.increment_write_attempts(session_key=session_key)
@ -524,10 +524,10 @@ def force_stop_stream(session_key, title, user):
args=[session_key, session['full_title'], session['user']], seconds=30) args=[session_key, session['full_title'], session['user']], seconds=30)
else: else:
logger.warn(u"Tautulli ActivityHandler :: Failed to write stream with sessionKey %s ratingKey %s to the database. " \ logger.warn("Tautulli ActivityHandler :: Failed to write stream with sessionKey %s ratingKey %s to the database. " \
"Removing session from the database. Write attempt %s." "Removing session from the database. Write attempt %s."
% (session['session_key'], session['rating_key'], str(session['write_attempts']))) % (session['session_key'], session['rating_key'], str(session['write_attempts'])))
logger.info(u"Tautulli ActivityHandler :: Removing stale stream with sessionKey %s ratingKey %s from session queue" logger.info("Tautulli ActivityHandler :: Removing stale stream with sessionKey %s ratingKey %s from session queue"
% (session['session_key'], session['rating_key'])) % (session['session_key'], session['rating_key']))
ap.delete_session(session_key=session_key) ap.delete_session(session_key=session_key)
delete_metadata_cache(session_key) delete_metadata_cache(session_key)
@ -561,7 +561,7 @@ def clear_recently_added_queue(rating_key, title):
def on_created(rating_key, **kwargs): def on_created(rating_key, **kwargs):
logger.debug(u"Tautulli TimelineHandler :: Library item %s added to Plex." % str(rating_key)) logger.debug("Tautulli TimelineHandler :: Library item %s added to Plex." % str(rating_key))
pms_connect = pmsconnect.PmsConnect() pms_connect = pmsconnect.PmsConnect()
metadata = pms_connect.get_metadata_details(rating_key) metadata = pms_connect.get_metadata_details(rating_key)
@ -570,14 +570,14 @@ def on_created(rating_key, **kwargs):
# now = int(time.time()) # now = int(time.time())
# #
# if helpers.cast_to_int(metadata['added_at']) < now - 86400: # Updated more than 24 hours ago # if helpers.cast_to_int(metadata['added_at']) < now - 86400: # Updated more than 24 hours ago
# logger.debug(u"Tautulli TimelineHandler :: Library item %s added more than 24 hours ago. Not notifying." # logger.debug("Tautulli TimelineHandler :: Library item %s added more than 24 hours ago. Not notifying."
# % str(rating_key)) # % str(rating_key))
# notify = False # notify = False
data_factory = datafactory.DataFactory() data_factory = datafactory.DataFactory()
if 'child_keys' not in kwargs: if 'child_keys' not in kwargs:
if data_factory.get_recently_added_item(rating_key): if data_factory.get_recently_added_item(rating_key):
logger.debug(u"Tautulli TimelineHandler :: Library item %s added already. Not notifying again." logger.debug("Tautulli TimelineHandler :: Library item %s added already. Not notifying again."
% str(rating_key)) % str(rating_key))
notify = False notify = False
@ -593,15 +593,15 @@ def on_created(rating_key, **kwargs):
for key in all_keys: for key in all_keys:
data_factory.set_recently_added_item(key) data_factory.set_recently_added_item(key)
logger.debug(u"Added %s items to the recently_added database table." % str(len(all_keys))) logger.debug("Added %s items to the recently_added database table." % str(len(all_keys)))
else: else:
logger.error(u"Tautulli TimelineHandler :: Unable to retrieve metadata for rating_key %s" % str(rating_key)) logger.error("Tautulli TimelineHandler :: Unable to retrieve metadata for rating_key %s" % str(rating_key))
def delete_metadata_cache(session_key): def delete_metadata_cache(session_key):
try: try:
os.remove(os.path.join(plexpy.CONFIG.CACHE_DIR, 'session_metadata/metadata-sessionKey-%s.json' % session_key)) os.remove(os.path.join(plexpy.CONFIG.CACHE_DIR, 'session_metadata/metadata-sessionKey-%s.json' % session_key))
except OSError as e: except OSError as e:
logger.error(u"Tautulli ActivityHandler :: Failed to remove metadata cache file (sessionKey %s): %s" logger.error("Tautulli ActivityHandler :: Failed to remove metadata cache file (sessionKey %s): %s"
% (session_key, e)) % (session_key, e))

View file

@ -48,7 +48,7 @@ def check_active_sessions(ws_request=False):
pms_connect = pmsconnect.PmsConnect() pms_connect = pmsconnect.PmsConnect()
session_list = pms_connect.get_current_activity() session_list = pms_connect.get_current_activity()
logger.debug(u"Tautulli Monitor :: Checking for active streams.") logger.debug("Tautulli Monitor :: Checking for active streams.")
if session_list: if session_list:
media_container = session_list['sessions'] media_container = session_list['sessions']
@ -65,12 +65,12 @@ def check_active_sessions(ws_request=False):
# Here we can check the play states # Here we can check the play states
if session['state'] != stream['state']: if session['state'] != stream['state']:
if session['state'] == 'paused': if session['state'] == 'paused':
logger.debug(u"Tautulli Monitor :: Session %s paused." % stream['session_key']) logger.debug("Tautulli Monitor :: Session %s paused." % stream['session_key'])
plexpy.NOTIFY_QUEUE.put({'stream_data': stream.copy(), 'notify_action': 'on_pause'}) plexpy.NOTIFY_QUEUE.put({'stream_data': stream.copy(), 'notify_action': 'on_pause'})
if session['state'] == 'playing' and stream['state'] == 'paused': if session['state'] == 'playing' and stream['state'] == 'paused':
logger.debug(u"Tautulli Monitor :: Session %s resumed." % stream['session_key']) logger.debug("Tautulli Monitor :: Session %s resumed." % stream['session_key'])
plexpy.NOTIFY_QUEUE.put({'stream_data': stream.copy(), 'notify_action': 'on_resume'}) plexpy.NOTIFY_QUEUE.put({'stream_data': stream.copy(), 'notify_action': 'on_resume'})
@ -102,7 +102,7 @@ def check_active_sessions(ws_request=False):
# Push it on it's own thread so we don't hold up our db actions # Push it on it's own thread so we don't hold up our db actions
# Our first buffer notification # Our first buffer notification
if buffer_values[0]['buffer_count'] == plexpy.CONFIG.BUFFER_THRESHOLD: if buffer_values[0]['buffer_count'] == plexpy.CONFIG.BUFFER_THRESHOLD:
logger.info(u"Tautulli Monitor :: User '%s' has triggered a buffer warning." logger.info("Tautulli Monitor :: User '%s' has triggered a buffer warning."
% stream['user']) % stream['user'])
# Set the buffer trigger time # Set the buffer trigger time
monitor_db.action('UPDATE sessions ' monitor_db.action('UPDATE sessions '
@ -116,7 +116,7 @@ def check_active_sessions(ws_request=False):
# Subsequent buffer notifications after wait time # Subsequent buffer notifications after wait time
if int(time.time()) > buffer_values[0]['buffer_last_triggered'] + \ if int(time.time()) > buffer_values[0]['buffer_last_triggered'] + \
plexpy.CONFIG.BUFFER_WAIT: plexpy.CONFIG.BUFFER_WAIT:
logger.info(u"Tautulli Monitor :: User '%s' has triggered multiple buffer warnings." logger.info("Tautulli Monitor :: User '%s' has triggered multiple buffer warnings."
% stream['user']) % stream['user'])
# Set the buffer trigger time # Set the buffer trigger time
monitor_db.action('UPDATE sessions ' monitor_db.action('UPDATE sessions '
@ -126,7 +126,7 @@ def check_active_sessions(ws_request=False):
plexpy.NOTIFY_QUEUE.put({'stream_data': stream.copy(), 'notify_action': 'on_buffer'}) plexpy.NOTIFY_QUEUE.put({'stream_data': stream.copy(), 'notify_action': 'on_buffer'})
logger.debug(u"Tautulli Monitor :: Session %s is buffering. Count is now %s. Last triggered %s." logger.debug("Tautulli Monitor :: Session %s is buffering. Count is now %s. Last triggered %s."
% (stream['session_key'], % (stream['session_key'],
buffer_values[0]['buffer_count'], buffer_values[0]['buffer_count'],
buffer_values[0]['buffer_last_triggered'])) buffer_values[0]['buffer_last_triggered']))
@ -146,7 +146,7 @@ def check_active_sessions(ws_request=False):
else: else:
# The user has stopped playing a stream # The user has stopped playing a stream
if stream['state'] != 'stopped': if stream['state'] != 'stopped':
logger.debug(u"Tautulli Monitor :: Session %s stopped." % stream['session_key']) logger.debug("Tautulli Monitor :: Session %s stopped." % stream['session_key'])
if not stream['stopped']: if not stream['stopped']:
# Set the stream stop time # Set the stream stop time
@ -170,22 +170,22 @@ def check_active_sessions(ws_request=False):
if row_id: if row_id:
# If session is written to the databaase successfully, remove the session from the session table # If session is written to the databaase successfully, remove the session from the session table
logger.debug(u"Tautulli Monitor :: Removing sessionKey %s ratingKey %s from session queue" logger.debug("Tautulli Monitor :: Removing sessionKey %s ratingKey %s from session queue"
% (stream['session_key'], stream['rating_key'])) % (stream['session_key'], stream['rating_key']))
monitor_process.delete_session(row_id=row_id) monitor_process.delete_session(row_id=row_id)
else: else:
stream['write_attempts'] += 1 stream['write_attempts'] += 1
if stream['write_attempts'] < plexpy.CONFIG.SESSION_DB_WRITE_ATTEMPTS: if stream['write_attempts'] < plexpy.CONFIG.SESSION_DB_WRITE_ATTEMPTS:
logger.warn(u"Tautulli Monitor :: Failed to write sessionKey %s ratingKey %s to the database. " \ logger.warn("Tautulli Monitor :: Failed to write sessionKey %s ratingKey %s to the database. " \
"Will try again on the next pass. Write attempt %s." "Will try again on the next pass. Write attempt %s."
% (stream['session_key'], stream['rating_key'], str(stream['write_attempts']))) % (stream['session_key'], stream['rating_key'], str(stream['write_attempts'])))
monitor_process.increment_write_attempts(session_key=stream['session_key']) monitor_process.increment_write_attempts(session_key=stream['session_key'])
else: else:
logger.warn(u"Tautulli Monitor :: Failed to write sessionKey %s ratingKey %s to the database. " \ logger.warn("Tautulli Monitor :: Failed to write sessionKey %s ratingKey %s to the database. " \
"Removing session from the database. Write attempt %s." "Removing session from the database. Write attempt %s."
% (stream['session_key'], stream['rating_key'], str(stream['write_attempts']))) % (stream['session_key'], stream['rating_key'], str(stream['write_attempts'])))
logger.debug(u"Tautulli Monitor :: Removing sessionKey %s ratingKey %s from session queue" logger.debug("Tautulli Monitor :: Removing sessionKey %s ratingKey %s from session queue"
% (stream['session_key'], stream['rating_key'])) % (stream['session_key'], stream['rating_key']))
monitor_process.delete_session(session_key=stream['session_key']) monitor_process.delete_session(session_key=stream['session_key'])
@ -194,11 +194,11 @@ def check_active_sessions(ws_request=False):
new_session = monitor_process.write_session(session) new_session = monitor_process.write_session(session)
if new_session: if new_session:
logger.debug(u"Tautulli Monitor :: Session %s started by user %s with ratingKey %s." logger.debug("Tautulli Monitor :: Session %s started by user %s with ratingKey %s."
% (session['session_key'], session['user_id'], session['rating_key'])) % (session['session_key'], session['user_id'], session['rating_key']))
else: else:
logger.debug(u"Tautulli Monitor :: Unable to read session list.") logger.debug("Tautulli Monitor :: Unable to read session list.")
def check_recently_added(): def check_recently_added():
@ -230,13 +230,13 @@ def check_recently_added():
if metadata: if metadata:
metadata = [metadata] metadata = [metadata]
else: else:
logger.error(u"Tautulli Monitor :: Unable to retrieve metadata for rating_key %s" \ logger.error("Tautulli Monitor :: Unable to retrieve metadata for rating_key %s" \
% str(item['rating_key'])) % str(item['rating_key']))
else: else:
metadata = pms_connect.get_metadata_children_details(item['rating_key']) metadata = pms_connect.get_metadata_children_details(item['rating_key'])
if not metadata: if not metadata:
logger.error(u"Tautulli Monitor :: Unable to retrieve children metadata for rating_key %s" \ logger.error("Tautulli Monitor :: Unable to retrieve children metadata for rating_key %s" \
% str(item['rating_key'])) % str(item['rating_key']))
if metadata: if metadata:
@ -247,7 +247,7 @@ def check_recently_added():
library_details = library_data.get_details(section_id=item['section_id']) library_details = library_data.get_details(section_id=item['section_id'])
if 0 < time_threshold - int(item['added_at']) <= time_interval: if 0 < time_threshold - int(item['added_at']) <= time_interval:
logger.debug(u"Tautulli Monitor :: Library item %s added to Plex." % str(item['rating_key'])) logger.debug("Tautulli Monitor :: Library item %s added to Plex." % str(item['rating_key']))
plexpy.NOTIFY_QUEUE.put({'timeline_data': item.copy(), 'notify_action': 'on_created'}) plexpy.NOTIFY_QUEUE.put({'timeline_data': item.copy(), 'notify_action': 'on_created'})
@ -261,10 +261,10 @@ def check_recently_added():
if metadata: if metadata:
item = metadata item = metadata
else: else:
logger.error(u"Tautulli Monitor :: Unable to retrieve grandparent metadata for grandparent_rating_key %s" \ logger.error("Tautulli Monitor :: Unable to retrieve grandparent metadata for grandparent_rating_key %s" \
% str(item['rating_key'])) % str(item['rating_key']))
logger.debug(u"Tautulli Monitor :: Library item %s added to Plex." % str(item['rating_key'])) logger.debug("Tautulli Monitor :: Library item %s added to Plex." % str(item['rating_key']))
# Check if any notification agents have notifications enabled # Check if any notification agents have notifications enabled
plexpy.NOTIFY_QUEUE.put({'timeline_data': item.copy(), 'notify_action': 'on_created'}) plexpy.NOTIFY_QUEUE.put({'timeline_data': item.copy(), 'notify_action': 'on_created'})
@ -273,19 +273,19 @@ def check_recently_added():
def connect_server(log=True, startup=False): def connect_server(log=True, startup=False):
if plexpy.CONFIG.PMS_IS_CLOUD: if plexpy.CONFIG.PMS_IS_CLOUD:
if log: if log:
logger.info(u"Tautulli Monitor :: Checking for Plex Cloud server status...") logger.info("Tautulli Monitor :: Checking for Plex Cloud server status...")
plex_tv = plextv.PlexTV() plex_tv = plextv.PlexTV()
status = plex_tv.get_cloud_server_status() status = plex_tv.get_cloud_server_status()
if status is True: if status is True:
logger.info(u"Tautulli Monitor :: Plex Cloud server is active.") logger.info("Tautulli Monitor :: Plex Cloud server is active.")
elif status is False: elif status is False:
if log: if log:
logger.info(u"Tautulli Monitor :: Plex Cloud server is sleeping.") logger.info("Tautulli Monitor :: Plex Cloud server is sleeping.")
else: else:
if log: if log:
logger.error(u"Tautulli Monitor :: Failed to retrieve Plex Cloud server status.") logger.error("Tautulli Monitor :: Failed to retrieve Plex Cloud server status.")
if not status and startup: if not status and startup:
web_socket.on_disconnect() web_socket.on_disconnect()
@ -295,12 +295,12 @@ def connect_server(log=True, startup=False):
if status: if status:
if log and not startup: if log and not startup:
logger.info(u"Tautulli Monitor :: Attempting to reconnect Plex server...") logger.info("Tautulli Monitor :: Attempting to reconnect Plex server...")
try: try:
web_socket.start_thread() web_socket.start_thread()
except Exception as e: except Exception as e:
logger.error(u"Websocket :: Unable to open connection: %s." % e) logger.error("Websocket :: Unable to open connection: %s." % e)
def check_server_access(): def check_server_access():
@ -319,17 +319,17 @@ def check_server_access():
# Check if the port is mapped # Check if the port is mapped
if not mapping_state == 'mapped': if not mapping_state == 'mapped':
ext_ping_count += 1 ext_ping_count += 1
logger.warn(u"Tautulli Monitor :: Plex remote access port not mapped, ping attempt %s." \ logger.warn("Tautulli Monitor :: Plex remote access port not mapped, ping attempt %s." \
% str(ext_ping_count)) % str(ext_ping_count))
# Check if the port is open # Check if the port is open
elif mapping_error == 'unreachable': elif mapping_error == 'unreachable':
ext_ping_count += 1 ext_ping_count += 1
logger.warn(u"Tautulli Monitor :: Plex remote access port mapped, but mapping failed, ping attempt %s." \ logger.warn("Tautulli Monitor :: Plex remote access port mapped, but mapping failed, ping attempt %s." \
% str(ext_ping_count)) % str(ext_ping_count))
# Reset external ping counter # Reset external ping counter
else: else:
if ext_ping_count >= plexpy.CONFIG.REMOTE_ACCESS_PING_THRESHOLD: if ext_ping_count >= plexpy.CONFIG.REMOTE_ACCESS_PING_THRESHOLD:
logger.info(u"Tautulli Monitor :: Plex remote access is back up.") logger.info("Tautulli Monitor :: Plex remote access is back up.")
plexpy.NOTIFY_QUEUE.put({'notify_action': 'on_extup'}) plexpy.NOTIFY_QUEUE.put({'notify_action': 'on_extup'})
@ -342,18 +342,18 @@ def check_server_access():
def check_server_updates(): def check_server_updates():
with monitor_lock: with monitor_lock:
logger.info(u"Tautulli Monitor :: Checking for PMS updates...") logger.info("Tautulli Monitor :: Checking for PMS updates...")
plex_tv = plextv.PlexTV() plex_tv = plextv.PlexTV()
download_info = plex_tv.get_plex_downloads() download_info = plex_tv.get_plex_downloads()
if download_info: if download_info:
logger.info(u"Tautulli Monitor :: Current PMS version: %s", plexpy.CONFIG.PMS_VERSION) logger.info("Tautulli Monitor :: Current PMS version: %s", plexpy.CONFIG.PMS_VERSION)
if download_info['update_available']: if download_info['update_available']:
logger.info(u"Tautulli Monitor :: PMS update available version: %s", download_info['version']) logger.info("Tautulli Monitor :: PMS update available version: %s", download_info['version'])
plexpy.NOTIFY_QUEUE.put({'notify_action': 'on_pmsupdate', 'pms_download_info': download_info}) plexpy.NOTIFY_QUEUE.put({'notify_action': 'on_pmsupdate', 'pms_download_info': download_info})
else: else:
logger.info(u"Tautulli Monitor :: No PMS update available.") logger.info("Tautulli Monitor :: No PMS update available.")

View file

@ -188,8 +188,8 @@ class ActivityProcessor(object):
if str(session['rating_key']).isdigit() and session['media_type'] in ('movie', 'episode', 'track'): if str(session['rating_key']).isdigit() and session['media_type'] in ('movie', 'episode', 'track'):
logging_enabled = True logging_enabled = True
else: else:
logger.debug(u"Tautulli ActivityProcessor :: Session %s ratingKey %s not logged. " logger.debug("Tautulli ActivityProcessor :: Session %s ratingKey %s not logged. "
u"Does not meet logging criteria. Media type is '%s'" % "Does not meet logging criteria. Media type is '%s'" %
(session['session_key'], session['rating_key'], session['media_type'])) (session['session_key'], session['rating_key'], session['media_type']))
return session['id'] return session['id']
@ -202,36 +202,36 @@ class ActivityProcessor(object):
if (session['media_type'] == 'movie' or session['media_type'] == 'episode') and \ if (session['media_type'] == 'movie' or session['media_type'] == 'episode') and \
(real_play_time < int(plexpy.CONFIG.LOGGING_IGNORE_INTERVAL)): (real_play_time < int(plexpy.CONFIG.LOGGING_IGNORE_INTERVAL)):
logging_enabled = False logging_enabled = False
logger.debug(u"Tautulli ActivityProcessor :: Play duration for session %s ratingKey %s is %s secs " logger.debug("Tautulli ActivityProcessor :: Play duration for session %s ratingKey %s is %s secs "
u"which is less than %s seconds, so we're not logging it." % "which is less than %s seconds, so we're not logging it." %
(session['session_key'], session['rating_key'], str(real_play_time), (session['session_key'], session['rating_key'], str(real_play_time),
plexpy.CONFIG.LOGGING_IGNORE_INTERVAL)) plexpy.CONFIG.LOGGING_IGNORE_INTERVAL))
if not is_import and session['media_type'] == 'track': if not is_import and session['media_type'] == 'track':
if real_play_time < 15 and session['duration'] >= 30: if real_play_time < 15 and session['duration'] >= 30:
logging_enabled = False logging_enabled = False
logger.debug(u"Tautulli ActivityProcessor :: Play duration for session %s ratingKey %s is %s secs, " logger.debug("Tautulli ActivityProcessor :: Play duration for session %s ratingKey %s is %s secs, "
u"looks like it was skipped so we're not logging it" % "looks like it was skipped so we're not logging it" %
(session['session_key'], session['rating_key'], str(real_play_time))) (session['session_key'], session['rating_key'], str(real_play_time)))
elif is_import and import_ignore_interval: elif is_import and import_ignore_interval:
if (session['media_type'] == 'movie' or session['media_type'] == 'episode') and \ if (session['media_type'] == 'movie' or session['media_type'] == 'episode') and \
(real_play_time < int(import_ignore_interval)): (real_play_time < int(import_ignore_interval)):
logging_enabled = False logging_enabled = False
logger.debug(u"Tautulli ActivityProcessor :: Play duration for ratingKey %s is %s secs which is less than %s " logger.debug("Tautulli ActivityProcessor :: Play duration for ratingKey %s is %s secs which is less than %s "
u"seconds, so we're not logging it." % "seconds, so we're not logging it." %
(session['rating_key'], str(real_play_time), import_ignore_interval)) (session['rating_key'], str(real_play_time), import_ignore_interval))
if not is_import and not user_details['keep_history']: if not is_import and not user_details['keep_history']:
logging_enabled = False logging_enabled = False
logger.debug(u"Tautulli ActivityProcessor :: History logging for user '%s' is disabled." % user_details['username']) logger.debug("Tautulli ActivityProcessor :: History logging for user '%s' is disabled." % user_details['username'])
elif not is_import and not library_details['keep_history']: elif not is_import and not library_details['keep_history']:
logging_enabled = False logging_enabled = False
logger.debug(u"Tautulli ActivityProcessor :: History logging for library '%s' is disabled." % library_details['section_name']) logger.debug("Tautulli ActivityProcessor :: History logging for library '%s' is disabled." % library_details['section_name'])
if logging_enabled: if logging_enabled:
# Fetch metadata first so we can return false if it fails # Fetch metadata first so we can return false if it fails
if not is_import: if not is_import:
logger.debug(u"Tautulli ActivityProcessor :: Fetching metadata for item ratingKey %s" % session['rating_key']) logger.debug("Tautulli ActivityProcessor :: Fetching metadata for item ratingKey %s" % session['rating_key'])
pms_connect = pmsconnect.PmsConnect() pms_connect = pmsconnect.PmsConnect()
metadata = pms_connect.get_metadata_details(rating_key=str(session['rating_key'])) metadata = pms_connect.get_metadata_details(rating_key=str(session['rating_key']))
if not metadata: if not metadata:
@ -245,7 +245,7 @@ class ActivityProcessor(object):
## TODO: Fix media info from imports. Temporary media info from import session. ## TODO: Fix media info from imports. Temporary media info from import session.
media_info = session media_info = session
# logger.debug(u"Tautulli ActivityProcessor :: Attempting to write sessionKey %s to session_history table..." # logger.debug("Tautulli ActivityProcessor :: Attempting to write sessionKey %s to session_history table..."
# % session['session_key']) # % session['session_key'])
keys = {'id': None} keys = {'id': None}
values = {'started': session['started'], values = {'started': session['started'],
@ -273,7 +273,7 @@ class ActivityProcessor(object):
'relayed': session['relayed'] 'relayed': session['relayed']
} }
# logger.debug(u"Tautulli ActivityProcessor :: Writing sessionKey %s session_history transaction..." # logger.debug("Tautulli ActivityProcessor :: Writing sessionKey %s session_history transaction..."
# % session['session_key']) # % session['session_key'])
self.db.upsert(table_name='session_history', key_dict=keys, value_dict=values) self.db.upsert(table_name='session_history', key_dict=keys, value_dict=values)
@ -326,12 +326,12 @@ class ActivityProcessor(object):
self.db.action(query=query, args=args) self.db.action(query=query, args=args)
# logger.debug(u"Tautulli ActivityProcessor :: Successfully written history item, last id for session_history is %s" # logger.debug("Tautulli ActivityProcessor :: Successfully written history item, last id for session_history is %s"
# % last_id) # % last_id)
# Write the session_history_media_info table # Write the session_history_media_info table
# logger.debug(u"Tautulli ActivityProcessor :: Attempting to write to sessionKey %s session_history_media_info table..." # logger.debug("Tautulli ActivityProcessor :: Attempting to write to sessionKey %s session_history_media_info table..."
# % session['session_key']) # % session['session_key'])
keys = {'id': last_id} keys = {'id': last_id}
values = {'rating_key': session['rating_key'], values = {'rating_key': session['rating_key'],
@ -403,7 +403,7 @@ class ActivityProcessor(object):
'optimized_version_title': session['optimized_version_title'] 'optimized_version_title': session['optimized_version_title']
} }
# logger.debug(u"Tautulli ActivityProcessor :: Writing sessionKey %s session_history_media_info transaction..." # logger.debug("Tautulli ActivityProcessor :: Writing sessionKey %s session_history_media_info transaction..."
# % session['session_key']) # % session['session_key'])
self.db.upsert(table_name='session_history_media_info', key_dict=keys, value_dict=values) self.db.upsert(table_name='session_history_media_info', key_dict=keys, value_dict=values)
@ -414,7 +414,7 @@ class ActivityProcessor(object):
genres = ";".join(metadata['genres']) genres = ";".join(metadata['genres'])
labels = ";".join(metadata['labels']) labels = ";".join(metadata['labels'])
# logger.debug(u"Tautulli ActivityProcessor :: Attempting to write to sessionKey %s session_history_metadata table..." # logger.debug("Tautulli ActivityProcessor :: Attempting to write to sessionKey %s session_history_metadata table..."
# % session['session_key']) # % session['session_key'])
keys = {'id': last_id} keys = {'id': last_id}
values = {'rating_key': session['rating_key'], values = {'rating_key': session['rating_key'],
@ -452,7 +452,7 @@ class ActivityProcessor(object):
'labels': labels 'labels': labels
} }
# logger.debug(u"Tautulli ActivityProcessor :: Writing sessionKey %s session_history_metadata transaction..." # logger.debug("Tautulli ActivityProcessor :: Writing sessionKey %s session_history_metadata transaction..."
# % session['session_key']) # % session['session_key'])
self.db.upsert(table_name='session_history_metadata', key_dict=keys, value_dict=values) self.db.upsert(table_name='session_history_metadata', key_dict=keys, value_dict=values)

View file

@ -142,9 +142,9 @@ class API2:
self._api_kwargs = kwargs self._api_kwargs = kwargs
if self._api_msg: if self._api_msg:
logger.api_debug(u'Tautulli APIv2 :: %s.' % self._api_msg) logger.api_debug('Tautulli APIv2 :: %s.' % self._api_msg)
logger.api_debug(u'Tautulli APIv2 :: Cleaned kwargs: %s' % self._api_kwargs) logger.api_debug('Tautulli APIv2 :: Cleaned kwargs: %s' % self._api_kwargs)
return self._api_kwargs return self._api_kwargs
@ -182,7 +182,7 @@ class API2:
end = int(end) end = int(end)
if regex: if regex:
logger.api_debug(u"Tautulli APIv2 :: Filtering log using regex '%s'" % regex) logger.api_debug("Tautulli APIv2 :: Filtering log using regex '%s'" % regex)
reg = re.compile(regex, flags=re.I) reg = re.compile(regex, flags=re.I)
with open(logfile, 'r') as f: with open(logfile, 'r') as f:
@ -218,15 +218,15 @@ class API2:
templog = templog[::-1] templog = templog[::-1]
if end > 0 or start > 0: if end > 0 or start > 0:
logger.api_debug(u"Tautulli APIv2 :: Slicing the log from %s to %s" % (start, end)) logger.api_debug("Tautulli APIv2 :: Slicing the log from %s to %s" % (start, end))
templog = templog[start:end] templog = templog[start:end]
if sort: if sort:
logger.api_debug(u"Tautulli APIv2 :: Sorting log based on '%s'" % sort) logger.api_debug("Tautulli APIv2 :: Sorting log based on '%s'" % sort)
templog = sorted(templog, key=lambda k: k[sort]) templog = sorted(templog, key=lambda k: k[sort])
if search: if search:
logger.api_debug(u"Tautulli APIv2 :: Searching log values for '%s'" % search) logger.api_debug("Tautulli APIv2 :: Searching log values for '%s'" % search)
tt = [d for d in templog for k, v in d.items() if search.lower() in v.lower()] tt = [d for d in templog for k, v in d.items() if search.lower() in v.lower()]
if len(tt): if len(tt):
@ -235,7 +235,7 @@ class API2:
if regex: if regex:
tt = [] tt = []
for l in templog: for l in templog:
stringdict = ' '.join(u'{}{}'.format(k, v) for k, v in l.items()) stringdict = ' '.join('{}{}'.format(k, v) for k, v in l.items())
if reg.search(stringdict): if reg.search(stringdict):
tt.append(l) tt.append(l)
@ -440,7 +440,7 @@ class API2:
self._api_result_type = 'error' self._api_result_type = 'error'
return return
logger.api_debug(u'Tautulli APIv2 :: Sending notification.') logger.api_debug('Tautulli APIv2 :: Sending notification.')
success = notification_handler.notify(notifier_id=notifier_id, success = notification_handler.notify(notifier_id=notifier_id,
notify_action='api', notify_action='api',
subject=subject, subject=subject,
@ -484,7 +484,7 @@ class API2:
self._api_result_type = 'error' self._api_result_type = 'error'
return return
logger.api_debug(u'Tautulli APIv2 :: Sending newsletter.') logger.api_debug('Tautulli APIv2 :: Sending newsletter.')
success = newsletter_handler.notify(newsletter_id=newsletter_id, success = newsletter_handler.notify(newsletter_id=newsletter_id,
notify_action='api', notify_action='api',
subject=subject, subject=subject,
@ -628,7 +628,7 @@ General optional parameters:
out = self._api_callback + '(' + out + ');' out = self._api_callback + '(' + out + ');'
# if we fail to generate the output fake an error # if we fail to generate the output fake an error
except Exception as e: except Exception as e:
logger.api_exception(u'Tautulli APIv2 :: ' + traceback.format_exc()) logger.api_exception('Tautulli APIv2 :: ' + traceback.format_exc())
self._api_response_code = 500 self._api_response_code = 500
out['message'] = traceback.format_exc() out['message'] = traceback.format_exc()
out['result'] = 'error' out['result'] = 'error'
@ -638,7 +638,7 @@ General optional parameters:
try: try:
out = xmltodict.unparse(out, pretty=True) out = xmltodict.unparse(out, pretty=True)
except Exception as e: except Exception as e:
logger.api_error(u'Tautulli APIv2 :: Failed to parse xml result') logger.api_error('Tautulli APIv2 :: Failed to parse xml result')
self._api_response_code = 500 self._api_response_code = 500
try: try:
out['message'] = e out['message'] = e
@ -646,7 +646,7 @@ General optional parameters:
out = xmltodict.unparse(out, pretty=True) out = xmltodict.unparse(out, pretty=True)
except Exception as e: except Exception as e:
logger.api_error(u'Tautulli APIv2 :: Failed to parse xml result error message %s' % e) logger.api_error('Tautulli APIv2 :: Failed to parse xml result error message %s' % e)
out = '''<?xml version="1.0" encoding="utf-8"?> out = '''<?xml version="1.0" encoding="utf-8"?>
<response> <response>
<message>%s</message> <message>%s</message>
@ -661,7 +661,7 @@ General optional parameters:
""" handles the stuff from the handler """ """ handles the stuff from the handler """
result = {} result = {}
logger.api_debug(u'Tautulli APIv2 :: API called with kwargs: %s' % kwargs) logger.api_debug('Tautulli APIv2 :: API called with kwargs: %s' % kwargs)
self._api_validate(**kwargs) self._api_validate(**kwargs)
@ -679,7 +679,7 @@ General optional parameters:
result = call(**self._api_kwargs) result = call(**self._api_kwargs)
except Exception as e: except Exception as e:
logger.api_error(u'Tautulli APIv2 :: Failed to run %s with %s: %s' % (self._api_cmd, self._api_kwargs, e)) logger.api_error('Tautulli APIv2 :: Failed to run %s with %s: %s' % (self._api_cmd, self._api_kwargs, e))
self._api_response_code = 500 self._api_response_code = 500
if self._api_debug: if self._api_debug:
cherrypy.request.show_tracebacks = True cherrypy.request.show_tracebacks = True

View file

@ -661,13 +661,13 @@ def make_backup(cleanup=False, scheduler=False):
try: try:
os.remove(file_) os.remove(file_)
except OSError as e: except OSError as e:
logger.error(u"Tautulli Config :: Failed to delete %s from the backup folder: %s" % (file_, e)) logger.error("Tautulli Config :: Failed to delete %s from the backup folder: %s" % (file_, e))
if backup_file in os.listdir(backup_folder): if backup_file in os.listdir(backup_folder):
logger.debug(u"Tautulli Config :: Successfully backed up %s to %s" % (plexpy.CONFIG_FILE, backup_file)) logger.debug("Tautulli Config :: Successfully backed up %s to %s" % (plexpy.CONFIG_FILE, backup_file))
return True return True
else: else:
logger.error(u"Tautulli Config :: Failed to backup %s to %s" % (plexpy.CONFIG_FILE, backup_file)) logger.error("Tautulli Config :: Failed to backup %s to %s" % (plexpy.CONFIG_FILE, backup_file))
return False return False
@ -748,12 +748,12 @@ class Config(object):
new_config[section][ini_key] = self._config[section][ini_key] new_config[section][ini_key] = self._config[section][ini_key]
# Write it to file # Write it to file
logger.info(u"Tautulli Config :: Writing configuration to file") logger.info("Tautulli Config :: Writing configuration to file")
try: try:
new_config.write() new_config.write()
except IOError as e: except IOError as e:
logger.error(u"Tautulli Config :: Error writing configuration file: %s", e) logger.error("Tautulli Config :: Error writing configuration file: %s", e)
self._blacklist() self._blacklist()

View file

@ -39,7 +39,7 @@ def drop_session_db():
def clear_history_tables(): def clear_history_tables():
logger.debug(u"Tautulli Database :: Deleting all session_history records... No turning back now bub.") logger.debug("Tautulli Database :: Deleting all session_history records... No turning back now bub.")
monitor_db = MonitorDatabase() monitor_db = MonitorDatabase()
monitor_db.action('DELETE FROM session_history') monitor_db.action('DELETE FROM session_history')
monitor_db.action('DELETE FROM session_history_media_info') monitor_db.action('DELETE FROM session_history_media_info')
@ -48,7 +48,7 @@ def clear_history_tables():
def delete_sessions(): def delete_sessions():
logger.debug(u"Tautulli Database :: Clearing temporary sessions from database.") logger.debug("Tautulli Database :: Clearing temporary sessions from database.")
monitor_db = MonitorDatabase() monitor_db = MonitorDatabase()
try: try:
@ -56,7 +56,7 @@ def delete_sessions():
monitor_db.action('VACUUM') monitor_db.action('VACUUM')
return True return True
except Exception as e: except Exception as e:
logger.warn(u"Tautulli Database :: Unable to clear temporary sessions from database: %s." % e) logger.warn("Tautulli Database :: Unable to clear temporary sessions from database: %s." % e)
return False return False
@ -103,13 +103,13 @@ def make_backup(cleanup=False, scheduler=False):
try: try:
os.remove(file_) os.remove(file_)
except OSError as e: except OSError as e:
logger.error(u"Tautulli Database :: Failed to delete %s from the backup folder: %s" % (file_, e)) logger.error("Tautulli Database :: Failed to delete %s from the backup folder: %s" % (file_, e))
if backup_file in os.listdir(backup_folder): if backup_file in os.listdir(backup_folder):
logger.debug(u"Tautulli Database :: Successfully backed up %s to %s" % (db_filename(), backup_file)) logger.debug("Tautulli Database :: Successfully backed up %s to %s" % (db_filename(), backup_file))
return True return True
else: else:
logger.error(u"Tautulli Database :: Failed to backup %s to %s" % (db_filename(), backup_file)) logger.error("Tautulli Database :: Failed to backup %s to %s" % (db_filename(), backup_file))
return False return False
@ -162,15 +162,15 @@ class MonitorDatabase(object):
except sqlite3.OperationalError as e: except sqlite3.OperationalError as e:
if "unable to open database file" in e or "database is locked" in e: if "unable to open database file" in e or "database is locked" in e:
logger.warn(u"Tautulli Database :: Database Error: %s", e) logger.warn("Tautulli Database :: Database Error: %s", e)
attempts += 1 attempts += 1
time.sleep(1) time.sleep(1)
else: else:
logger.error(u"Tautulli Database :: Database error: %s", e) logger.error("Tautulli Database :: Database error: %s", e)
raise raise
except sqlite3.DatabaseError as e: except sqlite3.DatabaseError as e:
logger.error(u"Tautulli Database :: Fatal Error executing %s :: %s", query, e) logger.error("Tautulli Database :: Fatal Error executing %s :: %s", query, e)
raise raise
return sql_result return sql_result
@ -214,7 +214,7 @@ class MonitorDatabase(object):
try: try:
self.action(insert_query, value_dict.values() + key_dict.values()) self.action(insert_query, value_dict.values() + key_dict.values())
except sqlite3.IntegrityError: except sqlite3.IntegrityError:
logger.info(u"Tautulli Database :: Queries failed: %s and %s", update_query, insert_query) logger.info("Tautulli Database :: Queries failed: %s and %s", update_query, insert_query)
# We want to know if it was an update or insert # We want to know if it was an update or insert
return trans_type return trans_type

View file

@ -176,7 +176,7 @@ class DataFactory(object):
['session_history.id', 'session_history_media_info.id']], ['session_history.id', 'session_history_media_info.id']],
kwargs=kwargs) kwargs=kwargs)
except Exception as e: except Exception as e:
logger.warn(u"Tautulli DataFactory :: Unable to execute database query for get_history: %s." % e) logger.warn("Tautulli DataFactory :: Unable to execute database query for get_history: %s." % e)
return {'recordsFiltered': 0, return {'recordsFiltered': 0,
'recordsTotal': 0, 'recordsTotal': 0,
'draw': 0, 'draw': 0,
@ -302,7 +302,7 @@ class DataFactory(object):
'LIMIT %s ' % (time_range, group_by, sort_type, stats_count) 'LIMIT %s ' % (time_range, group_by, sort_type, stats_count)
result = monitor_db.select(query) result = monitor_db.select(query)
except Exception as e: except Exception as e:
logger.warn(u"Tautulli DataFactory :: Unable to execute database query for get_home_stats: top_movies: %s." % e) logger.warn("Tautulli DataFactory :: Unable to execute database query for get_home_stats: top_movies: %s." % e)
return None return None
for item in result: for item in result:
@ -353,7 +353,7 @@ class DataFactory(object):
'LIMIT %s ' % (time_range, group_by, sort_type, stats_count) 'LIMIT %s ' % (time_range, group_by, sort_type, stats_count)
result = monitor_db.select(query) result = monitor_db.select(query)
except Exception as e: except Exception as e:
logger.warn(u"Tautulli DataFactory :: Unable to execute database query for get_home_stats: popular_movies: %s." % e) logger.warn("Tautulli DataFactory :: Unable to execute database query for get_home_stats: popular_movies: %s." % e)
return None return None
for item in result: for item in result:
@ -400,7 +400,7 @@ class DataFactory(object):
'LIMIT %s ' % (time_range, group_by, sort_type, stats_count) 'LIMIT %s ' % (time_range, group_by, sort_type, stats_count)
result = monitor_db.select(query) result = monitor_db.select(query)
except Exception as e: except Exception as e:
logger.warn(u"Tautulli DataFactory :: Unable to execute database query for get_home_stats: top_tv: %s." % e) logger.warn("Tautulli DataFactory :: Unable to execute database query for get_home_stats: top_tv: %s." % e)
return None return None
for item in result: for item in result:
@ -450,7 +450,7 @@ class DataFactory(object):
'LIMIT %s ' % (time_range, group_by, sort_type, stats_count) 'LIMIT %s ' % (time_range, group_by, sort_type, stats_count)
result = monitor_db.select(query) result = monitor_db.select(query)
except Exception as e: except Exception as e:
logger.warn(u"Tautulli DataFactory :: Unable to execute database query for get_home_stats: popular_tv: %s." % e) logger.warn("Tautulli DataFactory :: Unable to execute database query for get_home_stats: popular_tv: %s." % e)
return None return None
for item in result: for item in result:
@ -498,7 +498,7 @@ class DataFactory(object):
'LIMIT %s ' % (time_range, group_by, sort_type, stats_count) 'LIMIT %s ' % (time_range, group_by, sort_type, stats_count)
result = monitor_db.select(query) result = monitor_db.select(query)
except Exception as e: except Exception as e:
logger.warn(u"Tautulli DataFactory :: Unable to execute database query for get_home_stats: top_music: %s." % e) logger.warn("Tautulli DataFactory :: Unable to execute database query for get_home_stats: top_music: %s." % e)
return None return None
for item in result: for item in result:
@ -549,7 +549,7 @@ class DataFactory(object):
'LIMIT %s ' % (time_range, group_by, sort_type, stats_count) 'LIMIT %s ' % (time_range, group_by, sort_type, stats_count)
result = monitor_db.select(query) result = monitor_db.select(query)
except Exception as e: except Exception as e:
logger.warn(u"Tautulli DataFactory :: Unable to execute database query for get_home_stats: popular_music: %s." % e) logger.warn("Tautulli DataFactory :: Unable to execute database query for get_home_stats: popular_music: %s." % e)
return None return None
for item in result: for item in result:
@ -597,7 +597,7 @@ class DataFactory(object):
'LIMIT %s ' % (time_range, group_by, sort_type, stats_count) 'LIMIT %s ' % (time_range, group_by, sort_type, stats_count)
result = monitor_db.select(query) result = monitor_db.select(query)
except Exception as e: except Exception as e:
logger.warn(u"Tautulli DataFactory :: Unable to execute database query for get_home_stats: top_users: %s." % e) logger.warn("Tautulli DataFactory :: Unable to execute database query for get_home_stats: top_users: %s." % e)
return None return None
for item in result: for item in result:
@ -649,7 +649,7 @@ class DataFactory(object):
'LIMIT %s ' % (time_range, group_by, sort_type, stats_count) 'LIMIT %s ' % (time_range, group_by, sort_type, stats_count)
result = monitor_db.select(query) result = monitor_db.select(query)
except Exception as e: except Exception as e:
logger.warn(u"Tautulli DataFactory :: Unable to execute database query for get_home_stats: top_platforms: %s." % e) logger.warn("Tautulli DataFactory :: Unable to execute database query for get_home_stats: top_platforms: %s." % e)
return None return None
for item in result: for item in result:
@ -706,7 +706,7 @@ class DataFactory(object):
'LIMIT %s' % (time_range, group_by, movie_watched_percent, tv_watched_percent, stats_count) 'LIMIT %s' % (time_range, group_by, movie_watched_percent, tv_watched_percent, stats_count)
result = monitor_db.select(query) result = monitor_db.select(query)
except Exception as e: except Exception as e:
logger.warn(u"Tautulli DataFactory :: Unable to execute database query for get_home_stats: last_watched: %s." % e) logger.warn("Tautulli DataFactory :: Unable to execute database query for get_home_stats: last_watched: %s." % e)
return None return None
for item in result: for item in result:
@ -812,7 +812,7 @@ class DataFactory(object):
if result: if result:
most_concurrent.append(calc_most_concurrent(title, result)) most_concurrent.append(calc_most_concurrent(title, result))
except Exception as e: except Exception as e:
logger.warn(u"Tautulli DataFactory :: Unable to execute database query for get_home_stats: most_concurrent: %s." % e) logger.warn("Tautulli DataFactory :: Unable to execute database query for get_home_stats: most_concurrent: %s." % e)
return None return None
home_stats.append({'stat_id': stat, home_stats.append({'stat_id': stat,
@ -840,7 +840,7 @@ class DataFactory(object):
'ORDER BY section_type, count DESC, parent_count DESC, child_count DESC ' % ','.join(library_cards) 'ORDER BY section_type, count DESC, parent_count DESC, child_count DESC ' % ','.join(library_cards)
result = monitor_db.select(query) result = monitor_db.select(query)
except Exception as e: except Exception as e:
logger.warn(u"Tautulli DataFactory :: Unable to execute database query for get_library_stats: %s." % e) logger.warn("Tautulli DataFactory :: Unable to execute database query for get_library_stats: %s." % e)
return None return None
for item in result: for item in result:
@ -1103,7 +1103,7 @@ class DataFactory(object):
'%s ' % where '%s ' % where
result = monitor_db.select(query) result = monitor_db.select(query)
except Exception as e: except Exception as e:
logger.warn(u"Tautulli DataFactory :: Unable to execute database query for get_total_duration: %s." % e) logger.warn("Tautulli DataFactory :: Unable to execute database query for get_total_duration: %s." % e)
return None return None
total_duration = 0 total_duration = 0
@ -1126,7 +1126,7 @@ class DataFactory(object):
query = 'SELECT ip_address FROM sessions WHERE session_key = %d %s' % (int(session_key), user_cond) query = 'SELECT ip_address FROM sessions WHERE session_key = %d %s' % (int(session_key), user_cond)
result = monitor_db.select(query) result = monitor_db.select(query)
except Exception as e: except Exception as e:
logger.warn(u"Tautulli DataFactory :: Unable to execute database query for get_session_ip: %s." % e) logger.warn("Tautulli DataFactory :: Unable to execute database query for get_session_ip: %s." % e)
return ip_address return ip_address
else: else:
return ip_address return ip_address
@ -1187,14 +1187,14 @@ class DataFactory(object):
'JOIN image_hash_lookup ON cloudinary_lookup.img_hash = image_hash_lookup.img_hash ' \ 'JOIN image_hash_lookup ON cloudinary_lookup.img_hash = image_hash_lookup.img_hash ' \
'%s %s' % (where, order_by) '%s %s' % (where, order_by)
else: else:
logger.warn(u"Tautulli DataFactory :: Unable to execute database query for get_img_info: " logger.warn("Tautulli DataFactory :: Unable to execute database query for get_img_info: "
"service not provided.") "service not provided.")
return img_info return img_info
try: try:
img_info = monitor_db.select(query, args=args) img_info = monitor_db.select(query, args=args)
except Exception as e: except Exception as e:
logger.warn(u"Tautulli DataFactory :: Unable to execute database query for get_img_info: %s." % e) logger.warn("Tautulli DataFactory :: Unable to execute database query for get_img_info: %s." % e)
return img_info return img_info
@ -1213,7 +1213,7 @@ class DataFactory(object):
values = {'cloudinary_title': img_title, values = {'cloudinary_title': img_title,
'cloudinary_url': img_url} 'cloudinary_url': img_url}
else: else:
logger.warn(u"Tautulli DataFactory :: Unable to execute database query for set_img_info: " logger.warn("Tautulli DataFactory :: Unable to execute database query for set_img_info: "
"service not provided.") "service not provided.")
return return
@ -1226,7 +1226,7 @@ class DataFactory(object):
service = helpers.get_img_service() service = helpers.get_img_service()
if not rating_key and not delete_all: if not rating_key and not delete_all:
logger.error(u"Tautulli DataFactory :: Unable to delete hosted images: rating_key not provided.") logger.error("Tautulli DataFactory :: Unable to delete hosted images: rating_key not provided.")
return False return False
where = '' where = ''
@ -1249,7 +1249,7 @@ class DataFactory(object):
img_title=imgur_info['imgur_title'], img_title=imgur_info['imgur_title'],
fallback=imgur_info['fallback']) fallback=imgur_info['fallback'])
logger.info(u"Tautulli DataFactory :: Deleting Imgur info%s from the database." logger.info("Tautulli DataFactory :: Deleting Imgur info%s from the database."
% log_msg) % log_msg)
result = monitor_db.action('DELETE FROM imgur_lookup WHERE img_hash ' result = monitor_db.action('DELETE FROM imgur_lookup WHERE img_hash '
'IN (SELECT img_hash FROM image_hash_lookup %s)' % where, 'IN (SELECT img_hash FROM image_hash_lookup %s)' % where,
@ -1268,14 +1268,14 @@ class DataFactory(object):
for cloudinary_info in results: for cloudinary_info in results:
helpers.delete_from_cloudinary(rating_key=cloudinary_info['rating_key']) helpers.delete_from_cloudinary(rating_key=cloudinary_info['rating_key'])
logger.info(u"Tautulli DataFactory :: Deleting Cloudinary info%s from the database." logger.info("Tautulli DataFactory :: Deleting Cloudinary info%s from the database."
% log_msg) % log_msg)
result = monitor_db.action('DELETE FROM cloudinary_lookup WHERE img_hash ' result = monitor_db.action('DELETE FROM cloudinary_lookup WHERE img_hash '
'IN (SELECT img_hash FROM image_hash_lookup %s)' % where, 'IN (SELECT img_hash FROM image_hash_lookup %s)' % where,
args) args)
else: else:
logger.error(u"Tautulli DataFactory :: Unable to delete hosted images: invalid service '%s' provided." logger.error("Tautulli DataFactory :: Unable to delete hosted images: invalid service '%s' provided."
% service) % service)
return service return service
@ -1348,7 +1348,7 @@ class DataFactory(object):
lookup_info['musicbrainz_id'] = musicbrainz_info['musicbrainz_id'] lookup_info['musicbrainz_id'] = musicbrainz_info['musicbrainz_id']
except Exception as e: except Exception as e:
logger.warn(u"Tautulli DataFactory :: Unable to execute database query for get_lookup_info: %s." % e) logger.warn("Tautulli DataFactory :: Unable to execute database query for get_lookup_info: %s." % e)
return lookup_info return lookup_info
@ -1356,7 +1356,7 @@ class DataFactory(object):
monitor_db = database.MonitorDatabase() monitor_db = database.MonitorDatabase()
if rating_key: if rating_key:
logger.info(u"Tautulli DataFactory :: Deleting lookup info for '%s' (rating_key %s) from the database." logger.info("Tautulli DataFactory :: Deleting lookup info for '%s' (rating_key %s) from the database."
% (title, rating_key)) % (title, rating_key))
result_tvmaze = monitor_db.action('DELETE FROM tvmaze_lookup WHERE rating_key = ?', [rating_key]) result_tvmaze = monitor_db.action('DELETE FROM tvmaze_lookup WHERE rating_key = ?', [rating_key])
result_themoviedb = monitor_db.action('DELETE FROM themoviedb_lookup WHERE rating_key = ?', [rating_key]) result_themoviedb = monitor_db.action('DELETE FROM themoviedb_lookup WHERE rating_key = ?', [rating_key])
@ -1451,7 +1451,7 @@ class DataFactory(object):
grandparent_rating_key = result[0]['grandparent_rating_key'] grandparent_rating_key = result[0]['grandparent_rating_key']
except Exception as e: except Exception as e:
logger.warn(u"Tautulli DataFactory :: Unable to execute database query for get_rating_keys_list: %s." % e) logger.warn("Tautulli DataFactory :: Unable to execute database query for get_rating_keys_list: %s." % e)
return {} return {}
query = 'SELECT rating_key, parent_rating_key, grandparent_rating_key, title, parent_title, grandparent_title, ' \ query = 'SELECT rating_key, parent_rating_key, grandparent_rating_key, title, parent_title, grandparent_title, ' \
@ -1499,7 +1499,7 @@ class DataFactory(object):
monitor_db = database.MonitorDatabase() monitor_db = database.MonitorDatabase()
if row_id.isdigit(): if row_id.isdigit():
logger.info(u"Tautulli DataFactory :: Deleting row id %s from the session history database." % row_id) logger.info("Tautulli DataFactory :: Deleting row id %s from the session history database." % row_id)
session_history_del = \ session_history_del = \
monitor_db.action('DELETE FROM session_history WHERE id = ?', [row_id]) monitor_db.action('DELETE FROM session_history WHERE id = ?', [row_id])
session_history_media_info_del = \ session_history_media_info_del = \
@ -1532,7 +1532,7 @@ class DataFactory(object):
mapping = get_pairs(old_key_list, new_key_list) mapping = get_pairs(old_key_list, new_key_list)
if mapping: if mapping:
logger.info(u"Tautulli DataFactory :: Updating metadata in the database.") logger.info("Tautulli DataFactory :: Updating metadata in the database.")
for old_key, new_key in mapping.iteritems(): for old_key, new_key in mapping.iteritems():
metadata = pms_connect.get_metadata_details(new_key) metadata = pms_connect.get_metadata_details(new_key)
@ -1581,7 +1581,7 @@ class DataFactory(object):
genres = ";".join(metadata['genres']) genres = ";".join(metadata['genres'])
labels = ";".join(metadata['labels']) labels = ";".join(metadata['labels'])
#logger.info(u"Tautulli DataFactory :: Updating metadata in the database for rating key: %s." % new_rating_key) #logger.info("Tautulli DataFactory :: Updating metadata in the database for rating key: %s." % new_rating_key)
monitor_db = database.MonitorDatabase() monitor_db = database.MonitorDatabase()
# Update the session_history_metadata table # Update the session_history_metadata table
@ -1635,7 +1635,7 @@ class DataFactory(object):
join_evals=[], join_evals=[],
kwargs=kwargs) kwargs=kwargs)
except Exception as e: except Exception as e:
logger.warn(u"Tautulli DataFactory :: Unable to execute database query for get_notification_log: %s." % e) logger.warn("Tautulli DataFactory :: Unable to execute database query for get_notification_log: %s." % e)
return {'recordsFiltered': 0, return {'recordsFiltered': 0,
'recordsTotal': 0, 'recordsTotal': 0,
'draw': 0, 'draw': 0,
@ -1680,12 +1680,12 @@ class DataFactory(object):
monitor_db = database.MonitorDatabase() monitor_db = database.MonitorDatabase()
try: try:
logger.info(u"Tautulli DataFactory :: Clearing notification logs from database.") logger.info("Tautulli DataFactory :: Clearing notification logs from database.")
monitor_db.action('DELETE FROM notify_log') monitor_db.action('DELETE FROM notify_log')
monitor_db.action('VACUUM') monitor_db.action('VACUUM')
return True return True
except Exception as e: except Exception as e:
logger.warn(u"Tautulli DataFactory :: Unable to execute database query for delete_notification_log: %s." % e) logger.warn("Tautulli DataFactory :: Unable to execute database query for delete_notification_log: %s." % e)
return False return False
def get_newsletter_log(self, kwargs=None): def get_newsletter_log(self, kwargs=None):
@ -1714,7 +1714,7 @@ class DataFactory(object):
join_evals=[], join_evals=[],
kwargs=kwargs) kwargs=kwargs)
except Exception as e: except Exception as e:
logger.warn(u"Tautulli DataFactory :: Unable to execute database query for get_newsletter_log: %s." % e) logger.warn("Tautulli DataFactory :: Unable to execute database query for get_newsletter_log: %s." % e)
return {'recordsFiltered': 0, return {'recordsFiltered': 0,
'recordsTotal': 0, 'recordsTotal': 0,
'draw': 0, 'draw': 0,
@ -1753,12 +1753,12 @@ class DataFactory(object):
monitor_db = database.MonitorDatabase() monitor_db = database.MonitorDatabase()
try: try:
logger.info(u"Tautulli DataFactory :: Clearing newsletter logs from database.") logger.info("Tautulli DataFactory :: Clearing newsletter logs from database.")
monitor_db.action('DELETE FROM newsletter_log') monitor_db.action('DELETE FROM newsletter_log')
monitor_db.action('VACUUM') monitor_db.action('VACUUM')
return True return True
except Exception as e: except Exception as e:
logger.warn(u"Tautulli DataFactory :: Unable to execute database query for delete_newsletter_log: %s." % e) logger.warn("Tautulli DataFactory :: Unable to execute database query for delete_newsletter_log: %s." % e)
return False return False
def get_user_devices(self, user_id=''): def get_user_devices(self, user_id=''):
@ -1769,7 +1769,7 @@ class DataFactory(object):
query = 'SELECT machine_id FROM session_history WHERE user_id = ? GROUP BY machine_id' query = 'SELECT machine_id FROM session_history WHERE user_id = ? GROUP BY machine_id'
result = monitor_db.select(query=query, args=[user_id]) result = monitor_db.select(query=query, args=[user_id])
except Exception as e: except Exception as e:
logger.warn(u"Tautulli DataFactory :: Unable to execute database query for get_user_devices: %s." % e) logger.warn("Tautulli DataFactory :: Unable to execute database query for get_user_devices: %s." % e)
return [] return []
else: else:
return [] return []
@ -1784,7 +1784,7 @@ class DataFactory(object):
query = 'SELECT * FROM recently_added WHERE rating_key = ?' query = 'SELECT * FROM recently_added WHERE rating_key = ?'
result = monitor_db.select(query=query, args=[rating_key]) result = monitor_db.select(query=query, args=[rating_key])
except Exception as e: except Exception as e:
logger.warn(u"Tautulli DataFactory :: Unable to execute database query for get_recently_added_item: %s." % e) logger.warn("Tautulli DataFactory :: Unable to execute database query for get_recently_added_item: %s." % e)
return [] return []
else: else:
return [] return []
@ -1810,7 +1810,7 @@ class DataFactory(object):
try: try:
monitor_db.upsert(table_name='recently_added', key_dict=keys, value_dict=values) monitor_db.upsert(table_name='recently_added', key_dict=keys, value_dict=values)
except Exception as e: except Exception as e:
logger.warn(u"Tautulli DataFactory :: Unable to execute database query for set_recently_added_item: %s." % e) logger.warn("Tautulli DataFactory :: Unable to execute database query for set_recently_added_item: %s." % e)
return False return False
return True return True

View file

@ -84,7 +84,7 @@ class DataTables(object):
query = 'SELECT * FROM (SELECT %s FROM %s %s %s %s %s) %s %s' \ query = 'SELECT * FROM (SELECT %s FROM %s %s %s %s %s) %s %s' \
% (extracted_columns['column_string'], table_name, join, c_where, group, union, where, order) % (extracted_columns['column_string'], table_name, join, c_where, group, union, where, order)
# logger.debug(u"Query: %s" % query) # logger.debug("Query: %s" % query)
# Execute the query # Execute the query
filtered = self.ssp_db.select(query, args=args) filtered = self.ssp_db.select(query, args=args)

View file

@ -73,7 +73,7 @@ class Graphs(object):
result = monitor_db.select(query) result = monitor_db.select(query)
except Exception as e: except Exception as e:
logger.warn(u"Tautulli Graphs :: Unable to execute database query for get_total_plays_per_day: %s." % e) logger.warn("Tautulli Graphs :: Unable to execute database query for get_total_plays_per_day: %s." % e)
return None return None
# create our date range as some days may not have any data # create our date range as some days may not have any data
@ -180,7 +180,7 @@ class Graphs(object):
result = monitor_db.select(query) result = monitor_db.select(query)
except Exception as e: except Exception as e:
logger.warn(u"Tautulli Graphs :: Unable to execute database query for get_total_plays_per_dayofweek: %s." % e) logger.warn("Tautulli Graphs :: Unable to execute database query for get_total_plays_per_dayofweek: %s." % e)
return None return None
if plexpy.CONFIG.WEEK_START_MONDAY: if plexpy.CONFIG.WEEK_START_MONDAY:
@ -272,7 +272,7 @@ class Graphs(object):
result = monitor_db.select(query) result = monitor_db.select(query)
except Exception as e: except Exception as e:
logger.warn(u"Tautulli Graphs :: Unable to execute database query for get_total_plays_per_hourofday: %s." % e) logger.warn("Tautulli Graphs :: Unable to execute database query for get_total_plays_per_hourofday: %s." % e)
return None return None
hours_list = ['00','01','02','03','04','05', hours_list = ['00','01','02','03','04','05',
@ -364,7 +364,7 @@ class Graphs(object):
result = monitor_db.select(query) result = monitor_db.select(query)
except Exception as e: except Exception as e:
logger.warn(u"Tautulli Graphs :: Unable to execute database query for get_total_plays_per_month: %s." % e) logger.warn("Tautulli Graphs :: Unable to execute database query for get_total_plays_per_month: %s." % e)
return None return None
# create our date range as some months may not have any data # create our date range as some months may not have any data
@ -461,7 +461,7 @@ class Graphs(object):
result = monitor_db.select(query) result = monitor_db.select(query)
except Exception as e: except Exception as e:
logger.warn(u"Tautulli Graphs :: Unable to execute database query for get_total_plays_by_top_10_platforms: %s." % e) logger.warn("Tautulli Graphs :: Unable to execute database query for get_total_plays_by_top_10_platforms: %s." % e)
return None return None
categories = [] categories = []
@ -543,7 +543,7 @@ class Graphs(object):
result = monitor_db.select(query) result = monitor_db.select(query)
except Exception as e: except Exception as e:
logger.warn(u"Tautulli Graphs :: Unable to execute database query for get_total_plays_by_top_10_users: %s." % e) logger.warn("Tautulli Graphs :: Unable to execute database query for get_total_plays_by_top_10_users: %s." % e)
return None return None
categories = [] categories = []
@ -634,7 +634,7 @@ class Graphs(object):
result = monitor_db.select(query) result = monitor_db.select(query)
except Exception as e: except Exception as e:
logger.warn(u"Tautulli Graphs :: Unable to execute database query for get_total_plays_per_stream_type: %s." % e) logger.warn("Tautulli Graphs :: Unable to execute database query for get_total_plays_per_stream_type: %s." % e)
return None return None
# create our date range as some days may not have any data # create our date range as some days may not have any data
@ -740,7 +740,7 @@ class Graphs(object):
result = monitor_db.select(query) result = monitor_db.select(query)
except Exception as e: except Exception as e:
logger.warn(u"Tautulli Graphs :: Unable to execute database query for get_total_plays_by_source_resolution: %s." % e) logger.warn("Tautulli Graphs :: Unable to execute database query for get_total_plays_by_source_resolution: %s." % e)
return None return None
categories = [] categories = []
@ -850,7 +850,7 @@ class Graphs(object):
result = monitor_db.select(query) result = monitor_db.select(query)
except Exception as e: except Exception as e:
logger.warn(u"Tautulli Graphs :: Unable to execute database query for get_total_plays_by_stream_resolution: %s." % e) logger.warn("Tautulli Graphs :: Unable to execute database query for get_total_plays_by_stream_resolution: %s." % e)
return None return None
categories = [] categories = []
@ -939,7 +939,7 @@ class Graphs(object):
result = monitor_db.select(query) result = monitor_db.select(query)
except Exception as e: except Exception as e:
logger.warn(u"Tautulli Graphs :: Unable to execute database query for get_stream_type_by_top_10_platforms: %s." % e) logger.warn("Tautulli Graphs :: Unable to execute database query for get_stream_type_by_top_10_platforms: %s." % e)
return None return None
categories = [] categories = []
@ -1037,7 +1037,7 @@ class Graphs(object):
result = monitor_db.select(query) result = monitor_db.select(query)
except Exception as e: except Exception as e:
logger.warn(u"Tautulli Graphs :: Unable to execute database query for get_stream_type_by_top_10_users: %s." % e) logger.warn("Tautulli Graphs :: Unable to execute database query for get_stream_type_by_top_10_users: %s." % e)
return None return None
categories = [] categories = []

View file

@ -429,7 +429,7 @@ def create_https_certificates(ssl_cert, ssl_key):
altNames = ','.join(domains + ips) altNames = ','.join(domains + ips)
# Create the self-signed Tautulli certificate # Create the self-signed Tautulli certificate
logger.debug(u"Generating self-signed SSL certificate.") logger.debug("Generating self-signed SSL certificate.")
pkey = createKeyPair(TYPE_RSA, 2048) pkey = createKeyPair(TYPE_RSA, 2048)
cert = createSelfSignedCertificate(("Tautulli", pkey), serial, (0, 60 * 60 * 24 * 365 * 10), altNames) # ten years cert = createSelfSignedCertificate(("Tautulli", pkey), serial, (0, 60 * 60 * 24 * 365 * 10), altNames) # ten years
@ -568,9 +568,9 @@ def get_ip(host):
elif not re.fullmatch(r'[0-9]+(?:\.[0-9]+){3}(?!\d*-[a-z0-9]{6})', host): elif not re.fullmatch(r'[0-9]+(?:\.[0-9]+){3}(?!\d*-[a-z0-9]{6})', host):
try: try:
ip_address = socket.getaddrinfo(host, None)[0][4][0] ip_address = socket.getaddrinfo(host, None)[0][4][0]
logger.debug(u"IP Checker :: Resolved %s to %s." % (host, ip_address)) logger.debug("IP Checker :: Resolved %s to %s." % (host, ip_address))
except: except:
logger.error(u"IP Checker :: Bad IP or hostname provided: %s." % host) logger.error("IP Checker :: Bad IP or hostname provided: %s." % host)
return ip_address return ip_address
@ -594,27 +594,27 @@ def install_geoip_db():
geolite2_db = plexpy.CONFIG.GEOIP_DB or os.path.join(plexpy.DATA_DIR, geolite2_db) geolite2_db = plexpy.CONFIG.GEOIP_DB or os.path.join(plexpy.DATA_DIR, geolite2_db)
# Retrieve the GeoLite2 gzip file # Retrieve the GeoLite2 gzip file
logger.debug(u"Tautulli Helpers :: Downloading GeoLite2 gzip file from MaxMind...") logger.debug("Tautulli Helpers :: Downloading GeoLite2 gzip file from MaxMind...")
try: try:
maxmind = urllib.URLopener() maxmind = urllib.URLopener()
maxmind.retrieve(maxmind_url + geolite2_gz, temp_gz) maxmind.retrieve(maxmind_url + geolite2_gz, temp_gz)
md5_checksum = urllib2.urlopen(maxmind_url + geolite2_md5).read() md5_checksum = urllib2.urlopen(maxmind_url + geolite2_md5).read()
except Exception as e: except Exception as e:
logger.error(u"Tautulli Helpers :: Failed to download GeoLite2 gzip file from MaxMind: %s" % e) logger.error("Tautulli Helpers :: Failed to download GeoLite2 gzip file from MaxMind: %s" % e)
return False return False
# Extract the GeoLite2 database file # Extract the GeoLite2 database file
logger.debug(u"Tautulli Helpers :: Extracting GeoLite2 database...") logger.debug("Tautulli Helpers :: Extracting GeoLite2 database...")
try: try:
with gzip.open(temp_gz, 'rb') as gz: with gzip.open(temp_gz, 'rb') as gz:
with open(geolite2_db, 'wb') as db: with open(geolite2_db, 'wb') as db:
db.write(gz.read()) db.write(gz.read())
except Exception as e: except Exception as e:
logger.error(u"Tautulli Helpers :: Failed to extract the GeoLite2 database: %s" % e) logger.error("Tautulli Helpers :: Failed to extract the GeoLite2 database: %s" % e)
return False return False
# Check MD5 hash for GeoLite2 database file # Check MD5 hash for GeoLite2 database file
logger.debug(u"Tautulli Helpers :: Checking MD5 checksum for GeoLite2 database...") logger.debug("Tautulli Helpers :: Checking MD5 checksum for GeoLite2 database...")
try: try:
hash_md5 = hashlib.md5() hash_md5 = hashlib.md5()
with open(geolite2_db, 'rb') as f: with open(geolite2_db, 'rb') as f:
@ -623,21 +623,21 @@ def install_geoip_db():
md5_hash = hash_md5.hexdigest() md5_hash = hash_md5.hexdigest()
if md5_hash != md5_checksum: if md5_hash != md5_checksum:
logger.error(u"Tautulli Helpers :: MD5 checksum doesn't match for GeoLite2 database. " logger.error("Tautulli Helpers :: MD5 checksum doesn't match for GeoLite2 database. "
"Checksum: %s, file hash: %s" % (md5_checksum, md5_hash)) "Checksum: %s, file hash: %s" % (md5_checksum, md5_hash))
return False return False
except Exception as e: except Exception as e:
logger.error(u"Tautulli Helpers :: Failed to generate MD5 checksum for GeoLite2 database: %s" % e) logger.error("Tautulli Helpers :: Failed to generate MD5 checksum for GeoLite2 database: %s" % e)
return False return False
# Delete temportary GeoLite2 gzip file # Delete temportary GeoLite2 gzip file
logger.debug(u"Tautulli Helpers :: Deleting temporary GeoLite2 gzip file...") logger.debug("Tautulli Helpers :: Deleting temporary GeoLite2 gzip file...")
try: try:
os.remove(temp_gz) os.remove(temp_gz)
except Exception as e: except Exception as e:
logger.warn(u"Tautulli Helpers :: Failed to remove temporary GeoLite2 gzip file: %s" % e) logger.warn("Tautulli Helpers :: Failed to remove temporary GeoLite2 gzip file: %s" % e)
logger.debug(u"Tautulli Helpers :: GeoLite2 database installed successfully.") logger.debug("Tautulli Helpers :: GeoLite2 database installed successfully.")
plexpy.CONFIG.__setattr__('GEOIP_DB', geolite2_db) plexpy.CONFIG.__setattr__('GEOIP_DB', geolite2_db)
plexpy.CONFIG.write() plexpy.CONFIG.write()
@ -645,16 +645,16 @@ def install_geoip_db():
def uninstall_geoip_db(): def uninstall_geoip_db():
logger.debug(u"Tautulli Helpers :: Uninstalling the GeoLite2 database...") logger.debug("Tautulli Helpers :: Uninstalling the GeoLite2 database...")
try: try:
os.remove(plexpy.CONFIG.GEOIP_DB) os.remove(plexpy.CONFIG.GEOIP_DB)
plexpy.CONFIG.__setattr__('GEOIP_DB', '') plexpy.CONFIG.__setattr__('GEOIP_DB', '')
plexpy.CONFIG.write() plexpy.CONFIG.write()
except Exception as e: except Exception as e:
logger.error(u"Tautulli Helpers :: Failed to uninstall the GeoLite2 database: %s" % e) logger.error("Tautulli Helpers :: Failed to uninstall the GeoLite2 database: %s" % e)
return False return False
logger.debug(u"Tautulli Helpers :: GeoLite2 database uninstalled successfully.") logger.debug("Tautulli Helpers :: GeoLite2 database uninstalled successfully.")
return True return True
@ -758,7 +758,7 @@ def upload_to_imgur(img_data, img_title='', rating_key='', fallback=''):
img_url = delete_hash = '' img_url = delete_hash = ''
if not plexpy.CONFIG.IMGUR_CLIENT_ID: if not plexpy.CONFIG.IMGUR_CLIENT_ID:
logger.error(u"Tautulli Helpers :: Cannot upload image to Imgur. No Imgur client id specified in the settings.") logger.error("Tautulli Helpers :: Cannot upload image to Imgur. No Imgur client id specified in the settings.")
return img_url, delete_hash return img_url, delete_hash
headers = {'Authorization': 'Client-ID %s' % plexpy.CONFIG.IMGUR_CLIENT_ID} headers = {'Authorization': 'Client-ID %s' % plexpy.CONFIG.IMGUR_CLIENT_ID}
@ -771,18 +771,18 @@ def upload_to_imgur(img_data, img_title='', rating_key='', fallback=''):
headers=headers, data=data) headers=headers, data=data)
if response and not err_msg: if response and not err_msg:
logger.debug(u"Tautulli Helpers :: Image '{}' ({}) uploaded to Imgur.".format(img_title, fallback)) logger.debug("Tautulli Helpers :: Image '{}' ({}) uploaded to Imgur.".format(img_title, fallback))
imgur_response_data = response.json().get('data') imgur_response_data = response.json().get('data')
img_url = imgur_response_data.get('link', '').replace('http://', 'https://') img_url = imgur_response_data.get('link', '').replace('http://', 'https://')
delete_hash = imgur_response_data.get('deletehash', '') delete_hash = imgur_response_data.get('deletehash', '')
else: else:
if err_msg: if err_msg:
logger.error(u"Tautulli Helpers :: Unable to upload image '{}' ({}) to Imgur: {}".format(img_title, fallback, err_msg)) logger.error("Tautulli Helpers :: Unable to upload image '{}' ({}) to Imgur: {}".format(img_title, fallback, err_msg))
else: else:
logger.error(u"Tautulli Helpers :: Unable to upload image '{}' ({}) to Imgur.".format(img_title, fallback)) logger.error("Tautulli Helpers :: Unable to upload image '{}' ({}) to Imgur.".format(img_title, fallback))
if req_msg: if req_msg:
logger.debug(u"Tautulli Helpers :: Request response: {}".format(req_msg)) logger.debug("Tautulli Helpers :: Request response: {}".format(req_msg))
return img_url, delete_hash return img_url, delete_hash
@ -790,7 +790,7 @@ def upload_to_imgur(img_data, img_title='', rating_key='', fallback=''):
def delete_from_imgur(delete_hash, img_title='', fallback=''): def delete_from_imgur(delete_hash, img_title='', fallback=''):
""" Deletes an image from Imgur """ """ Deletes an image from Imgur """
if not plexpy.CONFIG.IMGUR_CLIENT_ID: if not plexpy.CONFIG.IMGUR_CLIENT_ID:
logger.error(u"Tautulli Helpers :: Cannot delete image from Imgur. No Imgur client id specified in the settings.") logger.error("Tautulli Helpers :: Cannot delete image from Imgur. No Imgur client id specified in the settings.")
return False return False
headers = {'Authorization': 'Client-ID %s' % plexpy.CONFIG.IMGUR_CLIENT_ID} headers = {'Authorization': 'Client-ID %s' % plexpy.CONFIG.IMGUR_CLIENT_ID}
@ -799,13 +799,13 @@ def delete_from_imgur(delete_hash, img_title='', fallback=''):
headers=headers) headers=headers)
if response and not err_msg: if response and not err_msg:
logger.debug(u"Tautulli Helpers :: Image '{}' ({}) deleted from Imgur.".format(img_title, fallback)) logger.debug("Tautulli Helpers :: Image '{}' ({}) deleted from Imgur.".format(img_title, fallback))
return True return True
else: else:
if err_msg: if err_msg:
logger.error(u"Tautulli Helpers :: Unable to delete image '{}' ({}) from Imgur: {}".format(img_title, fallback, err_msg)) logger.error("Tautulli Helpers :: Unable to delete image '{}' ({}) from Imgur: {}".format(img_title, fallback, err_msg))
else: else:
logger.error(u"Tautulli Helpers :: Unable to delete image '{}' ({}) from Imgur.".format(img_title, fallback)) logger.error("Tautulli Helpers :: Unable to delete image '{}' ({}) from Imgur.".format(img_title, fallback))
return False return False
@ -814,7 +814,7 @@ def upload_to_cloudinary(img_data, img_title='', rating_key='', fallback=''):
img_url = '' img_url = ''
if not plexpy.CONFIG.CLOUDINARY_CLOUD_NAME or not plexpy.CONFIG.CLOUDINARY_API_KEY or not plexpy.CONFIG.CLOUDINARY_API_SECRET: if not plexpy.CONFIG.CLOUDINARY_CLOUD_NAME or not plexpy.CONFIG.CLOUDINARY_API_KEY or not plexpy.CONFIG.CLOUDINARY_API_SECRET:
logger.error(u"Tautulli Helpers :: Cannot upload image to Cloudinary. Cloudinary settings not specified in the settings.") logger.error("Tautulli Helpers :: Cannot upload image to Cloudinary. Cloudinary settings not specified in the settings.")
return img_url return img_url
cloudinary.config( cloudinary.config(
@ -828,10 +828,10 @@ def upload_to_cloudinary(img_data, img_title='', rating_key='', fallback=''):
public_id='{}_{}'.format(fallback, rating_key), public_id='{}_{}'.format(fallback, rating_key),
tags=['tautulli', fallback, str(rating_key)], tags=['tautulli', fallback, str(rating_key)],
context={'title': img_title.encode('utf-8'), 'rating_key': str(rating_key), 'fallback': fallback}) context={'title': img_title.encode('utf-8'), 'rating_key': str(rating_key), 'fallback': fallback})
logger.debug(u"Tautulli Helpers :: Image '{}' ({}) uploaded to Cloudinary.".format(img_title, fallback)) logger.debug("Tautulli Helpers :: Image '{}' ({}) uploaded to Cloudinary.".format(img_title, fallback))
img_url = response.get('url', '') img_url = response.get('url', '')
except Exception as e: except Exception as e:
logger.error(u"Tautulli Helpers :: Unable to upload image '{}' ({}) to Cloudinary: {}".format(img_title, fallback, e)) logger.error("Tautulli Helpers :: Unable to upload image '{}' ({}) to Cloudinary: {}".format(img_title, fallback, e))
return img_url return img_url
@ -839,7 +839,7 @@ def upload_to_cloudinary(img_data, img_title='', rating_key='', fallback=''):
def delete_from_cloudinary(rating_key=None, delete_all=False): def delete_from_cloudinary(rating_key=None, delete_all=False):
""" Deletes an image from Cloudinary """ """ Deletes an image from Cloudinary """
if not plexpy.CONFIG.CLOUDINARY_CLOUD_NAME or not plexpy.CONFIG.CLOUDINARY_API_KEY or not plexpy.CONFIG.CLOUDINARY_API_SECRET: if not plexpy.CONFIG.CLOUDINARY_CLOUD_NAME or not plexpy.CONFIG.CLOUDINARY_API_KEY or not plexpy.CONFIG.CLOUDINARY_API_SECRET:
logger.error(u"Tautulli Helpers :: Cannot delete image from Cloudinary. Cloudinary settings not specified in the settings.") logger.error("Tautulli Helpers :: Cannot delete image from Cloudinary. Cloudinary settings not specified in the settings.")
return False return False
cloudinary.config( cloudinary.config(
@ -850,12 +850,12 @@ def delete_from_cloudinary(rating_key=None, delete_all=False):
if delete_all: if delete_all:
delete_resources_by_tag('tautulli') delete_resources_by_tag('tautulli')
logger.debug(u"Tautulli Helpers :: Deleted all images from Cloudinary.") logger.debug("Tautulli Helpers :: Deleted all images from Cloudinary.")
elif rating_key: elif rating_key:
delete_resources_by_tag(str(rating_key)) delete_resources_by_tag(str(rating_key))
logger.debug(u"Tautulli Helpers :: Deleted images from Cloudinary with rating_key {}.".format(rating_key)) logger.debug("Tautulli Helpers :: Deleted images from Cloudinary with rating_key {}.".format(rating_key))
else: else:
logger.debug(u"Tautulli Helpers :: Unable to delete images from Cloudinary: No rating_key provided.") logger.debug("Tautulli Helpers :: Unable to delete images from Cloudinary: No rating_key provided.")
return True return True
@ -865,7 +865,7 @@ def cloudinary_transform(rating_key=None, width=1000, height=1500, opacity=100,
url = '' url = ''
if not plexpy.CONFIG.CLOUDINARY_CLOUD_NAME or not plexpy.CONFIG.CLOUDINARY_API_KEY or not plexpy.CONFIG.CLOUDINARY_API_SECRET: if not plexpy.CONFIG.CLOUDINARY_CLOUD_NAME or not plexpy.CONFIG.CLOUDINARY_API_KEY or not plexpy.CONFIG.CLOUDINARY_API_SECRET:
logger.error(u"Tautulli Helpers :: Cannot transform image on Cloudinary. Cloudinary settings not specified in the settings.") logger.error("Tautulli Helpers :: Cannot transform image on Cloudinary. Cloudinary settings not specified in the settings.")
return url return url
cloudinary.config( cloudinary.config(
@ -895,9 +895,9 @@ def cloudinary_transform(rating_key=None, width=1000, height=1500, opacity=100,
try: try:
url, options = cloudinary_url('{}_{}'.format(fallback, rating_key), **img_options) url, options = cloudinary_url('{}_{}'.format(fallback, rating_key), **img_options)
logger.debug(u"Tautulli Helpers :: Image '{}' ({}) transformed on Cloudinary.".format(img_title, fallback)) logger.debug("Tautulli Helpers :: Image '{}' ({}) transformed on Cloudinary.".format(img_title, fallback))
except Exception as e: except Exception as e:
logger.error(u"Tautulli Helpers :: Unable to transform image '{}' ({}) on Cloudinary: {}".format(img_title, fallback, e)) logger.error("Tautulli Helpers :: Unable to transform image '{}' ({}) on Cloudinary: {}".format(img_title, fallback, e))
return url return url
@ -910,7 +910,7 @@ def cache_image(url, image=None):
# Create image directory if it doesn't exist # Create image directory if it doesn't exist
imgdir = os.path.join(plexpy.CONFIG.CACHE_DIR, 'images/') imgdir = os.path.join(plexpy.CONFIG.CACHE_DIR, 'images/')
if not os.path.exists(imgdir): if not os.path.exists(imgdir):
logger.debug(u"Tautulli Helpers :: Creating image cache directory at %s" % imgdir) logger.debug("Tautulli Helpers :: Creating image cache directory at %s" % imgdir)
os.makedirs(imgdir) os.makedirs(imgdir)
# Create a hash of the url to use as the filename # Create a hash of the url to use as the filename
@ -923,7 +923,7 @@ def cache_image(url, image=None):
with open(imagefile, 'wb') as cache_file: with open(imagefile, 'wb') as cache_file:
cache_file.write(image) cache_file.write(image)
except IOError as e: except IOError as e:
logger.error(u"Tautulli Helpers :: Failed to cache image %s: %s" % (imagefile, e)) logger.error("Tautulli Helpers :: Failed to cache image %s: %s" % (imagefile, e))
# Try to return the image from the cache directory # Try to return the image from the cache directory
if os.path.isfile(imagefile): if os.path.isfile(imagefile):

View file

@ -86,7 +86,7 @@ class HTTPHandler(object):
self.timeout = timeout or self.timeout self.timeout = timeout or self.timeout
if self.request_type not in self.valid_request_types: if self.request_type not in self.valid_request_types:
logger.debug(u"HTTP request made but unsupported request type given.") logger.debug("HTTP request made but unsupported request type given.")
return None return None
if uri: if uri:
@ -104,7 +104,7 @@ class HTTPHandler(object):
return responses[0] return responses[0]
else: else:
logger.debug(u"HTTP request made but no enpoint given.") logger.debug("HTTP request made but no enpoint given.")
return None return None
def _http_requests_pool(self, urls, workers=10, chunk=None): def _http_requests_pool(self, urls, workers=10, chunk=None):
@ -134,7 +134,7 @@ class HTTPHandler(object):
yield work yield work
except Exception as e: except Exception as e:
if not self._silent: if not self._silent:
logger.error(u"Failed to yield request: %s" % e) logger.error("Failed to yield request: %s" % e)
finally: finally:
pool.close() pool.close()
pool.join() pool.join()
@ -145,15 +145,15 @@ class HTTPHandler(object):
r = session.request(self.request_type, url, headers=self.headers, timeout=self.timeout) r = session.request(self.request_type, url, headers=self.headers, timeout=self.timeout)
except IOError as e: except IOError as e:
if not self._silent: if not self._silent:
logger.warn(u"Failed to access uri endpoint %s with error %s" % (self.uri, e)) logger.warn("Failed to access uri endpoint %s with error %s" % (self.uri, e))
return None return None
except Exception as e: except Exception as e:
if not self._silent: if not self._silent:
logger.warn(u"Failed to access uri endpoint %s. Is your server maybe accepting SSL connections only? %s" % (self.uri, e)) logger.warn("Failed to access uri endpoint %s. Is your server maybe accepting SSL connections only? %s" % (self.uri, e))
return None return None
except: except:
if not self._silent: if not self._silent:
logger.warn(u"Failed to access uri endpoint %s with Uncaught exception." % self.uri) logger.warn("Failed to access uri endpoint %s with Uncaught exception." % self.uri)
return None return None
response_status = r.status response_status = r.status
@ -164,7 +164,7 @@ class HTTPHandler(object):
return self._http_format_output(response_content, response_headers) return self._http_format_output(response_content, response_headers)
else: else:
if not self._silent: if not self._silent:
logger.warn(u"Failed to access uri endpoint %s. Status code %r" % (self.uri, response_status)) logger.warn("Failed to access uri endpoint %s. Status code %r" % (self.uri, response_status))
return None return None
def _http_format_output(self, response_content, response_headers): def _http_format_output(self, response_content, response_headers):
@ -191,5 +191,5 @@ class HTTPHandler(object):
except Exception as e: except Exception as e:
if not self._silent: if not self._silent:
logger.warn(u"Failed format response from uri %s to %s error %s" % (self.uri, self.output_format, e)) logger.warn("Failed format response from uri %s to %s error %s" % (self.uri, self.output_format, e))
return None return None

View file

@ -28,11 +28,11 @@ import session
def refresh_libraries(): def refresh_libraries():
logger.info(u"Tautulli Libraries :: Requesting libraries list refresh...") logger.info("Tautulli Libraries :: Requesting libraries list refresh...")
server_id = plexpy.CONFIG.PMS_IDENTIFIER server_id = plexpy.CONFIG.PMS_IDENTIFIER
if not server_id: if not server_id:
logger.error(u"Tautulli Libraries :: No PMS identifier, cannot refresh libraries. Verify server in settings.") logger.error("Tautulli Libraries :: No PMS identifier, cannot refresh libraries. Verify server in settings.")
return return
library_sections = pmsconnect.PmsConnect().get_library_details() library_sections = pmsconnect.PmsConnect().get_library_details()
@ -81,10 +81,10 @@ def refresh_libraries():
# # Start library labels update on it's own thread # # Start library labels update on it's own thread
# threading.Thread(target=libraries.update_labels).start() # threading.Thread(target=libraries.update_labels).start()
logger.info(u"Tautulli Libraries :: Libraries list refreshed.") logger.info("Tautulli Libraries :: Libraries list refreshed.")
return True return True
else: else:
logger.warn(u"Tautulli Libraries :: Unable to refresh libraries list.") logger.warn("Tautulli Libraries :: Unable to refresh libraries list.")
return False return False
@ -100,9 +100,9 @@ def update_section_ids():
query = 'SELECT section_id, section_type FROM library_sections' query = 'SELECT section_id, section_type FROM library_sections'
library_results = monitor_db.select(query=query) library_results = monitor_db.select(query=query)
except Exception as e: except Exception as e:
logger.warn(u"Tautulli Libraries :: Unable to execute database query for update_section_ids: %s." % e) logger.warn("Tautulli Libraries :: Unable to execute database query for update_section_ids: %s." % e)
logger.warn(u"Tautulli Libraries :: Unable to update section_id's in database.") logger.warn("Tautulli Libraries :: Unable to update section_id's in database.")
plexpy.CONFIG.UPDATE_SECTION_IDS = 1 plexpy.CONFIG.UPDATE_SECTION_IDS = 1
plexpy.CONFIG.write() plexpy.CONFIG.write()
return None return None
@ -112,7 +112,7 @@ def update_section_ids():
plexpy.CONFIG.write() plexpy.CONFIG.write()
return None return None
logger.debug(u"Tautulli Libraries :: Updating section_id's in database.") logger.debug("Tautulli Libraries :: Updating section_id's in database.")
# Get rating_key: section_id mapping pairs # Get rating_key: section_id mapping pairs
key_mappings = {} key_mappings = {}
@ -129,7 +129,7 @@ def update_section_ids():
children_list = library_children['children_list'] children_list = library_children['children_list']
key_mappings.update({child['rating_key']: child['section_id'] for child in children_list}) key_mappings.update({child['rating_key']: child['section_id'] for child in children_list})
else: else:
logger.warn(u"Tautulli Libraries :: Unable to get a list of library items for section_id %s." % section_id) logger.warn("Tautulli Libraries :: Unable to get a list of library items for section_id %s." % section_id)
error_keys = set() error_keys = set()
for item in history_results: for item in history_results:
@ -147,10 +147,10 @@ def update_section_ids():
error_keys.add(item['rating_key']) error_keys.add(item['rating_key'])
if error_keys: if error_keys:
logger.info(u"Tautulli Libraries :: Updated all section_id's in database except for rating_keys: %s." % logger.info("Tautulli Libraries :: Updated all section_id's in database except for rating_keys: %s." %
', '.join(str(key) for key in error_keys)) ', '.join(str(key) for key in error_keys))
else: else:
logger.info(u"Tautulli Libraries :: Updated all section_id's in database.") logger.info("Tautulli Libraries :: Updated all section_id's in database.")
plexpy.CONFIG.UPDATE_SECTION_IDS = 0 plexpy.CONFIG.UPDATE_SECTION_IDS = 0
plexpy.CONFIG.write() plexpy.CONFIG.write()
@ -166,9 +166,9 @@ def update_labels():
query = 'SELECT section_id, section_type FROM library_sections' query = 'SELECT section_id, section_type FROM library_sections'
library_results = monitor_db.select(query=query) library_results = monitor_db.select(query=query)
except Exception as e: except Exception as e:
logger.warn(u"Tautulli Libraries :: Unable to execute database query for update_labels: %s." % e) logger.warn("Tautulli Libraries :: Unable to execute database query for update_labels: %s." % e)
logger.warn(u"Tautulli Libraries :: Unable to update labels in database.") logger.warn("Tautulli Libraries :: Unable to update labels in database.")
plexpy.CONFIG.UPDATE_LABELS = 1 plexpy.CONFIG.UPDATE_LABELS = 1
plexpy.CONFIG.write() plexpy.CONFIG.write()
return None return None
@ -178,7 +178,7 @@ def update_labels():
plexpy.CONFIG.write() plexpy.CONFIG.write()
return None return None
logger.debug(u"Tautulli Libraries :: Updating labels in database.") logger.debug("Tautulli Libraries :: Updating labels in database.")
# Get rating_key: section_id mapping pairs # Get rating_key: section_id mapping pairs
key_mappings = {} key_mappings = {}
@ -209,7 +209,7 @@ def update_labels():
key_mappings[rating_key] = [label['label_title']] key_mappings[rating_key] = [label['label_title']]
else: else:
logger.warn(u"Tautulli Libraries :: Unable to get a list of library items for section_id %s." logger.warn("Tautulli Libraries :: Unable to get a list of library items for section_id %s."
% section_id) % section_id)
error_keys = set() error_keys = set()
@ -223,10 +223,10 @@ def update_labels():
error_keys.add(rating_key) error_keys.add(rating_key)
if error_keys: if error_keys:
logger.info(u"Tautulli Libraries :: Updated all labels in database except for rating_keys: %s." % logger.info("Tautulli Libraries :: Updated all labels in database except for rating_keys: %s." %
', '.join(str(key) for key in error_keys)) ', '.join(str(key) for key in error_keys))
else: else:
logger.info(u"Tautulli Libraries :: Updated all labels in database.") logger.info("Tautulli Libraries :: Updated all labels in database.")
plexpy.CONFIG.UPDATE_LABELS = 0 plexpy.CONFIG.UPDATE_LABELS = 0
plexpy.CONFIG.write() plexpy.CONFIG.write()
@ -305,7 +305,7 @@ class Libraries(object):
['session_history_metadata.id', 'session_history_media_info.id']], ['session_history_metadata.id', 'session_history_media_info.id']],
kwargs=kwargs) kwargs=kwargs)
except Exception as e: except Exception as e:
logger.warn(u"Tautulli Libraries :: Unable to execute database query for get_list: %s." % e) logger.warn("Tautulli Libraries :: Unable to execute database query for get_list: %s." % e)
return default_return return default_return
result = query['result'] result = query['result']
@ -374,19 +374,19 @@ class Libraries(object):
return default_return return default_return
if section_id and not str(section_id).isdigit(): if section_id and not str(section_id).isdigit():
logger.warn(u"Tautulli Libraries :: Datatable media info called but invalid section_id provided.") logger.warn("Tautulli Libraries :: Datatable media info called but invalid section_id provided.")
return default_return return default_return
elif rating_key and not str(rating_key).isdigit(): elif rating_key and not str(rating_key).isdigit():
logger.warn(u"Tautulli Libraries :: Datatable media info called but invalid rating_key provided.") logger.warn("Tautulli Libraries :: Datatable media info called but invalid rating_key provided.")
return default_return return default_return
elif not section_id and not rating_key: elif not section_id and not rating_key:
logger.warn(u"Tautulli Libraries :: Datatable media info called but no input provided.") logger.warn("Tautulli Libraries :: Datatable media info called but no input provided.")
return default_return return default_return
# Get the library details # Get the library details
library_details = self.get_details(section_id=section_id) library_details = self.get_details(section_id=section_id)
if library_details['section_id'] == None: if library_details['section_id'] == None:
logger.debug(u"Tautulli Libraries :: Library section_id %s not found." % section_id) logger.debug("Tautulli Libraries :: Library section_id %s not found." % section_id)
return default_return return default_return
if not section_type: if not section_type:
@ -416,7 +416,7 @@ class Libraries(object):
'GROUP BY session_history.%s ' % (count_by, group_by) 'GROUP BY session_history.%s ' % (count_by, group_by)
result = monitor_db.select(query, args=[section_id]) result = monitor_db.select(query, args=[section_id])
except Exception as e: except Exception as e:
logger.warn(u"Tautulli Libraries :: Unable to execute database query for get_datatables_media_info2: %s." % e) logger.warn("Tautulli Libraries :: Unable to execute database query for get_datatables_media_info2: %s." % e)
return default_return return default_return
watched_list = {} watched_list = {}
@ -433,8 +433,8 @@ class Libraries(object):
rows = json.load(inFile) rows = json.load(inFile)
library_count = len(rows) library_count = len(rows)
except IOError as e: except IOError as e:
#logger.debug(u"Tautulli Libraries :: No JSON file for rating_key %s." % rating_key) #logger.debug("Tautulli Libraries :: No JSON file for rating_key %s." % rating_key)
#logger.debug(u"Tautulli Libraries :: Refreshing data and creating new JSON file for rating_key %s." % rating_key) #logger.debug("Tautulli Libraries :: Refreshing data and creating new JSON file for rating_key %s." % rating_key)
pass pass
elif section_id: elif section_id:
try: try:
@ -443,8 +443,8 @@ class Libraries(object):
rows = json.load(inFile) rows = json.load(inFile)
library_count = len(rows) library_count = len(rows)
except IOError as e: except IOError as e:
#logger.debug(u"Tautulli Libraries :: No JSON file for library section_id %s." % section_id) #logger.debug("Tautulli Libraries :: No JSON file for library section_id %s." % section_id)
#logger.debug(u"Tautulli Libraries :: Refreshing data and creating new JSON file for section_id %s." % section_id) #logger.debug("Tautulli Libraries :: Refreshing data and creating new JSON file for section_id %s." % section_id)
pass pass
# If no cache was imported, get all library children items # If no cache was imported, get all library children items
@ -464,7 +464,7 @@ class Libraries(object):
library_count = library_children['library_count'] library_count = library_children['library_count']
children_list = library_children['children_list'] children_list = library_children['children_list']
else: else:
logger.warn(u"Tautulli Libraries :: Unable to get a list of library items.") logger.warn("Tautulli Libraries :: Unable to get a list of library items.")
return default_return return default_return
new_rows = [] new_rows = []
@ -509,14 +509,14 @@ class Libraries(object):
with open(outFilePath, 'w') as outFile: with open(outFilePath, 'w') as outFile:
json.dump(rows, outFile) json.dump(rows, outFile)
except IOError as e: except IOError as e:
logger.debug(u"Tautulli Libraries :: Unable to create cache file for rating_key %s." % rating_key) logger.debug("Tautulli Libraries :: Unable to create cache file for rating_key %s." % rating_key)
elif section_id: elif section_id:
try: try:
outFilePath = os.path.join(plexpy.CONFIG.CACHE_DIR,'media_info_%s.json' % section_id) outFilePath = os.path.join(plexpy.CONFIG.CACHE_DIR,'media_info_%s.json' % section_id)
with open(outFilePath, 'w') as outFile: with open(outFilePath, 'w') as outFile:
json.dump(rows, outFile) json.dump(rows, outFile)
except IOError as e: except IOError as e:
logger.debug(u"Tautulli Libraries :: Unable to create cache file for section_id %s." % section_id) logger.debug("Tautulli Libraries :: Unable to create cache file for section_id %s." % section_id)
# Update the last_played and play_count # Update the last_played and play_count
for item in rows: for item in rows:
@ -586,16 +586,16 @@ class Libraries(object):
return False return False
if section_id and not str(section_id).isdigit(): if section_id and not str(section_id).isdigit():
logger.warn(u"Tautulli Libraries :: Datatable media info file size called but invalid section_id provided.") logger.warn("Tautulli Libraries :: Datatable media info file size called but invalid section_id provided.")
return False return False
elif rating_key and not str(rating_key).isdigit(): elif rating_key and not str(rating_key).isdigit():
logger.warn(u"Tautulli Libraries :: Datatable media info file size called but invalid rating_key provided.") logger.warn("Tautulli Libraries :: Datatable media info file size called but invalid rating_key provided.")
return False return False
# Get the library details # Get the library details
library_details = self.get_details(section_id=section_id) library_details = self.get_details(section_id=section_id)
if library_details['section_id'] == None: if library_details['section_id'] == None:
logger.debug(u"Tautulli Libraries :: Library section_id %s not found." % section_id) logger.debug("Tautulli Libraries :: Library section_id %s not found." % section_id)
return False return False
if library_details['section_type'] == 'photo': if library_details['section_type'] == 'photo':
return False return False
@ -603,24 +603,24 @@ class Libraries(object):
rows = [] rows = []
# Import media info cache from json file # Import media info cache from json file
if rating_key: if rating_key:
#logger.debug(u"Tautulli Libraries :: Getting file sizes for rating_key %s." % rating_key) #logger.debug("Tautulli Libraries :: Getting file sizes for rating_key %s." % rating_key)
try: try:
inFilePath = os.path.join(plexpy.CONFIG.CACHE_DIR,'media_info_%s-%s.json' % (section_id, rating_key)) inFilePath = os.path.join(plexpy.CONFIG.CACHE_DIR,'media_info_%s-%s.json' % (section_id, rating_key))
with open(inFilePath, 'r') as inFile: with open(inFilePath, 'r') as inFile:
rows = json.load(inFile) rows = json.load(inFile)
except IOError as e: except IOError as e:
#logger.debug(u"Tautulli Libraries :: No JSON file for rating_key %s." % rating_key) #logger.debug("Tautulli Libraries :: No JSON file for rating_key %s." % rating_key)
#logger.debug(u"Tautulli Libraries :: Refreshing data and creating new JSON file for rating_key %s." % rating_key) #logger.debug("Tautulli Libraries :: Refreshing data and creating new JSON file for rating_key %s." % rating_key)
pass pass
elif section_id: elif section_id:
logger.debug(u"Tautulli Libraries :: Getting file sizes for section_id %s." % section_id) logger.debug("Tautulli Libraries :: Getting file sizes for section_id %s." % section_id)
try: try:
inFilePath = os.path.join(plexpy.CONFIG.CACHE_DIR,'media_info_%s.json' % section_id) inFilePath = os.path.join(plexpy.CONFIG.CACHE_DIR,'media_info_%s.json' % section_id)
with open(inFilePath, 'r') as inFile: with open(inFilePath, 'r') as inFile:
rows = json.load(inFile) rows = json.load(inFile)
except IOError as e: except IOError as e:
#logger.debug(u"Tautulli Libraries :: No JSON file for library section_id %s." % section_id) #logger.debug("Tautulli Libraries :: No JSON file for library section_id %s." % section_id)
#logger.debug(u"Tautulli Libraries :: Refreshing data and creating new JSON file for section_id %s." % section_id) #logger.debug("Tautulli Libraries :: Refreshing data and creating new JSON file for section_id %s." % section_id)
pass pass
# Get the total file size for each item # Get the total file size for each item
@ -653,20 +653,20 @@ class Libraries(object):
with open(outFilePath, 'w') as outFile: with open(outFilePath, 'w') as outFile:
json.dump(rows, outFile) json.dump(rows, outFile)
except IOError as e: except IOError as e:
logger.debug(u"Tautulli Libraries :: Unable to create cache file with file sizes for rating_key %s." % rating_key) logger.debug("Tautulli Libraries :: Unable to create cache file with file sizes for rating_key %s." % rating_key)
elif section_id: elif section_id:
try: try:
outFilePath = os.path.join(plexpy.CONFIG.CACHE_DIR,'media_info_%s.json' % section_id) outFilePath = os.path.join(plexpy.CONFIG.CACHE_DIR,'media_info_%s.json' % section_id)
with open(outFilePath, 'w') as outFile: with open(outFilePath, 'w') as outFile:
json.dump(rows, outFile) json.dump(rows, outFile)
except IOError as e: except IOError as e:
logger.debug(u"Tautulli Libraries :: Unable to create cache file with file sizes for section_id %s." % section_id) logger.debug("Tautulli Libraries :: Unable to create cache file with file sizes for section_id %s." % section_id)
if rating_key: if rating_key:
#logger.debug(u"Tautulli Libraries :: File sizes updated for rating_key %s." % rating_key) #logger.debug("Tautulli Libraries :: File sizes updated for rating_key %s." % rating_key)
pass pass
elif section_id: elif section_id:
logger.debug(u"Tautulli Libraries :: File sizes updated for section_id %s." % section_id) logger.debug("Tautulli Libraries :: File sizes updated for section_id %s." % section_id)
return True return True
@ -682,7 +682,7 @@ class Libraries(object):
try: try:
monitor_db.upsert('library_sections', value_dict, key_dict) monitor_db.upsert('library_sections', value_dict, key_dict)
except Exception as e: except Exception as e:
logger.warn(u"Tautulli Libraries :: Unable to execute database query for set_config: %s." % e) logger.warn("Tautulli Libraries :: Unable to execute database query for set_config: %s." % e)
def get_details(self, section_id=None): def get_details(self, section_id=None):
default_return = {'section_id': 0, default_return = {'section_id': 0,
@ -716,7 +716,7 @@ class Libraries(object):
else: else:
result = [] result = []
except Exception as e: except Exception as e:
logger.warn(u"Tautulli Libraries :: Unable to execute database query for get_details: %s." % e) logger.warn("Tautulli Libraries :: Unable to execute database query for get_details: %s." % e)
result = [] result = []
library_details = {} library_details = {}
@ -750,7 +750,7 @@ class Libraries(object):
return library_details return library_details
else: else:
logger.warn(u"Tautulli Libraries :: Unable to retrieve library %s from database. Requesting library list refresh." logger.warn("Tautulli Libraries :: Unable to retrieve library %s from database. Requesting library list refresh."
% section_id) % section_id)
# Let's first refresh the libraries list to make sure the library isn't newly added and not in the db yet # Let's first refresh the libraries list to make sure the library isn't newly added and not in the db yet
refresh_libraries() refresh_libraries()
@ -761,7 +761,7 @@ class Libraries(object):
return library_details return library_details
else: else:
logger.warn(u"Tautulli Users :: Unable to retrieve library %s from database. Returning 'Local' library." logger.warn("Tautulli Users :: Unable to retrieve library %s from database. Returning 'Local' library."
% section_id) % section_id)
# If there is no library data we must return something # If there is no library data we must return something
return default_return return default_return
@ -806,7 +806,7 @@ class Libraries(object):
else: else:
result = [] result = []
except Exception as e: except Exception as e:
logger.warn(u"Tautulli Libraries :: Unable to execute database query for get_watch_time_stats: %s." % e) logger.warn("Tautulli Libraries :: Unable to execute database query for get_watch_time_stats: %s." % e)
result = [] result = []
for item in result: for item in result:
@ -854,7 +854,7 @@ class Libraries(object):
else: else:
result = [] result = []
except Exception as e: except Exception as e:
logger.warn(u"Tautulli Libraries :: Unable to execute database query for get_user_stats: %s." % e) logger.warn("Tautulli Libraries :: Unable to execute database query for get_user_stats: %s." % e)
result = [] result = []
for item in result: for item in result:
@ -893,7 +893,7 @@ class Libraries(object):
else: else:
result = [] result = []
except Exception as e: except Exception as e:
logger.warn(u"Tautulli Libraries :: Unable to execute database query for get_recently_watched: %s." % e) logger.warn("Tautulli Libraries :: Unable to execute database query for get_recently_watched: %s." % e)
result = [] result = []
for row in result: for row in result:
@ -935,7 +935,7 @@ class Libraries(object):
'FROM library_sections WHERE deleted_section = 0' 'FROM library_sections WHERE deleted_section = 0'
result = monitor_db.select(query=query) result = monitor_db.select(query=query)
except Exception as e: except Exception as e:
logger.warn(u"Tautulli Libraries :: Unable to execute database query for get_sections: %s." % e) logger.warn("Tautulli Libraries :: Unable to execute database query for get_sections: %s." % e)
return None return None
libraries = [] libraries = []
@ -954,7 +954,7 @@ class Libraries(object):
try: try:
if section_id.isdigit(): if section_id.isdigit():
logger.info(u"Tautulli Libraries :: Deleting all history for library id %s from database." % section_id) logger.info("Tautulli Libraries :: Deleting all history for library id %s from database." % section_id)
session_history_media_info_del = \ session_history_media_info_del = \
monitor_db.action('DELETE FROM ' monitor_db.action('DELETE FROM '
'session_history_media_info ' 'session_history_media_info '
@ -978,7 +978,7 @@ class Libraries(object):
else: else:
return 'Unable to delete items, section_id not valid.' return 'Unable to delete items, section_id not valid.'
except Exception as e: except Exception as e:
logger.warn(u"Tautulli Libraries :: Unable to execute database query for delete_all_history: %s." % e) logger.warn("Tautulli Libraries :: Unable to execute database query for delete_all_history: %s." % e)
def delete(self, section_id=None): def delete(self, section_id=None):
monitor_db = database.MonitorDatabase() monitor_db = database.MonitorDatabase()
@ -986,7 +986,7 @@ class Libraries(object):
try: try:
if section_id.isdigit(): if section_id.isdigit():
self.delete_all_history(section_id) self.delete_all_history(section_id)
logger.info(u"Tautulli Libraries :: Deleting library with id %s from database." % section_id) logger.info("Tautulli Libraries :: Deleting library with id %s from database." % section_id)
monitor_db.action('UPDATE library_sections SET deleted_section = 1 WHERE section_id = ?', [section_id]) monitor_db.action('UPDATE library_sections SET deleted_section = 1 WHERE section_id = ?', [section_id])
monitor_db.action('UPDATE library_sections SET keep_history = 0 WHERE section_id = ?', [section_id]) monitor_db.action('UPDATE library_sections SET keep_history = 0 WHERE section_id = ?', [section_id])
monitor_db.action('UPDATE library_sections SET do_notify = 0 WHERE section_id = ?', [section_id]) monitor_db.action('UPDATE library_sections SET do_notify = 0 WHERE section_id = ?', [section_id])
@ -1002,7 +1002,7 @@ class Libraries(object):
else: else:
return 'Unable to delete library, section_id not valid.' return 'Unable to delete library, section_id not valid.'
except Exception as e: except Exception as e:
logger.warn(u"Tautulli Libraries :: Unable to execute database query for delete: %s." % e) logger.warn("Tautulli Libraries :: Unable to execute database query for delete: %s." % e)
def undelete(self, section_id=None, section_name=None): def undelete(self, section_id=None, section_name=None):
monitor_db = database.MonitorDatabase() monitor_db = database.MonitorDatabase()
@ -1012,7 +1012,7 @@ class Libraries(object):
query = 'SELECT * FROM library_sections WHERE section_id = ?' query = 'SELECT * FROM library_sections WHERE section_id = ?'
result = monitor_db.select(query=query, args=[section_id]) result = monitor_db.select(query=query, args=[section_id])
if result: if result:
logger.info(u"Tautulli Libraries :: Re-adding library with id %s to database." % section_id) logger.info("Tautulli Libraries :: Re-adding library with id %s to database." % section_id)
monitor_db.action('UPDATE library_sections SET deleted_section = 0 WHERE section_id = ?', [section_id]) monitor_db.action('UPDATE library_sections SET deleted_section = 0 WHERE section_id = ?', [section_id])
monitor_db.action('UPDATE library_sections SET keep_history = 1 WHERE section_id = ?', [section_id]) monitor_db.action('UPDATE library_sections SET keep_history = 1 WHERE section_id = ?', [section_id])
monitor_db.action('UPDATE library_sections SET do_notify = 1 WHERE section_id = ?', [section_id]) monitor_db.action('UPDATE library_sections SET do_notify = 1 WHERE section_id = ?', [section_id])
@ -1025,7 +1025,7 @@ class Libraries(object):
query = 'SELECT * FROM library_sections WHERE section_name = ?' query = 'SELECT * FROM library_sections WHERE section_name = ?'
result = monitor_db.select(query=query, args=[section_name]) result = monitor_db.select(query=query, args=[section_name])
if result: if result:
logger.info(u"Tautulli Libraries :: Re-adding library with name %s to database." % section_name) logger.info("Tautulli Libraries :: Re-adding library with name %s to database." % section_name)
monitor_db.action('UPDATE library_sections SET deleted_section = 0 WHERE section_name = ?', [section_name]) monitor_db.action('UPDATE library_sections SET deleted_section = 0 WHERE section_name = ?', [section_name])
monitor_db.action('UPDATE library_sections SET keep_history = 1 WHERE section_name = ?', [section_name]) monitor_db.action('UPDATE library_sections SET keep_history = 1 WHERE section_name = ?', [section_name])
monitor_db.action('UPDATE library_sections SET do_notify = 1 WHERE section_name = ?', [section_name]) monitor_db.action('UPDATE library_sections SET do_notify = 1 WHERE section_name = ?', [section_name])
@ -1035,7 +1035,7 @@ class Libraries(object):
return False return False
except Exception as e: except Exception as e:
logger.warn(u"Tautulli Libraries :: Unable to execute database query for undelete: %s." % e) logger.warn("Tautulli Libraries :: Unable to execute database query for undelete: %s." % e)
def delete_media_info_cache(self, section_id=None): def delete_media_info_cache(self, section_id=None):
import os import os
@ -1045,12 +1045,12 @@ class Libraries(object):
[os.remove(os.path.join(plexpy.CONFIG.CACHE_DIR, f)) for f in os.listdir(plexpy.CONFIG.CACHE_DIR) [os.remove(os.path.join(plexpy.CONFIG.CACHE_DIR, f)) for f in os.listdir(plexpy.CONFIG.CACHE_DIR)
if f.startswith('media_info_%s' % section_id) and f.endswith('.json')] if f.startswith('media_info_%s' % section_id) and f.endswith('.json')]
logger.debug(u"Tautulli Libraries :: Deleted media info table cache for section_id %s." % section_id) logger.debug("Tautulli Libraries :: Deleted media info table cache for section_id %s." % section_id)
return 'Deleted media info table cache for library with id %s.' % section_id return 'Deleted media info table cache for library with id %s.' % section_id
else: else:
return 'Unable to delete media info table cache, section_id not valid.' return 'Unable to delete media info table cache, section_id not valid.'
except Exception as e: except Exception as e:
logger.warn(u"Tautulli Libraries :: Unable to delete media info table cache: %s." % e) logger.warn("Tautulli Libraries :: Unable to delete media info table cache: %s." % e)
def delete_duplicate_libraries(self): def delete_duplicate_libraries(self):
monitor_db = database.MonitorDatabase() monitor_db = database.MonitorDatabase()
@ -1061,16 +1061,16 @@ class Libraries(object):
server_id = plexpy.CONFIG.PMS_IDENTIFIER server_id = plexpy.CONFIG.PMS_IDENTIFIER
try: try:
logger.debug(u"Tautulli Libraries :: Deleting libraries where server_id does not match %s." % server_id) logger.debug("Tautulli Libraries :: Deleting libraries where server_id does not match %s." % server_id)
monitor_db.action('DELETE FROM library_sections WHERE server_id != ?', [server_id]) monitor_db.action('DELETE FROM library_sections WHERE server_id != ?', [server_id])
return 'Deleted duplicate libraries from the database.' return 'Deleted duplicate libraries from the database.'
except Exception as e: except Exception as e:
logger.warn(u"Tautulli Libraries :: Unable to delete duplicate libraries: %s." % e) logger.warn("Tautulli Libraries :: Unable to delete duplicate libraries: %s." % e)
def update_libraries_db_notify(): def update_libraries_db_notify():
logger.info(u"Tautulli Libraries :: Upgrading library notification toggles...") logger.info("Tautulli Libraries :: Upgrading library notification toggles...")
# Set flag first in case something fails we don't want to keep re-adding the notifiers # Set flag first in case something fails we don't want to keep re-adding the notifiers
plexpy.CONFIG.__setattr__('UPDATE_LIBRARIES_DB_NOTIFY', 0) plexpy.CONFIG.__setattr__('UPDATE_LIBRARIES_DB_NOTIFY', 0)

View file

@ -64,13 +64,13 @@ def add_mobile_device(device_id=None, device_name=None, device_token=None, frien
try: try:
result = db.upsert(table_name='mobile_devices', key_dict=keys, value_dict=values) result = db.upsert(table_name='mobile_devices', key_dict=keys, value_dict=values)
except Exception as e: except Exception as e:
logger.warn(u"Tautulli MobileApp :: Failed to register mobile device in the database: %s." % e) logger.warn("Tautulli MobileApp :: Failed to register mobile device in the database: %s." % e)
return return
if result == 'insert': if result == 'insert':
logger.info(u"Tautulli MobileApp :: Registered mobile device '%s' in the database." % device_name) logger.info("Tautulli MobileApp :: Registered mobile device '%s' in the database." % device_name)
else: else:
logger.debug(u"Tautulli MobileApp :: Re-registered mobile device '%s' in the database." % device_name) logger.debug("Tautulli MobileApp :: Re-registered mobile device '%s' in the database." % device_name)
return True return True
@ -79,7 +79,7 @@ def get_mobile_device_config(mobile_device_id=None):
if str(mobile_device_id).isdigit(): if str(mobile_device_id).isdigit():
mobile_device_id = int(mobile_device_id) mobile_device_id = int(mobile_device_id)
else: else:
logger.error(u"Tautulli MobileApp :: Unable to retrieve mobile device config: invalid mobile_device_id %s." % mobile_device_id) logger.error("Tautulli MobileApp :: Unable to retrieve mobile device config: invalid mobile_device_id %s." % mobile_device_id)
return None return None
db = database.MonitorDatabase() db = database.MonitorDatabase()
@ -93,7 +93,7 @@ def set_mobile_device_config(mobile_device_id=None, **kwargs):
if str(mobile_device_id).isdigit(): if str(mobile_device_id).isdigit():
mobile_device_id = int(mobile_device_id) mobile_device_id = int(mobile_device_id)
else: else:
logger.error(u"Tautulli MobileApp :: Unable to set exisiting mobile device: invalid mobile_device_id %s." % mobile_device_id) logger.error("Tautulli MobileApp :: Unable to set exisiting mobile device: invalid mobile_device_id %s." % mobile_device_id)
return False return False
keys = {'id': mobile_device_id} keys = {'id': mobile_device_id}
@ -105,10 +105,10 @@ def set_mobile_device_config(mobile_device_id=None, **kwargs):
db = database.MonitorDatabase() db = database.MonitorDatabase()
try: try:
db.upsert(table_name='mobile_devices', key_dict=keys, value_dict=values) db.upsert(table_name='mobile_devices', key_dict=keys, value_dict=values)
logger.info(u"Tautulli MobileApp :: Updated mobile device agent: mobile_device_id %s." % mobile_device_id) logger.info("Tautulli MobileApp :: Updated mobile device agent: mobile_device_id %s." % mobile_device_id)
return True return True
except Exception as e: except Exception as e:
logger.warn(u"Tautulli MobileApp :: Unable to update mobile device: %s." % e) logger.warn("Tautulli MobileApp :: Unable to update mobile device: %s." % e)
return False return False
@ -116,7 +116,7 @@ def delete_mobile_device(mobile_device_id=None):
db = database.MonitorDatabase() db = database.MonitorDatabase()
if mobile_device_id: if mobile_device_id:
logger.debug(u"Tautulli MobileApp :: Deleting device_id %s from the database." % mobile_device_id) logger.debug("Tautulli MobileApp :: Deleting device_id %s from the database." % mobile_device_id)
result = db.action('DELETE FROM mobile_devices WHERE id = ?', args=[mobile_device_id]) result = db.action('DELETE FROM mobile_devices WHERE id = ?', args=[mobile_device_id])
return True return True
else: else:
@ -132,7 +132,7 @@ def set_last_seen(device_token=None):
result = db.action('UPDATE mobile_devices SET last_seen = ? WHERE device_token = ?', result = db.action('UPDATE mobile_devices SET last_seen = ? WHERE device_token = ?',
args=[last_seen, device_token]) args=[last_seen, device_token])
except Exception as e: except Exception as e:
logger.warn(u"Tautulli MobileApp :: Failed to set last_seen time for device: %s." % e) logger.warn("Tautulli MobileApp :: Failed to set last_seen time for device: %s." % e)
return return

View file

@ -30,7 +30,7 @@ NEWSLETTER_SCHED = None
def add_newsletter_each(newsletter_id=None, notify_action=None, **kwargs): def add_newsletter_each(newsletter_id=None, notify_action=None, **kwargs):
if not notify_action: if not notify_action:
logger.debug(u"Tautulli NewsletterHandler :: Notify called but no action received.") logger.debug("Tautulli NewsletterHandler :: Notify called but no action received.")
return return
data = {'newsletter': True, data = {'newsletter': True,
@ -58,19 +58,19 @@ def schedule_newsletter_job(newsletter_job_id, name='', func=None, remove_job=Fa
if NEWSLETTER_SCHED.get_job(newsletter_job_id): if NEWSLETTER_SCHED.get_job(newsletter_job_id):
if remove_job: if remove_job:
NEWSLETTER_SCHED.remove_job(newsletter_job_id) NEWSLETTER_SCHED.remove_job(newsletter_job_id)
logger.info(u"Tautulli NewsletterHandler :: Removed scheduled newsletter: %s" % name) logger.info("Tautulli NewsletterHandler :: Removed scheduled newsletter: %s" % name)
else: else:
NEWSLETTER_SCHED.reschedule_job( NEWSLETTER_SCHED.reschedule_job(
newsletter_job_id, args=args, trigger=CronTrigger.from_crontab(cron)) newsletter_job_id, args=args, trigger=CronTrigger.from_crontab(cron))
logger.info(u"Tautulli NewsletterHandler :: Re-scheduled newsletter: %s" % name) logger.info("Tautulli NewsletterHandler :: Re-scheduled newsletter: %s" % name)
elif not remove_job: elif not remove_job:
NEWSLETTER_SCHED.add_job( NEWSLETTER_SCHED.add_job(
func, args=args, id=newsletter_job_id, trigger=CronTrigger.from_crontab(cron)) func, args=args, id=newsletter_job_id, trigger=CronTrigger.from_crontab(cron))
logger.info(u"Tautulli NewsletterHandler :: Scheduled newsletter: %s" % name) logger.info("Tautulli NewsletterHandler :: Scheduled newsletter: %s" % name)
def notify(newsletter_id=None, notify_action=None, **kwargs): def notify(newsletter_id=None, notify_action=None, **kwargs):
logger.info(u"Tautulli NewsletterHandler :: Preparing newsletter for newsletter_id %s." % newsletter_id) logger.info("Tautulli NewsletterHandler :: Preparing newsletter for newsletter_id %s." % newsletter_id)
newsletter_config = newsletters.get_newsletter_config(newsletter_id=newsletter_id) newsletter_config = newsletters.get_newsletter_config(newsletter_id=newsletter_id)
@ -149,7 +149,7 @@ def set_notify_state(newsletter, notify_action, subject, body, message, filename
db.upsert(table_name='newsletter_log', key_dict=keys, value_dict=values) db.upsert(table_name='newsletter_log', key_dict=keys, value_dict=values)
return db.last_insert_id() return db.last_insert_id()
else: else:
logger.error(u"Tautulli NewsletterHandler :: Unable to set notify state.") logger.error("Tautulli NewsletterHandler :: Unable to set notify state.")
def set_notify_success(newsletter_log_id): def set_notify_success(newsletter_log_id):
@ -202,6 +202,6 @@ def get_newsletter(newsletter_uuid=None, newsletter_id_name=None):
newsletter = n_file.read() newsletter = n_file.read()
return newsletter return newsletter
except OSError as e: except OSError as e:
logger.error(u"Tautulli NewsletterHandler :: Failed to retrieve newsletter '%s': %s" % (newsletter_uuid, e)) logger.error("Tautulli NewsletterHandler :: Failed to retrieve newsletter '%s': %s" % (newsletter_uuid, e))
else: else:
logger.warn(u"Tautulli NewsletterHandler :: Newsletter file '%s' is missing." % newsletter_file) logger.warn("Tautulli NewsletterHandler :: Newsletter file '%s' is missing." % newsletter_file)

View file

@ -117,7 +117,7 @@ def delete_newsletter(newsletter_id=None):
db = database.MonitorDatabase() db = database.MonitorDatabase()
if str(newsletter_id).isdigit(): if str(newsletter_id).isdigit():
logger.debug(u"Tautulli Newsletters :: Deleting newsletter_id %s from the database." logger.debug("Tautulli Newsletters :: Deleting newsletter_id %s from the database."
% newsletter_id) % newsletter_id)
result = db.action('DELETE FROM newsletters WHERE id = ?', args=[newsletter_id]) result = db.action('DELETE FROM newsletters WHERE id = ?', args=[newsletter_id])
return True return True
@ -129,7 +129,7 @@ def get_newsletter_config(newsletter_id=None, mask_passwords=False):
if str(newsletter_id).isdigit(): if str(newsletter_id).isdigit():
newsletter_id = int(newsletter_id) newsletter_id = int(newsletter_id)
else: else:
logger.error(u"Tautulli Newsletters :: Unable to retrieve newsletter config: invalid newsletter_id %s." logger.error("Tautulli Newsletters :: Unable to retrieve newsletter config: invalid newsletter_id %s."
% newsletter_id) % newsletter_id)
return None return None
@ -150,7 +150,7 @@ def get_newsletter_config(newsletter_id=None, mask_passwords=False):
config=config, email_config=email_config, config=config, email_config=email_config,
subject=subject, body=body, message=message) subject=subject, body=body, message=message)
except Exception as e: except Exception as e:
logger.error(u"Tautulli Newsletters :: Failed to get newsletter config options: %s." % e) logger.error("Tautulli Newsletters :: Failed to get newsletter config options: %s." % e)
return return
if mask_passwords: if mask_passwords:
@ -171,14 +171,14 @@ def add_newsletter_config(agent_id=None, **kwargs):
if str(agent_id).isdigit(): if str(agent_id).isdigit():
agent_id = int(agent_id) agent_id = int(agent_id)
else: else:
logger.error(u"Tautulli Newsletters :: Unable to add new newsletter: invalid agent_id %s." logger.error("Tautulli Newsletters :: Unable to add new newsletter: invalid agent_id %s."
% agent_id) % agent_id)
return False return False
agent = next((a for a in available_newsletter_agents() if a['id'] == agent_id), None) agent = next((a for a in available_newsletter_agents() if a['id'] == agent_id), None)
if not agent: if not agent:
logger.error(u"Tautulli Newsletters :: Unable to retrieve new newsletter agent: invalid agent_id %s." logger.error("Tautulli Newsletters :: Unable to retrieve new newsletter agent: invalid agent_id %s."
% agent_id) % agent_id)
return False return False
@ -201,12 +201,12 @@ def add_newsletter_config(agent_id=None, **kwargs):
try: try:
db.upsert(table_name='newsletters', key_dict=keys, value_dict=values) db.upsert(table_name='newsletters', key_dict=keys, value_dict=values)
newsletter_id = db.last_insert_id() newsletter_id = db.last_insert_id()
logger.info(u"Tautulli Newsletters :: Added new newsletter agent: %s (newsletter_id %s)." logger.info("Tautulli Newsletters :: Added new newsletter agent: %s (newsletter_id %s)."
% (agent['label'], newsletter_id)) % (agent['label'], newsletter_id))
blacklist_logger() blacklist_logger()
return newsletter_id return newsletter_id
except Exception as e: except Exception as e:
logger.warn(u"Tautulli Newsletters :: Unable to add newsletter agent: %s." % e) logger.warn("Tautulli Newsletters :: Unable to add newsletter agent: %s." % e)
return False return False
@ -214,14 +214,14 @@ def set_newsletter_config(newsletter_id=None, agent_id=None, **kwargs):
if str(agent_id).isdigit(): if str(agent_id).isdigit():
agent_id = int(agent_id) agent_id = int(agent_id)
else: else:
logger.error(u"Tautulli Newsletters :: Unable to set existing newsletter: invalid agent_id %s." logger.error("Tautulli Newsletters :: Unable to set existing newsletter: invalid agent_id %s."
% agent_id) % agent_id)
return False return False
agent = next((a for a in available_newsletter_agents() if a['id'] == agent_id), None) agent = next((a for a in available_newsletter_agents() if a['id'] == agent_id), None)
if not agent: if not agent:
logger.error(u"Tautulli Newsletters :: Unable to retrieve existing newsletter agent: invalid agent_id %s." logger.error("Tautulli Newsletters :: Unable to retrieve existing newsletter agent: invalid agent_id %s."
% agent_id) % agent_id)
return False return False
@ -266,13 +266,13 @@ def set_newsletter_config(newsletter_id=None, agent_id=None, **kwargs):
db = database.MonitorDatabase() db = database.MonitorDatabase()
try: try:
db.upsert(table_name='newsletters', key_dict=keys, value_dict=values) db.upsert(table_name='newsletters', key_dict=keys, value_dict=values)
logger.info(u"Tautulli Newsletters :: Updated newsletter agent: %s (newsletter_id %s)." logger.info("Tautulli Newsletters :: Updated newsletter agent: %s (newsletter_id %s)."
% (agent['label'], newsletter_id)) % (agent['label'], newsletter_id))
newsletter_handler.schedule_newsletters(newsletter_id=newsletter_id) newsletter_handler.schedule_newsletters(newsletter_id=newsletter_id)
blacklist_logger() blacklist_logger()
return True return True
except Exception as e: except Exception as e:
logger.warn(u"Tautulli Newsletters :: Unable to update newsletter agent: %s." % e) logger.warn("Tautulli Newsletters :: Unable to update newsletter agent: %s." % e)
return False return False
@ -287,7 +287,7 @@ def send_newsletter(newsletter_id=None, subject=None, body=None, message=None, n
messsage=message) messsage=message)
return agent.send() return agent.send()
else: else:
logger.debug(u"Tautulli Newsletters :: Notification requested but no newsletter_id received.") logger.debug("Tautulli Newsletters :: Notification requested but no newsletter_id received.")
def blacklist_logger(): def blacklist_logger():
@ -492,11 +492,11 @@ class Newsletter(object):
self.newsletter = self.generate_newsletter() self.newsletter = self.generate_newsletter()
if self.template_error: if self.template_error:
logger.error(u"Tautulli Newsletters :: %s newsletter failed to render template. Newsletter not sent." % self.NAME) logger.error("Tautulli Newsletters :: %s newsletter failed to render template. Newsletter not sent." % self.NAME)
return False return False
if not self._has_data(): if not self._has_data():
logger.warn(u"Tautulli Newsletters :: %s newsletter has no data. Newsletter not sent." % self.NAME) logger.warn("Tautulli Newsletters :: %s newsletter has no data. Newsletter not sent." % self.NAME)
return False return False
self._save() self._save()
@ -522,9 +522,9 @@ class Newsletter(object):
n_file.write(line + '\r\n') n_file.write(line + '\r\n')
#n_file.write(line.strip()) #n_file.write(line.strip())
logger.info(u"Tautulli Newsletters :: %s newsletter saved to '%s'" % (self.NAME, newsletter_file)) logger.info("Tautulli Newsletters :: %s newsletter saved to '%s'" % (self.NAME, newsletter_file))
except OSError as e: except OSError as e:
logger.error(u"Tautulli Newsletters :: Failed to save %s newsletter to '%s': %s" logger.error("Tautulli Newsletters :: Failed to save %s newsletter to '%s': %s"
% (self.NAME, newsletter_file, e)) % (self.NAME, newsletter_file, e))
def _send(self): def _send(self):
@ -608,34 +608,28 @@ class Newsletter(object):
try: try:
subject = custom_formatter.format(unicode(self.subject), **self.parameters) subject = custom_formatter.format(unicode(self.subject), **self.parameters)
except LookupError as e: except LookupError as e:
logger.error( logger.error("Tautulli Newsletter :: Unable to parse parameter %s in newsletter subject. Using fallback." % e)
u"Tautulli Newsletter :: Unable to parse parameter %s in newsletter subject. Using fallback." % e)
subject = unicode(self._DEFAULT_SUBJECT).format(**self.parameters) subject = unicode(self._DEFAULT_SUBJECT).format(**self.parameters)
except Exception as e: except Exception as e:
logger.error( logger.error("Tautulli Newsletter :: Unable to parse custom newsletter subject: %s. Using fallback." % e)
u"Tautulli Newsletter :: Unable to parse custom newsletter subject: %s. Using fallback." % e)
subject = unicode(self._DEFAULT_SUBJECT).format(**self.parameters) subject = unicode(self._DEFAULT_SUBJECT).format(**self.parameters)
try: try:
body = custom_formatter.format(unicode(self.body), **self.parameters) body = custom_formatter.format(unicode(self.body), **self.parameters)
except LookupError as e: except LookupError as e:
logger.error( logger.error("Tautulli Newsletter :: Unable to parse parameter %s in newsletter body. Using fallback." % e)
u"Tautulli Newsletter :: Unable to parse parameter %s in newsletter body. Using fallback." % e)
body = unicode(self._DEFAULT_BODY).format(**self.parameters) body = unicode(self._DEFAULT_BODY).format(**self.parameters)
except Exception as e: except Exception as e:
logger.error( logger.error("Tautulli Newsletter :: Unable to parse custom newsletter body: %s. Using fallback." % e)
u"Tautulli Newsletter :: Unable to parse custom newsletter body: %s. Using fallback." % e)
body = unicode(self._DEFAULT_BODY).format(**self.parameters) body = unicode(self._DEFAULT_BODY).format(**self.parameters)
try: try:
message = custom_formatter.format(unicode(self.message), **self.parameters) message = custom_formatter.format(unicode(self.message), **self.parameters)
except LookupError as e: except LookupError as e:
logger.error( logger.error("Tautulli Newsletter :: Unable to parse parameter %s in newsletter message. Using fallback." % e)
u"Tautulli Newsletter :: Unable to parse parameter %s in newsletter message. Using fallback." % e)
message = unicode(self._DEFAULT_MESSAGE).format(**self.parameters) message = unicode(self._DEFAULT_MESSAGE).format(**self.parameters)
except Exception as e: except Exception as e:
logger.error( logger.error("Tautulli Newsletter :: Unable to parse custom newsletter message: %s. Using fallback." % e)
u"Tautulli Newsletter :: Unable to parse custom newsletter message: %s. Using fallback." % e)
message = unicode(self._DEFAULT_MESSAGE).format(**self.parameters) message = unicode(self._DEFAULT_MESSAGE).format(**self.parameters)
return subject, body, message return subject, body, message
@ -647,12 +641,10 @@ class Newsletter(object):
try: try:
filename = custom_formatter.format(unicode(self.filename), **self.parameters) filename = custom_formatter.format(unicode(self.filename), **self.parameters)
except LookupError as e: except LookupError as e:
logger.error( logger.error("Tautulli Newsletter :: Unable to parse parameter %s in newsletter filename. Using fallback." % e)
u"Tautulli Newsletter :: Unable to parse parameter %s in newsletter filename. Using fallback." % e)
filename = unicode(self._DEFAULT_FILENAME).format(**self.parameters) filename = unicode(self._DEFAULT_FILENAME).format(**self.parameters)
except Exception as e: except Exception as e:
logger.error( logger.error("Tautulli Newsletter :: Unable to parse custom newsletter subject: %s. Using fallback." % e)
u"Tautulli Newsletter :: Unable to parse custom newsletter subject: %s. Using fallback." % e)
filename = unicode(self._DEFAULT_FILENAME).format(**self.parameters) filename = unicode(self._DEFAULT_FILENAME).format(**self.parameters)
return filename return filename
@ -809,7 +801,7 @@ class RecentlyAdded(Newsletter):
from notification_handler import get_img_info, set_hash_image_info from notification_handler import get_img_info, set_hash_image_info
if not self.config['incl_libraries']: if not self.config['incl_libraries']:
logger.warn(u"Tautulli Newsletters :: Failed to retrieve %s newsletter data: no libraries selected." % self.NAME) logger.warn("Tautulli Newsletters :: Failed to retrieve %s newsletter data: no libraries selected." % self.NAME)
media_types = set() media_types = set()
for s in self._get_sections(): for s in self._get_sections():

View file

@ -62,15 +62,15 @@ def process_queue():
else: else:
add_notifier_each(**params) add_notifier_each(**params)
except Exception as e: except Exception as e:
logger.exception(u"Tautulli NotificationHandler :: Notification thread exception: %s" % e) logger.exception("Tautulli NotificationHandler :: Notification thread exception: %s" % e)
queue.task_done() queue.task_done()
logger.info(u"Tautulli NotificationHandler :: Notification thread exiting...") logger.info("Tautulli NotificationHandler :: Notification thread exiting...")
def start_threads(num_threads=1): def start_threads(num_threads=1):
logger.info(u"Tautulli NotificationHandler :: Starting background notification handler ({} threads).".format(num_threads)) logger.info("Tautulli NotificationHandler :: Starting background notification handler ({} threads).".format(num_threads))
for x in range(num_threads): for x in range(num_threads):
thread = threading.Thread(target=process_queue) thread = threading.Thread(target=process_queue)
thread.daemon = True thread.daemon = True
@ -79,7 +79,7 @@ def start_threads(num_threads=1):
def add_notifier_each(notifier_id=None, notify_action=None, stream_data=None, timeline_data=None, manual_trigger=False, **kwargs): def add_notifier_each(notifier_id=None, notify_action=None, stream_data=None, timeline_data=None, manual_trigger=False, **kwargs):
if not notify_action: if not notify_action:
logger.debug(u"Tautulli NotificationHandler :: Notify called but no action received.") logger.debug("Tautulli NotificationHandler :: Notify called but no action received.")
return return
if notifier_id: if notifier_id:
@ -111,7 +111,7 @@ def add_notifier_each(notifier_id=None, notify_action=None, stream_data=None, ti
**kwargs) **kwargs)
if not parameters: if not parameters:
logger.error(u"Tautulli NotificationHandler :: Failed to build notification parameters.") logger.error("Tautulli NotificationHandler :: Failed to build notification parameters.")
return return
for notifier in notifiers_enabled: for notifier in notifiers_enabled:
@ -127,7 +127,7 @@ def add_notifier_each(notifier_id=None, notify_action=None, stream_data=None, ti
data.update(kwargs) data.update(kwargs)
plexpy.NOTIFY_QUEUE.put(data) plexpy.NOTIFY_QUEUE.put(data)
else: else:
logger.debug(u"Tautulli NotificationHandler :: Custom notification conditions not satisfied, skipping notifier_id %s." % notifier['id']) logger.debug("Tautulli NotificationHandler :: Custom notification conditions not satisfied, skipping notifier_id %s." % notifier['id'])
# Add on_concurrent and on_newdevice to queue if action is on_play # Add on_concurrent and on_newdevice to queue if action is on_play
if notify_action == 'on_play': if notify_action == 'on_play':
@ -147,11 +147,11 @@ def notify_conditions(notify_action=None, stream_data=None, timeline_data=None):
# library_details = library_data.get_details(section_id=stream_data['section_id']) # library_details = library_data.get_details(section_id=stream_data['section_id'])
# if not user_details['do_notify']: # if not user_details['do_notify']:
# logger.debug(u"Tautulli NotificationHandler :: Notifications for user '%s' are disabled." % user_details['username']) # logger.debug("Tautulli NotificationHandler :: Notifications for user '%s' are disabled." % user_details['username'])
# return False # return False
# #
# elif not library_details['do_notify'] and notify_action not in ('on_concurrent', 'on_newdevice'): # elif not library_details['do_notify'] and notify_action not in ('on_concurrent', 'on_newdevice'):
# logger.debug(u"Tautulli NotificationHandler :: Notifications for library '%s' are disabled." % library_details['section_name']) # logger.debug("Tautulli NotificationHandler :: Notifications for library '%s' are disabled." % library_details['section_name'])
# return False # return False
if notify_action == 'on_concurrent': if notify_action == 'on_concurrent':
@ -201,7 +201,7 @@ def notify_conditions(notify_action=None, stream_data=None, timeline_data=None):
# library_details = library_data.get_details(section_id=timeline_data['section_id']) # library_details = library_data.get_details(section_id=timeline_data['section_id'])
# #
# if not library_details['do_notify_created']: # if not library_details['do_notify_created']:
# # logger.debug(u"Tautulli NotificationHandler :: Notifications for library '%s' is disabled." % library_details['section_name']) # # logger.debug("Tautulli NotificationHandler :: Notifications for library '%s' is disabled." % library_details['section_name'])
# return False # return False
return True return True
@ -218,7 +218,7 @@ def notify_custom_conditions(notifier_id=None, parameters=None):
custom_conditions = notifier_config['custom_conditions'] custom_conditions = notifier_config['custom_conditions']
if custom_conditions_logic or any(c for c in custom_conditions if c['value']): if custom_conditions_logic or any(c for c in custom_conditions if c['value']):
logger.debug(u"Tautulli NotificationHandler :: Checking custom notification conditions for notifier_id %s." logger.debug("Tautulli NotificationHandler :: Checking custom notification conditions for notifier_id %s."
% notifier_id) % notifier_id)
logic_groups = None logic_groups = None
@ -227,7 +227,7 @@ def notify_custom_conditions(notifier_id=None, parameters=None):
# Parse and validate the custom conditions logic # Parse and validate the custom conditions logic
logic_groups = helpers.parse_condition_logic_string(custom_conditions_logic, len(custom_conditions)) logic_groups = helpers.parse_condition_logic_string(custom_conditions_logic, len(custom_conditions))
except ValueError as e: except ValueError as e:
logger.error(u"Tautulli NotificationHandler :: Unable to parse custom condition logic '%s': %s." logger.error("Tautulli NotificationHandler :: Unable to parse custom condition logic '%s': %s."
% (custom_conditions_logic, e)) % (custom_conditions_logic, e))
return False return False
@ -244,7 +244,7 @@ def notify_custom_conditions(notifier_id=None, parameters=None):
if not parameter or not operator or not values: if not parameter or not operator or not values:
evaluated = True evaluated = True
evaluated_conditions.append(evaluated) evaluated_conditions.append(evaluated)
logger.debug(u"Tautulli NotificationHandler :: {%s} Blank condition > %s" % (i+1, evaluated)) logger.debug("Tautulli NotificationHandler :: {%s} Blank condition > %s" % (i+1, evaluated))
continue continue
# Make sure the condition values is in a list # Make sure the condition values is in a list
@ -263,7 +263,7 @@ def notify_custom_conditions(notifier_id=None, parameters=None):
values = [helpers.cast_to_float(v) for v in values] values = [helpers.cast_to_float(v) for v in values]
except ValueError as e: except ValueError as e:
logger.error(u"Tautulli NotificationHandler :: {%s} Unable to cast condition '%s', values '%s', to type '%s'." logger.error("Tautulli NotificationHandler :: {%s} Unable to cast condition '%s', values '%s', to type '%s'."
% (i+1, parameter, values, parameter_type)) % (i+1, parameter, values, parameter_type))
return False return False
@ -279,7 +279,7 @@ def notify_custom_conditions(notifier_id=None, parameters=None):
parameter_value = helpers.cast_to_float(parameter_value) parameter_value = helpers.cast_to_float(parameter_value)
except ValueError as e: except ValueError as e:
logger.error(u"Tautulli NotificationHandler :: {%s} Unable to cast parameter '%s', value '%s', to type '%s'." logger.error("Tautulli NotificationHandler :: {%s} Unable to cast parameter '%s', value '%s', to type '%s'."
% (i+1, parameter, parameter_value, parameter_type)) % (i+1, parameter, parameter_value, parameter_type))
return False return False
@ -310,28 +310,28 @@ def notify_custom_conditions(notifier_id=None, parameters=None):
else: else:
evaluated = None evaluated = None
logger.warn(u"Tautulli NotificationHandler :: {%s} Invalid condition operator '%s' > %s." logger.warn("Tautulli NotificationHandler :: {%s} Invalid condition operator '%s' > %s."
% (i+1, operator, evaluated)) % (i+1, operator, evaluated))
evaluated_conditions.append(evaluated) evaluated_conditions.append(evaluated)
logger.debug(u"Tautulli NotificationHandler :: {%s} %s | %s | %s > '%s' > %s" logger.debug("Tautulli NotificationHandler :: {%s} %s | %s | %s > '%s' > %s"
% (i+1, parameter, operator, ' or '.join(["'%s'" % v for v in values]), parameter_value, evaluated)) % (i+1, parameter, operator, ' or '.join(["'%s'" % v for v in values]), parameter_value, evaluated))
if logic_groups: if logic_groups:
# Format and evaluate the logic string # Format and evaluate the logic string
try: try:
evaluated_logic = helpers.eval_logic_groups_to_bool(logic_groups, evaluated_conditions) evaluated_logic = helpers.eval_logic_groups_to_bool(logic_groups, evaluated_conditions)
logger.debug(u"Tautulli NotificationHandler :: Condition logic: %s > %s" logger.debug("Tautulli NotificationHandler :: Condition logic: %s > %s"
% (custom_conditions_logic, evaluated_logic)) % (custom_conditions_logic, evaluated_logic))
except Exception as e: except Exception as e:
logger.error(u"Tautulli NotificationHandler :: Unable to evaluate custom condition logic: %s." % e) logger.error("Tautulli NotificationHandler :: Unable to evaluate custom condition logic: %s." % e)
return False return False
else: else:
evaluated_logic = all(evaluated_conditions[1:]) evaluated_logic = all(evaluated_conditions[1:])
logger.debug(u"Tautulli NotificationHandler :: Condition logic [blank]: %s > %s" logger.debug("Tautulli NotificationHandler :: Condition logic [blank]: %s > %s"
% (' and '.join(['{%s}' % (i+1) for i in range(len(custom_conditions))]), evaluated_logic)) % (' and '.join(['{%s}' % (i+1) for i in range(len(custom_conditions))]), evaluated_logic))
logger.debug(u"Tautulli NotificationHandler :: Custom conditions evaluated to '{}'. Conditions: {}.".format( logger.debug("Tautulli NotificationHandler :: Custom conditions evaluated to '{}'. Conditions: {}.".format(
evaluated_logic, evaluated_conditions[1:])) evaluated_logic, evaluated_conditions[1:]))
return evaluated_logic return evaluated_logic
@ -340,7 +340,7 @@ def notify_custom_conditions(notifier_id=None, parameters=None):
def notify(notifier_id=None, notify_action=None, stream_data=None, timeline_data=None, parameters=None, **kwargs): def notify(notifier_id=None, notify_action=None, stream_data=None, timeline_data=None, parameters=None, **kwargs):
logger.info(u"Tautulli NotificationHandler :: Preparing notification for notifier_id %s." % notifier_id) logger.info("Tautulli NotificationHandler :: Preparing notification for notifier_id %s." % notifier_id)
notifier_config = notifiers.get_notifier_config(notifier_id=notifier_id) notifier_config = notifiers.get_notifier_config(notifier_id=notifier_id)
@ -456,7 +456,7 @@ def set_notify_state(notifier, notify_action, subject='', body='', script_args='
monitor_db.upsert(table_name='notify_log', key_dict=keys, value_dict=values) monitor_db.upsert(table_name='notify_log', key_dict=keys, value_dict=values)
return monitor_db.last_insert_id() return monitor_db.last_insert_id()
else: else:
logger.error(u"Tautulli NotificationHandler :: Unable to set notify state.") logger.error("Tautulli NotificationHandler :: Unable to set notify state.")
def set_notify_success(notification_id): def set_notify_success(notification_id):
@ -1049,10 +1049,10 @@ def build_notify_text(subject='', body='', notify_action=None, parameters=None,
# Make sure subject and body text are strings # Make sure subject and body text are strings
if not isinstance(subject, basestring): if not isinstance(subject, basestring):
logger.error(u"Tautulli NotificationHandler :: Invalid subject text. Using fallback.") logger.error("Tautulli NotificationHandler :: Invalid subject text. Using fallback.")
subject = default_subject subject = default_subject
if not isinstance(body, basestring): if not isinstance(body, basestring):
logger.error(u"Tautulli NotificationHandler :: Invalid body text. Using fallback.") logger.error("Tautulli NotificationHandler :: Invalid body text. Using fallback.")
body = default_body body = default_body
media_type = parameters.get('media_type') media_type = parameters.get('media_type')
@ -1093,10 +1093,10 @@ def build_notify_text(subject='', body='', notify_action=None, parameters=None,
try: try:
script_args = [str_formatter(arg) for arg in helpers.split_args(subject)] script_args = [str_formatter(arg) for arg in helpers.split_args(subject)]
except LookupError as e: except LookupError as e:
logger.error(u"Tautulli NotificationHandler :: Unable to parse parameter %s in script argument. Using fallback." % e) logger.error("Tautulli NotificationHandler :: Unable to parse parameter %s in script argument. Using fallback." % e)
script_args = [] script_args = []
except Exception as e: except Exception as e:
logger.error(u"Tautulli NotificationHandler :: Unable to parse custom script arguments: %s. Using fallback." % e) logger.error("Tautulli NotificationHandler :: Unable to parse custom script arguments: %s. Using fallback." % e)
script_args = [] script_args = []
elif agent_id == 25: elif agent_id == 25:
@ -1104,53 +1104,51 @@ def build_notify_text(subject='', body='', notify_action=None, parameters=None,
try: try:
subject = json.loads(subject) subject = json.loads(subject)
except ValueError as e: except ValueError as e:
logger.error(u"Tautulli NotificationHandler :: Unable to parse custom webhook json header data: %s. Using fallback." % e) logger.error("Tautulli NotificationHandler :: Unable to parse custom webhook json header data: %s. Using fallback." % e)
subject = '' subject = ''
if subject: if subject:
try: try:
subject = json.dumps(helpers.traverse_map(subject, str_formatter)) subject = json.dumps(helpers.traverse_map(subject, str_formatter))
except LookupError as e: except LookupError as e:
logger.error(u"Tautulli NotificationHandler :: Unable to parse parameter %s in webhook header data. Using fallback." % e) logger.error("Tautulli NotificationHandler :: Unable to parse parameter %s in webhook header data. Using fallback." % e)
subject = '' subject = ''
except Exception as e: except Exception as e:
logger.error(u"Tautulli NotificationHandler :: Unable to parse custom webhook header data: %s. Using fallback." % e) logger.error("Tautulli NotificationHandler :: Unable to parse custom webhook header data: %s. Using fallback." % e)
subject = '' subject = ''
if body: if body:
try: try:
body = json.loads(body) body = json.loads(body)
except ValueError as e: except ValueError as e:
logger.error(u"Tautulli NotificationHandler :: Unable to parse custom webhook json body data: %s. Using fallback." % e) logger.error("Tautulli NotificationHandler :: Unable to parse custom webhook json body data: %s. Using fallback." % e)
body = '' body = ''
if body: if body:
try: try:
body = json.dumps(helpers.traverse_map(body, str_formatter)) body = json.dumps(helpers.traverse_map(body, str_formatter))
except LookupError as e: except LookupError as e:
logger.error(u"Tautulli NotificationHandler :: Unable to parse parameter %s in webhook body data. Using fallback." % e) logger.error("Tautulli NotificationHandler :: Unable to parse parameter %s in webhook body data. Using fallback." % e)
body = '' body = ''
except Exception as e: except Exception as e:
logger.error(u"Tautulli NotificationHandler :: Unable to parse custom webhook body data: %s. Using fallback." % e) logger.error("Tautulli NotificationHandler :: Unable to parse custom webhook body data: %s. Using fallback." % e)
body = '' body = ''
else: else:
try: try:
subject = str_formatter(subject) subject = str_formatter(subject)
except LookupError as e: except LookupError as e:
logger.error( logger.error("Tautulli NotificationHandler :: Unable to parse parameter %s in notification subject. Using fallback." % e)
u"Tautulli NotificationHandler :: Unable to parse parameter %s in notification subject. Using fallback." % e)
subject = unicode(default_subject).format(**parameters) subject = unicode(default_subject).format(**parameters)
except Exception as e: except Exception as e:
logger.error( logger.error("Tautulli NotificationHandler :: Unable to parse custom notification subject: %s. Using fallback." % e)
u"Tautulli NotificationHandler :: Unable to parse custom notification subject: %s. Using fallback." % e)
subject = unicode(default_subject).format(**parameters) subject = unicode(default_subject).format(**parameters)
try: try:
body = str_formatter(body) body = str_formatter(body)
except LookupError as e: except LookupError as e:
logger.error(u"Tautulli NotificationHandler :: Unable to parse parameter %s in notification body. Using fallback." % e) logger.error("Tautulli NotificationHandler :: Unable to parse parameter %s in notification body. Using fallback." % e)
body = unicode(default_body).format(**parameters) body = unicode(default_body).format(**parameters)
except Exception as e: except Exception as e:
logger.error(u"Tautulli NotificationHandler :: Unable to parse custom notification body: %s. Using fallback." % e) logger.error("Tautulli NotificationHandler :: Unable to parse custom notification body: %s. Using fallback." % e)
body = unicode(default_body).format(**parameters) body = unicode(default_body).format(**parameters)
return subject, body, script_args return subject, body, script_args
@ -1364,16 +1362,16 @@ def lookup_tvmaze_by_id(rating_key=None, thetvdb_id=None, imdb_id=None):
'WHERE rating_key = ?' 'WHERE rating_key = ?'
tvmaze_info = db.select_single(query, args=[rating_key]) tvmaze_info = db.select_single(query, args=[rating_key])
except Exception as e: except Exception as e:
logger.warn(u"Tautulli NotificationHandler :: Unable to execute database query for lookup_tvmaze_by_tvdb_id: %s." % e) logger.warn("Tautulli NotificationHandler :: Unable to execute database query for lookup_tvmaze_by_tvdb_id: %s." % e)
return {} return {}
if not tvmaze_info: if not tvmaze_info:
tvmaze_info = {} tvmaze_info = {}
if thetvdb_id: if thetvdb_id:
logger.debug(u"Tautulli NotificationHandler :: Looking up TVmaze info for thetvdb_id '{}'.".format(thetvdb_id)) logger.debug("Tautulli NotificationHandler :: Looking up TVmaze info for thetvdb_id '{}'.".format(thetvdb_id))
else: else:
logger.debug(u"Tautulli NotificationHandler :: Looking up TVmaze info for imdb_id '{}'.".format(imdb_id)) logger.debug("Tautulli NotificationHandler :: Looking up TVmaze info for imdb_id '{}'.".format(imdb_id))
params = {'thetvdb': thetvdb_id} if thetvdb_id else {'imdb': imdb_id} params = {'thetvdb': thetvdb_id} if thetvdb_id else {'imdb': imdb_id}
response, err_msg, req_msg = request.request_response2('http://api.tvmaze.com/lookup/shows', params=params) response, err_msg, req_msg = request.request_response2('http://api.tvmaze.com/lookup/shows', params=params)
@ -1398,10 +1396,10 @@ def lookup_tvmaze_by_id(rating_key=None, thetvdb_id=None, imdb_id=None):
else: else:
if err_msg: if err_msg:
logger.error(u"Tautulli NotificationHandler :: {}".format(err_msg)) logger.error("Tautulli NotificationHandler :: {}".format(err_msg))
if req_msg: if req_msg:
logger.debug(u"Tautulli NotificationHandler :: Request response: {}".format(req_msg)) logger.debug("Tautulli NotificationHandler :: Request response: {}".format(req_msg))
return tvmaze_info return tvmaze_info
@ -1414,16 +1412,16 @@ def lookup_themoviedb_by_id(rating_key=None, thetvdb_id=None, imdb_id=None):
'WHERE rating_key = ?' 'WHERE rating_key = ?'
themoviedb_info = db.select_single(query, args=[rating_key]) themoviedb_info = db.select_single(query, args=[rating_key])
except Exception as e: except Exception as e:
logger.warn(u"Tautulli NotificationHandler :: Unable to execute database query for lookup_themoviedb_by_imdb_id: %s." % e) logger.warn("Tautulli NotificationHandler :: Unable to execute database query for lookup_themoviedb_by_imdb_id: %s." % e)
return {} return {}
if not themoviedb_info: if not themoviedb_info:
themoviedb_info = {} themoviedb_info = {}
if thetvdb_id: if thetvdb_id:
logger.debug(u"Tautulli NotificationHandler :: Looking up The Movie Database info for thetvdb_id '{}'.".format(thetvdb_id)) logger.debug("Tautulli NotificationHandler :: Looking up The Movie Database info for thetvdb_id '{}'.".format(thetvdb_id))
else: else:
logger.debug(u"Tautulli NotificationHandler :: Looking up The Movie Database info for imdb_id '{}'.".format(imdb_id)) logger.debug("Tautulli NotificationHandler :: Looking up The Movie Database info for imdb_id '{}'.".format(imdb_id))
params = {'api_key': plexpy.CONFIG.THEMOVIEDB_APIKEY, params = {'api_key': plexpy.CONFIG.THEMOVIEDB_APIKEY,
'external_source': 'tvdb_id' if thetvdb_id else 'imdb_id' 'external_source': 'tvdb_id' if thetvdb_id else 'imdb_id'
@ -1461,10 +1459,10 @@ def lookup_themoviedb_by_id(rating_key=None, thetvdb_id=None, imdb_id=None):
else: else:
if err_msg: if err_msg:
logger.error(u"Tautulli NotificationHandler :: {}".format(err_msg)) logger.error("Tautulli NotificationHandler :: {}".format(err_msg))
if req_msg: if req_msg:
logger.debug(u"Tautulli NotificationHandler :: Request response: {}".format(req_msg)) logger.debug("Tautulli NotificationHandler :: Request response: {}".format(req_msg))
return themoviedb_info return themoviedb_info
@ -1480,7 +1478,7 @@ def get_themoviedb_info(rating_key=None, media_type=None, themoviedb_id=None):
'WHERE rating_key = ?' 'WHERE rating_key = ?'
result = db.select_single(query, args=[rating_key]) result = db.select_single(query, args=[rating_key])
except Exception as e: except Exception as e:
logger.warn(u"Tautulli NotificationHandler :: Unable to execute database query for get_themoviedb_info: %s." % e) logger.warn("Tautulli NotificationHandler :: Unable to execute database query for get_themoviedb_info: %s." % e)
return {} return {}
if result: if result:
@ -1491,7 +1489,7 @@ def get_themoviedb_info(rating_key=None, media_type=None, themoviedb_id=None):
themoviedb_json = {} themoviedb_json = {}
logger.debug(u"Tautulli NotificationHandler :: Looking up The Movie Database info for themoviedb_id '{}'.".format(themoviedb_id)) logger.debug("Tautulli NotificationHandler :: Looking up The Movie Database info for themoviedb_id '{}'.".format(themoviedb_id))
params = {'api_key': plexpy.CONFIG.THEMOVIEDB_APIKEY} params = {'api_key': plexpy.CONFIG.THEMOVIEDB_APIKEY}
response, err_msg, req_msg = request.request_response2('https://api.themoviedb.org/3/{}/{}'.format(media_type, themoviedb_id), params=params) response, err_msg, req_msg = request.request_response2('https://api.themoviedb.org/3/{}/{}'.format(media_type, themoviedb_id), params=params)
@ -1514,10 +1512,10 @@ def get_themoviedb_info(rating_key=None, media_type=None, themoviedb_id=None):
else: else:
if err_msg: if err_msg:
logger.error(u"Tautulli NotificationHandler :: {}".format(err_msg)) logger.error("Tautulli NotificationHandler :: {}".format(err_msg))
if req_msg: if req_msg:
logger.debug(u"Tautulli NotificationHandler :: Request response: {}".format(req_msg)) logger.debug("Tautulli NotificationHandler :: Request response: {}".format(req_msg))
return themoviedb_json return themoviedb_json
@ -1531,7 +1529,7 @@ def lookup_musicbrainz_info(musicbrainz_type=None, rating_key=None, artist=None,
'WHERE rating_key = ?' 'WHERE rating_key = ?'
musicbrainz_info = db.select_single(query, args=[rating_key]) musicbrainz_info = db.select_single(query, args=[rating_key])
except Exception as e: except Exception as e:
logger.warn(u"Tautulli NotificationHandler :: Unable to execute database query for lookup_musicbrainz: %s." % e) logger.warn("Tautulli NotificationHandler :: Unable to execute database query for lookup_musicbrainz: %s." % e)
return {} return {}
if not musicbrainz_info: if not musicbrainz_info:
@ -1542,23 +1540,23 @@ def lookup_musicbrainz_info(musicbrainz_type=None, rating_key=None, artist=None,
) )
if musicbrainz_type == 'artist': if musicbrainz_type == 'artist':
logger.debug(u"Tautulli NotificationHandler :: Looking up MusicBrainz info for " logger.debug("Tautulli NotificationHandler :: Looking up MusicBrainz info for "
u"{} '{}'.".format(musicbrainz_type, artist)) "{} '{}'.".format(musicbrainz_type, artist))
result = musicbrainzngs.search_artists(artist=artist, strict=True, limit=1) result = musicbrainzngs.search_artists(artist=artist, strict=True, limit=1)
if result['artist-list']: if result['artist-list']:
musicbrainz_info = result['artist-list'][0] musicbrainz_info = result['artist-list'][0]
elif musicbrainz_type == 'release': elif musicbrainz_type == 'release':
logger.debug(u"Tautulli NotificationHandler :: Looking up MusicBrainz info for " logger.debug("Tautulli NotificationHandler :: Looking up MusicBrainz info for "
u"{} '{} - {}'.".format(musicbrainz_type, artist, release)) "{} '{} - {}'.".format(musicbrainz_type, artist, release))
result = musicbrainzngs.search_releases(artist=artist, release=release, tracks=tracks, result = musicbrainzngs.search_releases(artist=artist, release=release, tracks=tracks,
strict=True, limit=1) strict=True, limit=1)
if result['release-list']: if result['release-list']:
musicbrainz_info = result['release-list'][0] musicbrainz_info = result['release-list'][0]
elif musicbrainz_type == 'recording': elif musicbrainz_type == 'recording':
logger.debug(u"Tautulli NotificationHandler :: Looking up MusicBrainz info for " logger.debug("Tautulli NotificationHandler :: Looking up MusicBrainz info for "
u"{} '{} - {} - {}'.".format(musicbrainz_type, artist, release, recording)) "{} '{} - {} - {}'.".format(musicbrainz_type, artist, release, recording))
result = musicbrainzngs.search_recordings(artist=artist, release=release, recording=recording, result = musicbrainzngs.search_recordings(artist=artist, release=release, recording=recording,
tracks=tracks, tnum=tnum, tracks=tracks, tnum=tnum,
strict=True, limit=1) strict=True, limit=1)
@ -1580,7 +1578,7 @@ def lookup_musicbrainz_info(musicbrainz_type=None, rating_key=None, artist=None,
musicbrainz_info.pop('musicbrainz_json') musicbrainz_info.pop('musicbrainz_json')
else: else:
logger.warning(u"Tautulli NotificationHandler :: No match found on MusicBrainz.") logger.warn("Tautulli NotificationHandler :: No match found on MusicBrainz.")
return musicbrainz_info return musicbrainz_info

View file

@ -447,7 +447,7 @@ def delete_notifier(notifier_id=None):
db = database.MonitorDatabase() db = database.MonitorDatabase()
if str(notifier_id).isdigit(): if str(notifier_id).isdigit():
logger.debug(u"Tautulli Notifiers :: Deleting notifier_id %s from the database." logger.debug("Tautulli Notifiers :: Deleting notifier_id %s from the database."
% notifier_id) % notifier_id)
result = db.action('DELETE FROM notifiers WHERE id = ?', args=[notifier_id]) result = db.action('DELETE FROM notifiers WHERE id = ?', args=[notifier_id])
return True return True
@ -459,7 +459,7 @@ def get_notifier_config(notifier_id=None, mask_passwords=False):
if str(notifier_id).isdigit(): if str(notifier_id).isdigit():
notifier_id = int(notifier_id) notifier_id = int(notifier_id)
else: else:
logger.error(u"Tautulli Notifiers :: Unable to retrieve notifier config: invalid notifier_id %s." logger.error("Tautulli Notifiers :: Unable to retrieve notifier config: invalid notifier_id %s."
% notifier_id) % notifier_id)
return None return None
@ -473,7 +473,7 @@ def get_notifier_config(notifier_id=None, mask_passwords=False):
config = json.loads(result.pop('notifier_config', '{}')) config = json.loads(result.pop('notifier_config', '{}'))
notifier_agent = get_agent_class(agent_id=result['agent_id'], config=config) notifier_agent = get_agent_class(agent_id=result['agent_id'], config=config)
except Exception as e: except Exception as e:
logger.error(u"Tautulli Notifiers :: Failed to get notifier config options: %s." % e) logger.error("Tautulli Notifiers :: Failed to get notifier config options: %s." % e)
return return
if mask_passwords: if mask_passwords:
@ -517,14 +517,14 @@ def add_notifier_config(agent_id=None, **kwargs):
if str(agent_id).isdigit(): if str(agent_id).isdigit():
agent_id = int(agent_id) agent_id = int(agent_id)
else: else:
logger.error(u"Tautulli Notifiers :: Unable to add new notifier: invalid agent_id %s." logger.error("Tautulli Notifiers :: Unable to add new notifier: invalid agent_id %s."
% agent_id) % agent_id)
return False return False
agent = next((a for a in available_notification_agents() if a['id'] == agent_id), None) agent = next((a for a in available_notification_agents() if a['id'] == agent_id), None)
if not agent: if not agent:
logger.error(u"Tautulli Notifiers :: Unable to retrieve new notification agent: invalid agent_id %s." logger.error("Tautulli Notifiers :: Unable to retrieve new notification agent: invalid agent_id %s."
% agent_id) % agent_id)
return False return False
@ -553,12 +553,12 @@ def add_notifier_config(agent_id=None, **kwargs):
try: try:
db.upsert(table_name='notifiers', key_dict=keys, value_dict=values) db.upsert(table_name='notifiers', key_dict=keys, value_dict=values)
notifier_id = db.last_insert_id() notifier_id = db.last_insert_id()
logger.info(u"Tautulli Notifiers :: Added new notification agent: %s (notifier_id %s)." logger.info("Tautulli Notifiers :: Added new notification agent: %s (notifier_id %s)."
% (agent['label'], notifier_id)) % (agent['label'], notifier_id))
blacklist_logger() blacklist_logger()
return notifier_id return notifier_id
except Exception as e: except Exception as e:
logger.warn(u"Tautulli Notifiers :: Unable to add notification agent: %s." % e) logger.warn("Tautulli Notifiers :: Unable to add notification agent: %s." % e)
return False return False
@ -566,14 +566,14 @@ def set_notifier_config(notifier_id=None, agent_id=None, **kwargs):
if str(agent_id).isdigit(): if str(agent_id).isdigit():
agent_id = int(agent_id) agent_id = int(agent_id)
else: else:
logger.error(u"Tautulli Notifiers :: Unable to set existing notifier: invalid agent_id %s." logger.error("Tautulli Notifiers :: Unable to set existing notifier: invalid agent_id %s."
% agent_id) % agent_id)
return False return False
agent = next((a for a in available_notification_agents() if a['id'] == agent_id), None) agent = next((a for a in available_notification_agents() if a['id'] == agent_id), None)
if not agent: if not agent:
logger.error(u"Tautulli Notifiers :: Unable to retrieve existing notification agent: invalid agent_id %s." logger.error("Tautulli Notifiers :: Unable to retrieve existing notification agent: invalid agent_id %s."
% agent_id) % agent_id)
return False return False
@ -614,7 +614,7 @@ def set_notifier_config(notifier_id=None, agent_id=None, **kwargs):
db = database.MonitorDatabase() db = database.MonitorDatabase()
try: try:
db.upsert(table_name='notifiers', key_dict=keys, value_dict=values) db.upsert(table_name='notifiers', key_dict=keys, value_dict=values)
logger.info(u"Tautulli Notifiers :: Updated notification agent: %s (notifier_id %s)." logger.info("Tautulli Notifiers :: Updated notification agent: %s (notifier_id %s)."
% (agent['label'], notifier_id)) % (agent['label'], notifier_id))
blacklist_logger() blacklist_logger()
@ -623,7 +623,7 @@ def set_notifier_config(notifier_id=None, agent_id=None, **kwargs):
return True return True
except Exception as e: except Exception as e:
logger.warn(u"Tautulli Notifiers :: Unable to update notification agent: %s." % e) logger.warn("Tautulli Notifiers :: Unable to update notification agent: %s." % e)
return False return False
@ -638,7 +638,7 @@ def send_notification(notifier_id=None, subject='', body='', notify_action='', n
notification_id=notification_id, notification_id=notification_id,
**kwargs) **kwargs)
else: else:
logger.debug(u"Tautulli Notifiers :: Notification requested but no notifier_id received.") logger.debug("Tautulli Notifiers :: Notification requested but no notifier_id received.")
def blacklist_logger(): def blacklist_logger():
@ -813,10 +813,10 @@ class Notifier(object):
def notify(self, subject='', body='', action='', **kwargs): def notify(self, subject='', body='', action='', **kwargs):
if self.NAME not in ('Script', 'Webhook'): if self.NAME not in ('Script', 'Webhook'):
if not subject and self.config.get('incl_subject', True): if not subject and self.config.get('incl_subject', True):
logger.error(u"Tautulli Notifiers :: %s notification subject cannot be blank." % self.NAME) logger.error("Tautulli Notifiers :: %s notification subject cannot be blank." % self.NAME)
return return
elif not body: elif not body:
logger.error(u"Tautulli Notifiers :: %s notification body cannot be blank." % self.NAME) logger.error("Tautulli Notifiers :: %s notification body cannot be blank." % self.NAME)
return return
return self.agent_notify(subject=subject, body=body, action=action, **kwargs) return self.agent_notify(subject=subject, body=body, action=action, **kwargs)
@ -825,11 +825,11 @@ class Notifier(object):
pass pass
def make_request(self, url, method='POST', **kwargs): def make_request(self, url, method='POST', **kwargs):
logger.info(u"Tautulli Notifiers :: Sending {name} notification...".format(name=self.NAME)) logger.info("Tautulli Notifiers :: Sending {name} notification...".format(name=self.NAME))
response, err_msg, req_msg = request.request_response2(url, method, **kwargs) response, err_msg, req_msg = request.request_response2(url, method, **kwargs)
if response and not err_msg: if response and not err_msg:
logger.info(u"Tautulli Notifiers :: {name} notification sent.".format(name=self.NAME)) logger.info("Tautulli Notifiers :: {name} notification sent.".format(name=self.NAME))
return True return True
else: else:
@ -837,13 +837,13 @@ class Notifier(object):
if response is not None and response.status_code >= 400 and response.status_code < 500: if response is not None and response.status_code >= 400 and response.status_code < 500:
verify_msg = " Verify you notification agent settings are correct." verify_msg = " Verify you notification agent settings are correct."
logger.error(u"Tautulli Notifiers :: {name} notification failed.{msg}".format(msg=verify_msg, name=self.NAME)) logger.error("Tautulli Notifiers :: {name} notification failed.{msg}".format(msg=verify_msg, name=self.NAME))
if err_msg: if err_msg:
logger.error(u"Tautulli Notifiers :: {}".format(err_msg)) logger.error("Tautulli Notifiers :: {}".format(err_msg))
if req_msg: if req_msg:
logger.debug(u"Tautulli Notifiers :: Request response: {}".format(req_msg)) logger.debug("Tautulli Notifiers :: Request response: {}".format(req_msg))
return False return False
@ -876,7 +876,7 @@ class ANDROIDAPP(Notifier):
# Check mobile device is still registered # Check mobile device is still registered
device = mobile_app.get_mobile_devices(device_id=self.config['device_id']) device = mobile_app.get_mobile_devices(device_id=self.config['device_id'])
if not device: if not device:
logger.warn(u"Tautulli Notifiers :: Unable to send Android app notification: device not registered.") logger.warn("Tautulli Notifiers :: Unable to send Android app notification: device not registered.")
return return
else: else:
device = device[0] device = device[0]
@ -927,7 +927,7 @@ class ANDROIDAPP(Notifier):
'salt': base64.b64encode(salt)} 'salt': base64.b64encode(salt)}
} }
else: else:
logger.warn(u"Tautulli Notifiers :: PyCryptodome library is missing. " logger.warn("Tautulli Notifiers :: PyCryptodome library is missing. "
"Android app notifications will be sent unecrypted. " "Android app notifications will be sent unecrypted. "
"Install the library to encrypt the notifications.") "Install the library to encrypt the notifications.")
@ -951,7 +951,7 @@ class ANDROIDAPP(Notifier):
query = 'SELECT * FROM mobile_devices' query = 'SELECT * FROM mobile_devices'
result = db.select(query=query) result = db.select(query=query)
except Exception as e: except Exception as e:
logger.warn(u"Tautulli Notifiers :: Unable to retrieve Android app devices list: %s." % e) logger.warn("Tautulli Notifiers :: Unable to retrieve Android app devices list: %s." % e)
return {'': ''} return {'': ''}
devices = {} devices = {}
@ -1107,7 +1107,7 @@ class BROWSER(Notifier):
} }
def agent_notify(self, subject='', body='', action='', **kwargs): def agent_notify(self, subject='', body='', action='', **kwargs):
logger.info(u"Tautulli Notifiers :: {name} notification sent.".format(name=self.NAME)) logger.info("Tautulli Notifiers :: {name} notification sent.".format(name=self.NAME))
return True return True
def _return_config_options(self): def _return_config_options(self):
@ -1380,11 +1380,11 @@ class EMAIL(Notifier):
mailserver.login(str(self.config['smtp_user']), str(self.config['smtp_password'])) mailserver.login(str(self.config['smtp_user']), str(self.config['smtp_password']))
mailserver.sendmail(self.config['from'], recipients, msg.as_string()) mailserver.sendmail(self.config['from'], recipients, msg.as_string())
logger.info(u"Tautulli Notifiers :: {name} notification sent.".format(name=self.NAME)) logger.info("Tautulli Notifiers :: {name} notification sent.".format(name=self.NAME))
success = True success = True
except Exception as e: except Exception as e:
logger.error(u"Tautulli Notifiers :: {name} notification failed: {e}".format( logger.error("Tautulli Notifiers :: {name} notification failed: {e}".format(
name=self.NAME, e=str(e).decode('utf-8'))) name=self.NAME, e=str(e).decode('utf-8')))
finally: finally:
@ -1517,7 +1517,7 @@ class FACEBOOK(Notifier):
perms=['publish_to_groups']) perms=['publish_to_groups'])
def _get_credentials(self, code=''): def _get_credentials(self, code=''):
logger.info(u"Tautulli Notifiers :: Requesting access token from {name}.".format(name=self.NAME)) logger.info("Tautulli Notifiers :: Requesting access token from {name}.".format(name=self.NAME))
app_id = plexpy.CONFIG.FACEBOOK_APP_ID app_id = plexpy.CONFIG.FACEBOOK_APP_ID
app_secret = plexpy.CONFIG.FACEBOOK_APP_SECRET app_secret = plexpy.CONFIG.FACEBOOK_APP_SECRET
@ -1539,7 +1539,7 @@ class FACEBOOK(Notifier):
plexpy.CONFIG.FACEBOOK_TOKEN = response['access_token'] plexpy.CONFIG.FACEBOOK_TOKEN = response['access_token']
except Exception as e: except Exception as e:
logger.error(u"Tautulli Notifiers :: Error requesting {name} access token: {e}".format(name=self.NAME, e=e)) logger.error("Tautulli Notifiers :: Error requesting {name} access token: {e}".format(name=self.NAME, e=e))
plexpy.CONFIG.FACEBOOK_TOKEN = '' plexpy.CONFIG.FACEBOOK_TOKEN = ''
# Clear out temporary config values # Clear out temporary config values
@ -1555,14 +1555,14 @@ class FACEBOOK(Notifier):
try: try:
api.put_object(parent_object=self.config['group_id'], connection_name='feed', **data) api.put_object(parent_object=self.config['group_id'], connection_name='feed', **data)
logger.info(u"Tautulli Notifiers :: {name} notification sent.".format(name=self.NAME)) logger.info("Tautulli Notifiers :: {name} notification sent.".format(name=self.NAME))
return True return True
except Exception as e: except Exception as e:
logger.error(u"Tautulli Notifiers :: Error sending {name} post: {e}".format(name=self.NAME, e=e)) logger.error("Tautulli Notifiers :: Error sending {name} post: {e}".format(name=self.NAME, e=e))
return False return False
else: else:
logger.error(u"Tautulli Notifiers :: Error sending {name} post: No {name} Group ID provided.".format(name=self.NAME)) logger.error("Tautulli Notifiers :: Error sending {name} post: No {name} Group ID provided.".format(name=self.NAME))
return False return False
def agent_notify(self, subject='', body='', action='', **kwargs): def agent_notify(self, subject='', body='', action='', **kwargs):
@ -1700,7 +1700,7 @@ class GROUPME(Notifier):
poster_content = result[0] poster_content = result[0]
else: else:
poster_content = '' poster_content = ''
logger.error(u"Tautulli Notifiers :: Unable to retrieve image for {name}.".format(name=self.NAME)) logger.error("Tautulli Notifiers :: Unable to retrieve image for {name}.".format(name=self.NAME))
if poster_content: if poster_content:
headers = {'X-Access-Token': self.config['access_token'], headers = {'X-Access-Token': self.config['access_token'],
@ -1709,14 +1709,14 @@ class GROUPME(Notifier):
r = requests.post('https://image.groupme.com/pictures', headers=headers, data=poster_content) r = requests.post('https://image.groupme.com/pictures', headers=headers, data=poster_content)
if r.status_code == 200: if r.status_code == 200:
logger.info(u"Tautulli Notifiers :: {name} poster sent.".format(name=self.NAME)) logger.info("Tautulli Notifiers :: {name} poster sent.".format(name=self.NAME))
r_content = r.json() r_content = r.json()
data['attachments'] = [{'type': 'image', data['attachments'] = [{'type': 'image',
'url': r_content['payload']['picture_url']}] 'url': r_content['payload']['picture_url']}]
else: else:
logger.error(u"Tautulli Notifiers :: {name} poster failed: " logger.error("Tautulli Notifiers :: {name} poster failed: "
u"[{r.status_code}] {r.reason}".format(name=self.NAME, r=r)) "[{r.status_code}] {r.reason}".format(name=self.NAME, r=r))
logger.debug(u"Tautulli Notifiers :: Request response: {}".format(request.server_message(r, True))) logger.debug("Tautulli Notifiers :: Request response: {}".format(request.server_message(r, True)))
return self.make_request('https://api.groupme.com/v3/bots/post', json=data) return self.make_request('https://api.groupme.com/v3/bots/post', json=data)
@ -1788,10 +1788,10 @@ class GROWL(Notifier):
try: try:
growl.register() growl.register()
except gntp.notifier.errors.NetworkError: except gntp.notifier.errors.NetworkError:
logger.error(u"Tautulli Notifiers :: {name} notification failed: network error".format(name=self.NAME)) logger.error("Tautulli Notifiers :: {name} notification failed: network error".format(name=self.NAME))
return False return False
except gntp.notifier.errors.AuthError: except gntp.notifier.errors.AuthError:
logger.error(u"Tautulli Notifiers :: {name} notification failed: authentication error".format(name=self.NAME)) logger.error("Tautulli Notifiers :: {name} notification failed: authentication error".format(name=self.NAME))
return False return False
# Fix message # Fix message
@ -1811,10 +1811,10 @@ class GROWL(Notifier):
description=body, description=body,
icon=image icon=image
) )
logger.info(u"Tautulli Notifiers :: {name} notification sent.".format(name=self.NAME)) logger.info("Tautulli Notifiers :: {name} notification sent.".format(name=self.NAME))
return True return True
except gntp.notifier.errors.NetworkError: except gntp.notifier.errors.NetworkError:
logger.error(u"Tautulli Notifiers :: {name} notification failed: network error".format(name=self.NAME)) logger.error("Tautulli Notifiers :: {name} notification failed: network error".format(name=self.NAME))
return False return False
def _return_config_options(self): def _return_config_options(self):
@ -2113,15 +2113,15 @@ class JOIN(Notifier):
if r.status_code == 200: if r.status_code == 200:
response_data = r.json() response_data = r.json()
if response_data.get('success'): if response_data.get('success'):
logger.info(u"Tautulli Notifiers :: {name} notification sent.".format(name=self.NAME)) logger.info("Tautulli Notifiers :: {name} notification sent.".format(name=self.NAME))
return True return True
else: else:
error_msg = response_data.get('errorMessage') error_msg = response_data.get('errorMessage')
logger.error(u"Tautulli Notifiers :: {name} notification failed: {msg}".format(name=self.NAME, msg=error_msg)) logger.error("Tautulli Notifiers :: {name} notification failed: {msg}".format(name=self.NAME, msg=error_msg))
return False return False
else: else:
logger.error(u"Tautulli Notifiers :: {name} notification failed: [{r.status_code}] {r.reason}".format(name=self.NAME, r=r)) logger.error("Tautulli Notifiers :: {name} notification failed: [{r.status_code}] {r.reason}".format(name=self.NAME, r=r))
logger.debug(u"Tautulli Notifiers :: Request response: {}".format(request.server_message(r, True))) logger.debug("Tautulli Notifiers :: Request response: {}".format(request.server_message(r, True)))
return False return False
def get_devices(self): def get_devices(self):
@ -2141,14 +2141,14 @@ class JOIN(Notifier):
devices.update({d['deviceName']: d['deviceName'] for d in response_devices}) devices.update({d['deviceName']: d['deviceName'] for d in response_devices})
else: else:
error_msg = response_data.get('errorMessage') error_msg = response_data.get('errorMessage')
logger.error(u"Tautulli Notifiers :: Unable to retrieve {name} devices list: {msg}".format(name=self.NAME, msg=error_msg)) logger.error("Tautulli Notifiers :: Unable to retrieve {name} devices list: {msg}".format(name=self.NAME, msg=error_msg))
else: else:
logger.error(u"Tautulli Notifiers :: Unable to retrieve {name} devices list: [{r.status_code}] {r.reason}".format(name=self.NAME, r=r)) logger.error("Tautulli Notifiers :: Unable to retrieve {name} devices list: [{r.status_code}] {r.reason}".format(name=self.NAME, r=r))
logger.debug(u"Tautulli Notifiers :: Request response: {}".format(request.server_message(r, True))) logger.debug("Tautulli Notifiers :: Request response: {}".format(request.server_message(r, True)))
except Exception as e: except Exception as e:
logger.error(u"Tautulli Notifiers :: Unable to retrieve {name} devices list: {msg}".format(name=self.NAME, msg=e)) logger.error("Tautulli Notifiers :: Unable to retrieve {name} devices list: {msg}".format(name=self.NAME, msg=e))
return devices return devices
@ -2235,7 +2235,7 @@ class MQTT(Notifier):
def agent_notify(self, subject='', body='', action='', **kwargs): def agent_notify(self, subject='', body='', action='', **kwargs):
if not self.config['topic']: if not self.config['topic']:
logger.error(u"Tautulli Notifiers :: MQTT topic not specified.") logger.error("Tautulli Notifiers :: MQTT topic not specified.")
return return
data = {'subject': subject.encode('utf-8'), data = {'subject': subject.encode('utf-8'),
@ -2349,11 +2349,11 @@ class NMA(Notifier):
response = p.push(title, subject, body, priority=self.config['priority'], batch_mode=batch) response = p.push(title, subject, body, priority=self.config['priority'], batch_mode=batch)
if response[self.config['api_key']][u'code'] == u'200': if response[self.config['api_key']]['code'] == '200':
logger.info(u"Tautulli Notifiers :: {name} notification sent.".format(name=self.NAME)) logger.info("Tautulli Notifiers :: {name} notification sent.".format(name=self.NAME))
return True return True
else: else:
logger.error(u"Tautulli Notifiers :: {name} notification failed.".format(name=self.NAME)) logger.error("Tautulli Notifiers :: {name} notification failed.".format(name=self.NAME))
return False return False
def _return_config_options(self): def _return_config_options(self):
@ -2390,7 +2390,7 @@ class OSX(Notifier):
self.objc = __import__("objc") self.objc = __import__("objc")
self.AppKit = __import__("AppKit") self.AppKit = __import__("AppKit")
except: except:
# logger.error(u"Tautulli Notifiers :: Cannot load OSX Notifications agent.") # logger.error("Tautulli Notifiers :: Cannot load OSX Notifications agent.")
pass pass
def validate(self): def validate(self):
@ -2449,13 +2449,13 @@ class OSX(Notifier):
notification_center = NSUserNotificationCenter.defaultUserNotificationCenter() notification_center = NSUserNotificationCenter.defaultUserNotificationCenter()
notification_center.deliverNotification_(notification) notification_center.deliverNotification_(notification)
logger.info(u"Tautulli Notifiers :: {name} notification sent.".format(name=self.NAME)) logger.info("Tautulli Notifiers :: {name} notification sent.".format(name=self.NAME))
del pool del pool
return True return True
except Exception as e: except Exception as e:
logger.error(u"Tautulli Notifiers :: {name} failed: {e}".format(name=self.NAME, e=e)) logger.error("Tautulli Notifiers :: {name} failed: {e}".format(name=self.NAME, e=e))
return False return False
def _return_config_options(self): def _return_config_options(self):
@ -2527,7 +2527,7 @@ class PLEX(Notifier):
image = os.path.join(plexpy.DATA_DIR, os.path.abspath("data/interfaces/default/images/logo-circle.png")) image = os.path.join(plexpy.DATA_DIR, os.path.abspath("data/interfaces/default/images/logo-circle.png"))
for host in hosts: for host in hosts:
logger.info(u"Tautulli Notifiers :: Sending notification command to {name} @ {host}".format(name=self.NAME, host=host)) logger.info("Tautulli Notifiers :: Sending notification command to {name} @ {host}".format(name=self.NAME, host=host))
try: try:
version = self._sendjson(host, 'Application.GetProperties', {'properties': ['version']})['version']['major'] version = self._sendjson(host, 'Application.GetProperties', {'properties': ['version']})['version']['major']
@ -2543,10 +2543,10 @@ class PLEX(Notifier):
if not request: if not request:
raise Exception raise Exception
else: else:
logger.info(u"Tautulli Notifiers :: {name} notification sent.".format(name=self.NAME)) logger.info("Tautulli Notifiers :: {name} notification sent.".format(name=self.NAME))
except Exception as e: except Exception as e:
logger.error(u"Tautulli Notifiers :: {name} notification failed: {e}".format(name=self.NAME, e=e)) logger.error("Tautulli Notifiers :: {name} notification failed: {e}".format(name=self.NAME, e=e))
return False return False
return True return True
@ -2694,7 +2694,7 @@ class PUSHBULLET(Notifier):
poster_content = result[0] poster_content = result[0]
else: else:
poster_content = '' poster_content = ''
logger.error(u"Tautulli Notifiers :: Unable to retrieve image for {name}.".format(name=self.NAME)) logger.error("Tautulli Notifiers :: Unable to retrieve image for {name}.".format(name=self.NAME))
if poster_content: if poster_content:
poster_filename = 'poster_{}.png'.format(pretty_metadata.parameters['rating_key']) poster_filename = 'poster_{}.png'.format(pretty_metadata.parameters['rating_key'])
@ -2713,9 +2713,9 @@ class PUSHBULLET(Notifier):
file_response.pop('data', None) file_response.pop('data', None)
data.update(file_response) data.update(file_response)
else: else:
logger.error(u"Tautulli Notifiers :: Unable to upload image to {name}: " logger.error("Tautulli Notifiers :: Unable to upload image to {name}: "
u"[{r.status_code}] {r.reason}".format(name=self.NAME, r=r)) "[{r.status_code}] {r.reason}".format(name=self.NAME, r=r))
logger.debug(u"Tautulli Notifiers :: Request response: {}".format(request.server_message(r, True))) logger.debug("Tautulli Notifiers :: Request response: {}".format(request.server_message(r, True)))
return self.make_request('https://api.pushbullet.com/v2/pushes', headers=headers, json=data) return self.make_request('https://api.pushbullet.com/v2/pushes', headers=headers, json=data)
@ -2734,12 +2734,12 @@ class PUSHBULLET(Notifier):
pushbullet_devices = response_data.get('devices', []) pushbullet_devices = response_data.get('devices', [])
devices.update({d['iden']: d['nickname'] for d in pushbullet_devices if d['active']}) devices.update({d['iden']: d['nickname'] for d in pushbullet_devices if d['active']})
else: else:
logger.error(u"Tautulli Notifiers :: Unable to retrieve {name} devices list: " logger.error("Tautulli Notifiers :: Unable to retrieve {name} devices list: "
u"[{r.status_code}] {r.reason}".format(name=self.NAME, r=r)) "[{r.status_code}] {r.reason}".format(name=self.NAME, r=r))
logger.debug(u"Tautulli Notifiers :: Request response: {}".format(request.server_message(r, True))) logger.debug("Tautulli Notifiers :: Request response: {}".format(request.server_message(r, True)))
except Exception as e: except Exception as e:
logger.error(u"Tautulli Notifiers :: Unable to retrieve {name} devices list: {msg}".format(name=self.NAME, msg=e)) logger.error("Tautulli Notifiers :: Unable to retrieve {name} devices list: {msg}".format(name=self.NAME, msg=e))
return devices return devices
@ -2851,7 +2851,7 @@ class PUSHOVER(Notifier):
poster_content = result[0] poster_content = result[0]
else: else:
poster_content = '' poster_content = ''
logger.error(u"Tautulli Notifiers :: Unable to retrieve image for {name}.".format(name=self.NAME)) logger.error("Tautulli Notifiers :: Unable to retrieve image for {name}.".format(name=self.NAME))
if poster_content: if poster_content:
poster_filename = 'poster_{}.png'.format(pretty_metadata.parameters['rating_key']) poster_filename = 'poster_{}.png'.format(pretty_metadata.parameters['rating_key'])
@ -2901,9 +2901,9 @@ class PUSHOVER(Notifier):
# print sounds # print sounds
# return sounds # return sounds
# else: # else:
# logger.error(u"Tautulli Notifiers :: Unable to retrieve {name} sounds list: " # logger.error("Tautulli Notifiers :: Unable to retrieve {name} sounds list: "
# u"[{r.status_code}] {r.reason}".format(name=self.NAME, r=r)) # "[{r.status_code}] {r.reason}".format(name=self.NAME, r=r))
# logger.debug(u"Tautulli Notifiers :: Request response: {}".format(request.server_message(r, True))) # logger.debug("Tautulli Notifiers :: Request response: {}".format(request.server_message(r, True)))
# return {'': ''} # return {'': ''}
# #
# else: # else:
@ -3089,13 +3089,13 @@ class SCRIPTS(Notifier):
timer.start() timer.start()
output, error = process.communicate() output, error = process.communicate()
status = process.returncode status = process.returncode
logger.debug(u"Tautulli Notifiers :: Subprocess returned with status code %s." % status) logger.debug("Tautulli Notifiers :: Subprocess returned with status code %s." % status)
finally: finally:
if timer: if timer:
timer.cancel() timer.cancel()
except OSError as e: except OSError as e:
logger.error(u"Tautulli Notifiers :: Failed to run script: %s" % e) logger.error("Tautulli Notifiers :: Failed to run script: %s" % e)
return False return False
if error: if error:
@ -3107,13 +3107,13 @@ class SCRIPTS(Notifier):
logger.debug("Tautulli Notifiers :: Script returned: \n %s" % out) logger.debug("Tautulli Notifiers :: Script returned: \n %s" % out)
if not self.script_killed: if not self.script_killed:
logger.info(u"Tautulli Notifiers :: Script notification sent.") logger.info("Tautulli Notifiers :: Script notification sent.")
return True return True
def kill_script(self, process): def kill_script(self, process):
process.kill() process.kill()
self.script_killed = True self.script_killed = True
logger.warn(u"Tautulli Notifiers :: Script exceeded timeout limit of %d seconds. " logger.warn("Tautulli Notifiers :: Script exceeded timeout limit of %d seconds. "
"Script killed." % self.config['timeout']) "Script killed." % self.config['timeout'])
def agent_notify(self, subject='', body='', action='', **kwargs): def agent_notify(self, subject='', body='', action='', **kwargs):
@ -3124,12 +3124,12 @@ class SCRIPTS(Notifier):
action(string): 'play' action(string): 'play'
""" """
if not self.config['script_folder']: if not self.config['script_folder']:
logger.error(u"Tautulli Notifiers :: No script folder specified.") logger.error("Tautulli Notifiers :: No script folder specified.")
return return
script_args = helpers.split_args(kwargs.get('script_args', subject)) script_args = helpers.split_args(kwargs.get('script_args', subject))
logger.debug(u"Tautulli Notifiers :: Trying to run notify script, action: %s, arguments: %s" logger.debug("Tautulli Notifiers :: Trying to run notify script, action: %s, arguments: %s"
% (action, script_args)) % (action, script_args))
script = kwargs.get('script', self.config.get('script', '')) script = kwargs.get('script', self.config.get('script', ''))
@ -3137,10 +3137,10 @@ class SCRIPTS(Notifier):
# Don't try to run the script if the action does not have one # Don't try to run the script if the action does not have one
if action and not script: if action and not script:
logger.debug(u"Tautulli Notifiers :: No script selected for action %s, exiting..." % action) logger.debug("Tautulli Notifiers :: No script selected for action %s, exiting..." % action)
return return
elif not script: elif not script:
logger.debug(u"Tautulli Notifiers :: No script selected, exiting...") logger.debug("Tautulli Notifiers :: No script selected, exiting...")
return return
name, ext = os.path.splitext(script) name, ext = os.path.splitext(script)
@ -3178,8 +3178,8 @@ class SCRIPTS(Notifier):
script.extend(script_args) script.extend(script_args)
logger.debug(u"Tautulli Notifiers :: Full script is: %s" % script) logger.debug("Tautulli Notifiers :: Full script is: %s" % script)
logger.debug(u"Tautulli Notifiers :: Executing script in a new thread.") logger.debug("Tautulli Notifiers :: Executing script in a new thread.")
thread = threading.Thread(target=self.run_script, args=(script, user_id)).start() thread = threading.Thread(target=self.run_script, args=(script, user_id)).start()
return True return True
@ -3433,7 +3433,7 @@ class TELEGRAM(Notifier):
poster_content = result[0] poster_content = result[0]
else: else:
poster_content = '' poster_content = ''
logger.error(u"Tautulli Notifiers :: Unable to retrieve image for {name}.".format(name=self.NAME)) logger.error("Tautulli Notifiers :: Unable to retrieve image for {name}.".format(name=self.NAME))
if poster_content: if poster_content:
poster_filename = 'poster_{}.png'.format(pretty_metadata.parameters['rating_key']) poster_filename = 'poster_{}.png'.format(pretty_metadata.parameters['rating_key'])
@ -3531,16 +3531,16 @@ class TWITTER(Notifier):
access_token = self.config['access_token'] access_token = self.config['access_token']
access_token_secret = self.config['access_token_secret'] access_token_secret = self.config['access_token_secret']
# logger.info(u"Tautulli Notifiers :: Sending tweet: " + message) # logger.info("Tautulli Notifiers :: Sending tweet: " + message)
api = twitter.Api(consumer_key, consumer_secret, access_token, access_token_secret) api = twitter.Api(consumer_key, consumer_secret, access_token, access_token_secret)
try: try:
api.PostUpdate(message, media=attachment) api.PostUpdate(message, media=attachment)
logger.info(u"Tautulli Notifiers :: {name} notification sent.".format(name=self.NAME)) logger.info("Tautulli Notifiers :: {name} notification sent.".format(name=self.NAME))
return True return True
except Exception as e: except Exception as e:
logger.error(u"Tautulli Notifiers :: {name} notification failed: {e}".format(name=self.NAME, e=e)) logger.error("Tautulli Notifiers :: {name} notification failed: {e}".format(name=self.NAME, e=e))
return False return False
def agent_notify(self, subject='', body='', action='', **kwargs): def agent_notify(self, subject='', body='', action='', **kwargs):
@ -3618,7 +3618,7 @@ class WEBHOOK(Notifier):
try: try:
webhook_headers = json.loads(subject) webhook_headers = json.loads(subject)
except ValueError as e: except ValueError as e:
logger.error(u"Tautulli Notifiers :: Invalid {name} json header data: {e}".format(name=self.NAME, e=e)) logger.error("Tautulli Notifiers :: Invalid {name} json header data: {e}".format(name=self.NAME, e=e))
return False return False
else: else:
webhook_headers = None webhook_headers = None
@ -3627,7 +3627,7 @@ class WEBHOOK(Notifier):
try: try:
webhook_body = json.loads(body) webhook_body = json.loads(body)
except ValueError as e: except ValueError as e:
logger.error(u"Tautulli Notifiers :: Invalid {name} json body data: {e}".format(name=self.NAME, e=e)) logger.error("Tautulli Notifiers :: Invalid {name} json body data: {e}".format(name=self.NAME, e=e))
return False return False
else: else:
webhook_body = None webhook_body = None
@ -3711,7 +3711,7 @@ class XBMC(Notifier):
image = os.path.join(plexpy.DATA_DIR, os.path.abspath("data/interfaces/default/images/logo-circle.png")) image = os.path.join(plexpy.DATA_DIR, os.path.abspath("data/interfaces/default/images/logo-circle.png"))
for host in hosts: for host in hosts:
logger.info(u"Tautulli Notifiers :: Sending notification command to XMBC @ " + host) logger.info("Tautulli Notifiers :: Sending notification command to XMBC @ " + host)
try: try:
version = self._sendjson(host, 'Application.GetProperties', {'properties': ['version']})['version']['major'] version = self._sendjson(host, 'Application.GetProperties', {'properties': ['version']})['version']['major']
@ -3727,10 +3727,10 @@ class XBMC(Notifier):
if not request: if not request:
raise Exception raise Exception
else: else:
logger.info(u"Tautulli Notifiers :: {name} notification sent.".format(name=self.NAME)) logger.info("Tautulli Notifiers :: {name} notification sent.".format(name=self.NAME))
except Exception as e: except Exception as e:
logger.error(u"Tautulli Notifiers :: {name} notification failed: {e}".format(name=self.NAME, e=e)) logger.error("Tautulli Notifiers :: {name} notification failed: {e}".format(name=self.NAME, e=e))
return False return False
return True return True
@ -3870,7 +3870,7 @@ class ZAPIER(Notifier):
def upgrade_config_to_db(): def upgrade_config_to_db():
logger.info(u"Tautulli Notifiers :: Upgrading to new notification system...") logger.info("Tautulli Notifiers :: Upgrading to new notification system...")
# Set flag first in case something fails we don't want to keep re-adding the notifiers # Set flag first in case something fails we don't want to keep re-adding the notifiers
plexpy.CONFIG.__setattr__('UPDATE_NOTIFIERS_DB', 0) plexpy.CONFIG.__setattr__('UPDATE_NOTIFIERS_DB', 0)

View file

@ -32,13 +32,13 @@ def extract_plexivity_xml(xml=None):
try: try:
xml_parse = minidom.parseString(clean_xml) xml_parse = minidom.parseString(clean_xml)
except: except:
logger.warn(u"Tautulli Importer :: Error parsing XML for Plexivity database.") logger.warn("Tautulli Importer :: Error parsing XML for Plexivity database.")
return None return None
# I think Plexivity only tracked videos and not music? # I think Plexivity only tracked videos and not music?
xml_head = xml_parse.getElementsByTagName('Video') xml_head = xml_parse.getElementsByTagName('Video')
if not xml_head: if not xml_head:
logger.warn(u"Tautulli Importer :: Error parsing XML for Plexivity database.") logger.warn("Tautulli Importer :: Error parsing XML for Plexivity database.")
return None return None
for a in xml_head: for a in xml_head:
@ -239,23 +239,23 @@ def validate_database(database=None, table_name=None):
try: try:
connection = sqlite3.connect(database, timeout=20) connection = sqlite3.connect(database, timeout=20)
except sqlite3.OperationalError: except sqlite3.OperationalError:
logger.error(u"Tautulli Importer :: Invalid database specified.") logger.error("Tautulli Importer :: Invalid database specified.")
return 'Invalid database specified.' return 'Invalid database specified.'
except ValueError: except ValueError:
logger.error(u"Tautulli Importer :: Invalid database specified.") logger.error("Tautulli Importer :: Invalid database specified.")
return 'Invalid database specified.' return 'Invalid database specified.'
except: except:
logger.error(u"Tautulli Importer :: Uncaught exception.") logger.error("Tautulli Importer :: Uncaught exception.")
return 'Uncaught exception.' return 'Uncaught exception.'
try: try:
connection.execute('SELECT xml from %s' % table_name) connection.execute('SELECT xml from %s' % table_name)
connection.close() connection.close()
except sqlite3.OperationalError: except sqlite3.OperationalError:
logger.error(u"Tautulli Importer :: Invalid database specified.") logger.error("Tautulli Importer :: Invalid database specified.")
return 'Invalid database specified.' return 'Invalid database specified.'
except: except:
logger.error(u"Tautulli Importer :: Uncaught exception.") logger.error("Tautulli Importer :: Uncaught exception.")
return 'Uncaught exception.' return 'Uncaught exception.'
return 'success' return 'success'
@ -266,19 +266,19 @@ def import_from_plexivity(database=None, table_name=None, import_ignore_interval
connection = sqlite3.connect(database, timeout=20) connection = sqlite3.connect(database, timeout=20)
connection.row_factory = sqlite3.Row connection.row_factory = sqlite3.Row
except sqlite3.OperationalError: except sqlite3.OperationalError:
logger.error(u"Tautulli Importer :: Invalid filename.") logger.error("Tautulli Importer :: Invalid filename.")
return None return None
except ValueError: except ValueError:
logger.error(u"Tautulli Importer :: Invalid filename.") logger.error("Tautulli Importer :: Invalid filename.")
return None return None
try: try:
connection.execute('SELECT xml from %s' % table_name) connection.execute('SELECT xml from %s' % table_name)
except sqlite3.OperationalError: except sqlite3.OperationalError:
logger.error(u"Tautulli Importer :: Database specified does not contain the required fields.") logger.error("Tautulli Importer :: Database specified does not contain the required fields.")
return None return None
logger.debug(u"Tautulli Importer :: Plexivity data import in progress...") logger.debug("Tautulli Importer :: Plexivity data import in progress...")
ap = activity_processor.ActivityProcessor() ap = activity_processor.ActivityProcessor()
user_data = users.Users() user_data = users.Users()
@ -287,7 +287,7 @@ def import_from_plexivity(database=None, table_name=None, import_ignore_interval
try: try:
users.refresh_users() users.refresh_users()
except: except:
logger.debug(u"Tautulli Importer :: Unable to refresh the users list. Aborting import.") logger.debug("Tautulli Importer :: Unable to refresh the users list. Aborting import.")
return None return None
query = 'SELECT id AS id, ' \ query = 'SELECT id AS id, ' \
@ -320,13 +320,13 @@ def import_from_plexivity(database=None, table_name=None, import_ignore_interval
# If we get back None from our xml extractor skip over the record and log error. # If we get back None from our xml extractor skip over the record and log error.
if not extracted_xml: if not extracted_xml:
logger.error(u"Tautulli Importer :: Skipping record with id %s due to malformed xml." logger.error("Tautulli Importer :: Skipping record with id %s due to malformed xml."
% str(row['id'])) % str(row['id']))
continue continue
# Skip line if we don't have a ratingKey to work with # Skip line if we don't have a ratingKey to work with
#if not row['rating_key']: #if not row['rating_key']:
# logger.error(u"Tautulli Importer :: Skipping record due to null ratingKey.") # logger.error("Tautulli Importer :: Skipping record due to null ratingKey.")
# continue # continue
# If the user_id no longer exists in the friends list, pull it from the xml. # If the user_id no longer exists in the friends list, pull it from the xml.
@ -430,13 +430,13 @@ def import_from_plexivity(database=None, table_name=None, import_ignore_interval
is_import=True, is_import=True,
import_ignore_interval=import_ignore_interval) import_ignore_interval=import_ignore_interval)
else: else:
logger.debug(u"Tautulli Importer :: Item has bad rating_key: %s" % session_history_metadata['rating_key']) logger.debug("Tautulli Importer :: Item has bad rating_key: %s" % session_history_metadata['rating_key'])
logger.debug(u"Tautulli Importer :: Plexivity data import complete.") logger.debug("Tautulli Importer :: Plexivity data import complete.")
import_users() import_users()
def import_users(): def import_users():
logger.debug(u"Tautulli Importer :: Importing Plexivity Users...") logger.debug("Tautulli Importer :: Importing Plexivity Users...")
monitor_db = database.MonitorDatabase() monitor_db = database.MonitorDatabase()
query = 'INSERT OR IGNORE INTO users (user_id, username) ' \ query = 'INSERT OR IGNORE INTO users (user_id, username) ' \
@ -445,6 +445,6 @@ def import_users():
try: try:
monitor_db.action(query) monitor_db.action(query)
logger.debug(u"Tautulli Importer :: Users imported.") logger.debug("Tautulli Importer :: Users imported.")
except: except:
logger.debug(u"Tautulli Importer :: Failed to import users.") logger.debug("Tautulli Importer :: Failed to import users.")

View file

@ -31,7 +31,7 @@ import session
def get_server_resources(return_presence=False, return_server=False, **kwargs): def get_server_resources(return_presence=False, return_server=False, **kwargs):
if not return_presence: if not return_presence:
logger.info(u"Tautulli PlexTV :: Requesting resources for server...") logger.info("Tautulli PlexTV :: Requesting resources for server...")
server = {'pms_name': plexpy.CONFIG.PMS_NAME, server = {'pms_name': plexpy.CONFIG.PMS_NAME,
'pms_version': plexpy.CONFIG.PMS_VERSION, 'pms_version': plexpy.CONFIG.PMS_VERSION,
@ -97,17 +97,17 @@ def get_server_resources(return_presence=False, return_server=False, **kwargs):
conn = next((c for c in conns if c['address'] == server['pms_ip'] conn = next((c for c in conns if c['address'] == server['pms_ip']
and c['port'] == str(server['pms_port'])), conns[0]) and c['port'] == str(server['pms_port'])), conns[0])
server['pms_url'] = conn['uri'] server['pms_url'] = conn['uri']
logger.info(u"Tautulli PlexTV :: Server URL retrieved.") logger.info("Tautulli PlexTV :: Server URL retrieved.")
# get_server_urls() failed or PMS_URL not found, fallback url doesn't use SSL # get_server_urls() failed or PMS_URL not found, fallback url doesn't use SSL
if not server['pms_url']: if not server['pms_url']:
server['pms_url'] = fallback_url server['pms_url'] = fallback_url
logger.warn(u"Tautulli PlexTV :: Unable to retrieve server URLs. Using user-defined value without SSL.") logger.warn("Tautulli PlexTV :: Unable to retrieve server URLs. Using user-defined value without SSL.")
# Not using SSL, remote has no effect # Not using SSL, remote has no effect
else: else:
server['pms_url'] = fallback_url server['pms_url'] = fallback_url
logger.info(u"Tautulli PlexTV :: Using user-defined URL.") logger.info("Tautulli PlexTV :: Using user-defined URL.")
if return_server: if return_server:
return server return server
@ -141,7 +141,7 @@ class PlexTV(object):
self.token = plexpy.CONFIG.PMS_TOKEN self.token = plexpy.CONFIG.PMS_TOKEN
if not self.token: if not self.token:
logger.error(u"Tautulli PlexTV :: PlexTV called, but no token provided.") logger.error("Tautulli PlexTV :: PlexTV called, but no token provided.")
return return
self.request_handler = http_handler.HTTPHandler(urls=self.urls, self.request_handler = http_handler.HTTPHandler(urls=self.urls,
@ -175,9 +175,9 @@ class PlexTV(object):
'user_id': xml_head[0].getAttribute('id') 'user_id': xml_head[0].getAttribute('id')
} }
else: else:
logger.warn(u"Tautulli PlexTV :: Could not get Plex authentication token.") logger.warn("Tautulli PlexTV :: Could not get Plex authentication token.")
except Exception as e: except Exception as e:
logger.warn(u"Tautulli PlexTV :: Unable to parse XML for get_token: %s." % e) logger.warn("Tautulli PlexTV :: Unable to parse XML for get_token: %s." % e)
return None return None
return user return user
@ -186,27 +186,27 @@ class PlexTV(object):
def get_plexpy_pms_token(self, force=False): def get_plexpy_pms_token(self, force=False):
if force: if force:
logger.debug(u"Tautulli PlexTV :: Forcing refresh of Plex.tv token.") logger.debug("Tautulli PlexTV :: Forcing refresh of Plex.tv token.")
devices_list = self.get_devices_list() devices_list = self.get_devices_list()
device_id = next((d for d in devices_list if d['device_identifier'] == plexpy.CONFIG.PMS_UUID), {}).get('device_id', None) device_id = next((d for d in devices_list if d['device_identifier'] == plexpy.CONFIG.PMS_UUID), {}).get('device_id', None)
if device_id: if device_id:
logger.debug(u"Tautulli PlexTV :: Removing Tautulli from Plex.tv devices.") logger.debug("Tautulli PlexTV :: Removing Tautulli from Plex.tv devices.")
try: try:
self.delete_plextv_device(device_id=device_id) self.delete_plextv_device(device_id=device_id)
except: except:
logger.error(u"Tautulli PlexTV :: Failed to remove Tautulli from Plex.tv devices.") logger.error("Tautulli PlexTV :: Failed to remove Tautulli from Plex.tv devices.")
return None return None
else: else:
logger.warn(u"Tautulli PlexTV :: No existing Tautulli device found.") logger.warn("Tautulli PlexTV :: No existing Tautulli device found.")
logger.info(u"Tautulli PlexTV :: Fetching a new Plex.tv token for Tautulli.") logger.info("Tautulli PlexTV :: Fetching a new Plex.tv token for Tautulli.")
user = self.get_token() user = self.get_token()
if user: if user:
token = user['auth_token'] token = user['auth_token']
plexpy.CONFIG.__setattr__('PMS_TOKEN', token) plexpy.CONFIG.__setattr__('PMS_TOKEN', token)
plexpy.CONFIG.write() plexpy.CONFIG.write()
logger.info(u"Tautulli PlexTV :: Updated Plex.tv token for Tautulli.") logger.info("Tautulli PlexTV :: Updated Plex.tv token for Tautulli.")
return token return token
@ -217,7 +217,7 @@ class PlexTV(object):
try: try:
xml_head = servers.getElementsByTagName('Device') xml_head = servers.getElementsByTagName('Device')
except Exception as e: except Exception as e:
logger.warn(u"Tautulli PlexTV :: Unable to parse XML for get_server_token: %s." % e) logger.warn("Tautulli PlexTV :: Unable to parse XML for get_server_token: %s." % e)
return None return None
for a in xml_head: for a in xml_head:
@ -257,11 +257,11 @@ class PlexTV(object):
} }
return pin return pin
else: else:
logger.warn(u"Tautulli PlexTV :: Could not get Plex authentication pin.") logger.warn("Tautulli PlexTV :: Could not get Plex authentication pin.")
return None return None
except Exception as e: except Exception as e:
logger.warn(u"Tautulli PlexTV :: Unable to parse XML for get_pin: %s." % e) logger.warn("Tautulli PlexTV :: Unable to parse XML for get_pin: %s." % e)
return None return None
else: else:
@ -388,7 +388,7 @@ class PlexTV(object):
try: try:
xml_head = own_account.getElementsByTagName('user') xml_head = own_account.getElementsByTagName('user')
except Exception as e: except Exception as e:
logger.warn(u"Tautulli PlexTV :: Unable to parse own account XML for get_full_users_list: %s." % e) logger.warn("Tautulli PlexTV :: Unable to parse own account XML for get_full_users_list: %s." % e)
return [] return []
for a in xml_head: for a in xml_head:
@ -415,7 +415,7 @@ class PlexTV(object):
try: try:
xml_head = friends_list.getElementsByTagName('User') xml_head = friends_list.getElementsByTagName('User')
except Exception as e: except Exception as e:
logger.warn(u"Tautulli PlexTV :: Unable to parse friends list XML for get_full_users_list: %s." % e) logger.warn("Tautulli PlexTV :: Unable to parse friends list XML for get_full_users_list: %s." % e)
return [] return []
for a in xml_head: for a in xml_head:
@ -439,7 +439,7 @@ class PlexTV(object):
try: try:
xml_head = shared_servers.getElementsByTagName('SharedServer') xml_head = shared_servers.getElementsByTagName('SharedServer')
except Exception as e: except Exception as e:
logger.warn(u"Tautulli PlexTV :: Unable to parse shared server list XML for get_full_users_list: %s." % e) logger.warn("Tautulli PlexTV :: Unable to parse shared server list XML for get_full_users_list: %s." % e)
return [] return []
user_map = {} user_map = {}
@ -484,7 +484,7 @@ class PlexTV(object):
try: try:
xml_head = sync_list.getElementsByTagName('SyncList') xml_head = sync_list.getElementsByTagName('SyncList')
except Exception as e: except Exception as e:
logger.warn(u"Tautulli PlexTV :: Unable to parse XML for get_synced_items: %s." % e) logger.warn("Tautulli PlexTV :: Unable to parse XML for get_synced_items: %s." % e)
return {} return {}
for a in xml_head: for a in xml_head:
@ -596,13 +596,13 @@ class PlexTV(object):
return session.filter_session_info(synced_items, filter_key='user_id') return session.filter_session_info(synced_items, filter_key='user_id')
def delete_sync(self, client_id, sync_id): def delete_sync(self, client_id, sync_id):
logger.info(u"Tautulli PlexTV :: Deleting sync item '%s'." % sync_id) logger.info("Tautulli PlexTV :: Deleting sync item '%s'." % sync_id)
self.delete_plextv_sync(client_id=client_id, sync_id=sync_id) self.delete_plextv_sync(client_id=client_id, sync_id=sync_id)
def get_server_connections(self, pms_identifier='', pms_ip='', pms_port=32400, include_https=True): def get_server_connections(self, pms_identifier='', pms_ip='', pms_port=32400, include_https=True):
if not pms_identifier: if not pms_identifier:
logger.error(u"Tautulli PlexTV :: Unable to retrieve server connections: no pms_identifier provided.") logger.error("Tautulli PlexTV :: Unable to retrieve server connections: no pms_identifier provided.")
return {} return {}
plextv_resources = self.get_plextv_resources(include_https=include_https, plextv_resources = self.get_plextv_resources(include_https=include_https,
@ -610,7 +610,7 @@ class PlexTV(object):
try: try:
xml_head = plextv_resources.getElementsByTagName('Device') xml_head = plextv_resources.getElementsByTagName('Device')
except Exception as e: except Exception as e:
logger.warn(u"Tautulli PlexTV :: Unable to parse XML for get_server_urls: %s." % e) logger.warn("Tautulli PlexTV :: Unable to parse XML for get_server_urls: %s." % e)
return {} return {}
# Function to get all connections for a device # Function to get all connections for a device
@ -671,7 +671,7 @@ class PlexTV(object):
try: try:
xml_head = servers.getElementsByTagName('Server') xml_head = servers.getElementsByTagName('Server')
except Exception as e: except Exception as e:
logger.warn(u"Tautulli PlexTV :: Unable to parse XML for get_server_times: %s." % e) logger.warn("Tautulli PlexTV :: Unable to parse XML for get_server_times: %s." % e)
return {} return {}
for a in xml_head: for a in xml_head:
@ -713,7 +713,7 @@ class PlexTV(object):
try: try:
xml_head = servers.getElementsByTagName('MediaContainer') xml_head = servers.getElementsByTagName('MediaContainer')
except Exception as e: except Exception as e:
logger.warn(u"Tautulli PlexTV :: Failed to get servers from plex: %s." % e) logger.warn("Tautulli PlexTV :: Failed to get servers from plex: %s." % e)
return [] return []
for a in xml_head: for a in xml_head:
@ -773,20 +773,20 @@ class PlexTV(object):
return clean_servers return clean_servers
def get_plex_downloads(self): def get_plex_downloads(self):
logger.debug(u"Tautulli PlexTV :: Retrieving current server version.") logger.debug("Tautulli PlexTV :: Retrieving current server version.")
pms_connect = pmsconnect.PmsConnect() pms_connect = pmsconnect.PmsConnect()
pms_connect.set_server_version() pms_connect.set_server_version()
update_channel = pms_connect.get_server_update_channel() update_channel = pms_connect.get_server_update_channel()
logger.debug(u"Tautulli PlexTV :: Plex update channel is %s." % update_channel) logger.debug("Tautulli PlexTV :: Plex update channel is %s." % update_channel)
plex_downloads = self.get_plextv_downloads(plexpass=(update_channel == 'beta')) plex_downloads = self.get_plextv_downloads(plexpass=(update_channel == 'beta'))
try: try:
available_downloads = json.loads(plex_downloads) available_downloads = json.loads(plex_downloads)
except Exception as e: except Exception as e:
logger.warn(u"Tautulli PlexTV :: Unable to load JSON for get_plex_updates.") logger.warn("Tautulli PlexTV :: Unable to load JSON for get_plex_updates.")
return {} return {}
# Get the updates for the platform # Get the updates for the platform
@ -795,7 +795,7 @@ class PlexTV(object):
available_downloads.get('nas').get(pms_platform) available_downloads.get('nas').get(pms_platform)
if not platform_downloads: if not platform_downloads:
logger.error(u"Tautulli PlexTV :: Unable to retrieve Plex updates: Could not match server platform: %s." logger.error("Tautulli PlexTV :: Unable to retrieve Plex updates: Could not match server platform: %s."
% pms_platform) % pms_platform)
return {} return {}
@ -803,11 +803,11 @@ class PlexTV(object):
v_new = helpers.cast_to_int("".join(v.zfill(4) for v in platform_downloads.get('version', '').split('-')[0].split('.')[:4])) v_new = helpers.cast_to_int("".join(v.zfill(4) for v in platform_downloads.get('version', '').split('-')[0].split('.')[:4]))
if not v_old: if not v_old:
logger.error(u"Tautulli PlexTV :: Unable to retrieve Plex updates: Invalid current server version: %s." logger.error("Tautulli PlexTV :: Unable to retrieve Plex updates: Invalid current server version: %s."
% plexpy.CONFIG.PMS_VERSION) % plexpy.CONFIG.PMS_VERSION)
return {} return {}
if not v_new: if not v_new:
logger.error(u"Tautulli PlexTV :: Unable to retrieve Plex updates: Invalid new server version: %s." logger.error("Tautulli PlexTV :: Unable to retrieve Plex updates: Invalid new server version: %s."
% platform_downloads.get('version')) % platform_downloads.get('version'))
return {} return {}
@ -838,7 +838,7 @@ class PlexTV(object):
try: try:
subscription = account_data.getElementsByTagName('subscription') subscription = account_data.getElementsByTagName('subscription')
except Exception as e: except Exception as e:
logger.warn(u"Tautulli PlexTV :: Unable to parse XML for get_plexpass_status: %s." % e) logger.warn("Tautulli PlexTV :: Unable to parse XML for get_plexpass_status: %s." % e)
return False return False
if subscription and helpers.get_xml_attr(subscription[0], 'active') == '1': if subscription and helpers.get_xml_attr(subscription[0], 'active') == '1':
@ -846,7 +846,7 @@ class PlexTV(object):
plexpy.CONFIG.write() plexpy.CONFIG.write()
return True return True
else: else:
logger.debug(u"Tautulli PlexTV :: Plex Pass subscription not found.") logger.debug("Tautulli PlexTV :: Plex Pass subscription not found.")
plexpy.CONFIG.__setattr__('PMS_PLEXPASS', 0) plexpy.CONFIG.__setattr__('PMS_PLEXPASS', 0)
plexpy.CONFIG.write() plexpy.CONFIG.write()
return False return False
@ -857,7 +857,7 @@ class PlexTV(object):
try: try:
xml_head = devices.getElementsByTagName('Device') xml_head = devices.getElementsByTagName('Device')
except Exception as e: except Exception as e:
logger.warn(u"Tautulli PlexTV :: Unable to parse XML for get_devices_list: %s." % e) logger.warn("Tautulli PlexTV :: Unable to parse XML for get_devices_list: %s." % e)
return [] return []
devices_list = [] devices_list = []
@ -885,7 +885,7 @@ class PlexTV(object):
try: try:
status_info = cloud_status.getElementsByTagName('info') status_info = cloud_status.getElementsByTagName('info')
except Exception as e: except Exception as e:
logger.warn(u"Tautulli PlexTV :: Unable to parse XML for get_cloud_server_status: %s." % e) logger.warn("Tautulli PlexTV :: Unable to parse XML for get_cloud_server_status: %s." % e)
return False return False
for info in status_info: for info in status_info:
@ -903,7 +903,7 @@ class PlexTV(object):
try: try:
xml_head = account_data.getElementsByTagName('user') xml_head = account_data.getElementsByTagName('user')
except Exception as e: except Exception as e:
logger.warn(u"Tautulli PlexTV :: Unable to parse XML for get_plex_account_details: %s." % e) logger.warn("Tautulli PlexTV :: Unable to parse XML for get_plex_account_details: %s." % e)
return None return None
for a in xml_head: for a in xml_head:

View file

@ -31,12 +31,12 @@ def extract_plexwatch_xml(xml=None):
try: try:
xml_parse = minidom.parseString(clean_xml) xml_parse = minidom.parseString(clean_xml)
except: except:
logger.warn(u"Tautulli Importer :: Error parsing XML for PlexWatch database.") logger.warn("Tautulli Importer :: Error parsing XML for PlexWatch database.")
return None return None
xml_head = xml_parse.getElementsByTagName('opt') xml_head = xml_parse.getElementsByTagName('opt')
if not xml_head: if not xml_head:
logger.warn(u"Tautulli Importer :: Error parsing XML for PlexWatch database.") logger.warn("Tautulli Importer :: Error parsing XML for PlexWatch database.")
return None return None
for a in xml_head: for a in xml_head:
@ -230,23 +230,23 @@ def validate_database(database=None, table_name=None):
try: try:
connection = sqlite3.connect(database, timeout=20) connection = sqlite3.connect(database, timeout=20)
except sqlite3.OperationalError: except sqlite3.OperationalError:
logger.error(u"Tautulli Importer :: Invalid database specified.") logger.error("Tautulli Importer :: Invalid database specified.")
return 'Invalid database specified.' return 'Invalid database specified.'
except ValueError: except ValueError:
logger.error(u"Tautulli Importer :: Invalid database specified.") logger.error("Tautulli Importer :: Invalid database specified.")
return 'Invalid database specified.' return 'Invalid database specified.'
except: except:
logger.error(u"Tautulli Importer :: Uncaught exception.") logger.error("Tautulli Importer :: Uncaught exception.")
return 'Uncaught exception.' return 'Uncaught exception.'
try: try:
connection.execute('SELECT ratingKey from %s' % table_name) connection.execute('SELECT ratingKey from %s' % table_name)
connection.close() connection.close()
except sqlite3.OperationalError: except sqlite3.OperationalError:
logger.error(u"Tautulli Importer :: Invalid database specified.") logger.error("Tautulli Importer :: Invalid database specified.")
return 'Invalid database specified.' return 'Invalid database specified.'
except: except:
logger.error(u"Tautulli Importer :: Uncaught exception.") logger.error("Tautulli Importer :: Uncaught exception.")
return 'Uncaught exception.' return 'Uncaught exception.'
return 'success' return 'success'
@ -257,19 +257,19 @@ def import_from_plexwatch(database=None, table_name=None, import_ignore_interval
connection = sqlite3.connect(database, timeout=20) connection = sqlite3.connect(database, timeout=20)
connection.row_factory = sqlite3.Row connection.row_factory = sqlite3.Row
except sqlite3.OperationalError: except sqlite3.OperationalError:
logger.error(u"Tautulli Importer :: Invalid filename.") logger.error("Tautulli Importer :: Invalid filename.")
return None return None
except ValueError: except ValueError:
logger.error(u"Tautulli Importer :: Invalid filename.") logger.error("Tautulli Importer :: Invalid filename.")
return None return None
try: try:
connection.execute('SELECT ratingKey from %s' % table_name) connection.execute('SELECT ratingKey from %s' % table_name)
except sqlite3.OperationalError: except sqlite3.OperationalError:
logger.error(u"Tautulli Importer :: Database specified does not contain the required fields.") logger.error("Tautulli Importer :: Database specified does not contain the required fields.")
return None return None
logger.debug(u"Tautulli Importer :: PlexWatch data import in progress...") logger.debug("Tautulli Importer :: PlexWatch data import in progress...")
ap = activity_processor.ActivityProcessor() ap = activity_processor.ActivityProcessor()
user_data = users.Users() user_data = users.Users()
@ -278,7 +278,7 @@ def import_from_plexwatch(database=None, table_name=None, import_ignore_interval
try: try:
users.refresh_users() users.refresh_users()
except: except:
logger.debug(u"Tautulli Importer :: Unable to refresh the users list. Aborting import.") logger.debug("Tautulli Importer :: Unable to refresh the users list. Aborting import.")
return None return None
query = 'SELECT time AS started, ' \ query = 'SELECT time AS started, ' \
@ -313,13 +313,13 @@ def import_from_plexwatch(database=None, table_name=None, import_ignore_interval
# If we get back None from our xml extractor skip over the record and log error. # If we get back None from our xml extractor skip over the record and log error.
if not extracted_xml: if not extracted_xml:
logger.error(u"Tautulli Importer :: Skipping record with ratingKey %s due to malformed xml." logger.error("Tautulli Importer :: Skipping record with ratingKey %s due to malformed xml."
% str(row['rating_key'])) % str(row['rating_key']))
continue continue
# Skip line if we don't have a ratingKey to work with # Skip line if we don't have a ratingKey to work with
if not row['rating_key']: if not row['rating_key']:
logger.error(u"Tautulli Importer :: Skipping record due to null ratingKey.") logger.error("Tautulli Importer :: Skipping record due to null ratingKey.")
continue continue
# If the user_id no longer exists in the friends list, pull it from the xml. # If the user_id no longer exists in the friends list, pull it from the xml.
@ -423,13 +423,13 @@ def import_from_plexwatch(database=None, table_name=None, import_ignore_interval
is_import=True, is_import=True,
import_ignore_interval=import_ignore_interval) import_ignore_interval=import_ignore_interval)
else: else:
logger.debug(u"Tautulli Importer :: Item has bad rating_key: %s" % session_history_metadata['rating_key']) logger.debug("Tautulli Importer :: Item has bad rating_key: %s" % session_history_metadata['rating_key'])
logger.debug(u"Tautulli Importer :: PlexWatch data import complete.") logger.debug("Tautulli Importer :: PlexWatch data import complete.")
import_users() import_users()
def import_users(): def import_users():
logger.debug(u"Tautulli Importer :: Importing PlexWatch Users...") logger.debug("Tautulli Importer :: Importing PlexWatch Users...")
monitor_db = database.MonitorDatabase() monitor_db = database.MonitorDatabase()
query = 'INSERT OR IGNORE INTO users (user_id, username) ' \ query = 'INSERT OR IGNORE INTO users (user_id, username) ' \
@ -438,6 +438,6 @@ def import_users():
try: try:
monitor_db.action(query) monitor_db.action(query)
logger.debug(u"Tautulli Importer :: Users imported.") logger.debug("Tautulli Importer :: Users imported.")
except: except:
logger.debug(u"Tautulli Importer :: Failed to import users.") logger.debug("Tautulli Importer :: Failed to import users.")

View file

@ -30,7 +30,7 @@ import users
def get_server_friendly_name(): def get_server_friendly_name():
logger.info(u"Tautulli Pmsconnect :: Requesting name from server...") logger.info("Tautulli Pmsconnect :: Requesting name from server...")
server_name = PmsConnect().get_server_pref(pref='FriendlyName') server_name = PmsConnect().get_server_pref(pref='FriendlyName')
# If friendly name is blank # If friendly name is blank
@ -44,7 +44,7 @@ def get_server_friendly_name():
if server_name and server_name != plexpy.CONFIG.PMS_NAME: if server_name and server_name != plexpy.CONFIG.PMS_NAME:
plexpy.CONFIG.__setattr__('PMS_NAME', server_name) plexpy.CONFIG.__setattr__('PMS_NAME', server_name)
plexpy.CONFIG.write() plexpy.CONFIG.write()
logger.info(u"Tautulli Pmsconnect :: Server name retrieved.") logger.info("Tautulli Pmsconnect :: Server name retrieved.")
return server_name return server_name
@ -474,7 +474,7 @@ class PmsConnect(object):
try: try:
xml_head = recent.getElementsByTagName('MediaContainer') xml_head = recent.getElementsByTagName('MediaContainer')
except Exception as e: except Exception as e:
logger.warn(u"Tautulli Pmsconnect :: Unable to parse XML for get_recently_added: %s." % e) logger.warn("Tautulli Pmsconnect :: Unable to parse XML for get_recently_added: %s." % e)
return [] return []
for a in xml_head: for a in xml_head:
@ -610,7 +610,7 @@ class PmsConnect(object):
try: try:
xml_head = metadata_xml.getElementsByTagName('MediaContainer') xml_head = metadata_xml.getElementsByTagName('MediaContainer')
except Exception as e: except Exception as e:
logger.warn(u"Tautulli Pmsconnect :: Unable to parse XML for get_metadata_details: %s." % e) logger.warn("Tautulli Pmsconnect :: Unable to parse XML for get_metadata_details: %s." % e)
return {} return {}
for a in xml_head: for a in xml_head:
@ -627,7 +627,7 @@ class PmsConnect(object):
elif a.getElementsByTagName('Photo'): elif a.getElementsByTagName('Photo'):
metadata_main_list = a.getElementsByTagName('Photo') metadata_main_list = a.getElementsByTagName('Photo')
else: else:
logger.debug(u"Tautulli Pmsconnect :: Metadata failed") logger.debug("Tautulli Pmsconnect :: Metadata failed")
return {} return {}
if sync_id and len(metadata_main_list) > 1: if sync_id and len(metadata_main_list) > 1:
@ -819,7 +819,7 @@ class PmsConnect(object):
'genres': show_details['genres'], 'genres': show_details['genres'],
'labels': show_details['labels'], 'labels': show_details['labels'],
'collections': show_details['collections'], 'collections': show_details['collections'],
'full_title': u'{} - {}'.format(helpers.get_xml_attr(metadata_main, 'parentTitle'), 'full_title': '{} - {}'.format(helpers.get_xml_attr(metadata_main, 'parentTitle'),
helpers.get_xml_attr(metadata_main, 'title')), helpers.get_xml_attr(metadata_main, 'title')),
'children_count': helpers.get_xml_attr(metadata_main, 'leafCount') 'children_count': helpers.get_xml_attr(metadata_main, 'leafCount')
} }
@ -885,7 +885,7 @@ class PmsConnect(object):
'genres': show_details['genres'], 'genres': show_details['genres'],
'labels': show_details['labels'], 'labels': show_details['labels'],
'collections': show_details['collections'], 'collections': show_details['collections'],
'full_title': u'{} - {}'.format(helpers.get_xml_attr(metadata_main, 'grandparentTitle'), 'full_title': '{} - {}'.format(helpers.get_xml_attr(metadata_main, 'grandparentTitle'),
helpers.get_xml_attr(metadata_main, 'title')), helpers.get_xml_attr(metadata_main, 'title')),
'children_count': helpers.get_xml_attr(metadata_main, 'leafCount') 'children_count': helpers.get_xml_attr(metadata_main, 'leafCount')
} }
@ -982,7 +982,7 @@ class PmsConnect(object):
'genres': genres, 'genres': genres,
'labels': labels, 'labels': labels,
'collections': collections, 'collections': collections,
'full_title': u'{} - {}'.format(helpers.get_xml_attr(metadata_main, 'parentTitle'), 'full_title': '{} - {}'.format(helpers.get_xml_attr(metadata_main, 'parentTitle'),
helpers.get_xml_attr(metadata_main, 'title')), helpers.get_xml_attr(metadata_main, 'title')),
'children_count': helpers.get_xml_attr(metadata_main, 'leafCount') 'children_count': helpers.get_xml_attr(metadata_main, 'leafCount')
} }
@ -1034,7 +1034,7 @@ class PmsConnect(object):
'genres': album_details['genres'], 'genres': album_details['genres'],
'labels': album_details['labels'], 'labels': album_details['labels'],
'collections': album_details['collections'], 'collections': album_details['collections'],
'full_title': u'{} - {}'.format(helpers.get_xml_attr(metadata_main, 'title'), 'full_title': '{} - {}'.format(helpers.get_xml_attr(metadata_main, 'title'),
track_artist), track_artist),
'children_count': helpers.get_xml_attr(metadata_main, 'leafCount') 'children_count': helpers.get_xml_attr(metadata_main, 'leafCount')
} }
@ -1131,7 +1131,7 @@ class PmsConnect(object):
'genres': photo_album_details.get('genres', ''), 'genres': photo_album_details.get('genres', ''),
'labels': photo_album_details.get('labels', ''), 'labels': photo_album_details.get('labels', ''),
'collections': photo_album_details.get('collections', ''), 'collections': photo_album_details.get('collections', ''),
'full_title': u'{} - {}'.format(helpers.get_xml_attr(metadata_main, 'parentTitle') or library_name, 'full_title': '{} - {}'.format(helpers.get_xml_attr(metadata_main, 'parentTitle') or library_name,
helpers.get_xml_attr(metadata_main, 'title')), helpers.get_xml_attr(metadata_main, 'title')),
'children_count': helpers.get_xml_attr(metadata_main, 'leafCount') 'children_count': helpers.get_xml_attr(metadata_main, 'leafCount')
} }
@ -1355,7 +1355,7 @@ class PmsConnect(object):
with open(out_file_path, 'w') as outFile: with open(out_file_path, 'w') as outFile:
json.dump(metadata, outFile) json.dump(metadata, outFile)
except (IOError, ValueError) as e: except (IOError, ValueError) as e:
logger.error(u"Tautulli Pmsconnect :: Unable to create cache file for metadata (sessionKey %s): %s" logger.error("Tautulli Pmsconnect :: Unable to create cache file for metadata (sessionKey %s): %s"
% (cache_key, e)) % (cache_key, e))
return metadata return metadata
@ -1375,7 +1375,7 @@ class PmsConnect(object):
try: try:
xml_head = metadata.getElementsByTagName('MediaContainer') xml_head = metadata.getElementsByTagName('MediaContainer')
except Exception as e: except Exception as e:
logger.warn(u"Tautulli Pmsconnect :: Unable to parse XML for get_metadata_children: %s." % e) logger.warn("Tautulli Pmsconnect :: Unable to parse XML for get_metadata_children: %s." % e)
return [] return []
metadata_list = [] metadata_list = []
@ -1425,7 +1425,7 @@ class PmsConnect(object):
try: try:
xml_head = libraries_data.getElementsByTagName('MediaContainer') xml_head = libraries_data.getElementsByTagName('MediaContainer')
except Exception as e: except Exception as e:
logger.warn(u"Tautulli Pmsconnect :: Unable to parse XML for get_library_metadata_details: %s." % e) logger.warn("Tautulli Pmsconnect :: Unable to parse XML for get_library_metadata_details: %s." % e)
return [] return []
metadata_list = [] metadata_list = []
@ -1470,7 +1470,7 @@ class PmsConnect(object):
try: try:
xml_head = session_data.getElementsByTagName('MediaContainer') xml_head = session_data.getElementsByTagName('MediaContainer')
except Exception as e: except Exception as e:
logger.warn(u"Tautulli Pmsconnect :: Unable to parse XML for get_current_activity: %s." % e) logger.warn("Tautulli Pmsconnect :: Unable to parse XML for get_current_activity: %s." % e)
return [] return []
session_list = [] session_list = []
@ -2070,7 +2070,7 @@ class PmsConnect(object):
plex_tv = plextv.PlexTV() plex_tv = plextv.PlexTV()
if not plex_tv.get_plexpass_status(): if not plex_tv.get_plexpass_status():
msg = 'No Plex Pass subscription' msg = 'No Plex Pass subscription'
logger.warn(u"Tautulli Pmsconnect :: Failed to terminate session: %s." % msg) logger.warn("Tautulli Pmsconnect :: Failed to terminate session: %s." % msg)
return msg return msg
message = message.encode('utf-8') or 'The server owner has ended the stream.' message = message.encode('utf-8') or 'The server owner has ended the stream.'
@ -2092,16 +2092,16 @@ class PmsConnect(object):
if not session: if not session:
msg = 'Invalid session_key (%s) or session_id (%s)' % (session_key, session_id) msg = 'Invalid session_key (%s) or session_id (%s)' % (session_key, session_id)
logger.warn(u"Tautulli Pmsconnect :: Failed to terminate session: %s." % msg) logger.warn("Tautulli Pmsconnect :: Failed to terminate session: %s." % msg)
return msg return msg
if session_id: if session_id:
logger.info(u"Tautulli Pmsconnect :: Terminating session %s (session_id %s)." % (session_key, session_id)) logger.info("Tautulli Pmsconnect :: Terminating session %s (session_id %s)." % (session_key, session_id))
result = self.get_sessions_terminate(session_id=session_id, reason=message) result = self.get_sessions_terminate(session_id=session_id, reason=message)
return True return True
else: else:
msg = 'Missing session_id' msg = 'Missing session_id'
logger.warn(u"Tautulli Pmsconnect :: Failed to terminate session: %s." % msg) logger.warn("Tautulli Pmsconnect :: Failed to terminate session: %s." % msg)
return msg return msg
def get_item_children(self, rating_key='', get_grandchildren=False): def get_item_children(self, rating_key='', get_grandchildren=False):
@ -2118,7 +2118,7 @@ class PmsConnect(object):
try: try:
xml_head = children_data.getElementsByTagName('MediaContainer') xml_head = children_data.getElementsByTagName('MediaContainer')
except Exception as e: except Exception as e:
logger.warn(u"Tautulli Pmsconnect :: Unable to parse XML for get_item_children: %s." % e) logger.warn("Tautulli Pmsconnect :: Unable to parse XML for get_item_children: %s." % e)
return [] return []
children_list = [] children_list = []
@ -2126,7 +2126,7 @@ class PmsConnect(object):
for a in xml_head: for a in xml_head:
if a.getAttribute('size'): if a.getAttribute('size'):
if a.getAttribute('size') == '0': if a.getAttribute('size') == '0':
logger.debug(u"Tautulli Pmsconnect :: No children data.") logger.debug("Tautulli Pmsconnect :: No children data.")
children_list = {'children_count': '0', children_list = {'children_count': '0',
'children_list': [] 'children_list': []
} }
@ -2231,7 +2231,7 @@ class PmsConnect(object):
try: try:
xml_head = children_data.getElementsByTagName('MediaContainer') xml_head = children_data.getElementsByTagName('MediaContainer')
except Exception as e: except Exception as e:
logger.warn(u"Tautulli Pmsconnect :: Unable to parse XML for get_item_children_related: %s." % e) logger.warn("Tautulli Pmsconnect :: Unable to parse XML for get_item_children_related: %s." % e)
return [] return []
children_results_list = {'movie': [], children_results_list = {'movie': [],
@ -2297,7 +2297,7 @@ class PmsConnect(object):
try: try:
xml_head = recent.getElementsByTagName('Server') xml_head = recent.getElementsByTagName('Server')
except Exception as e: except Exception as e:
logger.warn(u"Tautulli Pmsconnect :: Unable to parse XML for get_server_list: %s." % e) logger.warn("Tautulli Pmsconnect :: Unable to parse XML for get_server_list: %s." % e)
return [] return []
server_info = [] server_info = []
@ -2324,7 +2324,7 @@ class PmsConnect(object):
try: try:
xml_head = identity.getElementsByTagName('MediaContainer') xml_head = identity.getElementsByTagName('MediaContainer')
except Exception as e: except Exception as e:
logger.warn(u"Tautulli Pmsconnect :: Unable to parse XML for get_local_server_identity: %s." % e) logger.warn("Tautulli Pmsconnect :: Unable to parse XML for get_local_server_identity: %s." % e)
return {} return {}
server_identity = {} server_identity = {}
@ -2349,7 +2349,7 @@ class PmsConnect(object):
try: try:
xml_head = prefs.getElementsByTagName('Setting') xml_head = prefs.getElementsByTagName('Setting')
except Exception as e: except Exception as e:
logger.warn(u"Tautulli Pmsconnect :: Unable to parse XML for get_local_server_name: %s." % e) logger.warn("Tautulli Pmsconnect :: Unable to parse XML for get_local_server_name: %s." % e)
return '' return ''
pref_value = 'None' pref_value = 'None'
@ -2360,7 +2360,7 @@ class PmsConnect(object):
return pref_value return pref_value
else: else:
logger.debug(u"Tautulli Pmsconnect :: Server preferences queried but no parameter received.") logger.debug("Tautulli Pmsconnect :: Server preferences queried but no parameter received.")
return None return None
def get_server_children(self): def get_server_children(self):
@ -2374,7 +2374,7 @@ class PmsConnect(object):
try: try:
xml_head = libraries_data.getElementsByTagName('MediaContainer') xml_head = libraries_data.getElementsByTagName('MediaContainer')
except Exception as e: except Exception as e:
logger.warn(u"Tautulli Pmsconnect :: Unable to parse XML for get_libraries_list: %s." % e) logger.warn("Tautulli Pmsconnect :: Unable to parse XML for get_libraries_list: %s." % e)
return [] return []
libraries_list = [] libraries_list = []
@ -2382,7 +2382,7 @@ class PmsConnect(object):
for a in xml_head: for a in xml_head:
if a.getAttribute('size'): if a.getAttribute('size'):
if a.getAttribute('size') == '0': if a.getAttribute('size') == '0':
logger.debug(u"Tautulli Pmsconnect :: No libraries data.") logger.debug("Tautulli Pmsconnect :: No libraries data.")
libraries_list = {'libraries_count': '0', libraries_list = {'libraries_count': '0',
'libraries_list': [] 'libraries_list': []
} }
@ -2448,13 +2448,13 @@ class PmsConnect(object):
elif str(rating_key).isdigit(): elif str(rating_key).isdigit():
library_data = self.get_metadata_children(str(rating_key), output_format='xml') library_data = self.get_metadata_children(str(rating_key), output_format='xml')
else: else:
logger.warn(u"Tautulli Pmsconnect :: get_library_children called by invalid section_id or rating_key provided.") logger.warn("Tautulli Pmsconnect :: get_library_children called by invalid section_id or rating_key provided.")
return [] return []
try: try:
xml_head = library_data.getElementsByTagName('MediaContainer') xml_head = library_data.getElementsByTagName('MediaContainer')
except Exception as e: except Exception as e:
logger.warn(u"Tautulli Pmsconnect :: Unable to parse XML for get_library_children_details: %s." % e) logger.warn("Tautulli Pmsconnect :: Unable to parse XML for get_library_children_details: %s." % e)
return [] return []
children_list = [] children_list = []
@ -2462,7 +2462,7 @@ class PmsConnect(object):
for a in xml_head: for a in xml_head:
if a.getAttribute('size'): if a.getAttribute('size'):
if a.getAttribute('size') == '0': if a.getAttribute('size') == '0':
logger.debug(u"Tautulli Pmsconnect :: No library data.") logger.debug("Tautulli Pmsconnect :: No library data.")
children_list = {'library_count': '0', children_list = {'library_count': '0',
'children_list': [] 'children_list': []
} }
@ -2604,7 +2604,7 @@ class PmsConnect(object):
try: try:
xml_head = labels_data.getElementsByTagName('MediaContainer') xml_head = labels_data.getElementsByTagName('MediaContainer')
except Exception as e: except Exception as e:
logger.warn(u"Tautulli Pmsconnect :: Unable to parse XML for get_library_label_details: %s." % e) logger.warn("Tautulli Pmsconnect :: Unable to parse XML for get_library_label_details: %s." % e)
return None return None
labels_list = [] labels_list = []
@ -2612,7 +2612,7 @@ class PmsConnect(object):
for a in xml_head: for a in xml_head:
if a.getAttribute('size'): if a.getAttribute('size'):
if a.getAttribute('size') == '0': if a.getAttribute('size') == '0':
logger.debug(u"Tautulli Pmsconnect :: No labels data.") logger.debug("Tautulli Pmsconnect :: No labels data.")
return labels_list return labels_list
if a.getElementsByTagName('Directory'): if a.getElementsByTagName('Directory'):
@ -2674,7 +2674,7 @@ class PmsConnect(object):
return result[0], result[1] return result[0], result[1]
else: else:
logger.error(u"Tautulli Pmsconnect :: Image proxy queried but no input received.") logger.error("Tautulli Pmsconnect :: Image proxy queried but no input received.")
def get_search_results(self, query='', limit=''): def get_search_results(self, query='', limit=''):
""" """
@ -2687,7 +2687,7 @@ class PmsConnect(object):
try: try:
xml_head = search_results.getElementsByTagName('MediaContainer') xml_head = search_results.getElementsByTagName('MediaContainer')
except Exception as e: except Exception as e:
logger.warn(u"Tautulli Pmsconnect :: Unable to parse XML for get_search_result: %s." % e) logger.warn("Tautulli Pmsconnect :: Unable to parse XML for get_search_result: %s." % e)
return [] return []
search_results_list = {'movie': [], search_results_list = {'movie': [],
@ -2770,7 +2770,7 @@ class PmsConnect(object):
section_id = metadata['section_id'] section_id = metadata['section_id']
library_name = metadata['library_name'] library_name = metadata['library_name']
except Exception as e: except Exception as e:
logger.warn(u"Tautulli Pmsconnect :: Unable to get parent_rating_key for get_rating_keys_list: %s." % e) logger.warn("Tautulli Pmsconnect :: Unable to get parent_rating_key for get_rating_keys_list: %s." % e)
return {} return {}
elif media_type == 'episode' or media_type == 'track': elif media_type == 'episode' or media_type == 'track':
@ -2780,7 +2780,7 @@ class PmsConnect(object):
section_id = metadata['section_id'] section_id = metadata['section_id']
library_name = metadata['library_name'] library_name = metadata['library_name']
except Exception as e: except Exception as e:
logger.warn(u"Tautulli Pmsconnect :: Unable to get grandparent_rating_key for get_rating_keys_list: %s." % e) logger.warn("Tautulli Pmsconnect :: Unable to get grandparent_rating_key for get_rating_keys_list: %s." % e)
return {} return {}
# get parent_rating_keys # get parent_rating_keys
@ -2789,7 +2789,7 @@ class PmsConnect(object):
try: try:
xml_head = metadata.getElementsByTagName('MediaContainer') xml_head = metadata.getElementsByTagName('MediaContainer')
except Exception as e: except Exception as e:
logger.warn(u"Tautulli Pmsconnect :: Unable to parse XML for get_rating_keys_list: %s." % e) logger.warn("Tautulli Pmsconnect :: Unable to parse XML for get_rating_keys_list: %s." % e)
return {} return {}
for a in xml_head: for a in xml_head:
@ -2817,7 +2817,7 @@ class PmsConnect(object):
try: try:
xml_head = metadata.getElementsByTagName('MediaContainer') xml_head = metadata.getElementsByTagName('MediaContainer')
except Exception as e: except Exception as e:
logger.warn(u"Tautulli Pmsconnect :: Unable to parse XML for get_rating_keys_list: %s." % e) logger.warn("Tautulli Pmsconnect :: Unable to parse XML for get_rating_keys_list: %s." % e)
return {} return {}
for a in xml_head: for a in xml_head:
@ -2865,7 +2865,7 @@ class PmsConnect(object):
try: try:
xml_head = account_data.getElementsByTagName('MyPlex') xml_head = account_data.getElementsByTagName('MyPlex')
except Exception as e: except Exception as e:
logger.warn(u"Tautulli Pmsconnect :: Unable to parse XML for get_server_response: %s." % e) logger.warn("Tautulli Pmsconnect :: Unable to parse XML for get_server_response: %s." % e)
return None return None
server_response = {} server_response = {}
@ -2887,13 +2887,13 @@ class PmsConnect(object):
try: try:
xml_head = updater_status.getElementsByTagName('MediaContainer') xml_head = updater_status.getElementsByTagName('MediaContainer')
except Exception as e: except Exception as e:
logger.warn(u"Tautulli Pmsconnect :: Unable to parse XML for get_update_staus: %s." % e) logger.warn("Tautulli Pmsconnect :: Unable to parse XML for get_update_staus: %s." % e)
# Catch the malformed XML on certain PMX version. # Catch the malformed XML on certain PMX version.
# XML parser helper returns empty list if there is an error parsing XML # XML parser helper returns empty list if there is an error parsing XML
if updater_status == []: if updater_status == []:
logger.warn(u"Plex API updater XML is broken on the current PMS version. Please update your PMS manually.") logger.warn("Plex API updater XML is broken on the current PMS version. Please update your PMS manually.")
logger.info(u"Tautulli is unable to check for Plex updates. Disabling check for Plex updates.") logger.info("Tautulli is unable to check for Plex updates. Disabling check for Plex updates.")
# Disable check for Plex updates # Disable check for Plex updates
plexpy.CONFIG.MONITOR_PMS_UPDATES = 0 plexpy.CONFIG.MONITOR_PMS_UPDATES = 0

View file

@ -28,7 +28,7 @@ import session
def refresh_users(): def refresh_users():
logger.info(u"Tautulli Users :: Requesting users list refresh...") logger.info("Tautulli Users :: Requesting users list refresh...")
result = plextv.PlexTV().get_full_users_list() result = plextv.PlexTV().get_full_users_list()
if result: if result:
@ -58,10 +58,10 @@ def refresh_users():
monitor_db.upsert('users', item, keys_dict) monitor_db.upsert('users', item, keys_dict)
logger.info(u"Tautulli Users :: Users list refreshed.") logger.info("Tautulli Users :: Users list refreshed.")
return True return True
else: else:
logger.warn(u"Tautulli Users :: Unable to refresh users list.") logger.warn("Tautulli Users :: Unable to refresh users list.")
return False return False
@ -137,7 +137,7 @@ class Users(object):
['session_history.id', 'session_history_media_info.id']], ['session_history.id', 'session_history_media_info.id']],
kwargs=kwargs) kwargs=kwargs)
except Exception as e: except Exception as e:
logger.warn(u"Tautulli Users :: Unable to execute database query for get_list: %s." % e) logger.warn("Tautulli Users :: Unable to execute database query for get_list: %s." % e)
return default_return return default_return
users = query['result'] users = query['result']
@ -248,7 +248,7 @@ class Users(object):
['session_history.id', 'session_history_media_info.id']], ['session_history.id', 'session_history_media_info.id']],
kwargs=kwargs) kwargs=kwargs)
except Exception as e: except Exception as e:
logger.warn(u"Tautulli Users :: Unable to execute database query for get_unique_ips: %s." % e) logger.warn("Tautulli Users :: Unable to execute database query for get_unique_ips: %s." % e)
return default_return return default_return
results = query['result'] results = query['result']
@ -308,7 +308,7 @@ class Users(object):
try: try:
monitor_db.upsert('users', value_dict, key_dict) monitor_db.upsert('users', value_dict, key_dict)
except Exception as e: except Exception as e:
logger.warn(u"Tautulli Users :: Unable to execute database query for set_config: %s." % e) logger.warn("Tautulli Users :: Unable to execute database query for set_config: %s." % e)
def get_details(self, user_id=None, user=None, email=None): def get_details(self, user_id=None, user=None, email=None):
default_return = {'user_id': 0, default_return = {'user_id': 0,
@ -358,7 +358,7 @@ class Users(object):
else: else:
result = [] result = []
except Exception as e: except Exception as e:
logger.warn(u"Tautulli Users :: Unable to execute database query for get_details: %s." % e) logger.warn("Tautulli Users :: Unable to execute database query for get_details: %s." % e)
result = [] result = []
user_details = {} user_details = {}
@ -403,7 +403,7 @@ class Users(object):
return user_details return user_details
else: else:
logger.warn(u"Tautulli Users :: Unable to retrieve user %s from database. Requesting user list refresh." logger.warn("Tautulli Users :: Unable to retrieve user %s from database. Requesting user list refresh."
% user_id if user_id else user) % user_id if user_id else user)
# Let's first refresh the user list to make sure the user isn't newly added and not in the db yet # Let's first refresh the user list to make sure the user isn't newly added and not in the db yet
refresh_users() refresh_users()
@ -414,7 +414,7 @@ class Users(object):
return user_details return user_details
else: else:
logger.warn(u"Tautulli Users :: Unable to retrieve user %s from database. Returning 'Local' user." logger.warn("Tautulli Users :: Unable to retrieve user %s from database. Returning 'Local' user."
% user_id if user_id else user) % user_id if user_id else user)
# If there is no user data we must return something # If there is no user data we must return something
# Use "Local" user to retain compatibility with PlexWatch database value # Use "Local" user to retain compatibility with PlexWatch database value
@ -458,7 +458,7 @@ class Users(object):
else: else:
result = [] result = []
except Exception as e: except Exception as e:
logger.warn(u"Tautulli Users :: Unable to execute database query for get_watch_time_stats: %s." % e) logger.warn("Tautulli Users :: Unable to execute database query for get_watch_time_stats: %s." % e)
result = [] result = []
for item in result: for item in result:
@ -503,7 +503,7 @@ class Users(object):
else: else:
result = [] result = []
except Exception as e: except Exception as e:
logger.warn(u"Tautulli Users :: Unable to execute database query for get_player_stats: %s." % e) logger.warn("Tautulli Users :: Unable to execute database query for get_player_stats: %s." % e)
result = [] result = []
for item in result: for item in result:
@ -549,7 +549,7 @@ class Users(object):
else: else:
result = [] result = []
except Exception as e: except Exception as e:
logger.warn(u"Tautulli Users :: Unable to execute database query for get_recently_watched: %s." % e) logger.warn("Tautulli Users :: Unable to execute database query for get_recently_watched: %s." % e)
result = [] result = []
for row in result: for row in result:
@ -591,7 +591,7 @@ class Users(object):
'FROM users WHERE deleted_user = 0' 'FROM users WHERE deleted_user = 0'
result = monitor_db.select(query=query) result = monitor_db.select(query=query)
except Exception as e: except Exception as e:
logger.warn(u"Tautulli Users :: Unable to execute database query for get_users: %s." % e) logger.warn("Tautulli Users :: Unable to execute database query for get_users: %s." % e)
return None return None
users = [] users = []
@ -625,7 +625,7 @@ class Users(object):
try: try:
if str(user_id).isdigit(): if str(user_id).isdigit():
logger.info(u"Tautulli Users :: Deleting all history for user id %s from database." % user_id) logger.info("Tautulli Users :: Deleting all history for user id %s from database." % user_id)
session_history_media_info_del = \ session_history_media_info_del = \
monitor_db.action('DELETE FROM ' monitor_db.action('DELETE FROM '
'session_history_media_info ' 'session_history_media_info '
@ -649,7 +649,7 @@ class Users(object):
else: else:
return 'Unable to delete items. Input user_id not valid.' return 'Unable to delete items. Input user_id not valid.'
except Exception as e: except Exception as e:
logger.warn(u"Tautulli Users :: Unable to execute database query for delete_all_history: %s." % e) logger.warn("Tautulli Users :: Unable to execute database query for delete_all_history: %s." % e)
def delete(self, user_id=None): def delete(self, user_id=None):
monitor_db = database.MonitorDatabase() monitor_db = database.MonitorDatabase()
@ -657,7 +657,7 @@ class Users(object):
try: try:
if str(user_id).isdigit(): if str(user_id).isdigit():
self.delete_all_history(user_id) self.delete_all_history(user_id)
logger.info(u"Tautulli Users :: Deleting user with id %s from database." % user_id) logger.info("Tautulli Users :: Deleting user with id %s from database." % user_id)
monitor_db.action('UPDATE users SET deleted_user = 1 WHERE user_id = ?', [user_id]) monitor_db.action('UPDATE users SET deleted_user = 1 WHERE user_id = ?', [user_id])
monitor_db.action('UPDATE users SET keep_history = 0 WHERE user_id = ?', [user_id]) monitor_db.action('UPDATE users SET keep_history = 0 WHERE user_id = ?', [user_id])
monitor_db.action('UPDATE users SET do_notify = 0 WHERE user_id = ?', [user_id]) monitor_db.action('UPDATE users SET do_notify = 0 WHERE user_id = ?', [user_id])
@ -666,7 +666,7 @@ class Users(object):
else: else:
return 'Unable to delete user, user_id not valid.' return 'Unable to delete user, user_id not valid.'
except Exception as e: except Exception as e:
logger.warn(u"Tautulli Users :: Unable to execute database query for delete: %s." % e) logger.warn("Tautulli Users :: Unable to execute database query for delete: %s." % e)
def undelete(self, user_id=None, username=None): def undelete(self, user_id=None, username=None):
monitor_db = database.MonitorDatabase() monitor_db = database.MonitorDatabase()
@ -676,7 +676,7 @@ class Users(object):
query = 'SELECT * FROM users WHERE user_id = ?' query = 'SELECT * FROM users WHERE user_id = ?'
result = monitor_db.select(query=query, args=[user_id]) result = monitor_db.select(query=query, args=[user_id])
if result: if result:
logger.info(u"Tautulli Users :: Re-adding user with id %s to database." % user_id) logger.info("Tautulli Users :: Re-adding user with id %s to database." % user_id)
monitor_db.action('UPDATE users SET deleted_user = 0 WHERE user_id = ?', [user_id]) monitor_db.action('UPDATE users SET deleted_user = 0 WHERE user_id = ?', [user_id])
monitor_db.action('UPDATE users SET keep_history = 1 WHERE user_id = ?', [user_id]) monitor_db.action('UPDATE users SET keep_history = 1 WHERE user_id = ?', [user_id])
monitor_db.action('UPDATE users SET do_notify = 1 WHERE user_id = ?', [user_id]) monitor_db.action('UPDATE users SET do_notify = 1 WHERE user_id = ?', [user_id])
@ -688,7 +688,7 @@ class Users(object):
query = 'SELECT * FROM users WHERE username = ?' query = 'SELECT * FROM users WHERE username = ?'
result = monitor_db.select(query=query, args=[username]) result = monitor_db.select(query=query, args=[username])
if result: if result:
logger.info(u"Tautulli Users :: Re-adding user with username %s to database." % username) logger.info("Tautulli Users :: Re-adding user with username %s to database." % username)
monitor_db.action('UPDATE users SET deleted_user = 0 WHERE username = ?', [username]) monitor_db.action('UPDATE users SET deleted_user = 0 WHERE username = ?', [username])
monitor_db.action('UPDATE users SET keep_history = 1 WHERE username = ?', [username]) monitor_db.action('UPDATE users SET keep_history = 1 WHERE username = ?', [username])
monitor_db.action('UPDATE users SET do_notify = 1 WHERE username = ?', [username]) monitor_db.action('UPDATE users SET do_notify = 1 WHERE username = ?', [username])
@ -697,7 +697,7 @@ class Users(object):
return False return False
except Exception as e: except Exception as e:
logger.warn(u"Tautulli Users :: Unable to execute database query for undelete: %s." % e) logger.warn("Tautulli Users :: Unable to execute database query for undelete: %s." % e)
# Keep method for PlexWatch/Plexivity import # Keep method for PlexWatch/Plexivity import
def get_user_id(self, user=None): def get_user_id(self, user=None):
@ -731,7 +731,7 @@ class Users(object):
result = monitor_db.select(query) result = monitor_db.select(query)
except Exception as e: except Exception as e:
logger.warn(u"Tautulli Users :: Unable to execute database query for get_user_names: %s." % e) logger.warn("Tautulli Users :: Unable to execute database query for get_user_names: %s." % e)
return None return None
return session.friendly_name_to_username(result) return session.friendly_name_to_username(result)
@ -768,7 +768,7 @@ class Users(object):
'WHERE user_id = ?' 'WHERE user_id = ?'
result = monitor_db.select_single(query, args=[user_id]) result = monitor_db.select_single(query, args=[user_id])
except Exception as e: except Exception as e:
logger.warn(u"Tautulli Users :: Unable to execute database query for get_filters: %s." % e) logger.warn("Tautulli Users :: Unable to execute database query for get_filters: %s." % e)
result = {} result = {}
filters_list = {} filters_list = {}
@ -804,7 +804,7 @@ class Users(object):
try: try:
monitor_db.upsert(table_name='user_login', key_dict=keys, value_dict=values) monitor_db.upsert(table_name='user_login', key_dict=keys, value_dict=values)
except Exception as e: except Exception as e:
logger.warn(u"Tautulli Users :: Unable to execute database query for set_login_log: %s." % e) logger.warn("Tautulli Users :: Unable to execute database query for set_login_log: %s." % e)
def get_datatables_user_login(self, user_id=None, kwargs=None): def get_datatables_user_login(self, user_id=None, kwargs=None):
default_return = {'recordsFiltered': 0, default_return = {'recordsFiltered': 0,
@ -845,7 +845,7 @@ class Users(object):
join_evals=[['user_login.user_id', 'users.user_id']], join_evals=[['user_login.user_id', 'users.user_id']],
kwargs=kwargs) kwargs=kwargs)
except Exception as e: except Exception as e:
logger.warn(u"Tautulli Users :: Unable to execute database query for get_datatables_user_login: %s." % e) logger.warn("Tautulli Users :: Unable to execute database query for get_datatables_user_login: %s." % e)
return default_return return default_return
results = query['result'] results = query['result']
@ -880,10 +880,10 @@ class Users(object):
monitor_db = database.MonitorDatabase() monitor_db = database.MonitorDatabase()
try: try:
logger.info(u"Tautulli Users :: Clearing login logs from database.") logger.info("Tautulli Users :: Clearing login logs from database.")
monitor_db.action('DELETE FROM user_login') monitor_db.action('DELETE FROM user_login')
monitor_db.action('VACUUM') monitor_db.action('VACUUM')
return True return True
except Exception as e: except Exception as e:
logger.warn(u"Tautulli Users :: Unable to execute database query for delete_login_log: %s." % e) logger.warn("Tautulli Users :: Unable to execute database query for delete_login_log: %s." % e)
return False return False

View file

@ -40,8 +40,8 @@ def start_thread():
# Check for any existing sessions on start up # Check for any existing sessions on start up
activity_pinger.check_active_sessions(ws_request=True) activity_pinger.check_active_sessions(ws_request=True)
except Exception as e: except Exception as e:
logger.error(u"Tautulli WebSocket :: Failed to check for active sessions: %s." % e) logger.error("Tautulli WebSocket :: Failed to check for active sessions: %s." % e)
logger.warn(u"Tautulli WebSocket :: Attempt to fix by flushing temporary sessions...") logger.warn("Tautulli WebSocket :: Attempt to fix by flushing temporary sessions...")
database.delete_sessions() database.delete_sessions()
# Start the websocket listener on it's own thread # Start the websocket listener on it's own thread
@ -55,7 +55,7 @@ def on_connect():
plexpy.PLEX_SERVER_UP = True plexpy.PLEX_SERVER_UP = True
if not plexpy.PLEX_SERVER_UP: if not plexpy.PLEX_SERVER_UP:
logger.info(u"Tautulli WebSocket :: The Plex Media Server is back up.") logger.info("Tautulli WebSocket :: The Plex Media Server is back up.")
plexpy.NOTIFY_QUEUE.put({'notify_action': 'on_intup'}) plexpy.NOTIFY_QUEUE.put({'notify_action': 'on_intup'})
plexpy.PLEX_SERVER_UP = True plexpy.PLEX_SERVER_UP = True
@ -69,7 +69,7 @@ def on_disconnect():
plexpy.PLEX_SERVER_UP = False plexpy.PLEX_SERVER_UP = False
if plexpy.PLEX_SERVER_UP: if plexpy.PLEX_SERVER_UP:
logger.info(u"Tautulli WebSocket :: Unable to get a response from the server, Plex server is down.") logger.info("Tautulli WebSocket :: Unable to get a response from the server, Plex server is down.")
plexpy.NOTIFY_QUEUE.put({'notify_action': 'on_intdown'}) plexpy.NOTIFY_QUEUE.put({'notify_action': 'on_intdown'})
plexpy.PLEX_SERVER_UP = False plexpy.PLEX_SERVER_UP = False
@ -79,7 +79,7 @@ def on_disconnect():
def reconnect(): def reconnect():
close() close()
logger.info(u"Tautulli WebSocket :: Reconnecting websocket...") logger.info("Tautulli WebSocket :: Reconnecting websocket...")
start_thread() start_thread()
@ -90,14 +90,14 @@ def shutdown():
def close(): def close():
logger.info(u"Tautulli WebSocket :: Disconnecting websocket...") logger.info("Tautulli WebSocket :: Disconnecting websocket...")
plexpy.WEBSOCKET.close() plexpy.WEBSOCKET.close()
plexpy.WS_CONNECTED = False plexpy.WS_CONNECTED = False
def send_ping(): def send_ping():
if plexpy.WS_CONNECTED: if plexpy.WS_CONNECTED:
# logger.debug(u"Tautulli WebSocket :: Sending ping.") # logger.debug("Tautulli WebSocket :: Sending ping.")
plexpy.WEBSOCKET.ping("Hi?") plexpy.WEBSOCKET.ping("Hi?")
global pong_timer global pong_timer
@ -110,7 +110,7 @@ def wait_pong():
global pong_count global pong_count
pong_count += 1 pong_count += 1
logger.warning(u"Tautulli WebSocket :: Failed to receive pong from websocket, ping attempt %s." % str(pong_count)) logger.warn("Tautulli WebSocket :: Failed to receive pong from websocket, ping attempt %s." % str(pong_count))
if pong_count >= plexpy.CONFIG.WEBSOCKET_CONNECTION_ATTEMPTS: if pong_count >= plexpy.CONFIG.WEBSOCKET_CONNECTION_ATTEMPTS:
pong_count = 0 pong_count = 0
@ -118,7 +118,7 @@ def wait_pong():
def receive_pong(): def receive_pong():
# logger.debug(u"Tautulli WebSocket :: Received pong.") # logger.debug("Tautulli WebSocket :: Received pong.")
global pong_timer global pong_timer
global pong_count global pong_count
if pong_timer: if pong_timer:
@ -150,10 +150,10 @@ def run():
reconnects = 0 reconnects = 0
# Try an open the websocket connection # Try an open the websocket connection
logger.info(u"Tautulli WebSocket :: Opening %swebsocket." % secure) logger.info("Tautulli WebSocket :: Opening %swebsocket." % secure)
try: try:
plexpy.WEBSOCKET = create_connection(uri, header=header) plexpy.WEBSOCKET = create_connection(uri, header=header)
logger.info(u"Tautulli WebSocket :: Ready") logger.info("Tautulli WebSocket :: Ready")
plexpy.WS_CONNECTED = True plexpy.WS_CONNECTED = True
except (websocket.WebSocketException, IOError, Exception) as e: except (websocket.WebSocketException, IOError, Exception) as e:
logger.error("Tautulli WebSocket :: %s." % e) logger.error("Tautulli WebSocket :: %s." % e)
@ -173,7 +173,7 @@ def run():
break break
if reconnects == 0: if reconnects == 0:
logger.warn(u"Tautulli WebSocket :: Connection has closed.") logger.warn("Tautulli WebSocket :: Connection has closed.")
if not plexpy.CONFIG.PMS_IS_CLOUD and reconnects < plexpy.CONFIG.WEBSOCKET_CONNECTION_ATTEMPTS: if not plexpy.CONFIG.PMS_IS_CLOUD and reconnects < plexpy.CONFIG.WEBSOCKET_CONNECTION_ATTEMPTS:
reconnects += 1 reconnects += 1
@ -182,11 +182,11 @@ def run():
if reconnects > 1: if reconnects > 1:
time.sleep(plexpy.CONFIG.WEBSOCKET_CONNECTION_TIMEOUT) time.sleep(plexpy.CONFIG.WEBSOCKET_CONNECTION_TIMEOUT)
logger.warn(u"Tautulli WebSocket :: Reconnection attempt %s." % str(reconnects)) logger.warn("Tautulli WebSocket :: Reconnection attempt %s." % str(reconnects))
try: try:
plexpy.WEBSOCKET = create_connection(uri, header=header) plexpy.WEBSOCKET = create_connection(uri, header=header)
logger.info(u"Tautulli WebSocket :: Ready") logger.info("Tautulli WebSocket :: Ready")
plexpy.WS_CONNECTED = True plexpy.WS_CONNECTED = True
except (websocket.WebSocketException, IOError, Exception) as e: except (websocket.WebSocketException, IOError, Exception) as e:
logger.error("Tautulli WebSocket :: %s." % e) logger.error("Tautulli WebSocket :: %s." % e)
@ -206,7 +206,7 @@ def run():
if not plexpy.WS_CONNECTED and not ws_shutdown: if not plexpy.WS_CONNECTED and not ws_shutdown:
on_disconnect() on_disconnect()
logger.debug(u"Tautulli WebSocket :: Leaving thread.") logger.debug("Tautulli WebSocket :: Leaving thread.")
def receive(ws): def receive(ws):
@ -220,7 +220,7 @@ def receive(ws):
ws.send_close() ws.send_close()
return frame.opcode, None return frame.opcode, None
elif frame.opcode == websocket.ABNF.OPCODE_PING: elif frame.opcode == websocket.ABNF.OPCODE_PING:
# logger.debug(u"Tautulli WebSocket :: Received ping, sending pong.") # logger.debug("Tautulli WebSocket :: Received ping, sending pong.")
ws.pong("Hi!") ws.pong("Hi!")
elif frame.opcode == websocket.ABNF.OPCODE_PONG: elif frame.opcode == websocket.ABNF.OPCODE_PONG:
receive_pong() receive_pong()
@ -236,7 +236,7 @@ def process(opcode, data):
logger.websocket_debug(data) logger.websocket_debug(data)
info = json.loads(data) info = json.loads(data)
except Exception as e: except Exception as e:
logger.warn(u"Tautulli WebSocket :: Error decoding message from websocket: %s" % e) logger.warn("Tautulli WebSocket :: Error decoding message from websocket: %s" % e)
logger.websocket_error(data) logger.websocket_error(data)
return False return False
@ -250,26 +250,26 @@ def process(opcode, data):
time_line = info.get('PlaySessionStateNotification', info.get('_children', {})) time_line = info.get('PlaySessionStateNotification', info.get('_children', {}))
if not time_line: if not time_line:
logger.debug(u"Tautulli WebSocket :: Session found but unable to get timeline data.") logger.debug("Tautulli WebSocket :: Session found but unable to get timeline data.")
return False return False
try: try:
activity = activity_handler.ActivityHandler(timeline=time_line[0]) activity = activity_handler.ActivityHandler(timeline=time_line[0])
activity.process() activity.process()
except Exception as e: except Exception as e:
logger.error(u"Tautulli WebSocket :: Failed to process session data: %s." % e) logger.error("Tautulli WebSocket :: Failed to process session data: %s." % e)
if type == 'timeline': if type == 'timeline':
time_line = info.get('TimelineEntry', info.get('_children', {})) time_line = info.get('TimelineEntry', info.get('_children', {}))
if not time_line: if not time_line:
logger.debug(u"Tautulli WebSocket :: Timeline event found but unable to get timeline data.") logger.debug("Tautulli WebSocket :: Timeline event found but unable to get timeline data.")
return False return False
try: try:
activity = activity_handler.TimelineHandler(timeline=time_line[0]) activity = activity_handler.TimelineHandler(timeline=time_line[0])
activity.process() activity.process()
except Exception as e: except Exception as e:
logger.error(u"Tautulli WebSocket :: Failed to process timeline data: %s." % e) logger.error("Tautulli WebSocket :: Failed to process timeline data: %s." % e)
return True return True

View file

@ -84,7 +84,7 @@ def plex_user_login(username=None, password=None, token=None, headers=None):
# Register the new user / update the access tokens. # Register the new user / update the access tokens.
monitor_db = MonitorDatabase() monitor_db = MonitorDatabase()
try: try:
logger.debug(u"Tautulli WebAuth :: Registering token for user '%s' in the database." logger.debug("Tautulli WebAuth :: Registering token for user '%s' in the database."
% user_details['username']) % user_details['username'])
result = monitor_db.action('UPDATE users SET server_token = ? WHERE user_id = ?', result = monitor_db.action('UPDATE users SET server_token = ? WHERE user_id = ?',
[server_token, user_details['user_id']]) [server_token, user_details['user_id']])
@ -95,23 +95,23 @@ def plex_user_login(username=None, password=None, token=None, headers=None):
# Successful login # Successful login
return user_details, 'guest' return user_details, 'guest'
else: else:
logger.warn(u"Tautulli WebAuth :: Unable to register user '%s' in database." logger.warn("Tautulli WebAuth :: Unable to register user '%s' in database."
% user_details['username']) % user_details['username'])
return None return None
except Exception as e: except Exception as e:
logger.warn(u"Tautulli WebAuth :: Unable to register user '%s' in database: %s." logger.warn("Tautulli WebAuth :: Unable to register user '%s' in database: %s."
% (user_details['username'], e)) % (user_details['username'], e))
return None return None
else: else:
logger.warn(u"Tautulli WebAuth :: Unable to retrieve Plex.tv server token for user '%s'." logger.warn("Tautulli WebAuth :: Unable to retrieve Plex.tv server token for user '%s'."
% user_details['username']) % user_details['username'])
return None return None
elif username: elif username:
logger.warn(u"Tautulli WebAuth :: Unable to retrieve Plex.tv user token for user '%s'." % username) logger.warn("Tautulli WebAuth :: Unable to retrieve Plex.tv user token for user '%s'." % username)
return None return None
elif token: elif token:
logger.warn(u"Tautulli WebAuth :: Unable to retrieve Plex.tv user token for Plex OAuth.") logger.warn("Tautulli WebAuth :: Unable to retrieve Plex.tv user token for Plex OAuth.")
return None return None
@ -256,12 +256,12 @@ class AuthController(object):
if success: if success:
use_oauth = 'Plex OAuth' if oauth else 'form' use_oauth = 'Plex OAuth' if oauth else 'form'
logger.debug(u"Tautulli WebAuth :: %s user '%s' logged into Tautulli using %s login." logger.debug("Tautulli WebAuth :: %s user '%s' logged into Tautulli using %s login."
% (user_group.capitalize(), username, use_oauth)) % (user_group.capitalize(), username, use_oauth))
def on_logout(self, username, user_group): def on_logout(self, username, user_group):
"""Called on logout""" """Called on logout"""
logger.debug(u"Tautulli WebAuth :: %s user '%s' logged out of Tautulli." % (user_group.capitalize(), username)) logger.debug("Tautulli WebAuth :: %s user '%s' logged out of Tautulli." % (user_group.capitalize(), username))
def get_loginform(self, redirect_uri=''): def get_loginform(self, redirect_uri=''):
from plexpy.webserve import serve_template from plexpy.webserve import serve_template
@ -342,18 +342,18 @@ class AuthController(object):
elif admin_login == '1' and username: elif admin_login == '1' and username:
self.on_login(username=username) self.on_login(username=username)
logger.debug(u"Tautulli WebAuth :: Invalid admin login attempt from '%s'." % username) logger.debug("Tautulli WebAuth :: Invalid admin login attempt from '%s'." % username)
cherrypy.response.status = 401 cherrypy.response.status = 401
return error_message return error_message
elif username: elif username:
self.on_login(username=username) self.on_login(username=username)
logger.debug(u"Tautulli WebAuth :: Invalid user login attempt from '%s'." % username) logger.debug("Tautulli WebAuth :: Invalid user login attempt from '%s'." % username)
cherrypy.response.status = 401 cherrypy.response.status = 401
return error_message return error_message
elif token: elif token:
self.on_login(username='Plex OAuth', oauth=True) self.on_login(username='Plex OAuth', oauth=True)
logger.debug(u"Tautulli WebAuth :: Invalid Plex OAuth login attempt.") logger.debug("Tautulli WebAuth :: Invalid Plex OAuth login attempt.")
cherrypy.response.status = 401 cherrypy.response.status = 401
return error_message return error_message

View file

@ -226,7 +226,7 @@ class WebInterface(object):
if result: if result:
return serve_template(templatename="current_activity.html", data=result) return serve_template(templatename="current_activity.html", data=result)
else: else:
logger.warn(u"Unable to retrieve data for get_current_activity.") logger.warn("Unable to retrieve data for get_current_activity.")
return serve_template(templatename="current_activity.html", data=None) return serve_template(templatename="current_activity.html", data=None)
@cherrypy.expose @cherrypy.expose
@ -324,7 +324,7 @@ class WebInterface(object):
if result: if result:
return serve_template(templatename="recently_added.html", data=result['recently_added']) return serve_template(templatename="recently_added.html", data=result['recently_added'])
else: else:
logger.warn(u"Unable to retrieve data for get_recently_added.") logger.warn("Unable to retrieve data for get_recently_added.")
return serve_template(templatename="recently_added.html", data=None) return serve_template(templatename="recently_added.html", data=None)
@cherrypy.expose @cherrypy.expose
@ -459,14 +459,14 @@ class WebInterface(object):
if result: if result:
return result return result
else: else:
logger.warn(u"Unable to retrieve data for get_library_sections.") logger.warn("Unable to retrieve data for get_library_sections.")
@cherrypy.expose @cherrypy.expose
@cherrypy.tools.json_out() @cherrypy.tools.json_out()
@requireAuth(member_of("admin")) @requireAuth(member_of("admin"))
def refresh_libraries_list(self, **kwargs): def refresh_libraries_list(self, **kwargs):
""" Manually refresh the libraries list. """ """ Manually refresh the libraries list. """
logger.info(u"Manual libraries list refresh requested.") logger.info("Manual libraries list refresh requested.")
result = libraries.refresh_libraries() result = libraries.refresh_libraries()
if result: if result:
@ -490,10 +490,10 @@ class WebInterface(object):
library_data = libraries.Libraries() library_data = libraries.Libraries()
library_details = library_data.get_details(section_id=section_id) library_details = library_data.get_details(section_id=section_id)
except: except:
logger.warn(u"Unable to retrieve library details for section_id %s " % section_id) logger.warn("Unable to retrieve library details for section_id %s " % section_id)
return serve_template(templatename="library.html", title="Library", data=None, config=config) return serve_template(templatename="library.html", title="Library", data=None, config=config)
else: else:
logger.debug(u"Library page requested but no section_id received.") logger.debug("Library page requested but no section_id received.")
return serve_template(templatename="library.html", title="Library", data=None, config=config) return serve_template(templatename="library.html", title="Library", data=None, config=config)
return serve_template(templatename="library.html", title="Library", data=library_details, config=config) return serve_template(templatename="library.html", title="Library", data=library_details, config=config)
@ -562,7 +562,7 @@ class WebInterface(object):
if result: if result:
return serve_template(templatename="user_watch_time_stats.html", data=result, title="Watch Stats") return serve_template(templatename="user_watch_time_stats.html", data=result, title="Watch Stats")
else: else:
logger.warn(u"Unable to retrieve data for library_watch_time_stats.") logger.warn("Unable to retrieve data for library_watch_time_stats.")
return serve_template(templatename="user_watch_time_stats.html", data=None, title="Watch Stats") return serve_template(templatename="user_watch_time_stats.html", data=None, title="Watch Stats")
@cherrypy.expose @cherrypy.expose
@ -580,7 +580,7 @@ class WebInterface(object):
if result: if result:
return serve_template(templatename="library_user_stats.html", data=result, title="Player Stats") return serve_template(templatename="library_user_stats.html", data=result, title="Player Stats")
else: else:
logger.warn(u"Unable to retrieve data for library_user_stats.") logger.warn("Unable to retrieve data for library_user_stats.")
return serve_template(templatename="library_user_stats.html", data=None, title="Player Stats") return serve_template(templatename="library_user_stats.html", data=None, title="Player Stats")
@cherrypy.expose @cherrypy.expose
@ -598,7 +598,7 @@ class WebInterface(object):
if result: if result:
return serve_template(templatename="user_recently_watched.html", data=result, title="Recently Watched") return serve_template(templatename="user_recently_watched.html", data=result, title="Recently Watched")
else: else:
logger.warn(u"Unable to retrieve data for library_recently_watched.") logger.warn("Unable to retrieve data for library_recently_watched.")
return serve_template(templatename="user_recently_watched.html", data=None, title="Recently Watched") return serve_template(templatename="user_recently_watched.html", data=None, title="Recently Watched")
@cherrypy.expose @cherrypy.expose
@ -616,7 +616,7 @@ class WebInterface(object):
if result: if result:
return serve_template(templatename="library_recently_added.html", data=result['recently_added'], title="Recently Added") return serve_template(templatename="library_recently_added.html", data=result['recently_added'], title="Recently Added")
else: else:
logger.warn(u"Unable to retrieve data for library_recently_added.") logger.warn("Unable to retrieve data for library_recently_added.")
return serve_template(templatename="library_recently_added.html", data=None, title="Recently Added") return serve_template(templatename="library_recently_added.html", data=None, title="Recently Added")
@cherrypy.expose @cherrypy.expose
@ -781,9 +781,9 @@ class WebInterface(object):
if library_details: if library_details:
return library_details return library_details
else: else:
logger.warn(u"Unable to retrieve data for get_library.") logger.warn("Unable to retrieve data for get_library.")
else: else:
logger.warn(u"Library details requested but no section_id received.") logger.warn("Library details requested but no section_id received.")
@cherrypy.expose @cherrypy.expose
@cherrypy.tools.json_out() @cherrypy.tools.json_out()
@ -828,9 +828,9 @@ class WebInterface(object):
if result: if result:
return result return result
else: else:
logger.warn(u"Unable to retrieve data for get_library_watch_time_stats.") logger.warn("Unable to retrieve data for get_library_watch_time_stats.")
else: else:
logger.warn(u"Library watch time stats requested but no section_id received.") logger.warn("Library watch time stats requested but no section_id received.")
@cherrypy.expose @cherrypy.expose
@cherrypy.tools.json_out() @cherrypy.tools.json_out()
@ -871,9 +871,9 @@ class WebInterface(object):
if result: if result:
return result return result
else: else:
logger.warn(u"Unable to retrieve data for get_library_user_stats.") logger.warn("Unable to retrieve data for get_library_user_stats.")
else: else:
logger.warn(u"Library user stats requested but no section_id received.") logger.warn("Library user stats requested but no section_id received.")
@cherrypy.expose @cherrypy.expose
@cherrypy.tools.json_out() @cherrypy.tools.json_out()
@ -1094,7 +1094,7 @@ class WebInterface(object):
@requireAuth(member_of("admin")) @requireAuth(member_of("admin"))
def refresh_users_list(self, **kwargs): def refresh_users_list(self, **kwargs):
""" Manually refresh the users list. """ """ Manually refresh the users list. """
logger.info(u"Manual users list refresh requested.") logger.info("Manual users list refresh requested.")
result = users.refresh_users() result = users.refresh_users()
if result: if result:
@ -1113,10 +1113,10 @@ class WebInterface(object):
user_data = users.Users() user_data = users.Users()
user_details = user_data.get_details(user_id=user_id) user_details = user_data.get_details(user_id=user_id)
except: except:
logger.warn(u"Unable to retrieve user details for user_id %s " % user_id) logger.warn("Unable to retrieve user details for user_id %s " % user_id)
return serve_template(templatename="user.html", title="User", data=None) return serve_template(templatename="user.html", title="User", data=None)
else: else:
logger.debug(u"User page requested but no user_id received.") logger.debug("User page requested but no user_id received.")
return serve_template(templatename="user.html", title="User", data=None) return serve_template(templatename="user.html", title="User", data=None)
return serve_template(templatename="user.html", title="User", data=user_details) return serve_template(templatename="user.html", title="User", data=user_details)
@ -1190,7 +1190,7 @@ class WebInterface(object):
if result: if result:
return serve_template(templatename="user_watch_time_stats.html", data=result, title="Watch Stats") return serve_template(templatename="user_watch_time_stats.html", data=result, title="Watch Stats")
else: else:
logger.warn(u"Unable to retrieve data for user_watch_time_stats.") logger.warn("Unable to retrieve data for user_watch_time_stats.")
return serve_template(templatename="user_watch_time_stats.html", data=None, title="Watch Stats") return serve_template(templatename="user_watch_time_stats.html", data=None, title="Watch Stats")
@cherrypy.expose @cherrypy.expose
@ -1208,7 +1208,7 @@ class WebInterface(object):
if result: if result:
return serve_template(templatename="user_player_stats.html", data=result, title="Player Stats") return serve_template(templatename="user_player_stats.html", data=result, title="Player Stats")
else: else:
logger.warn(u"Unable to retrieve data for user_player_stats.") logger.warn("Unable to retrieve data for user_player_stats.")
return serve_template(templatename="user_player_stats.html", data=None, title="Player Stats") return serve_template(templatename="user_player_stats.html", data=None, title="Player Stats")
@cherrypy.expose @cherrypy.expose
@ -1226,7 +1226,7 @@ class WebInterface(object):
if result: if result:
return serve_template(templatename="user_recently_watched.html", data=result, title="Recently Watched") return serve_template(templatename="user_recently_watched.html", data=result, title="Recently Watched")
else: else:
logger.warn(u"Unable to retrieve data for get_user_recently_watched.") logger.warn("Unable to retrieve data for get_user_recently_watched.")
return serve_template(templatename="user_recently_watched.html", data=None, title="Recently Watched") return serve_template(templatename="user_recently_watched.html", data=None, title="Recently Watched")
@cherrypy.expose @cherrypy.expose
@ -1392,9 +1392,9 @@ class WebInterface(object):
if user_details: if user_details:
return user_details return user_details
else: else:
logger.warn(u"Unable to retrieve data for get_user.") logger.warn("Unable to retrieve data for get_user.")
else: else:
logger.warn(u"User details requested but no user_id received.") logger.warn("User details requested but no user_id received.")
@cherrypy.expose @cherrypy.expose
@cherrypy.tools.json_out() @cherrypy.tools.json_out()
@ -1439,9 +1439,9 @@ class WebInterface(object):
if result: if result:
return result return result
else: else:
logger.warn(u"Unable to retrieve data for get_user_watch_time_stats.") logger.warn("Unable to retrieve data for get_user_watch_time_stats.")
else: else:
logger.warn(u"User watch time stats requested but no user_id received.") logger.warn("User watch time stats requested but no user_id received.")
@cherrypy.expose @cherrypy.expose
@cherrypy.tools.json_out() @cherrypy.tools.json_out()
@ -1482,9 +1482,9 @@ class WebInterface(object):
if result: if result:
return result return result
else: else:
logger.warn(u"Unable to retrieve data for get_user_player_stats.") logger.warn("Unable to retrieve data for get_user_player_stats.")
else: else:
logger.warn(u"User watch time stats requested but no user_id received.") logger.warn("User watch time stats requested but no user_id received.")
@cherrypy.expose @cherrypy.expose
@cherrypy.tools.json_out() @cherrypy.tools.json_out()
@ -1890,7 +1890,7 @@ class WebInterface(object):
if result: if result:
return result return result
else: else:
logger.warn(u"Unable to retrieve data for get_plays_by_date.") logger.warn("Unable to retrieve data for get_plays_by_date.")
@cherrypy.expose @cherrypy.expose
@cherrypy.tools.json_out() @cherrypy.tools.json_out()
@ -1929,7 +1929,7 @@ class WebInterface(object):
if result: if result:
return result return result
else: else:
logger.warn(u"Unable to retrieve data for get_plays_by_dayofweek.") logger.warn("Unable to retrieve data for get_plays_by_dayofweek.")
@cherrypy.expose @cherrypy.expose
@cherrypy.tools.json_out() @cherrypy.tools.json_out()
@ -1968,7 +1968,7 @@ class WebInterface(object):
if result: if result:
return result return result
else: else:
logger.warn(u"Unable to retrieve data for get_plays_by_hourofday.") logger.warn("Unable to retrieve data for get_plays_by_hourofday.")
@cherrypy.expose @cherrypy.expose
@cherrypy.tools.json_out() @cherrypy.tools.json_out()
@ -2007,7 +2007,7 @@ class WebInterface(object):
if result: if result:
return result return result
else: else:
logger.warn(u"Unable to retrieve data for get_plays_per_month.") logger.warn("Unable to retrieve data for get_plays_per_month.")
@cherrypy.expose @cherrypy.expose
@cherrypy.tools.json_out() @cherrypy.tools.json_out()
@ -2046,7 +2046,7 @@ class WebInterface(object):
if result: if result:
return result return result
else: else:
logger.warn(u"Unable to retrieve data for get_plays_by_top_10_platforms.") logger.warn("Unable to retrieve data for get_plays_by_top_10_platforms.")
@cherrypy.expose @cherrypy.expose
@cherrypy.tools.json_out() @cherrypy.tools.json_out()
@ -2085,7 +2085,7 @@ class WebInterface(object):
if result: if result:
return result return result
else: else:
logger.warn(u"Unable to retrieve data for get_plays_by_top_10_users.") logger.warn("Unable to retrieve data for get_plays_by_top_10_users.")
@cherrypy.expose @cherrypy.expose
@cherrypy.tools.json_out() @cherrypy.tools.json_out()
@ -2124,7 +2124,7 @@ class WebInterface(object):
if result: if result:
return result return result
else: else:
logger.warn(u"Unable to retrieve data for get_plays_by_stream_type.") logger.warn("Unable to retrieve data for get_plays_by_stream_type.")
@cherrypy.expose @cherrypy.expose
@cherrypy.tools.json_out() @cherrypy.tools.json_out()
@ -2163,7 +2163,7 @@ class WebInterface(object):
if result: if result:
return result return result
else: else:
logger.warn(u"Unable to retrieve data for get_plays_by_source_resolution.") logger.warn("Unable to retrieve data for get_plays_by_source_resolution.")
@cherrypy.expose @cherrypy.expose
@cherrypy.tools.json_out() @cherrypy.tools.json_out()
@ -2202,7 +2202,7 @@ class WebInterface(object):
if result: if result:
return result return result
else: else:
logger.warn(u"Unable to retrieve data for get_plays_by_stream_resolution.") logger.warn("Unable to retrieve data for get_plays_by_stream_resolution.")
@cherrypy.expose @cherrypy.expose
@cherrypy.tools.json_out() @cherrypy.tools.json_out()
@ -2241,7 +2241,7 @@ class WebInterface(object):
if result: if result:
return result return result
else: else:
logger.warn(u"Unable to retrieve data for get_stream_type_by_top_10_users.") logger.warn("Unable to retrieve data for get_stream_type_by_top_10_users.")
@cherrypy.expose @cherrypy.expose
@cherrypy.tools.json_out() @cherrypy.tools.json_out()
@ -2280,7 +2280,7 @@ class WebInterface(object):
if result: if result:
return result return result
else: else:
logger.warn(u"Unable to retrieve data for get_stream_type_by_top_10_platforms.") logger.warn("Unable to retrieve data for get_stream_type_by_top_10_platforms.")
@cherrypy.expose @cherrypy.expose
@requireAuth() @requireAuth()
@ -2312,7 +2312,7 @@ class WebInterface(object):
if result: if result:
output = {"data": result} output = {"data": result}
else: else:
logger.warn(u"Unable to retrieve data for get_sync.") logger.warn("Unable to retrieve data for get_sync.")
output = {"data": []} output = {"data": []}
return output return output
@ -2435,7 +2435,7 @@ class WebInterface(object):
try: try:
log_lines = {'data': log_reader.get_log_tail(window=window, parsed=True, log_type=log_type)} log_lines = {'data': log_reader.get_log_tail(window=window, parsed=True, log_type=log_type)}
except: except:
logger.warn(u"Unable to retrieve Plex Logs.") logger.warn("Unable to retrieve Plex Logs.")
return log_lines return log_lines
@ -2659,7 +2659,7 @@ class WebInterface(object):
except Exception as e: except Exception as e:
result = 'error' result = 'error'
msg = 'Failed to clear the %s file.' % filename msg = 'Failed to clear the %s file.' % filename
logger.exception(u'Failed to clear the %s file: %s.' % (filename, e)) logger.exception('Failed to clear the %s file: %s.' % (filename, e))
return {'result': result, 'message': msg} return {'result': result, 'message': msg}
@ -2669,15 +2669,15 @@ class WebInterface(object):
plexpy.VERBOSE = not plexpy.VERBOSE plexpy.VERBOSE = not plexpy.VERBOSE
logger.initLogger(console=not plexpy.QUIET, logger.initLogger(console=not plexpy.QUIET,
log_dir=plexpy.CONFIG.LOG_DIR, verbose=plexpy.VERBOSE) log_dir=plexpy.CONFIG.LOG_DIR, verbose=plexpy.VERBOSE)
logger.info(u"Verbose toggled, set to %s", plexpy.VERBOSE) logger.info("Verbose toggled, set to %s", plexpy.VERBOSE)
logger.debug(u"If you read this message, debug logging is available") logger.debug("If you read this message, debug logging is available")
raise cherrypy.HTTPRedirect(plexpy.HTTP_ROOT + "logs") raise cherrypy.HTTPRedirect(plexpy.HTTP_ROOT + "logs")
@cherrypy.expose @cherrypy.expose
@requireAuth() @requireAuth()
def log_js_errors(self, page, message, file, line, **kwargs): def log_js_errors(self, page, message, file, line, **kwargs):
""" Logs javascript errors from the web interface. """ """ Logs javascript errors from the web interface. """
logger.error(u"WebUI :: /%s : %s. (%s:%s)" % (page.rpartition('/')[-1], logger.error("WebUI :: /%s : %s. (%s:%s)" % (page.rpartition('/')[-1],
message, message,
file.rpartition('/')[-1].partition('?')[0], file.rpartition('/')[-1].partition('?')[0],
line)) line))
@ -3336,7 +3336,7 @@ class WebInterface(object):
notifier = notifiers.get_notifier_config(notifier_id=notifier_id) notifier = notifiers.get_notifier_config(notifier_id=notifier_id)
if notifier: if notifier:
logger.debug(u"Sending %s%s notification." % (test, notifier['agent_label'])) logger.debug("Sending %s%s notification." % (test, notifier['agent_label']))
notification_handler.add_notifier_each(notifier_id=notifier_id, notification_handler.add_notifier_each(notifier_id=notifier_id,
notify_action=notify_action, notify_action=notify_action,
subject=subject, subject=subject,
@ -3345,10 +3345,10 @@ class WebInterface(object):
**kwargs) **kwargs)
return {'result': 'success', 'message': 'Notification queued.'} return {'result': 'success', 'message': 'Notification queued.'}
else: else:
logger.debug(u"Unable to send %snotification, invalid notifier_id %s." % (test, notifier_id)) logger.debug("Unable to send %snotification, invalid notifier_id %s." % (test, notifier_id))
return {'result': 'error', 'message': 'Invalid notifier id %s.' % notifier_id} return {'result': 'error', 'message': 'Invalid notifier id %s.' % notifier_id}
else: else:
logger.debug(u"Unable to send %snotification, no notifier_id received." % test) logger.debug("Unable to send %snotification, no notifier_id received." % test)
return {'result': 'error', 'message': 'No notifier id received.'} return {'result': 'error', 'message': 'No notifier id received.'}
@cherrypy.expose @cherrypy.expose
@ -3421,7 +3421,7 @@ class WebInterface(object):
if result: if result:
osx_notify = notifiers.OSX() osx_notify = notifiers.OSX()
osx_notify.notify(subject='Registered', body='Success :-)', subtitle=result) osx_notify.notify(subject='Registered', body='Success :-)', subtitle=result)
# logger.info(u"Registered %s, to re-register a different app, delete this app first" % result) # logger.info("Registered %s, to re-register a different app, delete this app first" % result)
else: else:
logger.warn(msg) logger.warn(msg)
return msg return msg
@ -3585,7 +3585,7 @@ class WebInterface(object):
elif app == 'plexivity': elif app == 'plexivity':
return serve_template(templatename="app_import.html", title="Import Plexivity Database", app="Plexivity") return serve_template(templatename="app_import.html", title="Import Plexivity Database", app="Plexivity")
logger.warn(u"No app specified for import.") logger.warn("No app specified for import.")
return return
@cherrypy.expose @cherrypy.expose
@ -3616,7 +3616,7 @@ class WebInterface(object):
if result: if result:
return result['auth_token'] return result['auth_token']
else: else:
logger.warn(u"Unable to retrieve Plex.tv token.") logger.warn("Unable to retrieve Plex.tv token.")
return None return None
@cherrypy.expose @cherrypy.expose
@ -3741,7 +3741,7 @@ class WebInterface(object):
if result: if result:
return result return result
else: else:
logger.warn(u"Unable to retrieve data for get_server_pref.") logger.warn("Unable to retrieve data for get_server_pref.")
@cherrypy.expose @cherrypy.expose
@cherrypy.tools.json_out() @cherrypy.tools.json_out()
@ -3751,7 +3751,7 @@ class WebInterface(object):
while not apikey or apikey == plexpy.CONFIG.API_KEY or mobile_app.get_mobile_device_by_token(device_token=apikey): while not apikey or apikey == plexpy.CONFIG.API_KEY or mobile_app.get_mobile_device_by_token(device_token=apikey):
apikey = plexpy.generate_uuid() apikey = plexpy.generate_uuid()
logger.info(u"New API key generated.") logger.info("New API key generated.")
logger._BLACKLIST_WORDS.add(apikey) logger._BLACKLIST_WORDS.add(apikey)
if device == 'true': if device == 'true':
@ -3862,7 +3862,7 @@ class WebInterface(object):
@requireAuth(member_of("admin")) @requireAuth(member_of("admin"))
def checkout_git_branch(self, git_remote=None, git_branch=None, **kwargs): def checkout_git_branch(self, git_remote=None, git_branch=None, **kwargs):
if git_branch == plexpy.CONFIG.GIT_BRANCH: if git_branch == plexpy.CONFIG.GIT_BRANCH:
logger.error(u"Already on the %s branch" % git_branch) logger.error("Already on the %s branch" % git_branch)
raise cherrypy.HTTPRedirect(plexpy.HTTP_ROOT + "home") raise cherrypy.HTTPRedirect(plexpy.HTTP_ROOT + "home")
# Set the new git remote and branch # Set the new git remote and branch
@ -3942,7 +3942,7 @@ class WebInterface(object):
if result: if result:
return serve_template(templatename="info_children_list.html", data=result, title="Children List") return serve_template(templatename="info_children_list.html", data=result, title="Children List")
else: else:
logger.warn(u"Unable to retrieve data for get_item_children.") logger.warn("Unable to retrieve data for get_item_children.")
return serve_template(templatename="info_children_list.html", data=None, title="Children List") return serve_template(templatename="info_children_list.html", data=None, title="Children List")
@cherrypy.expose @cherrypy.expose
@ -4098,10 +4098,10 @@ class WebInterface(object):
return result[0] return result[0]
else: else:
raise Exception(u'PMS image request failed') raise Exception('PMS image request failed')
except Exception as e: except Exception as e:
logger.warn(u'Failed to get image %s, falling back to %s.' % (img, fallback)) logger.warn('Failed to get image %s, falling back to %s.' % (img, fallback))
fbi = None fbi = None
if fallback == 'poster': if fallback == 'poster':
fbi = common.DEFAULT_POSTER_THUMB fbi = common.DEFAULT_POSTER_THUMB
@ -4246,7 +4246,7 @@ class WebInterface(object):
except OSError as e: except OSError as e:
result = 'error' result = 'error'
msg = 'Failed to delete %s.' % cache_dir msg = 'Failed to delete %s.' % cache_dir
logger.exception(u'Failed to delete %s: %s.' % (cache_dir, e)) logger.exception('Failed to delete %s: %s.' % (cache_dir, e))
return {'result': result, 'message': msg} return {'result': result, 'message': msg}
try: try:
@ -4254,7 +4254,7 @@ class WebInterface(object):
except OSError as e: except OSError as e:
result = 'error' result = 'error'
msg = 'Failed to make %s.' % cache_dir msg = 'Failed to make %s.' % cache_dir
logger.exception(u'Failed to create %s: %s.' % (cache_dir, e)) logger.exception('Failed to create %s: %s.' % (cache_dir, e))
return {'result': result, 'message': msg} return {'result': result, 'message': msg}
logger.info(msg) logger.info(msg)
@ -4369,7 +4369,7 @@ class WebInterface(object):
if result: if result:
return result return result
else: else:
logger.warn(u"Unable to retrieve data for search_results.") logger.warn("Unable to retrieve data for search_results.")
@cherrypy.expose @cherrypy.expose
@requireAuth() @requireAuth()
@ -4387,7 +4387,7 @@ class WebInterface(object):
if result: if result:
return serve_template(templatename="info_search_results_list.html", data=result, title="Search Result List") return serve_template(templatename="info_search_results_list.html", data=result, title="Search Result List")
else: else:
logger.warn(u"Unable to retrieve data for get_search_results_children.") logger.warn("Unable to retrieve data for get_search_results_children.")
return serve_template(templatename="info_search_results_list.html", data=None, title="Search Result List") return serve_template(templatename="info_search_results_list.html", data=None, title="Search Result List")
@ -4407,7 +4407,7 @@ class WebInterface(object):
if query: if query:
return serve_template(templatename="update_metadata.html", query=query, update=update, title="Info") return serve_template(templatename="update_metadata.html", query=query, update=update, title="Info")
else: else:
logger.warn(u"Unable to retrieve data for update_metadata.") logger.warn("Unable to retrieve data for update_metadata.")
return serve_template(templatename="update_metadata.html", query=query, update=update, title="Info") return serve_template(templatename="update_metadata.html", query=query, update=update, title="Info")
@cherrypy.expose @cherrypy.expose
@ -4476,7 +4476,7 @@ class WebInterface(object):
if result: if result:
return result return result
else: else:
logger.warn(u"Unable to retrieve data for get_new_rating_keys.") logger.warn("Unable to retrieve data for get_new_rating_keys.")
@cherrypy.expose @cherrypy.expose
@cherrypy.tools.json_out() @cherrypy.tools.json_out()
@ -4505,7 +4505,7 @@ class WebInterface(object):
if result: if result:
return result return result
else: else:
logger.warn(u"Unable to retrieve data for get_old_rating_keys.") logger.warn("Unable to retrieve data for get_old_rating_keys.")
@cherrypy.expose @cherrypy.expose
@ -4519,7 +4519,7 @@ class WebInterface(object):
if result: if result:
return result return result
else: else:
logger.warn(u"Unable to retrieve data for get_pms_sessions_json.") logger.warn("Unable to retrieve data for get_pms_sessions_json.")
return False return False
@cherrypy.expose @cherrypy.expose
@ -4678,7 +4678,7 @@ class WebInterface(object):
if metadata: if metadata:
return metadata return metadata
else: else:
logger.warn(u"Unable to retrieve data for get_metadata_details.") logger.warn("Unable to retrieve data for get_metadata_details.")
@cherrypy.expose @cherrypy.expose
@cherrypy.tools.json_out() @cherrypy.tools.json_out()
@ -4733,7 +4733,7 @@ class WebInterface(object):
if result: if result:
return result return result
else: else:
logger.warn(u"Unable to retrieve data for get_recently_added_details.") logger.warn("Unable to retrieve data for get_recently_added_details.")
@cherrypy.expose @cherrypy.expose
@cherrypy.tools.json_out() @cherrypy.tools.json_out()
@ -4747,7 +4747,7 @@ class WebInterface(object):
if result: if result:
return result return result
else: else:
logger.warn(u"Unable to retrieve data for get_friends_list.") logger.warn("Unable to retrieve data for get_friends_list.")
@cherrypy.expose @cherrypy.expose
@cherrypy.tools.json_out() @cherrypy.tools.json_out()
@ -4761,7 +4761,7 @@ class WebInterface(object):
if result: if result:
return result return result
else: else:
logger.warn(u"Unable to retrieve data for get_user_details.") logger.warn("Unable to retrieve data for get_user_details.")
@cherrypy.expose @cherrypy.expose
@cherrypy.tools.json_out() @cherrypy.tools.json_out()
@ -4775,7 +4775,7 @@ class WebInterface(object):
if result: if result:
return result return result
else: else:
logger.warn(u"Unable to retrieve data for get_server_list.") logger.warn("Unable to retrieve data for get_server_list.")
@cherrypy.expose @cherrypy.expose
@cherrypy.tools.json_out() @cherrypy.tools.json_out()
@ -4788,7 +4788,7 @@ class WebInterface(object):
if result: if result:
return result return result
else: else:
logger.warn(u"Unable to retrieve data for get_sync_lists.") logger.warn("Unable to retrieve data for get_sync_lists.")
@cherrypy.expose @cherrypy.expose
@cherrypy.tools.json_out() @cherrypy.tools.json_out()
@ -4800,7 +4800,7 @@ class WebInterface(object):
if result: if result:
return result return result
else: else:
logger.warn(u"Unable to retrieve data for get_servers.") logger.warn("Unable to retrieve data for get_servers.")
@cherrypy.expose @cherrypy.expose
@cherrypy.tools.json_out() @cherrypy.tools.json_out()
@ -4833,7 +4833,7 @@ class WebInterface(object):
if result: if result:
return result return result
else: else:
logger.warn(u"Unable to retrieve data for get_servers_info.") logger.warn("Unable to retrieve data for get_servers_info.")
@cherrypy.expose @cherrypy.expose
@cherrypy.tools.json_out() @cherrypy.tools.json_out()
@ -4863,7 +4863,7 @@ class WebInterface(object):
if result: if result:
return result return result
else: else:
logger.warn(u"Unable to retrieve data for get_server_identity.") logger.warn("Unable to retrieve data for get_server_identity.")
@cherrypy.expose @cherrypy.expose
@cherrypy.tools.json_out() @cherrypy.tools.json_out()
@ -4888,7 +4888,7 @@ class WebInterface(object):
if result: if result:
return result return result
else: else:
logger.warn(u"Unable to retrieve data for get_server_friendly_name.") logger.warn("Unable to retrieve data for get_server_friendly_name.")
@cherrypy.expose @cherrypy.expose
@cherrypy.tools.json_out() @cherrypy.tools.json_out()
@ -5168,9 +5168,9 @@ class WebInterface(object):
return result return result
else: else:
logger.warn(u"Unable to retrieve data for get_activity.") logger.warn("Unable to retrieve data for get_activity.")
except Exception as e: except Exception as e:
logger.exception(u"Unable to retrieve data for get_activity: %s" % e) logger.exception("Unable to retrieve data for get_activity: %s" % e)
@cherrypy.expose @cherrypy.expose
@cherrypy.tools.json_out() @cherrypy.tools.json_out()
@ -5208,7 +5208,7 @@ class WebInterface(object):
if result: if result:
return result return result
else: else:
logger.warn(u"Unable to retrieve data for get_full_libraries_list.") logger.warn("Unable to retrieve data for get_full_libraries_list.")
@cherrypy.expose @cherrypy.expose
@cherrypy.tools.json_out() @cherrypy.tools.json_out()
@ -5256,7 +5256,7 @@ class WebInterface(object):
if result: if result:
return result return result
else: else:
logger.warn(u"Unable to retrieve data for get_full_users_list.") logger.warn("Unable to retrieve data for get_full_users_list.")
@cherrypy.expose @cherrypy.expose
@cherrypy.tools.json_out() @cherrypy.tools.json_out()
@ -5310,7 +5310,7 @@ class WebInterface(object):
if result: if result:
return result return result
else: else:
logger.warn(u"Unable to retrieve data for get_synced_items.") logger.warn("Unable to retrieve data for get_synced_items.")
@cherrypy.expose @cherrypy.expose
@cherrypy.tools.json_out() @cherrypy.tools.json_out()
@ -5323,7 +5323,7 @@ class WebInterface(object):
if result: if result:
return result return result
else: else:
logger.warn(u"Unable to retrieve data for get_sync_transcode_queue.") logger.warn("Unable to retrieve data for get_sync_transcode_queue.")
@cherrypy.expose @cherrypy.expose
@cherrypy.tools.json_out() @cherrypy.tools.json_out()
@ -5418,7 +5418,7 @@ class WebInterface(object):
if result: if result:
return result return result
else: else:
logger.warn(u"Unable to retrieve data for get_home_stats.") logger.warn("Unable to retrieve data for get_home_stats.")
@cherrypy.expose @cherrypy.expose
@requireAuth(member_of("admin")) @requireAuth(member_of("admin"))
@ -5778,7 +5778,7 @@ class WebInterface(object):
newsletter = newsletters.get_newsletter_config(newsletter_id=newsletter_id) newsletter = newsletters.get_newsletter_config(newsletter_id=newsletter_id)
if newsletter: if newsletter:
logger.debug(u"Sending %s%s newsletter." % (test, newsletter['agent_label'])) logger.debug("Sending %s%s newsletter." % (test, newsletter['agent_label']))
newsletter_handler.add_newsletter_each(newsletter_id=newsletter_id, newsletter_handler.add_newsletter_each(newsletter_id=newsletter_id,
notify_action=notify_action, notify_action=notify_action,
subject=subject, subject=subject,
@ -5787,10 +5787,10 @@ class WebInterface(object):
**kwargs) **kwargs)
return {'result': 'success', 'message': 'Newsletter queued.'} return {'result': 'success', 'message': 'Newsletter queued.'}
else: else:
logger.debug(u"Unable to send %snewsletter, invalid newsletter_id %s." % (test, newsletter_id)) logger.debug("Unable to send %snewsletter, invalid newsletter_id %s." % (test, newsletter_id))
return {'result': 'error', 'message': 'Invalid newsletter id %s.' % newsletter_id} return {'result': 'error', 'message': 'Invalid newsletter id %s.' % newsletter_id}
else: else:
logger.debug(u"Unable to send %snotification, no newsletter_id received." % test) logger.debug("Unable to send %snotification, no newsletter_id received." % test)
return {'result': 'error', 'message': 'No newsletter id received.'} return {'result': 'error', 'message': 'No newsletter id received.'}
@cherrypy.expose @cherrypy.expose
@ -5873,10 +5873,10 @@ class WebInterface(object):
return newsletter_agent.generate_newsletter(preview=preview) return newsletter_agent.generate_newsletter(preview=preview)
logger.error(u"Failed to retrieve newsletter: Invalid newsletter_id %s" % newsletter_id) logger.error("Failed to retrieve newsletter: Invalid newsletter_id %s" % newsletter_id)
return "Failed to retrieve newsletter: invalid newsletter_id parameter" return "Failed to retrieve newsletter: invalid newsletter_id parameter"
logger.error(u"Failed to retrieve newsletter: Missing newsletter_id parameter.") logger.error("Failed to retrieve newsletter: Missing newsletter_id parameter.")
return "Failed to retrieve newsletter: missing newsletter_id parameter" return "Failed to retrieve newsletter: missing newsletter_id parameter"
@cherrypy.expose @cherrypy.expose

View file

@ -26,7 +26,7 @@ from plexpy.webserve import WebInterface
def start(): def start():
logger.info(u"Tautulli WebStart :: Initializing Tautulli web server...") logger.info("Tautulli WebStart :: Initializing Tautulli web server...")
web_config = { web_config = {
'http_port': plexpy.HTTP_PORT, 'http_port': plexpy.HTTP_PORT,
'http_host': plexpy.CONFIG.HTTP_HOST, 'http_host': plexpy.CONFIG.HTTP_HOST,
@ -45,12 +45,12 @@ def start():
def stop(): def stop():
logger.info(u"Tautulli WebStart :: Stopping Tautulli web server...") logger.info("Tautulli WebStart :: Stopping Tautulli web server...")
cherrypy.engine.exit() cherrypy.engine.exit()
def restart(): def restart():
logger.info(u"Tautulli WebStart :: Restarting Tautulli web server...") logger.info("Tautulli WebStart :: Restarting Tautulli web server...")
stop() stop()
start() start()
@ -69,11 +69,11 @@ def initialize(options):
(not (https_cert and os.path.exists(https_cert)) or (not (https_cert and os.path.exists(https_cert)) or
not (https_key and os.path.exists(https_key))): not (https_key and os.path.exists(https_key))):
if not create_https_certificates(https_cert, https_key): if not create_https_certificates(https_cert, https_key):
logger.warn(u"Tautulli WebStart :: Unable to create certificate and key. Disabling HTTPS") logger.warn("Tautulli WebStart :: Unable to create certificate and key. Disabling HTTPS")
enable_https = False enable_https = False
if not (os.path.exists(https_cert) and os.path.exists(https_key)): if not (os.path.exists(https_cert) and os.path.exists(https_key)):
logger.warn(u"Tautulli WebStart :: Disabled HTTPS because of missing certificate and key.") logger.warn("Tautulli WebStart :: Disabled HTTPS because of missing certificate and key.")
enable_https = False enable_https = False
options_dict = { options_dict = {
@ -107,7 +107,7 @@ def initialize(options):
if plexpy.CONFIG.HTTP_PLEX_ADMIN: if plexpy.CONFIG.HTTP_PLEX_ADMIN:
login_allowed.append("Plex admin") login_allowed.append("Plex admin")
logger.info(u"Tautulli WebStart :: Web server authentication is enabled: %s.", ' and '.join(login_allowed)) logger.info("Tautulli WebStart :: Web server authentication is enabled: %s.", ' and '.join(login_allowed))
if options['http_basic_auth']: if options['http_basic_auth']:
plexpy.AUTH_ENABLED = False plexpy.AUTH_ENABLED = False
@ -245,7 +245,7 @@ def initialize(options):
cherrypy.tree.mount(BaseRedirect(), '/') cherrypy.tree.mount(BaseRedirect(), '/')
try: try:
logger.info(u"Tautulli WebStart :: Starting Tautulli web server on %s://%s:%d%s", protocol, logger.info("Tautulli WebStart :: Starting Tautulli web server on %s://%s:%d%s", protocol,
options['http_host'], options['http_port'], options['http_root']) options['http_host'], options['http_port'], options['http_root'])
cherrypy.process.servers.check_port(str(options['http_host']), options['http_port']) cherrypy.process.servers.check_port(str(options['http_host']), options['http_port'])
if not plexpy.DEV: if not plexpy.DEV:
@ -274,7 +274,7 @@ class BaseRedirect(object):
def proxy(): def proxy():
# logger.debug(u"REQUEST URI: %s, HEADER [X-Forwarded-Host]: %s, [X-Host]: %s, [Origin]: %s, [Host]: %s", # logger.debug("REQUEST URI: %s, HEADER [X-Forwarded-Host]: %s, [X-Host]: %s, [Origin]: %s, [Host]: %s",
# cherrypy.request.wsgi_environ['REQUEST_URI'], # cherrypy.request.wsgi_environ['REQUEST_URI'],
# cherrypy.request.headers.get('X-Forwarded-Host'), # cherrypy.request.headers.get('X-Forwarded-Host'),
# cherrypy.request.headers.get('X-Host'), # cherrypy.request.headers.get('X-Host'),
@ -290,7 +290,7 @@ def proxy():
local = 'Origin' local = 'Origin'
elif cherrypy.request.headers.get('Host'): # nginx elif cherrypy.request.headers.get('Host'): # nginx
local = 'Host' local = 'Host'
# logger.debug(u"cherrypy.tools.proxy.local set to [%s]", local) # logger.debug("cherrypy.tools.proxy.local set to [%s]", local)
# Call original cherrypy proxy tool with the new local # Call original cherrypy proxy tool with the new local
cherrypy.lib.cptools.proxy(local=local) cherrypy.lib.cptools.proxy(local=local)