Massive code cleanup

* Finish up library pages (toggles and notifications)
* Update user pages to match library pages
* Fix no current activity bif thumbnail at the start of a stream
* Improved logging throughout PlexPy
This commit is contained in:
Jonathan Wong 2016-01-05 20:46:27 -08:00
parent 5fedac691d
commit 636f898da8
31 changed files with 2873 additions and 2715 deletions

View file

@ -377,7 +377,7 @@ def dbcheck():
# sessions table :: This is a temp table that logs currently active sessions
c_db.execute(
'CREATE TABLE IF NOT EXISTS sessions (id INTEGER PRIMARY KEY AUTOINCREMENT, '
'session_key INTEGER, rating_key INTEGER, media_type TEXT, started INTEGER, '
'session_key INTEGER, rating_key INTEGER, library_id INTEGER, media_type TEXT, started INTEGER, '
'paused_counter INTEGER DEFAULT 0, state TEXT, user_id INTEGER, user TEXT, friendly_name TEXT, '
'ip_address TEXT, machine_id TEXT, player TEXT, platform TEXT, title TEXT, parent_title TEXT, '
'grandparent_title TEXT, parent_rating_key INTEGER, grandparent_rating_key INTEGER, '
@ -441,7 +441,8 @@ def dbcheck():
'CREATE TABLE IF NOT EXISTS library_sections (id INTEGER PRIMARY KEY AUTOINCREMENT, '
'server_id TEXT, section_id INTEGER UNIQUE, section_name TEXT, section_type TEXT, '
'thumb TEXT, custom_thumb_url TEXT, art TEXT, count INTEGER, parent_count INTEGER, child_count INTEGER, '
'do_notify INTEGER DEFAULT 1, keep_history INTEGER DEFAULT 1)'
'do_notify INTEGER DEFAULT 1, do_notify_created INTEGER DEFAULT 1, keep_history INTEGER DEFAULT 1, '
'deleted_section INTEGER DEFAULT 0)'
)
# Upgrade sessions table from earlier versions
@ -591,6 +592,15 @@ def dbcheck():
'ALTER TABLE sessions ADD COLUMN last_paused INTEGER'
)
# Upgrade sessions table from earlier versions
try:
c_db.execute('SELECT library_id from sessions')
except sqlite3.OperationalError:
logger.debug(u"Altering database. Updating database table sessions.")
c_db.execute(
'ALTER TABLE sessions ADD COLUMN library_id INTEGER'
)
# Upgrade session_history table from earlier versions
try:
c_db.execute('SELECT reference_id from session_history')

View file

@ -16,7 +16,7 @@
import time
import plexpy
from plexpy import logger, pmsconnect, activity_processor, threading, notification_handler
from plexpy import logger, pmsconnect, activity_processor, threading, notification_handler, helpers
class ActivityHandler(object):
@ -165,8 +165,6 @@ class ActivityHandler(object):
# This function receives events from our websocket connection
def process(self):
if self.is_valid_session():
from plexpy import helpers
ap = activity_processor.ActivityProcessor()
db_session = ap.get_session_by_key(session_key=self.get_session_key())

View file

@ -13,7 +13,7 @@
# You should have received a copy of the GNU General Public License
# along with PlexPy. If not, see <http://www.gnu.org/licenses/>.
from plexpy import logger, pmsconnect, plextv, notification_handler, database, helpers, activity_processor
from plexpy import logger, pmsconnect, plextv, notification_handler, database, helpers, activity_processor, libraries
import threading
import plexpy
@ -46,16 +46,7 @@ def check_active_sessions(ws_request=False):
media_container = session_list['sessions']
# Check our temp table for what we must do with the new streams
db_streams = monitor_db.select('SELECT started, session_key, rating_key, media_type, title, parent_title, '
'grandparent_title, user_id, user, friendly_name, ip_address, player, '
'platform, machine_id, parent_rating_key, grandparent_rating_key, state, '
'view_offset, duration, video_decision, audio_decision, width, height, '
'container, video_codec, audio_codec, bitrate, video_resolution, '
'video_framerate, aspect_ratio, audio_channels, transcode_protocol, '
'transcode_container, transcode_video_codec, transcode_audio_codec, '
'transcode_audio_channels, transcode_width, transcode_height, '
'paused_counter, last_paused '
'FROM sessions')
db_streams = monitor_db.select('SELECT * FROM sessions')
for stream in db_streams:
if any(d['session_key'] == str(stream['session_key']) and d['rating_key'] == str(stream['rating_key'])
for d in media_container):
@ -182,7 +173,7 @@ def check_active_sessions(ws_request=False):
if int_ping_count == 3:
# Fire off notifications
threading.Thread(target=notification_handler.notify_timeline,
kwargs=dict(notify_action='intdown')).start()
kwargs=dict(notify_action='intdown')).start()
def check_recently_added():
@ -196,10 +187,16 @@ def check_recently_added():
pms_connect = pmsconnect.PmsConnect()
recently_added_list = pms_connect.get_recently_added_details(count='10')
library_data = libraries.Libraries()
if recently_added_list:
recently_added = recently_added_list['recently_added']
for item in recently_added:
library_details = library_data.get_details(section_id=item['library_id'])
if not library_details['do_notify_created']:
continue
metadata = []
if 0 < time_threshold - int(item['added_at']) <= time_interval:
@ -220,8 +217,12 @@ def check_recently_added():
% str(item['rating_key']))
if metadata:
if not plexpy.CONFIG.NOTIFY_RECENTLY_ADDED_GRANDPARENT:
for item in metadata:
library_details = library_data.get_details(section_id=item['library_id'])
if 0 < time_threshold - int(item['added_at']) <= time_interval:
logger.debug(u"PlexPy Monitor :: Library item %s has been added to Plex." % str(item['rating_key']))
# Fire off notifications

View file

