diff --git a/data/interfaces/default/library_stats.html b/data/interfaces/default/library_stats.html index 70f052e9..2eae932a 100644 --- a/data/interfaces/default/library_stats.html +++ b/data/interfaces/default/library_stats.html @@ -9,23 +9,16 @@ Variable names: data [array] data[array_index] :: Usable parameters -data['type'] Returns the type of the library. Either 'movie', 'show', 'photo', or 'artist'. -data['rows'] Returns an array containing stat data +data Returns an array containing stat data -data[array_index]['rows'] :: Usable parameters +data[array_index] :: Usable parameters -title Returns the title of the library. +section_name Returns the title of the library. +section_type Returns the type of the library. thumb Returns the thumb of the library. -count Returns the number of items in the library. -count_type Returns the sorting type for the library - -== Only if 'type' is 'show' -episode_count Return the number of episodes in the library. -episode_count_type Return the sorting type for the episodes. - -== Only if 'type' is 'artist' -album_count Return the number of episodes in the library. -album_count_type Return the sorting type for the episodes. +count Returns the number of top level items in the library. +parent_count Returns the number of parent items in the library. +child_count Returns the number of child items in the library. DOCUMENTATION :: END @@ -37,37 +30,58 @@ DOCUMENTATION :: END
  • - % if library['type'] != 'photo': + % if library['section_type'] != 'photo':

    - ${library['rows']['title']} + ${library['section_name']}

    % else: -

    ${library['rows']['title']}

    +

    ${library['section_name']}

    % endif
    + % if library['section_type'] == 'movie':
    -
    ${library['rows']['count_type']}
    -

    ${library['rows']['count']}

    +
    All Movies
    +

    ${library['count']}

    items

    - % if library['type'] == 'show': -
    -
    ${library['rows']['episode_count_type']}
    -

    ${library['rows']['episode_count']}

    + % elif library['section_type'] == 'show': +
    +
    All Shows
    +

    ${library['count']}

    items

    - % endif - % if library['type'] == 'artist':
    -
    ${library['rows']['album_count_type']}
    -

    ${library['rows']['album_count']}

    +
    All Episodes
    +

    ${library['child_count']}

    +

    items

    +
    + % elif library['section_type'] == 'artist': +
    +
    All Artists
    +

    ${library['count']}

    +

    items

    +
    +
    +
    All Albums
    +

    ${library['parent_count']}

    +

    items

    +
    + % elif library['section_type'] == 'photo': +
    +
    All Albums
    +

    ${library['count']}

    +

    items

    +
    +
    +
    All Photos
    +

    ${library['child_count']}

    items

    % endif
    - % if library['rows']['thumb']: + % if library['thumb']:
    -
    +
    % else:
    diff --git a/data/interfaces/default/settings.html b/data/interfaces/default/settings.html index 37c59b5b..aee086f0 100644 --- a/data/interfaces/default/settings.html +++ b/data/interfaces/default/settings.html @@ -348,7 +348,7 @@ available_notification_agents = sorted(notifiers.available_notification_agents()

    Friends List

    - +
    @@ -359,9 +359,29 @@ available_notification_agents = sorted(notifiers.available_notification_agents()
    -

    Refresh the user list when PlexPy starts.

    +

    Refresh the users list when PlexPy starts.

    +
    + +
    +

    Libraries List

    +
    +
    + +
    +
    + +
    + +
    +

    The interval (in hours) PlexPy will request an updated libraries list from your Plex Media Server. 1 minimum, 24 maximum.

    +
    +
    + +

    Refresh the libraries list when PlexPy starts.

    diff --git a/plexpy/__init__.py b/plexpy/__init__.py index 681d2565..703aaaaf 100644 --- a/plexpy/__init__.py +++ b/plexpy/__init__.py @@ -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) @@ -311,8 +315,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()): @@ -431,7 +441,9 @@ def dbcheck(): # 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, ' - 'section_id INTEGER UNIQUE, section_name TEXT, section_type TEXT)' + 'server_id TEXT, section_id INTEGER UNIQUE, section_name TEXT, section_type TEXT, thumb TEXT, ' + 'count INTEGER, parent_count INTEGER, child_count INTEGER, ' + 'do_notify INTEGER DEFAULT 1, keep_history INTEGER DEFAULT 1)' ) # Upgrade sessions table from earlier versions diff --git a/plexpy/config.py b/plexpy/config.py index ac33003c..0c5a9a3f 100644 --- a/plexpy/config.py +++ b/plexpy/config.py @@ -293,6 +293,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), diff --git a/plexpy/datafactory.py b/plexpy/datafactory.py index c83e6fbb..d334d1c1 100644 --- a/plexpy/datafactory.py +++ b/plexpy/datafactory.py @@ -654,6 +654,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: + logger.warn("Unable to execute database query for get_library_stats.") + 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() diff --git a/plexpy/pmsconnect.py b/plexpy/pmsconnect.py index d88ecf53..d59d09e1 100644 --- a/plexpy/pmsconnect.py +++ b/plexpy/pmsconnect.py @@ -13,7 +13,7 @@ # You should have received a copy of the GNU General Public License # along with PlexPy. If not, see . -from plexpy import logger, helpers, users, http_handler, common +from plexpy import logger, helpers, users, http_handler, common, database from urlparse import urlparse import plexpy @@ -37,6 +37,42 @@ def get_server_friendly_name(): return server_name +def refresh_libraries(): + logger.info("Requesting libraries list refresh...") + library_sections = PmsConnect().get_library_details() + + server_id = plexpy.CONFIG.PMS_IDENTIFIER + + if plexpy.CONFIG.HOME_LIBRARY_CARDS == ['first_run']: + populate_cards = True + else: + populate_cards = False + + cards = [] + + if library_sections: + monitor_db = database.MonitorDatabase() + + for section in library_sections: + section_keys = {'server_id': server_id, + 'section_id': section['key']} + section_values = {'server_id': server_id, + 'section_id': section['key'], + 'section_name': section['title'], + 'section_type': section['type'], + 'thumb': section['thumb'], + 'count': section['count'], + 'parent_count': section.get('parent_count', None), + 'child_count': section.get('child_count', None) + } + + monitor_db.upsert('library_sections', key_dict=section_keys, value_dict=section_values) + + logger.info("Libraries list refreshed.") + else: + logger.warn("Unable to refresh libraries list.") + + class PmsConnect(object): """ Retrieve data from Plex Server @@ -1446,10 +1482,22 @@ class PmsConnect(object): sort_type = '&type=1' elif library_type == 'show': sort_type = '&type=2' + elif library_type == 'season': + sort_type = '&type=3' elif library_type == 'episode': sort_type = '&type=4' + elif library_type == 'artist': + sort_type = '&type=8' elif library_type == 'album': - list_type = 'albums' + sort_type = '&type=9' + elif library_type == 'track': + sort_type = '&type=10' + elif library_type == 'photo': + sort_type = '' + elif library_type == 'photoAlbum': + sort_type = '&type=14' + elif library_type == 'picture': + sort_type = '&type=13' library_data = self.get_library_list(section_key, list_type, count, sort_type, output_format='xml') @@ -1492,7 +1540,7 @@ class PmsConnect(object): Output: array """ - def get_library_stats(self, library_cards=''): + def get_library_details(self): server_libraries = self.get_server_children() server_library_stats = [] @@ -1503,35 +1551,57 @@ class PmsConnect(object): for library in libraries_list: library_type = library['type'] section_key = library['key'] - if section_key in library_cards: - library_list = self.get_library_children(library_type, section_key) - else: - continue + library_list = self.get_library_children(library_type, section_key) if library_list['library_count'] != '0': library_stats = {'key': library['key'], 'title': library['title'], + 'type': library_type, 'thumb': library['thumb'], 'count': library_list['library_count'], 'count_type': library_list['count_type'] } if library_type == 'show': - episode_list = self.get_library_children(library_type='episode', section_key=section_key) - episode_stats = {'episode_count': episode_list['library_count'], - 'episode_count_type': 'All Episodes' - } - library_stats.update(episode_stats) + parent_list = self.get_library_children(library_type='season', section_key=section_key) + parent_stats = {'parent_count': parent_list['library_count'], + 'parent_count_type': 'All Seasons' + } + library_stats.update(parent_stats) + + child_list = self.get_library_children(library_type='episode', section_key=section_key) + child_stats = {'child_count': child_list['library_count'], + 'child_count_type': 'All Episodes' + } + library_stats.update(child_stats) if library_type == 'artist': - album_list = self.get_library_children(library_type='album', section_key=section_key) - album_stats = {'album_count': album_list['library_count'], - 'album_count_type': 'All Albums' - } - library_stats.update(album_stats) + parent_list = self.get_library_children(library_type='album', section_key=section_key) + parent_stats = {'parent_count': parent_list['library_count'], + 'parent_count_type': 'All Seasons' + } + library_stats.update(parent_stats) - server_library_stats.append({'type': library_type, - 'rows': library_stats}) + child_list = self.get_library_children(library_type='track', section_key=section_key) + child_stats = {'child_count': child_list['library_count'], + 'child_count_type': 'All Albums' + } + library_stats.update(child_stats) + + if library_type == 'photo': + parent_list = self.get_library_children(library_type='photoAlbum', section_key=section_key) + parent_stats = {'parent_count': parent_list['library_count'], + 'parent_count_type': 'All Photo Albums' + } + library_stats.update(parent_stats) + + child_list = self.get_library_children(library_type='picture', section_key=section_key) + child_stats = {'child_count': child_list['library_count'], + 'child_count_type': 'All Photos' + } + library_stats.update(child_stats) + + server_library_stats.append(library_stats) return server_library_stats diff --git a/plexpy/webserve.py b/plexpy/webserve.py index 28fe3219..8f8ab162 100644 --- a/plexpy/webserve.py +++ b/plexpy/webserve.py @@ -80,6 +80,7 @@ class WebInterface(object): config = { "launch_browser": checked(plexpy.CONFIG.LAUNCH_BROWSER), "refresh_users_on_startup": checked(plexpy.CONFIG.REFRESH_USERS_ON_STARTUP), + "refresh_librareis_on_startup": checked(plexpy.CONFIG.REFRESH_LIBRARIES_ON_STARTUP), "pms_identifier": plexpy.CONFIG.PMS_IDENTIFIER, "pms_ip": plexpy.CONFIG.PMS_IP, "pms_is_remote": checked(plexpy.CONFIG.PMS_IS_REMOTE), @@ -146,23 +147,12 @@ class WebInterface(object): @cherrypy.expose def library_stats(self, **kwargs): - pms_connect = pmsconnect.PmsConnect() + data_factory = datafactory.DataFactory() library_cards = plexpy.CONFIG.HOME_LIBRARY_CARDS.split(', ') - if library_cards == ['library_statistics_first']: - library_cards = ['library_statistics'] - server_children = pms_connect.get_server_children() - server_libraries = server_children['libraries_list'] - - for library in server_libraries: - library_cards.append(library['key']) - - plexpy.CONFIG.HOME_LIBRARY_CARDS = ', '.join(library_cards) - plexpy.CONFIG.write() - - stats_data = pms_connect.get_library_stats(library_cards=library_cards) - + stats_data = data_factory.get_library_stats(library_cards=library_cards) + return serve_template(templatename="library_stats.html", title="Library Stats", data=stats_data) @cherrypy.expose @@ -445,6 +435,8 @@ class WebInterface(object): "monitor_remote_access": checked(plexpy.CONFIG.MONITOR_REMOTE_ACCESS), "monitoring_interval": plexpy.CONFIG.MONITORING_INTERVAL, "monitoring_use_websocket": checked(plexpy.CONFIG.MONITORING_USE_WEBSOCKET), + "refresh_libraries_interval": plexpy.CONFIG.REFRESH_LIBRARIES_INTERVAL, + "refresh_libraries_on_startup": checked(plexpy.CONFIG.REFRESH_LIBRARIES_ON_STARTUP), "refresh_users_interval": plexpy.CONFIG.REFRESH_USERS_INTERVAL, "refresh_users_on_startup": checked(plexpy.CONFIG.REFRESH_USERS_ON_STARTUP), "ip_logging_enable": checked(plexpy.CONFIG.IP_LOGGING_ENABLE), @@ -503,9 +495,10 @@ class WebInterface(object): "movie_notify_enable", "tv_notify_enable", "music_notify_enable", "monitoring_use_websocket", "tv_notify_on_start", "movie_notify_on_start", "music_notify_on_start", "tv_notify_on_stop", "movie_notify_on_stop", "music_notify_on_stop", - "tv_notify_on_pause", "movie_notify_on_pause", "music_notify_on_pause", "refresh_users_on_startup", - "ip_logging_enable", "movie_logging_enable", "tv_logging_enable", "music_logging_enable", - "pms_is_remote", "home_stats_type", "group_history_tables", "notify_consecutive", + "tv_notify_on_pause", "movie_notify_on_pause", "music_notify_on_pause", + "refresh_libraries_on_startup", "refresh_users_on_startup", + "ip_logging_enable", "movie_logging_enable", "tv_logging_enable", "music_logging_enable", + "pms_is_remote", "home_stats_type", "group_history_tables", "notify_consecutive", "notify_recently_added", "notify_recently_added_grandparent", "monitor_remote_access" ] for checked_config in checked_configs: @@ -524,9 +517,15 @@ class WebInterface(object): del kwargs[use_config] # Check if we should refresh our data + refresh_libraries = False refresh_users = False reschedule = False + if 'monitoring_interval' in kwargs and 'refresh_libraries_interval' in kwargs: + if (kwargs['monitoring_interval'] != str(plexpy.CONFIG.MONITORING_INTERVAL)) or \ + (kwargs['refresh_libraries_interval'] != str(plexpy.CONFIG.REFRESH_LIBRARIES_INTERVAL)): + reschedule = True + if 'monitoring_interval' in kwargs and 'refresh_users_interval' in kwargs: if (kwargs['monitoring_interval'] != str(plexpy.CONFIG.MONITORING_INTERVAL)) or \ (kwargs['refresh_users_interval'] != str(plexpy.CONFIG.REFRESH_USERS_INTERVAL)): @@ -542,6 +541,7 @@ class WebInterface(object): if 'pms_ip' in kwargs: if kwargs['pms_ip'] != plexpy.CONFIG.PMS_IP: + refresh_libraries = True refresh_users = True if 'home_stats_cards' in kwargs: @@ -567,6 +567,10 @@ class WebInterface(object): if reschedule: plexpy.initialize_scheduler() + # Refresh users table if our server IP changes. + if refresh_libraries: + threading.Thread(target=pmsconnect.refresh_libraries).start() + # Refresh users table if our server IP changes. if refresh_users: threading.Thread(target=plextv.refresh_users).start() @@ -1310,10 +1314,15 @@ class WebInterface(object): else: logger.warn('Unable to retrieve data.') + @cherrypy.expose + def refresh_libraries_list(self, **kwargs): + threading.Thread(target=pmsconnect.refresh_libraries).start() + logger.info('Manual libraries list refresh requested.') + @cherrypy.expose def refresh_users_list(self, **kwargs): threading.Thread(target=plextv.refresh_users).start() - logger.info('Manual user list refresh requested.') + logger.info('Manual users list refresh requested.') @cherrypy.expose def get_sync(self, machine_id=None, user_id=None, **kwargs):