mirror of
https://github.com/Tautulli/Tautulli.git
synced 2025-07-15 01:32:57 -07:00
Merge pull request #263 from drzoidberg33/library-id-changes
Library id changes
This commit is contained in:
commit
ecedd4d231
74 changed files with 7355 additions and 3748 deletions
|
@ -175,6 +175,10 @@ def initialize(config_file):
|
|||
if CONFIG.PMS_TOKEN and CONFIG.REFRESH_USERS_ON_STARTUP:
|
||||
plextv.refresh_users()
|
||||
|
||||
# Refresh the libraries list on startup
|
||||
if CONFIG.PMS_TOKEN and CONFIG.REFRESH_LIBRARIES_ON_STARTUP:
|
||||
pmsconnect.refresh_libraries()
|
||||
|
||||
# Store the original umask
|
||||
UMASK = os.umask(0)
|
||||
os.umask(UMASK)
|
||||
|
@ -256,8 +260,6 @@ def initialize_scheduler():
|
|||
Start the scheduled background tasks. Re-schedule if interval settings changed.
|
||||
"""
|
||||
|
||||
|
||||
|
||||
with SCHED_LOCK:
|
||||
|
||||
# Check if scheduler should be started
|
||||
|
@ -280,7 +282,7 @@ def initialize_scheduler():
|
|||
else:
|
||||
seconds = 0
|
||||
|
||||
if CONFIG.PMS_IP and CONFIG.PMS_TOKEN:
|
||||
if CONFIG.PMS_IP and CONFIG.PMS_TOKEN and CONFIG.UPDATE_SECTION_IDS != -1:
|
||||
schedule_job(plextv.get_real_pms_url, 'Refresh Plex Server URLs',
|
||||
hours=12, minutes=0, seconds=0)
|
||||
schedule_job(pmsconnect.get_server_friendly_name, 'Refresh Plex Server Name',
|
||||
|
@ -311,8 +313,14 @@ def initialize_scheduler():
|
|||
else:
|
||||
hours = 0
|
||||
|
||||
|
||||
if CONFIG.PMS_TOKEN:
|
||||
schedule_job(plextv.refresh_users, 'Refresh users list', hours=hours, minutes=0, seconds=0)
|
||||
schedule_job(plextv.refresh_users, 'Refresh users list',
|
||||
hours=hours, minutes=0, seconds=0)
|
||||
|
||||
if CONFIG.PMS_IP and CONFIG.PMS_TOKEN:
|
||||
schedule_job(pmsconnect.refresh_libraries, 'Refresh libraries list',
|
||||
hours=hours, minutes=0, seconds=0)
|
||||
|
||||
# Start scheduler
|
||||
if start_jobs and len(SCHED.get_jobs()):
|
||||
|
@ -369,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, section_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, '
|
||||
|
@ -405,11 +413,10 @@ def dbcheck():
|
|||
'CREATE TABLE IF NOT EXISTS session_history_metadata (id INTEGER PRIMARY KEY, '
|
||||
'rating_key INTEGER, parent_rating_key INTEGER, grandparent_rating_key INTEGER, '
|
||||
'title TEXT, parent_title TEXT, grandparent_title TEXT, full_title TEXT, media_index INTEGER, '
|
||||
'parent_media_index INTEGER, thumb TEXT, parent_thumb TEXT, grandparent_thumb TEXT, art TEXT, media_type TEXT, '
|
||||
'year INTEGER, originally_available_at TEXT, added_at INTEGER, updated_at INTEGER, last_viewed_at INTEGER, '
|
||||
'content_rating TEXT, summary TEXT, tagline TEXT, rating TEXT, duration INTEGER DEFAULT 0, guid TEXT, '
|
||||
'directors TEXT, writers TEXT, actors TEXT, genres TEXT, studio TEXT)'
|
||||
''
|
||||
'parent_media_index INTEGER, section_id INTEGER, thumb TEXT, parent_thumb TEXT, grandparent_thumb TEXT, '
|
||||
'art TEXT, media_type TEXT, year INTEGER, originally_available_at TEXT, added_at INTEGER, updated_at INTEGER, '
|
||||
'last_viewed_at INTEGER, content_rating TEXT, summary TEXT, tagline TEXT, rating TEXT, '
|
||||
'duration INTEGER DEFAULT 0, guid TEXT, directors TEXT, writers TEXT, actors TEXT, genres TEXT, studio TEXT)'
|
||||
)
|
||||
|
||||
# users table :: This table keeps record of the friends list
|
||||
|
@ -421,6 +428,23 @@ def dbcheck():
|
|||
'keep_history INTEGER DEFAULT 1, deleted_user INTEGER DEFAULT 0)'
|
||||
)
|
||||
|
||||
# notify_log table :: This is a table which logs notifications sent
|
||||
c_db.execute(
|
||||
'CREATE TABLE IF NOT EXISTS notify_log (id INTEGER PRIMARY KEY AUTOINCREMENT, '
|
||||
'session_key INTEGER, rating_key INTEGER, user_id INTEGER, user TEXT, '
|
||||
'agent_id INTEGER, agent_name TEXT, on_play INTEGER, on_stop INTEGER, on_watched INTEGER, '
|
||||
'on_pause INTEGER, on_resume INTEGER, on_buffer INTEGER, on_created INTEGER)'
|
||||
)
|
||||
|
||||
# library_sections table :: This table keeps record of the servers library sections
|
||||
c_db.execute(
|
||||
'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, do_notify_created INTEGER DEFAULT 1, keep_history INTEGER DEFAULT 1, '
|
||||
'deleted_section INTEGER DEFAULT 0)'
|
||||
)
|
||||
|
||||
# Upgrade sessions table from earlier versions
|
||||
try:
|
||||
c_db.execute('SELECT started from sessions')
|
||||
|
@ -547,6 +571,59 @@ def dbcheck():
|
|||
'ALTER TABLE sessions ADD COLUMN transcode_height INTEGER'
|
||||
)
|
||||
|
||||
# Upgrade sessions table from earlier versions
|
||||
try:
|
||||
c_db.execute('SELECT buffer_count from sessions')
|
||||
except sqlite3.OperationalError:
|
||||
logger.debug(u"Altering database. Updating database table sessions.")
|
||||
c_db.execute(
|
||||
'ALTER TABLE sessions ADD COLUMN buffer_count INTEGER DEFAULT 0'
|
||||
)
|
||||
c_db.execute(
|
||||
'ALTER TABLE sessions ADD COLUMN buffer_last_triggered INTEGER'
|
||||
)
|
||||
|
||||
# Upgrade sessions table from earlier versions
|
||||
try:
|
||||
c_db.execute('SELECT last_paused from sessions')
|
||||
except sqlite3.OperationalError:
|
||||
logger.debug(u"Altering database. Updating database table sessions.")
|
||||
c_db.execute(
|
||||
'ALTER TABLE sessions ADD COLUMN last_paused INTEGER'
|
||||
)
|
||||
|
||||
# Upgrade sessions table from earlier versions
|
||||
try:
|
||||
c_db.execute('SELECT section_id from sessions')
|
||||
except sqlite3.OperationalError:
|
||||
logger.debug(u"Altering database. Updating database table sessions.")
|
||||
c_db.execute(
|
||||
'ALTER TABLE sessions ADD COLUMN section_id INTEGER'
|
||||
)
|
||||
|
||||
# Upgrade session_history table from earlier versions
|
||||
try:
|
||||
c_db.execute('SELECT reference_id from session_history')
|
||||
except sqlite3.OperationalError:
|
||||
logger.debug(u"Altering database. Updating database table session_history.")
|
||||
c_db.execute(
|
||||
'ALTER TABLE session_history ADD COLUMN reference_id INTEGER DEFAULT 0'
|
||||
)
|
||||
# Set reference_id to the first row where (user_id = previous row, rating_key != previous row) and user_id = user_id
|
||||
c_db.execute(
|
||||
'UPDATE session_history ' \
|
||||
'SET reference_id = (SELECT (CASE \
|
||||
WHEN (SELECT MIN(id) FROM session_history WHERE id > ( \
|
||||
SELECT MAX(id) FROM session_history \
|
||||
WHERE (user_id = t1.user_id AND rating_key <> t1.rating_key AND id < t1.id)) AND user_id = t1.user_id) IS NULL \
|
||||
THEN (SELECT MIN(id) FROM session_history WHERE (user_id = t1.user_id)) \
|
||||
ELSE (SELECT MIN(id) FROM session_history WHERE id > ( \
|
||||
SELECT MAX(id) FROM session_history \
|
||||
WHERE (user_id = t1.user_id AND rating_key <> t1.rating_key AND id < t1.id)) AND user_id = t1.user_id) END) ' \
|
||||
'FROM session_history AS t1 ' \
|
||||
'WHERE t1.id = session_history.id) '
|
||||
)
|
||||
|
||||
# Upgrade session_history_metadata table from earlier versions
|
||||
try:
|
||||
c_db.execute('SELECT full_title from session_history_metadata')
|
||||
|
@ -565,13 +642,14 @@ def dbcheck():
|
|||
'ALTER TABLE session_history_metadata ADD COLUMN tagline TEXT'
|
||||
)
|
||||
|
||||
# notify_log table :: This is a table which logs notifications sent
|
||||
c_db.execute(
|
||||
'CREATE TABLE IF NOT EXISTS notify_log (id INTEGER PRIMARY KEY AUTOINCREMENT, '
|
||||
'session_key INTEGER, rating_key INTEGER, user_id INTEGER, user TEXT, '
|
||||
'agent_id INTEGER, agent_name TEXT, on_play INTEGER, on_stop INTEGER, on_watched INTEGER, '
|
||||
'on_pause INTEGER, on_resume INTEGER, on_buffer INTEGER, on_created INTEGER)'
|
||||
)
|
||||
# Upgrade session_history_metadata table from earlier versions
|
||||
try:
|
||||
c_db.execute('SELECT section_id from session_history_metadata')
|
||||
except sqlite3.OperationalError:
|
||||
logger.debug(u"Altering database. Updating database table session_history_metadata.")
|
||||
c_db.execute(
|
||||
'ALTER TABLE session_history_metadata ADD COLUMN section_id INTEGER'
|
||||
)
|
||||
|
||||
# Upgrade users table from earlier versions
|
||||
try:
|
||||
|
@ -591,6 +669,24 @@ def dbcheck():
|
|||
'ALTER TABLE users ADD COLUMN keep_history INTEGER DEFAULT 1'
|
||||
)
|
||||
|
||||
# Upgrade users table from earlier versions
|
||||
try:
|
||||
c_db.execute('SELECT custom_avatar_url from users')
|
||||
except sqlite3.OperationalError:
|
||||
logger.debug(u"Altering database. Updating database table users.")
|
||||
c_db.execute(
|
||||
'ALTER TABLE users ADD COLUMN custom_avatar_url TEXT'
|
||||
)
|
||||
|
||||
# Upgrade users table from earlier versions
|
||||
try:
|
||||
c_db.execute('SELECT deleted_user from users')
|
||||
except sqlite3.OperationalError:
|
||||
logger.debug(u"Altering database. Updating database table users.")
|
||||
c_db.execute(
|
||||
'ALTER TABLE users ADD COLUMN deleted_user INTEGER DEFAULT 0'
|
||||
)
|
||||
|
||||
# Upgrade notify_log table from earlier versions
|
||||
try:
|
||||
c_db.execute('SELECT on_pause from notify_log')
|
||||
|
@ -615,74 +711,12 @@ def dbcheck():
|
|||
'ALTER TABLE notify_log ADD COLUMN on_created INTEGER'
|
||||
)
|
||||
|
||||
# Upgrade sessions table from earlier versions
|
||||
try:
|
||||
c_db.execute('SELECT buffer_count from sessions')
|
||||
except sqlite3.OperationalError:
|
||||
logger.debug(u"Altering database. Updating database table sessions.")
|
||||
c_db.execute(
|
||||
'ALTER TABLE sessions ADD COLUMN buffer_count INTEGER DEFAULT 0'
|
||||
)
|
||||
c_db.execute(
|
||||
'ALTER TABLE sessions ADD COLUMN buffer_last_triggered INTEGER'
|
||||
)
|
||||
|
||||
# Upgrade users table from earlier versions
|
||||
try:
|
||||
c_db.execute('SELECT custom_avatar_url from users')
|
||||
except sqlite3.OperationalError:
|
||||
logger.debug(u"Altering database. Updating database table users.")
|
||||
c_db.execute(
|
||||
'ALTER TABLE users ADD COLUMN custom_avatar_url TEXT'
|
||||
)
|
||||
|
||||
# Upgrade sessions table from earlier versions
|
||||
try:
|
||||
c_db.execute('SELECT last_paused from sessions')
|
||||
except sqlite3.OperationalError:
|
||||
logger.debug(u"Altering database. Updating database table sessions.")
|
||||
c_db.execute(
|
||||
'ALTER TABLE sessions ADD COLUMN last_paused INTEGER'
|
||||
)
|
||||
|
||||
# Add "Local" user to database as default unauthenticated user.
|
||||
result = c_db.execute('SELECT id FROM users WHERE username = "Local"')
|
||||
if not result.fetchone():
|
||||
logger.debug(u'User "Local" does not exist. Adding user.')
|
||||
c_db.execute('INSERT INTO users (user_id, username) VALUES (0, "Local")')
|
||||
|
||||
# Upgrade session_history table from earlier versions
|
||||
try:
|
||||
c_db.execute('SELECT reference_id from session_history')
|
||||
except sqlite3.OperationalError:
|
||||
logger.debug(u"Altering database. Updating database table session_history.")
|
||||
c_db.execute(
|
||||
'ALTER TABLE session_history ADD COLUMN reference_id INTEGER DEFAULT 0'
|
||||
)
|
||||
# Set reference_id to the first row where (user_id = previous row, rating_key != previous row) and user_id = user_id
|
||||
c_db.execute(
|
||||
'UPDATE session_history ' \
|
||||
'SET reference_id = (SELECT (CASE \
|
||||
WHEN (SELECT MIN(id) FROM session_history WHERE id > ( \
|
||||
SELECT MAX(id) FROM session_history \
|
||||
WHERE (user_id = t1.user_id AND rating_key <> t1.rating_key AND id < t1.id)) AND user_id = t1.user_id) IS NULL \
|
||||
THEN (SELECT MIN(id) FROM session_history WHERE (user_id = t1.user_id)) \
|
||||
ELSE (SELECT MIN(id) FROM session_history WHERE id > ( \
|
||||
SELECT MAX(id) FROM session_history \
|
||||
WHERE (user_id = t1.user_id AND rating_key <> t1.rating_key AND id < t1.id)) AND user_id = t1.user_id) END) ' \
|
||||
'FROM session_history AS t1 ' \
|
||||
'WHERE t1.id = session_history.id) '
|
||||
)
|
||||
|
||||
# Upgrade users table from earlier versions
|
||||
try:
|
||||
c_db.execute('SELECT deleted_user from users')
|
||||
except sqlite3.OperationalError:
|
||||
logger.debug(u"Altering database. Updating database table users.")
|
||||
c_db.execute(
|
||||
'ALTER TABLE users ADD COLUMN deleted_user INTEGER DEFAULT 0'
|
||||
)
|
||||
|
||||
conn_db.commit()
|
||||
c_db.close()
|
||||
|
||||
|
|
|
@ -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())
|
||||
|
||||
|
|
|
@ -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['section_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['section_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
|
||||
|
|
|
@ -29,6 +29,7 @@ class ActivityProcessor(object):
|
|||
def write_session(self, session=None, notify=True):
|
||||
if session:
|
||||
values = {'session_key': session['session_key'],
|
||||
'section_id': session['section_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['section_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...")
|
||||
|
@ -250,19 +257,20 @@ class ActivityProcessor(object):
|
|||
# logger.debug(u"PlexPy ActivityProcessor :: Attempting to write to session_history_metadata table...")
|
||||
query = 'INSERT INTO session_history_metadata (id, rating_key, parent_rating_key, ' \
|
||||
'grandparent_rating_key, title, parent_title, grandparent_title, full_title, media_index, ' \
|
||||
'parent_media_index, thumb, parent_thumb, grandparent_thumb, art, media_type, year, ' \
|
||||
'originally_available_at, added_at, updated_at, last_viewed_at, content_rating, summary, ' \
|
||||
'tagline, rating, duration, guid, directors, writers, actors, genres, studio) VALUES ' \
|
||||
'parent_media_index, section_id, thumb, parent_thumb, grandparent_thumb, art, media_type, ' \
|
||||
'year, originally_available_at, added_at, updated_at, last_viewed_at, content_rating, ' \
|
||||
'summary, tagline, rating, duration, guid, directors, writers, actors, genres, studio) VALUES ' \
|
||||
'(last_insert_rowid(), ' \
|
||||
'?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)'
|
||||
'?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)'
|
||||
|
||||
args = [session['rating_key'], session['parent_rating_key'], session['grandparent_rating_key'],
|
||||
session['title'], session['parent_title'], session['grandparent_title'], full_title,
|
||||
metadata['index'], metadata['parent_index'], metadata['thumb'], metadata['parent_thumb'],
|
||||
metadata['grandparent_thumb'], metadata['art'], session['media_type'], metadata['year'],
|
||||
metadata['originally_available_at'], metadata['added_at'], metadata['updated_at'],
|
||||
metadata['media_index'], metadata['parent_media_index'], metadata['section_id'], metadata['thumb'],
|
||||
metadata['parent_thumb'], metadata['grandparent_thumb'], metadata['art'], session['media_type'],
|
||||
metadata['year'], metadata['originally_available_at'], metadata['added_at'], metadata['updated_at'],
|
||||
metadata['last_viewed_at'], metadata['content_rating'], metadata['summary'], metadata['tagline'],
|
||||
metadata['rating'], metadata['duration'], metadata['guid'], directors, writers, actors, genres, metadata['studio']]
|
||||
metadata['rating'], metadata['duration'], metadata['guid'], directors, writers, actors, genres,
|
||||
metadata['studio']]
|
||||
|
||||
# logger.debug(u"PlexPy ActivityProcessor :: Writing session_history_metadata transaction...")
|
||||
self.db.action(query=query, args=args)
|
||||
|
@ -330,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:
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -97,6 +97,8 @@ _CONFIG_DEFINITIONS = {
|
|||
'FACEBOOK_ON_INTUP': (int, 'Facebook', 0),
|
||||
'FIRST_RUN_COMPLETE': (int, 'General', 0),
|
||||
'FREEZE_DB': (int, 'General', 0),
|
||||
'GET_FILE_SIZES': (int, 'General', 0),
|
||||
'GET_FILE_SIZES_HOLD': (dict, 'General', {'section_ids': [], 'rating_keys': []}),
|
||||
'GIT_BRANCH': (str, 'General', 'master'),
|
||||
'GIT_PATH': (str, 'General', ''),
|
||||
'GIT_USER': (str, 'General', 'drzoidberg33'),
|
||||
|
@ -118,12 +120,12 @@ _CONFIG_DEFINITIONS = {
|
|||
'GROWL_ON_INTDOWN': (int, 'Growl', 0),
|
||||
'GROWL_ON_EXTUP': (int, 'Growl', 0),
|
||||
'GROWL_ON_INTUP': (int, 'Growl', 0),
|
||||
'HOME_LIBRARY_CARDS': (str, 'General', 'library_statistics_first'),
|
||||
'HOME_LIBRARY_CARDS': (list, 'General', ['first_run']),
|
||||
'HOME_STATS_LENGTH': (int, 'General', 30),
|
||||
'HOME_STATS_TYPE': (int, 'General', 0),
|
||||
'HOME_STATS_COUNT': (int, 'General', 5),
|
||||
'HOME_STATS_CARDS': (str, 'General', 'watch_statistics, top_tv, popular_tv, top_movies, popular_movies, ' \
|
||||
'top_music, popular_music, last_watched, top_users, top_platforms, most_concurrent'),
|
||||
'HOME_STATS_CARDS': (list, 'General', ['top_tv', 'popular_tv', 'top_movies', 'popular_movies', 'top_music', \
|
||||
'popular_music', 'last_watched', 'top_users', 'top_platforms', 'most_concurrent']),
|
||||
'HTTPS_CERT': (str, 'General', ''),
|
||||
'HTTPS_KEY': (str, 'General', ''),
|
||||
'HTTP_HOST': (str, 'General', '0.0.0.0'),
|
||||
|
@ -293,6 +295,8 @@ _CONFIG_DEFINITIONS = {
|
|||
'PUSHOVER_ON_INTDOWN': (int, 'Pushover', 0),
|
||||
'PUSHOVER_ON_EXTUP': (int, 'Pushover', 0),
|
||||
'PUSHOVER_ON_INTUP': (int, 'Pushover', 0),
|
||||
'REFRESH_LIBRARIES_INTERVAL': (int, 'Monitoring', 12),
|
||||
'REFRESH_LIBRARIES_ON_STARTUP': (int, 'Monitoring', 1),
|
||||
'REFRESH_USERS_INTERVAL': (int, 'Monitoring', 12),
|
||||
'REFRESH_USERS_ON_STARTUP': (int, 'Monitoring', 1),
|
||||
'SLACK_ENABLED': (int, 'Slack', 0),
|
||||
|
@ -370,6 +374,7 @@ _CONFIG_DEFINITIONS = {
|
|||
'TWITTER_ON_EXTUP': (int, 'Twitter', 0),
|
||||
'TWITTER_ON_INTUP': (int, 'Twitter', 0),
|
||||
'UPDATE_DB_INTERVAL': (int, 'General', 24),
|
||||
'UPDATE_SECTION_IDS': (int, 'General', 1),
|
||||
'VERIFY_SSL_CERT': (bool_int, 'Advanced', 1),
|
||||
'VIDEO_LOGGING_ENABLE': (int, 'Monitoring', 1),
|
||||
'XBMC_ENABLED': (int, 'XBMC', 0),
|
||||
|
@ -505,3 +510,17 @@ class Config(object):
|
|||
self.MOVIE_LOGGING_ENABLE = 0
|
||||
self.TV_LOGGING_ENABLE = 0
|
||||
self.CONFIG_VERSION = '1'
|
||||
if self.CONFIG_VERSION == '1':
|
||||
# Change home_stats_cards to list
|
||||
if self.HOME_STATS_CARDS:
|
||||
home_stats_cards = ''.join(self.HOME_STATS_CARDS).split(', ')
|
||||
if 'watch_statistics' in home_stats_cards:
|
||||
home_stats_cards.remove('watch_statistics')
|
||||
self.HOME_STATS_CARDS = home_stats_cards
|
||||
# Change home_library_cards to list
|
||||
if self.HOME_LIBRARY_CARDS:
|
||||
home_library_cards = ''.join(self.HOME_LIBRARY_CARDS).split(', ')
|
||||
if 'library_statistics' in home_library_cards:
|
||||
home_library_cards.remove('library_statistics')
|
||||
self.HOME_LIBRARY_CARDS = home_library_cards
|
||||
self.CONFIG_VERSION = '2'
|
|
@ -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,
|
||||
|
@ -98,12 +98,12 @@ class DataFactory(object):
|
|||
for item in history:
|
||||
filter_duration += int(item['duration'])
|
||||
|
||||
if item["media_type"] == 'episode' and item["parent_thumb"]:
|
||||
thumb = item["parent_thumb"]
|
||||
elif item["media_type"] == 'episode':
|
||||
thumb = item["grandparent_thumb"]
|
||||
if item['media_type'] == 'episode' and item['parent_thumb']:
|
||||
thumb = item['parent_thumb']
|
||||
elif item['media_type'] == 'episode':
|
||||
thumb = item['grandparent_thumb']
|
||||
else:
|
||||
thumb = item["thumb"]
|
||||
thumb = item['thumb']
|
||||
|
||||
if item['percent_complete'] >= watched_percent:
|
||||
watched_status = 1
|
||||
|
@ -113,37 +113,37 @@ class DataFactory(object):
|
|||
watched_status = 0
|
||||
|
||||
# Rename Mystery platform names
|
||||
platform = common.PLATFORM_NAME_OVERRIDES.get(item["platform"], item["platform"])
|
||||
platform = common.PLATFORM_NAME_OVERRIDES.get(item['platform'], item['platform'])
|
||||
|
||||
row = {"reference_id": item["reference_id"],
|
||||
"id": item["id"],
|
||||
"date": item["date"],
|
||||
"started": item["started"],
|
||||
"stopped": item["stopped"],
|
||||
"duration": item["duration"],
|
||||
"paused_counter": item["paused_counter"],
|
||||
"user_id": item["user_id"],
|
||||
"user": item["user"],
|
||||
"friendly_name": item["friendly_name"],
|
||||
"platform": platform,
|
||||
"player": item['player'],
|
||||
"ip_address": item["ip_address"],
|
||||
"media_type": item["media_type"],
|
||||
"rating_key": item["rating_key"],
|
||||
"parent_rating_key": item["parent_rating_key"],
|
||||
"grandparent_rating_key": item["grandparent_rating_key"],
|
||||
"full_title": item["full_title"],
|
||||
"parent_title": item["parent_title"],
|
||||
"year": item["year"],
|
||||
"media_index": item["media_index"],
|
||||
"parent_media_index": item["parent_media_index"],
|
||||
"thumb": thumb,
|
||||
"video_decision": item["video_decision"],
|
||||
"audio_decision": item["audio_decision"],
|
||||
"percent_complete": int(round(item['percent_complete'])),
|
||||
"watched_status": watched_status,
|
||||
"group_count": item["group_count"],
|
||||
"group_ids": item["group_ids"]
|
||||
row = {'reference_id': item['reference_id'],
|
||||
'id': item['id'],
|
||||
'date': item['date'],
|
||||
'started': item['started'],
|
||||
'stopped': item['stopped'],
|
||||
'duration': item['duration'],
|
||||
'paused_counter': item['paused_counter'],
|
||||
'user_id': item['user_id'],
|
||||
'user': item['user'],
|
||||
'friendly_name': item['friendly_name'],
|
||||
'platform': platform,
|
||||
'player': item['player'],
|
||||
'ip_address': item['ip_address'],
|
||||
'media_type': item['media_type'],
|
||||
'rating_key': item['rating_key'],
|
||||
'parent_rating_key': item['parent_rating_key'],
|
||||
'grandparent_rating_key': item['grandparent_rating_key'],
|
||||
'full_title': item['full_title'],
|
||||
'parent_title': item['parent_title'],
|
||||
'year': item['year'],
|
||||
'media_index': item['media_index'],
|
||||
'parent_media_index': item['parent_media_index'],
|
||||
'thumb': thumb,
|
||||
'video_decision': item['video_decision'],
|
||||
'audio_decision': item['audio_decision'],
|
||||
'percent_complete': int(round(item['percent_complete'])),
|
||||
'watched_status': watched_status,
|
||||
'group_count': item['group_count'],
|
||||
'group_ids': item['group_ids']
|
||||
}
|
||||
|
||||
rows.append(row)
|
||||
|
@ -154,11 +154,11 @@ class DataFactory(object):
|
|||
'draw': query['draw'],
|
||||
'filter_duration': helpers.human_duration(filter_duration, sig='dhm'),
|
||||
'total_duration': helpers.human_duration(total_duration, sig='dhm')
|
||||
}
|
||||
}
|
||||
|
||||
return dict
|
||||
|
||||
def get_home_stats(self, grouping=0, time_range='30', stats_type=0, stats_count='5', stats_cards='', notify_watched_percent='85'):
|
||||
def get_home_stats(self, grouping=0, time_range='30', stats_type=0, stats_count='5', stats_cards=[], notify_watched_percent='85'):
|
||||
monitor_db = database.MonitorDatabase()
|
||||
|
||||
group_by = 'session_history.reference_id' if grouping else 'session_history.id'
|
||||
|
@ -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,
|
||||
|
@ -654,6 +656,35 @@ class DataFactory(object):
|
|||
|
||||
return home_stats
|
||||
|
||||
def get_library_stats(self, library_cards=[]):
|
||||
monitor_db = database.MonitorDatabase()
|
||||
|
||||
library_stats = []
|
||||
|
||||
for id in library_cards:
|
||||
if id.isdigit():
|
||||
try:
|
||||
query = 'SELECT section_id, section_name, section_type, thumb, count, parent_count, child_count ' \
|
||||
'FROM library_sections ' \
|
||||
'WHERE section_id = %s ' % id
|
||||
result = monitor_db.select(query)
|
||||
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:
|
||||
library = {'section_id': item['section_id'],
|
||||
'section_name': item['section_name'],
|
||||
'section_type': item['section_type'],
|
||||
'thumb': item['thumb'],
|
||||
'count': item['count'],
|
||||
'parent_count': item['parent_count'],
|
||||
'child_count': item['child_count']
|
||||
}
|
||||
library_stats.append(library)
|
||||
|
||||
return library_stats
|
||||
|
||||
def get_stream_details(self, row_id=None):
|
||||
monitor_db = database.MonitorDatabase()
|
||||
|
||||
|
@ -696,86 +727,33 @@ class DataFactory(object):
|
|||
|
||||
return stream_output
|
||||
|
||||
def get_recently_watched(self, user=None, user_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])
|
||||
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,
|
||||
'index': row['media_index'],
|
||||
'parent_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, row_id):
|
||||
def get_metadata_details(self, rating_key):
|
||||
monitor_db = database.MonitorDatabase()
|
||||
|
||||
if row_id:
|
||||
query = 'SELECT rating_key, parent_rating_key, grandparent_rating_key, title, parent_title, grandparent_title, ' \
|
||||
'full_title, media_index, parent_media_index, thumb, parent_thumb, grandparent_thumb, art, media_type, ' \
|
||||
'year, originally_available_at, added_at, updated_at, last_viewed_at, content_rating, summary, tagline, ' \
|
||||
'rating, duration, guid, directors, writers, actors, genres, studio ' \
|
||||
if rating_key:
|
||||
query = 'SELECT session_history_metadata.rating_key, session_history_metadata.parent_rating_key, ' \
|
||||
'session_history_metadata.grandparent_rating_key, session_history_metadata.title, ' \
|
||||
'session_history_metadata.parent_title, session_history_metadata.grandparent_title, ' \
|
||||
'session_history_metadata.full_title, library_sections.section_name, ' \
|
||||
'session_history_metadata.media_index, session_history_metadata.parent_media_index, ' \
|
||||
'session_history_metadata.section_id, session_history_metadata.thumb, ' \
|
||||
'session_history_metadata.parent_thumb, session_history_metadata.grandparent_thumb, ' \
|
||||
'session_history_metadata.art, session_history_metadata.media_type, session_history_metadata.year, ' \
|
||||
'session_history_metadata.originally_available_at, session_history_metadata.added_at, ' \
|
||||
'session_history_metadata.updated_at, session_history_metadata.last_viewed_at, ' \
|
||||
'session_history_metadata.content_rating, session_history_metadata.summary, ' \
|
||||
'session_history_metadata.tagline, session_history_metadata.rating, session_history_metadata.duration, ' \
|
||||
'session_history_metadata.guid, session_history_metadata.directors, session_history_metadata.writers, ' \
|
||||
'session_history_metadata.actors, session_history_metadata.genres, session_history_metadata.studio, ' \
|
||||
'session_history_media_info.container, session_history_media_info.bitrate, ' \
|
||||
'session_history_media_info.video_codec, session_history_media_info.video_resolution, ' \
|
||||
'session_history_media_info.video_framerate, session_history_media_info.audio_codec, ' \
|
||||
'session_history_media_info.audio_channels ' \
|
||||
'FROM session_history_metadata ' \
|
||||
'WHERE id = ?'
|
||||
result = monitor_db.select(query=query, args=[row_id])
|
||||
'JOIN library_sections ON session_history_metadata.section_id = library_sections.section_id ' \
|
||||
'JOIN session_history_media_info ON session_history_metadata.id = session_history_media_info.id ' \
|
||||
'WHERE session_history_metadata.rating_key = ?'
|
||||
result = monitor_db.select(query=query, args=[rating_key])
|
||||
else:
|
||||
result = []
|
||||
|
||||
|
@ -791,9 +769,9 @@ class DataFactory(object):
|
|||
'parent_rating_key': item['parent_rating_key'],
|
||||
'grandparent_rating_key': item['grandparent_rating_key'],
|
||||
'grandparent_title': item['grandparent_title'],
|
||||
'parent_index': item['parent_media_index'],
|
||||
'parent_media_index': item['parent_media_index'],
|
||||
'parent_title': item['parent_title'],
|
||||
'index': item['media_index'],
|
||||
'media_index': item['media_index'],
|
||||
'studio': item['studio'],
|
||||
'title': item['title'],
|
||||
'content_rating': item['content_rating'],
|
||||
|
@ -814,88 +792,61 @@ class DataFactory(object):
|
|||
'writers': writers,
|
||||
'directors': directors,
|
||||
'genres': genres,
|
||||
'actors': actors
|
||||
'actors': actors,
|
||||
'library_name': item['section_name'],
|
||||
'section_id': item['section_id'],
|
||||
'container': item['container'],
|
||||
'bitrate': item['bitrate'],
|
||||
'video_codec': item['video_codec'],
|
||||
'video_resolution': item['video_resolution'],
|
||||
'video_framerate': item['video_framerate'],
|
||||
'audio_codec': item['audio_codec'],
|
||||
'audio_channels': item['audio_channels']
|
||||
}
|
||||
|
||||
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):
|
||||
total_duration = 0
|
||||
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()
|
||||
|
@ -984,8 +935,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, ' \
|
||||
|
@ -1028,7 +979,25 @@ class DataFactory(object):
|
|||
|
||||
return key_list
|
||||
|
||||
def update_rating_key(self, old_key_list='', new_key_list='', media_type=''):
|
||||
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()
|
||||
monitor_db = database.MonitorDatabase()
|
||||
|
||||
# function to map rating keys pairs
|
||||
|
@ -1036,8 +1005,7 @@ class DataFactory(object):
|
|||
pairs = {}
|
||||
for k, v in old.iteritems():
|
||||
if k in new:
|
||||
if v['rating_key'] != new[k]['rating_key']:
|
||||
pairs.update({v['rating_key']: new[k]['rating_key']})
|
||||
pairs.update({v['rating_key']: new[k]['rating_key']})
|
||||
if 'children' in old[k]:
|
||||
pairs.update(get_pairs(old[k]['children'], new[k]['children']))
|
||||
|
||||
|
@ -1049,89 +1017,73 @@ class DataFactory(object):
|
|||
mapping = get_pairs(old_key_list, new_key_list)
|
||||
|
||||
if mapping:
|
||||
logger.info(u"PlexPy DataFactory :: Updating rating keys in the database.")
|
||||
logger.info(u"PlexPy DataFactory :: Updating metadata in the database.")
|
||||
for old_key, new_key in mapping.iteritems():
|
||||
# check rating_key (3 tables)
|
||||
monitor_db.action('UPDATE session_history SET rating_key = ? WHERE rating_key = ?',
|
||||
[new_key, old_key])
|
||||
monitor_db.action('UPDATE session_history_media_info SET rating_key = ? WHERE rating_key = ?',
|
||||
[new_key, old_key])
|
||||
monitor_db.action('UPDATE session_history_metadata SET rating_key = ? WHERE rating_key = ?',
|
||||
[new_key, old_key])
|
||||
result = pms_connect.get_metadata_details(new_key)
|
||||
|
||||
# check parent_rating_key (2 tables)
|
||||
monitor_db.action('UPDATE session_history SET parent_rating_key = ? WHERE parent_rating_key = ?',
|
||||
[new_key, old_key])
|
||||
monitor_db.action('UPDATE session_history_metadata SET parent_rating_key = ? WHERE parent_rating_key = ?',
|
||||
[new_key, old_key])
|
||||
if result:
|
||||
metadata = result['metadata']
|
||||
if metadata['media_type'] == 'show' or metadata['media_type'] == 'artist':
|
||||
# check grandparent_rating_key (2 tables)
|
||||
monitor_db.action('UPDATE session_history SET grandparent_rating_key = ? WHERE grandparent_rating_key = ?',
|
||||
[new_key, old_key])
|
||||
monitor_db.action('UPDATE session_history_metadata SET grandparent_rating_key = ? WHERE grandparent_rating_key = ?',
|
||||
[new_key, old_key])
|
||||
elif metadata['media_type'] == 'season' or metadata['media_type'] == 'album':
|
||||
# check parent_rating_key (2 tables)
|
||||
monitor_db.action('UPDATE session_history SET parent_rating_key = ? WHERE parent_rating_key = ?',
|
||||
[new_key, old_key])
|
||||
monitor_db.action('UPDATE session_history_metadata SET parent_rating_key = ? WHERE parent_rating_key = ?',
|
||||
[new_key, old_key])
|
||||
else:
|
||||
# check rating_key (2 tables)
|
||||
monitor_db.action('UPDATE session_history SET rating_key = ? WHERE rating_key = ?',
|
||||
[new_key, old_key])
|
||||
monitor_db.action('UPDATE session_history_media_info SET rating_key = ? WHERE rating_key = ?',
|
||||
[new_key, old_key])
|
||||
|
||||
# check grandparent_rating_key (2 tables)
|
||||
monitor_db.action('UPDATE session_history SET grandparent_rating_key = ? WHERE grandparent_rating_key = ?',
|
||||
[new_key, old_key])
|
||||
monitor_db.action('UPDATE session_history_metadata SET grandparent_rating_key = ? WHERE grandparent_rating_key = ?',
|
||||
[new_key, old_key])
|
||||
# update session_history_metadata table
|
||||
self.update_metadata_details(old_key, new_key, metadata)
|
||||
|
||||
# check thumb (1 table)
|
||||
monitor_db.action('UPDATE session_history_metadata SET thumb = replace(thumb, ?, ?) \
|
||||
WHERE thumb LIKE "/library/metadata/%s/thumb/%%"' % old_key,
|
||||
[old_key, new_key])
|
||||
|
||||
# check parent_thumb (1 table)
|
||||
monitor_db.action('UPDATE session_history_metadata SET parent_thumb = replace(parent_thumb, ?, ?) \
|
||||
WHERE parent_thumb LIKE "/library/metadata/%s/thumb/%%"' % old_key,
|
||||
[old_key, new_key])
|
||||
|
||||
# check grandparent_thumb (1 table)
|
||||
monitor_db.action('UPDATE session_history_metadata SET grandparent_thumb = replace(grandparent_thumb, ?, ?) \
|
||||
WHERE grandparent_thumb LIKE "/library/metadata/%s/thumb/%%"' % old_key,
|
||||
[old_key, new_key])
|
||||
|
||||
# check art (1 table)
|
||||
monitor_db.action('UPDATE session_history_metadata SET art = replace(art, ?, ?) \
|
||||
WHERE art LIKE "/library/metadata/%s/art/%%"' % old_key,
|
||||
[old_key, new_key])
|
||||
|
||||
return 'Updated rating key in database.'
|
||||
return 'Updated metadata in database.'
|
||||
else:
|
||||
return 'No updated rating key needed in database. No changes were made.'
|
||||
# for debugging
|
||||
#return mapping
|
||||
return 'Unable to update metadata in database. No changes were made.'
|
||||
|
||||
def get_session_ip(self, session_key=''):
|
||||
monitor_db = database.MonitorDatabase()
|
||||
def update_metadata_details(self, old_rating_key='', new_rating_key='', metadata=None):
|
||||
|
||||
if session_key:
|
||||
query = 'SELECT ip_address FROM sessions WHERE session_key = %d' % int(session_key)
|
||||
result = monitor_db.select(query)
|
||||
else:
|
||||
return None
|
||||
if metadata:
|
||||
# Create full_title
|
||||
if metadata['media_type'] == 'episode' or metadata['media_type'] == 'track':
|
||||
full_title = '%s - %s' % (metadata['grandparent_title'], metadata['title'])
|
||||
else:
|
||||
full_title = metadata['title']
|
||||
|
||||
ip_address = 'N/A'
|
||||
directors = ";".join(metadata['directors'])
|
||||
writers = ";".join(metadata['writers'])
|
||||
actors = ";".join(metadata['actors'])
|
||||
genres = ";".join(metadata['genres'])
|
||||
|
||||
for item in result:
|
||||
ip_address = item['ip_address']
|
||||
#logger.info(u"PlexPy DataFactory :: Updating metadata in the database for rating key: %s." % new_rating_key)
|
||||
monitor_db = database.MonitorDatabase()
|
||||
|
||||
return ip_address
|
||||
# Update the session_history_metadata table
|
||||
query = 'UPDATE session_history_metadata SET rating_key = ?, parent_rating_key = ?, ' \
|
||||
'grandparent_rating_key = ?, title = ?, parent_title = ?, grandparent_title = ?, full_title = ?, ' \
|
||||
'media_index = ?, parent_media_index = ?, section_id = ?, thumb = ?, parent_thumb = ?, ' \
|
||||
'grandparent_thumb = ?, art = ?, media_type = ?, year = ?, originally_available_at = ?, ' \
|
||||
'added_at = ?, updated_at = ?, last_viewed_at = ?, content_rating = ?, summary = ?, ' \
|
||||
'tagline = ?, rating = ?, duration = ?, guid = ?, directors = ?, writers = ?, actors = ?, ' \
|
||||
'genres = ?, studio = ? ' \
|
||||
'WHERE rating_key = ?'
|
||||
|
||||
def get_total_duration(self, custom_where=None):
|
||||
monitor_db = database.MonitorDatabase()
|
||||
args = [metadata['rating_key'], metadata['parent_rating_key'], metadata['grandparent_rating_key'],
|
||||
metadata['title'], metadata['parent_title'], metadata['grandparent_title'], full_title,
|
||||
metadata['media_index'], metadata['parent_media_index'], metadata['section_id'], metadata['thumb'],
|
||||
metadata['parent_thumb'], metadata['grandparent_thumb'], metadata['art'], metadata['media_type'],
|
||||
metadata['year'], metadata['originally_available_at'], metadata['added_at'], metadata['updated_at'],
|
||||
metadata['last_viewed_at'], metadata['content_rating'], metadata['summary'], metadata['tagline'],
|
||||
metadata['rating'], metadata['duration'], metadata['guid'], directors, writers, actors, genres,
|
||||
metadata['studio'],
|
||||
old_rating_key]
|
||||
|
||||
# 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 %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
|
||||
monitor_db.action(query=query, args=args)
|
|
@ -124,8 +124,9 @@ class DataTables(object):
|
|||
|
||||
order += ', '
|
||||
|
||||
order = order.rstrip(', ')
|
||||
if order:
|
||||
order = 'ORDER BY ' + order.rstrip(', ')
|
||||
order = 'ORDER BY ' + order
|
||||
|
||||
# Build where parameters
|
||||
if parameters['search']['value']:
|
||||
|
|
812
plexpy/graphs.py
812
plexpy/graphs.py
|
@ -32,10 +32,10 @@ class Graphs(object):
|
|||
|
||||
try:
|
||||
if y_axis == 'plays':
|
||||
query = 'SELECT date(started, "unixepoch", "localtime") as date_played, ' \
|
||||
'SUM(case when media_type = "episode" then 1 else 0 end) as tv_count, ' \
|
||||
'SUM(case when media_type = "movie" then 1 else 0 end) as movie_count, ' \
|
||||
'SUM(case when media_type = "track" then 1 else 0 end) as music_count ' \
|
||||
query = 'SELECT date(started, "unixepoch", "localtime") AS date_played, ' \
|
||||
'SUM(CASE WHEN media_type = "episode" THEN 1 ELSE 0 END) AS tv_count, ' \
|
||||
'SUM(CASE WHEN media_type = "movie" THEN 1 ELSE 0 END) AS movie_count, ' \
|
||||
'SUM(CASE WHEN media_type = "track" THEN 1 ELSE 0 END) AS music_count ' \
|
||||
'FROM session_history ' \
|
||||
'WHERE datetime(stopped, "unixepoch", "localtime") >= datetime("now", "-%s days", "localtime") ' \
|
||||
'GROUP BY date_played ' \
|
||||
|
@ -43,21 +43,21 @@ class Graphs(object):
|
|||
|
||||
result = monitor_db.select(query)
|
||||
else:
|
||||
query = 'SELECT date(started, "unixepoch", "localtime") as date_played, ' \
|
||||
'SUM(case when media_type = "episode" and stopped > 0 then (stopped - started) ' \
|
||||
' - (case when paused_counter is NULL then 0 else paused_counter end) else 0 end) as tv_count, ' \
|
||||
'SUM(case when media_type = "movie" and stopped > 0 then (stopped - started) ' \
|
||||
' - (case when paused_counter is NULL then 0 else paused_counter end) else 0 end) as movie_count, ' \
|
||||
'SUM(case when media_type = "track" and stopped > 0 then (stopped - started) ' \
|
||||
' - (case when paused_counter is NULL then 0 else paused_counter end) else 0 end) as music_count ' \
|
||||
query = 'SELECT date(started, "unixepoch", "localtime") AS date_played, ' \
|
||||
'SUM(CASE WHEN media_type = "episode" AND stopped > 0 THEN (stopped - started) ' \
|
||||
' - (CASE WHEN paused_counter IS NULL THEN 0 ELSE paused_counter END) ELSE 0 END) AS tv_count, ' \
|
||||
'SUM(CASE WHEN media_type = "movie" AND stopped > 0 THEN (stopped - started) ' \
|
||||
' - (CASE WHEN paused_counter IS NULL THEN 0 ELSE paused_counter END) ELSE 0 END) AS movie_count, ' \
|
||||
'SUM(CASE WHEN media_type = "track" AND stopped > 0 THEN (stopped - started) ' \
|
||||
' - (CASE WHEN paused_counter IS NULL THEN 0 ELSE paused_counter END) ELSE 0 END) AS music_count ' \
|
||||
'FROM session_history ' \
|
||||
'WHERE datetime(stopped, "unixepoch", "localtime") >= datetime("now", "-%s days", "localtime") ' \
|
||||
'GROUP BY date_played ' \
|
||||
'ORDER BY started ASC' % time_range
|
||||
|
||||
result = monitor_db.select(query)
|
||||
except:
|
||||
logger.warn("Unable to execute database query.")
|
||||
except Exception as e:
|
||||
logger.warn(u"PlexPy Graphs :: Unable to execute database query for get_total_plays_per_day: %s." % e)
|
||||
return None
|
||||
|
||||
# create our date range as some days may not have any data
|
||||
|
@ -108,49 +108,51 @@ class Graphs(object):
|
|||
if not time_range.isdigit():
|
||||
time_range = '30'
|
||||
|
||||
if y_axis == 'plays':
|
||||
query = 'SELECT strftime("%w", datetime(started, "unixepoch", "localtime")) as daynumber, ' \
|
||||
'case cast (strftime("%w", datetime(started, "unixepoch", "localtime")) as integer) ' \
|
||||
'when 0 then "Sunday" ' \
|
||||
'when 1 then "Monday" ' \
|
||||
'when 2 then "Tuesday" ' \
|
||||
'when 3 then "Wednesday" ' \
|
||||
'when 4 then "Thursday" ' \
|
||||
'when 5 then "Friday" ' \
|
||||
'else "Saturday" end as dayofweek, ' \
|
||||
'SUM(case when media_type = "episode" then 1 else 0 end) as tv_count, ' \
|
||||
'SUM(case when media_type = "movie" then 1 else 0 end) as movie_count, ' \
|
||||
'SUM(case when media_type = "track" then 1 else 0 end) as music_count ' \
|
||||
'FROM session_history ' \
|
||||
'WHERE datetime(stopped, "unixepoch", "localtime") >= ' \
|
||||
'datetime("now", "-' + time_range + ' days", "localtime") ' \
|
||||
'GROUP BY dayofweek ' \
|
||||
'ORDER BY daynumber'
|
||||
try:
|
||||
if y_axis == 'plays':
|
||||
query = 'SELECT strftime("%%w", datetime(started, "unixepoch", "localtime")) AS daynumber, ' \
|
||||
'(CASE CAST(strftime("%%w", datetime(started, "unixepoch", "localtime")) AS INTEGER) ' \
|
||||
'WHEN 0 THEN "Sunday" ' \
|
||||
'WHEN 1 THEN "Monday" ' \
|
||||
'WHEN 2 THEN "Tuesday" ' \
|
||||
'WHEN 3 THEN "Wednesday" ' \
|
||||
'WHEN 4 THEN "Thursday" ' \
|
||||
'WHEN 5 THEN "Friday" ' \
|
||||
'ELSE "Saturday" END) AS dayofweek, ' \
|
||||
'SUM(CASE WHEN media_type = "episode" THEN 1 ELSE 0 END) AS tv_count, ' \
|
||||
'SUM(CASE WHEN media_type = "movie" THEN 1 ELSE 0 END) AS movie_count, ' \
|
||||
'SUM(CASE WHEN media_type = "track" THEN 1 ELSE 0 END) AS music_count ' \
|
||||
'FROM session_history ' \
|
||||
'WHERE datetime(stopped, "unixepoch", "localtime") >= datetime("now", "-%s days", "localtime") ' \
|
||||
'GROUP BY dayofweek ' \
|
||||
'ORDER BY daynumber' % time_range
|
||||
|
||||
result = monitor_db.select(query)
|
||||
else:
|
||||
query = 'SELECT strftime("%w", datetime(started, "unixepoch", "localtime")) as daynumber, ' \
|
||||
'case cast (strftime("%w", datetime(started, "unixepoch", "localtime")) as integer) ' \
|
||||
'when 0 then "Sunday" ' \
|
||||
'when 1 then "Monday" ' \
|
||||
'when 2 then "Tuesday" ' \
|
||||
'when 3 then "Wednesday" ' \
|
||||
'when 4 then "Thursday" ' \
|
||||
'when 5 then "Friday" ' \
|
||||
'else "Saturday" end as dayofweek, ' \
|
||||
'SUM(case when media_type = "episode" and stopped > 0 then (stopped - started) ' \
|
||||
' - (case when paused_counter is NULL then 0 else paused_counter end) else 0 end) as tv_count, ' \
|
||||
'SUM(case when media_type = "movie" and stopped > 0 then (stopped - started) ' \
|
||||
' - (case when paused_counter is NULL then 0 else paused_counter end) else 0 end) as movie_count, ' \
|
||||
'SUM(case when media_type = "track" and stopped > 0 then (stopped - started) ' \
|
||||
' - (case when paused_counter is NULL then 0 else paused_counter end) else 0 end) as music_count ' \
|
||||
'FROM session_history ' \
|
||||
'WHERE datetime(stopped, "unixepoch", "localtime") >= ' \
|
||||
'datetime("now", "-' + time_range + ' days", "localtime") ' \
|
||||
'GROUP BY dayofweek ' \
|
||||
'ORDER BY daynumber'
|
||||
result = monitor_db.select(query)
|
||||
else:
|
||||
query = 'SELECT strftime("%%w", datetime(started, "unixepoch", "localtime")) AS daynumber, ' \
|
||||
'(CASE CAST(strftime("%%w", datetime(started, "unixepoch", "localtime")) AS INTEGER) ' \
|
||||
'WHEN 0 THEN "Sunday" ' \
|
||||
'WHEN 1 THEN "Monday" ' \
|
||||
'WHEN 2 THEN "Tuesday" ' \
|
||||
'WHEN 3 THEN "Wednesday" ' \
|
||||
'WHEN 4 THEN "Thursday" ' \
|
||||
'WHEN 5 THEN "Friday" ' \
|
||||
'ELSE "Saturday" END) AS dayofweek, ' \
|
||||
'SUM(CASE WHEN media_type = "episode" AND stopped > 0 THEN (stopped - started) ' \
|
||||
' - (CASE WHEN paused_counter IS NULL THEN 0 ELSE paused_counter END) ELSE 0 END) AS tv_count, ' \
|
||||
'SUM(CASE WHEN media_type = "movie" AND stopped > 0 THEN (stopped - started) ' \
|
||||
' - (CASE WHEN paused_counter IS NULL THEN 0 ELSE paused_counter END) ELSE 0 END) AS movie_count, ' \
|
||||
'SUM(CASE WHEN media_type = "track" AND stopped > 0 THEN (stopped - started) ' \
|
||||
' - (CASE WHEN paused_counter IS NULL THEN 0 ELSE paused_counter END) ELSE 0 END) AS music_count ' \
|
||||
'FROM session_history ' \
|
||||
'WHERE datetime(stopped, "unixepoch", "localtime") >= datetime("now", "-%s days", "localtime") ' \
|
||||
'GROUP BY dayofweek ' \
|
||||
'ORDER BY daynumber' % time_range
|
||||
|
||||
result = monitor_db.select(query)
|
||||
result = monitor_db.select(query)
|
||||
except Exception as e:
|
||||
logger.warn(u"PlexPy Graphs :: Unable to execute database query for get_total_plays_per_dayofweek: %s." % e)
|
||||
return None
|
||||
|
||||
days_list = ['Sunday', 'Monday', 'Tuesday', 'Wednesday',
|
||||
'Thursday', 'Friday', 'Saturday']
|
||||
|
@ -197,33 +199,35 @@ class Graphs(object):
|
|||
if not time_range.isdigit():
|
||||
time_range = '30'
|
||||
|
||||
if y_axis == 'plays':
|
||||
query = 'select strftime("%H", datetime(started, "unixepoch", "localtime")) as hourofday, ' \
|
||||
'SUM(case when media_type = "episode" then 1 else 0 end) as tv_count, ' \
|
||||
'SUM(case when media_type = "movie" then 1 else 0 end) as movie_count, ' \
|
||||
'SUM(case when media_type = "track" then 1 else 0 end) as music_count ' \
|
||||
'FROM session_history ' \
|
||||
'WHERE datetime(stopped, "unixepoch", "localtime") >= ' \
|
||||
'datetime("now", "-' + time_range + ' days", "localtime") ' \
|
||||
'GROUP BY hourofday ' \
|
||||
'ORDER BY hourofday'
|
||||
try:
|
||||
if y_axis == 'plays':
|
||||
query = 'SELECT strftime("%%H", datetime(started, "unixepoch", "localtime")) AS hourofday, ' \
|
||||
'SUM(CASE WHEN media_type = "episode" THEN 1 ELSE 0 END) AS tv_count, ' \
|
||||
'SUM(CASE WHEN media_type = "movie" THEN 1 ELSE 0 END) AS movie_count, ' \
|
||||
'SUM(CASE WHEN media_type = "track" THEN 1 ELSE 0 END) AS music_count ' \
|
||||
'FROM session_history ' \
|
||||
'WHERE datetime(stopped, "unixepoch", "localtime") >= datetime("now", "-%s days", "localtime") ' \
|
||||
'GROUP BY hourofday ' \
|
||||
'ORDER BY hourofday' % time_range
|
||||
|
||||
result = monitor_db.select(query)
|
||||
else:
|
||||
query = 'select strftime("%H", datetime(started, "unixepoch", "localtime")) as hourofday, ' \
|
||||
'SUM(case when media_type = "episode" and stopped > 0 then (stopped - started) ' \
|
||||
' - (case when paused_counter is NULL then 0 else paused_counter end) else 0 end) as tv_count, ' \
|
||||
'SUM(case when media_type = "movie" and stopped > 0 then (stopped - started) ' \
|
||||
' - (case when paused_counter is NULL then 0 else paused_counter end) else 0 end) as movie_count, ' \
|
||||
'SUM(case when media_type = "track" and stopped > 0 then (stopped - started) ' \
|
||||
' - (case when paused_counter is NULL then 0 else paused_counter end) else 0 end) as music_count ' \
|
||||
'FROM session_history ' \
|
||||
'WHERE datetime(stopped, "unixepoch", "localtime") >= ' \
|
||||
'datetime("now", "-' + time_range + ' days", "localtime") ' \
|
||||
'GROUP BY hourofday ' \
|
||||
'ORDER BY hourofday'
|
||||
result = monitor_db.select(query)
|
||||
else:
|
||||
query = 'SELECT strftime("%%H", datetime(started, "unixepoch", "localtime")) AS hourofday, ' \
|
||||
'SUM(CASE WHEN media_type = "episode" AND stopped > 0 THEN (stopped - started) ' \
|
||||
' - (CASE WHEN paused_counter IS NULL THEN 0 ELSE paused_counter END) ELSE 0 END) AS tv_count, ' \
|
||||
'SUM(CASE WHEN media_type = "movie" AND stopped > 0 THEN (stopped - started) ' \
|
||||
' - (CASE WHEN paused_counter IS NULL THEN 0 ELSE paused_counter END) ELSE 0 END) AS movie_count, ' \
|
||||
'SUM(CASE WHEN media_type = "track" AND stopped > 0 THEN (stopped - started) ' \
|
||||
' - (CASE WHEN paused_counter IS NULL THEN 0 ELSE paused_counter END) ELSE 0 END) AS music_count ' \
|
||||
'FROM session_history ' \
|
||||
'WHERE datetime(stopped, "unixepoch", "localtime") >= datetime("now", "-%s days", "localtime") ' \
|
||||
'GROUP BY hourofday ' \
|
||||
'ORDER BY hourofday' % time_range
|
||||
|
||||
result = monitor_db.select(query)
|
||||
result = monitor_db.select(query)
|
||||
except Exception as e:
|
||||
logger.warn(u"PlexPy Graphs :: Unable to execute database query for get_total_plays_per_hourofday: %s." % e)
|
||||
return None
|
||||
|
||||
hours_list = ['00','01','02','03','04','05',
|
||||
'06','07','08','09','10','11',
|
||||
|
@ -270,31 +274,36 @@ class Graphs(object):
|
|||
import time as time
|
||||
|
||||
monitor_db = database.MonitorDatabase()
|
||||
if y_axis == 'plays':
|
||||
query = 'SELECT strftime("%Y-%m", datetime(started, "unixepoch", "localtime")) as datestring, ' \
|
||||
'SUM(case when media_type = "episode" then 1 else 0 end) as tv_count, ' \
|
||||
'SUM(case when media_type = "movie" then 1 else 0 end) as movie_count, ' \
|
||||
'SUM(case when media_type = "track" then 1 else 0 end) as music_count ' \
|
||||
'FROM session_history ' \
|
||||
'WHERE datetime(started, "unixepoch", "localtime") >= datetime("now", "-12 months", "localtime") ' \
|
||||
'GROUP BY strftime("%Y-%m", datetime(started, "unixepoch", "localtime")) ' \
|
||||
'ORDER BY datestring DESC LIMIT 12'
|
||||
|
||||
result = monitor_db.select(query)
|
||||
else:
|
||||
query = 'SELECT strftime("%Y-%m", datetime(started, "unixepoch", "localtime")) as datestring, ' \
|
||||
'SUM(case when media_type = "episode" and stopped > 0 then (stopped - started) ' \
|
||||
' - (case when paused_counter is NULL then 0 else paused_counter end) else 0 end) as tv_count, ' \
|
||||
'SUM(case when media_type = "movie" and stopped > 0 then (stopped - started) ' \
|
||||
' - (case when paused_counter is NULL then 0 else paused_counter end) else 0 end) as movie_count, ' \
|
||||
'SUM(case when media_type = "track" and stopped > 0 then (stopped - started) ' \
|
||||
' - (case when paused_counter is NULL then 0 else paused_counter end) else 0 end) as music_count ' \
|
||||
'FROM session_history ' \
|
||||
'WHERE datetime(started, "unixepoch", "localtime") >= datetime("now", "-12 months", "localtime") ' \
|
||||
'GROUP BY strftime("%Y-%m", datetime(started, "unixepoch", "localtime")) ' \
|
||||
'ORDER BY datestring DESC LIMIT 12'
|
||||
try:
|
||||
if y_axis == 'plays':
|
||||
query = 'SELECT strftime("%Y-%m", datetime(started, "unixepoch", "localtime")) AS datestring, ' \
|
||||
'SUM(CASE WHEN media_type = "episode" THEN 1 ELSE 0 END) AS tv_count, ' \
|
||||
'SUM(CASE WHEN media_type = "movie" THEN 1 ELSE 0 END) AS movie_count, ' \
|
||||
'SUM(CASE WHEN media_type = "track" THEN 1 ELSE 0 END) AS music_count ' \
|
||||
'FROM session_history ' \
|
||||
'WHERE datetime(started, "unixepoch", "localtime") >= datetime("now", "-12 months", "localtime") ' \
|
||||
'GROUP BY strftime("%Y-%m", datetime(started, "unixepoch", "localtime")) ' \
|
||||
'ORDER BY datestring DESC LIMIT 12'
|
||||
|
||||
result = monitor_db.select(query)
|
||||
result = monitor_db.select(query)
|
||||
else:
|
||||
query = 'SELECT strftime("%Y-%m", datetime(started, "unixepoch", "localtime")) AS datestring, ' \
|
||||
'SUM(CASE WHEN media_type = "episode" AND stopped > 0 THEN (stopped - started) ' \
|
||||
' - (CASE WHEN paused_counter IS NULL THEN 0 ELSE paused_counter END) ELSE 0 END) AS tv_count, ' \
|
||||
'SUM(CASE WHEN media_type = "movie" AND stopped > 0 THEN (stopped - started) ' \
|
||||
' - (CASE WHEN paused_counter IS NULL THEN 0 ELSE paused_counter END) ELSE 0 END) AS movie_count, ' \
|
||||
'SUM(CASE WHEN media_type = "track" AND stopped > 0 THEN (stopped - started) ' \
|
||||
' - (CASE WHEN paused_counter IS NULL THEN 0 ELSE paused_counter END) ELSE 0 END) AS music_count ' \
|
||||
'FROM session_history ' \
|
||||
'WHERE datetime(started, "unixepoch", "localtime") >= datetime("now", "-12 months", "localtime") ' \
|
||||
'GROUP BY strftime("%Y-%m", datetime(started, "unixepoch", "localtime")) ' \
|
||||
'ORDER BY datestring DESC LIMIT 12'
|
||||
|
||||
result = monitor_db.select(query)
|
||||
except Exception as e:
|
||||
logger.warn(u"PlexPy Graphs :: Unable to execute database query for get_total_plays_per_month: %s." % e)
|
||||
return None
|
||||
|
||||
# create our date range as some months may not have any data
|
||||
# but we still want to display them
|
||||
|
@ -348,38 +357,40 @@ class Graphs(object):
|
|||
if not time_range.isdigit():
|
||||
time_range = '30'
|
||||
|
||||
if y_axis == 'plays':
|
||||
query = 'SELECT platform, ' \
|
||||
'SUM(case when media_type = "episode" then 1 else 0 end) as tv_count, ' \
|
||||
'SUM(case when media_type = "movie" then 1 else 0 end) as movie_count, ' \
|
||||
'SUM(case when media_type = "track" then 1 else 0 end) as music_count, ' \
|
||||
'COUNT(id) as total_count ' \
|
||||
'FROM session_history ' \
|
||||
'WHERE (datetime(stopped, "unixepoch", "localtime") >= ' \
|
||||
'datetime("now", "-' + time_range + ' days", "localtime")) ' \
|
||||
'GROUP BY platform ' \
|
||||
'ORDER BY total_count DESC ' \
|
||||
'LIMIT 10'
|
||||
try:
|
||||
if y_axis == 'plays':
|
||||
query = 'SELECT platform, ' \
|
||||
'SUM(CASE WHEN media_type = "episode" THEN 1 ELSE 0 END) AS tv_count, ' \
|
||||
'SUM(CASE WHEN media_type = "movie" THEN 1 ELSE 0 END) AS movie_count, ' \
|
||||
'SUM(CASE WHEN media_type = "track" THEN 1 ELSE 0 END) AS music_count, ' \
|
||||
'COUNT(id) AS total_count ' \
|
||||
'FROM session_history ' \
|
||||
'WHERE (datetime(stopped, "unixepoch", "localtime") >= datetime("now", "-%s days", "localtime")) ' \
|
||||
'GROUP BY platform ' \
|
||||
'ORDER BY total_count DESC ' \
|
||||
'LIMIT 10' % time_range
|
||||
|
||||
result = monitor_db.select(query)
|
||||
else:
|
||||
query = 'SELECT platform, ' \
|
||||
'SUM(case when media_type = "episode" and stopped > 0 then (stopped - started) ' \
|
||||
' - (case when paused_counter is NULL then 0 else paused_counter end) else 0 end) as tv_count, ' \
|
||||
'SUM(case when media_type = "movie" and stopped > 0 then (stopped - started) ' \
|
||||
' - (case when paused_counter is NULL then 0 else paused_counter end) else 0 end) as movie_count, ' \
|
||||
'SUM(case when media_type = "track" and stopped > 0 then (stopped - started) ' \
|
||||
' - (case when paused_counter is NULL then 0 else paused_counter end) else 0 end) as music_count, ' \
|
||||
'SUM(case when stopped > 0 then (stopped - started) ' \
|
||||
' - (case when paused_counter is NULL then 0 else paused_counter end) else 0 end) as total_duration ' \
|
||||
'FROM session_history ' \
|
||||
'WHERE (datetime(stopped, "unixepoch", "localtime") >= ' \
|
||||
'datetime("now", "-' + time_range + ' days", "localtime")) ' \
|
||||
'GROUP BY platform ' \
|
||||
'ORDER BY total_duration DESC ' \
|
||||
'LIMIT 10'
|
||||
result = monitor_db.select(query)
|
||||
else:
|
||||
query = 'SELECT platform, ' \
|
||||
'SUM(CASE WHEN media_type = "episode" AND stopped > 0 THEN (stopped - started) ' \
|
||||
' - (CASE WHEN paused_counter IS NULL THEN 0 ELSE paused_counter END) ELSE 0 END) AS tv_count, ' \
|
||||
'SUM(CASE WHEN media_type = "movie" AND stopped > 0 THEN (stopped - started) ' \
|
||||
' - (CASE WHEN paused_counter IS NULL THEN 0 ELSE paused_counter END) ELSE 0 END) AS movie_count, ' \
|
||||
'SUM(CASE WHEN media_type = "track" AND stopped > 0 THEN (stopped - started) ' \
|
||||
' - (CASE WHEN paused_counter IS NULL THEN 0 ELSE paused_counter END) ELSE 0 END) AS music_count, ' \
|
||||
'SUM(CASE WHEN stopped > 0 THEN (stopped - started) ' \
|
||||
' - (CASE WHEN paused_counter IS NULL THEN 0 ELSE paused_counter END) ELSE 0 END) AS total_duration ' \
|
||||
'FROM session_history ' \
|
||||
'WHERE (datetime(stopped, "unixepoch", "localtime") >= datetime("now", "-%s days", "localtime")) ' \
|
||||
'GROUP BY platform ' \
|
||||
'ORDER BY total_duration DESC ' \
|
||||
'LIMIT 10' % time_range
|
||||
|
||||
result = monitor_db.select(query)
|
||||
result = monitor_db.select(query)
|
||||
except Exception as e:
|
||||
logger.warn(u"PlexPy Graphs :: Unable to execute database query for get_total_plays_by_top_10_platforms: %s." % e)
|
||||
return None
|
||||
|
||||
categories = []
|
||||
series_1 = []
|
||||
|
@ -409,44 +420,44 @@ class Graphs(object):
|
|||
if not time_range.isdigit():
|
||||
time_range = '30'
|
||||
|
||||
if y_axis == 'plays':
|
||||
query = 'SELECT ' \
|
||||
'(case when users.friendly_name is null then users.username else ' \
|
||||
'users.friendly_name end) as friendly_name,' \
|
||||
'SUM(case when media_type = "episode" then 1 else 0 end) as tv_count, ' \
|
||||
'SUM(case when media_type = "movie" then 1 else 0 end) as movie_count, ' \
|
||||
'SUM(case when media_type = "track" then 1 else 0 end) as music_count, ' \
|
||||
'COUNT(session_history.id) as total_count ' \
|
||||
'FROM session_history ' \
|
||||
'JOIN users on session_history.user_id = users.user_id ' \
|
||||
'WHERE (datetime(session_history.stopped, "unixepoch", "localtime") >= ' \
|
||||
'datetime("now", "-' + time_range + ' days", "localtime")) ' \
|
||||
'GROUP BY session_history.user_id ' \
|
||||
'ORDER BY total_count DESC ' \
|
||||
'LIMIT 10'
|
||||
try:
|
||||
if y_axis == 'plays':
|
||||
query = 'SELECT ' \
|
||||
'(CASE WHEN users.friendly_name IS NULL THEN users.username ELSE users.friendly_name END) AS friendly_name,' \
|
||||
'SUM(CASE WHEN media_type = "episode" THEN 1 ELSE 0 END) AS tv_count, ' \
|
||||
'SUM(CASE WHEN media_type = "movie" THEN 1 ELSE 0 END) AS movie_count, ' \
|
||||
'SUM(CASE WHEN media_type = "track" THEN 1 ELSE 0 END) AS music_count, ' \
|
||||
'COUNT(session_history.id) AS total_count ' \
|
||||
'FROM session_history ' \
|
||||
'JOIN users ON session_history.user_id = users.user_id ' \
|
||||
'WHERE (datetime(stopped, "unixepoch", "localtime") >= datetime("now", "-%s days", "localtime")) ' \
|
||||
'GROUP BY session_history.user_id ' \
|
||||
'ORDER BY total_count DESC ' \
|
||||
'LIMIT 10' % time_range
|
||||
|
||||
result = monitor_db.select(query)
|
||||
else:
|
||||
query = 'SELECT ' \
|
||||
'(case when users.friendly_name is null then users.username else ' \
|
||||
'users.friendly_name end) as friendly_name,' \
|
||||
'SUM(case when media_type = "episode" and stopped > 0 then (stopped - started) ' \
|
||||
' - (case when paused_counter is NULL then 0 else paused_counter end) else 0 end) as tv_count, ' \
|
||||
'SUM(case when media_type = "movie" and stopped > 0 then (stopped - started) ' \
|
||||
' - (case when paused_counter is NULL then 0 else paused_counter end) else 0 end) as movie_count, ' \
|
||||
'SUM(case when media_type = "track" and stopped > 0 then (stopped - started) ' \
|
||||
' - (case when paused_counter is NULL then 0 else paused_counter end) else 0 end) as music_count, ' \
|
||||
'SUM(case when stopped > 0 then (stopped - started) ' \
|
||||
' - (case when paused_counter is NULL then 0 else paused_counter end) else 0 end) as total_duration ' \
|
||||
'FROM session_history ' \
|
||||
'JOIN users on session_history.user_id = users.user_id ' \
|
||||
'WHERE (datetime(session_history.stopped, "unixepoch", "localtime") >= ' \
|
||||
'datetime("now", "-' + time_range + ' days", "localtime")) ' \
|
||||
'GROUP BY session_history.user_id ' \
|
||||
'ORDER BY total_duration DESC ' \
|
||||
'LIMIT 10'
|
||||
result = monitor_db.select(query)
|
||||
else:
|
||||
query = 'SELECT ' \
|
||||
'(CASE WHEN users.friendly_name IS NULL THEN users.username ELSE users.friendly_name END) AS friendly_name,' \
|
||||
'SUM(CASE WHEN media_type = "episode" AND stopped > 0 THEN (stopped - started) ' \
|
||||
' - (CASE WHEN paused_counter IS NULL THEN 0 ELSE paused_counter END) ELSE 0 END) AS tv_count, ' \
|
||||
'SUM(CASE WHEN media_type = "movie" AND stopped > 0 THEN (stopped - started) ' \
|
||||
' - (CASE WHEN paused_counter IS NULL THEN 0 ELSE paused_counter END) ELSE 0 END) AS movie_count, ' \
|
||||
'SUM(CASE WHEN media_type = "track" AND stopped > 0 THEN (stopped - started) ' \
|
||||
' - (CASE WHEN paused_counter IS NULL THEN 0 ELSE paused_counter END) ELSE 0 END) AS music_count, ' \
|
||||
'SUM(CASE WHEN stopped > 0 THEN (stopped - started) ' \
|
||||
' - (CASE WHEN paused_counter IS NULL THEN 0 ELSE paused_counter END) ELSE 0 END) AS total_duration ' \
|
||||
'FROM session_history ' \
|
||||
'JOIN users ON session_history.user_id = users.user_id ' \
|
||||
'WHERE (datetime(stopped, "unixepoch", "localtime") >= datetime("now", "-%s days", "localtime")) ' \
|
||||
'GROUP BY session_history.user_id ' \
|
||||
'ORDER BY total_duration DESC ' \
|
||||
'LIMIT 10' % time_range
|
||||
|
||||
result = monitor_db.select(query)
|
||||
result = monitor_db.select(query)
|
||||
except Exception as e:
|
||||
logger.warn(u"PlexPy Graphs :: Unable to execute database query for get_total_plays_by_top_10_users: %s." % e)
|
||||
return None
|
||||
|
||||
categories = []
|
||||
series_1 = []
|
||||
|
@ -478,16 +489,13 @@ class Graphs(object):
|
|||
|
||||
try:
|
||||
if y_axis == 'plays':
|
||||
query = 'SELECT date(session_history.started, "unixepoch", "localtime") as date_played, ' \
|
||||
'SUM(case when (session_history_media_info.video_decision = "direct play" ' \
|
||||
'or session_history_media_info.audio_decision = "direct play") ' \
|
||||
'then 1 else 0 end) as dp_count, ' \
|
||||
'SUM(case when (session_history_media_info.video_decision != "transcode" ' \
|
||||
'and session_history_media_info.audio_decision = "copy") ' \
|
||||
'then 1 else 0 end) as ds_count, ' \
|
||||
'SUM(case when (session_history_media_info.video_decision = "transcode" ' \
|
||||
'or session_history_media_info.audio_decision = "transcode") ' \
|
||||
'then 1 else 0 end) as tc_count ' \
|
||||
query = 'SELECT date(session_history.started, "unixepoch", "localtime") AS date_played, ' \
|
||||
'SUM(CASE WHEN (session_history_media_info.video_decision = "direct play" ' \
|
||||
'OR session_history_media_info.audio_decision = "direct play") THEN 1 ELSE 0 END) AS dp_count, ' \
|
||||
'SUM(CASE WHEN (session_history_media_info.video_decision != "transcode" ' \
|
||||
'AND session_history_media_info.audio_decision = "copy") THEN 1 ELSE 0 END) AS ds_count, ' \
|
||||
'SUM(CASE WHEN (session_history_media_info.video_decision = "transcode" ' \
|
||||
'OR session_history_media_info.audio_decision = "transcode") THEN 1 ELSE 0 END) AS tc_count ' \
|
||||
'FROM session_history ' \
|
||||
'JOIN session_history_media_info ON session_history.id = session_history_media_info.id ' \
|
||||
'WHERE (datetime(session_history.stopped, "unixepoch", "localtime") >= ' \
|
||||
|
@ -498,19 +506,19 @@ class Graphs(object):
|
|||
|
||||
result = monitor_db.select(query)
|
||||
else:
|
||||
query = 'SELECT date(session_history.started, "unixepoch", "localtime") as date_played, ' \
|
||||
'SUM(case when (session_history_media_info.video_decision = "direct play" ' \
|
||||
'or session_history_media_info.audio_decision = "direct play") ' \
|
||||
'and session_history.stopped > 0 then (session_history.stopped - session_history.started) ' \
|
||||
' - (case when paused_counter is NULL then 0 else paused_counter end) else 0 end) as dp_count, ' \
|
||||
'SUM(case when (session_history_media_info.video_decision != "transcode" ' \
|
||||
'and session_history_media_info.audio_decision = "copy") ' \
|
||||
'and session_history.stopped > 0 then (session_history.stopped - session_history.started) ' \
|
||||
' - (case when paused_counter is NULL then 0 else paused_counter end) else 0 end) as ds_count, ' \
|
||||
'SUM(case when (session_history_media_info.video_decision = "transcode" ' \
|
||||
'or session_history_media_info.audio_decision = "transcode") ' \
|
||||
'and session_history.stopped > 0 then (session_history.stopped - session_history.started) ' \
|
||||
' - (case when paused_counter is NULL then 0 else paused_counter end) else 0 end) as tc_count ' \
|
||||
query = 'SELECT date(session_history.started, "unixepoch", "localtime") AS date_played, ' \
|
||||
'SUM(CASE WHEN (session_history_media_info.video_decision = "direct play" ' \
|
||||
'OR session_history_media_info.audio_decision = "direct play") ' \
|
||||
'AND session_history.stopped > 0 THEN (session_history.stopped - session_history.started) ' \
|
||||
' - (CASE WHEN paused_counter IS NULL THEN 0 ELSE paused_counter END) ELSE 0 END) AS dp_count, ' \
|
||||
'SUM(CASE WHEN (session_history_media_info.video_decision != "transcode" ' \
|
||||
'AND session_history_media_info.audio_decision = "copy") ' \
|
||||
'AND session_history.stopped > 0 THEN (session_history.stopped - session_history.started) ' \
|
||||
' - (CASE WHEN paused_counter IS NULL THEN 0 ELSE paused_counter END) ELSE 0 END) AS ds_count, ' \
|
||||
'SUM(CASE WHEN (session_history_media_info.video_decision = "transcode" ' \
|
||||
'OR session_history_media_info.audio_decision = "transcode") ' \
|
||||
'AND session_history.stopped > 0 THEN (session_history.stopped - session_history.started) ' \
|
||||
' - (CASE WHEN paused_counter IS NULL THEN 0 ELSE paused_counter END) ELSE 0 END) AS tc_count ' \
|
||||
'FROM session_history ' \
|
||||
'JOIN session_history_media_info ON session_history.id = session_history_media_info.id ' \
|
||||
'WHERE datetime(session_history.stopped, "unixepoch", "localtime") >= ' \
|
||||
|
@ -520,8 +528,8 @@ class Graphs(object):
|
|||
'ORDER BY started ASC' % time_range
|
||||
|
||||
result = monitor_db.select(query)
|
||||
except:
|
||||
logger.warn("Unable to execute database query.")
|
||||
except Exception as e:
|
||||
logger.warn(u"PlexPy Graphs :: Unable to execute database query for get_total_plays_per_stream_type: %s." % e)
|
||||
return None
|
||||
|
||||
# create our date range as some days may not have any data
|
||||
|
@ -572,54 +580,55 @@ class Graphs(object):
|
|||
if not time_range.isdigit():
|
||||
time_range = '30'
|
||||
|
||||
if y_axis == 'plays':
|
||||
query = 'SELECT session_history_media_info.video_resolution AS resolution, ' \
|
||||
'SUM(case when (session_history_media_info.video_decision = "direct play" ' \
|
||||
'or session_history_media_info.audio_decision = "direct play") ' \
|
||||
'then 1 else 0 end) as dp_count, ' \
|
||||
'SUM(case when (session_history_media_info.video_decision != "transcode" ' \
|
||||
'and session_history_media_info.audio_decision = "copy") ' \
|
||||
'then 1 else 0 end) as ds_count, ' \
|
||||
'SUM(case when (session_history_media_info.video_decision = "transcode" ' \
|
||||
'or session_history_media_info.audio_decision = "transcode") ' \
|
||||
'then 1 else 0 end) as tc_count, ' \
|
||||
'COUNT(session_history.id) as total_count ' \
|
||||
'FROM session_history ' \
|
||||
'JOIN session_history_media_info on session_history.id = session_history_media_info.id ' \
|
||||
'WHERE (datetime(session_history.stopped, "unixepoch", "localtime") >= ' \
|
||||
'datetime("now", "-' + time_range + ' days", "localtime")) AND ' \
|
||||
'(session_history.media_type = "episode" OR session_history.media_type = "movie") ' \
|
||||
'GROUP BY resolution ' \
|
||||
'ORDER BY total_count DESC ' \
|
||||
'LIMIT 10'
|
||||
try:
|
||||
if y_axis == 'plays':
|
||||
query = 'SELECT session_history_media_info.video_resolution AS resolution, ' \
|
||||
'SUM(CASE WHEN (session_history_media_info.video_decision = "direct play" ' \
|
||||
'OR session_history_media_info.audio_decision = "direct play") THEN 1 ELSE 0 END) AS dp_count, ' \
|
||||
'SUM(CASE WHEN (session_history_media_info.video_decision != "transcode" ' \
|
||||
'AND session_history_media_info.audio_decision = "copy") THEN 1 ELSE 0 END) AS ds_count, ' \
|
||||
'SUM(CASE WHEN (session_history_media_info.video_decision = "transcode" ' \
|
||||
'OR session_history_media_info.audio_decision = "transcode") THEN 1 ELSE 0 END) AS tc_count, ' \
|
||||
'COUNT(session_history.id) AS total_count ' \
|
||||
'FROM session_history ' \
|
||||
'JOIN session_history_media_info ON session_history.id = session_history_media_info.id ' \
|
||||
'WHERE (datetime(session_history.stopped, "unixepoch", "localtime") >= ' \
|
||||
'datetime("now", "-%s days", "localtime")) AND ' \
|
||||
'(session_history.media_type = "episode" OR session_history.media_type = "movie") ' \
|
||||
'GROUP BY resolution ' \
|
||||
'ORDER BY total_count DESC ' \
|
||||
'LIMIT 10' % time_range
|
||||
|
||||
result = monitor_db.select(query)
|
||||
else:
|
||||
query = 'SELECT session_history_media_info.video_resolution AS resolution,' \
|
||||
'SUM(case when (session_history_media_info.video_decision = "direct play" ' \
|
||||
'or session_history_media_info.audio_decision = "direct play") ' \
|
||||
'and session_history.stopped > 0 then (session_history.stopped - session_history.started) ' \
|
||||
' - (case when paused_counter is NULL then 0 else paused_counter end) else 0 end) as dp_count, ' \
|
||||
'SUM(case when (session_history_media_info.video_decision != "transcode" ' \
|
||||
'and session_history_media_info.audio_decision = "copy") ' \
|
||||
'and session_history.stopped > 0 then (session_history.stopped - session_history.started) ' \
|
||||
' - (case when paused_counter is NULL then 0 else paused_counter end) else 0 end) as ds_count, ' \
|
||||
'SUM(case when (session_history_media_info.video_decision = "transcode" ' \
|
||||
'or session_history_media_info.audio_decision = "transcode") ' \
|
||||
'and session_history.stopped > 0 then (session_history.stopped - session_history.started) ' \
|
||||
' - (case when paused_counter is NULL then 0 else paused_counter end) else 0 end) as tc_count, ' \
|
||||
'SUM(case when stopped > 0 then (stopped - started) ' \
|
||||
' - (case when paused_counter is NULL then 0 else paused_counter end) else 0 end) as total_duration ' \
|
||||
'FROM session_history ' \
|
||||
'JOIN session_history_media_info on session_history.id = session_history_media_info.id ' \
|
||||
'WHERE (datetime(session_history.stopped, "unixepoch", "localtime") >= ' \
|
||||
'datetime("now", "-' + time_range + ' days", "localtime")) AND ' \
|
||||
'(session_history.media_type = "episode" OR session_history.media_type = "movie") ' \
|
||||
'GROUP BY resolution ' \
|
||||
'ORDER BY total_duration DESC ' \
|
||||
'LIMIT 10'
|
||||
result = monitor_db.select(query)
|
||||
else:
|
||||
query = 'SELECT session_history_media_info.video_resolution AS resolution,' \
|
||||
'SUM(CASE WHEN (session_history_media_info.video_decision = "direct play" ' \
|
||||
'OR session_history_media_info.audio_decision = "direct play") ' \
|
||||
'AND session_history.stopped > 0 THEN (session_history.stopped - session_history.started) ' \
|
||||
' - (CASE WHEN paused_counter IS NULL THEN 0 ELSE paused_counter END) ELSE 0 END) AS dp_count, ' \
|
||||
'SUM(CASE WHEN (session_history_media_info.video_decision != "transcode" ' \
|
||||
'AND session_history_media_info.audio_decision = "copy") ' \
|
||||
'AND session_history.stopped > 0 THEN (session_history.stopped - session_history.started) ' \
|
||||
' - (CASE WHEN paused_counter IS NULL THEN 0 ELSE paused_counter END) ELSE 0 END) AS ds_count, ' \
|
||||
'SUM(CASE WHEN (session_history_media_info.video_decision = "transcode" ' \
|
||||
'OR session_history_media_info.audio_decision = "transcode") ' \
|
||||
'AND session_history.stopped > 0 THEN (session_history.stopped - session_history.started) ' \
|
||||
' - (CASE WHEN paused_counter IS NULL THEN 0 ELSE paused_counter END) ELSE 0 END) AS tc_count, ' \
|
||||
'SUM(CASE WHEN stopped > 0 THEN (stopped - started) ' \
|
||||
' - (CASE WHEN paused_counter IS NULL THEN 0 ELSE paused_counter END) ELSE 0 END) AS total_duration ' \
|
||||
'FROM session_history ' \
|
||||
'JOIN session_history_media_info ON session_history.id = session_history_media_info.id ' \
|
||||
'WHERE (datetime(session_history.stopped, "unixepoch", "localtime") >= ' \
|
||||
'datetime("now", "-%s days", "localtime")) AND ' \
|
||||
'(session_history.media_type = "episode" OR session_history.media_type = "movie") ' \
|
||||
'GROUP BY resolution ' \
|
||||
'ORDER BY total_duration DESC ' \
|
||||
'LIMIT 10' % time_range
|
||||
|
||||
result = monitor_db.select(query)
|
||||
result = monitor_db.select(query)
|
||||
except Exception as e:
|
||||
logger.warn(u"PlexPy Graphs :: Unable to execute database query for get_total_plays_by_source_resolution: %s." % e)
|
||||
return None
|
||||
|
||||
categories = []
|
||||
series_1 = []
|
||||
|
@ -649,74 +658,75 @@ class Graphs(object):
|
|||
if not time_range.isdigit():
|
||||
time_range = '30'
|
||||
|
||||
if y_axis == 'plays':
|
||||
query = 'SELECT ' \
|
||||
'(case when session_history_media_info.video_decision = "transcode" then ' \
|
||||
'(case ' \
|
||||
'when session_history_media_info.transcode_height <= 360 then "sd" ' \
|
||||
'when session_history_media_info.transcode_height <= 480 then "480" ' \
|
||||
'when session_history_media_info.transcode_height <= 576 then "576" ' \
|
||||
'when session_history_media_info.transcode_height <= 720 then "720" ' \
|
||||
'when session_history_media_info.transcode_height <= 1080 then "1080" ' \
|
||||
'when session_history_media_info.transcode_height <= 1440 then "QHD" ' \
|
||||
'when session_history_media_info.transcode_height <= 2160 then "4K" ' \
|
||||
'else "unknown" end) else session_history_media_info.video_resolution end) as resolution, ' \
|
||||
'SUM(case when (session_history_media_info.video_decision = "direct play" ' \
|
||||
'or session_history_media_info.audio_decision = "direct play") ' \
|
||||
'then 1 else 0 end) as dp_count, ' \
|
||||
'SUM(case when (session_history_media_info.video_decision != "transcode" ' \
|
||||
'and session_history_media_info.audio_decision = "copy") ' \
|
||||
'then 1 else 0 end) as ds_count, ' \
|
||||
'SUM(case when (session_history_media_info.video_decision = "transcode" '\
|
||||
'or session_history_media_info.audio_decision = "transcode") ' \
|
||||
'then 1 else 0 end) as tc_count, ' \
|
||||
'COUNT(session_history.id) as total_count ' \
|
||||
'FROM session_history ' \
|
||||
'JOIN session_history_media_info on session_history.id = session_history_media_info.id ' \
|
||||
'WHERE (datetime(session_history.stopped, "unixepoch", "localtime") >= ' \
|
||||
'datetime("now", "-' + time_range + ' days", "localtime")) AND ' \
|
||||
'(session_history.media_type = "episode" OR session_history.media_type = "movie") ' \
|
||||
'GROUP BY resolution ' \
|
||||
'ORDER BY total_count DESC ' \
|
||||
'LIMIT 10'
|
||||
try:
|
||||
if y_axis == 'plays':
|
||||
query = 'SELECT ' \
|
||||
'(CASE WHEN session_history_media_info.video_decision = "transcode" THEN ' \
|
||||
'(CASE ' \
|
||||
'WHEN session_history_media_info.transcode_height <= 360 THEN "sd" ' \
|
||||
'WHEN session_history_media_info.transcode_height <= 480 THEN "480" ' \
|
||||
'WHEN session_history_media_info.transcode_height <= 576 THEN "576" ' \
|
||||
'WHEN session_history_media_info.transcode_height <= 720 THEN "720" ' \
|
||||
'WHEN session_history_media_info.transcode_height <= 1080 THEN "1080" ' \
|
||||
'WHEN session_history_media_info.transcode_height <= 1440 THEN "QHD" ' \
|
||||
'WHEN session_history_media_info.transcode_height <= 2160 THEN "4K" ' \
|
||||
'ELSE "unknown" END) ELSE session_history_media_info.video_resolution END) AS resolution, ' \
|
||||
'SUM(CASE WHEN (session_history_media_info.video_decision = "direct play" ' \
|
||||
'OR session_history_media_info.audio_decision = "direct play") THEN 1 ELSE 0 END) AS dp_count, ' \
|
||||
'SUM(CASE WHEN (session_history_media_info.video_decision != "transcode" ' \
|
||||
'AND session_history_media_info.audio_decision = "copy") THEN 1 ELSE 0 END) AS ds_count, ' \
|
||||
'SUM(CASE WHEN (session_history_media_info.video_decision = "transcode" '\
|
||||
'OR session_history_media_info.audio_decision = "transcode") THEN 1 ELSE 0 END) AS tc_count, ' \
|
||||
'COUNT(session_history.id) AS total_count ' \
|
||||
'FROM session_history ' \
|
||||
'JOIN session_history_media_info ON session_history.id = session_history_media_info.id ' \
|
||||
'WHERE (datetime(session_history.stopped, "unixepoch", "localtime") >= ' \
|
||||
'datetime("now", "-%s days", "localtime")) AND ' \
|
||||
'(session_history.media_type = "episode" OR session_history.media_type = "movie") ' \
|
||||
'GROUP BY resolution ' \
|
||||
'ORDER BY total_count DESC ' \
|
||||
'LIMIT 10' % time_range
|
||||
|
||||
result = monitor_db.select(query)
|
||||
else:
|
||||
query = 'SELECT ' \
|
||||
'(case when session_history_media_info.video_decision = "transcode" then ' \
|
||||
'(case ' \
|
||||
'when session_history_media_info.transcode_height <= 360 then "sd" ' \
|
||||
'when session_history_media_info.transcode_height <= 480 then "480" ' \
|
||||
'when session_history_media_info.transcode_height <= 576 then "576" ' \
|
||||
'when session_history_media_info.transcode_height <= 720 then "720" ' \
|
||||
'when session_history_media_info.transcode_height <= 1080 then "1080" ' \
|
||||
'when session_history_media_info.transcode_height <= 1440 then "QHD" ' \
|
||||
'when session_history_media_info.transcode_height <= 2160 then "4K" ' \
|
||||
'else "unknown" end) else session_history_media_info.video_resolution end) as resolution, ' \
|
||||
'SUM(case when (session_history_media_info.video_decision = "direct play" ' \
|
||||
'or session_history_media_info.audio_decision = "direct play") ' \
|
||||
'and session_history.stopped > 0 then (session_history.stopped - session_history.started) ' \
|
||||
' - (case when paused_counter is NULL then 0 else paused_counter end) else 0 end) as dp_count, ' \
|
||||
'SUM(case when (session_history_media_info.video_decision != "transcode" ' \
|
||||
'and session_history_media_info.audio_decision = "copy") ' \
|
||||
'and session_history.stopped > 0 then (session_history.stopped - session_history.started) ' \
|
||||
' - (case when paused_counter is NULL then 0 else paused_counter end) else 0 end) as ds_count, ' \
|
||||
'SUM(case when (session_history_media_info.video_decision = "transcode" ' \
|
||||
'or session_history_media_info.audio_decision = "transcode") ' \
|
||||
'and session_history.stopped > 0 then (session_history.stopped - session_history.started) ' \
|
||||
' - (case when paused_counter is NULL then 0 else paused_counter end) else 0 end) as tc_count, ' \
|
||||
'SUM(case when stopped > 0 then (stopped - started) ' \
|
||||
' - (case when paused_counter is NULL then 0 else paused_counter end) else 0 end) as total_duration ' \
|
||||
'FROM session_history ' \
|
||||
'JOIN session_history_media_info on session_history.id = session_history_media_info.id ' \
|
||||
'WHERE (datetime(session_history.stopped, "unixepoch", "localtime") >= ' \
|
||||
'datetime("now", "-' + time_range + ' days", "localtime")) AND ' \
|
||||
'(session_history.media_type = "episode" OR session_history.media_type = "movie") ' \
|
||||
'GROUP BY resolution ' \
|
||||
'ORDER BY total_duration DESC ' \
|
||||
'LIMIT 10'
|
||||
result = monitor_db.select(query)
|
||||
else:
|
||||
query = 'SELECT ' \
|
||||
'(CASE WHEN session_history_media_info.video_decision = "transcode" THEN ' \
|
||||
'(CASE ' \
|
||||
'WHEN session_history_media_info.transcode_height <= 360 THEN "sd" ' \
|
||||
'WHEN session_history_media_info.transcode_height <= 480 THEN "480" ' \
|
||||
'WHEN session_history_media_info.transcode_height <= 576 THEN "576" ' \
|
||||
'WHEN session_history_media_info.transcode_height <= 720 THEN "720" ' \
|
||||
'WHEN session_history_media_info.transcode_height <= 1080 THEN "1080" ' \
|
||||
'WHEN session_history_media_info.transcode_height <= 1440 THEN "QHD" ' \
|
||||
'WHEN session_history_media_info.transcode_height <= 2160 THEN "4K" ' \
|
||||
'ELSE "unknown" END) ELSE session_history_media_info.video_resolution END) AS resolution, ' \
|
||||
'SUM(CASE WHEN (session_history_media_info.video_decision = "direct play" ' \
|
||||
'OR session_history_media_info.audio_decision = "direct play") ' \
|
||||
'AND session_history.stopped > 0 THEN (session_history.stopped - session_history.started) ' \
|
||||
' - (CASE WHEN paused_counter IS NULL THEN 0 ELSE paused_counter END) ELSE 0 END) AS dp_count, ' \
|
||||
'SUM(CASE WHEN (session_history_media_info.video_decision != "transcode" ' \
|
||||
'AND session_history_media_info.audio_decision = "copy") ' \
|
||||
'AND session_history.stopped > 0 THEN (session_history.stopped - session_history.started) ' \
|
||||
' - (CASE WHEN paused_counter IS NULL THEN 0 ELSE paused_counter END) ELSE 0 END) AS ds_count, ' \
|
||||
'SUM(CASE WHEN (session_history_media_info.video_decision = "transcode" ' \
|
||||
'OR session_history_media_info.audio_decision = "transcode") ' \
|
||||
'AND session_history.stopped > 0 THEN (session_history.stopped - session_history.started) ' \
|
||||
' - (CASE WHEN paused_counter IS NULL THEN 0 ELSE paused_counter END) ELSE 0 END) AS tc_count, ' \
|
||||
'SUM(CASE WHEN stopped > 0 THEN (stopped - started) ' \
|
||||
' - (CASE WHEN paused_counter IS NULL THEN 0 ELSE paused_counter END) ELSE 0 END) AS total_duration ' \
|
||||
'FROM session_history ' \
|
||||
'JOIN session_history_media_info ON session_history.id = session_history_media_info.id ' \
|
||||
'WHERE (datetime(session_history.stopped, "unixepoch", "localtime") >= ' \
|
||||
'datetime("now", "-%s days", "localtime")) AND ' \
|
||||
'(session_history.media_type = "episode" OR session_history.media_type = "movie") ' \
|
||||
'GROUP BY resolution ' \
|
||||
'ORDER BY total_duration DESC ' \
|
||||
'LIMIT 10' % time_range
|
||||
|
||||
result = monitor_db.select(query)
|
||||
result = monitor_db.select(query)
|
||||
except Exception as e:
|
||||
logger.warn(u"PlexPy Graphs :: Unable to execute database query for get_total_plays_by_stream_resolution: %s." % e)
|
||||
return None
|
||||
|
||||
categories = []
|
||||
series_1 = []
|
||||
|
@ -746,55 +756,54 @@ class Graphs(object):
|
|||
if not time_range.isdigit():
|
||||
time_range = '30'
|
||||
|
||||
if y_axis == 'plays':
|
||||
query = 'SELECT ' \
|
||||
'session_history.platform as platform, ' \
|
||||
'SUM(case when (session_history_media_info.video_decision = "direct play" ' \
|
||||
'or session_history_media_info.audio_decision = "direct play") ' \
|
||||
'then 1 else 0 end) as dp_count, ' \
|
||||
'SUM(case when (session_history_media_info.video_decision != "transcode" ' \
|
||||
'and session_history_media_info.audio_decision = "copy") ' \
|
||||
'then 1 else 0 end) as ds_count, ' \
|
||||
'SUM(case when (session_history_media_info.video_decision = "transcode" ' \
|
||||
'or session_history_media_info.audio_decision = "transcode") ' \
|
||||
'then 1 else 0 end) as tc_count, ' \
|
||||
'COUNT(session_history.id) as total_count ' \
|
||||
'FROM session_history ' \
|
||||
'JOIN session_history_media_info ON session_history.id = session_history_media_info.id ' \
|
||||
'WHERE datetime(session_history.started, "unixepoch", "localtime") >= ' \
|
||||
'datetime("now", "-' + time_range + ' days", "localtime") AND ' \
|
||||
'(session_history.media_type = "episode" OR session_history.media_type = "movie" OR session_history.media_type = "track") ' \
|
||||
'GROUP BY platform ' \
|
||||
'ORDER BY total_count DESC LIMIT 10'
|
||||
try:
|
||||
if y_axis == 'plays':
|
||||
query = 'SELECT session_history.platform AS platform, ' \
|
||||
'SUM(CASE WHEN (session_history_media_info.video_decision = "direct play" ' \
|
||||
'OR session_history_media_info.audio_decision = "direct play") THEN 1 ELSE 0 END) AS dp_count, ' \
|
||||
'SUM(CASE WHEN (session_history_media_info.video_decision != "transcode" ' \
|
||||
'AND session_history_media_info.audio_decision = "copy") THEN 1 ELSE 0 END) AS ds_count, ' \
|
||||
'SUM(CASE WHEN (session_history_media_info.video_decision = "transcode" ' \
|
||||
'OR session_history_media_info.audio_decision = "transcode") THEN 1 ELSE 0 END) AS tc_count, ' \
|
||||
'COUNT(session_history.id) AS total_count ' \
|
||||
'FROM session_history ' \
|
||||
'JOIN session_history_media_info ON session_history.id = session_history_media_info.id ' \
|
||||
'WHERE datetime(session_history.started, "unixepoch", "localtime") >= ' \
|
||||
'datetime("now", "-%s days", "localtime") AND ' \
|
||||
'(session_history.media_type = "episode" OR session_history.media_type = "movie" OR session_history.media_type = "track") ' \
|
||||
'GROUP BY platform ' \
|
||||
'ORDER BY total_count DESC LIMIT 10' % time_range
|
||||
|
||||
result = monitor_db.select(query)
|
||||
else:
|
||||
query = 'SELECT ' \
|
||||
'session_history.platform as platform, ' \
|
||||
'SUM(case when (session_history_media_info.video_decision = "direct play" ' \
|
||||
'or session_history_media_info.audio_decision = "direct play") ' \
|
||||
'and session_history.stopped > 0 then (session_history.stopped - session_history.started) ' \
|
||||
' - (case when paused_counter is NULL then 0 else paused_counter end) else 0 end) as dp_count, ' \
|
||||
'SUM(case when (session_history_media_info.video_decision != "transcode" ' \
|
||||
'and session_history_media_info.audio_decision = "copy") ' \
|
||||
'and session_history.stopped > 0 then (session_history.stopped - session_history.started) ' \
|
||||
' - (case when paused_counter is NULL then 0 else paused_counter end) else 0 end) as ds_count, ' \
|
||||
'SUM(case when (session_history_media_info.video_decision = "transcode" ' \
|
||||
'and session_history_media_info.audio_decision = "transcode") ' \
|
||||
'and session_history.stopped > 0 then (session_history.stopped - session_history.started) ' \
|
||||
' - (case when paused_counter is NULL then 0 else paused_counter end) else 0 end) as tc_count, ' \
|
||||
'SUM(case when session_history.stopped > 0 ' \
|
||||
'then (session_history.stopped - session_history.started) ' \
|
||||
' - (case when paused_counter is NULL then 0 else paused_counter end) else 0 end) as total_duration ' \
|
||||
'FROM session_history ' \
|
||||
'JOIN session_history_media_info ON session_history.id = session_history_media_info.id ' \
|
||||
'WHERE datetime(session_history.started, "unixepoch", "localtime") >= ' \
|
||||
'datetime("now", "-' + time_range + ' days", "localtime") AND ' \
|
||||
'(session_history.media_type = "episode" OR session_history.media_type = "movie" OR session_history.media_type = "track") ' \
|
||||
'GROUP BY platform ' \
|
||||
'ORDER BY total_duration DESC LIMIT 10'
|
||||
result = monitor_db.select(query)
|
||||
else:
|
||||
query = 'SELECT session_history.platform AS platform, ' \
|
||||
'SUM(CASE WHEN (session_history_media_info.video_decision = "direct play" ' \
|
||||
'OR session_history_media_info.audio_decision = "direct play") ' \
|
||||
'AND session_history.stopped > 0 THEN (session_history.stopped - session_history.started) ' \
|
||||
' - (CASE WHEN paused_counter IS NULL THEN 0 ELSE paused_counter END) ELSE 0 END) AS dp_count, ' \
|
||||
'SUM(CASE WHEN (session_history_media_info.video_decision != "transcode" ' \
|
||||
'AND session_history_media_info.audio_decision = "copy") ' \
|
||||
'AND session_history.stopped > 0 THEN (session_history.stopped - session_history.started) ' \
|
||||
' - (CASE WHEN paused_counter IS NULL THEN 0 ELSE paused_counter END) ELSE 0 END) AS ds_count, ' \
|
||||
'SUM(CASE WHEN (session_history_media_info.video_decision = "transcode" ' \
|
||||
'AND session_history_media_info.audio_decision = "transcode") ' \
|
||||
'AND session_history.stopped > 0 THEN (session_history.stopped - session_history.started) ' \
|
||||
' - (CASE WHEN paused_counter IS NULL THEN 0 ELSE paused_counter END) ELSE 0 END) AS tc_count, ' \
|
||||
'SUM(CASE WHEN session_history.stopped > 0 ' \
|
||||
'THEN (session_history.stopped - session_history.started) ' \
|
||||
' - (CASE WHEN paused_counter IS NULL THEN 0 ELSE paused_counter END) ELSE 0 END) AS total_duration ' \
|
||||
'FROM session_history ' \
|
||||
'JOIN session_history_media_info ON session_history.id = session_history_media_info.id ' \
|
||||
'WHERE datetime(session_history.started, "unixepoch", "localtime") >= ' \
|
||||
'datetime("now", "-%s days", "localtime") AND ' \
|
||||
'(session_history.media_type = "episode" OR session_history.media_type = "movie" OR session_history.media_type = "track") ' \
|
||||
'GROUP BY platform ' \
|
||||
'ORDER BY total_duration DESC LIMIT 10' % time_range
|
||||
|
||||
result = monitor_db.select(query)
|
||||
result = monitor_db.select(query)
|
||||
except Exception as e:
|
||||
logger.warn(u"PlexPy Graphs :: Unable to execute database query for get_stream_type_by_top_10_platforms: %s." % e)
|
||||
return None
|
||||
|
||||
categories = []
|
||||
series_1 = []
|
||||
|
@ -825,57 +834,58 @@ class Graphs(object):
|
|||
if not time_range.isdigit():
|
||||
time_range = '30'
|
||||
|
||||
if y_axis == 'plays':
|
||||
query = 'SELECT ' \
|
||||
'CASE WHEN users.friendly_name is null then users.username else users.friendly_name end as username, ' \
|
||||
'SUM(case when (session_history_media_info.video_decision = "direct play" ' \
|
||||
'or session_history_media_info.audio_decision = "direct play") ' \
|
||||
'then 1 else 0 end) as dp_count, ' \
|
||||
'SUM(case when (session_history_media_info.video_decision != "transcode" ' \
|
||||
'and session_history_media_info.audio_decision = "copy") ' \
|
||||
'then 1 else 0 end) as ds_count, ' \
|
||||
'SUM(case when (session_history_media_info.video_decision = "transcode" ' \
|
||||
'or session_history_media_info.audio_decision = "transcode") ' \
|
||||
'then 1 else 0 end) as tc_count, ' \
|
||||
'COUNT(session_history.id) as total_count ' \
|
||||
'FROM session_history ' \
|
||||
'JOIN users ON session_history.user_id = users.user_id ' \
|
||||
'JOIN session_history_media_info ON session_history.id = session_history_media_info.id ' \
|
||||
'WHERE datetime(session_history.started, "unixepoch", "localtime") >= ' \
|
||||
'datetime("now", "-' + time_range + ' days", "localtime") AND ' \
|
||||
'(session_history.media_type = "episode" OR session_history.media_type = "movie" OR session_history.media_type = "track") ' \
|
||||
'GROUP BY username ' \
|
||||
'ORDER BY total_count DESC LIMIT 10'
|
||||
try:
|
||||
if y_axis == 'plays':
|
||||
query = 'SELECT ' \
|
||||
'(CASE WHEN users.friendly_name IS NULL THEN users.username ELSE users.friendly_name END) AS username, ' \
|
||||
'SUM(CASE WHEN (session_history_media_info.video_decision = "direct play" ' \
|
||||
'OR session_history_media_info.audio_decision = "direct play") THEN 1 ELSE 0 END) AS dp_count, ' \
|
||||
'SUM(CASE WHEN (session_history_media_info.video_decision != "transcode" ' \
|
||||
'AND session_history_media_info.audio_decision = "copy") THEN 1 ELSE 0 END) AS ds_count, ' \
|
||||
'SUM(CASE WHEN (session_history_media_info.video_decision = "transcode" ' \
|
||||
'OR session_history_media_info.audio_decision = "transcode") THEN 1 ELSE 0 END) AS tc_count, ' \
|
||||
'COUNT(session_history.id) AS total_count ' \
|
||||
'FROM session_history ' \
|
||||
'JOIN users ON session_history.user_id = users.user_id ' \
|
||||
'JOIN session_history_media_info ON session_history.id = session_history_media_info.id ' \
|
||||
'WHERE datetime(session_history.started, "unixepoch", "localtime") >= ' \
|
||||
'datetime("now", "-%s days", "localtime") AND ' \
|
||||
'(session_history.media_type = "episode" OR session_history.media_type = "movie" OR session_history.media_type = "track") ' \
|
||||
'GROUP BY username ' \
|
||||
'ORDER BY total_count DESC LIMIT 10' % time_range
|
||||
|
||||
result = monitor_db.select(query)
|
||||
else:
|
||||
query = 'SELECT ' \
|
||||
'CASE WHEN users.friendly_name is null then users.username else users.friendly_name end as username, ' \
|
||||
'SUM(case when (session_history_media_info.video_decision = "direct play" ' \
|
||||
'or session_history_media_info.audio_decision = "direct play") ' \
|
||||
'and session_history.stopped > 0 then (session_history.stopped - session_history.started) ' \
|
||||
' - (case when paused_counter is NULL then 0 else paused_counter end) else 0 end) as dp_count, ' \
|
||||
'SUM(case when (session_history_media_info.video_decision != "transcode" ' \
|
||||
'and session_history_media_info.audio_decision = "copy") ' \
|
||||
'and session_history.stopped > 0 then (session_history.stopped - session_history.started) ' \
|
||||
' - (case when paused_counter is NULL then 0 else paused_counter end) else 0 end) as ds_count, ' \
|
||||
'SUM(case when (session_history_media_info.video_decision = "transcode" ' \
|
||||
'and session_history_media_info.audio_decision = "transcode") ' \
|
||||
'and session_history.stopped > 0 then (session_history.stopped - session_history.started) ' \
|
||||
' - (case when paused_counter is NULL then 0 else paused_counter end) else 0 end) as tc_count, ' \
|
||||
'SUM(case when session_history.stopped > 0 ' \
|
||||
'then (session_history.stopped - session_history.started) ' \
|
||||
' - (case when paused_counter is NULL then 0 else paused_counter end) else 0 end) as total_duration ' \
|
||||
'FROM session_history ' \
|
||||
'JOIN users ON session_history.user_id = users.user_id ' \
|
||||
'JOIN session_history_media_info ON session_history.id = session_history_media_info.id ' \
|
||||
'WHERE datetime(session_history.started, "unixepoch", "localtime") >= ' \
|
||||
'datetime("now", "-' + time_range + ' days", "localtime") AND ' \
|
||||
'(session_history.media_type = "episode" OR session_history.media_type = "movie" OR session_history.media_type = "track") ' \
|
||||
'GROUP BY username ' \
|
||||
'ORDER BY total_duration DESC LIMIT 10'
|
||||
result = monitor_db.select(query)
|
||||
else:
|
||||
query = 'SELECT ' \
|
||||
'(CASE WHEN users.friendly_name IS NULL THEN users.username ELSE users.friendly_name END) AS username, ' \
|
||||
'SUM(CASE WHEN (session_history_media_info.video_decision = "direct play" ' \
|
||||
'OR session_history_media_info.audio_decision = "direct play") ' \
|
||||
'AND session_history.stopped > 0 THEN (session_history.stopped - session_history.started) ' \
|
||||
' - (CASE WHEN paused_counter IS NULL THEN 0 ELSE paused_counter END) ELSE 0 END) AS dp_count, ' \
|
||||
'SUM(CASE WHEN (session_history_media_info.video_decision != "transcode" ' \
|
||||
'AND session_history_media_info.audio_decision = "copy") ' \
|
||||
'AND session_history.stopped > 0 THEN (session_history.stopped - session_history.started) ' \
|
||||
' - (CASE WHEN paused_counter IS NULL THEN 0 ELSE paused_counter END) ELSE 0 END) AS ds_count, ' \
|
||||
'SUM(CASE WHEN (session_history_media_info.video_decision = "transcode" ' \
|
||||
'AND session_history_media_info.audio_decision = "transcode") ' \
|
||||
'AND session_history.stopped > 0 THEN (session_history.stopped - session_history.started) ' \
|
||||
' - (CASE WHEN paused_counter IS NULL THEN 0 ELSE paused_counter END) ELSE 0 END) AS tc_count, ' \
|
||||
'SUM(CASE WHEN session_history.stopped > 0 ' \
|
||||
'THEN (session_history.stopped - session_history.started) ' \
|
||||
' - (CASE WHEN paused_counter IS NULL THEN 0 ELSE paused_counter END) ELSE 0 END) AS total_duration ' \
|
||||
'FROM session_history ' \
|
||||
'JOIN users ON session_history.user_id = users.user_id ' \
|
||||
'JOIN session_history_media_info ON session_history.id = session_history_media_info.id ' \
|
||||
'WHERE datetime(session_history.started, "unixepoch", "localtime") >= ' \
|
||||
'datetime("now", "-%s days", "localtime") AND ' \
|
||||
'(session_history.media_type = "episode" OR session_history.media_type = "movie" OR session_history.media_type = "track") ' \
|
||||
'GROUP BY username ' \
|
||||
'ORDER BY total_duration DESC LIMIT 10' % time_range
|
||||
|
||||
result = monitor_db.select(query)
|
||||
result = monitor_db.select(query)
|
||||
except Exception as e:
|
||||
logger.warn(u"PlexPy Graphs :: Unable to execute database query for get_stream_type_by_top_10_users: %s." % e)
|
||||
return None
|
||||
|
||||
categories = []
|
||||
series_1 = []
|
||||
|
|
|
@ -150,7 +150,7 @@ def human_duration(s, sig='dhms'):
|
|||
|
||||
hd = ''
|
||||
|
||||
if str(s).isdigit():
|
||||
if str(s).isdigit() and s > 0:
|
||||
d = int(s / 84600)
|
||||
h = int((s % 84600) / 3600)
|
||||
m = int(((s % 84600) % 3600) / 60)
|
||||
|
@ -173,6 +173,8 @@ def human_duration(s, sig='dhms'):
|
|||
hd_list.append(str(s) + ' secs')
|
||||
|
||||
hd = ' '.join(hd_list)
|
||||
else:
|
||||
hd = '0'
|
||||
|
||||
return hd
|
||||
|
||||
|
@ -364,13 +366,18 @@ def create_https_certificates(ssl_cert, ssl_key):
|
|||
return True
|
||||
|
||||
|
||||
def cast_to_int(s):
|
||||
try:
|
||||
return int(s)
|
||||
except ValueError:
|
||||
return -1
|
||||
|
||||
def cast_to_float(s):
|
||||
try:
|
||||
return float(s)
|
||||
except ValueError:
|
||||
return -1
|
||||
|
||||
|
||||
def convert_xml_to_json(xml):
|
||||
o = xmltodict.parse(xml)
|
||||
return json.dumps(o)
|
||||
|
|
835
plexpy/libraries.py
Normal file
835
plexpy/libraries.py
Normal file
|
@ -0,0 +1,835 @@
|
|||
# This file is part of PlexPy.
|
||||
#
|
||||
# PlexPy is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# PlexPy is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# 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, datatables, common, database, helpers
|
||||
import plexpy
|
||||
|
||||
def update_section_ids():
|
||||
from plexpy import pmsconnect, activity_pinger
|
||||
|
||||
plexpy.CONFIG.UPDATE_SECTION_IDS = -1
|
||||
|
||||
logger.info(u"PlexPy Libraries :: Updating section_id's in database.")
|
||||
|
||||
logger.debug(u"PlexPy Libraries :: Disabling monitoring while update in progress.")
|
||||
plexpy.schedule_job(activity_pinger.check_active_sessions, 'Check for active sessions',
|
||||
hours=0, minutes=0, seconds=0)
|
||||
plexpy.schedule_job(activity_pinger.check_recently_added, 'Check for recently added items',
|
||||
hours=0, minutes=0, seconds=0)
|
||||
plexpy.schedule_job(activity_pinger.check_server_response, 'Check for server response',
|
||||
hours=0, minutes=0, seconds=0)
|
||||
|
||||
monitor_db = database.MonitorDatabase()
|
||||
|
||||
try:
|
||||
query = 'SELECT id, rating_key FROM session_history_metadata WHERE section_id IS NULL'
|
||||
result = monitor_db.select(query=query)
|
||||
except Exception as e:
|
||||
logger.warn(u"PlexPy Libraries :: Unable to execute database query for update_section_ids: %s." % e)
|
||||
|
||||
logger.debug(u"PlexPy Libraries :: Unable to update section_id's in database.")
|
||||
plexpy.CONFIG.__setattr__('UPDATE_SECTION_IDS', 1)
|
||||
plexpy.CONFIG.write()
|
||||
|
||||
logger.debug(u"PlexPy Libraries :: Re-enabling monitoring.")
|
||||
plexpy.initialize_scheduler()
|
||||
return None
|
||||
|
||||
pms_connect = pmsconnect.PmsConnect()
|
||||
|
||||
error_keys = set()
|
||||
for item in result:
|
||||
id = item['id']
|
||||
rating_key = item['rating_key']
|
||||
metadata = pms_connect.get_metadata_details(rating_key=rating_key)
|
||||
|
||||
if metadata:
|
||||
metadata = metadata['metadata']
|
||||
section_keys = {'id': id}
|
||||
section_values = {'section_id': metadata['section_id']}
|
||||
monitor_db.upsert('session_history_metadata', key_dict=section_keys, value_dict=section_values)
|
||||
else:
|
||||
error_keys.add(rating_key)
|
||||
|
||||
if error_keys:
|
||||
logger.debug(u"PlexPy Libraries :: Updated all section_id's in database except for rating_keys: %s." %
|
||||
', '.join(str(key) for key in error_keys))
|
||||
else:
|
||||
logger.debug(u"PlexPy Libraries :: Updated all section_id's in database.")
|
||||
|
||||
plexpy.CONFIG.__setattr__('UPDATE_SECTION_IDS', 0)
|
||||
plexpy.CONFIG.write()
|
||||
|
||||
logger.debug(u"PlexPy Libraries :: Re-enabling monitoring.")
|
||||
plexpy.initialize_scheduler()
|
||||
|
||||
return True
|
||||
|
||||
class Libraries(object):
|
||||
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
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',
|
||||
'library_sections.parent_count',
|
||||
'library_sections.child_count',
|
||||
'library_sections.thumb AS library_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',
|
||||
'session_history_metadata.thumb',
|
||||
'session_history_metadata.parent_thumb',
|
||||
'session_history_metadata.grandparent_thumb',
|
||||
'session_history_metadata.media_type',
|
||||
'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],
|
||||
group_by=['library_sections.section_id'],
|
||||
join_types=['LEFT OUTER JOIN',
|
||||
'LEFT OUTER JOIN',
|
||||
'LEFT OUTER JOIN'],
|
||||
join_tables=['session_history_metadata',
|
||||
'session_history',
|
||||
'session_history_media_info'],
|
||||
join_evals=[['session_history_metadata.section_id', 'library_sections.section_id'],
|
||||
['session_history_metadata.id', 'session_history.id'],
|
||||
['session_history_metadata.id', 'session_history_media_info.id']],
|
||||
kwargs=kwargs)
|
||||
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,
|
||||
'data': 'null',
|
||||
'error': 'Unable to execute database query.'}
|
||||
|
||||
result = query['result']
|
||||
|
||||
rows = []
|
||||
for item in result:
|
||||
if item['media_type'] == 'episode' and item['parent_thumb']:
|
||||
thumb = item['parent_thumb']
|
||||
elif item['media_type'] == 'episode':
|
||||
thumb = item['grandparent_thumb']
|
||||
else:
|
||||
thumb = item['thumb']
|
||||
|
||||
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'],
|
||||
'do_notify': helpers.checked(item['do_notify']),
|
||||
'do_notify_created': helpers.checked(item['do_notify_created']),
|
||||
'keep_history': helpers.checked(item['keep_history'])
|
||||
}
|
||||
|
||||
rows.append(row)
|
||||
|
||||
dict = {'recordsFiltered': query['filteredCount'],
|
||||
'recordsTotal': query['totalCount'],
|
||||
'data': rows,
|
||||
'draw': query['draw']
|
||||
}
|
||||
|
||||
return dict
|
||||
|
||||
def get_datatables_media_info(self, section_id=None, section_type=None, rating_key=None, refresh=False, kwargs=None):
|
||||
from plexpy import pmsconnect
|
||||
import json, os
|
||||
|
||||
default_return = {'recordsFiltered': 0,
|
||||
'recordsTotal': 0,
|
||||
'draw': 0,
|
||||
'data': None,
|
||||
'error': 'Unable to execute database query.'}
|
||||
|
||||
if section_id and not str(section_id).isdigit():
|
||||
logger.warn(u"PlexPy Libraries :: Datatable media info called by invalid section_id provided.")
|
||||
return default_return
|
||||
elif rating_key and not str(rating_key).isdigit():
|
||||
logger.warn(u"PlexPy Libraries :: Datatable media info called by invalid rating_key provided.")
|
||||
return default_return
|
||||
|
||||
# Get the library details
|
||||
library_details = self.get_details(section_id=section_id)
|
||||
if library_details['section_id'] == None:
|
||||
logger.debug(u"PlexPy Libraries :: Library section_id %s not found." % section_id)
|
||||
return default_return
|
||||
|
||||
if not section_type:
|
||||
section_type = library_details['section_type']
|
||||
|
||||
# Get play counts from the database
|
||||
monitor_db = database.MonitorDatabase()
|
||||
|
||||
if plexpy.CONFIG.GROUP_HISTORY_TABLES:
|
||||
count_by = 'reference_id'
|
||||
else:
|
||||
count_by = 'id'
|
||||
|
||||
if section_type == 'show' or section_type == 'artist':
|
||||
group_by = 'grandparent_rating_key'
|
||||
elif section_type == 'season' or section_type == 'album':
|
||||
group_by = 'parent_rating_key'
|
||||
else:
|
||||
group_by = 'rating_key'
|
||||
|
||||
try:
|
||||
query = 'SELECT MAX(session_history.started) AS last_watched, COUNT(DISTINCT session_history.%s) AS play_count, ' \
|
||||
'session_history.rating_key, session_history.parent_rating_key, session_history.grandparent_rating_key ' \
|
||||
'FROM session_history ' \
|
||||
'JOIN session_history_metadata ON session_history.id = session_history_metadata.id ' \
|
||||
'WHERE session_history_metadata.section_id = ? ' \
|
||||
'GROUP BY session_history.%s ' % (count_by, group_by)
|
||||
result = monitor_db.select(query, args=[section_id])
|
||||
except Exception as e:
|
||||
logger.warn(u"PlexPy Libraries :: Unable to execute database query for get_datatables_media_info2: %s." % e)
|
||||
return default_return
|
||||
|
||||
watched_list = {}
|
||||
for item in result:
|
||||
watched_list[str(item[group_by])] = {'last_watched': item['last_watched'],
|
||||
'play_count': item['play_count']}
|
||||
|
||||
rows = []
|
||||
# Import media info cache from json file
|
||||
if rating_key:
|
||||
try:
|
||||
inFilePath = os.path.join(plexpy.CONFIG.CACHE_DIR,'media_info_%s-%s.json' % (section_id, rating_key))
|
||||
with open(inFilePath, 'r') as inFile:
|
||||
rows = json.load(inFile)
|
||||
library_count = len(rows)
|
||||
except IOError as e:
|
||||
#logger.debug(u"PlexPy Libraries :: No JSON file for rating_key %s." % rating_key)
|
||||
#logger.debug(u"PlexPy Libraries :: Refreshing data and creating new JSON file for rating_key %s." % rating_key)
|
||||
pass
|
||||
elif section_id:
|
||||
try:
|
||||
inFilePath = os.path.join(plexpy.CONFIG.CACHE_DIR,'media_info_%s.json' % section_id)
|
||||
with open(inFilePath, 'r') as inFile:
|
||||
rows = json.load(inFile)
|
||||
library_count = len(rows)
|
||||
except IOError as e:
|
||||
#logger.debug(u"PlexPy Libraries :: No JSON file for library section_id %s." % section_id)
|
||||
#logger.debug(u"PlexPy Libraries :: Refreshing data and creating new JSON file for section_id %s." % section_id)
|
||||
pass
|
||||
|
||||
# If no cache was imported, get all library children items
|
||||
cached_items = {d['rating_key']: d['file_size'] for d in rows}
|
||||
|
||||
if refresh or not rows:
|
||||
pms_connect = pmsconnect.PmsConnect()
|
||||
|
||||
if rating_key:
|
||||
library_children = pms_connect.get_library_children_details(rating_key=rating_key,
|
||||
get_media_info=True)
|
||||
elif section_id:
|
||||
library_children = pms_connect.get_library_children_details(section_id=section_id,
|
||||
section_type=section_type,
|
||||
get_media_info=True)
|
||||
|
||||
if library_children:
|
||||
library_count = library_children['library_count']
|
||||
children_list = library_children['childern_list']
|
||||
else:
|
||||
logger.warn(u"PlexPy Libraries :: Unable to get a list of library items.")
|
||||
return default_return
|
||||
|
||||
for item in children_list:
|
||||
cached_file_size = cached_items.get(item['rating_key'], None)
|
||||
file_size = cached_file_size if cached_file_size else item.get('file_size', '')
|
||||
|
||||
row = {'section_id': library_details['section_id'],
|
||||
'section_type': library_details['section_type'],
|
||||
'added_at': item['added_at'],
|
||||
'media_type': item['media_type'],
|
||||
'rating_key': item['rating_key'],
|
||||
'parent_rating_key': item['parent_rating_key'],
|
||||
'grandparent_rating_key': item['grandparent_rating_key'],
|
||||
'title': item['title'],
|
||||
'year': item['year'],
|
||||
'media_index': item['media_index'],
|
||||
'parent_media_index': item['parent_media_index'],
|
||||
'thumb': item['thumb'],
|
||||
'container': item.get('container', ''),
|
||||
'bitrate': item.get('bitrate', ''),
|
||||
'video_codec': item.get('video_codec', ''),
|
||||
'video_resolution': item.get('video_resolution', ''),
|
||||
'video_framerate': item.get('video_framerate', ''),
|
||||
'audio_codec': item.get('audio_codec', ''),
|
||||
'audio_channels': item.get('audio_channels', ''),
|
||||
'file_size': file_size
|
||||
}
|
||||
rows.append(row)
|
||||
|
||||
if not rows:
|
||||
return default_return
|
||||
|
||||
# Cache the media info to a json file
|
||||
if rating_key:
|
||||
try:
|
||||
outFilePath = os.path.join(plexpy.CONFIG.CACHE_DIR,'media_info_%s-%s.json' % (section_id, rating_key))
|
||||
with open(outFilePath, 'w') as outFile:
|
||||
json.dump(rows, outFile)
|
||||
except IOError as e:
|
||||
logger.debug(u"PlexPy Libraries :: Unable to create cache file for rating_key %s." % rating_key)
|
||||
elif section_id:
|
||||
try:
|
||||
outFilePath = os.path.join(plexpy.CONFIG.CACHE_DIR,'media_info_%s.json' % section_id)
|
||||
with open(outFilePath, 'w') as outFile:
|
||||
json.dump(rows, outFile)
|
||||
except IOError as e:
|
||||
logger.debug(u"PlexPy Libraries :: Unable to create cache file for section_id %s." % section_id)
|
||||
|
||||
# Update the last_watched and play_count
|
||||
for item in rows:
|
||||
watched_item = watched_list.get(item['rating_key'], None)
|
||||
if watched_item:
|
||||
item['last_watched'] = watched_item['last_watched']
|
||||
item['play_count'] = watched_item['play_count']
|
||||
else:
|
||||
item['last_watched'] = None
|
||||
item['play_count'] = None
|
||||
|
||||
results = []
|
||||
|
||||
# Get datatables JSON data
|
||||
if kwargs.get('json_data'):
|
||||
json_data = helpers.process_json_kwargs(json_kwargs=kwargs.get('json_data'))
|
||||
#print json_data
|
||||
|
||||
# Search results
|
||||
search_value = json_data['search']['value'].lower()
|
||||
if search_value:
|
||||
searchable_columns = [d['data'] for d in json_data['columns'] if d['searchable']]
|
||||
for row in rows:
|
||||
for k,v in row.iteritems():
|
||||
if k in searchable_columns and search_value in v.lower():
|
||||
results.append(row)
|
||||
break
|
||||
else:
|
||||
results = rows
|
||||
|
||||
filtered_count = len(results)
|
||||
|
||||
# Sort results
|
||||
results = sorted(results, key=lambda k: k['title'])
|
||||
sort_order = json_data['order']
|
||||
for order in reversed(sort_order):
|
||||
sort_key = json_data['columns'][int(order['column'])]['data']
|
||||
reverse = True if order['dir'] == 'desc' else False
|
||||
if rating_key and sort_key == 'title':
|
||||
results = sorted(results, key=lambda k: helpers.cast_to_int(k['media_index']), reverse=reverse)
|
||||
elif sort_key == 'file_size' or sort_key == 'bitrate':
|
||||
results = sorted(results, key=lambda k: helpers.cast_to_int(k[sort_key]), reverse=reverse)
|
||||
else:
|
||||
results = sorted(results, key=lambda k: k[sort_key], reverse=reverse)
|
||||
|
||||
total_file_size = sum([helpers.cast_to_int(d['file_size']) for d in results])
|
||||
|
||||
# Paginate results
|
||||
results = results[json_data['start']:(json_data['start'] + json_data['length'])]
|
||||
|
||||
filtered_file_size = sum([helpers.cast_to_int(d['file_size']) for d in results])
|
||||
|
||||
dict = {'recordsFiltered': filtered_count,
|
||||
'recordsTotal': library_count,
|
||||
'data': results,
|
||||
'draw': int(json_data['draw']),
|
||||
'filtered_file_size': filtered_file_size,
|
||||
'total_file_size': total_file_size
|
||||
}
|
||||
|
||||
return dict
|
||||
|
||||
def get_media_info_file_sizes(self, section_id=None, rating_key=None):
|
||||
from plexpy import pmsconnect
|
||||
import json, os
|
||||
|
||||
if section_id and not str(section_id).isdigit():
|
||||
logger.warn(u"PlexPy Libraries :: Datatable media info file size called by invalid section_id provided.")
|
||||
return False
|
||||
elif rating_key and not str(rating_key).isdigit():
|
||||
logger.warn(u"PlexPy Libraries :: Datatable media info file size called by invalid rating_key provided.")
|
||||
return False
|
||||
|
||||
# Get the library details
|
||||
library_details = self.get_details(section_id=section_id)
|
||||
if library_details['section_id'] == None:
|
||||
logger.debug(u"PlexPy Libraries :: Library section_id %s not found." % section_id)
|
||||
return False
|
||||
if library_details['section_type'] == 'photo':
|
||||
return False
|
||||
|
||||
rows = []
|
||||
# Import media info cache from json file
|
||||
if rating_key:
|
||||
#logger.debug(u"PlexPy Libraries :: Getting file sizes for rating_key %s." % rating_key)
|
||||
try:
|
||||
inFilePath = os.path.join(plexpy.CONFIG.CACHE_DIR,'media_info_%s-%s.json' % (section_id, rating_key))
|
||||
with open(inFilePath, 'r') as inFile:
|
||||
rows = json.load(inFile)
|
||||
except IOError as e:
|
||||
#logger.debug(u"PlexPy Libraries :: No JSON file for rating_key %s." % rating_key)
|
||||
#logger.debug(u"PlexPy Libraries :: Refreshing data and creating new JSON file for rating_key %s." % rating_key)
|
||||
pass
|
||||
elif section_id:
|
||||
logger.debug(u"PlexPy Libraries :: Getting file sizes for section_id %s." % section_id)
|
||||
try:
|
||||
inFilePath = os.path.join(plexpy.CONFIG.CACHE_DIR,'media_info_%s.json' % section_id)
|
||||
with open(inFilePath, 'r') as inFile:
|
||||
rows = json.load(inFile)
|
||||
except IOError as e:
|
||||
#logger.debug(u"PlexPy Libraries :: No JSON file for library section_id %s." % section_id)
|
||||
#logger.debug(u"PlexPy Libraries :: Refreshing data and creating new JSON file for section_id %s." % section_id)
|
||||
pass
|
||||
|
||||
# Get the total file size for each item
|
||||
pms_connect = pmsconnect.PmsConnect()
|
||||
|
||||
for item in rows:
|
||||
if item['rating_key'] and not item['file_size']:
|
||||
file_size = 0
|
||||
|
||||
child_metadata = pms_connect.get_metadata_children_details(rating_key=item['rating_key'],
|
||||
get_children=True,
|
||||
get_media_info=True)
|
||||
metadata_list = child_metadata['metadata']
|
||||
|
||||
for child_metadata in metadata_list:
|
||||
file_size += helpers.cast_to_int(child_metadata.get('file_size', 0))
|
||||
|
||||
item['file_size'] = file_size
|
||||
|
||||
# Cache the media info to a json file
|
||||
if rating_key:
|
||||
try:
|
||||
outFilePath = os.path.join(plexpy.CONFIG.CACHE_DIR,'media_info_%s-%s.json' % (section_id, rating_key))
|
||||
with open(outFilePath, 'w') as outFile:
|
||||
json.dump(rows, outFile)
|
||||
except IOError as e:
|
||||
logger.debug(u"PlexPy Libraries :: Unable to create cache file with file sizes for rating_key %s." % rating_key)
|
||||
elif section_id:
|
||||
try:
|
||||
outFilePath = os.path.join(plexpy.CONFIG.CACHE_DIR,'media_info_%s.json' % section_id)
|
||||
with open(outFilePath, 'w') as outFile:
|
||||
json.dump(rows, outFile)
|
||||
except IOError as e:
|
||||
logger.debug(u"PlexPy Libraries :: Unable to create cache file with file sizes for section_id %s." % section_id)
|
||||
|
||||
if rating_key:
|
||||
#logger.debug(u"PlexPy Libraries :: File sizes updated for rating_key %s." % rating_key)
|
||||
pass
|
||||
elif section_id:
|
||||
logger.debug(u"PlexPy Libraries :: File sizes updated for section_id %s." % section_id)
|
||||
|
||||
return True
|
||||
|
||||
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 = {'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(u"PlexPy Libraries :: Unable to execute database query for set_config: %s." % e)
|
||||
|
||||
def get_details(self, section_id=None):
|
||||
from plexpy import pmsconnect
|
||||
|
||||
monitor_db = database.MonitorDatabase()
|
||||
|
||||
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': 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 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
|
||||
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': 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:
|
||||
# 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': 'Local',
|
||||
'section_type': '',
|
||||
'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_watch_time_stats(self, section_id=None):
|
||||
monitor_db = database.MonitorDatabase()
|
||||
|
||||
time_queries = [1, 7, 30, 0]
|
||||
library_watch_time_stats = []
|
||||
|
||||
for days in time_queries:
|
||||
try:
|
||||
if days > 0:
|
||||
if str(section_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 section_id = ?' % days
|
||||
result = monitor_db.select(query, args=[section_id])
|
||||
else:
|
||||
result = []
|
||||
else:
|
||||
if str(section_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 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_watch_time_stats: %s." % e)
|
||||
result = []
|
||||
|
||||
for item in result:
|
||||
if item['total_time']:
|
||||
total_time = item['total_time']
|
||||
total_plays = item['total_plays']
|
||||
else:
|
||||
total_time = 0
|
||||
total_plays = 0
|
||||
|
||||
row = {'query_days': days,
|
||||
'total_time': total_time,
|
||||
'total_plays': total_plays
|
||||
}
|
||||
|
||||
library_watch_time_stats.append(row)
|
||||
|
||||
return library_watch_time_stats
|
||||
|
||||
def get_user_stats(self, section_id=None):
|
||||
monitor_db = database.MonitorDatabase()
|
||||
|
||||
user_stats = []
|
||||
|
||||
try:
|
||||
if str(section_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 ' \
|
||||
'JOIN session_history_metadata ON session_history_metadata.id = session_history.id ' \
|
||||
'JOIN users ON users.user_id = session_history.user_id ' \
|
||||
'WHERE section_id = ? ' \
|
||||
'GROUP BY user ' \
|
||||
'ORDER BY user_count DESC'
|
||||
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_user_stats: %s." % e)
|
||||
result = []
|
||||
|
||||
for item in result:
|
||||
row = {'user': item['user'],
|
||||
'user_id': item['user_id'],
|
||||
'thumb': item['thumb'],
|
||||
'total_plays': item['user_count']
|
||||
}
|
||||
user_stats.append(row)
|
||||
|
||||
return user_stats
|
||||
|
||||
def get_recently_watched(self, section_id=None, limit='10'):
|
||||
monitor_db = database.MonitorDatabase()
|
||||
recently_watched = []
|
||||
|
||||
if not limit.isdigit():
|
||||
limit = '10'
|
||||
|
||||
try:
|
||||
if str(section_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 section_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=[section_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'],
|
||||
'media_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()
|
||||
|
||||
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
|
||||
|
||||
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.section_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.section_id = ?)', [section_id])
|
||||
session_history_metadata_del = \
|
||||
monitor_db.action('DELETE FROM '
|
||||
'session_history_metadata '
|
||||
'WHERE session_history_metadata.section_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)
|
||||
|
||||
def delete_datatable_media_info_cache(self, section_id=None):
|
||||
import os
|
||||
|
||||
try:
|
||||
if section_id.isdigit():
|
||||
[os.remove(os.path.join(plexpy.CONFIG.CACHE_DIR, f)) for f in os.listdir(plexpy.CONFIG.CACHE_DIR)
|
||||
if f.startswith('media_info-%s' % section_id) and f.endswith('.json')]
|
||||
|
||||
logger.debug(u"PlexPy Libraries :: Deleted media info table cache for section_id %s." % section_id)
|
||||
return 'Deleted media info table cache for library with id %s.' % section_id
|
||||
else:
|
||||
return 'Unable to delete media info table cache, section_id not valid.'
|
||||
except Exception as e:
|
||||
logger.warn(u"PlexPy Libraries :: Unable to delete media info table cache: %s." % e)
|
|
@ -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['section_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)
|
||||
|
|
|
@ -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
|
||||
|
@ -2034,7 +2044,7 @@ class FacebookNotifier(object):
|
|||
self._post_facebook(subject + ': ' + message)
|
||||
|
||||
def test_notify(self):
|
||||
return self._post_facebook("This is a test notification from PlexPy at " + helpers.now())
|
||||
return self._post_facebook(u"PlexPy Notifiers :: This is a test notification from PlexPy at " + helpers.now())
|
||||
|
||||
def _get_authorization(self):
|
||||
return facebook.auth_url(app_id=self.app_id,
|
||||
|
@ -2042,7 +2052,7 @@ class FacebookNotifier(object):
|
|||
perms=['user_managed_groups','publish_actions'])
|
||||
|
||||
def _get_credentials(self, code):
|
||||
logger.info('Requesting access token from Facebook')
|
||||
logger.info(u"PlexPy Notifiers :: Requesting access token from Facebook")
|
||||
|
||||
try:
|
||||
# Request user access token
|
||||
|
@ -2062,7 +2072,7 @@ class FacebookNotifier(object):
|
|||
plexpy.CONFIG.FACEBOOK_TOKEN = access_token
|
||||
plexpy.CONFIG.write()
|
||||
except Exception as e:
|
||||
logger.info(u"Error requesting Facebook access token: %s" % e)
|
||||
logger.info(u"PlexPy Notifiers :: Error requesting Facebook access token: %s" % e)
|
||||
return False
|
||||
|
||||
return True
|
||||
|
@ -2076,21 +2086,23 @@ class FacebookNotifier(object):
|
|||
|
||||
try:
|
||||
api.put_wall_post(profile_id=group_id, message=message)
|
||||
logger.info(u"Facebook notifications sent.")
|
||||
logger.info(u"PlexPy Notifiers :: Facebook notifications sent.")
|
||||
except Exception as e:
|
||||
logger.info(u"Error sending Facebook post: %s" % e)
|
||||
logger.info(u"PlexPy Notifiers :: Error sending Facebook post: %s" % e)
|
||||
return False
|
||||
|
||||
return True
|
||||
else:
|
||||
logger.info('Error sending Facebook post: No Facebook Group ID provided.')
|
||||
logger.info(u"PlexPy Notifiers :: Error sending Facebook post: No Facebook Group ID provided.")
|
||||
return False
|
||||
|
||||
def return_config_options(self):
|
||||
config_option = [{'label': 'Instructions',
|
||||
'description': '<strong>Facebook notifications are currently experimental!</strong><br><br> \
|
||||
Step 1: Visit <a href="https://developers.facebook.com/apps/" target="_blank">Facebook Developers</a> to create a new app using <strong>advanced setup</strong>.<br>\
|
||||
Step 2: Go to <strong>Settings > Advanced</strong> and fill in <strong>Valid OAuth redirect URIs</strong> with your PlexPy URL (i.e. http://localhost:8181).<br>\
|
||||
Step 1: Visit <a href="https://developers.facebook.com/apps/" target="_blank"> \
|
||||
Facebook Developers</a> to create a new app using <strong>advanced setup</strong>.<br>\
|
||||
Step 2: Go to <strong>Settings > Advanced</strong> and fill in \
|
||||
<strong>Valid OAuth redirect URIs</strong> with your PlexPy URL (i.e. http://localhost:8181).<br>\
|
||||
Step 3: Fill in the <strong>App ID</strong> and <strong>App Secret</strong> below.<br>\
|
||||
Step 4: Click the <strong>Request Authorization</strong> button below.',
|
||||
'input_type': 'help'
|
||||
|
|
150
plexpy/plextv.py
150
plexpy/plextv.py
|
@ -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()
|
||||
|
@ -139,13 +139,16 @@ class PlexTV(object):
|
|||
plextv_response = self.get_plex_auth(output_format='xml')
|
||||
|
||||
if plextv_response:
|
||||
xml_head = plextv_response.getElementsByTagName('user')
|
||||
if not xml_head:
|
||||
logger.warn("Error parsing XML for Plex.tv token")
|
||||
try:
|
||||
xml_head = plextv_response.getElementsByTagName('user')
|
||||
if xml_head:
|
||||
auth_token = xml_head[0].getAttribute('authenticationToken')
|
||||
else:
|
||||
logger.warn(u"PlexPy PlexTV :: Could not get Plex authentication token.")
|
||||
except Exception as e:
|
||||
logger.warn(u"PlexPy PlexTV :: Unable to parse XML for get_token: %s." % e)
|
||||
return []
|
||||
|
||||
auth_token = xml_head[0].getAttribute('authenticationToken')
|
||||
|
||||
return auth_token
|
||||
else:
|
||||
return []
|
||||
|
@ -213,16 +216,16 @@ class PlexTV(object):
|
|||
|
||||
try:
|
||||
xml_parse = minidom.parseString(own_account)
|
||||
except Exception, e:
|
||||
logger.warn("Error parsing XML for Plex account details: %s" % e)
|
||||
except Exception as e:
|
||||
logger.warn(u"PlexPy PlexTV :: Unable to parse XML for get_full_users_list own account: %s" % e)
|
||||
return []
|
||||
except:
|
||||
logger.warn("Error parsing XML for Plex account details.")
|
||||
logger.warn(u"PlexPy PlexTV :: Unable to parse XML for get_full_users_list own account.")
|
||||
return []
|
||||
|
||||
xml_head = xml_parse.getElementsByTagName('user')
|
||||
if not xml_head:
|
||||
logger.warn("Error parsing XML for Plex account details.")
|
||||
logger.warn(u"PlexPy PlexTV :: Unable to parse XML for get_full_users_list.")
|
||||
else:
|
||||
for a in xml_head:
|
||||
own_details = {"user_id": helpers.get_xml_attr(a, 'id'),
|
||||
|
@ -238,14 +241,16 @@ class PlexTV(object):
|
|||
|
||||
try:
|
||||
xml_parse = minidom.parseString(friends_list)
|
||||
except Exception, e:
|
||||
logger.warn("Error parsing XML for Plex friends list: %s" % e)
|
||||
except Exception as e:
|
||||
logger.warn(u"PlexPy PlexTV :: Unable to parse XML for get_full_users_list friends list: %s" % e)
|
||||
return []
|
||||
except:
|
||||
logger.warn("Error parsing XML for Plex friends list.")
|
||||
logger.warn(u"PlexPy PlexTV :: Unable to parse XML for get_full_users_list friends list.")
|
||||
return []
|
||||
|
||||
xml_head = xml_parse.getElementsByTagName('User')
|
||||
if not xml_head:
|
||||
logger.warn("Error parsing XML for Plex friends list.")
|
||||
logger.warn(u"PlexPy PlexTV :: Unable to parse XML for get_full_users_list.")
|
||||
else:
|
||||
for a in xml_head:
|
||||
friend = {"user_id": helpers.get_xml_attr(a, 'id'),
|
||||
|
@ -269,17 +274,17 @@ class PlexTV(object):
|
|||
|
||||
try:
|
||||
xml_parse = minidom.parseString(sync_list)
|
||||
except Exception, e:
|
||||
logger.warn("Error parsing XML for Plex sync lists: %s" % e)
|
||||
except Exception as e:
|
||||
logger.warn(u"PlexPy PlexTV :: Unable to parse XML for get_synced_items: %s" % e)
|
||||
return []
|
||||
except:
|
||||
logger.warn("Error parsing XML for Plex sync lists.")
|
||||
logger.warn(u"PlexPy PlexTV :: Unable to parse XML for get_synced_items.")
|
||||
return []
|
||||
|
||||
xml_head = xml_parse.getElementsByTagName('SyncList')
|
||||
|
||||
if not xml_head:
|
||||
logger.warn("Error parsing XML for Plex sync lists.")
|
||||
logger.warn(u"PlexPy PlexTV :: Unable to parse XML for get_synced_items.")
|
||||
else:
|
||||
for a in xml_head:
|
||||
client_id = helpers.get_xml_attr(a, 'id')
|
||||
|
@ -287,8 +292,8 @@ class PlexTV(object):
|
|||
for device in sync_device:
|
||||
device_user_id = helpers.get_xml_attr(device, 'userID')
|
||||
try:
|
||||
device_username = user_data.get_user_details(user_id=device_user_id)['username']
|
||||
device_friendly_name = user_data.get_user_details(user_id=device_user_id)['friendly_name']
|
||||
device_username = user_data.get_details(user_id=device_user_id)['username']
|
||||
device_friendly_name = user_data.get_details(user_id=device_user_id)['friendly_name']
|
||||
except:
|
||||
device_username = ''
|
||||
device_friendly_name = ''
|
||||
|
@ -375,7 +380,7 @@ class PlexTV(object):
|
|||
if plexpy.CONFIG.PMS_IDENTIFIER:
|
||||
server_id = plexpy.CONFIG.PMS_IDENTIFIER
|
||||
else:
|
||||
logger.error('PlexPy PlexTV connector :: Unable to retrieve server identity.')
|
||||
logger.error(u"PlexPy PlexTV :: Unable to retrieve server identity.")
|
||||
return []
|
||||
|
||||
plextv_resources = self.get_plextv_resources(include_https=include_https)
|
||||
|
@ -383,17 +388,17 @@ class PlexTV(object):
|
|||
|
||||
try:
|
||||
xml_parse = minidom.parseString(plextv_resources)
|
||||
except Exception, e:
|
||||
logger.warn("Error parsing XML for Plex resources: %s" % e)
|
||||
except Exception as e:
|
||||
logger.warn(u"PlexPy PlexTV :: Unable to parse XML for get_server_urls: %s" % e)
|
||||
return []
|
||||
except:
|
||||
logger.warn("Error parsing XML for Plex resources.")
|
||||
logger.warn(u"PlexPy PlexTV :: Unable to parse XML for get_server_urls.")
|
||||
return []
|
||||
|
||||
try:
|
||||
xml_head = xml_parse.getElementsByTagName('Device')
|
||||
except:
|
||||
logger.warn("Error parsing XML for Plex resources.")
|
||||
except Exception as e:
|
||||
logger.warn(u"PlexPy PlexTV :: Unable to parse XML for get_server_urls: %s." % e)
|
||||
return []
|
||||
|
||||
for a in xml_head:
|
||||
|
@ -430,49 +435,14 @@ class PlexTV(object):
|
|||
|
||||
return server_urls
|
||||
|
||||
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')
|
||||
servers = xmltodict.parse(result, process_namespaces=True, attr_prefix='')
|
||||
clean_servers = []
|
||||
|
||||
try:
|
||||
if servers:
|
||||
# Fix if its only one "device"
|
||||
if int(servers['MediaContainer']['size']) == 1:
|
||||
servers['MediaContainer']['Device'] = [servers['MediaContainer']['Device']]
|
||||
|
||||
for server in servers['MediaContainer']['Device']:
|
||||
# Only grab servers online and own
|
||||
if server.get('presence', None) == '1' and server.get('owned', None) == '1' and server.get('provides', None) == 'server':
|
||||
# If someone only has one connection..
|
||||
if isinstance(server['Connection'], dict):
|
||||
server['Connection'] = [server['Connection']]
|
||||
|
||||
for s in server['Connection']:
|
||||
# to avoid circular ref
|
||||
d = {}
|
||||
d.update(s)
|
||||
d.update(server)
|
||||
d['label'] = d['name']
|
||||
d['value'] = d['address']
|
||||
del d['Connection']
|
||||
clean_servers.append(d)
|
||||
|
||||
except Exception as e:
|
||||
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.")
|
||||
except Exception as e:
|
||||
logger.warn(u"PlexPy PlexTV :: Unable to parse XML for get_server_times: %s." % e)
|
||||
return []
|
||||
|
||||
for a in xml_head:
|
||||
|
@ -482,4 +452,42 @@ class PlexTV(object):
|
|||
})
|
||||
break
|
||||
|
||||
return server_times
|
||||
return server_times
|
||||
|
||||
def discover(self):
|
||||
""" Query plex for all servers online. Returns the ones you own in a selectize format """
|
||||
servers = self.get_plextv_resources(include_https=True, output_format='xml')
|
||||
clean_servers = []
|
||||
|
||||
try:
|
||||
xml_head = servers.getElementsByTagName('MediaContainer')
|
||||
except Exception as e:
|
||||
logger.warn(u"PlexPy PlexTV :: Failed to get servers from plex: %s." % e)
|
||||
return []
|
||||
|
||||
for a in xml_head:
|
||||
if a.getAttribute('size'):
|
||||
if a.getAttribute('size') == '0':
|
||||
return []
|
||||
|
||||
if a.getElementsByTagName('Device'):
|
||||
devices = a.getElementsByTagName('Device')
|
||||
|
||||
for d in devices:
|
||||
if helpers.get_xml_attr(d, 'presence') == '1' and \
|
||||
helpers.get_xml_attr(d, 'owned') == '1' and \
|
||||
helpers.get_xml_attr(d, 'provides') == 'server':
|
||||
connections = d.getElementsByTagName('Connection')
|
||||
|
||||
for c in connections:
|
||||
server = {'httpsRequired': helpers.get_xml_attr(d, 'httpsRequired'),
|
||||
'clientIdentifier': helpers.get_xml_attr(d, 'clientIdentifier'),
|
||||
'label': helpers.get_xml_attr(d, 'name'),
|
||||
'ip': helpers.get_xml_attr(c, 'address'),
|
||||
'port': helpers.get_xml_attr(c, 'port'),
|
||||
'local': helpers.get_xml_attr(c, 'local'),
|
||||
'value': helpers.get_xml_attr(c, 'address')
|
||||
}
|
||||
clean_servers.append(server)
|
||||
|
||||
return clean_servers
|
|
@ -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:
|
||||
|
@ -41,6 +41,7 @@ def extract_plexwatch_xml(xml=None):
|
|||
grandparent_thumb = helpers.get_xml_attr(a, 'grandparentThumb')
|
||||
grandparent_title = helpers.get_xml_attr(a, 'grandparentTitle')
|
||||
guid = helpers.get_xml_attr(a, 'guid')
|
||||
section_id = helpers.get_xml_attr(a, 'librarySectionID')
|
||||
media_index = helpers.get_xml_attr(a, 'index')
|
||||
originally_available_at = helpers.get_xml_attr(a, 'originallyAvailableAt')
|
||||
last_viewed_at = helpers.get_xml_attr(a, 'lastViewedAt')
|
||||
|
@ -156,6 +157,7 @@ def extract_plexwatch_xml(xml=None):
|
|||
'title': title,
|
||||
'tagline': tagline,
|
||||
'guid': guid,
|
||||
'section_id': section_id,
|
||||
'media_index': media_index,
|
||||
'originally_available_at': originally_available_at,
|
||||
'last_viewed_at': last_viewed_at,
|
||||
|
@ -203,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'
|
||||
|
@ -230,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...")
|
||||
|
@ -249,6 +251,8 @@ def import_from_plexwatch(database=None, table_name=None, import_ignore_interval
|
|||
hours=0, minutes=0, seconds=0)
|
||||
plexpy.schedule_job(activity_pinger.check_recently_added, 'Check for recently added items',
|
||||
hours=0, minutes=0, seconds=0)
|
||||
plexpy.schedule_job(activity_pinger.check_server_response, 'Check for server response',
|
||||
hours=0, minutes=0, seconds=0)
|
||||
|
||||
ap = activity_processor.ActivityProcessor()
|
||||
user_data = users.Users()
|
||||
|
@ -352,8 +356,8 @@ def import_from_plexwatch(database=None, table_name=None, import_ignore_interval
|
|||
'title': row['title'],
|
||||
'parent_title': extracted_xml['parent_title'],
|
||||
'grandparent_title': row['grandparent_title'],
|
||||
'index': extracted_xml['media_index'],
|
||||
'parent_index': extracted_xml['parent_media_index'],
|
||||
'media_index': extracted_xml['media_index'],
|
||||
'parent_media_index': extracted_xml['parent_media_index'],
|
||||
'thumb': extracted_xml['thumb'],
|
||||
'parent_thumb': extracted_xml['parent_thumb'],
|
||||
'grandparent_thumb': extracted_xml['grandparent_thumb'],
|
||||
|
@ -370,6 +374,7 @@ def import_from_plexwatch(database=None, table_name=None, import_ignore_interval
|
|||
'rating': extracted_xml['rating'],
|
||||
'duration': extracted_xml['duration'],
|
||||
'guid': extracted_xml['guid'],
|
||||
'section_id': extracted_xml['section_id'],
|
||||
'directors': extracted_xml['directors'],
|
||||
'writers': extracted_xml['writers'],
|
||||
'actors': extracted_xml['actors'],
|
||||
|
@ -409,4 +414,3 @@ def import_users():
|
|||
logger.debug(u"PlexPy Importer :: Users imported.")
|
||||
except:
|
||||
logger.debug(u"PlexPy Importer :: Failed to import users.")
|
||||
|
||||
|
|
1099
plexpy/pmsconnect.py
1099
plexpy/pmsconnect.py
File diff suppressed because it is too large
Load diff
669
plexpy/users.py
669
plexpy/users.py
|
@ -21,29 +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 = ['session_history.id',
|
||||
'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'
|
||||
]
|
||||
|
@ -62,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,
|
||||
|
@ -74,38 +73,44 @@ class Users(object):
|
|||
|
||||
rows = []
|
||||
for item in users:
|
||||
if item["media_type"] == 'episode' and item["parent_thumb"]:
|
||||
thumb = item["parent_thumb"]
|
||||
elif item["media_type"] == 'episode':
|
||||
thumb = item["grandparent_thumb"]
|
||||
if item['friendly_name']:
|
||||
friendly_name = item['friendly_name']
|
||||
else:
|
||||
thumb = item["thumb"]
|
||||
friendly_name = item['username']
|
||||
|
||||
if item['media_type'] == 'episode' and item['parent_thumb']:
|
||||
thumb = item['parent_thumb']
|
||||
elif item['media_type'] == 'episode':
|
||||
thumb = item['grandparent_thumb']
|
||||
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"])
|
||||
platform = common.PLATFORM_NAME_OVERRIDES.get(item['platform'], item['platform'])
|
||||
|
||||
row = {"id": item['id'],
|
||||
"plays": item['plays'],
|
||||
"last_seen": item['last_seen'],
|
||||
"friendly_name": item['friendly_name'],
|
||||
"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'])
|
||||
row = {'user_id': item['user_id'],
|
||||
'username': item['username'],
|
||||
'friendly_name': 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'],
|
||||
'thumb': thumb,
|
||||
'media_type': item['media_type'],
|
||||
'rating_key': item['rating_key'],
|
||||
'video_decision': item['video_decision'],
|
||||
'do_notify': helpers.checked(item['do_notify']),
|
||||
'keep_history': helpers.checked(item['keep_history'])
|
||||
}
|
||||
|
||||
rows.append(row)
|
||||
|
@ -114,39 +119,38 @@ class Users(object):
|
|||
'recordsTotal': query['totalCount'],
|
||||
'data': rows,
|
||||
'draw': query['draw']
|
||||
}
|
||||
}
|
||||
|
||||
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',
|
||||
|
@ -158,8 +162,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,
|
||||
|
@ -180,18 +184,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)
|
||||
|
@ -200,290 +204,173 @@ class Users(object):
|
|||
'recordsTotal': query['totalCount'],
|
||||
'data': rows,
|
||||
'draw': query['draw']
|
||||
}
|
||||
}
|
||||
|
||||
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']:
|
||||
|
@ -502,14 +389,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 = ? ' \
|
||||
|
@ -517,15 +404,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
|
||||
|
@ -540,3 +422,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'],
|
||||
'media_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
|
2359
plexpy/webserve.py
2359
plexpy/webserve.py
File diff suppressed because it is too large
Load diff
Loading…
Add table
Add a link
Reference in a new issue