@ -29,6 +29,7 @@ class ActivityProcessor(object):
def write_session(self, session=None, notify=True):
if session:
values = {'session_key': session['session_key'],
'library_id': session['library_id'],
'rating_key': session['rating_key'],
'media_type': session['media_type'],
'state': session['state'],
@ -97,10 +98,13 @@ class ActivityProcessor(object):
self.db.upsert('sessions', ip_address, keys)
def write_session_history(self, session=None, import_metadata=None, is_import=False, import_ignore_interval=0):
from plexpy import users
from plexpy import users, libraries
user_data = users.Users()
user_details = user_data.get_user_friendly_name(user=session['user'])
user_details = user_data.get_details(user_id=session['user_id'])
library_data = libraries.Libraries()
library_details = library_data.get_details(section_id=session['library_id'])
if session:
logging_enabled = False
@ -155,7 +159,10 @@ class ActivityProcessor(object):
if not user_details['keep_history'] and not is_import:
logging_enabled = False
logger.debug(u"PlexPy ActivityProcessor :: History logging for user '%s' is disabled." % session['user'])
logger.debug(u"PlexPy ActivityProcessor :: History logging for user '%s' is disabled." % user_details['username'])
elif not library_details['keep_history'] and not is_import:
logging_enabled = False
logger.debug(u"PlexPy ActivityProcessor :: History logging for library '%s' is disabled." % library_details['section_name'])
if logging_enabled:
# logger.debug(u"PlexPy ActivityProcessor :: Attempting to write to session_history table...")
@ -331,15 +338,7 @@ class ActivityProcessor(object):
def get_session_by_key(self, session_key=None):
if str(session_key).isdigit():
result = self.db.select('SELECT started, session_key, rating_key, media_type, title, parent_title, '
'grandparent_title, user_id, user, friendly_name, ip_address, player, '
'platform, machine_id, parent_rating_key, grandparent_rating_key, state, '
'view_offset, duration, video_decision, audio_decision, width, height, '
'container, video_codec, audio_codec, bitrate, video_resolution, '
'video_framerate, aspect_ratio, audio_channels, transcode_protocol, '
'transcode_container, transcode_video_codec, transcode_audio_codec, '
'transcode_audio_channels, transcode_width, transcode_height, '
'paused_counter, last_paused '
result = self.db.select('SELECT * '
'FROM sessions WHERE session_key = ? LIMIT 1', args=[session_key])
for session in result:
if session:

View file

@ -323,7 +323,7 @@ class Api(object):
custom_where = [['strftime("%Y-%m-%d", datetime(date, "unixepoch", "localtime"))', start_date]]
data_factory = datafactory.DataFactory()
history = data_factory.get_history(kwargs=kwargs, custom_where=custom_where)
history = data_factory.get_datatables_history(kwargs=kwargs, custom_where=custom_where)
self.data = history
return self.data

View file

@ -26,7 +26,7 @@ class DataFactory(object):
def __init__(self):
pass
def get_history(self, kwargs=None, custom_where=None, grouping=0, watched_percent=85):
def get_datatables_history(self, kwargs=None, custom_where=None, grouping=0, watched_percent=85):
data_tables = datatables.DataTables()
group_by = ['session_history.reference_id'] if grouping else ['session_history.id']
@ -81,8 +81,8 @@ class DataFactory(object):
['session_history.id', 'session_history_metadata.id'],
['session_history.id', 'session_history_media_info.id']],
kwargs=kwargs)
except:
logger.warn("Unable to execute database query for get_history.")
except Exception as e:
logger.warn(u"PlexPy DataFactory :: Unable to execute database query for get_history: %s." % e)
return {'recordsFiltered': 0,
'recordsTotal': 0,
'draw': 0,
@ -185,8 +185,8 @@ class DataFactory(object):
'ORDER BY %s DESC ' \
'LIMIT %s ' % (time_range, group_by, sort_type, stats_count)
result = monitor_db.select(query)
except:
logger.warn("Unable to execute database query for get_home_stats: top_tv.")
except Exception as e:
logger.warn(u"PlexPy DataFactory :: Unable to execute database query for get_home_stats: top_tv: %s." % e)
return None
for item in result:
@ -229,8 +229,8 @@ class DataFactory(object):
'ORDER BY users_watched DESC, %s DESC ' \
'LIMIT %s ' % (time_range, group_by, sort_type, stats_count)
result = monitor_db.select(query)
except:
logger.warn("Unable to execute database query for get_home_stats: popular_tv.")
except Exception as e:
logger.warn(u"PlexPy DataFactory :: Unable to execute database query for get_home_stats: popular_tv: %s." % e)
return None
for item in result:
@ -270,8 +270,8 @@ class DataFactory(object):
'ORDER BY %s DESC ' \
'LIMIT %s ' % (time_range, group_by, sort_type, stats_count)
result = monitor_db.select(query)
except:
logger.warn("Unable to execute database query for get_home_stats: top_movies.")
except Exception as e:
logger.warn(u"PlexPy DataFactory :: Unable to execute database query for get_home_stats: top_movies: %s." % e)
return None
for item in result:
@ -313,8 +313,8 @@ class DataFactory(object):
'ORDER BY users_watched DESC, %s DESC ' \
'LIMIT %s ' % (time_range, group_by, sort_type, stats_count)
result = monitor_db.select(query)
except:
logger.warn("Unable to execute database query for get_home_stats: popular_movies.")
except Exception as e:
logger.warn(u"PlexPy DataFactory :: Unable to execute database query for get_home_stats: popular_movies: %s." % e)
return None
for item in result:
@ -354,8 +354,8 @@ class DataFactory(object):
'ORDER BY %s DESC ' \
'LIMIT %s ' % (time_range, group_by, sort_type, stats_count)
result = monitor_db.select(query)
except:
logger.warn("Unable to execute database query for get_home_stats: top_music.")
except Exception as e:
logger.warn(u"PlexPy DataFactory :: Unable to execute database query for get_home_stats: top_music: %s." % e)
return None
for item in result:
@ -398,8 +398,8 @@ class DataFactory(object):
'ORDER BY users_watched DESC, %s DESC ' \
'LIMIT %s ' % (time_range, group_by, sort_type, stats_count)
result = monitor_db.select(query)
except:
logger.warn("Unable to execute database query for get_home_stats: popular_music.")
except Exception as e:
logger.warn(u"PlexPy DataFactory :: Unable to execute database query for get_home_stats: popular_music: %s." % e)
return None
for item in result:
@ -424,13 +424,13 @@ class DataFactory(object):
elif stat == 'top_users':
top_users = []
try:
query = 'SELECT t.user, t.user_id, t.custom_avatar_url as thumb, ' \
query = 'SELECT t.user, t.user_id, t.user_thumb, t.custom_thumb, ' \
'(CASE WHEN t.friendly_name IS NULL THEN t.username ELSE t.friendly_name END) ' \
' AS friendly_name, ' \
'MAX(t.started) AS last_watch, COUNT(t.id) AS total_plays, SUM(t.d) AS total_duration ' \
'FROM (SELECT *, SUM(CASE WHEN stopped > 0 THEN (stopped - started) - ' \
' (CASE WHEN paused_counter IS NULL THEN 0 ELSE paused_counter END) ELSE 0 END) ' \
' AS d ' \
' AS d, users.thumb AS user_thumb, users.custom_avatar_url AS custom_thumb ' \
' FROM session_history ' \
' JOIN session_history_metadata ON session_history_metadata.id = session_history.id ' \
' LEFT OUTER JOIN users ON session_history.user_id = users.user_id ' \
@ -441,15 +441,17 @@ class DataFactory(object):
'ORDER BY %s DESC ' \
'LIMIT %s ' % (time_range, group_by, sort_type, stats_count)
result = monitor_db.select(query)
except:
logger.warn("Unable to execute database query for get_home_stats: top_users.")
except Exception as e:
logger.warn(u"PlexPy DataFactory :: Unable to execute database query for get_home_stats: top_users: %s." % e)
return None
for item in result:
if not item['thumb'] or item['thumb'] == '':
user_thumb = common.DEFAULT_USER_THUMB
if item['custom_thumb'] and item['custom_thumb'] != item['user_thumb']:
user_thumb = item['custom_thumb']
elif item['user_thumb']:
user_thumb = item['user_thumb']
else:
user_thumb = item['thumb']
user_thumb = common.DEFAULT_USER_THUMB
row = {'user': item['user'],
'user_id': item['user_id'],
@ -490,8 +492,8 @@ class DataFactory(object):
'ORDER BY %s DESC ' \
'LIMIT %s ' % (time_range, group_by, sort_type, stats_count)
result = monitor_db.select(query)
except:
logger.warn("Unable to execute database query for get_home_stats: top_platforms.")
except Exception as e:
logger.warn(u"PlexPy DataFactory :: Unable to execute database query for get_home_stats: top_platforms: %s." % e)
return None
for item in result:
@ -542,8 +544,8 @@ class DataFactory(object):
'ORDER BY last_watch DESC ' \
'LIMIT %s' % (time_range, group_by, notify_watched_percent, stats_count)
result = monitor_db.select(query)
except:
logger.warn("Unable to execute database query for get_home_stats: last_watched.")
except Exception as e:
logger.warn(u"PlexPy DataFactory :: Unable to execute database query for get_home_stats: last_watched: %s." % e)
return None
for item in result:
@ -645,8 +647,8 @@ class DataFactory(object):
result = monitor_db.select(query)
if result:
most_concurrent.append(calc_most_concurrent(title, result))
except:
logger.warn("Unable to execute database query for get_home_stats: most_concurrent.")
except Exception as e:
logger.warn(u"PlexPy DataFactory :: Unable to execute database query for get_home_stats: most_concurrent: %s." % e)
return None
home_stats.append({'stat_id': stat,
@ -664,10 +666,10 @@ class DataFactory(object):
try:
query = 'SELECT section_id, section_name, section_type, thumb, count, parent_count, child_count ' \
'FROM library_sections ' \
'WHERE section_id = %s' % id
'WHERE section_id = %s ' % id
result = monitor_db.select(query)
except:
logger.warn("Unable to execute database query for get_library_stats.")
except Exception as e:
logger.warn(u"PlexPy DataFactory :: Unable to execute database query for get_library_stats: %s." % e)
return None
for item in result:
@ -725,86 +727,6 @@ class DataFactory(object):
return stream_output
def get_recently_watched(self, user=None, user_id=None, library_id=None, limit='10'):
monitor_db = database.MonitorDatabase()
recently_watched = []
if not limit.isdigit():
limit = '10'
try:
if user_id:
query = 'SELECT session_history.id, session_history.media_type, session_history.rating_key, session_history.parent_rating_key, ' \
'title, parent_title, grandparent_title, thumb, parent_thumb, grandparent_thumb, media_index, parent_media_index, ' \
'year, started, user ' \
'FROM session_history_metadata ' \
'JOIN session_history ON session_history_metadata.id = session_history.id ' \
'WHERE user_id = ? ' \
'GROUP BY (CASE WHEN session_history.media_type = "track" THEN session_history.parent_rating_key ' \
' ELSE session_history.rating_key END) ' \
'ORDER BY started DESC LIMIT ?'
result = monitor_db.select(query, args=[user_id, limit])
elif user:
query = 'SELECT session_history.id, session_history.media_type, session_history.rating_key, session_history.parent_rating_key, ' \
'title, parent_title, grandparent_title, thumb, parent_thumb, grandparent_thumb, media_index, parent_media_index, ' \
'year, started, user ' \
'FROM session_history_metadata ' \
'JOIN session_history ON session_history_metadata.id = session_history.id ' \
'WHERE user = ? ' \
'GROUP BY (CASE WHEN session_history.media_type = "track" THEN session_history.parent_rating_key ' \
' ELSE session_history.rating_key END) ' \
'ORDER BY started DESC LIMIT ?'
result = monitor_db.select(query, args=[user, limit])
elif library_id:
query = 'SELECT session_history.id, session_history.media_type, session_history.rating_key, session_history.parent_rating_key, ' \
'title, parent_title, grandparent_title, thumb, parent_thumb, grandparent_thumb, media_index, parent_media_index, ' \
'year, started, user ' \
'FROM session_history_metadata ' \
'JOIN session_history ON session_history_metadata.id = session_history.id ' \
'WHERE library_id = ? ' \
'GROUP BY (CASE WHEN session_history.media_type = "track" THEN session_history.parent_rating_key ' \
' ELSE session_history.rating_key END) ' \
'ORDER BY started DESC LIMIT ?'
result = monitor_db.select(query, args=[library_id, limit])
else:
query = 'SELECT session_history.id, session_history.media_type, session_history.rating_key, session_history.parent_rating_key, ' \
'title, parent_title, grandparent_title, thumb, parent_thumb, grandparent_thumb, media_index, parent_media_index, ' \
'year, started, user ' \
'FROM session_history_metadata ' \
'JOIN session_history ON session_history_metadata.id = session_history.id ' \
'GROUP BY (CASE WHEN session_history.media_type = "track" THEN session_history.parent_rating_key ' \
' ELSE session_history.rating_key END) ' \
'ORDER BY started DESC LIMIT ?'
result = monitor_db.select(query, args=[limit])
except:
logger.warn("Unable to execute database query for get_recently_watched.")
return None
for row in result:
if row['media_type'] == 'episode' and row['parent_thumb']:
thumb = row['parent_thumb']
elif row['media_type'] == 'episode':
thumb = row['grandparent_thumb']
else:
thumb = row['thumb']
recent_output = {'row_id': row['id'],
'type': row['media_type'],
'rating_key': row['rating_key'],
'title': row['title'],
'parent_title': row['parent_title'],
'grandparent_title': row['grandparent_title'],
'thumb': thumb,
'media_index': row['media_index'],
'parent_media_index': row['parent_media_index'],
'year': row['year'],
'time': row['started'],
'user': row['user']
}
recently_watched.append(recent_output)
return recently_watched
def get_metadata_details(self, rating_key):
monitor_db = database.MonitorDatabase()
@ -866,89 +788,52 @@ class DataFactory(object):
'directors': directors,
'genres': genres,
'actors': actors,
'library_title': item['section_name'],
'library_name': item['section_name'],
'library_id': item['library_id']
}
return metadata
def delete_session_history_rows(self, row_id=None):
def get_total_duration(self, custom_where=None):
monitor_db = database.MonitorDatabase()
if row_id.isdigit():
logger.info(u"PlexPy DataFactory :: Deleting row id %s from the session history database." % row_id)
session_history_del = \
monitor_db.action('DELETE FROM session_history WHERE id = ?', [row_id])
session_history_media_info_del = \
monitor_db.action('DELETE FROM session_history_media_info WHERE id = ?', [row_id])
session_history_metadata_del = \
monitor_db.action('DELETE FROM session_history_metadata WHERE id = ?', [row_id])
return 'Deleted rows %s.' % row_id
# Split up custom wheres
if custom_where:
where = 'WHERE ' + ' AND '.join([w[0] + ' = "' + w[1] + '"' for w in custom_where])
else:
return 'Unable to delete rows. Input row not valid.'
where = ''
try:
query = 'SELECT SUM(CASE WHEN stopped > 0 THEN (stopped - started) ELSE 0 END) - ' \
'SUM(CASE WHEN paused_counter IS NULL THEN 0 ELSE paused_counter END) AS total_duration ' \
'FROM session_history ' \
'JOIN session_history_metadata ON session_history_metadata.id = session_history.id ' \
'%s ' % where
result = monitor_db.select(query)
except Exception as e:
logger.warn(u"PlexPy DataFactory :: Unable to execute database query for get_total_duration: %s." % e)
return None
def delete_all_user_history(self, user_id=None):
for item in result:
total_duration = item['total_duration']
return total_duration
def get_session_ip(self, session_key=''):
monitor_db = database.MonitorDatabase()
if user_id.isdigit():
logger.info(u"PlexPy DataFactory :: Deleting all history for user id %s from database." % user_id)
session_history_media_info_del = \
monitor_db.action('DELETE FROM '
'session_history_media_info '
'WHERE session_history_media_info.id IN (SELECT session_history_media_info.id '
'FROM session_history_media_info '
'JOIN session_history ON session_history_media_info.id = session_history.id '
'WHERE session_history.user_id = ?)', [user_id])
session_history_metadata_del = \
monitor_db.action('DELETE FROM '
'session_history_metadata '
'WHERE session_history_metadata.id IN (SELECT session_history_metadata.id '
'FROM session_history_metadata '
'JOIN session_history ON session_history_metadata.id = session_history.id '
'WHERE session_history.user_id = ?)', [user_id])
session_history_del = \
monitor_db.action('DELETE FROM '
'session_history '
'WHERE session_history.user_id = ?', [user_id])
return 'Deleted all items for user_id %s.' % user_id
if session_key:
query = 'SELECT ip_address FROM sessions WHERE session_key = %d' % int(session_key)
result = monitor_db.select(query)
else:
return 'Unable to delete items. Input user_id not valid.'
return None
def delete_user(self, user_id=None):
monitor_db = database.MonitorDatabase()
ip_address = 'N/A'
if user_id.isdigit():
self.delete_all_user_history(user_id)
logger.info(u"PlexPy DataFactory :: 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 keep_history = 0 WHERE user_id = ?', [user_id])
monitor_db.action('UPDATE users SET do_notify = 0 WHERE user_id = ?', [user_id])
for item in result:
ip_address = item['ip_address']
return 'Deleted user with id %s.' % user_id
else:
return 'Unable to delete user. Input user_id not valid.'
def undelete_user(self, user_id=None, username=None):
monitor_db = database.MonitorDatabase()
if user_id and user_id.isdigit():
logger.info(u"PlexPy DataFactory :: 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 keep_history = 1 WHERE user_id = ?', [user_id])
monitor_db.action('UPDATE users SET do_notify = 1 WHERE user_id = ?', [user_id])
return 'Re-added user with id %s.' % user_id
elif username:
logger.info(u"PlexPy DataFactory :: 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 keep_history = 1 WHERE username = ?', [username])
monitor_db.action('UPDATE users SET do_notify = 1 WHERE username = ?', [username])
return 'Re-added user with username %s.' % username
else:
return 'Unable to re-add user. Input user_id or username not valid.'
return ip_address
def get_search_query(self, rating_key=''):
monitor_db = database.MonitorDatabase()
@ -1037,8 +922,8 @@ class DataFactory(object):
grandparent_rating_key = result[0]['grandparent_rating_key']
except:
logger.warn("Unable to execute database query for get_rating_keys_list.")
except Exception as e:
logger.warn(u"PlexPy DataFactory :: Unable to execute database query for get_rating_keys_list: %s." % e)
return {}
query = 'SELECT rating_key, parent_rating_key, grandparent_rating_key, title, parent_title, grandparent_title, ' \
@ -1081,6 +966,22 @@ class DataFactory(object):
return key_list
def delete_session_history_rows(self, row_id=None):
monitor_db = database.MonitorDatabase()
if row_id.isdigit():
logger.info(u"PlexPy DataFactory :: Deleting row id %s from the session history database." % row_id)
session_history_del = \
monitor_db.action('DELETE FROM session_history WHERE id = ?', [row_id])
session_history_media_info_del = \
monitor_db.action('DELETE FROM session_history_media_info WHERE id = ?', [row_id])
session_history_metadata_del = \
monitor_db.action('DELETE FROM session_history_metadata WHERE id = ?', [row_id])
return 'Deleted rows %s.' % row_id
else:
return 'Unable to delete rows. Input row not valid.'
def update_metadata(self, old_key_list='', new_key_list='', media_type=''):
from plexpy import pmsconnect
pms_connect = pmsconnect.PmsConnect()
@ -1134,8 +1035,6 @@ class DataFactory(object):
return 'Updated metadata in database.'
else:
return 'Unable to update metadata in database. No changes were made.'
# for debugging
#return mapping
def update_metadata_details(self, old_rating_key='', new_rating_key='', metadata=None):
@ -1176,31 +1075,6 @@ class DataFactory(object):
monitor_db.action(query=query, args=args)
def get_total_duration(self, custom_where=None):
monitor_db = database.MonitorDatabase()
# Split up custom wheres
if custom_where:
where = 'WHERE ' + ' AND '.join([w[0] + ' = "' + w[1] + '"' for w in custom_where])
else:
where = ''
try:
query = 'SELECT SUM(CASE WHEN stopped > 0 THEN (stopped - started) ELSE 0 END) - ' \
'SUM(CASE WHEN paused_counter IS NULL THEN 0 ELSE paused_counter END) AS total_duration ' \
'FROM session_history ' \
'JOIN session_history_metadata ON session_history_metadata.id = session_history.id ' \
'%s ' % where
result = monitor_db.select(query)
except:
logger.warn("Unable to execute database query for get_total_duration.")
return None
for item in result:
total_duration = item['total_duration']
return total_duration
def update_library_ids(self):
from plexpy import pmsconnect
@ -1210,8 +1084,8 @@ class DataFactory(object):
try:
query = 'SELECT id, rating_key FROM session_history_metadata WHERE library_id IS NULL'
result = monitor_db.select(query=query)
except:
logger.warn("Unable to execute database query for update_library_id.")
except Exception as e:
logger.warn(u"PlexPy DataFactory :: Unable to execute database query for update_library_id: %s." % e)
return None
for item in result:
@ -1230,60 +1104,4 @@ class DataFactory(object):
else:
continue
return True
def get_library_sections(self):
monitor_db = database.MonitorDatabase()
try:
query = 'SELECT section_id, section_name FROM library_sections'
result = monitor_db.select(query=query)
except:
logger.warn("Unable to execute database query for get_library_sections.")
return None
libraries = []
for item in result:
library = {'section_id': item['section_id'],
'section_name': item['section_name']
}
libraries.append(library)
return libraries
def update_library_sections(self):
from plexpy import pmsconnect
pms_connect = pmsconnect.PmsConnect()
library_sections = pms_connect.get_server_children()
if library_sections:
if library_sections['libraries_count'] != '0':
monitor_db = database.MonitorDatabase()
for section in library_sections['libraries_list']:
section_keys = {'section_id': section['key']}
section_values = {'section_id': section['key'],
'section_name': section['title'],
'section_type': section['type']}
monitor_db.upsert('library_sections', key_dict=section_keys, value_dict=section_values)
return True
def get_session_ip(self, session_key=''):
monitor_db = database.MonitorDatabase()
if session_key:
query = 'SELECT ip_address FROM sessions WHERE session_key = %d' % int(session_key)
result = monitor_db.select(query)
else:
return None
ip_address = 'N/A'
for item in result:
ip_address = item['ip_address']
return ip_address
return True

View file

@ -14,6 +14,7 @@
# along with PlexPy. If not, see <http://www.gnu.org/licenses/>.
from plexpy import logger, datatables, common, database, helpers
import plexpy
class Libraries(object):
@ -21,22 +22,23 @@ class Libraries(object):
def __init__(self):
pass
def get_library_list(self, kwargs=None):
def get_datatables_list(self, kwargs=None):
data_tables = datatables.DataTables()
custom_where = ['library_sections.deleted_section', 0]
columns = ['library_sections.section_id',
'library_sections.section_name',
'library_sections.section_type',
'library_sections.count as count',
'library_sections.count',
'library_sections.parent_count',
'library_sections.child_count',
'library_sections.thumb AS library_thumb',
'(CASE WHEN library_sections.custom_thumb_url == library_sections.thumb \
THEN NULL ELSE custom_thumb_url END) AS custom_thumb',
'library_sections.custom_thumb_url AS custom_thumb',
'library_sections.art',
'COUNT(session_history.id) as plays',
'MAX(session_history.started) as last_accessed',
'session_history_metadata.full_title as last_watched',
'COUNT(session_history.id) AS plays',
'MAX(session_history.started) AS last_accessed',
'session_history_metadata.full_title AS last_watched',
'session_history_metadata.thumb',
'session_history_metadata.parent_thumb',
'session_history_metadata.grandparent_thumb',
@ -44,12 +46,13 @@ class Libraries(object):
'session_history.rating_key',
'session_history_media_info.video_decision',
'library_sections.do_notify',
'library_sections.do_notify_created',
'library_sections.keep_history'
]
try:
query = data_tables.ssp_query(table_name='library_sections',
columns=columns,
custom_where=[],
custom_where=[custom_where],
group_by=['library_sections.section_id'],
join_types=['LEFT OUTER JOIN',
'LEFT OUTER JOIN',
@ -61,8 +64,8 @@ class Libraries(object):
['session_history_metadata.id', 'session_history.id'],
['session_history_metadata.id', 'session_history_media_info.id']],
kwargs=kwargs)
except:
logger.warn("Unable to execute database query for get_library_list.")
except Exception as e:
logger.warn(u"PlexPy Libraries :: Unable to execute database query for get_list: %s." % e)
return {'recordsFiltered': 0,
'recordsTotal': 0,
'draw': 0,
@ -80,23 +83,30 @@ class Libraries(object):
else:
thumb = item['thumb']
row = {'plays': item['plays'],
if item['custom_thumb'] and item['custom_thumb'] != item['library_thumb']:
library_thumb = item['custom_thumb']
elif item['library_thumb']:
library_thumb = item['library_thumb']
else:
library_thumb = common.DEFAULT_COVER_THUMB
row = {'section_id': item['section_id'],
'section_name': item['section_name'],
'section_type': item['section_type'].capitalize(),
'count': item['count'],
'parent_count': item['parent_count'],
'child_count': item['child_count'],
'library_thumb': library_thumb,
'library_art': item['art'],
'plays': item['plays'],
'last_accessed': item['last_accessed'],
'last_watched': item['last_watched'],
'thumb': thumb,
'media_type': item['media_type'],
'rating_key': item['rating_key'],
'video_decision': item['video_decision'],
'section_id': item['section_id'],
'section_name': item['section_name'],
'section_type': item['section_type'].capitalize(),
'count': item['count'],
'parent_count': item['parent_count'],
'library_thumb': item['library_thumb'],
'custom_thumb': item['custom_thumb'],
'library_art': item['art'],
'child_count': item['child_count'],
'do_notify': helpers.checked(item['do_notify']),
'do_notify_created': helpers.checked(item['do_notify_created']),
'keep_history': helpers.checked(item['keep_history'])
}
@ -110,123 +120,154 @@ class Libraries(object):
return dict
def set_library_config(self, section_id=None, do_notify=1, keep_history=1, custom_thumb=''):
def set_config(self, section_id=None, custom_thumb='', do_notify=1, keep_history=1, do_notify_created=1):
if section_id:
monitor_db = database.MonitorDatabase()
key_dict = {'section_id': section_id}
value_dict = {'do_notify': do_notify,
'keep_history': keep_history,
'custom_thumb_url': custom_thumb}
value_dict = {'custom_thumb_url': custom_thumb,
'do_notify': do_notify,
'do_notify_created': do_notify_created,
'keep_history': keep_history}
try:
monitor_db.upsert('library_sections', value_dict, key_dict)
except:
logger.warn("Unable to execute database query for set_user_friendly_name.")
logger.warn(u"PlexPy Libraries :: Unable to execute database query for set_config: %s." % e)
def get_library_details(self, section_id=None):
def get_details(self, section_id=None):
from plexpy import pmsconnect
monitor_db = database.MonitorDatabase()
if section_id:
query = 'SELECT section_id, section_name, section_type, count, parent_count, child_count, ' \
'thumb AS library_thumb, (CASE WHEN library_sections.custom_thumb_url == library_sections.thumb ' \
' THEN NULL ELSE custom_thumb_url END) AS custom_thumb, art, do_notify, keep_history ' \
'FROM library_sections ' \
'WHERE section_id = ? '
result = monitor_db.select(query, args=[section_id])
else:
result = None
try:
if section_id:
query = 'SELECT section_id, section_name, section_type, count, parent_count, child_count, ' \
'thumb AS library_thumb, custom_thumb_url AS custom_thumb, art, ' \
'do_notify, do_notify_created, keep_history ' \
'FROM library_sections ' \
'WHERE section_id = ? '
result = monitor_db.select(query, args=[section_id])
else:
result = []
except Exception as e:
logger.warn(u"PlexPy Libraries :: Unable to execute database query for get_details: %s." % e)
result = []
if result:
library_details = {}
for item in result:
if item['custom_thumb'] and item['custom_thumb'] != item['library_thumb']:
library_thumb = item['custom_thumb']
elif item['library_thumb']:
library_thumb = item['library_thumb']
else:
library_thumb = common.DEFAULT_COVER_THUMB
library_details = {'section_id': item['section_id'],
'section_name': item['section_name'],
'section_type': item['section_type'],
'library_thumb': item['library_thumb'],
'custom_thumb': item['custom_thumb'],
'library_thumb': library_thumb,
'library_art': item['art'],
'count': item['count'],
'parent_count': item['parent_count'],
'child_count': item['child_count'],
'do_notify': item['do_notify'],
'do_notify_created': item['do_notify_created'],
'keep_history': item['keep_history']
}
return library_details
else:
logger.warn(u"PlexPy :: Unable to retrieve library from local database. Requesting library list refresh.")
logger.warn(u"PlexPy Libraries :: Unable to retrieve library from local database. Requesting library list refresh.")
# Let's first refresh the user list to make sure the user isn't newly added and not in the db yet
if section_id:
# Refresh libraries
pmsconnect.refresh_libraries()
query = 'SELECT section_id, section_name, section_type, count, parent_count, child_count, ' \
'thumb AS library_thumb, (CASE WHEN library_sections.custom_thumb_url == library_sections.thumb ' \
' THEN NULL ELSE custom_thumb_url END) AS custom_thumb, art, do_notify, keep_history ' \
'FROM library_sections ' \
'WHERE section_id = ? '
result = monitor_db.select(query, args=[section_id])
else:
result = None
try:
if section_id:
# Refresh libraries
pmsconnect.refresh_libraries()
query = 'SELECT section_id, section_name, section_type, count, parent_count, child_count, ' \
'thumb AS library_thumb, custom_thumb_url AS custom_thumb, art, ' \
'do_notify, do_notify_created, keep_history ' \
'FROM library_sections ' \
'WHERE section_id = ? '
result = monitor_db.select(query, args=[section_id])
else:
result = []
except:
logger.warn(u"PlexPy Libraries :: Unable to execute database query for get_details: %s." % e)
result = []
if result:
library_details = {}
for item in result:
if item['custom_thumb'] and item['custom_thumb'] != item['library_thumb']:
library_thumb = item['custom_thumb']
elif item['library_thumb']:
library_thumb = item['library_thumb']
else:
library_thumb = common.DEFAULT_COVER_THUMB
library_details = {'section_id': item['section_id'],
'section_name': item['section_name'],
'section_type': item['section_type'],
'library_thumb': item['library_thumb'],
'custom_thumb': item['custom_thumb'],
'library_thumb': library_thumb,
'library_art': item['art'],
'count': item['count'],
'parent_count': item['parent_count'],
'child_count': item['child_count'],
'do_notify': item['do_notify'],
'do_notify_created': item['do_notify_created'],
'keep_history': item['keep_history']
}
return user_details
return library_details
else:
# If there is no library data we must return something
# Use "Local" user to retain compatibility with PlexWatch database value
return {'section_id': None,
'section_name': '',
'section_name': 'Local',
'section_type': '',
'library_thumb': '',
'custom_thumb': '',
'library_thumb': common.DEFAULT_COVER_THUMB,
'library_art': '',
'count': 0,
'parent_count': 0,
'child_count': 0,
'do_notify': 0,
'do_notify_created': 0,
'keep_history': 0
}
def get_library_watch_time_stats(self, library_id=None):
def get_watch_time_stats(self, library_id=None):
monitor_db = database.MonitorDatabase()
time_queries = [1, 7, 30, 0]
library_watch_time_stats = []
for days in time_queries:
if days > 0:
if library_id:
query = 'SELECT (SUM(stopped - started) - ' \
'SUM(CASE WHEN paused_counter is null THEN 0 ELSE paused_counter END)) as total_time, ' \
'COUNT(session_history.id) AS total_plays ' \
'FROM session_history ' \
'JOIN session_history_metadata ON session_history_metadata.id = session_history.id ' \
'WHERE datetime(stopped, "unixepoch", "localtime") >= datetime("now", "-%s days", "localtime") ' \
'AND library_id = ?' % days
result = monitor_db.select(query, args=[library_id])
else:
query = 'SELECT (SUM(stopped - started) - ' \
'SUM(CASE WHEN paused_counter is null THEN 0 ELSE paused_counter END)) as total_time, ' \
'COUNT(session_history.id) AS total_plays ' \
'FROM session_history ' \
'JOIN session_history_metadata ON session_history_metadata.id = session_history.id ' \
'WHERE library_id = ?'
result = monitor_db.select(query, args=[library_id])
try:
if days > 0:
if str(library_id).isdigit():
query = 'SELECT (SUM(stopped - started) - ' \
'SUM(CASE WHEN paused_counter is null THEN 0 ELSE paused_counter END)) as total_time, ' \
'COUNT(session_history.id) AS total_plays ' \
'FROM session_history ' \
'JOIN session_history_metadata ON session_history_metadata.id = session_history.id ' \
'WHERE datetime(stopped, "unixepoch", "localtime") >= datetime("now", "-%s days", "localtime") ' \
'AND library_id = ?' % days
result = monitor_db.select(query, args=[library_id])
else:
result = []
else:
if str(library_id).isdigit():
query = 'SELECT (SUM(stopped - started) - ' \
'SUM(CASE WHEN paused_counter is null THEN 0 ELSE paused_counter END)) as total_time, ' \
'COUNT(session_history.id) AS total_plays ' \
'FROM session_history ' \
'JOIN session_history_metadata ON session_history_metadata.id = session_history.id ' \
'WHERE library_id = ?'
result = monitor_db.select(query, args=[library_id])
else:
result = []
except Exception as e:
logger.warn(u"PlexPy Libraries :: Unable to execute database query for get_watch_time_stats: %s." % e)
result = []
for item in result:
if item['total_time']:
@ -245,13 +286,13 @@ class Libraries(object):
return library_watch_time_stats
def get_library_user_stats(self, library_id=None):
def get_user_stats(self, library_id=None):
monitor_db = database.MonitorDatabase()
user_stats = []
try:
if library_id:
if str(library_id).isdigit():
query = 'SELECT (CASE WHEN users.friendly_name IS NULL THEN users.username ' \
'ELSE users.friendly_name END) AS user, users.user_id, users.thumb, COUNT(user) AS user_count ' \
'FROM session_history ' \
@ -261,9 +302,11 @@ class Libraries(object):
'GROUP BY user ' \
'ORDER BY user_count DESC'
result = monitor_db.select(query, args=[library_id])
except:
logger.warn("Unable to execute database query for get_library_user_stats.")
return None
else:
result = []
except Exception as e:
logger.warn(u"PlexPy Libraries :: Unable to execute database query for get_user_stats: %s." % e)
result = []
for item in result:
row = {'user': item['user'],
@ -275,30 +318,151 @@ class Libraries(object):
return user_stats
def delete_all_library_history(self, section_id=None):
def get_recently_watched(self, library_id=None, limit='10'):
monitor_db = database.MonitorDatabase()
recently_watched = []
if not limit.isdigit():
limit = '10'
try:
if str(library_id).isdigit():
query = 'SELECT session_history.id, session_history.media_type, session_history.rating_key, session_history.parent_rating_key, ' \
'title, parent_title, grandparent_title, thumb, parent_thumb, grandparent_thumb, media_index, parent_media_index, ' \
'year, started, user ' \
'FROM session_history_metadata ' \
'JOIN session_history ON session_history_metadata.id = session_history.id ' \
'WHERE library_id = ? ' \
'GROUP BY (CASE WHEN session_history.media_type = "track" THEN session_history.parent_rating_key ' \
' ELSE session_history.rating_key END) ' \
'ORDER BY started DESC LIMIT ?'
result = monitor_db.select(query, args=[library_id, limit])
else:
result = []
except Exception as e:
logger.warn(u"PlexPy Libraries :: Unable to execute database query for get_recently_watched: %s." % e)
result = []
for row in result:
if row['media_type'] == 'episode' and row['parent_thumb']:
thumb = row['parent_thumb']
elif row['media_type'] == 'episode':
thumb = row['grandparent_thumb']
else:
thumb = row['thumb']
recent_output = {'row_id': row['id'],
'type': row['media_type'],
'rating_key': row['rating_key'],
'title': row['title'],
'parent_title': row['parent_title'],
'grandparent_title': row['grandparent_title'],
'thumb': thumb,
'media_index': row['media_index'],
'parent_media_index': row['parent_media_index'],
'year': row['year'],
'time': row['started'],
'user': row['user']
}
recently_watched.append(recent_output)
return recently_watched
def get_sections(self):
monitor_db = database.MonitorDatabase()
if section_id.isdigit():
logger.info(u"PlexPy Libraries :: Deleting all history for library id %s from database." % section_id)
session_history_media_info_del = \
monitor_db.action('DELETE FROM '
'session_history_media_info '
'WHERE session_history_media_info.id IN (SELECT session_history_media_info.id '
'FROM session_history_media_info '
'JOIN session_history_metadata ON session_history_media_info.id = session_history_metadata.id '
'WHERE session_history_metadata.library_id = ?)', [section_id])
session_history_del = \
monitor_db.action('DELETE FROM '
'session_history '
'WHERE session_history.id IN (SELECT session_history.id '
'FROM session_history '
'JOIN session_history_metadata ON session_history.id = session_history_metadata.id '
'WHERE session_history_metadata.library_id = ?)', [section_id])
session_history_metadata_del = \
monitor_db.action('DELETE FROM '
'session_history_metadata '
'WHERE session_history_metadata.library_id = ?', [section_id])
try:
query = 'SELECT section_id, section_name FROM library_sections WHERE deleted_section = 0'
result = monitor_db.select(query=query)
except Exception as e:
logger.warn(u"PlexPy Libraries :: Unable to execute database query for get_sections: %s." % e)
return None
return 'Deleted all items for library_id %s.' % section_id
else:
return 'Unable to delete items. Input library_id not valid.'
libraries = []
for item in result:
library = {'section_id': item['section_id'],
'section_name': item['section_name']
}
libraries.append(library)
return libraries
def delete_all_history(self, section_id=None):
monitor_db = database.MonitorDatabase()
try:
if section_id.isdigit():
logger.info(u"PlexPy Libraries :: Deleting all history for library id %s from database." % section_id)
session_history_media_info_del = \
monitor_db.action('DELETE FROM '
'session_history_media_info '
'WHERE session_history_media_info.id IN (SELECT session_history_media_info.id '
'FROM session_history_media_info '
'JOIN session_history_metadata ON session_history_media_info.id = session_history_metadata.id '
'WHERE session_history_metadata.library_id = ?)', [section_id])
session_history_del = \
monitor_db.action('DELETE FROM '
'session_history '
'WHERE session_history.id IN (SELECT session_history.id '
'FROM session_history '
'JOIN session_history_metadata ON session_history.id = session_history_metadata.id '
'WHERE session_history_metadata.library_id = ?)', [section_id])
session_history_metadata_del = \
monitor_db.action('DELETE FROM '
'session_history_metadata '
'WHERE session_history_metadata.library_id = ?', [section_id])
return 'Deleted all items for section_id %s.' % section_id
else:
return 'Unable to delete items, section_id not valid.'
except Exception as e:
logger.warn(u"PlexPy Libraries :: Unable to execute database query for delete_all_history: %s." % e)
def delete(self, section_id=None):
monitor_db = database.MonitorDatabase()
try:
if section_id.isdigit():
self.delete_all_history(section_id)
logger.info(u"PlexPy 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 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_created = 0 WHERE section_id = ?', [section_id])
library_cards = plexpy.CONFIG.HOME_LIBRARY_CARDS
if section_id in library_cards:
library_cards.remove(section_id)
plexpy.CONFIG.__setattr__('HOME_LIBRARY_CARDS', library_cards)
plexpy.CONFIG.write()
return 'Deleted library with id %s.' % section_id
else:
return 'Unable to delete library, section_id not valid.'
except Exception as e:
logger.warn(u"PlexPy Libraries :: Unable to execute database query for delete: %s." % e)
def undelete(self, section_id=None, section_name=None):
monitor_db = database.MonitorDatabase()
try:
if section_id and section_id.isdigit():
logger.info(u"PlexPy 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 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_created = 1 WHERE section_id = ?', [section_id])
return 'Re-added library with id %s.' % section_id
elif section_name:
logger.info(u"PlexPy 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 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_created = 1 WHERE section_name = ?', [section_name])
return 'Re-added library with section_name %s.' % section_name
else:
return 'Unable to re-add library, section_id or section_name not valid.'
except Exception as e:
logger.warn(u"PlexPy Libraries :: Unable to execute database query for undelete: %s." % e)

View file

@ -16,20 +16,28 @@
import re
import time
import re
from plexpy import logger, config, notifiers, database, helpers, plextv, pmsconnect
import plexpy
def notify(stream_data=None, notify_action=None):
from plexpy import users
from plexpy import users, libraries
if stream_data and notify_action:
# Check if notifications enabled for user
# Check if notifications enabled for user and library
user_data = users.Users()
user_details = user_data.get_user_friendly_name(user=stream_data['user'])
user_details = user_data.get_details(user_id=stream_data['user_id'])
library_data = libraries.Libraries()
library_details = library_data.get_details(section_id=stream_data['library_id'])
if not user_details['do_notify']:
# logger.debug(u"PlexPy NotificationHandler :: Notifications for user '%s' is disabled." % user_details['username'])
return
elif not library_details['do_notify']:
# logger.debug(u"PlexPy NotificationHandler :: Notifications for library '%s' is disabled." % library_details['section_name'])
return
if (stream_data['media_type'] == 'movie' and plexpy.CONFIG.MOVIE_NOTIFY_ENABLE) \
@ -195,10 +203,10 @@ def notify(stream_data=None, notify_action=None):
elif stream_data['media_type'] == 'clip':
pass
else:
#logger.debug(u"PlexPy Notifier :: Notify called with unsupported media type.")
#logger.debug(u"PlexPy NotificationHandler :: Notify called with unsupported media type.")
pass
else:
logger.debug(u"PlexPy Notifier :: Notify called but incomplete data received.")
logger.debug(u"PlexPy NotificationHandler :: Notify called but incomplete data received.")
def notify_timeline(timeline_data=None, notify_action=None):
@ -256,7 +264,7 @@ def notify_timeline(timeline_data=None, notify_action=None):
notify_action=notify_action,
script_args=notify_strings[2])
else:
logger.debug(u"PlexPy Notifier :: Notify timeline called but incomplete data received.")
logger.debug(u"PlexPy NotificationHandler :: Notify timeline called but incomplete data received.")
def get_notify_state(session):
@ -334,11 +342,10 @@ def set_notify_state(session, state, agent_info):
monitor_db.upsert(table_name='notify_log', key_dict=keys, value_dict=values)
else:
logger.error('PlexPy Notifier :: Unable to set notify state.')
logger.error(u"PlexPy NotificationHandler :: Unable to set notify state.")
def build_notify_text(session=None, timeline=None, state=None):
# Get the server name
server_name = plexpy.CONFIG.PMS_NAME
@ -350,7 +357,7 @@ def build_notify_text(session=None, timeline=None, state=None):
updated_at = server_times[0]['updated_at']
server_uptime = helpers.human_duration(int(time.time() - helpers.cast_to_float(updated_at)))
else:
logger.error(u"PlexPy Notifier :: Unable to retrieve server uptime.")
logger.error(u"PlexPy NotificationHandler :: Unable to retrieve server uptime.")
server_uptime = 'N/A'
# Get metadata feed for item
@ -367,7 +374,7 @@ def build_notify_text(session=None, timeline=None, state=None):
if metadata_list:
metadata = metadata_list['metadata']
else:
logger.error(u"PlexPy Notifier :: Unable to retrieve metadata for rating_key %s" % str(rating_key))
logger.error(u"PlexPy NotificationHandler :: Unable to retrieve metadata for rating_key %s" % str(rating_key))
return []
# Check for exclusion tags
@ -547,15 +554,16 @@ def build_notify_text(session=None, timeline=None, state=None):
'transcode_audio_codec': transcode_audio_codec,
'transcode_audio_channels': transcode_audio_channels,
'title': full_title,
'library_name': metadata['library_name'],
'show_name': show_name,
'episode_name': episode_name,
'artist_name': artist_name,
'album_name': album_name,
'track_name': track_name,
'season_num': metadata['parent_index'].zfill(1),
'season_num00': metadata['parent_index'].zfill(2),
'episode_num': metadata['index'].zfill(1),
'episode_num00': metadata['index'].zfill(2),
'season_num': metadata['parent_media_index'].zfill(1),
'season_num00': metadata['parent_media_index'].zfill(2),
'episode_num': metadata['media_index'].zfill(1),
'episode_num00': metadata['media_index'].zfill(2),
'year': metadata['year'],
'studio': metadata['studio'],
'content_rating': metadata['content_rating'],
@ -597,16 +605,16 @@ def build_notify_text(session=None, timeline=None, state=None):
try:
subject_text = unicode(on_start_subject).format(**available_params)
except LookupError, e:
logger.error(u"PlexPy Notifier :: Unable to parse field %s in notification subject. Using fallback." % e)
logger.error(u"PlexPy NotificationHandler :: Unable to parse field %s in notification subject. Using fallback." % e)
except:
logger.error(u"PlexPy Notifier :: Unable to parse custom notification subject. Using fallback.")
logger.error(u"PlexPy NotificationHandler :: Unable to parse custom notification subject. Using fallback.")
try:
body_text = unicode(on_start_body).format(**available_params)
except LookupError, e:
logger.error(u"PlexPy Notifier :: Unable to parse field %s in notification body. Using fallback." % e)
logger.error(u"PlexPy NotificationHandler :: Unable to parse field %s in notification body. Using fallback." % e)
except:
logger.error(u"PlexPy Notifier :: Unable to parse custom notification body. Using fallback.")
logger.error(u"PlexPy NotificationHandler :: Unable to parse custom notification body. Using fallback.")
return [subject_text, body_text, script_args]
else:
@ -621,16 +629,16 @@ def build_notify_text(session=None, timeline=None, state=None):
try:
subject_text = unicode(on_stop_subject).format(**available_params)
except LookupError, e:
logger.error(u"PlexPy Notifier :: Unable to parse field %s in notification subject. Using fallback." % e)
logger.error(u"PlexPy NotificationHandler :: Unable to parse field %s in notification subject. Using fallback." % e)
except:
logger.error(u"PlexPy Notifier :: Unable to parse custom notification subject. Using fallback.")
logger.error(u"PlexPy NotificationHandler :: Unable to parse custom notification subject. Using fallback.")
try:
body_text = unicode(on_stop_body).format(**available_params)
except LookupError, e:
logger.error(u"PlexPy Notifier :: Unable to parse field %s in notification body. Using fallback." % e)
logger.error(u"PlexPy NotificationHandler :: Unable to parse field %s in notification body. Using fallback." % e)
except:
logger.error(u"PlexPy Notifier :: Unable to parse custom notification body. Using fallback.")
logger.error(u"PlexPy NotificationHandler :: Unable to parse custom notification body. Using fallback.")
return [subject_text, body_text, script_args]
else:
@ -645,16 +653,16 @@ def build_notify_text(session=None, timeline=None, state=None):
try:
subject_text = unicode(on_pause_subject).format(**available_params)
except LookupError, e:
logger.error(u"PlexPy Notifier :: Unable to parse field %s in notification subject. Using fallback." % e)
logger.error(u"PlexPy NotificationHandler :: Unable to parse field %s in notification subject. Using fallback." % e)
except:
logger.error(u"PlexPy Notifier :: Unable to parse custom notification subject. Using fallback.")
logger.error(u"PlexPy NotificationHandler :: Unable to parse custom notification subject. Using fallback.")
try:
body_text = unicode(on_pause_body).format(**available_params)
except LookupError, e:
logger.error(u"PlexPy Notifier :: Unable to parse field %s in notification body. Using fallback." % e)
logger.error(u"PlexPy NotificationHandler :: Unable to parse field %s in notification body. Using fallback." % e)
except:
logger.error(u"PlexPy Notifier :: Unable to parse custom notification body. Using fallback.")
logger.error(u"PlexPy NotificationHandler :: Unable to parse custom notification body. Using fallback.")
return [subject_text, body_text, script_args]
else:
@ -669,16 +677,16 @@ def build_notify_text(session=None, timeline=None, state=None):
try:
subject_text = unicode(on_resume_subject).format(**available_params)
except LookupError, e:
logger.error(u"PlexPy Notifier :: Unable to parse field %s in notification subject. Using fallback." % e)
logger.error(u"PlexPy NotificationHandler :: Unable to parse field %s in notification subject. Using fallback." % e)
except:
logger.error(u"PlexPy Notifier :: Unable to parse custom notification subject. Using fallback.")
logger.error(u"PlexPy NotificationHandler :: Unable to parse custom notification subject. Using fallback.")
try:
body_text = unicode(on_resume_body).format(**available_params)
except LookupError, e:
logger.error(u"PlexPy Notifier :: Unable to parse field %s in notification body. Using fallback." % e)
logger.error(u"PlexPy NotificationHandler :: Unable to parse field %s in notification body. Using fallback." % e)
except:
logger.error(u"PlexPy Notifier :: Unable to parse custom notification body. Using fallback.")
logger.error(u"PlexPy NotificationHandler :: Unable to parse custom notification body. Using fallback.")
return [subject_text, body_text, script_args]
else:
@ -693,16 +701,16 @@ def build_notify_text(session=None, timeline=None, state=None):
try:
subject_text = unicode(on_buffer_subject).format(**available_params)
except LookupError, e:
logger.error(u"PlexPy Notifier :: Unable to parse field %s in notification subject. Using fallback." % e)
logger.error(u"PlexPy NotificationHandler :: Unable to parse field %s in notification subject. Using fallback." % e)
except:
logger.error(u"PlexPy Notifier :: Unable to parse custom notification subject. Using fallback.")
logger.error(u"PlexPy NotificationHandler :: Unable to parse custom notification subject. Using fallback.")
try:
body_text = unicode(on_buffer_body).format(**available_params)
except LookupError, e:
logger.error(u"PlexPy Notifier :: Unable to parse field %s in notification body. Using fallback." % e)
logger.error(u"PlexPy NotificationHandler :: Unable to parse field %s in notification body. Using fallback." % e)
except:
logger.error(u"PlexPy Notifier :: Unable to parse custom notification body. Using fallback.")
logger.error(u"PlexPy NotificationHandler :: Unable to parse custom notification body. Using fallback.")
return [subject_text, body_text, script_args]
else:
@ -717,16 +725,16 @@ def build_notify_text(session=None, timeline=None, state=None):
try:
subject_text = unicode(on_watched_subject).format(**available_params)
except LookupError, e:
logger.error(u"PlexPy Notifier :: Unable to parse field %s in notification subject. Using fallback." % e)
logger.error(u"PlexPy NotificationHandler :: Unable to parse field %s in notification subject. Using fallback." % e)
except:
logger.error(u"PlexPy Notifier :: Unable to parse custom notification subject. Using fallback.")
logger.error(u"PlexPy NotificationHandler :: Unable to parse custom notification subject. Using fallback.")
try:
body_text = unicode(on_watched_body).format(**available_params)
except LookupError, e:
logger.error(u"PlexPy Notifier :: Unable to parse field %s in notification body. Using fallback." % e)
logger.error(u"PlexPy NotificationHandler :: Unable to parse field %s in notification body. Using fallback." % e)
except:
logger.error(u"PlexPy Notifier :: Unable to parse custom notification body. Using fallback.")
logger.error(u"PlexPy NotificationHandler :: Unable to parse custom notification body. Using fallback.")
return [subject_text, body_text, script_args]
else:
@ -739,16 +747,16 @@ def build_notify_text(session=None, timeline=None, state=None):
try:
subject_text = unicode(on_created_subject).format(**available_params)
except LookupError, e:
logger.error(u"PlexPy Notifier :: Unable to parse field %s in notification subject. Using fallback." % e)
logger.error(u"PlexPy NotificationHandler :: Unable to parse field %s in notification subject. Using fallback." % e)
except:
logger.error(u"PlexPy Notifier :: Unable to parse custom notification subject. Using fallback.")
logger.error(u"PlexPy NotificationHandler :: Unable to parse custom notification subject. Using fallback.")
try:
body_text = unicode(on_created_body).format(**available_params)
except LookupError, e:
logger.error(u"PlexPy Notifier :: Unable to parse field %s in notification body. Using fallback." % e)
logger.error(u"PlexPy NotificationHandler :: Unable to parse field %s in notification body. Using fallback." % e)
except:
logger.error(u"PlexPy Notifier :: Unable to parse custom notification body. Using fallback.")
logger.error(u"PlexPy NotificationHandler :: Unable to parse custom notification body. Using fallback.")
return [subject_text, body_text, script_args]
else:
@ -769,7 +777,7 @@ def build_server_notify_text(state=None):
updated_at = server_times[0]['updated_at']
server_uptime = helpers.human_duration(int(time.time() - helpers.cast_to_float(updated_at)))
else:
logger.error(u"PlexPy Notifier :: Unable to retrieve server uptime.")
logger.error(u"PlexPy NotificationHandler :: Unable to retrieve server uptime.")
server_uptime = 'N/A'
on_extdown_subject = plexpy.CONFIG.NOTIFY_ON_EXTDOWN_SUBJECT_TEXT
@ -812,14 +820,14 @@ def build_server_notify_text(state=None):
try:
subject_text = unicode(on_extdown_subject).format(**available_params)
except LookupError, e:
logger.error(u"PlexPy Notifier :: Unable to parse field %s in notification subject. Using fallback." % e)
logger.error(u"PlexPy NotificationHandler :: Unable to parse field %s in notification subject. Using fallback." % e)
except:
logger.error(u"PlexPy Notifier :: Unable to parse custom notification subject. Using fallback.")
logger.error(u"PlexPy NotificationHandler :: Unable to parse custom notification subject. Using fallback.")
try:
body_text = unicode(on_extdown_body).format(**available_params)
except LookupError, e:
logger.error(u"PlexPy Notifier :: Unable to parse field %s in notification body. Using fallback." % e)
logger.error(u"PlexPy NotificationHandler :: Unable to parse field %s in notification body. Using fallback." % e)
except:
logger.error(u"PlexPy Notifier :: Unable to parse custom notification body. Using fallback.")
@ -835,16 +843,16 @@ def build_server_notify_text(state=None):
try:
subject_text = unicode(on_intdown_subject).format(**available_params)
except LookupError, e:
logger.error(u"PlexPy Notifier :: Unable to parse field %s in notification subject. Using fallback." % e)
logger.error(u"PlexPy NotificationHandler :: Unable to parse field %s in notification subject. Using fallback." % e)
except:
logger.error(u"PlexPy Notifier :: Unable to parse custom notification subject. Using fallback.")
logger.error(u"PlexPy NotificationHandler :: Unable to parse custom notification subject. Using fallback.")
try:
body_text = unicode(on_intdown_body).format(**available_params)
except LookupError, e:
logger.error(u"PlexPy Notifier :: Unable to parse field %s in notification body. Using fallback." % e)
logger.error(u"PlexPy NotificationHandler :: Unable to parse field %s in notification body. Using fallback." % e)
except:
logger.error(u"PlexPy Notifier :: Unable to parse custom notification body. Using fallback.")
logger.error(u"PlexPy NotificationHandler :: Unable to parse custom notification body. Using fallback.")
return [subject_text, body_text, script_args]
else:
@ -857,16 +865,16 @@ def build_server_notify_text(state=None):
try:
subject_text = unicode(on_extup_subject).format(**available_params)
except LookupError, e:
logger.error(u"PlexPy Notifier :: Unable to parse field %s in notification subject. Using fallback." % e)
logger.error(u"PlexPy NotificationHandler :: Unable to parse field %s in notification subject. Using fallback." % e)
except:
logger.error(u"PlexPy Notifier :: Unable to parse custom notification subject. Using fallback.")
logger.error(u"PlexPy NotificationHandler :: Unable to parse custom notification subject. Using fallback.")
try:
body_text = unicode(on_extup_body).format(**available_params)
except LookupError, e:
logger.error(u"PlexPy Notifier :: Unable to parse field %s in notification body. Using fallback." % e)
logger.error(u"PlexPy NotificationHandler :: Unable to parse field %s in notification body. Using fallback." % e)
except:
logger.error(u"PlexPy Notifier :: Unable to parse custom notification body. Using fallback.")
logger.error(u"PlexPy NotificationHandler :: Unable to parse custom notification body. Using fallback.")
return [subject_text, body_text, script_args]
else:
@ -879,16 +887,16 @@ def build_server_notify_text(state=None):
try:
subject_text = unicode(on_intup_subject).format(**available_params)
except LookupError, e:
logger.error(u"PlexPy Notifier :: Unable to parse field %s in notification subject. Using fallback." % e)
logger.error(u"PlexPy NotificationHandler :: Unable to parse field %s in notification subject. Using fallback." % e)
except:
logger.error(u"PlexPy Notifier :: Unable to parse custom notification subject. Using fallback.")
logger.error(u"PlexPy NotificationHandler :: Unable to parse custom notification subject. Using fallback.")
try:
body_text = unicode(on_intup_body).format(**available_params)
except LookupError, e:
logger.error(u"PlexPy Notifier :: Unable to parse field %s in notification body. Using fallback." % e)
logger.error(u"PlexPy NotificationHandler :: Unable to parse field %s in notification body. Using fallback." % e)
except:
logger.error(u"PlexPy Notifier :: Unable to parse custom notification body. Using fallback.")
logger.error(u"PlexPy NotificationHandler :: Unable to parse custom notification body. Using fallback.")
return [subject_text, body_text, script_args]
else:
@ -899,7 +907,5 @@ def build_server_notify_text(state=None):
def strip_tag(data):
import re
p = re.compile(r'<.*?>')
return p.sub('', data)

View file

@ -525,10 +525,10 @@ class GROWL(object):
try:
growl.register()
except gntp.notifier.errors.NetworkError:
logger.warning(u'Growl notification failed: network error')
logger.warn(u"PlexPy Notifier :: Growl notification failed: network error")
return
except gntp.notifier.errors.AuthError:
logger.warning(u'Growl notification failed: authentication error')
logger.warn(u"PlexPy Notifier :: Growl notification failed: authentication error")
return
# Fix message
@ -548,11 +548,11 @@ class GROWL(object):
description=message,
icon=image
)
logger.info(u"PlexPy Notifier :: Growl notification sent.")
except gntp.notifier.errors.NetworkError:
logger.warning(u'Growl notification failed: network error')
logger.warn(u"PlexPy Notifier :: Growl notification failed: network error")
return
logger.info(u"Growl notifications sent.")
def updateLibrary(self):
# For uniformity reasons not removed
@ -617,14 +617,14 @@ class PROWL(object):
request_status = response.status
if request_status == 200:
logger.info(u"Prowl notifications sent.")
return True
logger.info(u"PlexPy Notifier :: Prowl notification sent.")
return True
elif request_status == 401:
logger.info(u"Prowl auth failed: %s" % response.reason)
return False
logger.warn(u"PlexPy Notifier :: Prowl notification failed: %s" % response.reason)
return False
else:
logger.info(u"Prowl notification failed.")
return False
logger.warn(u"PlexPy Notifier :: Prowl notification failed.")
return False
def updateLibrary(self):
# For uniformity reasons not removed
@ -698,7 +698,7 @@ class XBMC(object):
time = "3000" # in ms
for host in hosts:
logger.info('Sending notification command to XMBC @ ' + host)
logger.info(u"PlexPy Notifier :: Sending notification command to XMBC @ " + host)
try:
version = self._sendjson(host, 'Application.GetProperties', {'properties': ['version']})['version']['major']
@ -713,15 +713,17 @@ class XBMC(object):
if not request:
raise Exception
else:
logger.info(u"PlexPy Notifier :: XBMC notification sent.")
except Exception:
logger.error('Error sending notification request to XBMC')
logger.warn(u"PlexPy Notifier :: XBMC notification filed.")
def return_config_options(self):
config_option = [{'label': 'XBMC Host:Port',
'value': self.hosts,
'name': 'xbmc_host',
'description': 'Host running XBMC (e.g. http://localhost:8080). Separate multiple hosts with commas.',
'description': 'Host running XBMC (e.g. http://localhost:8080). Separate multiple hosts with commas (,).',
'input_type': 'text'
},
{'label': 'XBMC Username',
@ -763,12 +765,12 @@ class Plex(object):
base64string = base64.encodestring('%s:%s' % (username, password)).replace('\n', '')
req.add_header("Authorization", "Basic %s" % base64string)
logger.info('Plex url: %s' % url)
# logger.info(u"PlexPy Notifier :: Plex url: %s" % url)
try:
handle = urllib2.urlopen(req)
except Exception as e:
logger.warn('Error opening Plex url: %s' % e)
logger.error(u"PlexPy Notifier :: Error opening Plex url: %s" % e)
return
response = handle.read().decode(plexpy.SYS_ENCODING)
@ -784,7 +786,7 @@ class Plex(object):
time = "3000" # in ms
for host in hosts:
logger.info('Sending notification command to Plex Media Server @ ' + host)
logger.info(u"PlexPy Notifier :: Sending notification command to Plex Media Server @ " + host)
try:
notification = header + "," + message + "," + time
notifycommand = {'command': 'ExecBuiltIn', 'parameter': 'Notification(' + notification + ')'}
@ -792,9 +794,11 @@ class Plex(object):
if not request:
raise Exception
else:
logger.info(u"PlexPy Notifier :: Plex notification sent.")
except:
logger.warn('Error sending notification request to Plex Media Server')
logger.warn(u"PlexPy Notifier :: Plex notification failed.")
def return_config_options(self):
config_option = [{'label': 'Plex Client Host:Port',
@ -855,9 +859,10 @@ class NMA(object):
response = p.push(title, event, message, priority=nma_priority, batch_mode=batch)
if not response[api][u'code'] == u'200':
logger.error(u'Could not send notification to NotifyMyAndroid')
logger.warn(u"PlexPy Notifier :: NotifyMyAndroid notification failed.")
return False
else:
logger.info(u"PlexPy Notifier :: NotifyMyAndroid notification sent.")
return True
def return_config_options(self):
@ -918,14 +923,14 @@ class PUSHBULLET(object):
# logger.debug(u"PushBullet response body: %r" % response.read())
if request_status == 200:
logger.info(u"PushBullet notifications sent.")
return True
logger.info(u"PlexPy Notifier :: PushBullet notification sent.")
return True
elif request_status >= 400 and request_status < 500:
logger.info(u"PushBullet request failed: %s" % response.reason)
return False
logger.warn(u"PlexPy Notifier :: PushBullet notification failed: %s" % response.reason)
return False
else:
logger.info(u"PushBullet notification failed serverside.")
return False
logger.warn(u"PlexPy Notifier :: PushBullet notification failed.")
return False
def test(self, apikey, deviceid):
@ -952,10 +957,10 @@ class PUSHBULLET(object):
devices.update({'': ''})
return devices
elif request_status >= 400 and request_status < 500:
logger.info(u"Unable to retrieve Pushbullet devices list: %s" % response.reason)
logger.warn(u"PlexPy Notifier :: Unable to retrieve Pushbullet devices list: %s" % response.reason)
return {'': ''}
else:
logger.info(u"Unable to retrieve Pushbullet devices list.")
logger.warn(u"PlexPy Notifier :: Unable to retrieve Pushbullet devices list.")
return {'': ''}
else:
@ -1020,14 +1025,14 @@ class PUSHALOT(object):
# logger.debug(u"Pushalot response body: %r" % response.read())
if request_status == 200:
logger.info(u"Pushalot notifications sent.")
return True
logger.info(u"PlexPy Notifier :: Pushalot notification sent.")
return True
elif request_status == 410:
logger.info(u"Pushalot auth failed: %s" % response.reason)
return False
logger.warn(u"PlexPy Notifier :: Pushalot notification failed: %s" % response.reason)
return False
else:
logger.info(u"Pushalot notification failed.")
return False
logger.warn(u"PlexPy Notifier :: Pushalot notification failed.")
return False
def return_config_options(self):
config_option = [{'label': 'Pushalot API Key',
@ -1077,14 +1082,14 @@ class PUSHOVER(object):
# logger.debug(u"Pushover response body: %r" % response.read())
if request_status == 200:
logger.info(u"Pushover notifications sent.")
return True
logger.info(u"PlexPy Notifier :: Pushover notification sent.")
return True
elif request_status >= 400 and request_status < 500:
logger.info(u"Pushover request failed: %s" % response.reason)
return False
logger.warn(u"PlexPy Notifier :: Pushover notification failed: %s" % response.reason)
return False
else:
logger.info(u"Pushover notification failed.")
return False
logger.warn(u"PlexPy Notifier :: Pushover notification failed.")
return False
def updateLibrary(self):
# For uniformity reasons not removed
@ -1111,10 +1116,10 @@ class PUSHOVER(object):
sounds.update({'': ''})
return sounds
elif request_status >= 400 and request_status < 500:
logger.info(u"Unable to retrieve Pushover notification sounds list: %s" % response.reason)
logger.warn(u"PlexPy Notifier :: Unable to retrieve Pushover notification sounds list: %s" % response.reason)
return {'': ''}
else:
logger.info(u"Unable to retrieve Pushover notification sounds list.")
logger.warn(u"PlexPy Notifier :: Unable to retrieve Pushover notification sounds list.")
return {'': ''}
else:
@ -1177,12 +1182,12 @@ class TwitterNotifier(object):
oauth_consumer = oauth.Consumer(key=self.consumer_key, secret=self.consumer_secret)
oauth_client = oauth.Client(oauth_consumer)
logger.info('Requesting temp token from Twitter')
logger.info("PlexPy Notifier :: Requesting temp token from Twitter")
resp, content = oauth_client.request(self.REQUEST_TOKEN_URL, 'GET')
if resp['status'] != '200':
logger.info('Invalid respond from Twitter requesting temp token: %s' % resp['status'])
logger.warn("PlexPy Notifier :: Invalid respond from Twitter requesting temp token: %s" % resp['status'])
else:
request_token = dict(parse_qsl(content))
@ -1201,25 +1206,25 @@ class TwitterNotifier(object):
token = oauth.Token(request_token['oauth_token'], request_token['oauth_token_secret'])
token.set_verifier(key)
logger.info('Generating and signing request for an access token using key ' + key)
# logger.debug(u"Generating and signing request for an access token using key " + key)
oauth_consumer = oauth.Consumer(key=self.consumer_key, secret=self.consumer_secret)
# logger.debug('oauth_consumer: ' + str(oauth_consumer))
# logger.debug(u"oauth_consumer: " + str(oauth_consumer))
oauth_client = oauth.Client(oauth_consumer, token)
# logger.info('oauth_client: ' + str(oauth_client))
# logger.debug(u"oauth_client: " + str(oauth_client))
resp, content = oauth_client.request(self.ACCESS_TOKEN_URL, method='POST', body='oauth_verifier=%s' % key)
# logger.info('resp, content: ' + str(resp) + ',' + str(content))
# logger.debug(u"resp, content: " + str(resp) + ',' + str(content))
access_token = dict(parse_qsl(content))
# logger.info('access_token: ' + str(access_token))
# logger.debug(u"access_token: " + str(access_token))
# logger.info('resp[status] = ' + str(resp['status']))
# logger.debug(u"resp[status] = " + str(resp['status']))
if resp['status'] != '200':
logger.info('The request for a token with did not succeed: ' + str(resp['status']), logger.ERROR)
logger.error(u"PlexPy Notifier :: The request for a Twitter token did not succeed: " + str(resp['status']), logger.ERROR)
return False
else:
logger.info('Your Twitter Access Token key: %s' % access_token['oauth_token'])
logger.info('Access Token secret: %s' % access_token['oauth_token_secret'])
# logger.info(u"PlexPy Notifier :: Your Twitter Access Token key: %s" % access_token['oauth_token'])
# logger.info(u"PlexPy Notifier :: Access Token secret: %s" % access_token['oauth_token_secret'])
plexpy.CONFIG.TWITTER_USERNAME = access_token['oauth_token']
plexpy.CONFIG.TWITTER_PASSWORD = access_token['oauth_token_secret']
plexpy.CONFIG.write()
@ -1231,15 +1236,15 @@ class TwitterNotifier(object):
access_token_key = plexpy.CONFIG.TWITTER_USERNAME
access_token_secret = plexpy.CONFIG.TWITTER_PASSWORD
# logger.info(u"Sending tweet: " + message)
# logger.info(u"PlexPy Notifier :: Sending tweet: " + message)
api = twitter.Api(username, password, access_token_key, access_token_secret)
try:
api.PostUpdate(message)
logger.info(u"Twitter notifications sent.")
logger.info(u"PlexPy Notifier :: Twitter notification sent")
except Exception as e:
logger.info(u"Error sending Tweet: %s" % e)
logger.warn(u"PlexPy Notifier :: Twitter notification failed: %s" % e)
return False
return True
@ -1335,13 +1340,13 @@ class OSX_NOTIFY(object):
notification_center = NSUserNotificationCenter.defaultUserNotificationCenter()
notification_center.deliverNotification_(notification)
logger.info(u"OSX Notify notifications sent.")
logger.info(u"PlexPy Notifier :: OSX Notify notification sent.")
del pool
return True
except Exception as e:
logger.warn('Error sending OS X Notification: %s' % e)
logger.warn(u"PlexPy Notifier :: OSX notification failed: %s" % e)
return False
def swizzled_bundleIdentifier(self, original, swizzled):
@ -1382,13 +1387,47 @@ class BOXCAR(object):
req = urllib2.Request(self.url)
handle = urllib2.urlopen(req, data)
handle.close()
logger.info(u"Boxcar2 notifications sent.")
logger.info(u"PlexPy Notifier :: Boxcar2 notification sent.")
return True
except urllib2.URLError as e:
logger.warn('Error sending Boxcar2 Notification: %s' % e)
logger.warn(u"PlexPy Notifier :: Boxcar2 notification failed: %s" % e)
return False
def get_sounds(self):
sounds = {'': '',
'beep-crisp': 'Beep (Crisp)',
'beep-soft': 'Beep (Soft)',
'bell-modern': 'Bell (Modern)',
'bell-one-tone': 'Bell (One Tone)',
'bell-simple': 'Bell (Simple)',
'bell-triple': 'Bell (Triple)',
'bird-1': 'Bird (1)',
'bird-2': 'Bird (2)',
'boing': 'Boing',
'cash': 'Cash',
'clanging': 'Clanging',
'detonator-charge': 'Detonator Charge',
'digital-alarm': 'Digital Alarm',
'done': 'Done',
'echo': 'Echo',
'flourish': 'Flourish',
'harp': 'Harp',
'light': 'Light',
'magic-chime':'Magic Chime',
'magic-coin': 'Magic Coin',
'no-sound': 'No Sound',
'notifier-1': 'Notifier (1)',
'notifier-2': 'Notifier (2)',
'notifier-3': 'Notifier (3)',
'orchestral-long': 'Orchestral (Long)',
'orchestral-short': 'Orchestral (Short)',
'score': 'Score',
'success': 'Success',
'up': 'Up'}
return sounds
def return_config_options(self):
config_option = [{'label': 'Boxcar Access Token',
'value': plexpy.CONFIG.BOXCAR_TOKEN,
@ -1401,36 +1440,7 @@ class BOXCAR(object):
'name': 'boxcar_sound',
'description': 'Set the notification sound. Leave blank for the default sound.',
'input_type': 'select',
'select_options': {'': '',
'beep-crisp': 'Beep (Crisp)',
'beep-soft': 'Beep (Soft)',
'bell-modern': 'Bell (Modern)',
'bell-one-tone': 'Bell (One Tone)',
'bell-simple': 'Bell (Simple)',
'bell-triple': 'Bell (Triple)',
'bird-1': 'Bird (1)',
'bird-2': 'Bird (2)',
'boing': 'Boing',
'cash': 'Cash',
'clanging': 'Clanging',
'detonator-charge': 'Detonator Charge',
'digital-alarm': 'Digital Alarm',
'done': 'Done',
'echo': 'Echo',
'flourish': 'Flourish',
'harp': 'Harp',
'light': 'Light',
'magic-chime': 'Magic Chime',
'magic-coin': 'Magic Coin',
'no-sound': 'No Sound',
'notifier-1': 'Notifier (1)',
'notifier-2': 'Notifier (2)',
'notifier-3': 'Notifier (3)',
'orchestral-long': 'Orchestral (Long)',
'orchestral-short': 'Orchestral (Short)',
'score': 'Score',
'success': 'Success',
'up': 'Up'}
'select_options': self.get_sounds()
}
]
@ -1471,11 +1481,11 @@ class Email(object):
mailserver.sendmail(plexpy.CONFIG.EMAIL_FROM, recipients, message.as_string())
mailserver.quit()
logger.info(u"Email notifications sent.")
logger.info(u"PlexPy Notifier :: Email notification sent.")
return True
except Exception, e:
logger.warn('Error sending Email: %s' % e)
except Exception as e:
logger.warn(u"PlexPy Notifier :: Email notification failed: %s" % e)
return False
def return_config_options(self):
@ -1558,7 +1568,7 @@ class IFTTT(object):
data = {'value1': subject.encode("utf-8"),
'value2': message.encode("utf-8")}
# logger.debug("Ifttt SENDING: %s" % json.dumps(data))
# logger.debug(u"Ifttt SENDING: %s" % json.dumps(data))
http_handler.request("POST",
"/trigger/%s/with/key/%s" % (self.event, self.apikey),
@ -1571,14 +1581,14 @@ class IFTTT(object):
# logger.debug(u"Ifttt response body: %r" % response.read())
if request_status == 200:
logger.info(u"Ifttt notifications sent.")
return True
logger.info(u"PlexPy Notifier :: Ifttt notification sent.")
return True
elif request_status >= 400 and request_status < 500:
logger.info(u"Ifttt request failed: %s" % response.reason)
return False
logger.warn(u"PlexPy Notifier :: Ifttt notification failed: %s" % response.reason)
return False
else:
logger.info(u"Ifttt notification failed serverside.")
return False
logger.warn(u"PlexPy Notifier :: Ifttt notification failed.")
return False
def test(self):
return self.notify('PlexPy', 'Test Message')
@ -1631,14 +1641,14 @@ class TELEGRAM(object):
request_status = response.status
if request_status == 200:
logger.info(u"Telegram notifications sent.")
return True
logger.info(u"PlexPy Notifier :: Telegram notification sent.")
return True
elif request_status >= 400 and request_status < 500:
logger.info(u"Telegram request failed: %s" % response.reason)
return False
logger.warn(u"PlexPy Notifier :: Telegram notification failed: %s" % response.reason)
return False
else:
logger.info(u"Telegram notification failed serverside.")
return False
logger.warn(u"PlexPy Notifier :: Telegram notification failed.")
return False
def updateLibrary(self):
# For uniformity reasons not removed
@ -1708,14 +1718,14 @@ class SLACK(object):
request_status = response.status
if request_status == 200:
logger.info(u"Slack notifications sent.")
return True
logger.info(u"PlexPy Notifier :: Slack notification sent.")
return True
elif request_status >= 400 and request_status < 500:
logger.info(u"Slack request failed: %s" % response.reason)
return False
logger.warn(u"PlexPy Notifier :: Slack notification failed: %s" % response.reason)
return False
else:
logger.info(u"Slack notification failed serverside.")
return False
logger.warn(u"PlexPy Notifier :: Slack notification failed.")
return False
def updateLibrary(self):
#For uniformity reasons not removed

View file

@ -16,7 +16,7 @@
# You should have received a copy of the GNU General Public License
# along with PlexPy. If not, see <http://www.gnu.org/licenses/>.
from plexpy import logger, helpers, users, http_handler, database
from plexpy import logger, helpers, http_handler, database, users
import xmltodict
import json
from xml.dom import minidom
@ -26,7 +26,7 @@ import plexpy
def refresh_users():
logger.info("Requesting users list refresh...")
logger.info(u"PlexPy PlexTV :: Requesting users list refresh...")
result = PlexTV().get_full_users_list()
monitor_db = database.MonitorDatabase()
@ -55,13 +55,13 @@ def refresh_users():
monitor_db.upsert('users', new_value_dict, control_value_dict)
logger.info("Users list refreshed.")
logger.info(u"PlexPy PlexTV :: Users list refreshed.")
else:
logger.warn("Unable to refresh users list.")
logger.warn(u"PlexPy PlexTV :: Unable to refresh users list.")
def get_real_pms_url():
logger.info("Requesting URLs for server...")
logger.info(u"PlexPy PlexTV :: Requesting URLs for server...")
# Reset any current PMS_URL value
plexpy.CONFIG.__setattr__('PMS_URL', '')
@ -85,15 +85,15 @@ def get_real_pms_url():
if plexpy.CONFIG.PMS_IS_REMOTE and item['local'] == '0':
plexpy.CONFIG.__setattr__('PMS_URL', item['uri'])
plexpy.CONFIG.write()
logger.info("Server URL retrieved.")
logger.info(u"PlexPy PlexTV :: Server URL retrieved.")
if not plexpy.CONFIG.PMS_IS_REMOTE and item['local'] == '1':
plexpy.CONFIG.__setattr__('PMS_URL', item['uri'])
plexpy.CONFIG.write()
logger.info("Server URL retrieved.")
logger.info(u"PlexPy PlexTV :: Server URL retrieved.")
else:
plexpy.CONFIG.__setattr__('PMS_URL', fallback_url)
plexpy.CONFIG.write()
logger.warn("Unable to retrieve server URLs. Using user-defined value.")
logger.warn(u"PlexPy PlexTV :: Unable to retrieve server URLs. Using user-defined value.")
else:
plexpy.CONFIG.__setattr__('PMS_URL', fallback_url)
plexpy.CONFIG.write()
@ -213,7 +213,7 @@ class PlexTV(object):
try:
xml_parse = minidom.parseString(own_account)
except Exception, e:
except Exception as e:
logger.warn("Error parsing XML for Plex account details: %s" % e)
return []
except:
@ -238,7 +238,7 @@ class PlexTV(object):
try:
xml_parse = minidom.parseString(friends_list)
except Exception, e:
except Exception as e:
logger.warn("Error parsing XML for Plex friends list: %s" % e)
except:
logger.warn("Error parsing XML for Plex friends list.")
@ -269,7 +269,7 @@ class PlexTV(object):
try:
xml_parse = minidom.parseString(sync_list)
except Exception, e:
except Exception as e:
logger.warn("Error parsing XML for Plex sync lists: %s" % e)
return []
except:
@ -383,7 +383,7 @@ class PlexTV(object):
try:
xml_parse = minidom.parseString(plextv_resources)
except Exception, e:
except Exception as e:
logger.warn("Error parsing XML for Plex resources: %s" % e)
return []
except:
@ -430,6 +430,25 @@ class PlexTV(object):
return server_urls
def get_server_times(self):
servers = self.get_plextv_server_list(output_format='xml')
server_times = []
try:
xml_head = servers.getElementsByTagName('Server')
except:
logger.warn("Error parsing XML for Plex servers.")
return []
for a in xml_head:
if helpers.get_xml_attr(a, 'machineIdentifier') == plexpy.CONFIG.PMS_IDENTIFIER:
server_times.append({"created_at": helpers.get_xml_attr(a, 'createdAt'),
"updated_at": helpers.get_xml_attr(a, 'updatedAt')
})
break
return server_times
def discover(self):
""" Query plex for all servers online. Returns the ones you own in a selectize format """
result = self.get_plextv_resources(include_https=True, output_format='raw')
@ -463,23 +482,4 @@ class PlexTV(object):
logger.warn('Failed to get servers from plex %s' % e)
return clean_servers
return json.dumps(clean_servers, indent=4)
def get_server_times(self):
servers = self.get_plextv_server_list(output_format='xml')
server_times = []
try:
xml_head = servers.getElementsByTagName('Server')
except:
logger.warn("Error parsing XML for Plex servers.")
return []
for a in xml_head:
if helpers.get_xml_attr(a, 'machineIdentifier') == plexpy.CONFIG.PMS_IDENTIFIER:
server_times.append({"created_at": helpers.get_xml_attr(a, 'createdAt'),
"updated_at": helpers.get_xml_attr(a, 'updatedAt')
})
break
return server_times
return json.dumps(clean_servers, indent=4)

View file

@ -26,12 +26,12 @@ def extract_plexwatch_xml(xml=None):
try:
xml_parse = minidom.parseString(clean_xml)
except:
logger.warn("Error parsing XML for Plexwatch database.")
logger.warn(u"PlexPy Importer :: Error parsing XML for Plexwatch database.")
return None
xml_head = xml_parse.getElementsByTagName('opt')
if not xml_head:
logger.warn("Error parsing XML for Plexwatch database.")
logger.warn(u"PlexPy Importer :: Error parsing XML for Plexwatch database.")
return None
for a in xml_head:
@ -205,23 +205,23 @@ def validate_database(database=None, table_name=None):
try:
connection = sqlite3.connect(database, timeout=20)
except sqlite3.OperationalError:
logger.error('PlexPy Importer :: Invalid database specified.')
logger.error(u"PlexPy Importer :: Invalid database specified.")
return 'Invalid database specified.'
except ValueError:
logger.error('PlexPy Importer :: Invalid database specified.')
logger.error(u"PlexPy Importer :: Invalid database specified.")
return 'Invalid database specified.'
except:
logger.error('PlexPy Importer :: Uncaught exception.')
logger.error(u"PlexPy Importer :: Uncaught exception.")
return 'Uncaught exception.'
try:
connection.execute('SELECT ratingKey from %s' % table_name)
connection.close()
except sqlite3.OperationalError:
logger.error('PlexPy Importer :: Invalid database specified.')
logger.error(u"PlexPy Importer :: Invalid database specified.")
return 'Invalid database specified.'
except:
logger.error('PlexPy Importer :: Uncaught exception.')
logger.error(u"PlexPy Importer :: Uncaught exception.")
return 'Uncaught exception.'
return 'success'
@ -232,16 +232,16 @@ def import_from_plexwatch(database=None, table_name=None, import_ignore_interval
connection = sqlite3.connect(database, timeout=20)
connection.row_factory = sqlite3.Row
except sqlite3.OperationalError:
logger.error('PlexPy Importer :: Invalid filename.')
logger.error(u"PlexPy Importer :: Invalid filename.")
return None
except ValueError:
logger.error('PlexPy Importer :: Invalid filename.')
logger.error(u"PlexPy Importer :: Invalid filename.")
return None
try:
connection.execute('SELECT ratingKey from %s' % table_name)
except sqlite3.OperationalError:
logger.error('PlexPy Importer :: Database specified does not contain the required fields.')
logger.error(u"PlexPy Importer :: Database specified does not contain the required fields.")
return None
logger.debug(u"PlexPy Importer :: PlexWatch data import in progress...")

File diff suppressed because it is too large Load diff

View file

@ -21,28 +21,28 @@ class Users(object):
def __init__(self):
pass
def get_user_list(self, kwargs=None):
def get_datatables_list(self, kwargs=None):
data_tables = datatables.DataTables()
custom_where = ['users.deleted_user', 0]
columns = ['users.user_id as user_id',
'users.custom_avatar_url as user_thumb',
'(case when users.friendly_name is null then users.username else \
users.friendly_name end) as friendly_name',
'MAX(session_history.started) as last_seen',
'session_history.ip_address as ip_address',
'COUNT(session_history.id) as plays',
'session_history.platform as platform',
'session_history.player as player',
'session_history_metadata.full_title as last_watched',
columns = ['users.user_id',
'users.username',
'users.friendly_name',
'users.thumb AS user_thumb',
'users.custom_avatar_url AS custom_thumb',
'COUNT(session_history.id) AS plays',
'MAX(session_history.started) AS last_seen',
'session_history_metadata.full_title AS last_watched',
'session_history.ip_address',
'session_history.platform',
'session_history.player',
'session_history_metadata.thumb',
'session_history_metadata.parent_thumb',
'session_history_metadata.grandparent_thumb',
'session_history_metadata.media_type',
'session_history.rating_key as rating_key',
'session_history.rating_key',
'session_history_media_info.video_decision',
'users.username as user',
'users.do_notify as do_notify',
'users.keep_history as keep_history'
]
@ -61,8 +61,8 @@ class Users(object):
['session_history.id', 'session_history_metadata.id'],
['session_history.id', 'session_history_media_info.id']],
kwargs=kwargs)
except:
logger.warn("Unable to execute database query.")
except Exception as e:
logger.warn(u"PlexPy Users :: Unable to execute database query for get_list: %s." % e)
return {'recordsFiltered': 0,
'recordsTotal': 0,
'draw': 0,
@ -80,28 +80,30 @@ class Users(object):
else:
thumb = item['thumb']
if not item['user_thumb'] or item['user_thumb'] == '':
user_thumb = common.DEFAULT_USER_THUMB
else:
if item['custom_thumb'] and item['custom_thumb'] != item['user_thumb']:
user_thumb = item['custom_thumb']
elif item['user_thumb']:
user_thumb = item['user_thumb']
else:
user_thumb = common.DEFAULT_USER_THUMB
# Rename Mystery platform names
platform = common.PLATFORM_NAME_OVERRIDES.get(item['platform'], item['platform'])
row = {'plays': item['plays'],
'last_seen': item['last_seen'],
row = {'user_id': item['user_id'],
'username': item['username'],
'friendly_name': item['friendly_name'],
'user_thumb': user_thumb,
'plays': item['plays'],
'last_seen': item['last_seen'],
'last_watched': item['last_watched'],
'ip_address': item['ip_address'],
'platform': platform,
'player': item['player'],
'last_watched': item['last_watched'],
'thumb': thumb,
'media_type': item['media_type'],
'rating_key': item['rating_key'],
'video_decision': item['video_decision'],
'user_thumb': user_thumb,
'user': item['user'],
'user_id': item['user_id'],
'do_notify': helpers.checked(item['do_notify']),
'keep_history': helpers.checked(item['keep_history'])
}
@ -116,35 +118,34 @@ class Users(object):
return dict
def get_user_unique_ips(self, kwargs=None, custom_where=None):
def get_datatables_unique_ips(self, user_id=None, kwargs=None):
data_tables = datatables.DataTables()
# Change custom_where column name due to ambiguous column name after JOIN
custom_where[0][0] = 'custom_user_id' if custom_where[0][0] == 'user_id' else custom_where[0][0]
custom_where = ['users.user_id', user_id]
columns = ['session_history.id',
'session_history.started as last_seen',
'session_history.ip_address as ip_address',
'COUNT(session_history.id) as play_count',
'session_history.platform as platform',
'session_history.player as player',
'session_history_metadata.full_title as last_watched',
'session_history.started AS last_seen',
'session_history.ip_address',
'COUNT(session_history.id) AS play_count',
'session_history.platform',
'session_history.player',
'session_history_metadata.full_title AS last_watched',
'session_history_metadata.thumb',
'session_history_metadata.parent_thumb',
'session_history_metadata.grandparent_thumb',
'session_history_metadata.media_type',
'session_history.rating_key as rating_key',
'session_history.rating_key',
'session_history_media_info.video_decision',
'session_history.user as user',
'session_history.user',
'session_history.user_id as custom_user_id',
'(case when users.friendly_name is null then users.username else \
users.friendly_name end) as friendly_name'
'(CASE WHEN users.friendly_name IS NULL THEN users.username ELSE \
users.friendly_name END) AS friendly_name'
]
try:
query = data_tables.ssp_query(table_name='session_history',
columns=columns,
custom_where=custom_where,
custom_where=[custom_where],
group_by=['ip_address'],
join_types=['JOIN',
'JOIN',
@ -156,8 +157,8 @@ class Users(object):
['session_history.id', 'session_history_metadata.id'],
['session_history.id', 'session_history_media_info.id']],
kwargs=kwargs)
except:
logger.warn("Unable to execute database query.")
except Exception as e:
logger.warn(u"PlexPy Users :: Unable to execute database query for get_unique_ips: %s." % e)
return {'recordsFiltered': 0,
'recordsTotal': 0,
'draw': 0,
@ -178,18 +179,18 @@ class Users(object):
# Rename Mystery platform names
platform = common.PLATFORM_NAME_OVERRIDES.get(item["platform"], item["platform"])
row = {"id": item['id'],
"last_seen": item['last_seen'],
"ip_address": item['ip_address'],
"play_count": item['play_count'],
"platform": platform,
"player": item['player'],
"last_watched": item['last_watched'],
"thumb": thumb,
"media_type": item['media_type'],
"rating_key": item['rating_key'],
"video_decision": item['video_decision'],
"friendly_name": item['friendly_name']
row = {'id': item['id'],
'last_seen': item['last_seen'],
'ip_address': item['ip_address'],
'play_count': item['play_count'],
'platform': platform,
'player': item['player'],
'last_watched': item['last_watched'],
'thumb': thumb,
'media_type': item['media_type'],
'rating_key': item['rating_key'],
'video_decision': item['video_decision'],
'friendly_name': item['friendly_name']
}
rows.append(row)
@ -202,286 +203,169 @@ class Users(object):
return dict
# TODO: The getter and setter for this needs to become a config getter/setter for more than just friendlyname
def set_user_friendly_name(self, user=None, user_id=None, friendly_name=None, do_notify=0, keep_history=1):
if user_id:
if friendly_name.strip() == '':
friendly_name = None
def set_config(self, user_id=None, friendly_name='', custom_thumb='', do_notify=1, keep_history=1):
if str(user_id).isdigit():
monitor_db = database.MonitorDatabase()
control_value_dict = {"user_id": user_id}
new_value_dict = {"friendly_name": friendly_name,
"do_notify": do_notify,
"keep_history": keep_history}
key_dict = {'user_id': user_id}
value_dict = {'friendly_name': friendly_name,
'custom_avatar_url': custom_thumb,
'do_notify': do_notify,
'keep_history': keep_history}
try:
monitor_db.upsert('users', new_value_dict, control_value_dict)
except Exception, e:
logger.debug(u"Uncaught exception %s" % e)
if user:
if friendly_name.strip() == '':
friendly_name = None
monitor_db.upsert('users', value_dict, key_dict)
except Exception as e:
logger.warn(u"PlexPy Users :: Unable to execute database query for set_config: %s." % e)
monitor_db = database.MonitorDatabase()
control_value_dict = {"username": user}
new_value_dict = {"friendly_name": friendly_name,
"do_notify": do_notify,
"keep_history": keep_history}
try:
monitor_db.upsert('users', new_value_dict, control_value_dict)
except Exception, e:
logger.debug(u"Uncaught exception %s" % e)
def set_user_profile_url(self, user=None, user_id=None, profile_url=None):
if user_id:
if profile_url.strip() == '':
profile_url = None
monitor_db = database.MonitorDatabase()
control_value_dict = {"user_id": user_id}
new_value_dict = {"custom_avatar_url": profile_url}
try:
monitor_db.upsert('users', new_value_dict, control_value_dict)
except Exception, e:
logger.debug(u"Uncaught exception %s" % e)
if user:
if profile_url.strip() == '':
profile_url = None
monitor_db = database.MonitorDatabase()
control_value_dict = {"username": user}
new_value_dict = {"custom_avatar_url": profile_url}
try:
monitor_db.upsert('users', new_value_dict, control_value_dict)
except Exception, e:
logger.debug(u"Uncaught exception %s" % e)
def get_user_friendly_name(self, user=None, user_id=None):
if user_id:
monitor_db = database.MonitorDatabase()
query = 'select username, ' \
'(CASE WHEN friendly_name IS NULL THEN username ELSE friendly_name END) as friendly_name,' \
'do_notify, keep_history, custom_avatar_url as thumb ' \
'FROM users WHERE user_id = ?'
result = monitor_db.select(query, args=[user_id])
if result:
user_detail = {'user_id': user_id,
'user': result[0]['username'],
'friendly_name': result[0]['friendly_name'],
'thumb': result[0]['thumb'],
'do_notify': helpers.checked(result[0]['do_notify']),
'keep_history': helpers.checked(result[0]['keep_history'])
}
return user_detail
else:
user_detail = {'user_id': user_id,
'user': '',
'friendly_name': '',
'do_notify': '',
'thumb': '',
'keep_history': ''}
return user_detail
elif user:
monitor_db = database.MonitorDatabase()
query = 'select user_id, ' \
'(CASE WHEN friendly_name IS NULL THEN username ELSE friendly_name END) as friendly_name,' \
'do_notify, keep_history, custom_avatar_url as thumb ' \
'FROM users WHERE username = ?'
result = monitor_db.select(query, args=[user])
if result:
user_detail = {'user_id': result[0]['user_id'],
'user': user,
'friendly_name': result[0]['friendly_name'],
'thumb': result[0]['thumb'],
'do_notify': helpers.checked(result[0]['do_notify']),
'keep_history': helpers.checked(result[0]['keep_history'])}
return user_detail
else:
user_detail = {'user_id': None,
'user': user,
'friendly_name': '',
'do_notify': '',
'thumb': '',
'keep_history': ''}
return user_detail
return None
def get_user_id(self, user=None):
if user:
try:
monitor_db = database.MonitorDatabase()
query = 'select user_id FROM users WHERE username = ?'
result = monitor_db.select_single(query, args=[user])
if result:
return result['user_id']
else:
return None
except:
return None
return None
def get_user_details(self, user=None, user_id=None):
def get_details(self, user_id=None, user=None):
from plexpy import plextv
monitor_db = database.MonitorDatabase()
if user:
query = 'SELECT user_id, username, friendly_name, email, ' \
'custom_avatar_url as thumb, is_home_user, is_allow_sync, is_restricted, do_notify ' \
'FROM users ' \
'WHERE username = ? ' \
'UNION ALL ' \
'SELECT null, user, null, null, null, null, null, null, null ' \
'FROM session_history ' \
'WHERE user = ? ' \
'GROUP BY user ' \
'LIMIT 1'
result = monitor_db.select(query, args=[user, user])
elif user_id:
query = 'SELECT user_id, username, friendly_name, email, ' \
'custom_avatar_url as thumb, is_home_user, is_allow_sync, is_restricted, do_notify ' \
'FROM users ' \
'WHERE user_id = ? ' \
'UNION ALL ' \
'SELECT user_id, user, null, null, null, null, null, null, null ' \
'FROM session_history ' \
'WHERE user_id = ? ' \
'GROUP BY user ' \
'LIMIT 1'
result = monitor_db.select(query, args=[user_id, user_id])
else:
result = None
try:
if str(user_id).isdigit():
query = 'SELECT user_id, username, friendly_name, thumb AS user_thumb, custom_avatar_url AS custom_thumb, ' \
'email, is_home_user, is_allow_sync, is_restricted, do_notify, keep_history ' \
'FROM users ' \
'WHERE user_id = ? '
result = monitor_db.select(query, args=[user_id])
elif user:
query = 'SELECT user_id, username, friendly_name, thumb AS user_thumb, custom_avatar_url AS custom_thumb, ' \
'email, is_home_user, is_allow_sync, is_restricted, do_notify, keep_history ' \
'FROM users ' \
'WHERE username = ? '
result = monitor_db.select(query, args=[user])
else:
result = []
except Exception as e:
logger.warn(u"PlexPy Users :: Unable to execute database query for get_details: %s." % e)
result = []
if result:
user_details = {}
for item in result:
if not item['friendly_name']:
friendly_name = item['username']
else:
if item['friendly_name']:
friendly_name = item['friendly_name']
if not item['thumb'] or item['thumb'] == '':
user_thumb = common.DEFAULT_USER_THUMB
else:
user_thumb = item['thumb']
friendly_name = item['username']
user_details = {"user_id": item['user_id'],
"username": item['username'],
"friendly_name": friendly_name,
"email": item['email'],
"thumb": user_thumb,
"is_home_user": item['is_home_user'],
"is_allow_sync": item['is_allow_sync'],
"is_restricted": item['is_restricted'],
"do_notify": item['do_notify']
if item['custom_thumb'] and item['custom_thumb'] != item['user_thumb']:
user_thumb = item['custom_thumb']
elif item['user_thumb']:
user_thumb = item['user_thumb']
else:
user_thumb = common.DEFAULT_USER_THUMB
user_details = {'user_id': item['user_id'],
'username': item['username'],
'friendly_name': friendly_name,
'user_thumb': user_thumb,
'email': item['email'],
'is_home_user': item['is_home_user'],
'is_allow_sync': item['is_allow_sync'],
'is_restricted': item['is_restricted'],
'do_notify': item['do_notify'],
'keep_history': item['keep_history']
}
return user_details
else:
logger.warn(u"PlexPy :: Unable to retrieve user from local database. Requesting user list refresh.")
logger.warn(u"PlexPy Users :: Unable to retrieve user from local database. Requesting user list refresh.")
# Let's first refresh the user list to make sure the user isn't newly added and not in the db yet
if user:
# Refresh users
plextv.refresh_users()
query = 'SELECT user_id, username, friendly_name, email, ' \
'custom_avatar_url as thumb, is_home_user, is_allow_sync, is_restricted, do_notify ' \
'FROM users ' \
'WHERE username = ? ' \
'UNION ALL ' \
'SELECT null, user, null, null, null, null, null, null, null ' \
'FROM session_history ' \
'WHERE user = ? ' \
'GROUP BY user ' \
'LIMIT 1'
result = monitor_db.select(query, args=[user, user])
elif user_id:
# Refresh users
plextv.refresh_users()
query = 'SELECT user_id, username, friendly_name, email, ' \
'custom_avatar_url as thumb, is_home_user, is_allow_sync, is_restricted, do_notify ' \
'FROM users ' \
'WHERE user_id = ? ' \
'UNION ALL ' \
'SELECT user_id, user, null, null, null, null, null, null, null ' \
'FROM session_history ' \
'WHERE user_id = ? ' \
'GROUP BY user ' \
'LIMIT 1'
result = monitor_db.select(query, args=[user_id, user_id])
else:
result = None
try:
if str(user_id).isdigit():
# Refresh users
plextv.refresh_users()
query = 'SELECT user_id, username, friendly_name, thumb AS user_thumb, custom_avatar_url AS custom_thumb, ' \
'email, is_home_user, is_allow_sync, is_restricted, do_notify, keep_history ' \
'FROM users ' \
'WHERE user_id = ? '
result = monitor_db.select(query, args=[user_id])
elif user:
query = 'SELECT user_id, username, friendly_name, thumb AS user_thumb, custom_avatar_url AS custom_thumb, ' \
'email, is_home_user, is_allow_sync, is_restricted, do_notify, keep_history ' \
'FROM users ' \
'WHERE username = ? '
result = monitor_db.select(query, args=[user])
else:
result = []
except Exception as e:
logger.warn(u"PlexPy Users :: Unable to execute database query for get_details: %s." % e)
result = []
if result:
user_details = {}
for item in result:
if not item['friendly_name']:
friendly_name = item['username']
else:
if item['friendly_name']:
friendly_name = item['friendly_name']
if not item['thumb'] or item['thumb'] == '':
user_thumb = common.DEFAULT_USER_THUMB
else:
user_thumb = item['thumb']
friendly_name = item['username']
user_details = {"user_id": item['user_id'],
"username": item['username'],
"friendly_name": friendly_name,
"email": item['email'],
"thumb": user_thumb,
"is_home_user": item['is_home_user'],
"is_allow_sync": item['is_allow_sync'],
"is_restricted": item['is_restricted'],
"do_notify": item['do_notify']
if item['custom_thumb'] and item['custom_thumb'] != item['user_thumb']:
user_thumb = item['custom_thumb']
elif item['user_thumb']:
user_thumb = item['user_thumb']
else:
user_thumb = common.DEFAULT_USER_THUMB
user_details = {'user_id': item['user_id'],
'username': item['username'],
'friendly_name': friendly_name,
'user_thumb': user_thumb,
'email': item['email'],
'is_home_user': item['is_home_user'],
'is_allow_sync': item['is_allow_sync'],
'is_restricted': item['is_restricted'],
'do_notify': item['do_notify'],
'keep_history': item['keep_history']
}
return user_details
else:
# If there is no user data we must return something
# Use "Local" user to retain compatibility with PlexWatch database value
return {"user_id": None,
"username": 'Local',
"friendly_name": 'Local',
"email": '',
"thumb": '',
"is_home_user": 0,
"is_allow_sync": 0,
"is_restricted": 0,
"do_notify": 0
return {'user_id': None,
'username': 'Local',
'friendly_name': 'Local',
'user_thumb': common.DEFAULT_USER_THUMB,
'email': '',
'is_home_user': 0,
'is_allow_sync': 0,
'is_restricted': 0,
'do_notify': 0,
'keep_history': 0
}
def get_user_watch_time_stats(self, user=None, user_id=None):
def get_watch_time_stats(self, user_id=None):
monitor_db = database.MonitorDatabase()
time_queries = [1, 7, 30, 0]
user_watch_time_stats = []
for days in time_queries:
if days > 0:
if user_id:
query = 'SELECT (SUM(stopped - started) - ' \
'SUM(CASE WHEN paused_counter is null THEN 0 ELSE paused_counter END)) as total_time, ' \
'COUNT(id) AS total_plays ' \
'FROM session_history ' \
'WHERE datetime(stopped, "unixepoch", "localtime") >= datetime("now", "-%s days", "localtime") ' \
'AND user_id = ?' % days
result = monitor_db.select(query, args=[user_id])
elif user:
query = 'SELECT (SUM(stopped - started) - ' \
'SUM(CASE WHEN paused_counter is null THEN 0 ELSE paused_counter END)) as total_time, ' \
'COUNT(id) AS total_plays ' \
'FROM session_history ' \
'WHERE datetime(stopped, "unixepoch", "localtime") >= datetime("now", "-%s days", "localtime") ' \
'AND user = ?' % days
result = monitor_db.select(query, args=[user])
else:
query = 'SELECT (SUM(stopped - started) - ' \
'SUM(CASE WHEN paused_counter is null THEN 0 ELSE paused_counter END)) as total_time, ' \
'COUNT(id) AS total_plays ' \
'FROM session_history ' \
'WHERE user = ?'
result = monitor_db.select(query, args=[user])
try:
if days > 0:
if str(user_id).isdigit():
query = 'SELECT (SUM(stopped - started) - ' \
' SUM(CASE WHEN paused_counter is null THEN 0 ELSE paused_counter END)) as total_time, ' \
'COUNT(id) AS total_plays ' \
'FROM session_history ' \
'WHERE datetime(stopped, "unixepoch", "localtime") >= datetime("now", "-%s days", "localtime") ' \
'AND user_id = ?' % days
result = monitor_db.select(query, args=[user_id])
else:
result = []
else:
if str(user_id).isdigit():
query = 'SELECT (SUM(stopped - started) - ' \
' SUM(CASE WHEN paused_counter is null THEN 0 ELSE paused_counter END)) as total_time, ' \
'COUNT(id) AS total_plays ' \
'FROM session_history ' \
'WHERE user_id = ?'
result = monitor_db.select(query, args=[user_id])
else:
result = []
except Exception as e:
logger.warn(u"PlexPy Users :: Unable to execute database query for get_watch_time_stats: %s." % e)
result = []
for item in result:
if item['total_time']:
@ -500,14 +384,14 @@ class Users(object):
return user_watch_time_stats
def get_user_player_stats(self, user=None, user_id=None):
def get_player_stats(self, user_id=None):
monitor_db = database.MonitorDatabase()
player_stats = []
result_id = 0
try:
if user_id:
if str(user_id).isdigit():
query = 'SELECT player, COUNT(player) as player_count, platform ' \
'FROM session_history ' \
'WHERE user_id = ? ' \
@ -515,15 +399,10 @@ class Users(object):
'ORDER BY player_count DESC'
result = monitor_db.select(query, args=[user_id])
else:
query = 'SELECT player, COUNT(player) as player_count, platform ' \
'FROM session_history ' \
'WHERE user = ? ' \
'GROUP BY player ' \
'ORDER BY player_count DESC'
result = monitor_db.select(query, args=[user])
except:
logger.warn("Unable to execute database query.")
return None
result = []
except Exception as e:
logger.warn(u"PlexPy Users :: Unable to execute database query for get_player_stats: %s." % e)
result = []
for item in result:
# Rename Mystery platform names
@ -538,3 +417,140 @@ class Users(object):
result_id += 1
return player_stats
def get_recently_watched(self, user_id=None, limit='10'):
monitor_db = database.MonitorDatabase()
recently_watched = []
if not limit.isdigit():
limit = '10'
try:
if str(user_id).isdigit():
query = 'SELECT session_history.id, session_history.media_type, session_history.rating_key, session_history.parent_rating_key, ' \
'title, parent_title, grandparent_title, thumb, parent_thumb, grandparent_thumb, media_index, parent_media_index, ' \
'year, started, user ' \
'FROM session_history_metadata ' \
'JOIN session_history ON session_history_metadata.id = session_history.id ' \
'WHERE user_id = ? ' \
'GROUP BY (CASE WHEN session_history.media_type = "track" THEN session_history.parent_rating_key ' \
' ELSE session_history.rating_key END) ' \
'ORDER BY started DESC LIMIT ?'
result = monitor_db.select(query, args=[user_id, limit])
else:
result = []
except Exception as e:
logger.warn(u"PlexPy Users :: Unable to execute database query for get_recently_watched: %s." % e)
result = []
for row in result:
if row['media_type'] == 'episode' and row['parent_thumb']:
thumb = row['parent_thumb']
elif row['media_type'] == 'episode':
thumb = row['grandparent_thumb']
else:
thumb = row['thumb']
recent_output = {'row_id': row['id'],
'type': row['media_type'],
'rating_key': row['rating_key'],
'title': row['title'],
'parent_title': row['parent_title'],
'grandparent_title': row['grandparent_title'],
'thumb': thumb,
'media_index': row['media_index'],
'parent_media_index': row['parent_media_index'],
'year': row['year'],
'time': row['started'],
'user': row['user']
}
recently_watched.append(recent_output)
return recently_watched
def delete_all_history(self, user_id=None):
monitor_db = database.MonitorDatabase()
try:
if str(user_id).isdigit():
logger.info(u"PlexPy DataFactory :: Deleting all history for user id %s from database." % user_id)
session_history_media_info_del = \
monitor_db.action('DELETE FROM '
'session_history_media_info '
'WHERE session_history_media_info.id IN (SELECT session_history_media_info.id '
'FROM session_history_media_info '
'JOIN session_history ON session_history_media_info.id = session_history.id '
'WHERE session_history.user_id = ?)', [user_id])
session_history_metadata_del = \
monitor_db.action('DELETE FROM '
'session_history_metadata '
'WHERE session_history_metadata.id IN (SELECT session_history_metadata.id '
'FROM session_history_metadata '
'JOIN session_history ON session_history_metadata.id = session_history.id '
'WHERE session_history.user_id = ?)', [user_id])
session_history_del = \
monitor_db.action('DELETE FROM '
'session_history '
'WHERE session_history.user_id = ?', [user_id])
return 'Deleted all items for user_id %s.' % user_id
else:
return 'Unable to delete items. Input user_id not valid.'
except Exception as e:
logger.warn(u"PlexPy Users :: Unable to execute database query for delete_all_history: %s." % e)
def delete(self, user_id=None):
monitor_db = database.MonitorDatabase()
try:
if str(user_id).isdigit():
self.delete_all_history(user_id)
logger.info(u"PlexPy DataFactory :: 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 keep_history = 0 WHERE user_id = ?', [user_id])
monitor_db.action('UPDATE users SET do_notify = 0 WHERE user_id = ?', [user_id])
return 'Deleted user with id %s.' % user_id
else:
return 'Unable to delete user, user_id not valid.'
except Exception as e:
logger.warn(u"PlexPy Users :: Unable to execute database query for delete: %s." % e)
def undelete(self, user_id=None, username=None):
monitor_db = database.MonitorDatabase()
try:
if user_id and str(user_id).isdigit():
logger.info(u"PlexPy DataFactory :: 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 keep_history = 1 WHERE user_id = ?', [user_id])
monitor_db.action('UPDATE users SET do_notify = 1 WHERE user_id = ?', [user_id])
return 'Re-added user with id %s.' % user_id
elif username:
logger.info(u"PlexPy DataFactory :: 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 keep_history = 1 WHERE username = ?', [username])
monitor_db.action('UPDATE users SET do_notify = 1 WHERE username = ?', [username])
return 'Re-added user with username %s.' % username
else:
return 'Unable to re-add user, user_id or username not valid.'
except Exception as e:
logger.warn(u"PlexPy Users :: Unable to execute database query for undelete: %s." % e)
# Keep method for PlexWatch import
def get_user_id(self, user=None):
if user:
try:
monitor_db = database.MonitorDatabase()
query = 'SELECT user_id FROM users WHERE username = ?'
result = monitor_db.select_single(query, args=[user])
if result:
return result['user_id']
else:
return None
except:
return None
return None

File diff suppressed because it is too large Load diff