mirror of
https://github.com/Tautulli/Tautulli.git
synced 2025-07-11 15:56:07 -07:00
Fix merge conflicts
This commit is contained in:
commit
0784b0a0db
8 changed files with 1098 additions and 25 deletions
|
@ -57,6 +57,18 @@ from plexpy import version
|
|||
</div>
|
||||
<div class="collapse navbar-collapse navbar-right" id="navbar-collapse-1">
|
||||
<ul class="nav navbar-nav">
|
||||
<li>
|
||||
<form action="search" method="post" class="form" id="search_form">
|
||||
<div class="input-group">
|
||||
<span class="input-textbox">
|
||||
<input type="text" class="form-control" name="search_query" id="search_query" aria-label="Search" placeholder="Search..."/>
|
||||
</span>
|
||||
<span class="input-group-btn">
|
||||
<button class="btn btn-dark btn-inactive" type="submit" id="search_button"><i class="fa fa-search"></i></button>
|
||||
</span>
|
||||
</div>
|
||||
</form>
|
||||
</li>
|
||||
% if title=="Home":
|
||||
<li class="active"><a href="home"><i class="fa fa-lg fa-home"></i></a></li>
|
||||
% else:
|
||||
|
@ -117,6 +129,28 @@ ${next.headerIncludes()}
|
|||
$('#updatebar').show();
|
||||
}
|
||||
</script>
|
||||
<script>
|
||||
$('#search_form').submit(function (e) {
|
||||
if ($('#search_query').hasClass('active') && $('#search_query').val().trim() != '') {
|
||||
$.ajax({
|
||||
type: 'post',
|
||||
url: 'search',
|
||||
data: { 'query': $('#search_query').val() }
|
||||
})
|
||||
} else {
|
||||
e.preventDefault();
|
||||
$('#search_button').removeClass('btn-inactive');
|
||||
$('#search_query').clearQueue().val('').animate({ right: '0', width: '250px' }).addClass('active').focus();
|
||||
}
|
||||
})
|
||||
$('#search_query').on('blur', function (e) {
|
||||
if ($(this).val().trim() == '') {
|
||||
$(this).delay(200).animate({ right: '-250px', width: '0' }, function () {
|
||||
$('#search_button').addClass('btn-inactive');
|
||||
}).removeClass('active');
|
||||
}
|
||||
});
|
||||
</script>
|
||||
${next.javascriptIncludes()}
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -1246,11 +1246,39 @@ a:hover .summary-poster-face-track .summary-poster-face-overlay span {
|
|||
background-size: contain;
|
||||
height: 16px;
|
||||
}
|
||||
#children-list, #search-results-list {
|
||||
position: relative;
|
||||
z-index: 0;
|
||||
}
|
||||
.item-children-wrapper {
|
||||
}
|
||||
.item-children-section-title {
|
||||
position: relative;
|
||||
padding: 10px;
|
||||
background-color: #2c2c2c;
|
||||
border-bottom: 1px solid #3d3d3d;
|
||||
border-top: 1px solid #282828;
|
||||
height: 50px;
|
||||
line-height: 22px;
|
||||
padding: 13px 20px;
|
||||
margin: 20px 0;
|
||||
}
|
||||
.item-children-section-title h4 {
|
||||
position: relative;
|
||||
margin: 0;
|
||||
line-height: 22px;
|
||||
color: #fff;
|
||||
font-size: 16px;
|
||||
text-align: center;
|
||||
text-transform: uppercase;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.item-children-instance {
|
||||
list-style: none;
|
||||
margin: 0;
|
||||
overflow: hidden;
|
||||
}
|
||||
.item-children-instance li {
|
||||
float: left;
|
||||
|
@ -1348,6 +1376,9 @@ a:hover .item-children-poster {
|
|||
text-align: left;
|
||||
clear: both;
|
||||
}
|
||||
.item-children-instance-text-wrapper h3.text-muted {
|
||||
color: #777;
|
||||
}
|
||||
.item-children-list-item-odd {
|
||||
border-top: 0px solid #343434;
|
||||
border-bottom: 0px solid #343434;
|
||||
|
@ -1391,6 +1422,13 @@ a:hover .item-children-poster {
|
|||
width: 40px;
|
||||
margin-right: 20px;
|
||||
}
|
||||
#new_title h3 {
|
||||
color: #F9AA03;
|
||||
font-size: 14px;
|
||||
line-height: 1.42857143;
|
||||
font-weight: bold;
|
||||
margin: 0;
|
||||
}
|
||||
.settings-alert {
|
||||
float: left;
|
||||
padding: 0;
|
||||
|
@ -2412,4 +2450,37 @@ table[id^='history_child'] thead th {
|
|||
line-height: 0;
|
||||
height: 0 !important;
|
||||
overflow: hidden;
|
||||
}
|
||||
#search_form {
|
||||
width: 350px;
|
||||
padding: 8px 15px;
|
||||
}
|
||||
#search_form span.input-textbox {
|
||||
overflow: hidden;
|
||||
width: 250px;
|
||||
height: 34px;
|
||||
display: inline-flex;
|
||||
float: right;
|
||||
}
|
||||
#search_form #search_query {
|
||||
width: 0;
|
||||
height: 34px;
|
||||
margin-top: 0;
|
||||
float: right;
|
||||
position: relative;
|
||||
right: -250px;
|
||||
border-radius: 3px 0 0 3px;
|
||||
}
|
||||
#search_form #search_query.active {
|
||||
width: 250px;
|
||||
right: 0px;
|
||||
}
|
||||
#search_form #search_button.btn-inactive {
|
||||
background-color: #000;
|
||||
border: 1px solid rgba(0,0,0,0);
|
||||
-webkit-transition: background 0.3s;
|
||||
-moz-transition: background 0.3s;
|
||||
-ms-transition: background 0.3s;
|
||||
-o-transition: background 0.3s;
|
||||
transition: background 0.3s;
|
||||
}
|
|
@ -11,27 +11,40 @@ data :: Usable parameters (if not applicable for media type, blank value will be
|
|||
|
||||
== Global keys ==
|
||||
rating_key Returns the unique identifier for the media item.
|
||||
type Returns the type of media. Either 'movie', 'episode' or 'show' or 'season'.
|
||||
type Returns the type of media. Either 'movie', 'show', 'season', 'episode', 'artist', 'album', or 'track'.
|
||||
art Returns the location of the item's artwork
|
||||
title Returns the name of the episode, show, season or movie.
|
||||
title Returns the name of the movie, show, episode, artist, album, or track.
|
||||
duration Returns the standard runtime of the media.
|
||||
content_rating Returns the age rating for the media.
|
||||
summary Returns a brief description of the media plot.
|
||||
grandparent_title Returns the name of the TV show.
|
||||
parent_index Returns the season number of the TV show.
|
||||
index Returns the episode number.
|
||||
grandparent_title Returns the name of the show, or artist.
|
||||
parent_index Returns the index number of the season.
|
||||
index Returns the index number of the episode, or track.
|
||||
parent_thumb Returns the location of the item's thumbnail. Use with pms_image_proxy.
|
||||
writers Returns an array of writers.
|
||||
thumb Returns the location of the item's thumbnail. Use with pms_image_proxy.
|
||||
parent_title Returns the name of the TV show.
|
||||
parent_title Returns the name of the show, or artist.
|
||||
rating Returns the 5 star rating value for the movie. Between 1 and 5.
|
||||
year Returns the release year of the movie.
|
||||
year Returns the release year of the movie, or show.
|
||||
genres Returns an array of genres.
|
||||
actors Returns an array of actors.
|
||||
directors Returns an array of directors.
|
||||
studio Returns the name of the studio.
|
||||
originally_available_at Returns the air date of the item.
|
||||
|
||||
query :: Usable parameters
|
||||
|
||||
== Global keys ==
|
||||
query_string Returns the string used for the search query.
|
||||
title Returns the name of the movie, episode, or track.
|
||||
parent_title Returns the name of the album.
|
||||
grandparent_title Returns the name of the show, or artist.
|
||||
media_index Returns the index number of the episode, or track.
|
||||
parent_media_index Returns the index number of the season.
|
||||
year Returns the release year of the movie, or show.
|
||||
media_type Returns the type of media. Either 'movie', 'show', 'season', 'episode', 'artist', 'album', or 'track'.
|
||||
rating_key Returns the unique identifier for the media item.
|
||||
|
||||
DOCUMENTATION :: END
|
||||
</%doc>
|
||||
|
||||
|
@ -261,7 +274,7 @@ DOCUMENTATION :: END
|
|||
</div>
|
||||
</div>
|
||||
<div class='table-card-back'>
|
||||
<div id="children-list"></div>
|
||||
<div id="children-list"><i class="fa fa-refresh fa-spin"></i> Loading season list...</div>
|
||||
</div>
|
||||
</div>
|
||||
% elif data['type'] == 'season':
|
||||
|
@ -272,7 +285,7 @@ DOCUMENTATION :: END
|
|||
</div>
|
||||
</div>
|
||||
<div class='table-card-back'>
|
||||
<div id="children-list"></div>
|
||||
<div id="children-list"><i class="fa fa-refresh fa-spin"></i> Loading episode list...</div>
|
||||
</div>
|
||||
</div>
|
||||
% elif data['type'] == 'artist':
|
||||
|
@ -283,7 +296,7 @@ DOCUMENTATION :: END
|
|||
</div>
|
||||
</div>
|
||||
<div class='table-card-back'>
|
||||
<div id="children-list"></div>
|
||||
<div id="children-list"><i class="fa fa-refresh fa-spin"></i> Loading album list...</div>
|
||||
</div>
|
||||
</div>
|
||||
% elif data['type'] == 'album':
|
||||
|
@ -294,7 +307,7 @@ DOCUMENTATION :: END
|
|||
</div>
|
||||
</div>
|
||||
<div class='table-card-back'>
|
||||
<div id="children-list"></div>
|
||||
<div id="children-list"><i class="fa fa-refresh fa-spin"></i> Loading track list...</div>
|
||||
</div>
|
||||
</div>
|
||||
% endif
|
||||
|
@ -361,11 +374,122 @@ DOCUMENTATION :: END
|
|||
% else:
|
||||
<div class="container-fluid">
|
||||
<div class="row">
|
||||
<div class="col-md-10">
|
||||
<h3>
|
||||
Error retrieving item data. This media may not be available in the Plex Media Server database
|
||||
anymore.
|
||||
</h3>
|
||||
<div class="summary-container">
|
||||
<div class="summary-navbar">
|
||||
<div class="col-md-12">
|
||||
<div class="summary-navbar-list">
|
||||
% if query:
|
||||
% if query['media_type'] == 'movie':
|
||||
<span>Movies</span>
|
||||
<span class="hidden-xs hidden-sm"><i class="fa fa-chevron-right"></i></span>
|
||||
<span>${query['title']}</span>
|
||||
% elif query['media_type'] == 'show':
|
||||
<span>TV Shows</span>
|
||||
<span class="hidden-xs hidden-sm"><i class="fa fa-chevron-right"></i></span>
|
||||
<span>${query['grandparent_title']}</span>
|
||||
% elif query['media_type'] == 'season':
|
||||
<span class="hidden-xs hidden-sm">TV Shows</span>
|
||||
<span class="hidden-xs hidden-sm"><i class="fa fa-chevron-right"></i></span>
|
||||
<span class="hidden-xs hidden-sm">${query['grandparent_title']}</span>
|
||||
<span class="hidden-xs hidden-sm"><i class="fa fa-chevron-right"></i></span>
|
||||
<span>Season ${query['parent_media_index']}</span>
|
||||
% elif query['media_type'] == 'episode':
|
||||
<span class="hidden-xs hidden-sm">TV Shows</span>
|
||||
<span class="hidden-xs hidden-sm"><i class="fa fa-chevron-right"></i></span>
|
||||
<span class="hidden-xs hidden-sm">${query['grandparent_title']}</span>
|
||||
<span class="hidden-xs hidden-sm"><i class="fa fa-chevron-right"></i></span>
|
||||
<span>Season ${query['parent_media_index']}</span>
|
||||
<span><i class="fa fa-chevron-right"></i></span>
|
||||
<span>Episode ${query['media_index']} - ${query['title']}</span>
|
||||
% elif query['media_type'] == 'artist':
|
||||
<span>Music</span>
|
||||
<span><i class="fa fa-chevron-right"></i></span>
|
||||
<span>${query['grandparent_title']}</span>
|
||||
% elif query['media_type'] == 'album':
|
||||
<span class="hidden-xs hidden-sm">Music</span>
|
||||
<span class="hidden-xs hidden-sm"><i class="fa fa-chevron-right"></i></span>
|
||||
<span>${query['grandparent_title']}</span>
|
||||
<span><i class="fa fa-chevron-right"></i></span>
|
||||
<span>${query['parent_title']}</span>
|
||||
% elif query['media_type'] == 'track':
|
||||
<span class="hidden-xs hidden-sm">Music</span>
|
||||
<span class="hidden-xs hidden-sm"><i class="fa fa-chevron-right"></i></span>
|
||||
<span class="hidden-xs hidden-sm">${query['grandparent_title']}</span>
|
||||
<span class="hidden-xs hidden-sm"><i class="fa fa-chevron-right"></i></span>
|
||||
<span>${query['parent_title']}</span>
|
||||
<span><i class="fa fa-chevron-right"></i></span>
|
||||
<span>Track ${query['media_index']} - ${query['title']}</span>
|
||||
% endif
|
||||
% endif
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="summary-content-title-wrapper">
|
||||
<div class="col-md-12">
|
||||
<h4 style="text-align: center; margin-bottom: 20px;">
|
||||
Error retrieving item metadata. This media item is not available in the Plex Media Server library.
|
||||
</h4>
|
||||
% if query:
|
||||
<h4 style="text-align: center; margin-bottom: 20px;">
|
||||
If the item has been moved, please select the correct match below to update the PlexPy database.
|
||||
</h4>
|
||||
% endif
|
||||
</div>
|
||||
</div>
|
||||
<div class="summary-content-wrapper">
|
||||
<div class='col-md-12'>
|
||||
% if query:
|
||||
<div class='table-card-header'>
|
||||
<div class="header-bar">
|
||||
<span>Search Results for <strong>${query['query_string']}</strong></span>
|
||||
</div>
|
||||
</div>
|
||||
<div class='table-card-back'>
|
||||
<div id="search-results-list"><i class="fa fa-refresh fa-spin"></i> Loading search results...</div>
|
||||
</div>
|
||||
<div class="modal fade" id="confirm-modal" tabindex="-1" role="dialog" aria-labelledby="confirm-modal">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal" aria-hidden="true"><i class="fa fa-remove"></i></button>
|
||||
<h4 class="modal-title" id="myModalLabel">Confirm Update</h4>
|
||||
</div>
|
||||
<div class="modal-body" style="text-align: center;">
|
||||
<p>Are you REALLY sure you want to replace
|
||||
<p><strong>
|
||||
% if query['media_type'] == 'movie':
|
||||
${query['title']}<br />${query['year']}
|
||||
% elif query['media_type'] == 'show':
|
||||
${query['grandparent_title']}
|
||||
% elif query['media_type'] == 'season':
|
||||
${query['grandparent_title']}<br />S${query['parent_media_index']}
|
||||
% elif query['media_type'] == 'episode':
|
||||
${query['grandparent_title']}<br />${query['title']}<br />S${query['parent_media_index']} · E${query['media_index']}
|
||||
% elif query['media_type'] == 'artist':
|
||||
${query['grandparent_title']}
|
||||
% elif query['media_type'] == 'album':
|
||||
${query['grandparent_title']}<br />${query['parent_title']}
|
||||
% elif query['media_type'] == 'track':
|
||||
${query['grandparent_title']}<br />${query['title']}<br />${query['parent_title']}
|
||||
% endif
|
||||
</strong></p>
|
||||
<p> with </p>
|
||||
<p><span id="new_title"></span></p>
|
||||
% if query['media_type'] != 'movie':
|
||||
<p>All items for <strong>${query['grandparent_title']}</strong> will also be updated.</p>
|
||||
% endif
|
||||
<p>This is permanent and cannot be undone!</p>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-dark" data-dismiss="modal">Cancel</button>
|
||||
<button type="button" class="btn btn-danger btn-ok" data-dismiss="modal" id="confirm-update">Update</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
% endif
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -381,13 +505,6 @@ DOCUMENTATION :: END
|
|||
<script src="interfaces/default/js/moment-with-locale.js"></script>
|
||||
|
||||
% if data:
|
||||
% if data['type'] == 'movie' or data['type'] == 'show' or data['type'] == 'episode':
|
||||
<script>
|
||||
// Convert rating to 5 star rating type
|
||||
var starRating = Math.round(${data['rating']} / 2);
|
||||
$('#stars').attr('data-rateit-value', starRating);
|
||||
</script>
|
||||
% endif
|
||||
<script src="interfaces/default/js/tables/history_table.js"></script>
|
||||
% if data['type'] == 'show' or data['type'] == 'artist':
|
||||
<script>
|
||||
|
@ -488,10 +605,57 @@ DOCUMENTATION :: END
|
|||
});
|
||||
</script>
|
||||
% endif
|
||||
% if data['rating']:
|
||||
<script>
|
||||
// Convert rating to 5 star rating type
|
||||
var starRating = Math.round(${data['rating']} / 2);
|
||||
$('#stars').attr('data-rateit-value', starRating);
|
||||
</script>
|
||||
% endif
|
||||
<script>
|
||||
$("#airdate").html(moment($("#airdate").text()).format('MMM DD, YYYY'));
|
||||
$("#runtime").html(millisecondsToMinutes($("#runtime").text(), true));
|
||||
$('div.art-face').animate({ opacity: 0.2 }, { duration: 1000 });
|
||||
</script>
|
||||
% elif query:
|
||||
<script>
|
||||
$.ajax({
|
||||
url: 'get_search_results_children',
|
||||
type: "GET",
|
||||
async: true,
|
||||
data: {'query': "${query['query_string']}",
|
||||
'media_type': "${query['media_type']}",
|
||||
'season_index': "${query['parent_media_index']}"
|
||||
},
|
||||
complete: function(xhr, status) {
|
||||
$("#search-results-list").html(xhr.responseText); }
|
||||
});
|
||||
$(document).on('click', '#search-results-list a', function (e) {
|
||||
e.preventDefault();
|
||||
var new_rating_key = $(this).attr("id");
|
||||
var new_href = $(this).attr("href");
|
||||
|
||||
$('#new_title').html($(this).find('.item-children-instance-text-wrapper').html());
|
||||
|
||||
$('#confirm-modal').modal();
|
||||
$('#confirm-modal').one('click', '#confirm-update', function () {
|
||||
$(this).prop('disabled', true);
|
||||
var msg = "<i class='fa fa-refresh fa-spin'></i> Updating database..."
|
||||
showMsg(msg, false, false, 0)
|
||||
|
||||
$.ajax({
|
||||
url: 'update_history_rating_key',
|
||||
data: { old_rating_key: "${query['rating_key']}",
|
||||
new_rating_key: new_rating_key,
|
||||
media_type: "${query['media_type']}"
|
||||
},
|
||||
async: true,
|
||||
success: function (data) {
|
||||
window.location.href = new_href;
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
</script>
|
||||
% endif
|
||||
</%def>
|
||||
|
|
224
data/interfaces/default/info_search_results_list.html
Normal file
224
data/interfaces/default/info_search_results_list.html
Normal file
|
@ -0,0 +1,224 @@
|
|||
<%doc>
|
||||
USAGE DOCUMENTATION :: PLEASE LEAVE THIS AT THE TOP OF THIS FILE
|
||||
|
||||
For Mako templating syntax documentation please visit: http://docs.makotemplates.org/en/latest/
|
||||
|
||||
Filename: info_children_list.html
|
||||
Version: 0.1
|
||||
Variable names: data [list]
|
||||
|
||||
data :: Usable parameters
|
||||
|
||||
== Global keys ==
|
||||
results_count Returns the number of search results.
|
||||
results_list Returns a dictionary of search result types.
|
||||
|
||||
data['results_list'] :: Usable paramaters
|
||||
|
||||
== media_type keys ==
|
||||
movie Returns an array of movie results
|
||||
show Returns an array of show results
|
||||
season Returns an array of season results
|
||||
episode Returns an array of episode results
|
||||
artist Returns an array of artist results
|
||||
album Returns an array of album results
|
||||
track Returns an array of track results
|
||||
|
||||
data['results_list'][media_type] :: Usable paramaters
|
||||
|
||||
== Global keys ==
|
||||
rating_key Returns the unique identifier for the media item.
|
||||
type Returns the type of media. Either 'movie', 'show', 'season', 'episode', 'artist', 'album', or 'track'.
|
||||
art Returns the location of the item's artwork
|
||||
title Returns the name of the movie, show, episode, artist, album, or track.
|
||||
duration Returns the standard runtime of the media.
|
||||
content_rating Returns the age rating for the media.
|
||||
summary Returns a brief description of the media plot.
|
||||
grandparent_title Returns the name of the show, or artist.
|
||||
parent_index Returns the index number of the season.
|
||||
index Returns the index number of the episode, or track.
|
||||
parent_thumb Returns the location of the item's thumbnail. Use with pms_image_proxy.
|
||||
writers Returns an array of writers.
|
||||
thumb Returns the location of the item's thumbnail. Use with pms_image_proxy.
|
||||
parent_title Returns the name of the show, or artist.
|
||||
rating Returns the 5 star rating value for the movie. Between 1 and 5.
|
||||
year Returns the release year of the movie, or show.
|
||||
genres Returns an array of genres.
|
||||
actors Returns an array of actors.
|
||||
directors Returns an array of directors.
|
||||
studio Returns the name of the studio.
|
||||
originally_available_at Returns the air date of the item.
|
||||
|
||||
DOCUMENTATION :: END
|
||||
</%doc>
|
||||
|
||||
% if data != None:
|
||||
% if data['results_count'] > 0:
|
||||
% if 'movie' in data['results_list'] and data['results_list']['movie']:
|
||||
<div class="item-children-wrapper">
|
||||
<div class="item-children-section-title">
|
||||
<h4>Movies</h4>
|
||||
</div>
|
||||
<ul class="item-children-instance list-unstyled">
|
||||
% for child in data['results_list']['movie']:
|
||||
<li>
|
||||
<a href="info?item_id=${child['rating_key']}" id="${child['rating_key']}">
|
||||
<div class="item-children-poster">
|
||||
<div class="item-children-poster-face season-poster" style="background-image: url(pms_image_proxy?img=${child['thumb']}&width=300&height=450);"></div>
|
||||
</div>
|
||||
<div class="item-children-instance-text-wrapper season-item">
|
||||
<h3 title="${child['title']}">${child['title']}</h3>
|
||||
<h3 class="text-muted">${child['year']}</h3>
|
||||
</div>
|
||||
</a>
|
||||
</li>
|
||||
% endfor
|
||||
</ul>
|
||||
</div>
|
||||
% endif
|
||||
% if 'show' in data['results_list'] and data['results_list']['show']:
|
||||
<div class="item-children-wrapper">
|
||||
<div class="item-children-section-title">
|
||||
<h4>TV Shows</h4>
|
||||
</div>
|
||||
<ul class="item-children-instance list-unstyled">
|
||||
% for child in data['results_list']['show']:
|
||||
<li>
|
||||
<a href="info?item_id=${child['rating_key']}" id="${child['rating_key']}">
|
||||
<div class="item-children-poster">
|
||||
<div class="item-children-poster-face season-poster" style="background-image: url(pms_image_proxy?img=${child['thumb']}&width=300&height=450);"></div>
|
||||
</div>
|
||||
<div class="item-children-instance-text-wrapper season-item">
|
||||
<h3 title="${child['title']}">${child['title']}</h3>
|
||||
<h3 class="text-muted">${child['year']}</h3>
|
||||
</div>
|
||||
</a>
|
||||
</li>
|
||||
% endfor
|
||||
</ul>
|
||||
</div>
|
||||
% endif
|
||||
% if 'season' in data['results_list'] and data['results_list']['season']:
|
||||
<div class="item-children-wrapper">
|
||||
<div class="item-children-section-title">
|
||||
<h4>Seasons</h4>
|
||||
</div>
|
||||
<ul class="item-children-instance list-unstyled">
|
||||
% for child in data['results_list']['season']:
|
||||
<li>
|
||||
<a href="info?item_id=${child['rating_key']}" id="${child['rating_key']}">
|
||||
<div class="item-children-poster">
|
||||
<div class="item-children-poster-face season-poster" style="background-image: url(pms_image_proxy?img=${child['thumb']}&width=300&height=450);"></div>
|
||||
</div>
|
||||
<div class="item-children-instance-text-wrapper season-item">
|
||||
<h3 title="${child['parent_title']}">${child['parent_title']}</h3>
|
||||
<h3 class="text-muted">S${child['index']}</h3>
|
||||
</div>
|
||||
</a>
|
||||
</li>
|
||||
% endfor
|
||||
</ul>
|
||||
</div>
|
||||
% endif
|
||||
% if 'episode' in data['results_list'] and data['results_list']['episode']:
|
||||
<div class="item-children-wrapper">
|
||||
<div class="item-children-section-title">
|
||||
<h4>Episodes</h4>
|
||||
</div>
|
||||
<ul class="item-children-instance list-unstyled">
|
||||
% for child in data['results_list']['episode']:
|
||||
<li>
|
||||
<a href="info?item_id=${child['rating_key']}" id="${child['rating_key']}">
|
||||
<div class="item-children-poster">
|
||||
<div class="item-children-poster-face episode-poster" style="background-image: url(pms_image_proxy?img=${child['thumb']}&width=300&height=450);"></div>
|
||||
</div>
|
||||
<div class="item-children-instance-text-wrapper episode-item">
|
||||
<h3 title="${child['grandparent_title']}">${child['grandparent_title']}</h3>
|
||||
<h3 title="${child['title']}">${child['title']}</h3>
|
||||
<h3 class="text-muted">S${child['parent_index']} · E${child['index']}</h3>
|
||||
</div>
|
||||
</a>
|
||||
</li>
|
||||
% endfor
|
||||
</ul>
|
||||
</div>
|
||||
% endif
|
||||
% if 'artist' in data['results_list'] and data['results_list']['artist']:
|
||||
<div class="item-children-wrapper">
|
||||
<div class="item-children-section-title">
|
||||
<h4>Artists</h4>
|
||||
</div>
|
||||
<ul class="item-children-instance list-unstyled">
|
||||
% for child in data['results_list']['artist']:
|
||||
<li>
|
||||
<a href="info?item_id=${child['rating_key']}" id="${child['rating_key']}">
|
||||
<div class="item-children-poster">
|
||||
<div class="item-children-poster-face album-poster" style="background-image: url(pms_image_proxy?img=${child['thumb']}&width=300&height=300);"></div>
|
||||
</div>
|
||||
<div class="item-children-instance-text-wrapper album-item">
|
||||
<h3 title="${child['title']}">${child['title']}</h3>
|
||||
</div>
|
||||
</a>
|
||||
</li>
|
||||
% endfor
|
||||
</ul>
|
||||
</div>
|
||||
% endif
|
||||
% if 'album' in data['results_list'] and data['results_list']['album']:
|
||||
<div class="item-children-wrapper">
|
||||
<div class="item-children-section-title">
|
||||
<h4>Albums</h4>
|
||||
</div>
|
||||
<ul class="item-children-instance list-unstyled">
|
||||
% for child in data['results_list']['album']:
|
||||
<li>
|
||||
<a href="info?item_id=${child['rating_key']}" id="${child['rating_key']}">
|
||||
<div class="item-children-poster">
|
||||
<div class="item-children-poster-face album-poster" style="background-image: url(pms_image_proxy?img=${child['thumb']}&width=300&height=300);"></div>
|
||||
</div>
|
||||
<div class="item-children-instance-text-wrapper album-item">
|
||||
<h3 title="${child['parent_title']}">${child['parent_title']}</h3>
|
||||
<h3 title="${child['title']}">${child['title']}</h3>
|
||||
</div>
|
||||
</a>
|
||||
</li>
|
||||
% endfor
|
||||
</ul>
|
||||
</div>
|
||||
% endif
|
||||
% if 'track' in data['results_list'] and data['results_list']['track']:
|
||||
<div class="item-children-wrapper">
|
||||
<div class="item-children-section-title">
|
||||
<h4>Tracks</h4>
|
||||
</div>
|
||||
<ul class="item-children-instance list-unstyled">
|
||||
% for child in data['results_list']['track']:
|
||||
<li>
|
||||
<a href="info?item_id=${child['rating_key']}" id="${child['rating_key']}">
|
||||
<div class="item-children-poster">
|
||||
<div class="item-children-poster-face album-poster" style="background-image: url(pms_image_proxy?img=${child['parent_thumb']}&width=300&height=300);">
|
||||
<div class="item-children-card-overlay">
|
||||
<div class="item-children-overlay-text">
|
||||
Track ${child['index']}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="item-children-instance-text-wrapper album-item">
|
||||
<h3 title="${child['grandparent_title']}">${child['grandparent_title']}</h3>
|
||||
<h3 title="${child['title']}">${child['title']}</h3>
|
||||
<h3 title="${child['parent_title']}" class="text-muted">${child['parent_title']}</h3>
|
||||
</div>
|
||||
</a>
|
||||
</li>
|
||||
% endfor
|
||||
</ul>
|
||||
</div>
|
||||
% endif
|
||||
% else:
|
||||
<div class="item-children-wrapper">
|
||||
No search results found.
|
||||
</div>
|
||||
% endif
|
||||
% endif
|
||||
|
41
data/interfaces/default/search.html
Normal file
41
data/interfaces/default/search.html
Normal file
|
@ -0,0 +1,41 @@
|
|||
<%inherit file="base.html"/>
|
||||
|
||||
<%def name="headIncludes()">
|
||||
</%def>
|
||||
|
||||
<%def name="headerIncludes()">
|
||||
</%def>
|
||||
|
||||
<%def name="body()">
|
||||
<div class='container-fluid'>
|
||||
<div class='table-card-header'>
|
||||
<div class="header-bar">
|
||||
<span><i class="fa fa-search"></i> Search Results
|
||||
% if query:
|
||||
for <strong>${query}</strong>
|
||||
% endif
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class='table-card-back'>
|
||||
<div id="search-results-list"><i class="fa fa-refresh fa-spin"></i> Loading search results...</div>
|
||||
</div>
|
||||
</div>
|
||||
</%def>
|
||||
|
||||
<%def name="javascriptIncludes()">
|
||||
<script>
|
||||
$('#search_button').removeClass('btn-inactive');
|
||||
$('#search_query').val('${query}').css({ right: '0', width: '250px' }).addClass('active');
|
||||
|
||||
$.ajax({
|
||||
url: 'get_search_results_children',
|
||||
type: "GET",
|
||||
async: true,
|
||||
data: {'query': "${query}"},
|
||||
complete: function (xhr, status) {
|
||||
$("#search-results-list").html(xhr.responseText);
|
||||
}
|
||||
});
|
||||
</script>
|
||||
</%def>
|
|
@ -789,4 +789,204 @@ class DataFactory(object):
|
|||
|
||||
return 'Deleted all items for user_id %s.' % user_id
|
||||
else:
|
||||
return 'Unable to delete items. Input user_id not valid.'
|
||||
return 'Unable to delete items. Input user_id not valid.'
|
||||
|
||||
def get_search_query(self, rating_key=''):
|
||||
monitor_db = database.MonitorDatabase()
|
||||
|
||||
if rating_key:
|
||||
query = 'SELECT rating_key, parent_rating_key, grandparent_rating_key, title, parent_title, grandparent_title, ' \
|
||||
'media_index, parent_media_index, year, media_type ' \
|
||||
'FROM session_history_metadata ' \
|
||||
'WHERE rating_key = ? ' \
|
||||
'OR parent_rating_key = ? ' \
|
||||
'OR grandparent_rating_key = ? ' \
|
||||
'LIMIT 1'
|
||||
result = monitor_db.select(query=query, args=[rating_key, rating_key, rating_key])
|
||||
else:
|
||||
result = []
|
||||
|
||||
query = {}
|
||||
query_string = None
|
||||
media_type = None
|
||||
|
||||
for item in result:
|
||||
title = item['title']
|
||||
parent_title = item['parent_title']
|
||||
grandparent_title = item['grandparent_title']
|
||||
media_index = item['media_index']
|
||||
parent_media_index = item['parent_media_index']
|
||||
year = item['year']
|
||||
|
||||
if str(item['rating_key']) == rating_key:
|
||||
query_string = item['title']
|
||||
media_type = item['media_type']
|
||||
|
||||
elif str(item['parent_rating_key']) == rating_key:
|
||||
if item['media_type'] == 'episode':
|
||||
query_string = item['grandparent_title']
|
||||
media_type = 'season'
|
||||
elif item['media_type'] == 'track':
|
||||
query_string = item['parent_title']
|
||||
media_type = 'album'
|
||||
|
||||
elif str(item['grandparent_rating_key']) == rating_key:
|
||||
if item['media_type'] == 'episode':
|
||||
query_string = item['grandparent_title']
|
||||
media_type = 'show'
|
||||
elif item['media_type'] == 'track':
|
||||
query_string = item['grandparent_title']
|
||||
media_type = 'artist'
|
||||
|
||||
if query_string and media_type:
|
||||
query = {'query_string': query_string.replace('"', ''),
|
||||
'title': title,
|
||||
'parent_title': parent_title,
|
||||
'grandparent_title': grandparent_title,
|
||||
'media_index': media_index,
|
||||
'parent_media_index': parent_media_index,
|
||||
'year': year,
|
||||
'media_type': media_type,
|
||||
'rating_key': rating_key
|
||||
}
|
||||
else:
|
||||
return None
|
||||
|
||||
return query
|
||||
|
||||
def get_rating_keys_list(self, rating_key='', media_type=''):
|
||||
monitor_db = database.MonitorDatabase()
|
||||
|
||||
if media_type == 'movie':
|
||||
key_list = {0: {'rating_key': int(rating_key)}}
|
||||
return key_list
|
||||
|
||||
if media_type == 'artist' or media_type == 'album' or media_type == 'track':
|
||||
match_type = 'title'
|
||||
else:
|
||||
match_type = 'index'
|
||||
|
||||
# Get the grandparent rating key
|
||||
try:
|
||||
query = 'SELECT rating_key, parent_rating_key, grandparent_rating_key ' \
|
||||
'FROM session_history_metadata ' \
|
||||
'WHERE rating_key = ? ' \
|
||||
'OR parent_rating_key = ? ' \
|
||||
'OR grandparent_rating_key = ? ' \
|
||||
'LIMIT 1'
|
||||
result = monitor_db.select(query=query, args=[rating_key, rating_key, rating_key])
|
||||
|
||||
grandparent_rating_key = result[0]['grandparent_rating_key']
|
||||
|
||||
except:
|
||||
logger.warn("Unable to execute database query.")
|
||||
return {}
|
||||
|
||||
query = 'SELECT rating_key, parent_rating_key, grandparent_rating_key, title, parent_title, grandparent_title, ' \
|
||||
'media_index, parent_media_index ' \
|
||||
'FROM session_history_metadata ' \
|
||||
'WHERE {0} = ? ' \
|
||||
'GROUP BY {1} '
|
||||
|
||||
# get grandparent_rating_keys
|
||||
grandparents = {}
|
||||
result = monitor_db.select(query=query.format('grandparent_rating_key', 'grandparent_rating_key'),
|
||||
args=[grandparent_rating_key])
|
||||
for item in result:
|
||||
# get parent_rating_keys
|
||||
parents = {}
|
||||
result = monitor_db.select(query=query.format('grandparent_rating_key', 'parent_rating_key'),
|
||||
args=[item['grandparent_rating_key']])
|
||||
for item in result:
|
||||
# get rating_keys
|
||||
children = {}
|
||||
result = monitor_db.select(query=query.format('parent_rating_key', 'rating_key'),
|
||||
args=[item['parent_rating_key']])
|
||||
for item in result:
|
||||
key = item['media_index']
|
||||
children.update({key: {'rating_key': item['rating_key']}})
|
||||
|
||||
key = item['parent_media_index'] if match_type == 'index' else item['parent_title']
|
||||
parents.update({key:
|
||||
{'rating_key': item['parent_rating_key'],
|
||||
'children': children}
|
||||
})
|
||||
|
||||
key = 0 if match_type == 'index' else item['grandparent_title']
|
||||
grandparents.update({key:
|
||||
{'rating_key': item['grandparent_rating_key'],
|
||||
'children': parents}
|
||||
})
|
||||
|
||||
key_list = grandparents
|
||||
|
||||
return key_list
|
||||
|
||||
def update_rating_key(self, old_key_list='', new_key_list='', media_type=''):
|
||||
monitor_db = database.MonitorDatabase()
|
||||
|
||||
# function to map rating keys pairs
|
||||
def get_pairs(old, new):
|
||||
pairs = {}
|
||||
for k, v in old.iteritems():
|
||||
if k in new:
|
||||
if v['rating_key'] != new[k]['rating_key']:
|
||||
pairs.update({v['rating_key']: new[k]['rating_key']})
|
||||
if 'children' in old[k]:
|
||||
pairs.update(get_pairs(old[k]['children'], new[k]['children']))
|
||||
|
||||
return pairs
|
||||
|
||||
# map rating keys pairs
|
||||
mapping = {}
|
||||
if old_key_list and new_key_list:
|
||||
mapping = get_pairs(old_key_list, new_key_list)
|
||||
|
||||
if mapping:
|
||||
logger.info(u"PlexPy DataFactory :: Updating rating keys in the database.")
|
||||
for old_key, new_key in mapping.iteritems():
|
||||
# check rating_key (3 tables)
|
||||
monitor_db.action('UPDATE session_history SET rating_key = ? WHERE rating_key = ?',
|
||||
[new_key, old_key])
|
||||
monitor_db.action('UPDATE session_history_media_info SET rating_key = ? WHERE rating_key = ?',
|
||||
[new_key, old_key])
|
||||
monitor_db.action('UPDATE session_history_metadata SET rating_key = ? WHERE rating_key = ?',
|
||||
[new_key, old_key])
|
||||
|
||||
# check parent_rating_key (2 tables)
|
||||
monitor_db.action('UPDATE session_history SET parent_rating_key = ? WHERE parent_rating_key = ?',
|
||||
[new_key, old_key])
|
||||
monitor_db.action('UPDATE session_history_metadata SET parent_rating_key = ? WHERE parent_rating_key = ?',
|
||||
[new_key, old_key])
|
||||
|
||||
# check grandparent_rating_key (2 tables)
|
||||
monitor_db.action('UPDATE session_history SET grandparent_rating_key = ? WHERE grandparent_rating_key = ?',
|
||||
[new_key, old_key])
|
||||
monitor_db.action('UPDATE session_history_metadata SET grandparent_rating_key = ? WHERE grandparent_rating_key = ?',
|
||||
[new_key, old_key])
|
||||
|
||||
# check thumb (1 table)
|
||||
monitor_db.action('UPDATE session_history_metadata SET thumb = replace(thumb, ?, ?) \
|
||||
WHERE thumb LIKE "/library/metadata/%s/thumb/%%"' % old_key,
|
||||
[old_key, new_key])
|
||||
|
||||
# check parent_thumb (1 table)
|
||||
monitor_db.action('UPDATE session_history_metadata SET parent_thumb = replace(parent_thumb, ?, ?) \
|
||||
WHERE parent_thumb LIKE "/library/metadata/%s/thumb/%%"' % old_key,
|
||||
[old_key, new_key])
|
||||
|
||||
# check grandparent_thumb (1 table)
|
||||
monitor_db.action('UPDATE session_history_metadata SET grandparent_thumb = replace(grandparent_thumb, ?, ?) \
|
||||
WHERE grandparent_thumb LIKE "/library/metadata/%s/thumb/%%"' % old_key,
|
||||
[old_key, new_key])
|
||||
|
||||
# check art (1 table)
|
||||
monitor_db.action('UPDATE session_history_metadata SET art = replace(art, ?, ?) \
|
||||
WHERE art LIKE "/library/metadata/%s/art/%%"' % old_key,
|
||||
[old_key, new_key])
|
||||
|
||||
return 'Updated rating key in database.'
|
||||
else:
|
||||
return 'No updated rating key needed in database. No changes were made.'
|
||||
# for debugging
|
||||
#return mapping
|
|
@ -17,6 +17,7 @@ from plexpy import logger, helpers, users, http_handler
|
|||
from urlparse import urlparse
|
||||
|
||||
import plexpy
|
||||
import urllib2
|
||||
|
||||
|
||||
class PmsConnect(object):
|
||||
|
@ -72,6 +73,23 @@ class PmsConnect(object):
|
|||
|
||||
return request
|
||||
|
||||
"""
|
||||
Return metadata for children of the request item.
|
||||
|
||||
Parameters required: rating_key { Plex ratingKey }
|
||||
Optional parameters: output_format { dict, json }
|
||||
|
||||
Output: array
|
||||
"""
|
||||
def get_metadata_children(self, rating_key='', output_format=''):
|
||||
uri = '/library/metadata/' + rating_key + '/children'
|
||||
request = self.request_handler.make_request(uri=uri,
|
||||
proto=self.protocol,
|
||||
request_type='GET',
|
||||
output_format=output_format)
|
||||
|
||||
return request
|
||||
|
||||
"""
|
||||
Return list of recently added items.
|
||||
|
||||
|
@ -219,6 +237,22 @@ class PmsConnect(object):
|
|||
|
||||
return request
|
||||
|
||||
"""
|
||||
Return search results.
|
||||
|
||||
Optional parameters: output_format { dict, json }
|
||||
|
||||
Output: array
|
||||
"""
|
||||
def get_search(self, query='', track='', output_format=''):
|
||||
uri = '/search?query=' + urllib2.quote(query.encode('utf8')) + track
|
||||
request = self.request_handler.make_request(uri=uri,
|
||||
proto=self.protocol,
|
||||
request_type='GET',
|
||||
output_format=output_format)
|
||||
|
||||
return request
|
||||
|
||||
"""
|
||||
Return processed and validated list of recently added items.
|
||||
|
||||
|
@ -1340,3 +1374,202 @@ class PmsConnect(object):
|
|||
else:
|
||||
logger.error("Image proxy queries but no input received.")
|
||||
return None
|
||||
|
||||
"""
|
||||
Return processed list of search results.
|
||||
|
||||
Output: array
|
||||
"""
|
||||
def get_search_results(self, query=''):
|
||||
search_results = self.get_search(query=query, output_format='xml')
|
||||
search_results_tracks = self.get_search(query=query, track='&type=10', output_format='xml')
|
||||
|
||||
xml_head = []
|
||||
try:
|
||||
try:
|
||||
xml_head += search_results.getElementsByTagName('MediaContainer')
|
||||
except:
|
||||
pass
|
||||
try:
|
||||
xml_head += search_results_tracks.getElementsByTagName('MediaContainer')
|
||||
except:
|
||||
pass
|
||||
except:
|
||||
logger.warn("Unable to parse XML for get_search_result_details.")
|
||||
return []
|
||||
|
||||
search_results_count = 0
|
||||
search_results_list = {'movie': [],
|
||||
'show': [],
|
||||
'season': [],
|
||||
'episode': [],
|
||||
'artist': [],
|
||||
'album': [],
|
||||
'track': []
|
||||
}
|
||||
|
||||
totalSize = 0
|
||||
for a in xml_head:
|
||||
if a.getAttribute('size'):
|
||||
totalSize += int(a.getAttribute('size'))
|
||||
if totalSize == 0:
|
||||
logger.debug(u"No search results.")
|
||||
search_results_list = {'results_count': search_results_count,
|
||||
'results_list': []
|
||||
}
|
||||
return search_results_list
|
||||
|
||||
for a in xml_head:
|
||||
if a.getElementsByTagName('Video'):
|
||||
result_data = a.getElementsByTagName('Video')
|
||||
for result in result_data:
|
||||
rating_key = helpers.get_xml_attr(result, 'ratingKey')
|
||||
metadata = self.get_metadata_details(rating_key=rating_key)
|
||||
if metadata['metadata']['type'] == 'movie':
|
||||
search_results_list['movie'].append(metadata['metadata'])
|
||||
elif metadata['metadata']['type'] == 'episode':
|
||||
search_results_list['episode'].append(metadata['metadata'])
|
||||
search_results_count += 1
|
||||
|
||||
if a.getElementsByTagName('Directory'):
|
||||
result_data = a.getElementsByTagName('Directory')
|
||||
for result in result_data:
|
||||
rating_key = helpers.get_xml_attr(result, 'ratingKey')
|
||||
metadata = self.get_metadata_details(rating_key=rating_key)
|
||||
if metadata['metadata']['type'] == 'show':
|
||||
search_results_list['show'].append(metadata['metadata'])
|
||||
|
||||
show_seasons = self.get_item_children(rating_key=metadata['metadata']['rating_key'])
|
||||
if show_seasons['children_count'] != '0':
|
||||
for season in show_seasons['children_list']:
|
||||
if season['rating_key']:
|
||||
rating_key = season['rating_key']
|
||||
metadata = self.get_metadata_details(rating_key=rating_key)
|
||||
search_results_list['season'].append(metadata['metadata'])
|
||||
search_results_count += 1
|
||||
|
||||
elif metadata['metadata']['type'] == 'artist':
|
||||
search_results_list['artist'].append(metadata['metadata'])
|
||||
elif metadata['metadata']['type'] == 'album':
|
||||
search_results_list['album'].append(metadata['metadata'])
|
||||
search_results_count += 1
|
||||
|
||||
if a.getElementsByTagName('Track'):
|
||||
result_data = a.getElementsByTagName('Track')
|
||||
for result in result_data:
|
||||
rating_key = helpers.get_xml_attr(result, 'ratingKey')
|
||||
metadata = self.get_metadata_details(rating_key=rating_key)
|
||||
search_results_list['track'].append(metadata['metadata'])
|
||||
search_results_count += 1
|
||||
|
||||
output = {'results_count': search_results_count,
|
||||
'results_list': search_results_list
|
||||
}
|
||||
|
||||
return output
|
||||
|
||||
"""
|
||||
Return processed list of grandparent/parent/child rating keys.
|
||||
|
||||
Output: array
|
||||
"""
|
||||
def get_rating_keys_list(self, rating_key='', media_type=''):
|
||||
|
||||
if media_type == 'movie':
|
||||
key_list = {0: {'rating_key': int(rating_key)}}
|
||||
return key_list
|
||||
|
||||
if media_type == 'artist' or media_type == 'album' or media_type == 'track':
|
||||
match_type = 'title'
|
||||
else:
|
||||
match_type = 'index'
|
||||
|
||||
# get grandparent rating key
|
||||
if media_type == 'season' or media_type == 'album':
|
||||
try:
|
||||
metadata = self.get_metadata_details(rating_key=rating_key)
|
||||
rating_key = metadata['metadata']['parent_rating_key']
|
||||
except:
|
||||
logger.warn("Unable to get parent_rating_key for get_rating_keys_list.")
|
||||
return {}
|
||||
|
||||
elif media_type == 'episode' or media_type == 'track':
|
||||
try:
|
||||
metadata = self.get_metadata_details(rating_key=rating_key)
|
||||
rating_key = metadata['metadata']['grandparent_rating_key']
|
||||
except:
|
||||
logger.warn("Unable to get grandparent_rating_key for get_rating_keys_list.")
|
||||
return {}
|
||||
|
||||
# get parent_rating_keys
|
||||
metadata = self.get_metadata_children(str(rating_key), output_format='xml')
|
||||
|
||||
try:
|
||||
xml_head = metadata.getElementsByTagName('MediaContainer')
|
||||
except:
|
||||
logger.warn("Unable to parse XML for get_rating_keys_list.")
|
||||
return {}
|
||||
|
||||
for a in xml_head:
|
||||
if a.getAttribute('size'):
|
||||
if a.getAttribute('size') == '0':
|
||||
return {}
|
||||
|
||||
title = helpers.get_xml_attr(a, 'title2')
|
||||
|
||||
if a.getElementsByTagName('Directory'):
|
||||
parents_metadata = a.getElementsByTagName('Directory')
|
||||
else:
|
||||
parents_metadata = []
|
||||
|
||||
parents = {}
|
||||
for item in parents_metadata:
|
||||
parent_rating_key = helpers.get_xml_attr(item, 'ratingKey')
|
||||
parent_index = helpers.get_xml_attr(item, 'index')
|
||||
parent_title = helpers.get_xml_attr(item, 'title')
|
||||
|
||||
if parent_rating_key:
|
||||
# get rating_keys
|
||||
metadata = self.get_metadata_children(str(parent_rating_key), output_format='xml')
|
||||
|
||||
try:
|
||||
xml_head = metadata.getElementsByTagName('MediaContainer')
|
||||
except:
|
||||
logger.warn("Unable to parse XML for get_rating_keys_list.")
|
||||
return {}
|
||||
|
||||
for a in xml_head:
|
||||
if a.getAttribute('size'):
|
||||
if a.getAttribute('size') == '0':
|
||||
return {}
|
||||
|
||||
if a.getElementsByTagName('Video'):
|
||||
children_metadata = a.getElementsByTagName('Video')
|
||||
elif a.getElementsByTagName('Track'):
|
||||
children_metadata = a.getElementsByTagName('Track')
|
||||
else:
|
||||
children_metadata = []
|
||||
|
||||
children = {}
|
||||
for item in children_metadata:
|
||||
child_rating_key = helpers.get_xml_attr(item, 'ratingKey')
|
||||
child_index = helpers.get_xml_attr(item, 'index')
|
||||
child_title = helpers.get_xml_attr(item, 'title')
|
||||
|
||||
if child_rating_key:
|
||||
key = int(child_index)
|
||||
children.update({key: {'rating_key': int(child_rating_key)}})
|
||||
|
||||
key = int(parent_index) if match_type == 'index' else parent_title
|
||||
parents.update({key:
|
||||
{'rating_key': int(parent_rating_key),
|
||||
'children': children}
|
||||
})
|
||||
|
||||
key = 0 if match_type == 'index' else title
|
||||
key_list = {key:
|
||||
{'rating_key': int(rating_key),
|
||||
'children': parents}
|
||||
}
|
||||
|
||||
return key_list
|
|
@ -761,6 +761,7 @@ class WebInterface(object):
|
|||
@cherrypy.expose
|
||||
def info(self, item_id=None, source=None, **kwargs):
|
||||
metadata = None
|
||||
query = None
|
||||
|
||||
config = {
|
||||
"pms_identifier": plexpy.CONFIG.PMS_IDENTIFIER
|
||||
|
@ -774,12 +775,15 @@ class WebInterface(object):
|
|||
result = pms_connect.get_metadata_details(rating_key=item_id)
|
||||
if result:
|
||||
metadata = result['metadata']
|
||||
else:
|
||||
data_factory = datafactory.DataFactory()
|
||||
query = data_factory.get_search_query(rating_key=item_id)
|
||||
|
||||
if metadata:
|
||||
return serve_template(templatename="info.html", data=metadata, title="Info", config=config)
|
||||
else:
|
||||
logger.warn('Unable to retrieve data.')
|
||||
return serve_template(templatename="info.html", data=None, title="Info")
|
||||
return serve_template(templatename="info.html", data=None, query=query, title="Info")
|
||||
|
||||
@cherrypy.expose
|
||||
def get_user_recently_watched(self, user=None, user_id=None, limit='10', **kwargs):
|
||||
|
@ -1335,3 +1339,105 @@ class WebInterface(object):
|
|||
cherrypy.response.headers['Content-type'] = 'application/json'
|
||||
return json.dumps({'message': 'no data received'})
|
||||
|
||||
@cherrypy.expose
|
||||
def search(self, search_query=''):
|
||||
query = search_query.replace('"', '')
|
||||
|
||||
return serve_template(templatename="search.html", title="Search", query=query)
|
||||
|
||||
@cherrypy.expose
|
||||
def search_results(self, query, **kwargs):
|
||||
|
||||
pms_connect = pmsconnect.PmsConnect()
|
||||
result = pms_connect.get_search_results(query)
|
||||
|
||||
if result:
|
||||
cherrypy.response.headers['Content-type'] = 'application/json'
|
||||
return json.dumps(result)
|
||||
else:
|
||||
logger.warn('Unable to retrieve data.')
|
||||
|
||||
@cherrypy.expose
|
||||
def get_search_results_children(self, query, media_type=None, season_index=None, **kwargs):
|
||||
|
||||
pms_connect = pmsconnect.PmsConnect()
|
||||
result = pms_connect.get_search_results(query)
|
||||
|
||||
if media_type:
|
||||
result['results_list'] = {media_type: result['results_list'][media_type]}
|
||||
if media_type == 'season' and season_index:
|
||||
for season in result['results_list']['season']:
|
||||
if season['index'] == season_index:
|
||||
result['results_list']['season'] = [season]
|
||||
break
|
||||
|
||||
if result:
|
||||
return serve_template(templatename="info_search_results_list.html", data=result, title="Search Result List")
|
||||
else:
|
||||
logger.warn('Unable to retrieve data.')
|
||||
return serve_template(templatename="info_search_results_list.html", data=None, title="Search Result List")
|
||||
|
||||
@cherrypy.expose
|
||||
def update_history_rating_key(self, old_rating_key, new_rating_key, media_type, **kwargs):
|
||||
data_factory = datafactory.DataFactory()
|
||||
pms_connect = pmsconnect.PmsConnect()
|
||||
|
||||
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)
|
||||
|
||||
update_db = data_factory.update_rating_key(old_key_list=old_key_list,
|
||||
new_key_list=new_key_list,
|
||||
media_type=media_type)
|
||||
|
||||
if update_db:
|
||||
cherrypy.response.headers['Content-type'] = 'application/json'
|
||||
return json.dumps({'message': update_db})
|
||||
else:
|
||||
cherrypy.response.headers['Content-type'] = 'application/json'
|
||||
return json.dumps({'message': 'no data received'})
|
||||
|
||||
|
||||
# test code
|
||||
@cherrypy.expose
|
||||
def get_new_rating_keys(self, rating_key='', media_type='', **kwargs):
|
||||
|
||||
pms_connect = pmsconnect.PmsConnect()
|
||||
result = pms_connect.get_rating_keys_list(rating_key=rating_key, media_type=media_type)
|
||||
|
||||
if result:
|
||||
cherrypy.response.headers['Content-type'] = 'application/json'
|
||||
return json.dumps(result)
|
||||
else:
|
||||
logger.warn('Unable to retrieve data.')
|
||||
|
||||
@cherrypy.expose
|
||||
def get_old_rating_keys(self, rating_key='', media_type='', **kwargs):
|
||||
|
||||
data_factory = datafactory.DataFactory()
|
||||
result = data_factory.get_rating_keys_list(rating_key=rating_key, media_type=media_type)
|
||||
|
||||
if result:
|
||||
cherrypy.response.headers['Content-type'] = 'application/json'
|
||||
return json.dumps(result)
|
||||
else:
|
||||
logger.warn('Unable to retrieve data.')
|
||||
|
||||
@cherrypy.expose
|
||||
def get_map_rating_keys(self, old_rating_key, new_rating_key, media_type, **kwargs):
|
||||
|
||||
data_factory = datafactory.DataFactory()
|
||||
pms_connect = pmsconnect.PmsConnect()
|
||||
|
||||
if new_rating_key:
|
||||
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)
|
||||
|
||||
result = data_factory.update_rating_key(old_key_list=old_key_list,
|
||||
new_key_list=new_key_list,
|
||||
media_type=media_type)
|
||||
|
||||
if result:
|
||||
cherrypy.response.headers['Content-type'] = 'application/json'
|
||||
return json.dumps(result)
|
||||
else:
|
||||
logger.warn('Unable to retrieve data.')
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue