mostly working server manager and multi server support

This commit is contained in:
tyler breese 2023-10-15 01:59:53 -04:00
commit 09faeaa985
25 changed files with 996 additions and 830 deletions

View file

@ -69,67 +69,66 @@ DOCUMENTATION :: END
<%
data = defaultdict(lambda: 'Unknown', **session)
sk = data['session_key']
href = page('info', data['rating_key'])
parent_href = page('info', data['parent_rating_key'])
grandparent_href = page('info', data['grandparent_rating_key'])
href = page('info', data['rating_key'], server_id=data['server_id'])
parent_href = page('info', data['parent_rating_key'], server_id=data['server_id'])
grandparent_href = page('info', data['grandparent_rating_key'], server_id=data['server_id'])
user_href = page('user', data['user_id']) if data['user_id'] else '#'
season = short_season(data['parent_title'])
%>
<div class="dashboard-activity-instance" id="activity-instance-${sk}" data-key="${sk}" data-id="${data['session_id']}"
data-rating_key="${data['rating_key']}" data-parent_rating_key="${data['parent_rating_key']}" data-grandparent_rating_key="${data['grandparent_rating_key']}"
data-rating_key="${data['rating_key']}" data-server_id="${data['server_id']}" data-parent_rating_key="${data['parent_rating_key']}" data-grandparent_rating_key="${data['grandparent_rating_key']}"
data-guid="${data['guid']}">
<div class="dashboard-activity-container">
<%
if data['live']:
background_url = page('pms_image_proxy', data['art'], data['rating_key'], 500, 280, 40, '282828', 3, fallback='art-live', refresh=True)
background_url = page('pms_image_proxy', data['art'], data['rating_key'], 500, 280, 40, '282828', 3, fallback='art-live', refresh=True, server_id=data['server_id'])
elif data['channel_stream'] == 0:
background_url = page('pms_image_proxy', data['art'], data['rating_key'], 500, 280, 40, '282828', 3, fallback='art', refresh=True)
background_url = page('pms_image_proxy', data['art'], data['rating_key'], 500, 280, 40, '282828', 3, fallback='art', refresh=True, server_id=data['server_id'])
else:
background_url = page('pms_image_proxy', data['art'] or data['thumb'], data['rating_key'], 500, 280, 40, '282828', 3, fallback='art', refresh=True, clip=True)
background_url = page('pms_image_proxy', data['art'] or data['thumb'], data['rating_key'], 500, 280, 40, '282828', 3, fallback='art', refresh=True, clip=True, server_id=data['server_id'])
%>
<div id="background-${sk}" class="dashboard-activity-background" style="background-image: url(${background_url});">
<div class="dashboard-activity-poster-container hidden-xs">
% if data['media_type'] == 'track':
<div id="poster-${sk}-bg" class="dashboard-activity-poster" style="background-image: url(${page('pms_image_proxy', data['parent_thumb'], data['parent_rating_key'], 300, 300, 60, '282828', 3, fallback='cover', refresh=True)});"></div>
<div id="poster-${sk}-bg" class="dashboard-activity-poster" style="background-image: url(${page('pms_image_proxy', data['parent_thumb'], data['parent_rating_key'], 300, 300, 60, '282828', 3, fallback='cover', refresh=True, server_id=data['server_id'])});"></div>
% endif
% if data['live']:
% if data['media_type'] == 'movie':
<a id="poster-url-${sk}" href="${href}" title="${data['title']}">
<div id="poster-${sk}" class="dashboard-activity-poster" style="background-image: url(${page('pms_image_proxy', data['thumb'], data['rating_key'], 300, 450, fallback='poster-live', refresh=True)});"></div>
<div id="poster-${sk}" class="dashboard-activity-poster" style="background-image: url(${page('pms_image_proxy', data['thumb'], data['rating_key'], 300, 450, fallback='poster-live', refresh=True, server_id=data['server_id'])});"></div>
</a>
% elif data['media_type'] == 'episode':
<a id="poster-url-${sk}" href="${href}" title="${data['grandparent_title']}">
<div id="poster-${sk}" class="dashboard-activity-poster" style="background-image: url(${page('pms_image_proxy', data['grandparent_thumb'], data['rating_key'], 300, 450, fallback='poster-live', refresh=True)});"></div>
<div id="poster-${sk}" class="dashboard-activity-poster" style="background-image: url(${page('pms_image_proxy', data['grandparent_thumb'], data['rating_key'], 300, 450, fallback='poster-live', refresh=True, server_id=data['server_id'])});"></div>
</a>
% else:
<div id="poster-${sk}" class="dashboard-activity-poster" style="background-image: url(${page('pms_image_proxy', data['grandparent_thumb'] or data['thumb'], data['rating_key'], 300, 450, fallback='poster-live', refresh=True)});"></div>
<div id="poster-${sk}" class="dashboard-activity-poster" style="background-image: url(${page('pms_image_proxy', data['grandparent_thumb'] or data['thumb'], data['rating_key'], 300, 450, fallback='poster-live', refresh=True, server_id=data['server_id'])});"></div>
% endif
% elif data['channel_stream'] == 0:
% if data['media_type'] == 'movie':
<a id="poster-url-${sk}" href="${href}" title="${data['title']}">
<div id="poster-${sk}" class="dashboard-activity-poster" style="background-image: url(${page('pms_image_proxy', data['thumb'], data['rating_key'], 300, 450, fallback='poster', refresh=True)});"></div>
<div id="poster-${sk}" class="dashboard-activity-poster" style="background-image: url(${page('pms_image_proxy', data['thumb'], data['rating_key'], 300, 450, fallback='poster', refresh=True, server_id=data['server_id'])});"></div>
</a>
% elif data['media_type'] == 'episode':
<a id="poster-url-${sk}" href="${grandparent_href}" title="${data['grandparent_title']}">
<div id="poster-${sk}" class="dashboard-activity-poster" style="background-image: url(${page('pms_image_proxy', data['grandparent_thumb'], data['grandparent_rating_key'], 300, 450, fallback='poster', refresh=True)});"></div>
<div id="poster-${sk}" class="dashboard-activity-poster" style="background-image: url(${page('pms_image_proxy', data['grandparent_thumb'], data['grandparent_rating_key'], 300, 450, fallback='poster', refresh=True, server_id=data['server_id'])});"></div>
</a>
% elif data['media_type'] == 'track':
<a id="poster-url-${sk}" href="${parent_href}" title="${data['parent_title']}">
<div id="poster-${sk}" class="dashboard-activity-cover" style="background-image: url(${page('pms_image_proxy', data['parent_thumb'], data['parent_rating_key'], 300, 300, fallback='cover', refresh=True)});"></div>
<div id="poster-${sk}" class="dashboard-activity-cover" style="background-image: url(${page('pms_image_proxy', data['parent_thumb'], data['parent_rating_key'], 300, 300, fallback='cover', refresh=True, server_id=data['server_id'])});"></div>
</a>
% elif data['media_type'] in ('photo', 'clip'):
% if data['parent_thumb']:
<div id="poster-${sk}" class="dashboard-activity-poster" style="background-image: url(${page('pms_image_proxy', data['parent_thumb'], data['parent_rating_key'], 300, 450, fallback='poster', refresh=True)});"></div>
<div id="poster-${sk}" class="dashboard-activity-poster" style="background-image: url(${page('pms_image_proxy', data['parent_thumb'], data['parent_rating_key'], 300, 450, fallback='poster', refresh=True, server_id=data['server_id'])});"></div>
% else:
<div id="poster-${sk}" class="dashboard-activity-poster" style="background-image: url(${page('pms_image_proxy', data['thumb'], data['rating_key'], 300, 450, fallback='poster', refresh=True)});"></div>
<div id="poster-${sk}" class="dashboard-activity-poster" style="background-image: url(${page('pms_image_proxy', data['thumb'], data['rating_key'], 300, 450, fallback='poster', refresh=True, server_id=data['server_id'])});"></div>
% endif
% else:
<div id="poster-${sk}" class="dashboard-activity-poster" style="background-image: url(images/poster.png);"></div>
% endif
% else:
<div id="poster-${sk}" class="dashboard-activity-poster" style="background-image: url(${page('pms_image_proxy', data['channel_icon'], data['rating_key'], 300, 300, 60, '282828', 3, fallback='cover', refresh=True)});"></div>
<div id="poster-${sk}" class="dashboard-activity-cover" style="background-image: url(${page('pms_image_proxy', data['channel_icon'], data['rating_key'], 300, 300, fallback='cover', refresh=True)});"></div>
<div id="poster-${sk}" class="dashboard-activity-poster" style="background-image: url(${page('pms_image_proxy', data['channel_icon'], data['rating_key'], 300, 300, 60, '282828', 3, fallback='cover', refresh=True, server_id=data['server_id'])});"></div>
<div id="poster-${sk}" class="dashboard-activity-cover" style="background-image: url(${page('pms_image_proxy', data['channel_icon'], data['rating_key'], 300, 300, fallback='cover', refresh=True, server_id=data['server_id'])});"></div>
% endif
</div>
<div class="dashboard-activity-info-icon">
@ -141,7 +140,7 @@ DOCUMENTATION :: END
%>
<div id="platform-${sk}" class="dashboard-activity-info-platform${no_terminate} svg-icon platform-${data['platform_name']}" title="${data['platform']}"></div>
% if _session['user_group'] == 'admin' and plexpy.CONFIG.PMS_PLEXPASS and data['session_id']:
<div class="dashboard-activity-terminate-session" id="terminate-button-${sk}" data-key="${sk}" data-id="${data['session_id']}" data-toggle="tooltip" title="Terminate Stream">
<div class="dashboard-activity-terminate-session" id="terminate-button-${sk}" data-key="${sk}" data-id="${data['session_id']}" data-toggle="tooltip" data-server_id="${data['server_id']}" title="Terminate Stream">
<i class="fa fa-times" style="padding-top: 10px;"></i>
</div>
% endif
@ -179,6 +178,10 @@ DOCUMENTATION :: END
<span data-toggle="tooltip" title="Quality profile is only an estimate based on bitrate and may be incorrect"><i class="fa fa-exclamation-circle"></i></span>
</div>
</li>
<li class="dashboard-activity-info-item">
<div class="sub-heading">Server</div>
<div class="sub-value platform-right">${data['server_name']}(${data['server_ip']}:${data['server_port']})</div>
</li>
% if data['optimized_version'] == 1:
<li class="dashboard-activity-info-item">
<div class="sub-heading">Optimized</div>

View file

@ -70,17 +70,18 @@ DOCUMENTATION :: END
<%
stat_id = top_stat['stat_id']
row0 = top_stat['rows'][0]
row0['server_id']="test"
%>
<div class="dashboard-stats-instance" id="stats-instance-${stat_id}" data-stat_id="${stat_id}">
<div class="dashboard-stats-container">
% if stat_id in ('top_movies', 'popular_movies', 'top_tv', 'popular_tv', 'top_music', 'popular_music', 'last_watched'):
<% fallback = 'art-live' if row0['live'] else 'art' %>
<div id="stats-background-${stat_id}" class="dashboard-stats-background" style="background-image: url(${page('pms_image_proxy', row0['art'], row0['rating_key'], 500, 280, 40, '282828', 3, fallback=fallback)});">
<div id="stats-background-${stat_id}" class="dashboard-stats-background" style="background-image: url(${page('pms_image_proxy', row0['art'], row0['rating_key'], 500, 280, 40, '282828', 3, fallback=fallback, server_id=row0['server_id'])});">
% elif stat_id == 'top_libraries':
<% fallback = 'art-live' if row0['live'] else row0['library_art'] %>
<div id="stats-background-${stat_id}" class="dashboard-stats-background" style="background-image: url(${page('pms_image_proxy', row0['art'] or row0['library_art'], None, 500, 280, 40, '282828', 3, fallback=fallback)});" data-library_art="${row0['library_art']}">
<div id="stats-background-${stat_id}" class="dashboard-stats-background" style="background-image: url(${page('pms_image_proxy', row0['art'] or row0['library_art'], None, 500, 280, 40, '282828', 3, fallback=fallback, server_id=row0['server_id'])});" data-library_art="${row0['library_art']}">
% elif stat_id == 'top_users':
<div id="stats-background-${stat_id}" class="dashboard-stats-background" data-blurhash="${page('pms_image_proxy', row0['user_thumb'] or 'interfaces/default/images/gravatar-default.png', None, 100, 100, 40, '282828', 0, fallback='user')}">
<div id="stats-background-${stat_id}" class="dashboard-stats-background" data-blurhash="${page('pms_image_proxy', row0['user_thumb'] or 'interfaces/default/images/gravatar-default.png', None, 100, 100, 40, '282828', 0, fallback='user', server_id=row0['server_id'])}">
% elif stat_id == 'top_platforms':
<div id="stats-background-${stat_id}" class="dashboard-stats-background platform-${row0['platform_name']}-rgba no-image">
% else:
@ -89,7 +90,7 @@ DOCUMENTATION :: END
% if stat_id in ('top_movies', 'popular_movies', 'top_tv', 'popular_tv', 'top_music', 'popular_music', 'last_watched'):
<div class="dashboard-stats-poster-container hidden-xs">
% if stat_id in ('top_music', 'popular_music'):
<div id="stats-thumb-${stat_id}-bg" class="dashboard-stats-poster" style="background-image: url(${page('pms_image_proxy', row0['thumb'], row0['rating_key'], 300, 300, 60, '282828', 3, fallback='cover')});"></div>
<div id="stats-thumb-${stat_id}-bg" class="dashboard-stats-poster" style="background-image: url(${page('pms_image_proxy', row0['thumb'], row0['rating_key'], 300, 300, 60, '282828', 3, fallback='cover', server_id=row0['server_id'])});"></div>
% endif
<%
height, fallback = ('450', 'poster')
@ -101,24 +102,24 @@ DOCUMENTATION :: END
href = '#'
if row0['rating_key']:
if row0['live']:
href = page('info', row0['rating_key'], row0['guid'], history=True, live=row0['live'])
href = page('info', row0['rating_key'], row0['guid'], history=True, live=row0['live'], server_id=row0['server_id'])
else:
href = page('info', row0['rating_key'], history=True)
href = page('info', row0['rating_key'], history=True, server_id=row0['server_id'])
%>
<a id="stats-thumb-url-${stat_id}" href="${href}" title="${row0['title']}">
<div id="stats-thumb-${stat_id}" class="dashboard-stats-${fallback.split('-')[0]}" style="background-image: url(${page('pms_image_proxy', row0['thumb'], row0['grandparent_rating_key'] or row0['rating_key'], 300, height, fallback=fallback)});"></div>
<div id="stats-thumb-${stat_id}" class="dashboard-stats-${fallback.split('-')[0]}" style="background-image: url(${page('pms_image_proxy', row0['thumb'], row0['grandparent_rating_key'] or row0['rating_key'], 300, height, fallback=fallback, server_id=row0['server_id'])});"></div>
</a>
</div>
% elif stat_id == 'top_libraries':
% if row0['library_thumb'].startswith('http'):
<div id="stats-thumb-${stat_id}" class="dashboard-stats-flat hidden-xs" style="background-image: url(${page('pms_image_proxy', row0['library_thumb'], None, 100, 100, fallback='cover')});"></div>
<div id="stats-thumb-${stat_id}" class="dashboard-stats-flat hidden-xs" style="background-image: url(${page('pms_image_proxy', row0['library_thumb'], None, 100, 100, fallback='cover', server_id=row0['server_id'])});"></div>
% else:
<div id="stats-thumb-${stat_id}" class="dashboard-stats-flat svg-icon library-${row0['section_type']} hidden-xs"></div>
% endif
% elif stat_id == 'top_users':
<% user_href = page('user', row0['user_id']) if row0['user_id'] else '#' %>
<a id="stats-thumb-url-${stat_id}" href="${user_href}" title="${row0['user']}" class="hidden-xs">
<div id="stats-thumb-${stat_id}" class="dashboard-stats-circle" style="background-image: url(${page('pms_image_proxy', row0['user_thumb'] or 'interfaces/default/images/gravatar-default.png', None, 100, 100, fallback='user')})"></div>
<div id="stats-thumb-${stat_id}" class="dashboard-stats-circle" style="background-image: url(${page('pms_image_proxy', row0['user_thumb'] or 'interfaces/default/images/gravatar-default.png', None, 100, 100, fallback='user', server_id=row0['server_id'])})"></div>
</a>
% elif stat_id == 'top_platforms':
<div id="stats-thumb-${stat_id}" class="dashboard-stats-flat svg-icon platform-${row0['platform_name']} transparent hidden-xs"></div>
@ -157,15 +158,15 @@ DOCUMENTATION :: END
href = '#'
if row['rating_key']:
if row['live']:
href = page('info', row['rating_key'], row['guid'], history=True, live=row['live'])
href = page('info', row['rating_key'], row['guid'], history=True, live=row['live'], server_id=row['server_id'])
else:
href = page('info', row['rating_key'], history=True)
href = page('info', row['rating_key'], history=True, server_id=row['server_id'])
%>
<a href="${href}" title="${row['title']}">
${row['title']}
</a>
% elif stat_id == 'top_libraries':
<% library_href = page('library', row['section_id']) %>
<% library_href = page('library', row['section_id'], server_id=row['server_id']) %>
<a href="${library_href}" title="${row['section_name']}">
${row['section_name']}
</a>

View file

