This commit is contained in:
herby2212 2024-10-14 11:34:34 +02:00 committed by GitHub
commit 9e16b6b11b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
19 changed files with 139 additions and 28 deletions

View file

@ -10,14 +10,15 @@ Variable names: data {dict}
data :: Usable parameters data :: Usable parameters
== Global keys == == Global keys ==
session_key Returns a unique session id for the active stream session_key Returns a unique session id for the active stream.
rating_key Returns the unique identifier for the media item. rating_key Returns the unique identifier for the media item.
media_index Returns the index of the media item. media_index Returns the index of the media item.
parent_media_index Returns the index of the media item's parent. parent_media_index Returns the index of the media item's parent.
media_type Returns the type of session. Either 'track', 'episode' or 'movie'. media_type Returns the type of session. Either 'track', 'episode' or 'movie'.
thumb Returns the location of the item's thumbnail. Use with pms_image_proxy. thumb Returns the location of the item's thumbnail. Use with pms_image_proxy.
bif_thumb Returns the location of the item's bif thumbnail. Use with pms_image_proxy. bif_thumb Returns the location of the item's bif thumbnail. Use with pms_image_proxy.
art Returns the location of the item's artwork art Returns the location of the item's artwork.
originally_available_at Returns the air date of the item.
progress_percent Returns the current progress of the item. 0 to 100. progress_percent Returns the current progress of the item. 0 to 100.
user Returns the name of the user owning the session. user Returns the name of the user owning the session.
user_id Returns the Plex user id if available. user_id Returns the Plex user id if available.
@ -62,7 +63,7 @@ DOCUMENTATION :: END
% if session is not None: % if session is not None:
<% <%
from collections import defaultdict from collections import defaultdict
from plexpy.helpers import cast_to_int, get_percent, page, short_season from plexpy.helpers import cast_to_int, get_percent, page, short_season, format_date_based_show
from plexpy.common import VIDEO_RESOLUTION_OVERRIDES, AUDIO_CODEC_OVERRIDES, EXTRA_TYPES from plexpy.common import VIDEO_RESOLUTION_OVERRIDES, AUDIO_CODEC_OVERRIDES, EXTRA_TYPES
import plexpy import plexpy
%> %>
@ -76,6 +77,12 @@ DOCUMENTATION :: END
user_href = page('user', data['user_id']) if data['user_id'] else '#' user_href = page('user', data['user_id']) if data['user_id'] else '#'
season = short_season(data['parent_title']) season = short_season(data['parent_title'])
%> %>
% if not data['media_index']:
<%
data['originally_available_at'] = format_date_based_show(data['originally_available_at'])
%>
% endif
<div class="dashboard-activity-instance" id="activity-instance-${sk}" data-key="${sk}" data-id="${data['session_id']}" <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-parent_rating_key="${data['parent_rating_key']}" data-grandparent_rating_key="${data['grandparent_rating_key']}"
data-guid="${data['guid']}"> data-guid="${data['guid']}">
@ -502,8 +509,12 @@ DOCUMENTATION :: END
% if data['media_type'] == 'movie': % if data['media_type'] == 'movie':
<span title="${data['year']}" class="sub-heading">${data['year']}</span> <span title="${data['year']}" class="sub-heading">${data['year']}</span>
% elif data['media_type'] == 'episode': % elif data['media_type'] == 'episode':
% if data['media_index']:
<a href="${parent_href}" title="${data['parent_title']}" class="sub-heading">${season}</a> <a href="${parent_href}" title="${data['parent_title']}" class="sub-heading">${season}</a>
&middot; <a href="${href}" title="Episode ${data['media_index']}" class="sub-heading">E${data['media_index']}</a> &middot; <a href="${href}" title="Episode ${data['media_index']}" class="sub-heading">E${data['media_index']}</a>
% else:
<a href="${href}" title="Episode ${data['originally_available_at']}" class="sub-heading">E${data['originally_available_at']}</a>
% endif
% elif data['media_type'] == 'track': % elif data['media_type'] == 'track':
<a id="metadata-parent_title-${sk}" href="${parent_href}" title="${data['parent_title']}" class="sub-heading">${data['parent_title']}</a> <a id="metadata-parent_title-${sk}" href="${parent_href}" title="${data['parent_title']}" class="sub-heading">${data['parent_title']}</a>
% elif data['media_type'] == 'photo': % elif data['media_type'] == 'photo':

View file

@ -43,7 +43,7 @@ DOCUMENTATION :: END
from plexpy import notifiers from plexpy import notifiers
from plexpy.common import MEDIA_TYPE_HEADERS, MEDIA_FLAGS_AUDIO, MEDIA_FLAGS_VIDEO from plexpy.common import MEDIA_TYPE_HEADERS, MEDIA_FLAGS_AUDIO, MEDIA_FLAGS_VIDEO
from plexpy.helpers import page, get_percent, cast_to_int, short_season from plexpy.helpers import page, get_percent, cast_to_int, short_season, format_date_based_show
# Get audio codec file # Get audio codec file
def af(codec): def af(codec):
@ -83,9 +83,14 @@ DOCUMENTATION :: END
<% <%
data = defaultdict(lambda: None, **metadata) data = defaultdict(lambda: None, **metadata)
media_info = defaultdict(lambda: None, **(data['media_info'][0] if data['media_info'] else {})) media_info = defaultdict(lambda: None, **(data['media_info'][0] if data['media_info'] else {}))
episode = ''
season = '' season = ''
if data['media_type'] == 'episode': if data['media_type'] == 'episode':
season = short_season(data['parent_title']) season = short_season(data['parent_title'])
if data['media_index']:
episode = data['media_index']
else:
episode = format_date_based_show(data['originally_available_at'])
elif data['media_type'] == 'season': elif data['media_type'] == 'season':
season = short_season(data['title']) season = short_season(data['title'])
%> %>
@ -140,7 +145,7 @@ DOCUMENTATION :: END
<span class="breadcrumb-arrow"><i class="fa fa-chevron-right"></i></span> <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'])}">${data['parent_title']}</a></li>
<span class="breadcrumb-arrow"><i class="fa fa-chevron-right"></i></span> <span class="breadcrumb-arrow"><i class="fa fa-chevron-right"></i></span>
<li class="active metadata-xml">Episode ${data['media_index']} - ${data['title']}</li> <li class="active metadata-xml">Episode ${episode} - ${data['title']}</li>
% elif data['media_type'] == 'artist': % 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'])}">${data['library_name']}</a></li>
<span class="breadcrumb-arrow"><i class="fa fa-chevron-right"></i></span> <span class="breadcrumb-arrow"><i class="fa fa-chevron-right"></i></span>
@ -252,7 +257,9 @@ DOCUMENTATION :: END
<h1>${data['grandparent_title']}</h1> <h1>${data['grandparent_title']}</h1>
<h2>${data['title']}</h2> <h2>${data['title']}</h2>
% if data['media_index']: % if data['media_index']:
<h3 class="hidden-xs">${season} &middot; E${data['media_index']}</h3> <h3 class="hidden-xs">${season} &middot; E${episode}</h3>
% else:
<h3 class="hidden-xs">E${episode}</h3>
% endif % endif
% endif % endif
% elif data['media_type'] in ('movie', 'show', 'artist', 'collection', 'playlist', 'photo_album'): % elif data['media_type'] in ('movie', 'show', 'artist', 'collection', 'playlist', 'photo_album'):
@ -263,7 +270,11 @@ DOCUMENTATION :: END
% elif data['media_type'] == 'episode': % 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'])}">${data['grandparent_title']}</a></h1>
<h2>${data['title']}</h2> <h2>${data['title']}</h2>
<h3 class="hidden-xs">${season} &middot; E${data['media_index']}</h3> % if data['media_index']:
<h3 class="hidden-xs">${season} &middot; E${episode}</h3>
% else:
<h3 class="hidden-xs">E${episode}</h3>
% endif
% elif data['media_type'] == 'album': % 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'])}">${data['parent_title']}</a></h1>
<h2>${data['title']}</h2> <h2>${data['title']}</h2>
@ -766,9 +777,14 @@ DOCUMENTATION :: END
% if metadata: % if metadata:
<% <%
data = defaultdict(None, **metadata) data = defaultdict(None, **metadata)
episode = ''
season = '' season = ''
if data['media_type'] == 'episode': if data['media_type'] == 'episode':
season = short_season(data['parent_title']) season = short_season(data['parent_title'])
if data['media_index']:
episode = data['media_index']
else:
episode = format_date_based_show(data['originally_available_at'])
elif data['media_type'] == 'season': elif data['media_type'] == 'season':
season = short_season(data['title']) season = short_season(data['title'])
%> %>
@ -812,7 +828,7 @@ DOCUMENTATION :: END
% elif data['media_type'] == 'season': % elif data['media_type'] == 'season':
${data['parent_title']}<br />${data['title']} ${data['parent_title']}<br />${data['title']}
% elif data['media_type'] == 'episode': % elif data['media_type'] == 'episode':
${data['grandparent_title']}<br />${data['title']}<br />${season} &middot; E${data['media_index']} ${data['grandparent_title']}<br />${data['title']}<br />${season} &middot; E${episode}
% elif data['media_type'] == 'artist': % elif data['media_type'] == 'artist':
${data['title']} ${data['title']}
% elif data['media_type'] == 'album': % elif data['media_type'] == 'album':

View file

@ -19,6 +19,7 @@ data['children_list'] :: Usable paramaters
== Global keys == == Global keys ==
rating_key Returns the unique identifier for the media item. rating_key Returns the unique identifier for the media item.
media_index Returns the episode number. media_index Returns the episode number.
originally_available_at Returns the air date of the item.
title Returns the name of the episode. title Returns the name of the episode.
thumb Returns the location of the item's thumbnail. Use with pms_image_proxy. thumb Returns the location of the item's thumbnail. Use with pms_image_proxy.
parent_thumb Returns the location of the item's parent thumbnail. Use with pms_image_proxy. parent_thumb Returns the location of the item's parent thumbnail. Use with pms_image_proxy.
@ -28,7 +29,7 @@ DOCUMENTATION :: END
% if data != None: % if data != None:
<% <%
from plexpy.helpers import cast_to_int, page, short_season from plexpy.helpers import cast_to_int, page, short_season, format_date_based_show
%> %>
% if data['children_count'] > 0: % if data['children_count'] > 0:
<div class="item-children-wrapper"> <div class="item-children-wrapper">
@ -176,7 +177,7 @@ DOCUMENTATION :: END
<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')});">
<div class="item-children-card-overlay"> <div class="item-children-card-overlay">
<div class="item-children-overlay-text"> <div class="item-children-overlay-text">
Episode ${child['media_index'] or child['originally_available_at']} Episode ${child['media_index'] or format_date_based_show(child['originally_available_at'])}
</div> </div>
</div> </div>
</div> </div>

View file

@ -1,5 +1,6 @@
var date_format = 'YYYY-MM-DD'; var date_format = 'YYYY-MM-DD';
var time_format = 'hh:mm a'; var time_format = 'hh:mm a';
var date_based_tv_show_format = 'YYYY\u00b7MM\u00b7DD';
var history_to_delete = []; var history_to_delete = [];
$.ajax({ $.ajax({
@ -8,6 +9,7 @@ $.ajax({
success: function(data) { success: function(data) {
date_format = data.date_format; date_format = data.date_format;
time_format = data.time_format; time_format = data.time_format;
date_based_tv_show_format = data.date_based_tv_show_format;
} }
}); });
@ -179,9 +181,11 @@ history_table_options = {
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>'; 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'], history, rowData['live']) + '"><div style="float: left;">' + media_type + '&nbsp;' + thumb_popover + '</div></a></div>'); $(td).html('<div class="history-title"><a href="' + page('info', rowData['rating_key'], rowData['guid'], history, rowData['live']) + '"><div style="float: left;">' + media_type + '&nbsp;' + thumb_popover + '</div></a></div>');
} else if (rowData['media_type'] === 'episode') { } else if (rowData['media_type'] === 'episode') {
rowData['originally_available_at'] = moment(rowData['originally_available_at']).format(date_based_tv_show_format);
icon = (rowData['live']) ? 'fa-broadcast-tower' : 'fa-television'; icon = (rowData['live']) ? 'fa-broadcast-tower' : 'fa-television';
icon_title = (rowData['live']) ? 'Live TV' : 'Episode'; 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'] + ')'; } 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 (isNaN(parseInt(rowData['media_index'])) && rowData['originally_available_at']) { parent_info = ' (' + rowData['originally_available_at'] + ')'; }
else if (rowData['live'] && rowData['originally_available_at']) { parent_info = ' (' + rowData['originally_available_at'] + ')'; } 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>'; 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>'; 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>';

View file