@ -71,9 +71,6 @@
<div class="col-md-12">
<div class="home-padded-header padded-header" id="library-statistics-header">
<h3 class="pull-left">Library Statistics</h3>
<div class="button-bar">
<span class="btn btn-dark active" style="cursor: default">${config['pms_name']}</span>
</div>
</div>
</div>
</div>
@ -757,7 +754,8 @@
data: {
session_key: key,
session_id: session_id,
message: message
message: message,
server_id: "test1"
},
async: true,
success: function (data) {

View file

@ -93,7 +93,7 @@ DOCUMENTATION :: END
<div class="row">
% if data['media_type'] not in ('photo_album', 'photo', 'playlist'):
<% fallback = 'art-live-full' if data['live'] else None %>
<div class="art-face" style="background-image:url(${page('pms_image_proxy', data['art'], data['rating_key'], 1920, 1080, fallback=fallback)})"></div>
<div class="art-face" style="background-image:url(${page('pms_image_proxy', data['art'], data['rating_key'], 1920, 1080, fallback=fallback, server_id=data['server_id'])})"></div>
% endif
% if _session['user_group'] == 'admin':
<span class="overlay-refresh-image info-art" title="Refresh background image"><i class="fa fa-refresh refresh_pms_image"></i></span>
@ -104,7 +104,7 @@ DOCUMENTATION :: END
<div class="summary-navbar-list">
<ul class="list-unstyled breadcrumb">
% if data['live']:
<li><a href="${page('library', data['section_id'])}">${data['library_name']}</a></li>
<li><a href="${page('library', data['section_id'], server_id=data['server_id'])}">${data['library_name']}</a></li>
<span class="breadcrumb-arrow"><i class="fa fa-chevron-right"></i></span>
% if data['media_type'] == 'movie':
<li class="active metadata-xml">${data['title']}</li>
@ -120,57 +120,57 @@ DOCUMENTATION :: END
% endif
% endif
% elif data['media_type'] in ('movie', 'collection'):
<li><a href="${page('library', data['section_id'])}">${data['library_name']}</a></li>
<li><a href="${page('library', data['section_id'], server_id=data['server_id'])}">${data['library_name']}</a></li>
<span class="breadcrumb-arrow"><i class="fa fa-chevron-right"></i></span>
<li class="active metadata-xml">${data['title']}</li>
% elif data['media_type'] == 'show':
<li><a href="${page('library', data['section_id'])}">${data['library_name']}</a></li>
<li><a href="${page('library', data['section_id'], server_id=data['server_id'])}">${data['library_name']}</a></li>
<span class="breadcrumb-arrow"><i class="fa fa-chevron-right"></i></span>
<li class="active metadata-xml">${data['title']}</li>
% elif data['media_type'] == 'season':
<li class="hidden-xs hidden-sm"><a href="${page('library', data['section_id'])}">${data['library_name']}</a></li>
<li class="hidden-xs hidden-sm"><a href="${page('library', data['section_id'], server_id=data['server_id'])}">${data['library_name']}</a></li>
<span class="breadcrumb-arrow"><i class="fa fa-chevron-right"></i></span>
<li><a href="${page('info', data['parent_rating_key'])}">${data['parent_title']}</a></li>
<li><a href="${page('info', data['parent_rating_key'], server_id=data['server_id'])}">${data['parent_title']}</a></li>
<span class="breadcrumb-arrow"><i class="fa fa-chevron-right"></i></span>
<li class="active metadata-xml">${data['title']}</li>
% elif data['media_type'] == 'episode':
<li class="hidden-xs hidden-sm"><a href="${page('library', data['section_id'])}">${data['library_name']}</a></li>
<li class="hidden-xs hidden-sm"><a href="${page('library', data['section_id'], server_id=data['server_id'])}">${data['library_name']}</a></li>
<span class="breadcrumb-arrow"><i class="fa fa-chevron-right"></i></span>
<li class="hidden-xs hidden-sm"><a href="${page('info', data['grandparent_rating_key'])}">${data['grandparent_title']}</a></li>
<li class="hidden-xs hidden-sm"><a href="${page('info', data['grandparent_rating_key'], server_id=data['server_id'])}">${data['grandparent_title']}</a></li>
<span class="breadcrumb-arrow"><i class="fa fa-chevron-right"></i></span>
<li><a href="${page('info', data['parent_rating_key'])}">${data['parent_title']}</a></li>
<li><a href="${page('info', data['parent_rating_key'], server_id=data['server_id'])}">${data['parent_title']}</a></li>
<span class="breadcrumb-arrow"><i class="fa fa-chevron-right"></i></span>
<li class="active metadata-xml">Episode ${data['media_index']} - ${data['title']}</li>
% elif data['media_type'] == 'artist':
<li><a href="${page('library', data['section_id'])}">${data['library_name']}</a></li>
<li><a href="${page('library', data['section_id'], server_id=data['server_id'])}">${data['library_name']}</a></li>
<span class="breadcrumb-arrow"><i class="fa fa-chevron-right"></i></span>
<li class="active metadata-xml">${data['title']}</li>
% elif data['media_type'] == 'album':
<li class="hidden-xs hidden-sm"><a href="${page('library', data['section_id'])}">${data['library_name']}</a></li>
<li class="hidden-xs hidden-sm"><a href="${page('library', data['section_id'], server_id=data['server_id'])}">${data['library_name']}</a></li>
<span class="breadcrumb-arrow"><i class="fa fa-chevron-right"></i></span>
<li><a href="${page('info', data['parent_rating_key'])}">${data['parent_title']}</a></li>
<li><a href="${page('info', data['parent_rating_key'], server_id=data['server_id'])}">${data['parent_title']}</a></li>
<span class="breadcrumb-arrow"><i class="fa fa-chevron-right"></i></span>
<li class="active metadata-xml">${data['title']}</li>
% elif data['media_type'] == 'track':
<li class="hidden-xs hidden-sm"><a href="${page('library', data['section_id'])}">${data['library_name']}</a></li>
<li class="hidden-xs hidden-sm"><a href="${page('library', data['section_id'], server_id=data['server_id'])}">${data['library_name']}</a></li>
<span class="breadcrumb-arrow"><i class="fa fa-chevron-right"></i></span>
<li class="hidden-xs hidden-sm"><a href="${page('info', data['grandparent_rating_key'])}">${data['grandparent_title']}</a></li>
<li class="hidden-xs hidden-sm"><a href="${page('info', data['grandparent_rating_key'], server_id=data['server_id'])}">${data['grandparent_title']}</a></li>
<span class="breadcrumb-arrow"><i class="fa fa-chevron-right"></i></span>
<li><a href="${page('info', data['parent_rating_key'])}">${data['parent_title']}</a></li>
<li><a href="${page('info', data['parent_rating_key'], server_id=data['server_id'])}">${data['parent_title']}</a></li>
<span class="breadcrumb-arrow"><i class="fa fa-chevron-right"></i></span>
<li class="active metadata-xml">Track ${data['media_index']} - ${data['title']}</li>
% elif data['media_type'] == 'photo_album':
<li><a href="${page('library', data['section_id'])}">${data['library_name']}</a></li>
<li><a href="${page('library', data['section_id'], server_id=data['server_id'])}">${data['library_name']}</a></li>
<span class="breadcrumb-arrow"><i class="fa fa-chevron-right"></i></span>
% if data['parent_title']:
<li><a href="${page('info', data['parent_rating_key'])}">${data['parent_title']}</a></li>
<li><a href="${page('info', data['parent_rating_key'], server_id=data['server_id'])}">${data['parent_title']}</a></li>
<span class="breadcrumb-arrow"><i class="fa fa-chevron-right"></i></span>
% endif
<li class="active metadata-xml">${data['title']}</li>
% elif data['media_type'] in ('photo', 'clip'):
<li class="hidden-xs hidden-sm"><a href="${page('library', data['section_id'])}">${data['library_name']}</a></li>
<li class="hidden-xs hidden-sm"><a href="${page('library', data['section_id'], server_id=data['server_id'])}">${data['library_name']}</a></li>
<span class="breadcrumb-arrow"><i class="fa fa-chevron-right"></i></span>
<li><a href="${page('info', data['parent_rating_key'])}">${data['parent_title']}</a></li>
<li><a href="${page('info', data['parent_rating_key'], server_id=data['server_id'])}">${data['parent_title']}</a></li>
<span class="breadcrumb-arrow"><i class="fa fa-chevron-right"></i></span>
<li class="active metadata-xml">${data['title']}</li>
% elif data['media_type'] == 'playlist':
@ -178,7 +178,7 @@ DOCUMENTATION :: END
<li><a href="${page('user', user_info.get('user_id'))}">${user_info.get('friendly_name')}</a></li>
<span class="breadcrumb-arrow"><i class="fa fa-chevron-right"></i></span>
% elif data['section_id']:
<li><a href="${page('library', data['section_id'])}">${data['library_name']}</a></li>
<li><a href="${page('library', data['section_id'], server_id=data['server_id'])}">${data['library_name']}</a></li>
<span class="breadcrumb-arrow"><i class="fa fa-chevron-right"></i></span>
% endif
<li class="active metadata-xml">${data['title']}</li>
@ -192,21 +192,21 @@ DOCUMENTATION :: END
<div class="summary-content-poster hidden-xs hidden-sm">
<% legacy = '&legacy=1' if data['media_type'] in ('photo_album', 'photo', 'clip') else '' %>
% if data['media_type'] in ('track', 'photo'):
<a href="${config['pms_web_url']}#!/server/${config['pms_identifier']}/details?key=%2Flibrary%2Fmetadata%2F${data['parent_rating_key']}${legacy}" target="_blank" rel="noreferrer" title="View on Plex Web">
<a href="${config['pms_web_url']}#!/server/${data['server_id']}/details?key=%2Flibrary%2Fmetadata%2F${data['parent_rating_key']}${legacy}" target="_blank" rel="noreferrer" title="View on Plex Web">
% elif data['media_type'] == 'playlist':
<a href="${config['pms_web_url']}#!/server/${config['pms_identifier']}/playlist?key=%2Fplaylists%2F${data['rating_key']}" target="_blank" rel="noreferrer" title="View on Plex Web">
<a href="${config['pms_web_url']}#!/server/${data['server_id']}/playlist?key=%2Fplaylists%2F${data['rating_key']}" target="_blank" rel="noreferrer" title="View on Plex Web">
% elif not data['live']:
<a href="${config['pms_web_url']}#!/server/${config['pms_identifier']}/details?key=%2Flibrary%2Fmetadata%2F${data['rating_key']}${legacy}" target="_blank" rel="noreferrer" title="View on Plex Web">
<a href="${config['pms_web_url']}#!/server/${data['server_id']}/details?key=%2Flibrary%2Fmetadata%2F${data['rating_key']}${legacy}" target="_blank" rel="noreferrer" title="View on Plex Web">
% endif
% if data['live']:
<div class="summary-poster-face" style="background-image: url(${page('pms_image_proxy', data['grandparent_thumb'] or data['thumb'], data['rating_key'], 300, 450, fallback='poster-live')});">
<div class="summary-poster-face" style="background-image: url(${page('pms_image_proxy', data['grandparent_thumb'] or data['thumb'], data['rating_key'], 300, 450, fallback='poster-live', server_id=data['server_id'])});">
<div class="summary-poster-face-overlay">
<span></span>
</div>
</div>
% else:
% if data['media_type'] == 'episode':
<div class="summary-poster-face-episode" style="background-image: url(${page('pms_image_proxy', data['thumb'], data['rating_key'], 500, 280, fallback='art')});">
<div class="summary-poster-face-episode" style="background-image: url(${page('pms_image_proxy', data['thumb'], data['rating_key'], 500, 280, fallback='art', server_id=data['server_id'])});">
<div class="summary-poster-face-overlay">
<span></span>
</div>
@ -215,7 +215,7 @@ DOCUMENTATION :: END
<span class="overlay-refresh-image" title="Refresh image"><i class="fa fa-refresh refresh_pms_image"></i></span>
% endif
% elif data['media_type'] in ('artist', 'album', 'track', 'playlist', 'photo_album', 'photo', 'clip') or data['sub_media_type'] in ('artist', 'album', 'track'):
<div class="summary-poster-face-track" style="background-image: url(${page('pms_image_proxy', data['thumb'], data['rating_key'], 300, 300, fallback='cover')});">
<div class="summary-poster-face-track" style="background-image: url(${page('pms_image_proxy', data['thumb'], data['rating_key'], 300, 300, fallback='cover', server_id=data['server_id'])});">
<div class="summary-poster-face-overlay">
<span></span>
</div>
@ -227,7 +227,7 @@ DOCUMENTATION :: END
<span class="overlay-refresh-image" title="Refresh image"><i class="fa fa-refresh refresh_pms_image"></i></span>
% endif
% else:
<div class="summary-poster-face" style="background-image: url(${page('pms_image_proxy', data['thumb'], data['rating_key'], 300, 450, fallback='poster')});">
<div class="summary-poster-face" style="background-image: url(${page('pms_image_proxy', data['thumb'], data['rating_key'], 300, 450, fallback='poster', server_id=data['server_id'])});">
<div class="summary-poster-face-overlay">
<span></span>
</div>
@ -258,21 +258,21 @@ DOCUMENTATION :: END
% elif data['media_type'] in ('movie', 'show', 'artist', 'collection', 'playlist', 'photo_album'):
<h1>&nbsp;</h1><h1>${data['title']}</h1>
% elif data['media_type'] == 'season':
<h1>&nbsp;</h1><h1><a href="${page('info', data['parent_rating_key'])}">${data['parent_title']}</a></h1>
<h1>&nbsp;</h1><h1><a href="${page('info', data['parent_rating_key'], server_id=data['server_id'])}">${data['parent_title']}</a></h1>
<h3 class="hidden-xs">${season}</h3>
% elif data['media_type'] == 'episode':
<h1><a href="${page('info', data['grandparent_rating_key'])}">${data['grandparent_title']}</a></h1>
<h1><a href="${page('info', data['grandparent_rating_key'], server_id=data['server_id'])}">${data['grandparent_title']}</a></h1>
<h2>${data['title']}</h2>
<h3 class="hidden-xs">${season} &middot; E${data['media_index']}</h3>
% elif data['media_type'] == 'album':
<h1><a href="${page('info', data['parent_rating_key'])}">${data['parent_title']}</a></h1>
<h1><a href="${page('info', data['parent_rating_key'], server_id=data['server_id'])}">${data['parent_title']}</a></h1>
<h2>${data['title']}</h2>
% elif data['media_type'] == 'track':
<h1><a href="${page('info', data['grandparent_rating_key'])}">${data['grandparent_title']}</a></h1>
<h2><a href="${page('info', data['parent_rating_key'])}">${data['parent_title']}</a> - ${data['title']}</h2>
<h1><a href="${page('info', data['grandparent_rating_key'], server_id=data['server_id'])}">${data['grandparent_title']}</a></h1>
<h2><a href="${page('info', data['parent_rating_key'], server_id=data['server_id'])}">${data['parent_title']}</a> - ${data['title']}</h2>
<h3 class="hidden-xs">T${data['media_index']}</h3>
% elif data['media_type'] in ('photo', 'clip'):
<h1><a href="${page('info', data['parent_rating_key'])}">${data['parent_title']}</a></h1>
<h1><a href="${page('info', data['parent_rating_key'], server_id=data['server_id'])}">${data['parent_title']}</a></h1>
<h2>${data['title']}</h2>
% endif
</div>
@ -878,17 +878,18 @@ DOCUMENTATION :: END
transcode_decision: transcode_decision,
user_id: "${history_user_id}",
% if data['live']:
guid: "${data['guid']}
guid: "${data['guid']}",
% elif data['media_type'] in ('show', 'artist'):
grandparent_rating_key: "${data['rating_key']}"
grandparent_rating_key: "${data['rating_key']}",
% elif data['media_type'] in ('season', 'album'):
parent_rating_key: "${data['rating_key']}"
parent_rating_key: "${data['rating_key']}",
% elif data['media_type'] in ('movie', 'episode', 'track'):
rating_key: "${data['rating_key']}"
rating_key: "${data['rating_key']}",
% elif data['media_type'] in ('collection', 'playlist'):
media_type: "${data['media_type']}",
rating_key: "${data['rating_key']}"
rating_key: "${data['rating_key']}",
% endif
server_id: "${data['server_id']}"
};
}
}
@ -932,7 +933,8 @@ DOCUMENTATION :: END
async: true,
data: {
rating_key: "${data['rating_key']}",
media_type: "${data['media_type']}"
media_type: "${data['media_type']}",
server_id: "${data['server_id']}"
},
complete: function(xhr, status) {
$("#children-list").html(xhr.responseText);
@ -948,7 +950,8 @@ DOCUMENTATION :: END
async: true,
data: {
rating_key: "${data['rating_key']}",
media_type: "${data['media_type']}"
media_type: "${data['media_type']}",
server_id: "${data['server_id']}"
},
complete: function(xhr, status) {
$("#watch-time-stats").html(xhr.responseText);
@ -960,7 +963,8 @@ DOCUMENTATION :: END
async: true,
data: {
rating_key: "${data['rating_key']}",
media_type: "${data['media_type']}"
media_type: "${data['media_type']}",
server_id: "${data['server_id']}"
},
complete: function(xhr, status) {
$("#user-stats").html(xhr.responseText);
@ -976,7 +980,8 @@ DOCUMENTATION :: END
async: true,
data: {
rating_key: "${data['rating_key']}",
title: "${data['title']}"
title: "${data['title']}",
server_id: "${data['server_id']}"
},
complete: function(xhr, status) {
$("#collection-related-list-container").html(xhr.responseText).show();
@ -1064,7 +1069,7 @@ DOCUMENTATION :: END
data: function ( d ) {
return {
json_data: JSON.stringify( d ),
rating_key: "${data['rating_key']}"
rating_key: "${data['rating_key']}",
};
}
};

View file

@ -48,61 +48,61 @@ DOCUMENTATION :: END
<span class="item-children-list-item-title">
% if child['media_type'] == 'movie':
<span class="media-type-tooltip" data-toggle="tooltip" title="Movie"><i class="fa fa-film fa-fw"></i></span>
<a href="${page('info', child['rating_key'])}" title="${child['title']}">
<span class="thumb-tooltip" data-toggle="popover" data-img="${page('pms_image_proxy', child['thumb'], child['rating_key'], 300, 450, fallback='poster')}" data-height="120" data-width="80">
<a href="${page('info', child['rating_key'], server_id=child['server_id'])}" title="${child['title']}">
<span class="thumb-tooltip" data-toggle="popover" data-img="${page('pms_image_proxy', child['thumb'], child['rating_key'], 300, 450, fallback='poster', server_id=child['server_id'])}" data-height="120" data-width="80">
${child['title']}
</span>
</a>
<span class="text-muted"> (${child['year']})</span>
% elif child['media_type'] == 'episode':
<span class="media-type-tooltip" data-toggle="tooltip" title="Episode"><i class="fa fa-television fa-fw"></i></span>
<a href="${page('info', child['grandparent_rating_key'])}" title="${child['grandparent_title']}">
<span class="thumb-tooltip" data-toggle="popover" data-img="${page('pms_image_proxy', child['grandparent_thumb'], child['grandparent_rating_key'], 300, 450, fallback='poster')}" data-height="120" data-width="80">
<a href="${page('info', child['grandparent_rating_key'], server_id=child['server_id'])}" title="${child['grandparent_title']}">
<span class="thumb-tooltip" data-toggle="popover" data-img="${page('pms_image_proxy', child['grandparent_thumb'], child['grandparent_rating_key'], 300, 450, fallback='poster', server_id=child['server_id'])}" data-height="120" data-width="80">
${child['grandparent_title']}
</span>
</a> -
<a href="${page('info', child['rating_key'])}" title="${child['title']}">
<span class="thumb-tooltip" data-toggle="popover" data-img="${page('pms_image_proxy', child['parent_thumb'], child['parent_rating_key'], 300, 450, fallback='poster')}" data-height="120" data-width="80">
<a href="${page('info', child['rating_key'], server_id=child['server_id'])}" title="${child['title']}">
<span class="thumb-tooltip" data-toggle="popover" data-img="${page('pms_image_proxy', child['parent_thumb'], child['parent_rating_key'], 300, 450, fallback='poster', server_id=child['server_id'])}" data-height="120" data-width="80">
${child['title']}
</span>
</a>
<span class="text-muted"> (<a class="no-highlight" href="${page('info', child['parent_rating_key'])}" title="${child['parent_title']}">${short_season(child['parent_title'])}</a> &middot; <a class="no-highlight" href="${page('info', child['rating_key'])}" title="${child['title']}">E${child['media_index']}</a>)</span>
<span class="text-muted"> (<a class="no-highlight" href="${page('info', child['parent_rating_key'], server_id=child['server_id'])}" title="${child['parent_title']}">${short_season(child['parent_title'])}</a> &middot; <a class="no-highlight" href="${page('info', child['rating_key'], server_id=child['server_id'])}" title="${child['title']}">E${child['media_index']}</a>)</span>
% elif child['media_type'] == 'track':
<span class="media-type-tooltip" data-toggle="tooltip" title="Track"><i class="fa fa-music fa-fw"></i></span>
<a href="${page('info', child['rating_key'])}" title="${child['title']}">
<span class="thumb-tooltip" data-toggle="popover" data-img="${page('pms_image_proxy', child['parent_thumb'], child['parent_rating_key'], 300, 300, fallback='cover')}" data-height="80" data-width="80">
<a href="${page('info', child['rating_key'], server_id=child['server_id'])}" title="${child['title']}">
<span class="thumb-tooltip" data-toggle="popover" data-img="${page('pms_image_proxy', child['parent_thumb'], child['parent_rating_key'], 300, 300, fallback='cover', server_id=child['server_id'])}" data-height="80" data-width="80">
${child['title']}
</span>
</a> -
<a href="${page('info', child['grandparent_rating_key'])}" title="${child['grandparent_title']}">
<span class="thumb-tooltip" data-toggle="popover" data-img="${page('pms_image_proxy', child['grandparent_thumb'], child['grandparent_rating_key'], 300, 300, fallback='cover')}" data-height="80" data-width="80">
<span class="thumb-tooltip" data-toggle="popover" data-img="${page('pms_image_proxy', child['grandparent_thumb'], child['grandparent_rating_key'], 300, 300, fallback='cover', server_id=child['server_id'])}" data-height="80" data-width="80">
${child['grandparent_title']}
</span>
</a>
<span class="text-muted"> (<a class="no-highlight" href="${page('info', child['parent_rating_key'])}" title="${child['parent_title']}">${child['parent_title']}</a>)</span>
<span class="text-muted"> (<a class="no-highlight" href="${page('info', child['parent_rating_key'], server_id=child['server_id'])}" title="${child['parent_title']}">${child['parent_title']}</a>)</span>
% elif child['media_type'] == 'photo':
<span class="media-type-tooltip" data-toggle="tooltip" title="Photo"><i class="fa fa-picture-o fa-fw"></i></span>
<a href="${page('info', child['rating_key'])}" title="${child['title']}">
<span class="thumb-tooltip" data-toggle="popover" data-img="${page('pms_image_proxy', child['thumb'], child['rating_key'], 300, 300, fallback='cover')}" data-height="80" data-width="80">
<a href="${page('info', child['rating_key'], server_id=child['server_id'])}" title="${child['title']}">
<span class="thumb-tooltip" data-toggle="popover" data-img="${page('pms_image_proxy', child['thumb'], child['rating_key'], 300, 300, fallback='cover', server_id=child['server_id'])}" data-height="80" data-width="80">
${child['title']}
</span>
</a>
% if child['grandparent_title']:
- <a href="${page('info', child['grandparent_rating_key'])}" title="${child['grandparent_title']}">
<span class="thumb-tooltip" data-toggle="popover" data-img="${page('pms_image_proxy', child['grandparent_thumb'], child['grandparent_rating_key'], 300, 300, fallback='cover')}" data-height="80" data-width="80">
- <a href="${page('info', child['grandparent_rating_key'], server_id=child['server_id'])}" title="${child['grandparent_title']}">
<span class="thumb-tooltip" data-toggle="popover" data-img="${page('pms_image_proxy', child['grandparent_thumb'], child['grandparent_rating_key'], 300, 300, fallback='cover', server_id=child['server_id'])}" data-height="80" data-width="80">
${child['grandparent_title']}
</span>
</a>
% endif
<span class="text-muted"> (<a class="no-highlight" href="${page('info', child['parent_rating_key'])}" title="${child['parent_title']}">${child['parent_title']}</a>)</span>
<span class="text-muted"> (<a class="no-highlight" href="${page('info', child['parent_rating_key'], server_id=child['server_id'])}" title="${child['parent_title']}">${child['parent_title']}</a>)</span>
% elif child['media_type'] == 'clip':
<span class="media-type-tooltip" data-toggle="tooltip" title="Video"><i class="fa fa-video-camera fa-fw"></i></span>
<a href="${page('info', child['rating_key'])}" title="${child['title']}">
<span class="thumb-tooltip" data-toggle="popover" data-img="${page('pms_image_proxy', child['thumb'], child['rating_key'], 300, 300, fallback='cover')}" data-height="80" data-width="80">
<a href="${page('info', child['rating_key'], server_id=child['server_id'])}" title="${child['title']}">
<span class="thumb-tooltip" data-toggle="popover" data-img="${page('pms_image_proxy', child['thumb'], child['rating_key'], 300, 300, fallback='cover', server_id=child['server_id'])}" data-height="80" data-width="80">
${child['title']}
</span>
</a>
<span class="text-muted"> (<a class="no-highlight" href="${page('info', child['parent_rating_key'])}" title="${child['parent_title']}">${child['parent_title']}</a>)</span>
<span class="text-muted"> (<a class="no-highlight" href="${page('info', child['parent_rating_key'], server_id=child['server_id'])}" title="${child['parent_title']}">${child['parent_title']}</a>)</span>
% endif
</span>
% if child['duration']:
@ -113,9 +113,9 @@ DOCUMENTATION :: END
% endif
</div>
% elif child['media_type'] == 'movie':
<a href="${page('info', child['rating_key'])}" title="${child['title']}">
<a href="${page('info', child['rating_key'], server_id=child['server_id'])}" title="${child['title']}">
<div class="item-children-poster">
<div class="item-children-poster-face poster-item" style="background-image: url(${page('pms_image_proxy', child['thumb'], child['rating_key'], 300, 450, fallback='poster')});"></div>
<div class="item-children-poster-face poster-item" style="background-image: url(${page('pms_image_proxy', child['thumb'], child['rating_key'], 300, 450, fallback='poster', server_id=child['server_id'])});"></div>
% if _session['user_group'] == 'admin':
<span class="overlay-refresh-image" title="Refresh image"><i class="fa fa-refresh refresh_pms_image"></i></span>
% endif
@ -123,14 +123,14 @@ DOCUMENTATION :: END
</a>
<div class="item-children-instance-text-wrapper poster-item">
<h3>
<a href="${page('info', child['rating_key'])}" title="${child['title']}">${child['title']}</a>
<a href="${page('info', child['rating_key'], server_id=child['server_id'])}" title="${child['title']}">${child['title']}</a>
</h3>
<h3 class="text-muted">${child['year']}</h3>
</div>
% elif child['media_type'] == 'show':
<a href="${page('info', child['rating_key'])}" title="${child['title']}">
<a href="${page('info', child['rating_key'], server_id=child['server_id'])}" title="${child['title']}">
<div class="item-children-poster">
<div class="item-children-poster-face poster-item" style="background-image: url(${page('pms_image_proxy', child['thumb'], child['rating_key'], 300, 450, fallback='poster')});"></div>
<div class="item-children-poster-face poster-item" style="background-image: url(${page('pms_image_proxy', child['thumb'], child['rating_key'], 300, 450, fallback='poster', server_id=child['server_id'])});"></div>
% if _session['user_group'] == 'admin':
<span class="overlay-refresh-image" title="Refresh image"><i class="fa fa-refresh refresh_pms_image"></i></span>
% endif
@ -138,16 +138,16 @@ DOCUMENTATION :: END
</a>
<div class="item-children-instance-text-wrapper poster-item">
<h3>
<a href="${page('info', child['rating_key'])}" title="${child['title']}">${child['title']}</a>
<a href="${page('info', child['rating_key'], server_id=child['server_id'])}" title="${child['title']}">${child['title']}</a>
</h3>
</div>
% elif child['media_type'] == 'season':
<a href="${page('info', child['rating_key'])}" title="${child['title']}">
<a href="${page('info', child['rating_key'], server_id=child['server_id'])}" title="${child['title']}">
<div class="item-children-poster">
% if child['thumb']:
<div class="item-children-poster-face poster-item" style="background-image: url(${page('pms_image_proxy', child['thumb'], child['rating_key'], 300, 450, fallback='poster')});">
<div class="item-children-poster-face poster-item" style="background-image: url(${page('pms_image_proxy', child['thumb'], child['rating_key'], 300, 450, fallback='poster', server_id=child['server_id'])});">
% else:
<div class="item-children-poster-face poster-item" style="background-image: url(${page('pms_image_proxy', child['parent_thumb'], child['parent_rating_key'], 300, 450, fallback='poster')});">
<div class="item-children-poster-face poster-item" style="background-image: url(${page('pms_image_proxy', child['parent_thumb'], child['parent_rating_key'], 300, 450, fallback='poster', server_id=child['server_id'])});">
% endif
<div class="item-children-card-overlay">
<div class="item-children-overlay-text">
@ -162,18 +162,18 @@ DOCUMENTATION :: END
</a>
<div class="item-children-instance-text-wrapper poster-item">
<h3>
<a href="${page('info', child['rating_key'])}" title="${child['title']}">${child['title']}</a>
<a href="${page('info', child['rating_key'], server_id=child['server_id'])}" title="${child['title']}">${child['title']}</a>
</h3>
% if media_type == 'collection':
<h3 class="text-muted">
<a class="text-muted" href="${page('info', child['parent_rating_key'])}" title="${child['parent_title']}">${child['parent_title']}</a>
<a class="text-muted" href="${page('info', child['parent_rating_key'], server_id=child['server_id'])}" title="${child['parent_title']}">${child['parent_title']}</a>
</h3>
% endif
</div>
% elif child['media_type'] == 'episode':
<a href="${page('info', child['rating_key'])}" title="Episode ${child['media_index']}">
<a href="${page('info', child['rating_key'], server_id=child['server_id'])}" title="Episode ${child['media_index']}">
<div class="item-children-poster">
<div class="item-children-poster-face episode-item" style="background-image: url(${page('pms_image_proxy', child['thumb'], child['rating_key'], 500, 280, fallback='art')});">
<div class="item-children-poster-face episode-item" style="background-image: url(${page('pms_image_proxy', child['thumb'], child['rating_key'], 500, 280, fallback='art', server_id=child['server_id'])});">
<div class="item-children-card-overlay">
<div class="item-children-overlay-text">
Episode ${child['media_index'] or child['originally_available_at']}
@ -187,22 +187,22 @@ DOCUMENTATION :: END
</a>
<div class="item-children-instance-text-wrapper episode-item">
<h3>
<a href="${page('info', child['rating_key'])}" title="${child['title']}">${child['title']}</a>
<a href="${page('info', child['rating_key'], server_id=child['server_id'])}" title="${child['title']}">${child['title']}</a>
</h3>
% if media_type == 'collection':
<h3 class="text-muted">
<a href="${page('info', child['grandparent_rating_key'])}" title="${child['grandparent_title']}">${child['grandparent_title']}</a>
<a href="${page('info', child['grandparent_rating_key'], server_id=child['server_id'])}" title="${child['grandparent_title']}">${child['grandparent_title']}</a>
</h3>
<h3 class="text-muted">
<a href="${page('info', child['parent_rating_key'])}" title="${child['parent_title']}">${short_season(child['parent_title'])}</a>
&middot; <a href="${page('info', child['rating_key'])}" title="Episode ${child['media_index']}">E${child['media_index']}</a>
<a href="${page('info', child['parent_rating_key'], server_id=child['server_id'])}" title="${child['parent_title']}">${short_season(child['parent_title'])}</a>
&middot; <a href="${page('info', child['rating_key'], server_id=child['server_id'])}" title="Episode ${child['media_index']}">E${child['media_index']}</a>
</h3>
% endif
</div>
% elif child['media_type'] == 'artist':
<a href="${page('info', child['rating_key'])}" title="${child['title']}">
<a href="${page('info', child['rating_key'], server_id=child['server_id'])}" title="${child['title']}">
<div class="item-children-poster">
<div class="item-children-poster-face cover-item" style="background-image: url(${page('pms_image_proxy', child['thumb'], child['rating_key'], 300, 300, fallback='cover')});"></div>
<div class="item-children-poster-face cover-item" style="background-image: url(${page('pms_image_proxy', child['thumb'], child['rating_key'], 300, 300, fallback='cover', server_id=child['server_id'])});"></div>
% if _session['user_group'] == 'admin':
<span class="overlay-refresh-image" title="Refresh image"><i class="fa fa-refresh refresh_pms_image"></i></span>
% endif
@ -210,13 +210,13 @@ DOCUMENTATION :: END
</a>
<div class="item-children-instance-text-wrapper cover-item">
<h3>
<a href="${page('info', child['rating_key'])}" title="${child['title']}">${child['title']}</a>
<a href="${page('info', child['rating_key'], server_id=child['server_id'])}" title="${child['title']}">${child['title']}</a>
</h3>
</div>
% elif child['media_type'] == 'album':
<a href="${page('info', child['rating_key'])}" title="${child['title']}">
<a href="${page('info', child['rating_key'], server_id=child['server_id'])}" title="${child['title']}">
<div class="item-children-poster">
<div class="item-children-poster-face cover-item" style="background-image: url(${page('pms_image_proxy', child['thumb'], child['rating_key'], 300, 300, fallback='cover')});"></div>
<div class="item-children-poster-face cover-item" style="background-image: url(${page('pms_image_proxy', child['thumb'], child['rating_key'], 300, 300, fallback='cover', server_id=child['server_id'])});"></div>
% if _session['user_group'] == 'admin':
<span class="overlay-refresh-image" title="Refresh image"><i class="fa fa-refresh refresh_pms_image"></i></span>
% endif
@ -224,11 +224,11 @@ DOCUMENTATION :: END
</a>
<div class="item-children-instance-text-wrapper cover-item">
<h3>
<a href="${page('info', child['rating_key'])}" title="${child['title']}">${child['title']}</a>
<a href="${page('info', child['rating_key'], server_id=child['server_id'])}" title="${child['title']}">${child['title']}</a>
</h3>
% if media_type == 'collection':
<h3 class="text-muted">
<a class="text-muted" href="${page('info', child['parent_rating_key'])}" title="${child['parent_title']}">${child['parent_title']}</a>
<a class="text-muted" href="${page('info', child['parent_rating_key'], server_id=child['server_id'])}" title="${child['parent_title'], server_id=child['server_id']}">${child['parent_title']}</a>
</h3>
% endif
</div>
@ -238,19 +238,19 @@ DOCUMENTATION :: END
<span class="item-children-list-item-index">${child['media_index']}</span>
<span class="item-children-list-item-title">
<span class="media-type-tooltip" data-toggle="tooltip" title="Track"><i class="fa fa-music fa-fw"></i></span>
<a href="${page('info', child['rating_key'])}" title="${child['title']}">
<span class="thumb-tooltip" data-toggle="popover" data-img="${page('pms_image_proxy', child['parent_thumb'], child['parent_rating_key'], 300, 300, fallback='cover')}" data-height="80" data-width="80">
<a href="${page('info', child['rating_key'], server_id=child['server_id'])}" title="${child['title']}">
<span class="thumb-tooltip" data-toggle="popover" data-img="${page('pms_image_proxy', child['parent_thumb'], child['parent_rating_key'], 300, 300, fallback='cover', server_id=child['server_id'])}" data-height="80" data-width="80">
${child['title']}
</span>
</a>
% if media_type == 'collection':
-
<a href="${page('info', child['grandparent_rating_key'])}" title="${child['grandparent_title']}">
<a href="${page('info', child['grandparent_rating_key'], server_id=child['server_id'])}" title="${child['grandparent_title'], server_id=child['server_id']}">
<span class="thumb-tooltip" data-toggle="popover" data-img="${page('pms_image_proxy', child['grandparent_thumb'], child['grandparent_rating_key'], 300, 300, fallback='cover')}" data-height="80" data-width="80">
${child['grandparent_title']}
</span>
</a>
<span class="text-muted"> (<a class="no-highlight" href="${page('info', child['parent_rating_key'])}" title="${child['parent_title']}">${child['parent_title']}</a>)</span>
<span class="text-muted"> (<a class="no-highlight" href="${page('info', child['parent_rating_key'], server_id=child['server_id'])}" title="${child['parent_title']}">${child['parent_title']}</a>)</span>
% elif child['original_title']:
<span class="text-muted"> - ${child['original_title']}</span>
% endif
@ -272,8 +272,8 @@ DOCUMENTATION :: END
% else:
<span class="media-type-tooltip" data-toggle="tooltip" title="Photo"><i class="fa fa-picture-o fa-fw"></i></span>
% endif
<a href="${page('info', child['rating_key'])}" title="${child['title']}">
<span class="thumb-tooltip" data-toggle="popover" data-img="${page('pms_image_proxy', child['thumb'], child['rating_key'], 300, 300, fallback='cover')}" data-height="80" data-width="80">
<a href="${page('info', child['rating_key'], server_id=child['server_id'])}" title="${child['title']}">
<span class="thumb-tooltip" data-toggle="popover" data-img="${page('pms_image_proxy', child['thumb'], child['rating_key'], 300, 300, fallback='cover', server_id=child['server_id'])}" data-height="80" data-width="80">
${child['title']}
</span>
</a>

View file

@ -784,7 +784,7 @@ function page(endpoint, ...args) {
return endpoint + '?' + $.param(params).replace(/'/g, '%27');
}
function pms_image_proxy(img, rating_key, width, height, opacity, background, blur, fallback, refresh, clip, img_format) {
function pms_image_proxy(img, rating_key, width, height, opacity, background, blur, fallback, refresh, clip, img_format, server_id) {
var params = {};
if (img != null) { params.img = img; }
@ -798,11 +798,12 @@ function pms_image_proxy(img, rating_key, width, height, opacity, background, bl
if (refresh != null) { params.refresh = true; }
if (clip != null) { params.clip = true; }
if (img_format != null) { params.img_format = img_format; }
if (server_id != null) { params.server_id = server_id; }
return params;
}
function info_page(rating_key, guid, history, live) {
function info_page(rating_key, guid, history, live, server_id) {
var params = {};
if (live && history) {
@ -813,13 +814,16 @@ function info_page(rating_key, guid, history, live) {
if (history) { params.source = 'history'; }
if (server_id != null) { params.server_id = server_id; }
return params;
}
function library_page(section_id) {
function library_page(section_id, server_id) {
var params = {};
if (section_id != null) { params.section_id = section_id; }
if (server_id != null) { params.server_id = server_id; }
return params;
}

View file

@ -49,12 +49,12 @@ libraries_list_table_options = {
if (!rowData['is_active']) { inactive = '<span class="inactive-library-tooltip" data-toggle="tooltip" title="Library not on Plex server"><i class="fa fa-exclamation-triangle"></i></span>'; }
if (cellData !== null && cellData !== '') {
if (rowData['library_thumb'].substring(0, 4) == "http") {
$(td).html('<a href="' + page('library', rowData['section_id']) + '"><div class="libraries-poster-face" style="background-image: url(' + rowData['library_thumb'] + ');">' + inactive + '</div></a>');
$(td).html('<a href="' + page('library', rowData['section_id'], rowData['server_id']) + '"><div class="libraries-poster-face" style="background-image: url(' + rowData['library_thumb'] + ');">' + inactive + '</div></a>');
} else {
$(td).html('<a href="' + page('library', rowData['section_id']) + '"><div class="libraries-poster-face svg-icon library-' + rowData['section_type'] + '">' + inactive + '</div></a>');
$(td).html('<a href="' + page('library', rowData['section_id'], rowData['server_id']) + '"><div class="libraries-poster-face svg-icon library-' + rowData['section_type'] + '">' + inactive + '</div></a>');
}
} else {
$(td).html('<a href="' + page('library', rowData['section_id']) + '"><div class="libraries-poster-face" style="background-image: url(../../images/cover.png);">' + inactive + '</div></a>');
$(td).html('<a href="' + page('library', rowData['section_id'], rowData['server_id']) + '"><div class="libraries-poster-face" style="background-image: url(../../images/cover.png);">' + inactive + '</div></a>');
}
},
"orderable": false,
@ -68,7 +68,7 @@ libraries_list_table_options = {
"createdCell": function (td, cellData, rowData, row, col) {
if (cellData !== null && cellData !== '') {
$(td).html('<div data-id="' + rowData['row_id'] + '">' +
'<a href="' + page('library', rowData['section_id']) + '">' + cellData + '</a>' +
'<a href="' + page('library', rowData['section_id'], rowData['server_id']) + '">' + cellData + '</a>' +
'</div>');
} else {
$(td).html('n/a');
@ -154,23 +154,23 @@ libraries_list_table_options = {
icon_title = (rowData['live']) ? 'Live TV' : 'Movie';
if (rowData['year']) { parent_info = ' (' + rowData['year'] + ')'; }
media_type = '<span class="media-type-tooltip" data-toggle="tooltip" title="' + icon_title + '"><i class="fa ' + icon + ' fa-fw"></i></span>';
thumb_popover = '<span class="thumb-tooltip" data-toggle="popover" data-img="' + page('pms_image_proxy', rowData['thumb'], rowData['rating_key'], 300, 450, null, null, null, fallback) + '" data-height="120" data-width="80">' + cellData + parent_info + '</span>';
$(td).html('<div class="history-title"><a href="' + page('info', rowData['rating_key'], rowData['guid'], true, rowData['live']) + '"><div style="float: left;">' + media_type + '&nbsp;' + thumb_popover + '</div></a></div>');
thumb_popover = '<span class="thumb-tooltip" data-toggle="popover" data-img="' + page('pms_image_proxy', rowData['thumb'], rowData['rating_key'], 300, 450, null, null, null, fallback, rowData['server_id']) + '" data-height="120" data-width="80">' + cellData + parent_info + '</span>';
$(td).html('<div class="history-title"><a href="' + page('info', rowData['rating_key'], rowData['guid'], true, rowData['live'], rowData['server_id']) + '"><div style="float: left;">' + media_type + '&nbsp;' + thumb_popover + '</div></a></div>');
} else if (rowData['media_type'] === 'episode') {
icon = (rowData['live']) ? 'fa-broadcast-tower' : 'fa-television';
icon_title = (rowData['live']) ? 'Live TV' : 'Episode';
if (!isNaN(parseInt(rowData['parent_media_index'])) && !isNaN(parseInt(rowData['media_index']))) { parent_info = ' (' + short_season(rowData['parent_title']) + ' &middot; E' + rowData['media_index'] + ')'; }
else if (rowData['live'] && rowData['originally_available_at']) { parent_info = ' (' + rowData['originally_available_at'] + ')'; }
media_type = '<span class="media-type-tooltip" data-toggle="tooltip" title="' + icon_title + '"><i class="fa ' + icon + ' fa-fw"></i></span>';
thumb_popover = '<span class="thumb-tooltip" data-toggle="popover" data-img="' + page('pms_image_proxy', rowData['thumb'], rowData['rating_key'], 300, 450, null, null, null, fallback) + '" data-height="120" data-width="80">' + cellData + parent_info + '</span>';
$(td).html('<div class="history-title"><a href="' + page('info', rowData['rating_key'], rowData['guid'], true, rowData['live']) + '"><div style="float: left;" >' + media_type + '&nbsp;' + thumb_popover + '</div></a></div>');
thumb_popover = '<span class="thumb-tooltip" data-toggle="popover" data-img="' + page('pms_image_proxy', rowData['thumb'], rowData['rating_key'], 300, 450, null, null, null, fallback, rowData['server_id']) + '" data-height="120" data-width="80">' + cellData + parent_info + '</span>';
$(td).html('<div class="history-title"><a href="' + page('info', rowData['rating_key'], rowData['guid'], true, rowData['live'], rowData['server_id']) + '"><div style="float: left;" >' + media_type + '&nbsp;' + thumb_popover + '</div></a></div>');
} else if (rowData['media_type'] === 'track') {
if (rowData['parent_title']) { parent_info = ' (' + rowData['parent_title'] + ')'; }
media_type = '<span class="media-type-tooltip" data-toggle="tooltip" title="Track"><i class="fa fa-music fa-fw"></i></span>';
thumb_popover = '<span class="thumb-tooltip" data-toggle="popover" data-img="' + page('pms_image_proxy', rowData['thumb'], rowData['rating_key'], 300, 300, null, null, null, 'cover') + '" data-height="80" data-width="80">' + cellData + parent_info + '</span>';
$(td).html('<div class="history-title"><a href="' + page('info', rowData['rating_key'], rowData['guid'], true, rowData['live']) + '"><div style="float: left;">' + media_type + '&nbsp;' + thumb_popover + '</div></a></div>');
thumb_popover = '<span class="thumb-tooltip" data-toggle="popover" data-img="' + page('pms_image_proxy', rowData['thumb'], rowData['rating_key'], 300, 300, null, null, null, 'cover', rowData['server_id']) + '" data-height="80" data-width="80">' + cellData + parent_info + '</span>';
$(td).html('<div class="history-title"><a href="' + page('info', rowData['rating_key'], rowData['guid'], true, rowData['live'], rowData['server_id']) + '"><div style="float: left;">' + media_type + '&nbsp;' + thumb_popover + '</div></a></div>');
} else if (rowData['media_type']) {
$(td).html('<a href="' + page('info', rowData['rating_key']) + '">' + cellData + '</a>');
$(td).html('<a href="' + page('info', rowData['rating_key'], rowData['server_id']) + '">' + cellData + '</a>');
}
} else {
$(td).html('n/a');

View file

@ -548,6 +548,7 @@ DOCUMENTATION :: END
% endif
var section_name = '${data['section_name'].replace("'", "\\'")}';
var refresh_table = false;
var server_id = "${data['server_id']}";
% if config['get_file_sizes']:
var get_file_sizes = false;
@ -577,7 +578,8 @@ DOCUMENTATION :: END
json_data: JSON.stringify( d ),
section_id: section_id,
user_id: "${history_user_id}",
transcode_decision: transcode_decision
transcode_decision: transcode_decision,
server_id: server_id
};
}
};
@ -625,7 +627,8 @@ DOCUMENTATION :: END
data: function ( d ) {
return {
json_data: JSON.stringify( d ),
section_id: section_id
section_id: section_id,
server_id: server_id
};
}
};
@ -657,7 +660,8 @@ DOCUMENTATION :: END
data: function ( d ) {
return {
json_data: JSON.stringify( d ),
section_id: section_id
section_id: section_id,
server_id: server_id
};
}
};
@ -686,7 +690,8 @@ DOCUMENTATION :: END
async: true,
data: {
section_id: section_id,
limit: 50
limit: 50,
server_id: server_id
},
complete: function(xhr, status) {
$("#library-recently-watched").html(xhr.responseText);
@ -702,7 +707,8 @@ DOCUMENTATION :: END
async: true,
data: {
section_id: section_id,
limit: 50
limit: 50,
server_id: server_id
},
complete: function(xhr, status) {
$("#library-recently-added").html(xhr.responseText);
@ -811,7 +817,10 @@ DOCUMENTATION :: END
$.ajax({
url: 'library_watch_time_stats',
async: true,
data: { section_id: section_id },
data: {
section_id: section_id,
server_id: server_id
},
complete: function(xhr, status) {
$("#library-time-stats").html(xhr.responseText);
}
@ -821,7 +830,10 @@ DOCUMENTATION :: END
$.ajax({
url: 'library_user_stats',
async: true,
data: { section_id: section_id },
data: {
section_id: section_id,
server_id: server_id
},
complete: function(xhr, status) {
$("#library-user-stats").html(xhr.responseText);
}
@ -840,7 +852,8 @@ DOCUMENTATION :: END
return {
json_data: JSON.stringify( d ),
section_id: section_id,
refresh: refresh_table
refresh: refresh_table,
server_id: server_id
};
}
};
@ -874,7 +887,8 @@ DOCUMENTATION :: END
data: function ( d ) {
return {
json_data: JSON.stringify( d ),
section_id: section_id
section_id: section_id,
server_id: server_id
};
}
};
@ -904,7 +918,10 @@ DOCUMENTATION :: END
$("#edit-library-tooltip").tooltip('hide');
$.ajax({
url: 'edit_library_dialog',
data: { section_id: section_id },
data: {
section_id: section_id,
server_id: server_id
},
cache: false,
async: true,
complete: function(xhr, status) {
@ -920,7 +937,8 @@ DOCUMENTATION :: END
section_id: $(this).data('section_id'),
media_type: $(this).data('media_type'),
sub_media_type: $(this).data('sub_media_type'),
export_type: $(this).data('export_type')
export_type: $(this).data('export_type'),
server_id: server_id
},
cache: false,
async: true,
@ -941,7 +959,10 @@ DOCUMENTATION :: END
$.ajax({
url: 'delete_history_rows',
type: 'POST',
data: { row_ids: history_to_delete.join(',') },
data: {
row_ids: history_to_delete.join(','),
server_id: server_id
},
async: true,
success: function (data) {
var msg = "History deleted";

View file

@ -42,19 +42,19 @@ DOCUMENTATION :: END
<li>
% if item['media_type'] == 'episode' or item['media_type'] == 'movie':
% if item['media_type'] == 'movie':
<a href="${page('info', item['rating_key'])}" title="${item['title']}">
<a href="${page('info', item['rating_key'], server_id=item['server_id'])}" title="${item['title']}">
% elif item['media_type'] == 'episode':
<a href="${page('info', item['rating_key'])}" title="${item['grandparent_title']}">
<a href="${page('info', item['rating_key'], server_id=item['server_id'])}" title="${item['grandparent_title']}">
% endif
<div class="dashboard-recent-media-poster">
% if item['media_type'] == 'episode':
% if item['parent_thumb']:
<div class="dashboard-recent-media-poster-face" style="background-image: url(${page('pms_image_proxy', item['parent_thumb'], item['parent_rating_key'], 300, 450, fallback='poster')});">
<div class="dashboard-recent-media-poster-face" style="background-image: url(${page('pms_image_proxy', item['parent_thumb'], item['parent_rating_key'], 300, 450, fallback='poster', server_id=item['server_id'])});">
% else:
<div class="dashboard-recent-media-poster-face" style="background-image: url(${page('pms_image_proxy', item['grandparent_thumb'], item['grandparent_rating_key'], 300, 450, fallback='poster')});">
<div class="dashboard-recent-media-poster-face" style="background-image: url(${page('pms_image_proxy', item['grandparent_thumb'], item['grandparent_rating_key'], 300, 450, fallback='poster', server_id=item['server_id'])});">
% endif
% elif item['media_type'] == 'movie':
<div class="dashboard-recent-media-poster-face" style="background-image: url(${page('pms_image_proxy', item['thumb'], item['rating_key'], 300, 450, fallback='poster')});">
<div class="dashboard-recent-media-poster-face" style="background-image: url(${page('pms_image_proxy', item['thumb'], item['rating_key'], 300, 450, fallback='poster', server_id=item['server_id'])});">
% endif
<div class="dashboard-recent-media-overlay">
<div class="dashboard-recent-media-overlay-text" id="added_at-${item['rating_key']}">
@ -72,27 +72,27 @@ DOCUMENTATION :: END
<div class="dashboard-recent-media-metacontainer">
% if item['media_type'] == 'episode':
<h3>
<a href="${page('info', item['grandparent_rating_key'])}" title="${item['grandparent_title']}">${item['grandparent_title']}</a>
<a href="${page('info', item['grandparent_rating_key'], server_id=item['server_id'])}" title="${item['grandparent_title']}">${item['grandparent_title']}</a>
</h3>
<h3 class="text-muted">
<a href="${page('info', item['rating_key'])}" title="${item['title']}">${item['title']}</a>
<a href="${page('info', item['rating_key'], server_id=item['server_id'])}" title="${item['title']}">${item['title']}</a>
</h3>
<h3 class="text-muted">
<a href="${page('info', item['parent_rating_key'])}" title="${item['parent_title']}">${short_season(item['parent_title'])}</a>
&middot; <a href="${page('info', item['rating_key'])}" title="Episode ${item['media_index']}">E${item['media_index']}</a>
<a href="${page('info', item['parent_rating_key'], server_id=item['server_id'])}" title="${item['parent_title']}">${short_season(item['parent_title'])}</a>
&middot; <a href="${page('info', item['rating_key'], server_id=item['server_id'])}" title="Episode ${item['media_index']}">E${item['media_index']}</a>
</h3>
% elif item['media_type'] == 'movie':
<h3>
<a href="${page('info', item['rating_key'])}" title="${item['title']}">${item['title']}</a>
<a href="${page('info', item['rating_key'], server_id=item['server_id'])}" title="${item['title']}">${item['title']}</a>
</h3>
<h3 class="text-muted">${item['year']}</h3>
<h3 class="text-muted">&nbsp;</h3>
% endif
</div>
% elif item['media_type'] == 'album':
<a href="${page('info', item['rating_key'])}" title="${item['title']}">
<a href="${page('info', item['rating_key'], server_id=item['server_id'])}" title="${item['title']}">
<div class="dashboard-recent-media-cover">
<div class="dashboard-recent-media-cover-face" style="background-image: url(${page('pms_image_proxy', item['thumb'], item['rating_key'], 300, 300, fallback='cover')});">
<div class="dashboard-recent-media-cover-face" style="background-image: url(${page('pms_image_proxy', item['thumb'], item['rating_key'], 300, 300, fallback='cover', server_id=item['server_id'])});">
<div class="dashboard-recent-media-overlay">
<div class="dashboard-recent-media-overlay-text" id="added_at-${item['rating_key']}">
<script>
@ -104,10 +104,10 @@ DOCUMENTATION :: END
</div>
<div class="dashboard-recent-media-metacontainer">
<h3>
<a href="${page('info', item['parent_rating_key'])}" title="${item['parent_title']}">${item['parent_title']}</a>
<a href="${page('info', item['parent_rating_key'], server_id=item['server_id'])}" title="${item['parent_title']}">${item['parent_title']}</a>
</h3>
<h3 class="text-muted">
<a class="text-muted" href="${page('info', item['rating_key'])}" title="${item['title']}">${item['title']}</a>
<a class="text-muted" href="${page('info', item['rating_key'], server_id=item['server_id'])}" title="${item['title']}">${item['title']}</a>
</h3>
<h3 class="text-muted">&nbsp;</h3>
</div>

View file

@ -42,9 +42,9 @@ DOCUMENTATION :: END
<div class="dashboard-recent-media-instance">
<li data-type="${item['media_type']}">
% if item['media_type'] == 'movie':
<a href="${page('info', item['rating_key'])}" title="${item['title']}">
<a href="${page('info', item['rating_key'], server_id=item['server_id'])}" title="${item['title']}">
<div class="dashboard-recent-media-poster">
<div class="dashboard-recent-media-poster-face" style="background-image: url(${page('pms_image_proxy', item['thumb'], item['rating_key'], 300, 450, fallback='poster')});">
<div class="dashboard-recent-media-poster-face" style="background-image: url(${page('pms_image_proxy', item['thumb'], item['rating_key'], 300, 450, fallback='poster', server_id=item['server_id'])});">
<div class="dashboard-recent-media-overlay">
<div class="dashboard-recent-media-overlay-text" id="added_at-${item['rating_key']}">
<script>
@ -60,15 +60,15 @@ DOCUMENTATION :: END
</a>
<div class="dashboard-recent-media-metacontainer">
<h3>
<a href="${page('info', item['rating_key'])}" title="${item['title']}">${item['title']}</a>
<a href="${page('info', item['rating_key'], server_id=item['server_id'])}" title="${item['title']}">${item['title']}</a>
</h3>
<h3 class="text-muted">${item['year']}</h3>
<h3 class="text-muted">&nbsp;</h3>
</div>
% elif item['media_type'] == 'show':
<a href="${page('info', item['rating_key'])}" title="${item['title']}">
<a href="${page('info', item['rating_key'], server_id=item['server_id'])}" title="${item['title']}">
<div class="dashboard-recent-media-poster">
<div class="dashboard-recent-media-poster-face" style="background-image: url(${page('pms_image_proxy', item['thumb'], item['rating_key'], 300, 450, fallback='poster')});">
<div class="dashboard-recent-media-poster-face" style="background-image: url(${page('pms_image_proxy', item['thumb'], item['rating_key'], 300, 450, fallback='poster', server_id=item['server_id'])});">
<div class="dashboard-recent-media-overlay">
<div class="dashboard-recent-media-overlay-text" id="added_at-${item['rating_key']}">
<script>
@ -84,7 +84,7 @@ DOCUMENTATION :: END
</a>
<div class="dashboard-recent-media-metacontainer">
<h3>
<a href="${page('info', item['rating_key'])}" title="${item['title']}">${item['title']}</a>
<a href="${page('info', item['rating_key'], server_id=item['server_id'])}" title="${item['title']}">${item['title']}</a>
</h3>
<h3 class="text-muted">
${item['child_count']} Season${'s' if cast_to_int(item['child_count']) > 1 else ''}
@ -92,12 +92,12 @@ DOCUMENTATION :: END
<h3 class="text-muted">&nbsp;</h3>
</div>
% elif item['media_type'] == 'season':
<a href="${page('info', item['rating_key'])}" title="${item['parent_title']}">
<a href="${page('info', item['rating_key'], server_id=item['server_id'])}" title="${item['parent_title']}">
<div class="dashboard-recent-media-poster">
% if item['thumb']:
<div class="dashboard-recent-media-poster-face" style="background-image: url(${page('pms_image_proxy', item['thumb'], item['rating_key'], 300, 450, fallback='poster')});">
<div class="dashboard-recent-media-poster-face" style="background-image: url(${page('pms_image_proxy', item['thumb'], item['rating_key'], 300, 450, fallback='poster', server_id=item['server_id'])});">
% else:
<div class="dashboard-recent-media-poster-face" style="background-image: url(${page('pms_image_proxy', item['parent_thumb'], item['parent_rating_key'], 300, 450, fallback='poster')});">
<div class="dashboard-recent-media-poster-face" style="background-image: url(${page('pms_image_proxy', item['parent_thumb'], item['parent_rating_key'], 300, 450, fallback='poster', server_id=item['server_id'])});">
% endif
<div class="dashboard-recent-media-overlay">
<div class="dashboard-recent-media-overlay-text" id="added_at-${item['rating_key']}">
@ -114,17 +114,17 @@ DOCUMENTATION :: END
</a>
<div class="dashboard-recent-media-metacontainer">
<h3>
<a href="${page('info', item['parent_rating_key'])}" title="${item['parent_title']}">${item['parent_title']}</a>
<a href="${page('info', item['parent_rating_key'], server_id=item['server_id'])}" title="${item['parent_title']}">${item['parent_title']}</a>
</h3>
<h3 class="text-muted">
<a class="text-muted" href="${page('info', item['rating_key'])}" title="${item['title']}">${item['title']}</a>
<a class="text-muted" href="${page('info', item['rating_key'], server_id=item['server_id'])}" title="${item['title']}">${item['title']}</a>
</h3>
<h3 class="text-muted">&nbsp;</h3>
</div>
% elif item['media_type'] == 'episode':
<a href="${page('info', item['rating_key'])}" title="${item['title']}">
<a href="${page('info', item['rating_key'], server_id=item['server_id'])}" title="${item['title']}">
<div class="dashboard-recent-media-poster">
<div class="dashboard-recent-media-poster-face" style="background-image: url(${page('pms_image_proxy', item['grandparent_thumb'], item['grandparent_rating_key'], 300, 450, fallback='poster')});">
<div class="dashboard-recent-media-poster-face" style="background-image: url(${page('pms_image_proxy', item['grandparent_thumb'], item['grandparent_rating_key'], 300, 450, fallback='poster', server_id=item['server_id'])});">
<div class="dashboard-recent-media-overlay">
<div class="dashboard-recent-media-overlay-text" id="added_at-${item['rating_key']}">
<script>
@ -140,21 +140,21 @@ DOCUMENTATION :: END
</a>
<div class="dashboard-recent-media-metacontainer">
<h3>
<a href="${page('info', item['grandparent_rating_key'])}" title="${item['grandparent_title']}">${item['grandparent_title']}</a>
<a href="${page('info', item['grandparent_rating_key'], server_id=item['server_id'])}" title="${item['grandparent_title']}">${item['grandparent_title']}</a>
</h3>
<h3 class="text-muted">
<a href="${page('info', item['rating_key'])}" title="${item['title']}">${item['title']}</a>
<a href="${page('info', item['rating_key'], server_id=item['server_id'])}" title="${item['title']}">${item['title']}</a>
</h3>
<h3 class="text-muted">
<a href="${page('info', item['parent_rating_key'])}" title="${item['parent_title']}">${short_season(item['parent_title'])}</a>
<a href="${page('info', item['parent_rating_key'], server_id=item['server_id'])}" title="${item['parent_title']}">${short_season(item['parent_title'])}</a>
&middot;
<a href="${page('info', item['rating_key'])}" title="Episode ${item['media_index']}">E${item['media_index']}</a>
<a href="${page('info', item['rating_key'], server_id=item['server_id'])}" title="Episode ${item['media_index']}">E${item['media_index']}</a>
</h3>
</div>
% elif item['media_type'] == 'album':
<a href="${page('info', item['rating_key'])}" title="${item['parent_title']}">
<a href="${page('info', item['rating_key'], server_id=item['server_id'])}" title="${item['parent_title']}">
<div class="dashboard-recent-media-cover">
<div class="dashboard-recent-media-cover-face" style="background-image: url(${page('pms_image_proxy', item['thumb'], item['rating_key'], 300, 300, fallback='cover')});">
<div class="dashboard-recent-media-cover-face" style="background-image: url(${page('pms_image_proxy', item['thumb'], item['rating_key'], 300, 300, fallback='cover', server_id=item['server_id'])});">
<div class="dashboard-recent-media-overlay">
<div class="dashboard-recent-media-overlay-text" id="added_at-${item['rating_key']}">
<script>
@ -170,10 +170,10 @@ DOCUMENTATION :: END
</a>
<div class="dashboard-recent-media-metacontainer">
<h3>
<a href="${page('info', item['parent_rating_key'])}" title="${item['parent_title']}">${item['parent_title']}</a>
<a href="${page('info', item['parent_rating_key'], server_id=item['server_id'])}" title="${item['parent_title']}">${item['parent_title']}</a>
</h3>
<h3 class="text-muted">
<a class="text-muted" href="${page('info', item['rating_key'])}" title="${item['title']}">${item['title']}</a>
<a class="text-muted" href="${page('info', item['rating_key'], server_id=item['server_id'])}" title="${item['title']}">${item['title']}</a>
</h3>
<h3 class="text-muted">&nbsp;</h3>
</div>

View file

@ -38,12 +38,12 @@ DOCUMENTATION :: END
% if item['media_type'] == 'episode' or item['media_type'] == 'movie':
% if item['rating_key']:
% if item['media_type'] == 'movie':
<a href="${page('info', item['rating_key'], history=True, live=item['live'])}" title="${item['title']}">
<a href="${page('info', item['rating_key'], history=True, live=item['live'], server_id=item['server_id'])}" title="${item['title']}">
% elif item['media_type'] == 'episode':
<a href="${page('info', item['rating_key'], history=True, live=item['live'])}" title="${item['grandparent_title']}">
<a href="${page('info', item['rating_key'], history=True, live=item['live'], server_id=item['server_id'])}" title="${item['grandparent_title']}">
% endif
<div class="dashboard-recent-media-poster">
<div class="dashboard-recent-media-poster-face" style="background-image: url(${page('pms_image_proxy', item['thumb'], item['rating_key'], 300, 450, fallback='poster')});">
<div class="dashboard-recent-media-poster-face" style="background-image: url(${page('pms_image_proxy', item['thumb'], item['rating_key'], 300, 450, fallback='poster', server_id=item['server_id'])});">
<div class="dashboard-recent-media-overlay">
<div class="dashboard-recent-media-overlay-text" id="time-${item['time']}">
<script>
@ -61,36 +61,36 @@ DOCUMENTATION :: END
% if item['media_type'] == 'episode':
% if item['live']:
<h3>
<a href="${page('info', item['rating_key'], history=True, live=item['live'])}" title="${item['grandparent_title']}">${item['grandparent_title']}</a>
<a href="${page('info', item['rating_key'], history=True, live=item['live'], server_id=item['server_id'])}" title="${item['grandparent_title']}">${item['grandparent_title']}</a>
</h3>
<h3 class="text-muted" title="${item['title']}">
<a href="${page('info', item['rating_key'], history=True, live=item['live'])}" title="${item['title']}">${item['title']}</a>
<a href="${page('info', item['rating_key'], history=True, live=item['live'], server_id=item['server_id'])}" title="${item['title']}">${item['title']}</a>
</h3>
% if item['media_index']:
<h3 class="text-muted">
<a href="${page('info', item['rating_key'], history=True, live=item['live'])}" title="${item['parent_title']}">${short_season(item['parent_title'])}</a>
&middot; <a href="${page('info', item['rating_key'], history=True, live=item['live'])}" title="Episode ${item['media_index']}">E${item['media_index']}</a>
<a href="${page('info', item['rating_key'], history=True, live=item['live'], server_id=item['server_id'])}" title="${item['parent_title']}">${short_season(item['parent_title'])}</a>
&middot; <a href="${page('info', item['rating_key'], history=True, live=item['live'], server_id=item['server_id'])}" title="Episode ${item['media_index']}">E${item['media_index']}</a>
</h3>
% else:
<h3 class="text-muted">
<a href="${page('info', item['rating_key'], history=True, live=item['live'])}" title="${item['originally_available_at']}">${item['originally_available_at']}</a>
<a href="${page('info', item['rating_key'], history=True, live=item['live'], server_id=item['server_id'])}" title="${item['originally_available_at']}">${item['originally_available_at']}</a>
</h3>
% endif
% else:
<h3>
<a href="${page('info', item['grandparent_rating_key'])}" title="${item['grandparent_title']}">${item['grandparent_title']}</a>
<a href="${page('info', item['grandparent_rating_key'], server_id=item['server_id'])}" title="${item['grandparent_title']}">${item['grandparent_title']}</a>
</h3>
<h3 class="text-muted" title="${item['title']}">
<a href="${page('info', item['rating_key'], history=True, live=item['live'])}" title="${item['title']}">${item['title']}</a>
<a href="${page('info', item['rating_key'], history=True, live=item['live'], server_id=item['server_id'])}" title="${item['title']}">${item['title']}</a>
</h3>
<h3 class="text-muted">
<a href="${page('info', item['parent_rating_key'])}" title="${item['parent_title']}">${short_season(item['parent_title'])}</a>
&middot; <a href="${page('info', item['rating_key'], history=True, live=item['live'])}" title="Episode ${item['media_index']}">E${item['media_index']}</a>
<a href="${page('info', item['parent_rating_key'], server_id=item['server_id'])}" title="${item['parent_title']}">${short_season(item['parent_title'])}</a>
&middot; <a href="${page('info', item['rating_key'], history=True, live=item['live'], server_id=item['server_id'])}" title="Episode ${item['media_index']}">E${item['media_index']}</a>
</h3>
% endif
% elif item['media_type'] == 'movie':
<h3 title="${item['title']}">
<a href="${page('info', item['rating_key'], history=True, live=item['live'])}" title="${item['title']}">${item['title']}</a>
<a href="${page('info', item['rating_key'], history=True, live=item['live'], server_id=item['server_id'])}" title="${item['title']}">${item['title']}</a>
</h3>
<h3 class="text-muted">${item['year']}</h3>
<h3 class="text-muted">&nbsp;</h3>
@ -116,9 +116,9 @@ DOCUMENTATION :: END
% endif
% elif item['media_type'] == 'track':
% if item['rating_key']:
<a href="${page('info', item['rating_key'], history=True, live=item['live'])}" title="${item['parent_title']}">
<a href="${page('info', item['rating_key'], history=True, live=item['live'], server_id=item['server_id'])}" title="${item['parent_title']}">
<div class="dashboard-recent-media-cover">
<div class="dashboard-recent-media-cover-face" style="background-image: url(${page('pms_image_proxy', item['thumb'], item['rating_key'], 300, 300, fallback='cover')});">
<div class="dashboard-recent-media-cover-face" style="background-image: url(${page('pms_image_proxy', item['thumb'], item['rating_key'], 300, 300, fallback='cover', server_id=item['server_id'])});">
<div class="dashboard-recent-media-overlay">
<div class="dashboard-recent-media-overlay-text" id="time-${item['time']}">
<script>
@ -131,13 +131,13 @@ DOCUMENTATION :: END
</a>
<div class="dashboard-recent-media-metacontainer">
<h3 title="${item['original_title'] or item['grandparent_title']}">
<a href="${page('info', item['grandparent_rating_key'])}" title="${item['original_title'] or item['grandparent_title']}">${item['original_title'] or item['grandparent_title']}</a>
<a href="${page('info', item['grandparent_rating_key'], server_id=item['server_id'])}" title="${item['original_title'] or item['grandparent_title']}">${item['original_title'] or item['grandparent_title']}</a>
</h3>
<h3 class="text-muted" title="${item['title']}">
<a href="${page('info', item['rating_key'], history=True, live=item['live'])}" title="${item['title']}">${item['title']}</a>
<a href="${page('info', item['rating_key'], history=True, live=item['live'], server_id=item['server_id'])}" title="${item['title']}">${item['title']}</a>
</h3>
<h3 class="text-muted">
<a href="${page('info', item['parent_rating_key'])}" title="${item['parent_title']}">${item['parent_title']}</a>
<a href="${page('info', item['parent_rating_key'], server_id=item['server_id'])}" title="${item['parent_title']}">${item['parent_title']}</a>
</h3>
</div>
% else:

View file

@ -662,13 +662,14 @@ def dbcheck():
"buffer_count INTEGER DEFAULT 0, buffer_last_triggered INTEGER, last_paused INTEGER, watched INTEGER DEFAULT 0, "
"intro INTEGER DEFAULT 0, credits INTEGER DEFAULT 0, commercial INTEGER DEFAULT 0, marker INTEGER DEFAULT 0, "
"initial_stream INTEGER DEFAULT 1, write_attempts INTEGER DEFAULT 0, raw_stream_info TEXT, "
"rating_key_websocket TEXT)"
"rating_key_websocket TEXT, "
"server_id TEXT)"
)
# sessions_continued table :: This is a temp table that keeps track of continued streaming sessions
c_db.execute(
"CREATE TABLE IF NOT EXISTS sessions_continued (id INTEGER PRIMARY KEY AUTOINCREMENT, "
"user_id INTEGER, machine_id TEXT, media_type TEXT, stopped INTEGER)"
"user_id INTEGER, machine_id TEXT, media_type TEXT, stopped INTEGER, server_id TEXT)"
)
# session_history table :: This is a history table which logs essential stream details
@ -679,7 +680,7 @@ def dbcheck():
"platform TEXT, platform_version TEXT, profile TEXT, machine_id TEXT, "
"bandwidth INTEGER, location TEXT, quality_profile TEXT, secure INTEGER, relayed INTEGER, "
"parent_rating_key INTEGER, grandparent_rating_key INTEGER, media_type TEXT, section_id INTEGER, "
"view_offset INTEGER DEFAULT 0)"
"view_offset INTEGER DEFAULT 0, server_id TEXT)"
)
# session_history_media_info table :: This is a table which logs each session"s media info
@ -705,7 +706,7 @@ def dbcheck():
"stream_subtitle_decision TEXT, stream_subtitle_codec TEXT, "
"stream_subtitle_container TEXT, stream_subtitle_forced INTEGER, stream_subtitle_language TEXT, "
"synced_version INTEGER, synced_version_profile TEXT, "
"optimized_version INTEGER, optimized_version_profile TEXT, optimized_version_title TEXT)"
"optimized_version INTEGER, optimized_version_profile TEXT, optimized_version_title TEXT, server_id TEXT)"
)
# session_history_metadata table :: This is a table which logs each session"s media metadata
@ -719,7 +720,7 @@ def dbcheck():
"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, "
"labels TEXT, live INTEGER DEFAULT 0, channel_call_sign TEXT, channel_identifier TEXT, channel_thumb TEXT, "
"marker_credits_first INTEGER DEFAULT NULL, marker_credits_final INTEGER DEFAULT NULL)"
"marker_credits_first INTEGER DEFAULT NULL, marker_credits_final INTEGER DEFAULT NULL, server_id TEXT)"
)
# users table :: This table keeps record of the friends list
@ -731,7 +732,8 @@ def dbcheck():
"is_allow_sync INTEGER DEFAULT NULL, is_restricted INTEGER DEFAULT NULL, "
"do_notify INTEGER DEFAULT 1, keep_history INTEGER DEFAULT 1, deleted_user INTEGER DEFAULT 0, "
"allow_guest INTEGER DEFAULT 0, user_token TEXT, server_token TEXT, shared_libraries TEXT, "
"filter_all TEXT, filter_movies TEXT, filter_tv TEXT, filter_music TEXT, filter_photos TEXT)"
"filter_all TEXT, filter_movies TEXT, filter_tv TEXT, filter_music TEXT, filter_photos TEXT, "
"server_id TEXT )"
)
# library_sections table :: This table keeps record of the servers library sections
@ -813,7 +815,7 @@ def dbcheck():
"CREATE TABLE IF NOT EXISTS recently_added (id INTEGER PRIMARY KEY AUTOINCREMENT, "
"added_at INTEGER, pms_identifier TEXT, section_id INTEGER, "
"rating_key INTEGER, parent_rating_key INTEGER, grandparent_rating_key INTEGER, media_type TEXT, "
"media_info TEXT)"
"media_info TEXT, server_id TEXT)"
)
# mobile_devices table :: This table keeps record of devices linked with the mobile app

View file

@ -32,7 +32,7 @@ if plexpy.PYTHON2:
import helpers
import logger
import notification_handler
import pmsconnect
import server_manager
else:
from plexpy import activity_processor
from plexpy import common
@ -40,7 +40,7 @@ else:
from plexpy import helpers
from plexpy import logger
from plexpy import notification_handler
from plexpy import pmsconnect
from plexpy import server_manager
ACTIVITY_SCHED = None
@ -78,26 +78,26 @@ class ActivityHandler(object):
def get_metadata(self, skip_cache=False):
if self.metadata is None:
cache_key = None if skip_cache else self.session_key
pms_connect = pmsconnect.PmsConnect()
metadata = pms_connect.get_metadata_details(rating_key=self.rating_key, cache_key=cache_key)
for pms_connect in server_manager.ServerManger().get_server_list():
metadata = pms_connect.get_metadata_details(rating_key=self.rating_key, cache_key=cache_key)
if metadata:
self.metadata = metadata
if metadata:
self.metadata = metadata
def get_live_session(self, skip_cache=False):
pms_connect = pmsconnect.PmsConnect()
session_list = pms_connect.get_current_activity(skip_cache=skip_cache)
for pms_connect in server_manager.ServerManger().get_server_list():
session_list = pms_connect.get_current_activity(skip_cache=skip_cache)
if session_list:
for session in session_list['sessions']:
if int(session['session_key']) == self.session_key:
# Live sessions don't have rating keys in sessions
# Get it from the websocket data
if not session['rating_key']:
session['rating_key'] = self.rating_key
session['rating_key_websocket'] = self.rating_key
self.session = session
return session
if session_list:
for session in session_list['sessions']:
if int(session['session_key']) == self.session_key:
# Live sessions don't have rating keys in sessions
# Get it from the websocket data
if not session['rating_key']:
session['rating_key'] = self.rating_key
session['rating_key_websocket'] = self.rating_key
self.session = session
return session
def update_db_session(self, notify=False):
if self.session is None:
@ -552,9 +552,9 @@ class ReachabilityHandler(object):
self.is_reachable = self.data.get('reachable', False)
def remote_access_enabled(self):
pms_connect = pmsconnect.PmsConnect()
pref = pms_connect.get_server_pref(pref='PublishServerOnPlexOnlineKey')
return helpers.bool_true(pref)
for pms_connect in server_manager.ServerManger().get_server_list():
pref = pms_connect.get_server_pref(pref='PublishServerOnPlexOnlineKey')
return helpers.bool_true(pref)
def on_extdown(self, server_response):
plexpy.NOTIFY_QUEUE.put({'notify_action': 'on_extdown', 'remote_access_info': server_response})
@ -571,8 +571,8 @@ class ReachabilityHandler(object):
if self.is_reachable and plexpy.PLEX_REMOTE_ACCESS_UP:
return
pms_connect = pmsconnect.PmsConnect()
server_response = pms_connect.get_server_response()
for pms_connect in server_manager.ServerManger().get_server_list():
server_response = pms_connect.get_server_response()
if not server_response:
return
@ -702,8 +702,8 @@ def clear_recently_added_queue(rating_key, title):
def on_created(rating_key, **kwargs):
pms_connect = pmsconnect.PmsConnect()
metadata = pms_connect.get_metadata_details(rating_key)
for pms_connect in server_manager.ServerManger().get_server_list():
metadata = pms_connect.get_metadata_details(rating_key)
logger.debug("Tautulli TimelineHandler :: Library item '%s' (%s) added to Plex.",
metadata['full_title'], str(rating_key))

View file

@ -28,8 +28,8 @@ if plexpy.PYTHON2:
import logger
import notification_handler
import plextv
import pmsconnect
import web_socket
import server_manager
else:
from plexpy import activity_handler
from plexpy import activity_processor
@ -39,8 +39,9 @@ else:
from plexpy import logger
from plexpy import notification_handler
from plexpy import plextv
from plexpy import pmsconnect
from plexpy import web_socket
from plexpy import server_manager
monitor_lock = threading.Lock()
@ -60,166 +61,167 @@ def check_active_sessions(ws_request=False):
for stream in db_streams:
activity_handler.delete_metadata_cache(stream['session_key'])
pms_connect = pmsconnect.PmsConnect()
session_list = pms_connect.get_current_activity()
session_list = []
for pms_connect in server_manager.ServerManger().get_server_list():
session_list = pms_connect.get_current_activity()
logger.debug("Tautulli Monitor :: Checking for active streams.")
logger.debug("Tautulli Monitor :: Checking for active streams.")
if session_list:
media_container = session_list['sessions']
if session_list:
media_container = session_list['sessions']
# Check our temp table for what we must do with the new streams
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):
# The user's session is still active
for session in media_container:
if session['session_key'] == str(stream['session_key']) and \
session['rating_key'] == str(stream['rating_key']):
# The user is still playing the same media item
# Here we can check the play states
if session['state'] != stream['state']:
if session['state'] == 'paused':
logger.debug("Tautulli Monitor :: Session %s paused." % stream['session_key'])
# Check our temp table for what we must do with the new streams
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):
# The user's session is still active
for session in media_container:
if session['session_key'] == str(stream['session_key']) and \
session['rating_key'] == str(stream['rating_key']):
# The user is still playing the same media item
# Here we can check the play states
if session['state'] != stream['state']:
if session['state'] == 'paused':
logger.debug("Tautulli Monitor :: Session %s paused." % stream['session_key'])
plexpy.NOTIFY_QUEUE.put({'stream_data': stream.copy(), 'notify_action': 'on_pause'})
plexpy.NOTIFY_QUEUE.put({'stream_data': stream.copy(), 'notify_action': 'on_pause'})
if session['state'] == 'playing' and stream['state'] == 'paused':
logger.debug("Tautulli Monitor :: Session %s resumed." % stream['session_key'])
if session['state'] == 'playing' and stream['state'] == 'paused':
logger.debug("Tautulli Monitor :: Session %s resumed." % stream['session_key'])
plexpy.NOTIFY_QUEUE.put({'stream_data': stream.copy(), 'notify_action': 'on_resume'})
plexpy.NOTIFY_QUEUE.put({'stream_data': stream.copy(), 'notify_action': 'on_resume'})
if session['state'] == 'error':
logger.debug("Tautulli Monitor :: Session %s encountered an error." % stream['session_key'])
if session['state'] == 'error':
logger.debug("Tautulli Monitor :: Session %s encountered an error." % stream['session_key'])
plexpy.NOTIFY_QUEUE.put({'stream_data': stream.copy(), 'notify_action': 'on_error'})
plexpy.NOTIFY_QUEUE.put({'stream_data': stream.copy(), 'notify_action': 'on_error'})
if stream['state'] == 'paused' and not ws_request:
# The stream is still paused so we need to increment the paused_counter
# Using the set config parameter as the interval, probably not the most accurate but
# it will have to do for now. If it's a websocket request don't use this method.
paused_counter = int(stream['paused_counter']) + plexpy.CONFIG.MONITORING_INTERVAL
monitor_db.action("UPDATE sessions SET paused_counter = ? "
"WHERE session_key = ? AND rating_key = ?",
[paused_counter, stream['session_key'], stream['rating_key']])
if stream['state'] == 'paused' and not ws_request:
# The stream is still paused so we need to increment the paused_counter
# Using the set config parameter as the interval, probably not the most accurate but
# it will have to do for now. If it's a websocket request don't use this method.
paused_counter = int(stream['paused_counter']) + plexpy.CONFIG.MONITORING_INTERVAL
monitor_db.action("UPDATE sessions SET paused_counter = ? "
"WHERE session_key = ? AND rating_key = ?",
[paused_counter, stream['session_key'], stream['rating_key']])
if session['state'] == 'buffering' and plexpy.CONFIG.BUFFER_THRESHOLD > 0:
# The stream is buffering so we need to increment the buffer_count
# We're going just increment on every monitor ping,
# would be difficult to keep track otherwise
monitor_db.action("UPDATE sessions SET buffer_count = buffer_count + 1 "
"WHERE session_key = ? AND rating_key = ?",
[stream['session_key'], stream['rating_key']])
if session['state'] == 'buffering' and plexpy.CONFIG.BUFFER_THRESHOLD > 0:
# The stream is buffering so we need to increment the buffer_count
# We're going just increment on every monitor ping,
# would be difficult to keep track otherwise
monitor_db.action("UPDATE sessions SET buffer_count = buffer_count + 1 "
"WHERE session_key = ? AND rating_key = ?",
[stream['session_key'], stream['rating_key']])
# Check the current buffer count and last buffer to determine if we should notify
buffer_values = monitor_db.select("SELECT buffer_count, buffer_last_triggered "
"FROM sessions "
"WHERE session_key = ? AND rating_key = ?",
[stream['session_key'], stream['rating_key']])
# Check the current buffer count and last buffer to determine if we should notify
buffer_values = monitor_db.select("SELECT buffer_count, buffer_last_triggered "
"FROM sessions "
"WHERE session_key = ? AND rating_key = ?",
[stream['session_key'], stream['rating_key']])
if buffer_values[0]['buffer_count'] >= plexpy.CONFIG.BUFFER_THRESHOLD:
# Push any notifications -
# Push it on it's own thread so we don't hold up our db actions
# Our first buffer notification
if buffer_values[0]['buffer_count'] == plexpy.CONFIG.BUFFER_THRESHOLD:
logger.info("Tautulli Monitor :: User '%s' has triggered a buffer warning."
% stream['user'])
# Set the buffer trigger time
monitor_db.action("UPDATE sessions "
"SET buffer_last_triggered = strftime('%s', 'now') "
"WHERE session_key = ? AND rating_key = ?",
[stream['session_key'], stream['rating_key']])
plexpy.NOTIFY_QUEUE.put({'stream_data': stream.copy(), 'notify_action': 'on_buffer'})
else:
# Subsequent buffer notifications after wait time
if helpers.timestamp() > buffer_values[0]['buffer_last_triggered'] + \
plexpy.CONFIG.BUFFER_WAIT:
logger.info("Tautulli Monitor :: User '%s' has triggered multiple buffer warnings."
% stream['user'])
if buffer_values[0]['buffer_count'] >= plexpy.CONFIG.BUFFER_THRESHOLD:
# Push any notifications -
# Push it on it's own thread so we don't hold up our db actions
# Our first buffer notification
if buffer_values[0]['buffer_count'] == plexpy.CONFIG.BUFFER_THRESHOLD:
logger.info("Tautulli Monitor :: User '%s' has triggered a buffer warning."
% stream['user'])
# Set the buffer trigger time
monitor_db.action("UPDATE sessions "
"SET buffer_last_triggered = strftime('%s', 'now') "
"WHERE session_key = ? AND rating_key = ?",
[stream['session_key'], stream['rating_key']])
"SET buffer_last_triggered = strftime('%s', 'now') "
"WHERE session_key = ? AND rating_key = ?",
[stream['session_key'], stream['rating_key']])
plexpy.NOTIFY_QUEUE.put({'stream_data': stream.copy(), 'notify_action': 'on_buffer'})
logger.debug("Tautulli Monitor :: Session %s is buffering. Count is now %s. Last triggered %s."
% (stream['session_key'],
buffer_values[0]['buffer_count'],
buffer_values[0]['buffer_last_triggered']))
else:
# Subsequent buffer notifications after wait time
if helpers.timestamp() > buffer_values[0]['buffer_last_triggered'] + \
plexpy.CONFIG.BUFFER_WAIT:
logger.info("Tautulli Monitor :: User '%s' has triggered multiple buffer warnings."
% stream['user'])
# Set the buffer trigger time
monitor_db.action("UPDATE sessions "
"SET buffer_last_triggered = strftime('%s', 'now') "
"WHERE session_key = ? AND rating_key = ?",
[stream['session_key'], stream['rating_key']])
# Check if the user has reached the offset in the media we defined as the "watched" percent
# Don't trigger if state is buffer as some clients push the progress to the end when
# buffering on start.
if session['state'] != 'buffering':
progress_percent = helpers.get_percent(session['view_offset'], session['duration'])
notify_states = notification_handler.get_notify_state(session=session)
if (session['media_type'] == 'movie' and progress_percent >= plexpy.CONFIG.MOVIE_WATCHED_PERCENT or
session['media_type'] == 'episode' and progress_percent >= plexpy.CONFIG.TV_WATCHED_PERCENT or
session['media_type'] == 'track' and progress_percent >= plexpy.CONFIG.MUSIC_WATCHED_PERCENT) \
and not any(d['notify_action'] == 'on_watched' for d in notify_states):
plexpy.NOTIFY_QUEUE.put({'stream_data': stream.copy(), 'notify_action': 'on_watched'})
plexpy.NOTIFY_QUEUE.put({'stream_data': stream.copy(), 'notify_action': 'on_buffer'})
else:
# The user has stopped playing a stream
if stream['state'] != 'stopped':
logger.debug("Tautulli Monitor :: Session %s stopped." % stream['session_key'])
logger.debug("Tautulli Monitor :: Session %s is buffering. Count is now %s. Last triggered %s."
% (stream['session_key'],
buffer_values[0]['buffer_count'],
buffer_values[0]['buffer_last_triggered']))
if not stream['stopped']:
# Set the stream stop time
stream['stopped'] = helpers.timestamp()
monitor_db.action("UPDATE sessions SET stopped = ?, state = ? "
"WHERE session_key = ? AND rating_key = ?",
[stream['stopped'], 'stopped', stream['session_key'], stream['rating_key']])
# Check if the user has reached the offset in the media we defined as the "watched" percent
# Don't trigger if state is buffer as some clients push the progress to the end when
# buffering on start.
if session['state'] != 'buffering':
progress_percent = helpers.get_percent(session['view_offset'], session['duration'])
notify_states = notification_handler.get_notify_state(session=session)
if (session['media_type'] == 'movie' and progress_percent >= plexpy.CONFIG.MOVIE_WATCHED_PERCENT or
session['media_type'] == 'episode' and progress_percent >= plexpy.CONFIG.TV_WATCHED_PERCENT or
session['media_type'] == 'track' and progress_percent >= plexpy.CONFIG.MUSIC_WATCHED_PERCENT) \
and not any(d['notify_action'] == 'on_watched' for d in notify_states):
plexpy.NOTIFY_QUEUE.put({'stream_data': stream.copy(), 'notify_action': 'on_watched'})
progress_percent = helpers.get_percent(stream['view_offset'], stream['duration'])
notify_states = notification_handler.get_notify_state(session=stream)
if (stream['media_type'] == 'movie' and progress_percent >= plexpy.CONFIG.MOVIE_WATCHED_PERCENT or
stream['media_type'] == 'episode' and progress_percent >= plexpy.CONFIG.TV_WATCHED_PERCENT or
stream['media_type'] == 'track' and progress_percent >= plexpy.CONFIG.MUSIC_WATCHED_PERCENT) \
and not any(d['notify_action'] == 'on_watched' for d in notify_states):
plexpy.NOTIFY_QUEUE.put({'stream_data': stream.copy(), 'notify_action': 'on_watched'})
plexpy.NOTIFY_QUEUE.put({'stream_data': stream.copy(), 'notify_action': 'on_stop'})
# Write the item history on playback stop
row_id = monitor_process.write_session_history(session=stream)
if row_id:
# If session is written to the databaase successfully, remove the session from the session table
logger.debug("Tautulli Monitor :: Removing sessionKey %s ratingKey %s from session queue"
% (stream['session_key'], stream['rating_key']))
monitor_process.delete_session(row_id=row_id)
else:
stream['write_attempts'] += 1
# The user has stopped playing a stream
if stream['state'] != 'stopped':
logger.debug("Tautulli Monitor :: Session %s stopped." % stream['session_key'])
if stream['write_attempts'] < plexpy.CONFIG.SESSION_DB_WRITE_ATTEMPTS:
logger.warn("Tautulli Monitor :: Failed to write sessionKey %s ratingKey %s to the database. " \
"Will try again on the next pass. Write attempt %s."
% (stream['session_key'], stream['rating_key'], str(stream['write_attempts'])))
monitor_process.increment_write_attempts(session_key=stream['session_key'])
else:
logger.warn("Tautulli Monitor :: Failed to write sessionKey %s ratingKey %s to the database. " \
"Removing session from the database. Write attempt %s."
% (stream['session_key'], stream['rating_key'], str(stream['write_attempts'])))
if not stream['stopped']:
# Set the stream stop time
stream['stopped'] = helpers.timestamp()
monitor_db.action("UPDATE sessions SET stopped = ?, state = ? "
"WHERE session_key = ? AND rating_key = ?",
[stream['stopped'], 'stopped', stream['session_key'], stream['rating_key']])
progress_percent = helpers.get_percent(stream['view_offset'], stream['duration'])
notify_states = notification_handler.get_notify_state(session=stream)
if (stream['media_type'] == 'movie' and progress_percent >= plexpy.CONFIG.MOVIE_WATCHED_PERCENT or
stream['media_type'] == 'episode' and progress_percent >= plexpy.CONFIG.TV_WATCHED_PERCENT or
stream['media_type'] == 'track' and progress_percent >= plexpy.CONFIG.MUSIC_WATCHED_PERCENT) \
and not any(d['notify_action'] == 'on_watched' for d in notify_states):
plexpy.NOTIFY_QUEUE.put({'stream_data': stream.copy(), 'notify_action': 'on_watched'})
plexpy.NOTIFY_QUEUE.put({'stream_data': stream.copy(), 'notify_action': 'on_stop'})
# Write the item history on playback stop
row_id = monitor_process.write_session_history(session=stream)
if row_id:
# If session is written to the databaase successfully, remove the session from the session table
logger.debug("Tautulli Monitor :: Removing sessionKey %s ratingKey %s from session queue"
% (stream['session_key'], stream['rating_key']))
monitor_process.delete_session(session_key=stream['session_key'])
% (stream['session_key'], stream['rating_key']))
monitor_process.delete_session(row_id=row_id)
else:
stream['write_attempts'] += 1
# Process the newly received session data
for session in media_container:
new_session = monitor_process.write_session(session)
if stream['write_attempts'] < plexpy.CONFIG.SESSION_DB_WRITE_ATTEMPTS:
logger.warn("Tautulli Monitor :: Failed to write sessionKey %s ratingKey %s to the database. " \
"Will try again on the next pass. Write attempt %s."
% (stream['session_key'], stream['rating_key'], str(stream['write_attempts'])))
monitor_process.increment_write_attempts(session_key=stream['session_key'])
else:
logger.warn("Tautulli Monitor :: Failed to write sessionKey %s ratingKey %s to the database. " \
"Removing session from the database. Write attempt %s."
% (stream['session_key'], stream['rating_key'], str(stream['write_attempts'])))
logger.debug("Tautulli Monitor :: Removing sessionKey %s ratingKey %s from session queue"
% (stream['session_key'], stream['rating_key']))
monitor_process.delete_session(session_key=stream['session_key'])
if new_session:
logger.debug("Tautulli Monitor :: Session %s started by user %s (%s) with ratingKey %s (%s)%s."
% (str(session['session_key']), str(session['user_id']), session['username'],
str(session['rating_key']), session['full_title'], '[Live TV]' if session['live'] else ''))
# Process the newly received session data
for session in media_container:
new_session = monitor_process.write_session(session)
else:
logger.debug("Tautulli Monitor :: Unable to read session list.")
if new_session:
logger.debug("Tautulli Monitor :: Session %s started by user %s (%s) with ratingKey %s (%s)%s."
% (str(session['session_key']), str(session['user_id']), session['username'],
str(session['rating_key']), session['full_title'], '[Live TV]' if session['live'] else ''))
else:
logger.debug("Tautulli Monitor :: Unable to read session list.")
def connect_server(log=True, startup=False):

View file

@ -26,15 +26,15 @@ if plexpy.PYTHON2:
import helpers
import libraries
import logger
import pmsconnect
import users
import server_manager
else:
from plexpy import database
from plexpy import helpers
from plexpy import libraries
from plexpy import logger
from plexpy import pmsconnect
from plexpy import users
from plexpy import server_manager
class ActivityProcessor(object):
@ -273,19 +273,20 @@ class ActivityProcessor(object):
# Fetch metadata first so we can return false if it fails
if not is_import:
logger.debug("Tautulli ActivityProcessor :: Fetching metadata for item ratingKey %s" % session['rating_key'])
pms_connect = pmsconnect.PmsConnect()
if session['live']:
metadata = pms_connect.get_metadata_details(rating_key=str(session['rating_key']),
cache_key=session['session_key'],
return_cache=True)
else:
metadata = pms_connect.get_metadata_details(rating_key=str(session['rating_key']))
if not metadata:
return False
else:
media_info = {}
if 'media_info' in metadata and len(metadata['media_info']) > 0:
media_info = metadata['media_info'][0]
for pms_connect in server_manager.ServerManger().get_server_list():
if session['live']:
metadata = pms_connect.get_metadata_details(rating_key=str(session['rating_key']),
cache_key=session['session_key'],
return_cache=True)
else:
metadata = pms_connect.get_metadata_details(rating_key=str(session['rating_key']))
if not metadata:
return False
else:
media_info = {}
if 'media_info' in metadata and len(metadata['media_info']) > 0:
media_info = metadata['media_info'][0]
else:
metadata = import_metadata
## TODO: Fix media info from imports. Temporary media info from import session.

View file

@ -32,7 +32,7 @@ if plexpy.PYTHON2:
import libraries
import helpers
import logger
import pmsconnect
import server_manager
import session
import users
else:
@ -42,7 +42,7 @@ else:
from plexpy import datatables
from plexpy import helpers
from plexpy import logger
from plexpy import pmsconnect
from plexpy import server_manager
from plexpy import session
from plexpy import users
@ -1214,9 +1214,9 @@ class DataFactory(object):
group_by = 'session_history.reference_id' if grouping else 'session_history.id'
if media_type in ('collection', 'playlist'):
pms_connect = pmsconnect.PmsConnect()
result = pms_connect.get_item_children(rating_key=rating_key, media_type=media_type)
rating_keys = [child['rating_key'] for child in result['children_list']]
for pms_connect in server_manager.ServerManger().get_server_list():
result += pms_connect.get_item_children(rating_key=rating_key, media_type=media_type)
rating_keys += [child['rating_key'] for child in result['children_list']]
else:
rating_keys = [rating_key]
@ -1298,9 +1298,9 @@ class DataFactory(object):
group_by = 'session_history.reference_id' if grouping else 'session_history.id'
if media_type in ('collection', 'playlist'):
pms_connect = pmsconnect.PmsConnect()
result = pms_connect.get_item_children(rating_key=rating_key, media_type=media_type)
rating_keys = [child['rating_key'] for child in result['children_list']]
for pms_connect in server_manager.ServerManger().get_server_list():
result += pms_connect.get_item_children(rating_key=rating_key, media_type=media_type)
rating_keys += [child['rating_key'] for child in result['children_list']]
else:
rating_keys = [rating_key]
@ -2029,8 +2029,8 @@ class DataFactory(object):
return key_list
def update_metadata(self, old_key_list='', new_key_list='', media_type='', single_update=False):
pms_connect = pmsconnect.PmsConnect()
def update_metadata(self, old_key_list='', new_key_list='', media_type='', single_update=False, server_id=None):
pms_connect = server_manager.ServerManger().get_server(server_id=server_id)
monitor_db = database.MonitorDatabase()
# function to map rating keys pairs
@ -2400,10 +2400,10 @@ class DataFactory(object):
return result
def set_recently_added_item(self, rating_key=''):
def set_recently_added_item(self, rating_key='', server_id=None):
monitor_db = database.MonitorDatabase()
pms_connect = pmsconnect.PmsConnect()
pms_connect = server_manager.ServerManger().get_server(server_id=server_id)
metadata = pms_connect.get_metadata_details(rating_key)
keys = {'rating_key': metadata['rating_key']}

View file

@ -1578,7 +1578,7 @@ def page(endpoint, *args, **kwargs):
def pms_image_proxy(img=None, rating_key=None, width=None, height=None,
opacity=None, background=None, blur=None, img_format=None,
fallback=None, refresh=None, clip=None):
fallback=None, refresh=None, clip=None, server_id=None):
params = {}
if img is not None:
@ -1603,11 +1603,13 @@ def pms_image_proxy(img=None, rating_key=None, width=None, height=None,
params['refresh'] = 'true'
if clip is not None:
params['clip'] = 'true'
if server_id is not None:
params['server_id'] = server_id
return params
def info_page(rating_key=None, guid=None, history=None, live=None):
def info_page(rating_key=None, guid=None, history=None, live=None, server_id=None):
params = {}
if live and history:
@ -1618,14 +1620,20 @@ def info_page(rating_key=None, guid=None, history=None, live=None):
if history:
params['source'] = 'history'
if server_id is not None:
params['server_id'] = server_id
return params
def library_page(section_id=None):
def library_page(section_id=None, server_id=None):
params = {}
if section_id is not None:
params['section_id'] = section_id
if server_id is not None:
params['server_id'] = server_id
return params

View file

@ -32,9 +32,9 @@ if plexpy.PYTHON2:
import helpers
import logger
import plextv
import pmsconnect
import session
import users
import server_manager
from plex import Plex
else:
from plexpy import common
@ -43,71 +43,75 @@ else:
from plexpy import helpers
from plexpy import logger
from plexpy import plextv
from plexpy import pmsconnect
from plexpy import session
from plexpy import users
from plexpy import server_manager
from plexpy.plex import Plex
def refresh_libraries():
logger.info("Tautulli Libraries :: Requesting libraries list refresh...")
server_id = plexpy.CONFIG.PMS_IDENTIFIER
if not server_id:
logger.error("Tautulli Libraries :: No PMS identifier, cannot refresh libraries. Verify server in settings.")
return
passed = True
library_sections = pmsconnect.PmsConnect().get_library_details()
for server in server_manager.ServerManger().get_server_list():
library_sections = server.get_library_details()
if library_sections:
monitor_db = database.MonitorDatabase()
server_id = server.get_server_identity()["machine_identifier"]
if not server_id:
logger.error("Tautulli Libraries :: No PMS identifier, cannot refresh libraries. Verify server in settings.")
continue
library_keys = []
new_keys = []
if library_sections:
monitor_db = database.MonitorDatabase()
# Keep track of section_id to update is_active status
section_ids = [common.LIVE_TV_SECTION_ID] # Live TV library always considered active
library_keys = []
new_keys = []
for section in library_sections:
section_ids.append(helpers.cast_to_int(section['section_id']))
# Keep track of section_id to update is_active status
section_ids = [common.LIVE_TV_SECTION_ID] # Live TV library always considered active
section_keys = {'server_id': server_id,
'section_id': section['section_id']}
section_values = {'server_id': server_id,
'section_id': section['section_id'],
'section_name': section['section_name'],
'section_type': section['section_type'],
'agent': section['agent'],
'thumb': section['thumb'],
'art': section['art'],
'count': section['count'],
'parent_count': section.get('parent_count', None),
'child_count': section.get('child_count', None),
'is_active': section['is_active']
}
for section in library_sections:
section_ids.append(helpers.cast_to_int(section['section_id']))
result = monitor_db.upsert('library_sections', key_dict=section_keys, value_dict=section_values)
section_keys = {'server_id': server_id,
'section_id': section['section_id']}
section_values = {'server_id': server_id,
'section_id': section['section_id'],
'section_name': section['section_name'],
'section_type': section['section_type'],
'agent': section['agent'],
'thumb': section['thumb'],
'art': section['art'],
'count': section['count'],
'parent_count': section.get('parent_count', None),
'child_count': section.get('child_count', None),
'is_active': section['is_active']
}
library_keys.append(section['section_id'])
result = monitor_db.upsert('library_sections', key_dict=section_keys, value_dict=section_values)
if result == 'insert':
new_keys.append(section['section_id'])
library_keys.append(section['section_id'])
add_live_tv_library(refresh=True)
if result == 'insert':
new_keys.append(section['section_id'])
query = "UPDATE library_sections SET is_active = 0 WHERE server_id != ? OR " \
"section_id NOT IN ({})".format(", ".join(["?"] * len(section_ids)))
monitor_db.action(query=query, args=[plexpy.CONFIG.PMS_IDENTIFIER] + section_ids)
add_live_tv_library(refresh=True)
new_keys = plexpy.CONFIG.HOME_LIBRARY_CARDS + new_keys
plexpy.CONFIG.__setattr__('HOME_LIBRARY_CARDS', new_keys)
plexpy.CONFIG.write()
# query = "UPDATE library_sections SET is_active = 0 WHERE server_id != ? OR " \
# "section_id NOT IN ({})".format(", ".join(["?"] * len(section_ids)))
# monitor_db.action(query=query, args=[plexpy.CONFIG.PMS_IDENTIFIER] + section_ids)
logger.info("Tautulli Libraries :: Libraries list refreshed.")
return True
else:
logger.warn("Tautulli Libraries :: Unable to refresh libraries list.")
return False
new_keys = plexpy.CONFIG.HOME_LIBRARY_CARDS + new_keys
plexpy.CONFIG.__setattr__('HOME_LIBRARY_CARDS', new_keys)
plexpy.CONFIG.write()
logger.info("Tautulli Libraries :: Libraries list refreshed.")
else:
logger.warn("Tautulli Libraries :: Unable to refresh libraries list.")
passed = False
return passed
def add_live_tv_library(refresh=False):
@ -439,7 +443,8 @@ class Libraries(object):
'do_notify': item['do_notify'],
'do_notify_created': item['do_notify_created'],
'keep_history': item['keep_history'],
'is_active': item['is_active']
'is_active': item['is_active'],
'server_id': item['server_id']
}
rows.append(row)
@ -519,63 +524,62 @@ class Libraries(object):
# If no cache was imported, get all library children items
cached_items = {d['rating_key']: d['file_size'] for d in rows} if not refresh else {}
for pms_connect in server_manager.ServerManger().get_server_list():
if refresh or not 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,
section_id=section_id,
section_type=section_type,
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['children_list']
else:
logger.warn("Tautulli Libraries :: Unable to get a list of library items.")
return default_return
if rating_key:
library_children = pms_connect.get_library_children_details(rating_key=rating_key,
section_id=section_id,
section_type=section_type,
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['children_list']
else:
logger.warn("Tautulli Libraries :: Unable to get a list of library items.")
return default_return
new_rows = []
for item in children_list:
## TODO: Check list of media info items, currently only grabs first item
new_rows = []
for item in children_list:
## TODO: Check list of media info items, currently only grabs first item
cached_file_size = cached_items.get(item['rating_key'], None)
file_size = cached_file_size if cached_file_size else item.get('file_size', '')
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'],
'sort_title': item['sort_title'] or 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
}
new_rows.append(row)
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'],
'sort_title': item['sort_title'] or 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
}
new_rows.append(row)
rows = new_rows
if not rows:
return default_return
rows = new_rows
if not rows:
return default_return
# Cache the media info to a json file
self._save_media_info_cache(section_id=section_id, rating_key=rating_key, rows=rows)
# Cache the media info to a json file
self._save_media_info_cache(section_id=section_id, rating_key=rating_key, rows=rows)
# Update the last_played and play_count
for item in rows:
@ -670,29 +674,28 @@ class Libraries(object):
elif section_id:
logger.debug("Tautulli Libraries :: Fetting file sizes for section_id %s." % section_id)
pms_connect = pmsconnect.PmsConnect()
for pms_connect in server_manager.ServerManger().get_server_list():
for item in rows:
if item['rating_key'] and not item['file_size']:
file_size = 0
for item in rows:
if item['rating_key'] and not item['file_size']:
file_size = 0
metadata = pms_connect.get_metadata_children_details(rating_key=item['rating_key'],
get_children=True,
media_type=item['media_type'],
section_id=section_id)
metadata = pms_connect.get_metadata_children_details(rating_key=item['rating_key'],
get_children=True,
media_type=item['media_type'],
section_id=section_id)
for child_metadata in metadata:
## TODO: Check list of media info items, currently only grabs first item
media_info = media_part_info = {}
if 'media_info' in child_metadata and len(child_metadata['media_info']) > 0:
media_info = child_metadata['media_info'][0]
if 'parts' in media_info and len (media_info['parts']) > 0:
media_part_info = next((p for p in media_info['parts'] if p['selected']),
media_info['parts'][0])
for child_metadata in metadata:
## TODO: Check list of media info items, currently only grabs first item
media_info = media_part_info = {}
if 'media_info' in child_metadata and len(child_metadata['media_info']) > 0:
media_info = child_metadata['media_info'][0]
if 'parts' in media_info and len (media_info['parts']) > 0:
media_part_info = next((p for p in media_info['parts'] if p['selected']),
media_info['parts'][0])
file_size += helpers.cast_to_int(media_part_info.get('file_size', 0))
file_size += helpers.cast_to_int(media_part_info.get('file_size', 0))
item['file_size'] = file_size
item['file_size'] = file_size
# Cache the media info to a json file
self._save_media_info_cache(section_id=section_id, rating_key=rating_key, rows=rows)
@ -1018,7 +1021,7 @@ class Libraries(object):
return session.mask_session_info(user_stats, mask_metadata=False)
def get_recently_watched(self, section_id=None, limit='10'):
def get_recently_watched(self, section_id=None, limit='10', server_id=None):
if not session.allow_session_library(section_id):
return []
@ -1037,7 +1040,7 @@ class Libraries(object):
"year, originally_available_at, added_at, live, started, user, content_rating, labels, section_id " \
"FROM session_history_metadata " \
"JOIN session_history ON session_history_metadata.id = session_history.id " \
"WHERE section_id = ? " \
"WHERE section_id = ? and server_id = '" + server_id + "' " \
"GROUP BY session_history.rating_key " \
"ORDER BY MAX(started) DESC LIMIT ?"
result = monitor_db.select(query, args=[section_id, limit])
@ -1075,6 +1078,7 @@ class Libraries(object):
'user': row['user'],
'section_id': row['section_id'],
'content_rating': row['content_rating'],
'server_id': row['server_id'],
'labels': row['labels'].split(';') if row['labels'] else (),
}
recently_watched.append(recent_output)

View file

@ -37,7 +37,7 @@ if plexpy.PYTHON2:
import libraries
import logger
import newsletter_handler
import pmsconnect
import server_manager
from notifiers import send_notification, EMAIL
else:
from plexpy import common
@ -46,7 +46,7 @@ else:
from plexpy import libraries
from plexpy import logger
from plexpy import newsletter_handler
from plexpy import pmsconnect
from plexpy import server_manager
from plexpy.notifiers import send_notification, EMAIL
@ -706,125 +706,125 @@ class RecentlyAdded(Newsletter):
def _get_recently_added(self, media_type=None):
from plexpy.notification_handler import format_group_index
pms_connect = pmsconnect.PmsConnect()
for pms_connect in server_manager.ServerManger().get_server_list():
recently_added = []
done = False
start = 0
recently_added = []
done = False
start = 0
while not done:
recent_items = pms_connect.get_recently_added_details(start=str(start), count='10', media_type=media_type)
filtered_items = [i for i in recent_items['recently_added']
if self.start_time < helpers.cast_to_int(i['added_at'])]
if len(filtered_items) < 10:
done = True
else:
start += 10
while not done:
recent_items = pms_connect.get_recently_added_details(start=str(start), count='10', media_type=media_type)
filtered_items = [i for i in recent_items['recently_added']
if self.start_time < helpers.cast_to_int(i['added_at'])]
if len(filtered_items) < 10:
done = True
else:
start += 10
recently_added.extend(filtered_items)
recently_added.extend(filtered_items)
if media_type in ('movie', 'other_video'):
movie_list = []
for item in recently_added:
# Filter included libraries
if item['section_id'] not in self.config['incl_libraries']:
continue
if media_type in ('movie', 'other_video'):
movie_list = []
for item in recently_added:
# Filter included libraries
if item['section_id'] not in self.config['incl_libraries']:
continue
if self.start_time < helpers.cast_to_int(item['added_at']) < self.end_time:
movie_list.append(item)
if self.start_time < helpers.cast_to_int(item['added_at']) < self.end_time:
movie_list.append(item)
recently_added = movie_list
recently_added += movie_list
if media_type == 'show':
shows_list = []
show_rating_keys = []
for item in recently_added:
# Filter included libraries
if item['section_id'] not in self.config['incl_libraries']:
continue
if media_type == 'show':
shows_list = []
show_rating_keys = []
for item in recently_added:
# Filter included libraries
if item['section_id'] not in self.config['incl_libraries']:
continue
if item['media_type'] == 'show':
show_rating_key = item['rating_key']
elif item['media_type'] == 'season':
show_rating_key = item['parent_rating_key']
elif item['media_type'] == 'episode':
show_rating_key = item['grandparent_rating_key']
if item['media_type'] == 'show':
show_rating_key = item['rating_key']
elif item['media_type'] == 'season':
show_rating_key = item['parent_rating_key']
elif item['media_type'] == 'episode':
show_rating_key = item['grandparent_rating_key']
if show_rating_key in show_rating_keys:
continue
if show_rating_key in show_rating_keys:
continue
show_metadata = pms_connect.get_metadata_details(show_rating_key, media_info=False)
children = pms_connect.get_item_children(show_rating_key, media_type=media_type, get_grandchildren=True)
filtered_children = [i for i in children['children_list']
if self.start_time < helpers.cast_to_int(i['added_at']) < self.end_time]
filtered_children.sort(key=lambda x: helpers.cast_to_int(x['parent_media_index']))
show_metadata = pms_connect.get_metadata_details(show_rating_key, media_info=False)
children = pms_connect.get_item_children(show_rating_key, media_type=media_type, get_grandchildren=True)
filtered_children = [i for i in children['children_list']
if self.start_time < helpers.cast_to_int(i['added_at']) < self.end_time]
filtered_children.sort(key=lambda x: helpers.cast_to_int(x['parent_media_index']))
if not filtered_children:
continue
if not filtered_children:
continue
seasons = []
for (index, title), children in groupby(filtered_children,
key=lambda x: (x['parent_media_index'], x['parent_title'])):
episodes = list(children)
num, num00 = format_group_index([helpers.cast_to_int(d['media_index']) for d in episodes])
seasons = []
for (index, title), children in groupby(filtered_children,
key=lambda x: (x['parent_media_index'], x['parent_title'])):
episodes = list(children)
num, num00 = format_group_index([helpers.cast_to_int(d['media_index']) for d in episodes])
seasons.append({'media_index': index,
'title': title,
'episode_range': num00,
'episode_count': len(episodes),
'episode': episodes})
seasons.append({'media_index': index,
'title': title,
'episode_range': num00,
'episode_count': len(episodes),
'episode': episodes})
num, num00 = format_group_index([helpers.cast_to_int(d['media_index']) for d in seasons])
num, num00 = format_group_index([helpers.cast_to_int(d['media_index']) for d in seasons])
show_metadata['season_range'] = num00
show_metadata['season_count'] = len(seasons)
show_metadata['season'] = seasons
show_metadata['season_range'] = num00
show_metadata['season_count'] = len(seasons)
show_metadata['season'] = seasons
shows_list.append(show_metadata)
show_rating_keys.append(show_rating_key)
shows_list.append(show_metadata)
show_rating_keys.append(show_rating_key)
recently_added = shows_list
recently_added += shows_list
if media_type == 'artist':
artists_list = []
artist_rating_keys = []
for item in recently_added:
# Filter included libraries
if item['section_id'] not in self.config['incl_libraries']:
continue
if media_type == 'artist':
artists_list = []
artist_rating_keys = []
for item in recently_added:
# Filter included libraries
if item['section_id'] not in self.config['incl_libraries']:
continue
if item['media_type'] == 'artist':
artist_rating_key = item['rating_key']
elif item['media_type'] == 'album':
artist_rating_key = item['parent_rating_key']
elif item['media_type'] == 'track':
artist_rating_key = item['grandparent_rating_key']
if item['media_type'] == 'artist':
artist_rating_key = item['rating_key']
elif item['media_type'] == 'album':
artist_rating_key = item['parent_rating_key']
elif item['media_type'] == 'track':
artist_rating_key = item['grandparent_rating_key']
if artist_rating_key in artist_rating_keys:
continue
if artist_rating_key in artist_rating_keys:
continue
artist_metadata = pms_connect.get_metadata_details(artist_rating_key, media_info=False)
children = pms_connect.get_item_children(artist_rating_key, media_type=media_type)
filtered_children = [i for i in children['children_list']
if self.start_time < helpers.cast_to_int(i['added_at']) < self.end_time]
filtered_children.sort(key=lambda x: x['added_at'])
artist_metadata = pms_connect.get_metadata_details(artist_rating_key, media_info=False)
children = pms_connect.get_item_children(artist_rating_key, media_type=media_type)
filtered_children = [i for i in children['children_list']
if self.start_time < helpers.cast_to_int(i['added_at']) < self.end_time]
filtered_children.sort(key=lambda x: x['added_at'])
if not filtered_children:
continue
if not filtered_children:
continue
albums = []
for a in filtered_children:
album_metadata = pms_connect.get_metadata_details(a['rating_key'], media_info=False)
album_metadata['track_count'] = helpers.cast_to_int(album_metadata['children_count'])
albums.append(album_metadata)
albums = []
for a in filtered_children:
album_metadata = pms_connect.get_metadata_details(a['rating_key'], media_info=False)
album_metadata['track_count'] = helpers.cast_to_int(album_metadata['children_count'])
albums.append(album_metadata)
artist_metadata['album_count'] = len(albums)
artist_metadata['album'] = albums
artist_metadata['album_count'] = len(albums)
artist_metadata['album'] = albums
artists_list.append(artist_metadata)
artist_rating_keys.append(artist_rating_key)
artists_list.append(artist_metadata)
artist_rating_keys.append(artist_rating_key)
recently_added = artists_list
recently_added += artists_list
return recently_added

View file

@ -47,8 +47,8 @@ if plexpy.PYTHON2:
import logger
import helpers
import notifiers
import pmsconnect
import request
import server_manager
from newsletter_handler import notify as notify_newsletter
else:
from plexpy import activity_processor
@ -58,8 +58,8 @@ else:
from plexpy import logger
from plexpy import helpers
from plexpy import notifiers
from plexpy import pmsconnect
from plexpy import request
from plexpy import server_manager
from plexpy.newsletter_handler import notify as notify_newsletter
@ -180,23 +180,23 @@ def notify_conditions(notify_action=None, stream_data=None, timeline_data=None,
# return False
if notify_action == 'on_concurrent':
pms_connect = pmsconnect.PmsConnect()
result = pms_connect.get_current_activity()
for pms_connect in server_manager.ServerManger().get_server_list():
result = pms_connect.get_current_activity()
user_sessions = []
if result:
user_sessions = [s for s in result['sessions'] if s['user_id'] == stream_data['user_id']]
user_sessions = []
if result:
user_sessions = [s for s in result['sessions'] if s['user_id'] == stream_data['user_id']]
if plexpy.CONFIG.NOTIFY_CONCURRENT_BY_IP:
ip_addresses = set()
for s in user_sessions:
if helpers.ip_type(s['ip_address']) == 'IPv6':
ip_addresses.add(helpers.get_ipv6_network_address(s['ip_address']))
elif helpers.ip_type(s['ip_address']) == 'IPv4':
ip_addresses.add(s['ip_address'])
evaluated = len(ip_addresses) >= plexpy.CONFIG.NOTIFY_CONCURRENT_THRESHOLD
else:
evaluated = len(user_sessions) >= plexpy.CONFIG.NOTIFY_CONCURRENT_THRESHOLD
if plexpy.CONFIG.NOTIFY_CONCURRENT_BY_IP:
ip_addresses = set()
for s in user_sessions:
if helpers.ip_type(s['ip_address']) == 'IPv6':
ip_addresses.add(helpers.get_ipv6_network_address(s['ip_address']))
elif helpers.ip_type(s['ip_address']) == 'IPv4':
ip_addresses.add(s['ip_address'])
evaluated = len(ip_addresses) >= plexpy.CONFIG.NOTIFY_CONCURRENT_THRESHOLD
else:
evaluated = len(user_sessions) >= plexpy.CONFIG.NOTIFY_CONCURRENT_THRESHOLD
elif notify_action == 'on_newdevice':
data_factory = datafactory.DataFactory()
@ -595,18 +595,18 @@ def build_media_notify_params(notify_action=None, session=None, timeline=None, m
notify_params.update(media_info)
notify_params.update(media_part_info)
for pmsconnect in server_manager.ServerManger().get_server_list():
metadata = pmsconnect.get_metadata_details(rating_key=rating_key)
metadata = pmsconnect.PmsConnect().get_metadata_details(rating_key=rating_key)
child_metadata = grandchild_metadata = []
for key in kwargs.pop('child_keys', []):
child = pmsconnect.PmsConnect().get_metadata_details(rating_key=key)
if child:
child_metadata.append(child)
for key in kwargs.pop('grandchild_keys', []):
grandchild = pmsconnect.PmsConnect().get_metadata_details(rating_key=key)
if grandchild:
grandchild_metadata.append(grandchild)
child_metadata = grandchild_metadata = []
for key in kwargs.pop('child_keys', []):
child = pmsconnect.get_metadata_details(rating_key=key)
if child:
child_metadata.append(child)
for key in kwargs.pop('grandchild_keys', []):
grandchild = pmsconnect.get_metadata_details(rating_key=key)
if grandchild:
grandchild_metadata.append(grandchild)
# Session values
session = session or {}
@ -1235,83 +1235,84 @@ def build_server_notify_params(notify_action=None, **kwargs):
date_format = plexpy.CONFIG.DATE_FORMAT.replace('Do','')
time_format = plexpy.CONFIG.TIME_FORMAT.replace('Do','')
update_channel = pmsconnect.PmsConnect().get_server_update_channel()
for pmsconnect in server_manager.ServerManger().get_server_list():
update_channel = pmsconnect.get_server_update_channel()
pms_download_info = defaultdict(str, kwargs.pop('pms_download_info', {}))
plexpy_download_info = defaultdict(str, kwargs.pop('plexpy_download_info', {}))
remote_access_info = defaultdict(str, kwargs.pop('remote_access_info', {}))
pms_download_info = defaultdict(str, kwargs.pop('pms_download_info', {}))
plexpy_download_info = defaultdict(str, kwargs.pop('plexpy_download_info', {}))
remote_access_info = defaultdict(str, kwargs.pop('remote_access_info', {}))
windows_exe = macos_pkg = ''
if plexpy_download_info:
release_assets = plexpy_download_info.get('assets', [])
for asset in release_assets:
if asset['content_type'] == 'application/vnd.microsoft.portable-executable':
windows_exe = asset['browser_download_url']
elif asset['content_type'] == 'application/vnd.apple.installer+xml':
macos_pkg = asset['browser_download_url']
windows_exe = macos_pkg = ''
if plexpy_download_info:
release_assets = plexpy_download_info.get('assets', [])
for asset in release_assets:
if asset['content_type'] == 'application/vnd.microsoft.portable-executable':
windows_exe = asset['browser_download_url']
elif asset['content_type'] == 'application/vnd.apple.installer+xml':
macos_pkg = asset['browser_download_url']
now = arrow.now()
now_iso = now.isocalendar()
now = arrow.now()
now_iso = now.isocalendar()
available_params = {
# Global paramaters
'tautulli_version': common.RELEASE,
'tautulli_remote': plexpy.CONFIG.GIT_REMOTE,
'tautulli_branch': plexpy.CONFIG.GIT_BRANCH,
'tautulli_commit': plexpy.CURRENT_VERSION,
'server_name': helpers.pms_name(),
'server_ip': plexpy.CONFIG.PMS_IP,
'server_port': plexpy.CONFIG.PMS_PORT,
'server_url': plexpy.CONFIG.PMS_URL,
'server_platform': plexpy.CONFIG.PMS_PLATFORM,
'server_version': plexpy.CONFIG.PMS_VERSION,
'server_machine_id': plexpy.CONFIG.PMS_IDENTIFIER,
'action': notify_action.split('on_')[-1],
'current_year': now.year,
'current_month': now.month,
'current_day': now.day,
'current_hour': now.hour,
'current_minute': now.minute,
'current_second': now.second,
'current_weekday': now_iso[2],
'current_week': now_iso[1],
'week_number': now_iso[1], # Keep for backwards compatibility
'datestamp': now.format(date_format),
'timestamp': now.format(time_format),
'unixtime': helpers.timestamp(),
'utctime': helpers.utc_now_iso(),
# Plex remote access parameters
'remote_access_mapping_state': remote_access_info['mapping_state'],
'remote_access_mapping_error': remote_access_info['mapping_error'],
'remote_access_public_address': remote_access_info['public_address'],
'remote_access_public_port': remote_access_info['public_port'],
'remote_access_private_address': remote_access_info['private_address'],
'remote_access_private_port': remote_access_info['private_port'],
'remote_access_reason': remote_access_info['reason'],
# Plex Media Server update parameters
'update_version': pms_download_info['version'],
'update_url': pms_download_info['download_url'],
'update_release_date': arrow.get(pms_download_info['release_date']).format(date_format)
if pms_download_info['release_date'] else '',
'update_channel': 'Beta' if update_channel == 'beta' else 'Public',
'update_platform': pms_download_info['platform'],
'update_distro': pms_download_info['distro'],
'update_distro_build': pms_download_info['build'],
'update_requirements': pms_download_info['requirements'],
'update_extra_info': pms_download_info['extra_info'],
'update_changelog_added': pms_download_info['changelog_added'],
'update_changelog_fixed': pms_download_info['changelog_fixed'],
# Tautulli update parameters
'tautulli_update_version': plexpy_download_info['tag_name'],
'tautulli_update_release_url': plexpy_download_info['html_url'],
'tautulli_update_exe': windows_exe,
'tautulli_update_pkg': macos_pkg,
'tautulli_update_tar': plexpy_download_info['tarball_url'],
'tautulli_update_zip': plexpy_download_info['zipball_url'],
'tautulli_update_commit': kwargs.pop('plexpy_update_commit', ''),
'tautulli_update_behind': kwargs.pop('plexpy_update_behind', ''),
'tautulli_update_changelog': plexpy_download_info['body']
}
available_params = {
# Global paramaters
'tautulli_version': common.RELEASE,
'tautulli_remote': plexpy.CONFIG.GIT_REMOTE,
'tautulli_branch': plexpy.CONFIG.GIT_BRANCH,
'tautulli_commit': plexpy.CURRENT_VERSION,
'server_name': helpers.pms_name(),
'server_ip': plexpy.CONFIG.PMS_IP,
'server_port': plexpy.CONFIG.PMS_PORT,
'server_url': plexpy.CONFIG.PMS_URL,
'server_platform': plexpy.CONFIG.PMS_PLATFORM,
'server_version': plexpy.CONFIG.PMS_VERSION,
'server_machine_id': plexpy.CONFIG.PMS_IDENTIFIER,
'action': notify_action.split('on_')[-1],
'current_year': now.year,
'current_month': now.month,
'current_day': now.day,
'current_hour': now.hour,
'current_minute': now.minute,
'current_second': now.second,
'current_weekday': now_iso[2],
'current_week': now_iso[1],
'week_number': now_iso[1], # Keep for backwards compatibility
'datestamp': now.format(date_format),
'timestamp': now.format(time_format),
'unixtime': helpers.timestamp(),
'utctime': helpers.utc_now_iso(),
# Plex remote access parameters
'remote_access_mapping_state': remote_access_info['mapping_state'],
'remote_access_mapping_error': remote_access_info['mapping_error'],
'remote_access_public_address': remote_access_info['public_address'],
'remote_access_public_port': remote_access_info['public_port'],
'remote_access_private_address': remote_access_info['private_address'],
'remote_access_private_port': remote_access_info['private_port'],
'remote_access_reason': remote_access_info['reason'],
# Plex Media Server update parameters
'update_version': pms_download_info['version'],
'update_url': pms_download_info['download_url'],
'update_release_date': arrow.get(pms_download_info['release_date']).format(date_format)
if pms_download_info['release_date'] else '',
'update_channel': 'Beta' if update_channel == 'beta' else 'Public',
'update_platform': pms_download_info['platform'],
'update_distro': pms_download_info['distro'],
'update_distro_build': pms_download_info['build'],
'update_requirements': pms_download_info['requirements'],
'update_extra_info': pms_download_info['extra_info'],
'update_changelog_added': pms_download_info['changelog_added'],
'update_changelog_fixed': pms_download_info['changelog_fixed'],
# Tautulli update parameters
'tautulli_update_version': plexpy_download_info['tag_name'],
'tautulli_update_release_url': plexpy_download_info['html_url'],
'tautulli_update_exe': windows_exe,
'tautulli_update_pkg': macos_pkg,
'tautulli_update_tar': plexpy_download_info['tarball_url'],
'tautulli_update_zip': plexpy_download_info['zipball_url'],
'tautulli_update_commit': kwargs.pop('plexpy_update_commit', ''),
'tautulli_update_behind': kwargs.pop('plexpy_update_behind', ''),
'tautulli_update_changelog': plexpy_download_info['body']
}
return available_params
@ -1551,47 +1552,47 @@ def get_img_info(img=None, rating_key=None, title='', width=1000, height=1500,
img_info = database_img_info[0]
elif not database_img_info and img:
pms_connect = pmsconnect.PmsConnect()
result = pms_connect.get_image(refresh=True, **image_info)
for pms_connect in server_manager.ServerManger().get_server_list():
result = pms_connect.get_image(refresh=True, **image_info)
if result and result[0]:
img_url = delete_hash = ''
if result and result[0]:
img_url = delete_hash = ''
if service == 'imgur':
img_url, delete_hash = helpers.upload_to_imgur(img_data=result[0],
img_title=title,
rating_key=rating_key,
fallback=fallback)
elif service == 'cloudinary':
img_url = helpers.upload_to_cloudinary(img_data=result[0],
img_title=title,
rating_key=rating_key,
fallback=fallback)
if service == 'imgur':
img_url, delete_hash = helpers.upload_to_imgur(img_data=result[0],
img_title=title,
rating_key=rating_key,
fallback=fallback)
elif service == 'cloudinary':
img_url = helpers.upload_to_cloudinary(img_data=result[0],
img_title=title,
rating_key=rating_key,
fallback=fallback)
if img_url:
img_hash = set_hash_image_info(**image_info)
data_factory.set_img_info(img_hash=img_hash,
img_title=title,
img_url=img_url,
delete_hash=delete_hash,
service=service)
if img_url:
img_hash = set_hash_image_info(**image_info)
data_factory.set_img_info(img_hash=img_hash,
img_title=title,
img_url=img_url,
delete_hash=delete_hash,
service=service)
img_info = {'img_title': title, 'img_url': img_url}
img_info = {'img_title': title, 'img_url': img_url}
if img_info['img_url'] and service == 'cloudinary':
# Transform image using Cloudinary
image_info = {'rating_key': rating_key,
'width': width,
'height': height,
'opacity': opacity,
'background': background,
'blur': blur,
'fallback': fallback,
'img_title': title}
if img_info['img_url'] and service == 'cloudinary':
# Transform image using Cloudinary
image_info = {'rating_key': rating_key,
'width': width,
'height': height,
'opacity': opacity,
'background': background,
'blur': blur,
'fallback': fallback,
'img_title': title}
transformed_url = helpers.cloudinary_transform(**image_info)
if transformed_url:
img_info['img_url'] = transformed_url
transformed_url = helpers.cloudinary_transform(**image_info)
if transformed_url:
img_info['img_url'] = transformed_url
return img_info

View file

@ -67,7 +67,7 @@ if plexpy.PYTHON2:
import helpers
import logger
import mobile_app
import pmsconnect
import server_manager
import request
import users
else:
@ -76,7 +76,7 @@ else:
from plexpy import helpers
from plexpy import logger
from plexpy import mobile_app
from plexpy import pmsconnect
from plexpy import server_manager
from plexpy import request
from plexpy import users

View file

@ -603,6 +603,7 @@ class PmsConnect(object):
for guid in m.getElementsByTagName('Guid'):
guids.append(helpers.get_xml_attr(guid, 'id'))
server_info = self.get_server_info()
recent_item = {'media_type': helpers.get_xml_attr(m, 'type'),
'section_id': helpers.get_xml_attr(m, 'librarySectionID'),
'library_name': helpers.get_xml_attr(m, 'librarySectionTitle'),
@ -645,7 +646,8 @@ class PmsConnect(object):
'collections': collections,
'guids': guids,
'full_title': helpers.get_xml_attr(m, 'title'),
'child_count': helpers.get_xml_attr(m, 'childCount')
'child_count': helpers.get_xml_attr(m, 'childCount'),
'server_id': server_info['machine_identifier']
}
recents_list.append(recent_item)
@ -2294,6 +2296,7 @@ class PmsConnect(object):
synced_version_profile = ''
optimized_version_profile = ''
server_info = self.get_server_info()
# Entire session output (single dict for backwards compatibility)
session_output = {'session_key': session_key,
'media_type': media_type,
@ -2303,7 +2306,11 @@ class PmsConnect(object):
'synced_version_profile': synced_version_profile,
'optimized_version_profile': optimized_version_profile,
'user': user_details['username'], # Keep for backwards compatibility
'channel_stream': channel_stream
'channel_stream': channel_stream,
'server_id': server_info['machine_identifier'],
'server_name': server_info['name'],
'server_ip': server_info['host'],
'server_port': server_info['port'],
}
session_output.update(metadata_details)
@ -2492,7 +2499,8 @@ class PmsConnect(object):
'genres': genres,
'labels': labels,
'collections': collections,
'full_title': helpers.get_xml_attr(m, 'title')
'full_title': helpers.get_xml_attr(m, 'title'),
'server_id': self.get_server_info()['machine_identifier']
}
children_list.append(children_output)
@ -2597,6 +2605,20 @@ class PmsConnect(object):
return server_info
def get_server_info(self):
"""
Return the base info of the current pms connection.
Output: dict
"""
server_info = {}
servers = self.get_servers_info()
current = self.get_server_identity()
for server in servers:
if server['machine_identifier'] == current['machine_identifier']:
server_info = server
return server_info
def get_server_identity(self):
"""
Return the local machine identity.
@ -2614,7 +2636,7 @@ class PmsConnect(object):
server_identity = {}
for a in xml_head:
server_identity = {"machine_identifier": helpers.get_xml_attr(a, 'machineIdentifier'),
"version": helpers.get_xml_attr(a, 'version')
"version": helpers.get_xml_attr(a, 'version'),
}
return server_identity

44
plexpy/server_manager.py Normal file
View file

@ -0,0 +1,44 @@
# -*- coding: utf-8 -*-
# This file is part of Tautulli.
#
# Tautulli 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.
#
# Tautulli 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 Tautulli. If not, see <http://www.gnu.org/licenses/>.
import plexpy
if plexpy.PYTHON2:
import pmsconnect
else:
from plexpy import pmsconnect
class ServerManger(object):
"""
Return processed and validated library statistics.
Output: array
"""
def get_server_list(self):
pmsServers = []
for server in pmsconnect.PmsConnect().get_servers_info():
url = 'http://{hostname}:{port}'.format(hostname=server["host"], port=server["port"])
pmsServers.append(pmsconnect.PmsConnect(url=url))
return pmsServers
def get_server(self, server_id):
if server_id is not None:
for server in pmsconnect.PmsConnect().get_servers_info():
if server['machine_identifier'] == server_id:
url = 'http://{hostname}:{port}'.format(hostname=server["host"], port=server["port"])
return pmsconnect.PmsConnect(url=url)
return None

View file

@ -35,12 +35,14 @@ if plexpy.PYTHON2:
import activity_processor
import database
import logger
import server_manager
else:
from plexpy import activity_handler
from plexpy import activity_pinger
from plexpy import activity_processor
from plexpy import database
from plexpy import logger
from plexpy import server_manager
name = 'websocket'

View file

@ -76,6 +76,7 @@ if plexpy.PYTHON2:
import versioncheck
import web_socket
import webstart
import server_manager
from api2 import API2
from helpers import checked, addtoapi, get_ip, create_https_certificates, build_datatables_json, sanitize_out
from session import get_session_info, get_session_user_id, allow_session_user, allow_session_library
@ -111,6 +112,7 @@ else:
from plexpy import versioncheck
from plexpy import web_socket
from plexpy import webstart
from plexpy import server_manager
from plexpy.api2 import API2
from plexpy.helpers import checked, addtoapi, get_ip, create_https_certificates, build_datatables_json, sanitize_out
from plexpy.session import get_session_info, get_session_user_id, allow_session_user, allow_session_library
@ -141,7 +143,7 @@ def serve_template(template_name, **kwargs):
try:
template = TEMPLATE_LOOKUP.get_template(template_name)
return template.render(http_root=http_root, server_name=server_name, cache_param=cache_param,
_session=_session, **kwargs)
_session=_session, server_id="test2", **kwargs)
except Exception as e:
logger.exception("WebUI :: Mako template render error: %s" % e)
return mako.exceptions.html_error_template().render()
@ -333,10 +335,17 @@ class WebInterface(object):
@cherrypy.expose
@requireAuth()
def get_current_activity(self, **kwargs):
result = {
'stream_count':0,
'sessions': []
}
for server in server_manager.ServerManger().get_server_list():
res = server.get_current_activity()
if len(res['sessions']) > 0:
result['sessions'] += res['sessions']
pms_connect = pmsconnect.PmsConnect(token=plexpy.CONFIG.PMS_TOKEN)
result = pms_connect.get_current_activity()
result['stream_count'] = len(result['sessions'])
if result:
return serve_template(template_name="current_activity.html", data=result)
else:
@ -347,9 +356,17 @@ class WebInterface(object):
@requireAuth()
def get_current_activity_instance(self, session_key=None, **kwargs):
pms_connect = pmsconnect.PmsConnect(token=plexpy.CONFIG.PMS_TOKEN)
result = pms_connect.get_current_activity()
result = {
'stream_count':0,
'sessions': []
}
for server in server_manager.ServerManger().get_server_list():
res = server.get_current_activity()
if len(res['sessions']) > 0:
result['sessions'] += res['sessions']
result['stream_count'] = len(result['sessions'])
if result:
session = next((s for s in result['sessions'] if s['session_key'] == session_key), None)
return serve_template(template_name="current_activity_instance.html", session=session)
@ -360,7 +377,7 @@ class WebInterface(object):
@cherrypy.tools.json_out()
@requireAuth(member_of("admin"))
@addtoapi()
def terminate_session(self, session_key='', session_id='', message='', **kwargs):
def terminate_session(self, session_key='', session_id='', message='', server_id=None, **kwargs):
""" Stop a streaming session.
```
@ -375,7 +392,7 @@ class WebInterface(object):
None
```
"""
pms_connect = pmsconnect.PmsConnect()
pms_connect = server_manager.ServerManger().get_server(server_id=server_id)
result = pms_connect.terminate_session(session_key=session_key, session_id=session_id, message=message)
if isinstance(result, str):
@ -422,14 +439,18 @@ class WebInterface(object):
@cherrypy.expose
@requireAuth()
def get_recently_added(self, count='0', media_type='', **kwargs):
def get_recently_added(self, count='0', media_type='', server_id=None, **kwargs):
results =[]
try:
pms_connect = pmsconnect.PmsConnect()
result = pms_connect.get_recently_added_details(count=count, media_type=media_type)
for pms_connect in server_manager.ServerManger().get_server_list():
results += pms_connect.get_recently_added_details(count=count, media_type=media_type)['recently_added']
except IOError as e:
return serve_template(template_name="recently_added.html", data=None)
result = {'recently_added': results}
if result and 'recently_added' in result:
return serve_template(template_name="recently_added.html", data=result['recently_added'])
else:
@ -619,7 +640,7 @@ class WebInterface(object):
@cherrypy.expose
@requireAuth()
def library(self, section_id=None, **kwargs):
def library(self, section_id=None, server_id=None, **kwargs):
if not allow_session_library(section_id):
raise cherrypy.HTTPRedirect(plexpy.HTTP_ROOT)
@ -631,7 +652,7 @@ class WebInterface(object):
if section_id:
try:
library_data = libraries.Libraries()
library_details = library_data.get_details(section_id=section_id)
library_details = library_data.get_details(section_id=section_id, server_id=server_id)
except:
logger.warn("Unable to retrieve library details for section_id %s " % section_id)
return serve_template(template_name="library.html", title="Library", data=None, config=config)
@ -733,13 +754,13 @@ class WebInterface(object):
@cherrypy.expose
@requireAuth()
def library_recently_watched(self, section_id=None, limit='10', **kwargs):
def library_recently_watched(self, section_id=None, limit='10', server_id=None, **kwargs):
if not allow_session_library(section_id):
return serve_template(template_name="user_recently_watched.html", data=None, title="Recently Watched")
if section_id:
library_data = libraries.Libraries()
result = library_data.get_recently_watched(section_id=section_id, limit=limit)
result = library_data.get_recently_watched(section_id=section_id, limit=limit, server_id=server_id)
else:
result = None
@ -751,12 +772,13 @@ class WebInterface(object):
@cherrypy.expose
@requireAuth()
def library_recently_added(self, section_id=None, limit='10', **kwargs):
def library_recently_added(self, section_id=None, limit='10', server_id=None, **kwargs):
if not allow_session_library(section_id):
return serve_template(template_name="library_recently_added.html", data=None, title="Recently Added")
result = []
if section_id:
pms_connect = pmsconnect.PmsConnect()
pms_connect = server_manager.ServerManger().get_server(server_id=server_id)
result = pms_connect.get_recently_added_details(section_id=section_id, count=limit)
else:
result = None
@ -1900,7 +1922,7 @@ class WebInterface(object):
@requireAuth()
@sanitize_out()
@addtoapi()
def get_history(self, user=None, user_id=None, grouping=None, include_activity=None, **kwargs):
def get_history(self, user=None, user_id=None, grouping=None, include_activity=None, server_id=None, **kwargs):
""" Get the Tautulli history.
```
@ -2017,7 +2039,7 @@ class WebInterface(object):
custom_where.append(['session_history.user', user])
if 'rating_key' in kwargs:
if kwargs.get('media_type') in ('collection', 'playlist') and kwargs.get('rating_key'):
pms_connect = pmsconnect.PmsConnect()
pms_connect = server_manager.ServerManger().get_server(server_id=server_id)
result = pms_connect.get_item_children(rating_key=kwargs.pop('rating_key'), media_type=kwargs.pop('media_type'))
rating_keys = [child['rating_key'] for child in result['children_list']]
custom_where.append(['session_history_metadata.rating_key OR', rating_keys])
@ -4385,7 +4407,7 @@ class WebInterface(object):
@cherrypy.expose
@requireAuth()
def info(self, rating_key=None, guid=None, source=None, section_id=None, user_id=None, **kwargs):
def info(self, rating_key=None, guid=None, source=None, section_id=None, user_id=None, server_id=None, **kwargs):
if rating_key and not str(rating_key).isdigit():
raise cherrypy.HTTPRedirect(plexpy.HTTP_ROOT)
@ -4404,8 +4426,9 @@ class WebInterface(object):
# Try to get metadata from the Plex server first
if rating_key:
pms_connect = pmsconnect.PmsConnect()
pms_connect = server_manager.ServerManger().get_server(server_id=server_id)
metadata = pms_connect.get_metadata_details(rating_key=rating_key, section_id=section_id)
metadata['server_id'] = pms_connect.get_server_info()['machine_identifier']
# If the item is not found on the Plex server, get the metadata from history
if not metadata and source == 'history':
@ -4433,10 +4456,12 @@ class WebInterface(object):
@cherrypy.expose
@requireAuth()
def get_item_children(self, rating_key='', media_type=None, **kwargs):
def get_item_children(self, rating_key='', media_type=None, server_id=None, **kwargs):
pms_connect = pmsconnect.PmsConnect()
result = pms_connect.get_item_children(rating_key=rating_key, media_type=media_type)
result = None
pms_connect = server_manager.ServerManger().get_server(server_id=server_id)
if pms_connect is not None:
result = pms_connect.get_item_children(rating_key=rating_key, media_type=media_type)
if result:
return serve_template(template_name="info_children_list.html", data=result,
@ -4447,9 +4472,9 @@ class WebInterface(object):
@cherrypy.expose
@requireAuth()
def get_item_children_related(self, rating_key='', title='', **kwargs):
def get_item_children_related(self, rating_key='', title='', server_id=None, **kwargs):
pms_connect = pmsconnect.PmsConnect()
pms_connect = server_manager.ServerManger().get_server(server_id=server_id)
result = pms_connect.get_item_children_related(rating_key=rating_key)
if result:
@ -4601,7 +4626,7 @@ class WebInterface(object):
@cherrypy.tools.json_out()
@requireAuth(member_of("admin"))
@addtoapi("get_children_metadata")
def get_children_metadata_details(self, rating_key='', media_type=None, **kwargs):
def get_children_metadata_details(self, rating_key='', media_type=None, server_id=None, **kwargs):
""" Get the metadata for the children of a media item.
```
@ -4667,7 +4692,7 @@ class WebInterface(object):
}
```
"""
pms_connect = pmsconnect.PmsConnect()
pms_connect = server_manager.ServerManger().get_server(server_id=server_id)
metadata = pms_connect.get_item_children(rating_key=rating_key,
media_type=media_type)
@ -4681,7 +4706,7 @@ class WebInterface(object):
@cherrypy.tools.json_out()
@requireAuth(member_of("admin"))
@addtoapi('notify_recently_added')
def send_manual_on_created(self, notifier_id='', rating_key='', **kwargs):
def send_manual_on_created(self, notifier_id='', rating_key='', server_id=None, **kwargs):
""" Send a recently added notification using Tautulli.
```
@ -4700,7 +4725,7 @@ class WebInterface(object):
```
"""
if rating_key:
pms_connect = pmsconnect.PmsConnect()
pms_connect = server_manager.ServerManger().get_server(server_id=server_id)
metadata = pms_connect.get_metadata_details(rating_key=rating_key)
data = {'timeline_data': metadata, 'notify_action': 'on_created', 'manual_trigger': True}
@ -4733,7 +4758,7 @@ class WebInterface(object):
@addtoapi('pms_image_proxy')
def real_pms_image_proxy(self, img=None, rating_key=None, width=750, height=1000,
opacity=100, background='000000', blur=0, img_format='png',
fallback=None, refresh=False, clip=False, **kwargs):
fallback=None, refresh=False, clip=False, server_id=None, **kwargs):
""" Gets an image from the PMS and saves it to the image cache directory.
```
@ -4817,27 +4842,30 @@ class WebInterface(object):
except NotFound:
# the image does not exist, download it from pms
try:
pms_connect = pmsconnect.PmsConnect()
pms_connect.request_handler._silent = True
result = pms_connect.get_image(img=img,
width=width,
height=height,
opacity=opacity,
background=background,
blur=blur,
img_format=img_format,
clip=clip,
refresh=refresh)
pms_connect = server_manager.ServerManger().get_server(server_id=server_id)
if pms_connect is not None:
pms_connect.request_handler._silent = True
result = pms_connect.get_image(img=img,
width=width,
height=height,
opacity=opacity,
background=background,
blur=blur,
img_format=img_format,
clip=clip,
refresh=refresh)
if result and result[0]:
cherrypy.response.headers['Content-type'] = result[1]
if plexpy.CONFIG.CACHE_IMAGES and 'indexes' not in img:
with open(ffp, 'wb') as f:
f.write(result[0])
if result and result[0]:
cherrypy.response.headers['Content-type'] = result[1]
if plexpy.CONFIG.CACHE_IMAGES and 'indexes' not in img:
with open(ffp, 'wb') as f:
f.write(result[0])
return result[0]
return result[0]
else:
raise Exception('PMS image request failed')
else:
raise Exception('PMS image request failed')
raise Exception('PMS server not found')
except Exception as e:
logger.warn("Failed to get image %s, falling back to %s." % (img, fallback))
@ -5141,8 +5169,9 @@ class WebInterface(object):
}
```
"""
pms_connect = pmsconnect.PmsConnect()
result = pms_connect.get_search_results(query=query, limit=limit)
result = []
for pms_connect in server_manager.ServerManger().get_server_list():
result += pms_connect.get_search_results(query=query, limit=limit)
if result:
return result
@ -5154,8 +5183,9 @@ class WebInterface(object):
@requireAuth()
def get_search_results_children(self, query='', limit='', media_type=None, season_index=None, **kwargs):
pms_connect = pmsconnect.PmsConnect()
result = pms_connect.get_search_results(query=query, limit=limit)
result = []
for pms_connect in server_manager.ServerManger().get_server_list():
result += pms_connect.get_search_results(query=query, limit=limit)
if media_type:
result['results_list'] = {media_type: result['results_list'][media_type]}
@ -5193,7 +5223,7 @@ class WebInterface(object):
@cherrypy.tools.json_out()
@requireAuth(member_of("admin"))
@addtoapi()
def update_metadata_details(self, old_rating_key, new_rating_key, media_type, single_update=False, **kwargs):
def update_metadata_details(self, old_rating_key, new_rating_key, media_type, single_update=False, server_id=None, **kwargs):
""" Update the metadata in the Tautulli database by matching rating keys.
Also updates all parents or children of the media item if it is a show/season/episode
or artist/album/track.
@ -5215,7 +5245,7 @@ class WebInterface(object):
if new_rating_key:
data_factory = datafactory.DataFactory()
pms_connect = pmsconnect.PmsConnect()
pms_connect = server_manager.ServerManger().get_server(server_id=server_id)
old_key_list = data_factory.get_rating_keys_list(rating_key=old_rating_key, media_type=media_type)
new_key_list = pms_connect.get_rating_keys_list(rating_key=new_rating_key, media_type=media_type)
@ -5235,7 +5265,7 @@ class WebInterface(object):
@cherrypy.tools.json_out()
@requireAuth(member_of("admin"))
@addtoapi()
def get_new_rating_keys(self, rating_key='', media_type='', **kwargs):
def get_new_rating_keys(self, rating_key='', media_type='', server_id=None, **kwargs):
""" Get a list of new rating keys for the PMS of all of the item's parent/children.
```
@ -5252,7 +5282,7 @@ class WebInterface(object):
```
"""
pms_connect = pmsconnect.PmsConnect()
pms_connect = server_manager.ServerManger().get_server(server_id=server_id)
result = pms_connect.get_rating_keys_list(rating_key=rating_key, media_type=media_type)
if result:
@ -5296,8 +5326,9 @@ class WebInterface(object):
@requireAuth(member_of("admin"))
def get_pms_sessions_json(self, **kwargs):
""" Get all the current sessions. """
pms_connect = pmsconnect.PmsConnect()
result = pms_connect.get_sessions('json')
result = []
for pms_connect in server_manager.ServerManger().get_server_list():
result += pms_connect.get_sessions('json')
if result:
return result
@ -5309,7 +5340,7 @@ class WebInterface(object):
@cherrypy.tools.json_out()
@requireAuth(member_of("admin"))
@addtoapi("get_metadata")
def get_metadata_details(self, rating_key='', sync_id='', **kwargs):
def get_metadata_details(self, rating_key='', sync_id='', server_id=None, **kwargs):
""" Get the metadata for a media item.
```
@ -5505,7 +5536,7 @@ class WebInterface(object):
}
```
"""
pms_connect = pmsconnect.PmsConnect()
pms_connect = server_manager.ServerManger().get_server(server_id=server_id)
metadata = pms_connect.get_metadata_details(rating_key=rating_key,
sync_id=sync_id)
@ -5600,8 +5631,11 @@ class WebInterface(object):
if 'type' in kwargs:
media_type = kwargs['type']
pms_connect = pmsconnect.PmsConnect()
result = pms_connect.get_recently_added_details(start=start, count=count, media_type=media_type, section_id=section_id)
result =[]
for pms_connect in server_manager.ServerManger().get_server_list():
result = pms_connect.get_recently_added_details(start=start, count=count, media_type=media_type, section_id=section_id)
if result:
return result
@ -5668,7 +5702,8 @@ class WebInterface(object):
@cherrypy.tools.json_out()
@requireAuth(member_of("admin"))
def get_servers(self, **kwargs):
pms_connect = pmsconnect.PmsConnect()
# just grab first one
pms_connect = server_manager.ServerManger().get_server_list()[0]
result = pms_connect.get_server_list(output_format='json')
if result:
@ -5701,7 +5736,7 @@ class WebInterface(object):
]
```
"""
pms_connect = pmsconnect.PmsConnect()
pms_connect = server_manager.ServerManger().get_server_list()[0]
result = pms_connect.get_servers_info()
if result:
@ -5890,6 +5925,7 @@ class WebInterface(object):
"relay": 0,
"section_id": "2",
"secure": 1,
"server_id": XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX
"session_id": "helf15l3rxgw01xxe0jf3l3d",
"session_key": "27",
"shared_libraries": [
@ -6033,8 +6069,18 @@ class WebInterface(object):
```
"""
try:
pms_connect = pmsconnect.PmsConnect(token=plexpy.CONFIG.PMS_TOKEN)
result = pms_connect.get_current_activity()
result = {
'stream_count':0,
'sessions': []
}
for server in server_manager.ServerManger().get_server_list():
res = server.get_current_activity()
if len(res['sessions']) > 0:
result['sessions'] += res['sessions']
result['stream_count'] = len(result['sessions'])
if result:
if session_key:
@ -6103,8 +6149,9 @@ class WebInterface(object):
]
```
"""
pms_connect = pmsconnect.PmsConnect()
result = pms_connect.get_library_details()
result=[]
for pms_connect in server_manager.ServerManger().get_server_list():
result += pms_connect.get_library_details()
if result:
return result
@ -6224,8 +6271,9 @@ class WebInterface(object):
@requireAuth(member_of("admin"))
def get_sync_transcode_queue(self, **kwargs):
""" Return details for currently syncing items. """
pms_connect = pmsconnect.PmsConnect()
result = pms_connect.get_sync_transcode_queue(output_format='json')
result =[]
for pms_connect in server_manager.ServerManger().get_server_list():
result += pms_connect.get_sync_transcode_queue(output_format='json')
if result:
return result