@ -1,5 +1,6 @@
var date_format = 'YYYY-MM-DD'; var date_format = 'YYYY-MM-DD';
var time_format = 'hh:mm a'; var time_format = 'hh:mm a';
var date_based_tv_show_format = 'YYYY\u00b7MM\u00b7DD';
$.ajax({ $.ajax({
url: 'get_date_formats', url: 'get_date_formats',
@ -7,6 +8,7 @@ $.ajax({
success: function(data) { success: function(data) {
date_format = data.date_format; date_format = data.date_format;
time_format = data.time_format; time_format = data.time_format;
date_based_tv_show_format = data.date_based_tv_show_format;
} }
}); });
@ -112,9 +114,11 @@ history_table_modal_options = {
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>'; 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>'); $(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>');
} else if (rowData['media_type'] === 'episode') { } else if (rowData['media_type'] === 'episode') {
rowData['originally_available_at'] = moment(rowData['originally_available_at']).format(date_based_tv_show_format);
icon = (rowData['live']) ? 'fa-broadcast-tower' : 'fa-television'; icon = (rowData['live']) ? 'fa-broadcast-tower' : 'fa-television';
icon_title = (rowData['live']) ? 'Live TV' : 'Episode'; 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'] + ')'; } 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 (isNaN(parseInt(rowData['media_index'])) && rowData['originally_available_at']) { parent_info = ' (' + rowData['originally_available_at'] + ')'; }
else if (rowData['live'] && rowData['originally_available_at']) { parent_info = ' (' + rowData['originally_available_at'] + ')'; } 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>'; 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>'; 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>';

View file

@ -1,5 +1,6 @@
var date_format = 'YYYY-MM-DD'; var date_format = 'YYYY-MM-DD';
var time_format = 'hh:mm a'; var time_format = 'hh:mm a';
var date_based_tv_show_format = 'YYYY\u00b7MM\u00b7DD';
$.ajax({ $.ajax({
url: 'get_date_formats', url: 'get_date_formats',
@ -7,6 +8,7 @@ $.ajax({
success: function (data) { success: function (data) {
date_format = data.date_format; date_format = data.date_format;
time_format = data.time_format; time_format = data.time_format;
date_based_tv_show_format = data.date_based_tv_show_format;
} }
}); });
@ -94,7 +96,10 @@ media_info_table_options = {
$(td).html('<div class="history-title"><a href="' + page('info', rowData['rating_key']) + '"><div style="float: left; padding-left: 15px;">' + media_type + '&nbsp;' + thumb_popover + '</div></a></div>'); $(td).html('<div class="history-title"><a href="' + page('info', rowData['rating_key']) + '"><div style="float: left; padding-left: 15px;">' + media_type + '&nbsp;' + thumb_popover + '</div></a></div>');
} else if (rowData['media_type'] === 'episode') { } else if (rowData['media_type'] === 'episode') {
media_type = '<span class="media-type-tooltip" data-toggle="tooltip" title="Episode"><i class="fa fa-television fa-fw"></i></span>'; media_type = '<span class="media-type-tooltip" data-toggle="tooltip" title="Episode"><i class="fa fa-television fa-fw"></i></span>';
thumb_popover = '<span class="thumb-tooltip" data-toggle="popover" data-img="' + page('pms_image_proxy', rowData['thumb'], rowData['rating_key'], 500, 280, null, null, null, 'art') + '" data-height="80" data-width="140">E' + rowData['media_index'] + ' - ' + rowData['title'] + '</span>'; thumb_popover = (rowData['media_index']) ?
'<span class="thumb-tooltip" data-toggle="popover" data-img="' + page('pms_image_proxy', rowData['thumb'], rowData['rating_key'], 500, 280, null, null, null, 'art') + '" data-height="80" data-width="140">E' + rowData['media_index'] + ' - ' + rowData['title'] + '</span>'
: '<span class="thumb-tooltip" data-toggle="popover" data-img="' + page('pms_image_proxy', rowData['thumb'], rowData['rating_key'], 500, 280, null, null, null, 'art') + '" data-height="80" data-width="140">E' + moment(rowData['originally_available_at']).format(date_based_tv_show_format)
+ ' - ' + rowData['title'] + '</span>';
$(td).html('<div class="history-title"><a href="' + page('info', rowData['rating_key']) + '"><div style="float: left; padding-left: 30px;">' + media_type + '&nbsp;' + thumb_popover + '</div></a></div>'); $(td).html('<div class="history-title"><a href="' + page('info', rowData['rating_key']) + '"><div style="float: left; padding-left: 30px;">' + media_type + '&nbsp;' + thumb_popover + '</div></a></div>');
} else if (rowData['media_type'] === 'artist') { } else if (rowData['media_type'] === 'artist') {
media_type = '<span class="media-type-tooltip" data-toggle="tooltip" title="Artist"><i class="fa fa-music fa-fw"></i></span>'; media_type = '<span class="media-type-tooltip" data-toggle="tooltip" title="Artist"><i class="fa fa-music fa-fw"></i></span>';

View file

@ -1,5 +1,14 @@
var users_to_delete = []; var users_to_delete = [];
var users_to_purge = []; var users_to_purge = [];
var date_based_tv_show_format = 'YYYY\u00b7MM\u00b7DD';
$.ajax({
url: 'get_date_formats',
type: 'GET',
success: function (data) {
date_based_tv_show_format = data.date_based_tv_show_format;
}
});
function toggleEditNames() { function toggleEditNames() {
if ($('.edit-control').hasClass('hidden')) { if ($('.edit-control').hasClass('hidden')) {
@ -211,7 +220,9 @@ users_list_table_options = {
} else if (rowData['media_type'] === 'episode') { } else if (rowData['media_type'] === 'episode') {
icon = (rowData['live']) ? 'fa-broadcast-tower' : 'fa-television'; icon = (rowData['live']) ? 'fa-broadcast-tower' : 'fa-television';
icon_title = (rowData['live']) ? 'Live TV' : 'Episode'; icon_title = (rowData['live']) ? 'Live TV' : 'Episode';
rowData['originally_available_at'] = moment(rowData['originally_available_at']).format(date_based_tv_show_format);
if (!isNaN(parseInt(rowData['parent_media_index'])) && !isNaN(parseInt(rowData['media_index']))) { parent_info = ' (' + short_season(rowData['parent_title']) + ' &middot; E' + rowData['media_index'] + ')'; } 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 (isNaN(parseInt(rowData['media_index'])) && rowData['originally_available_at']) { parent_info = ' (' + rowData['originally_available_at'] + ')'; }
else if (rowData['live'] && rowData['originally_available_at']) { parent_info = ' (' + rowData['originally_available_at'] + ')'; } 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>'; 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>'; 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>';

View file

@ -19,6 +19,7 @@ parent_title Returns the name of the artist.
grandparent_title Returns the name of the show. grandparent_title Returns the name of the show.
media_index Returns the index number of the episode. media_index Returns the index number of the episode.
parent_media_index Returns the index number of the season. parent_media_index Returns the index number of the season.
originally_available_at Returns the air date of the media item.
section_id Returns the library section number of the media item. section_id Returns the library section number of the media item.
library_name Returns the library section name of the media item. library_name Returns the library section name of the media item.
year Returns the release year of the movie, episode, or album. year Returns the release year of the movie, episode, or album.
@ -32,7 +33,7 @@ DOCUMENTATION :: END
% if data: % if data:
<% <%
from plexpy.helpers import page, short_season from plexpy.helpers import page, short_season, format_date_based_show
%> %>
<div class="dashboard-recent-media-row"> <div class="dashboard-recent-media-row">
@ -78,8 +79,12 @@ DOCUMENTATION :: END
<a href="${page('info', item['rating_key'])}" title="${item['title']}">${item['title']}</a> <a href="${page('info', item['rating_key'])}" title="${item['title']}">${item['title']}</a>
</h3> </h3>
<h3 class="text-muted"> <h3 class="text-muted">
% if item['media_index']:
<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'])}" 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> &middot; <a href="${page('info', item['rating_key'])}" title="Episode ${item['media_index']}">E${item['media_index']}</a>
% else:
<a href="${page('info', item['rating_key'])}" title="Episode ${format_date_based_show(item['originally_available_at'])}">E${format_date_based_show(item['originally_available_at'])}</a>
% endif
</h3> </h3>
% elif item['media_type'] == 'movie': % elif item['media_type'] == 'movie':
<h3> <h3>

View file

@ -19,6 +19,7 @@ parent_title Returns the name of the artist.
grandparent_title Returns the name of the show. grandparent_title Returns the name of the show.
media_index Returns the index number of the episode. media_index Returns the index number of the episode.
parent_media_index Returns the index number of the season. parent_media_index Returns the index number of the season.
originally_available_at Returns the air date of the media item.
section_id Returns the library section number of the media item. section_id Returns the library section number of the media item.
library_name Returns the library section name of the media item. library_name Returns the library section name of the media item.
year Returns the release year of the movie, episode, or album. year Returns the release year of the movie, episode, or album.
@ -32,7 +33,7 @@ DOCUMENTATION :: END
% if data != None: % if data != None:
<% <%
from plexpy.helpers import cast_to_int, page, short_season from plexpy.helpers import cast_to_int, page, short_season, format_date_based_show
%> %>
% if data: % if data:
<div class="dashboard-recent-media-row"> <div class="dashboard-recent-media-row">
@ -146,9 +147,14 @@ DOCUMENTATION :: END
<a href="${page('info', item['rating_key'])}" title="${item['title']}">${item['title']}</a> <a href="${page('info', item['rating_key'])}" title="${item['title']}">${item['title']}</a>
</h3> </h3>
<h3 class="text-muted"> <h3 class="text-muted">
% if item['media_index']:
<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'])}" title="${item['parent_title']}">${short_season(item['parent_title'])}</a>
&middot; &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'])}" title="Episode ${item['media_index']}">E${item['media_index']}</a>
% else:
<a href="${page('info', item['rating_key'])}" title="Episode ${format_date_based_show(item['originally_available_at'])}">
E${format_date_based_show(item['originally_available_at'])}</a>
% endif
</h3> </h3>
</div> </div>
% elif item['media_type'] == 'album': % elif item['media_type'] == 'album':

View file

@ -126,6 +126,15 @@
</div> </div>
<p class="help-block">Set your preferred time format. <a href="javascript:void(0)" data-target="#dateTimeOptionsModal" data-toggle="modal">Click here</a> to see the parameter list.</p> <p class="help-block">Set your preferred time format. <a href="javascript:void(0)" data-target="#dateTimeOptionsModal" data-toggle="modal">Click here</a> to see the parameter list.</p>
</div> </div>
<div class="form-group advanced-setting">
<label for="date_based_tv_show_format">Date Based TV Show Format</label>
<div class="row">
<div class="col-md-4">
<input type="text" class="form-control" id="date_based_tv_show_format" name="date_based_tv_show_format" value="${config['date_based_tv_show_format']}" data-parsley-trigger="change" required>
</div>
</div>
<p class="help-block">Set your preferred display format for date based tv shows.</p>
</div>
<div class="checkbox advanced-setting"> <div class="checkbox advanced-setting">
<label> <label>
<input type="checkbox" id="week_start_monday" name="week_start_monday" value="1" ${config['week_start_monday']}> Week Starting on Monday <input type="checkbox" id="week_start_monday" name="week_start_monday" value="1" ${config['week_start_monday']}> Week Starting on Monday

View file

@ -21,6 +21,7 @@ parent_title Returns the name of the artist.
grandparent_title Returns the name of the show. grandparent_title Returns the name of the show.
media_index Returns the index number of the episode. media_index Returns the index number of the episode.
parent_media_index Returns the index number of the season. parent_media_index Returns the index number of the season.
originally_available_at Returns the air date of the media item.
year Returns the release year of the movie, episode, or album. year Returns the release year of the movie, episode, or album.
DOCUMENTATION :: END DOCUMENTATION :: END
@ -28,7 +29,7 @@ DOCUMENTATION :: END
% if data: % if data:
<% <%
from plexpy.helpers import page, short_season from plexpy.helpers import page, short_season, format_date_based_show
%> %>
<div class="dashboard-recent-media-row"> <div class="dashboard-recent-media-row">
<div id="recently-watched-row-scroller"> <div id="recently-watched-row-scroller">
@ -59,6 +60,9 @@ DOCUMENTATION :: END
</a> </a>
<div class="dashboard-recent-media-metacontainer"> <div class="dashboard-recent-media-metacontainer">
% if item['media_type'] == 'episode': % if item['media_type'] == 'episode':
% if not item['media_index']:
item['originally_available_at'] = format_date_based_show(item['originally_available_at'])
% endif
% if item['live']: % if item['live']:
<h3> <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'])}" title="${item['grandparent_title']}">${item['grandparent_title']}</a>
@ -68,8 +72,12 @@ DOCUMENTATION :: END
</h3> </h3>
% if item['media_index']: % if item['media_index']:
<h3 class="text-muted"> <h3 class="text-muted">
% if item['media_index']:
<a href="${page('info', item['rating_key'], history=True, live=item['live'])}" title="${item['parent_title']}">${short_season(item['parent_title'])}</a> <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> &middot; <a href="${page('info', item['rating_key'], history=True, live=item['live'])}" title="Episode ${item['media_index']}">E${item['media_index']}</a>
% else:
<a href="${page('info', item['rating_key'], history=True, live=item['live'])}" title="Episode ${item['originally_available_at']}">E${item['originally_available_at']}</a>
% endif
</h3> </h3>
% else: % else:
<h3 class="text-muted"> <h3 class="text-muted">

View file

@ -1,7 +1,7 @@
% if data: % if data:
<% <%
import plexpy import plexpy
from plexpy.helpers import grouper, get_img_service from plexpy.helpers import grouper, get_img_service, format_date_based_show
recently_added = data['recently_added'] recently_added = data['recently_added']
if plexpy.CONFIG.NEWSLETTER_SELF_HOSTED and plexpy.CONFIG.HTTP_BASE_URL: if plexpy.CONFIG.NEWSLETTER_SELF_HOSTED and plexpy.CONFIG.HTTP_BASE_URL:
@ -755,8 +755,11 @@
<p class="nowrap mb5" style="font-family: 'Open Sans', Helvetica, Arial, sans-serif;font-weight: 400;margin: 0;margin-bottom: 5px;white-space: nowrap;text-overflow: ellipsis;overflow: hidden;max-width: 325px;color: #ffffff;"> <p class="nowrap mb5" style="font-family: 'Open Sans', Helvetica, Arial, sans-serif;font-weight: 400;margin: 0;margin-bottom: 5px;white-space: nowrap;text-overflow: ellipsis;overflow: hidden;max-width: 325px;color: #ffffff;">
% for i, season in enumerate(show['season'][:8]): % for i, season in enumerate(show['season'][:8]):
% if season['episode_count'] == 1: % if season['episode_count'] == 1:
% if season['episode'][0]['media_index']:
${season['title']} &middot; Episode ${season['episode'][0]['media_index']} - ${season['episode'][0]['title']} ${season['title']} &middot; Episode ${season['episode'][0]['media_index']} - ${season['episode'][0]['title']}
% else: % else:
${season['title']} &middot; Episode ${format_date_based_show(season['episode'][0]['originally_available_at'])}
- ${season['episode'][0]['title']}
${season['title']} &middot; Episodes ${season['episode_range']} ${season['title']} &middot; Episodes ${season['episode_range']}
% endif % endif
% if i < min(show['season_count'], 7): % if i < min(show['season_count'], 7):

View file

@ -42,6 +42,7 @@ FILENAME = "config.ini"
_CONFIG_DEFINITIONS = { _CONFIG_DEFINITIONS = {
'ALLOW_GUEST_ACCESS': (int, 'General', 0), 'ALLOW_GUEST_ACCESS': (int, 'General', 0),
'DATE_FORMAT': (str, 'General', 'YYYY-MM-DD'), 'DATE_FORMAT': (str, 'General', 'YYYY-MM-DD'),
'DATE_BASED_TV_SHOW_FORMAT': (str, 'Advanced', 'YYYY&middot;MM&middot;DD'),
'PMS_CLIENT_ID': (str, 'PMS', ''), 'PMS_CLIENT_ID': (str, 'PMS', ''),
'PMS_IDENTIFIER': (str, 'PMS', ''), 'PMS_IDENTIFIER': (str, 'PMS', ''),
'PMS_IP': (str, 'PMS', '127.0.0.1'), 'PMS_IP': (str, 'PMS', '127.0.0.1'),
@ -240,6 +241,7 @@ SETTINGS = [
'CLOUDINARY_API_SECRET', 'CLOUDINARY_API_SECRET',
'CLOUDINARY_CLOUD_NAME', 'CLOUDINARY_CLOUD_NAME',
'DATE_FORMAT', 'DATE_FORMAT',
'DATE_BASED_TV_SHOW_FORMAT',
'EXPORT_DIR', 'EXPORT_DIR',
'GIT_BRANCH', 'GIT_BRANCH',
'GIT_PATH', 'GIT_PATH',

View file

@ -25,6 +25,7 @@ from collections import OrderedDict
from datetime import date, datetime, timezone from datetime import date, datetime, timezone
from functools import reduce, wraps from functools import reduce, wraps
import hashlib import hashlib
import html
import imghdr import imghdr
from itertools import groupby from itertools import groupby
from future.moves.itertools import islice, zip_longest from future.moves.itertools import islice, zip_longest
@ -417,6 +418,8 @@ def clean_filename(filename, replace='_'):
cleaned_filename = ''.join(c if c in whitelist else replace for c in cleaned_filename) cleaned_filename = ''.join(c if c in whitelist else replace for c in cleaned_filename)
return cleaned_filename return cleaned_filename
def format_date_based_show(date):
return str(arrow.get(date).format(html.unescape(plexpy.CONFIG.DATE_BASED_TV_SHOW_FORMAT)))
def split_strip(s, delimiter=','): def split_strip(s, delimiter=','):
return [x.strip() for x in str(s).split(delimiter) if x.strip()] return [x.strip() for x in str(s).split(delimiter) if x.strip()]

View file

@ -502,6 +502,7 @@ class Libraries(object):
# If no cache was imported, get all library children items # 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 {} cached_items = {d['rating_key']: d['file_size'] for d in rows} if not refresh else {}
# TODO: Auto trigger for update - needs to be triggered to get date based episode support
if refresh or not rows: if refresh or not rows:
pms_connect = pmsconnect.PmsConnect() pms_connect = pmsconnect.PmsConnect()
@ -540,6 +541,7 @@ class Libraries(object):
'year': item['year'], 'year': item['year'],
'media_index': item['media_index'], 'media_index': item['media_index'],
'parent_media_index': item['parent_media_index'], 'parent_media_index': item['parent_media_index'],
'originally_available_at': item['originally_available_at'],
'thumb': item['thumb'], 'thumb': item['thumb'],
'container': item.get('container', ''), 'container': item.get('container', ''),
'bitrate': item.get('bitrate', ''), 'bitrate': item.get('bitrate', ''),

View file

@ -763,6 +763,16 @@ class RecentlyAdded(Newsletter):
for (index, title), children in groupby(filtered_children, for (index, title), children in groupby(filtered_children,
key=lambda x: (x['parent_media_index'], x['parent_title'])): key=lambda x: (x['parent_media_index'], x['parent_title'])):
episodes = list(children) episodes = list(children)
isDateBased = True
for e in episodes:
if e['media_index']:
isDateBased = False
break
if isDateBased:
num00 = helpers.format_date_based_show(episodes[0]['originally_available_at']) + " - " + helpers.format_date_based_show(episodes[len(episodes)-1]['originally_available_at'])
else:
num, num00 = format_group_index([helpers.cast_to_int(d['media_index']) for d in episodes]) num, num00 = format_group_index([helpers.cast_to_int(d['media_index']) for d in episodes])
seasons.append({'media_index': index, seasons.append({'media_index': index,

View file

@ -915,8 +915,11 @@ def build_media_notify_params(notify_action=None, session=None, timeline=None, m
track_name = notify_params['title'] track_name = notify_params['title']
season_num = str(notify_params['parent_media_index']).zfill(1) season_num = str(notify_params['parent_media_index']).zfill(1)
season_num00 = str(notify_params['parent_media_index']).zfill(2) season_num00 = str(notify_params['parent_media_index']).zfill(2)
if notify_params['media_index']:
episode_num = str(notify_params['media_index']).zfill(1) episode_num = str(notify_params['media_index']).zfill(1)
episode_num00 = str(notify_params['media_index']).zfill(2) episode_num00 = str(notify_params['media_index']).zfill(2)
else:
episode_num = episode_num00 = helpers.format_date_based_show(notify_params['originally_available_at'])
disc_num = str(notify_params['parent_media_index']).zfill(1) disc_num = str(notify_params['parent_media_index']).zfill(1)
disc_num00 = str(notify_params['parent_media_index']).zfill(2) disc_num00 = str(notify_params['parent_media_index']).zfill(2)
track_num = str(notify_params['media_index']).zfill(1) track_num = str(notify_params['media_index']).zfill(1)

View file

@ -2873,6 +2873,7 @@ class PmsConnect(object):
'sort_title': helpers.get_xml_attr(item, 'titleSort'), 'sort_title': helpers.get_xml_attr(item, 'titleSort'),
'media_index': helpers.get_xml_attr(item, 'index'), 'media_index': helpers.get_xml_attr(item, 'index'),
'parent_media_index': helpers.get_xml_attr(item, 'parentIndex'), 'parent_media_index': helpers.get_xml_attr(item, 'parentIndex'),
'originally_available_at': helpers.get_xml_attr(item, 'originallyAvailableAt'),
'year': helpers.get_xml_attr(item, 'year'), 'year': helpers.get_xml_attr(item, 'year'),
'thumb': helpers.get_xml_attr(item, 'thumb'), 'thumb': helpers.get_xml_attr(item, 'thumb'),
'parent_thumb': helpers.get_xml_attr(item, 'thumb'), 'parent_thumb': helpers.get_xml_attr(item, 'thumb'),

View file

@ -21,6 +21,7 @@ from io import open, BytesIO
import json import json
import linecache import linecache
import os import os
import html
import shutil import shutil
import ssl as _ssl import ssl as _ssl
import sys import sys
@ -271,7 +272,7 @@ class WebInterface(object):
json: json:
{"date_format": "YYYY-MM-DD", {"date_format": "YYYY-MM-DD",
"time_format": "HH:mm", "time_format": "HH:mm",
} "date_based_tv_show_format": "YYYY\u00b7MM\u00b7DD"}
``` ```
""" """
if plexpy.CONFIG.DATE_FORMAT: if plexpy.CONFIG.DATE_FORMAT:
@ -282,9 +283,14 @@ class WebInterface(object):
time_format = plexpy.CONFIG.TIME_FORMAT time_format = plexpy.CONFIG.TIME_FORMAT
else: else:
time_format = 'HH:mm' time_format = 'HH:mm'
if plexpy.CONFIG.DATE_BASED_TV_SHOW_FORMAT:
date_based_tv_show_format = html.unescape(plexpy.CONFIG.DATE_BASED_TV_SHOW_FORMAT)
else:
date_based_tv_show_format = html.unescape('YYYY&middot;MM&middot;DD')
formats = {'date_format': date_format, formats = {'date_format': date_format,
'time_format': time_format} 'time_format': time_format,
'date_based_tv_show_format': date_based_tv_show_format}
return formats return formats
@ -769,6 +775,7 @@ class WebInterface(object):
"media_type": "show", "media_type": "show",
"parent_media_index": "", "parent_media_index": "",
"parent_rating_key": "", "parent_rating_key": "",
"originally_available_at": "2011-08-21",
"play_count": 15, "play_count": 15,
"rating_key": "1219", "rating_key": "1219",
"section_id": 2, "section_id": 2,