Compare commits
14 Commits
v2.0.9-bet
...
v2.0.11-be
Author | SHA1 | Date | |
---|---|---|---|
![]() |
cf14fbc3f0 | ||
![]() |
e471d5207d | ||
![]() |
5722a52082 | ||
![]() |
08c32e875e | ||
![]() |
7d3ee3afb3 | ||
![]() |
def8600f5c | ||
![]() |
74a68f3c7d | ||
![]() |
64c9247dd1 | ||
![]() |
1bfcd34247 | ||
![]() |
19864e97e6 | ||
![]() |
ec5c5e1420 | ||
![]() |
803f4e14ca | ||
![]() |
6cc254b80a | ||
![]() |
59593ab1aa |
26
CHANGELOG.md
26
CHANGELOG.md
@@ -1,16 +1,36 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
|
## v2.0.11-beta (2018-01-05)
|
||||||
|
|
||||||
|
* Notifications:
|
||||||
|
* Fix: Some notification parameters showing up blank.
|
||||||
|
* UI:
|
||||||
|
* Fix: Stream data showing up as "None" for pre-v2 history.
|
||||||
|
* Other:
|
||||||
|
* Fix: Ability to login using the hashed password.
|
||||||
|
|
||||||
|
|
||||||
|
## v2.0.10-beta (2018-01-04)
|
||||||
|
|
||||||
|
* Monitoring:
|
||||||
|
* Fix: HW transcoding indicator on activity cards incorrect after refreshing.
|
||||||
|
* Notifications:
|
||||||
|
* Remove: Notification toggles from library and user settings. Use custom conditions to filter out notifications instead.
|
||||||
|
* UI:
|
||||||
|
* Fix: Incorrect examples for some date format options. Also added a few missing date format options. (Thanks @Tommatheussen)
|
||||||
|
|
||||||
|
|
||||||
## v2.0.9-beta (2018-01-03)
|
## v2.0.9-beta (2018-01-03)
|
||||||
|
|
||||||
* Notifications:
|
* Notifications:
|
||||||
* Fix: Notifications failing due to incorrect season/episode number types.
|
* Fix: Notifications failing due to incorrect season/episode number types.
|
||||||
|
|
||||||
|
|
||||||
## v2.0.8-beta (2018-01-03)
|
## v2.0.8-beta (2018-01-03)
|
||||||
|
|
||||||
* Monitoring:
|
* Monitoring:
|
||||||
* Fix: Fix HW transcoding indicator on activity cards.
|
* Fix: Incorrect HW transcoding indicator on activity cards.
|
||||||
* Fix: Fix long product/player names hidden behind platform icon on activity cards.
|
* Fix: Long product/player names hidden behind platform icon on activity cards.
|
||||||
* Notifications:
|
* Notifications:
|
||||||
* Fix: Notifications failing due to some missing notification parameters.
|
* Fix: Notifications failing due to some missing notification parameters.
|
||||||
|
|
||||||
|
@@ -47,24 +47,12 @@ DOCUMENTATION :: END
|
|||||||
</div>
|
</div>
|
||||||
<p class="help-block">Change the library's picture in Tautulli. To reset to default, leave this field empty and save.</p>
|
<p class="help-block">Change the library's picture in Tautulli. To reset to default, leave this field empty and save.</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="checkbox">
|
|
||||||
<label>
|
|
||||||
<input type="checkbox" id="do_notify" name="do_notify" value="1" ${helpers.checked(data['do_notify'])}> Enable notifications
|
|
||||||
</label>
|
|
||||||
<p class="help-block">Uncheck this if you do not want to receive notifications for this library's activity.</p>
|
|
||||||
</div>
|
|
||||||
<div class="checkbox">
|
<div class="checkbox">
|
||||||
<label>
|
<label>
|
||||||
<input type="checkbox" id="keep_history" name="keep_history" value="1" ${helpers.checked(data['keep_history'])}> Keep history
|
<input type="checkbox" id="keep_history" name="keep_history" value="1" ${helpers.checked(data['keep_history'])}> Keep history
|
||||||
</label>
|
</label>
|
||||||
<p class="help-block">Uncheck this if you do not want to keep any history on this library's activity.</p>
|
<p class="help-block">Uncheck this if you do not want to keep any history on this library's activity.</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="checkbox">
|
|
||||||
<label>
|
|
||||||
<input type="checkbox" id="do_notify_created" name="do_notify_created" value="1" ${helpers.checked(data['do_notify_created'])}> Enable recently added notifications
|
|
||||||
</label>
|
|
||||||
<p class="help-block">Uncheck this if you do not want to receive recently added notifications for this library.</p>
|
|
||||||
</div>
|
|
||||||
% if data['section_id']:
|
% if data['section_id']:
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<button class="btn btn-danger" id="delete-all-history">Purge</button>
|
<button class="btn btn-danger" id="delete-all-history">Purge</button>
|
||||||
@@ -85,15 +73,7 @@ DOCUMENTATION :: END
|
|||||||
// Save library options
|
// Save library options
|
||||||
$("#save_library").on('click', function () {
|
$("#save_library").on('click', function () {
|
||||||
var custom_thumb = $("#custom_thumb_url").val();
|
var custom_thumb = $("#custom_thumb_url").val();
|
||||||
var do_notify = 0;
|
|
||||||
var do_notify_created = 0;
|
|
||||||
var keep_history = 0;
|
var keep_history = 0;
|
||||||
if ($("#do_notify").is(":checked")) {
|
|
||||||
do_notify = 1;
|
|
||||||
}
|
|
||||||
if ($("#do_notify_created").is(":checked")) {
|
|
||||||
do_notify_created = 1;
|
|
||||||
}
|
|
||||||
if ($("#keep_history").is(":checked")) {
|
if ($("#keep_history").is(":checked")) {
|
||||||
keep_history = 1;
|
keep_history = 1;
|
||||||
}
|
}
|
||||||
@@ -103,8 +83,6 @@ DOCUMENTATION :: END
|
|||||||
data: {
|
data: {
|
||||||
section_id: '${data["section_id"]}',
|
section_id: '${data["section_id"]}',
|
||||||
custom_thumb: custom_thumb,
|
custom_thumb: custom_thumb,
|
||||||
do_notify: do_notify,
|
|
||||||
do_notify_created: do_notify_created,
|
|
||||||
keep_history: keep_history
|
keep_history: keep_history
|
||||||
},
|
},
|
||||||
cache: false,
|
cache: false,
|
||||||
|
@@ -56,12 +56,6 @@ DOCUMENTATION :: END
|
|||||||
</div>
|
</div>
|
||||||
<p class="help-block">Change the users profile picture in Tautulli. To reset to default, leave this field empty and save.</p>
|
<p class="help-block">Change the users profile picture in Tautulli. To reset to default, leave this field empty and save.</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="checkbox">
|
|
||||||
<label>
|
|
||||||
<input type="checkbox" id="do_notify" name="do_notify" value="1" ${helpers.checked(data['do_notify'])}> Enable notifications
|
|
||||||
</label>
|
|
||||||
<p class="help-block">Uncheck this if you do not want to receive notifications for this user's activity.</p>
|
|
||||||
</div>
|
|
||||||
<div class="checkbox">
|
<div class="checkbox">
|
||||||
<label>
|
<label>
|
||||||
<input type="checkbox" id="keep_history" name="keep_history" value="1" ${helpers.checked(data['keep_history'])}> Keep history
|
<input type="checkbox" id="keep_history" name="keep_history" value="1" ${helpers.checked(data['keep_history'])}> Keep history
|
||||||
@@ -95,12 +89,8 @@ DOCUMENTATION :: END
|
|||||||
$("#save_user").on('click', function () {
|
$("#save_user").on('click', function () {
|
||||||
var friendly_name = $("input#friendly_name").val();
|
var friendly_name = $("input#friendly_name").val();
|
||||||
var custom_thumb = $("#custom_avatar_url").val();
|
var custom_thumb = $("#custom_avatar_url").val();
|
||||||
var do_notify = 0;
|
|
||||||
var keep_history = 0;
|
var keep_history = 0;
|
||||||
var allow_guest = 0;
|
var allow_guest = 0;
|
||||||
if ($("#do_notify").is(":checked")) {
|
|
||||||
do_notify = 1;
|
|
||||||
}
|
|
||||||
if ($("#keep_history").is(":checked")) {
|
if ($("#keep_history").is(":checked")) {
|
||||||
keep_history = 1;
|
keep_history = 1;
|
||||||
}
|
}
|
||||||
@@ -114,7 +104,6 @@ DOCUMENTATION :: END
|
|||||||
user_id: '${data["user_id"]}',
|
user_id: '${data["user_id"]}',
|
||||||
friendly_name: friendly_name,
|
friendly_name: friendly_name,
|
||||||
custom_thumb: custom_thumb,
|
custom_thumb: custom_thumb,
|
||||||
do_notify: do_notify,
|
|
||||||
keep_history: keep_history,
|
keep_history: keep_history,
|
||||||
allow_guest: allow_guest
|
allow_guest: allow_guest
|
||||||
},
|
},
|
||||||
|
@@ -325,25 +325,26 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Update play state icon
|
// Update play state icon
|
||||||
|
var state_icon = '';
|
||||||
switch (s.state) {
|
switch (s.state) {
|
||||||
case 'playing':
|
case 'playing':
|
||||||
var state_icon = '<i class="fa fa-fw fa-play"></i> ';
|
state_icon = '<i class="fa fa-fw fa-play"></i> ';
|
||||||
break;
|
break;
|
||||||
case 'paused':
|
case 'paused':
|
||||||
var state_icon = '<i class="fa fa-fw fa-pause"></i> ';
|
state_icon = '<i class="fa fa-fw fa-pause"></i> ';
|
||||||
break;
|
break;
|
||||||
case 'buffering':
|
case 'buffering':
|
||||||
var state_icon = '<i class="fa fa-fw fa-spinner"></i> ';
|
state_icon = '<i class="fa fa-fw fa-spinner"></i> ';
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
var state_icon = '<i class="fa fa-fw fa-question-circle"></i> ';
|
state_icon = '<i class="fa fa-fw fa-question-circle"></i> ';
|
||||||
}
|
}
|
||||||
$('#play-state-' + key).html(state_icon).attr('title', capitalizeFirstLetter(s.state));
|
$('#play-state-' + key).html(state_icon).attr('title', capitalizeFirstLetter(s.state));
|
||||||
|
|
||||||
// Switching tracks can be under the same session key, so need to update the info.
|
// Switching tracks can be under the same session key, so need to update the info.
|
||||||
if (s.media_type === 'track') {
|
if (s.media_type === 'track') {
|
||||||
// Update if artist changed
|
// Update if artist changed
|
||||||
if (s.grandparent_rating_key != instance.data('grandparent_rating_key')) {
|
if (s.grandparent_rating_key !== instance.data('grandparent_rating_key')) {
|
||||||
$('#background-' + key).css('background-image', 'url(pms_image_proxy?img=' + s.art + '&width=500&height=280&fallback=art&refresh=true)');
|
$('#background-' + key).css('background-image', 'url(pms_image_proxy?img=' + s.art + '&width=500&height=280&fallback=art&refresh=true)');
|
||||||
$('#metadata-grandparent_title-' + key)
|
$('#metadata-grandparent_title-' + key)
|
||||||
.attr('href', 'info?rating_key=' + s.grandparent_rating_key)
|
.attr('href', 'info?rating_key=' + s.grandparent_rating_key)
|
||||||
@@ -351,7 +352,7 @@
|
|||||||
.text(s.grandparent_title);
|
.text(s.grandparent_title);
|
||||||
}
|
}
|
||||||
// Update cover if album changed
|
// Update cover if album changed
|
||||||
if (s.parent_rating_key != instance.data('parent_rating_key')) {
|
if (s.parent_rating_key !== instance.data('parent_rating_key')) {
|
||||||
$('#poster-' + key).css('background-image', 'url(pms_image_proxy?img=' + s.parent_thumb + '&width=300&height=300&fallback=poster&refresh=true)');
|
$('#poster-' + key).css('background-image', 'url(pms_image_proxy?img=' + s.parent_thumb + '&width=300&height=300&fallback=poster&refresh=true)');
|
||||||
$('#poster-' + key + '-bg').css('background-image', 'url(pms_image_proxy?img=' + s.parent_thumb + '&width=300&height=300&fallback=poster&refresh=true)');
|
$('#poster-' + key + '-bg').css('background-image', 'url(pms_image_proxy?img=' + s.parent_thumb + '&width=300&height=300&fallback=poster&refresh=true)');
|
||||||
$('#poster-url-' + key)
|
$('#poster-url-' + key)
|
||||||
@@ -363,7 +364,7 @@
|
|||||||
.text(s.parent_title);
|
.text(s.parent_title);
|
||||||
}
|
}
|
||||||
// Update cover if track changed
|
// Update cover if track changed
|
||||||
if (s.parent_rating_key != instance.data('parent_rating_key')) {
|
if (s.parent_rating_key !== instance.data('parent_rating_key')) {
|
||||||
$('#metadata-title-' + key)
|
$('#metadata-title-' + key)
|
||||||
.attr('href', 'info?rating_key=' + s.rating_key)
|
.attr('href', 'info?rating_key=' + s.rating_key)
|
||||||
.attr('title', s.title)
|
.attr('title', s.title)
|
||||||
@@ -374,7 +375,7 @@
|
|||||||
// Update the transcode state
|
// Update the transcode state
|
||||||
var transcode_decision = '';
|
var transcode_decision = '';
|
||||||
if (s.transcode_decision === 'transcode') {
|
if (s.transcode_decision === 'transcode') {
|
||||||
var throttled = (s.transcode_throttled == 1) ? ' (Throttled)' : ' (Speed: ' + s.transcode_speed + ')';
|
var throttled = (s.transcode_throttled === 1) ? ' (Throttled)' : ' (Speed: ' + s.transcode_speed + ')';
|
||||||
transcode_decision = 'Transcode' + throttled;
|
transcode_decision = 'Transcode' + throttled;
|
||||||
} else if (s.transcode_decision === 'copy') {
|
} else if (s.transcode_decision === 'copy') {
|
||||||
transcode_decision = 'Direct Stream';
|
transcode_decision = 'Direct Stream';
|
||||||
@@ -392,36 +393,32 @@
|
|||||||
$('#transcode_container-' + key).html(transcode_container);
|
$('#transcode_container-' + key).html(transcode_container);
|
||||||
|
|
||||||
var video_decision = '';
|
var video_decision = '';
|
||||||
if (['movie', 'episode', 'clip'].indexOf(s.media_type) > -1 && s.video_decision != '') {
|
if (['movie', 'episode', 'clip'].indexOf(s.media_type) > -1 && s.video_decision !== '') {
|
||||||
|
var v_res= '';
|
||||||
switch (s.video_resolution.toLowerCase()) {
|
switch (s.video_resolution.toLowerCase()) {
|
||||||
case 'sd':
|
case 'sd':
|
||||||
var v_res = 'SD';
|
v_res = 'SD';
|
||||||
break;
|
break;
|
||||||
case '4k':
|
case '4k':
|
||||||
var v_res = '4k';
|
v_res = '4k';
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
var v_res = s.video_resolution + 'p'
|
v_res = s.video_resolution + 'p'
|
||||||
}
|
}
|
||||||
|
var sv_res = '';
|
||||||
switch (s.stream_video_resolution.toLowerCase()) {
|
switch (s.stream_video_resolution.toLowerCase()) {
|
||||||
case 'sd':
|
case 'sd':
|
||||||
var sv_res = 'SD';
|
sv_res = 'SD';
|
||||||
break;
|
break;
|
||||||
case '4k':
|
case '4k':
|
||||||
var sv_res = '4k';
|
sv_res = '4k';
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
var sv_res = s.stream_video_resolution + 'p'
|
sv_res = s.stream_video_resolution + 'p'
|
||||||
}
|
}
|
||||||
if (s.stream_video_decision === 'transcode') {
|
if (s.stream_video_decision === 'transcode') {
|
||||||
var hw_d = '';
|
var hw_d = (s.transcode_hw_decoding === 1) ? ' (HW)' : '';
|
||||||
var hw_e = '';
|
var hw_e = (s.transcode_hw_encoding === 1) ? ' (HW)' : '';
|
||||||
if (s.transcode_hw_requested === 1 && s.transcode_hw_full_pipeline === 0) {
|
|
||||||
hw_d = ' (HW)';
|
|
||||||
} else if (s.transcode_hw_requested === 1 && s.transcode_hw_full_pipeline === 1) {
|
|
||||||
hw_d = ' (HW)';
|
|
||||||
hw_e = ' (HW)';
|
|
||||||
}
|
|
||||||
video_decision = 'Transcode (' + s.video_codec.toUpperCase() + hw_d + ' ' + v_res + ' → ' + s.stream_video_codec.toUpperCase() + hw_e + ' ' + sv_res + ')';
|
video_decision = 'Transcode (' + s.video_codec.toUpperCase() + hw_d + ' ' + v_res + ' → ' + s.stream_video_codec.toUpperCase() + hw_e + ' ' + sv_res + ')';
|
||||||
} else if (s.stream_video_decision === 'copy') {
|
} else if (s.stream_video_decision === 'copy') {
|
||||||
video_decision = 'Direct Stream (' + s.stream_video_codec.toUpperCase() + ' ' + sv_res + ')';
|
video_decision = 'Direct Stream (' + s.stream_video_codec.toUpperCase() + ' ' + sv_res + ')';
|
||||||
@@ -434,7 +431,7 @@
|
|||||||
$('#video_decision-' + key).html(video_decision);
|
$('#video_decision-' + key).html(video_decision);
|
||||||
|
|
||||||
var audio_decision = '';
|
var audio_decision = '';
|
||||||
if (['movie', 'episode', 'clip', 'track'].indexOf(s.media_type) > -1 && s.audio_codec) {
|
if (['movie', 'episode', 'clip', 'track'].indexOf(s.media_type) > -1 && s.audio_decision) {
|
||||||
var a_codec = (s.audio_codec === 'truehd') ? 'TrueHD' : s.audio_codec.toUpperCase();
|
var a_codec = (s.audio_codec === 'truehd') ? 'TrueHD' : s.audio_codec.toUpperCase();
|
||||||
var sa_codec = (s.stream_audio_codec === 'truehd') ? 'TrueHD' : s.stream_audio_codec.toUpperCase();
|
var sa_codec = (s.stream_audio_codec === 'truehd') ? 'TrueHD' : s.stream_audio_codec.toUpperCase();
|
||||||
if (s.stream_audio_decision === 'transcode') {
|
if (s.stream_audio_decision === 'transcode') {
|
||||||
@@ -456,13 +453,13 @@
|
|||||||
} else if (s.stream_subtitle_decision === 'burn') {
|
} else if (s.stream_subtitle_decision === 'burn') {
|
||||||
subtitle_decision = 'Burn (' + s.subtitle_codec.toUpperCase() + ')';
|
subtitle_decision = 'Burn (' + s.subtitle_codec.toUpperCase() + ')';
|
||||||
} else {
|
} else {
|
||||||
subtitle_decision = 'Direct Play (' + ((s.synced_version == '1') ? s.stream_subtitle_codec.toUpperCase() : s.subtitle_codec.toUpperCase()) + ')';
|
subtitle_decision = 'Direct Play (' + ((s.synced_version === '1') ? s.stream_subtitle_codec.toUpperCase() : s.subtitle_codec.toUpperCase()) + ')';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$('#subtitle_decision-' + key).html(subtitle_decision);
|
$('#subtitle_decision-' + key).html(subtitle_decision);
|
||||||
|
|
||||||
// Update the stream quality profile and bandwidth
|
// Update the stream quality profile and bandwidth
|
||||||
if (s.media_type != 'photo' && s.quality_profile != 'Unknown') {
|
if (s.media_type !== 'photo' && s.quality_profile !== 'Unknown') {
|
||||||
var br = parseInt(s.stream_bitrate) || '';
|
var br = parseInt(s.stream_bitrate) || '';
|
||||||
if (br) {
|
if (br) {
|
||||||
if (br > 1000) {
|
if (br > 1000) {
|
||||||
@@ -478,9 +475,9 @@
|
|||||||
$('#optimized_version-' + key).html(s.optimized_version_profile + ' (' + s.optimized_version_title + ')');
|
$('#optimized_version-' + key).html(s.optimized_version_profile + ' (' + s.optimized_version_title + ')');
|
||||||
$('#synced_quality_profile-' + key).html(s.synced_quality_profile);
|
$('#synced_quality_profile-' + key).html(s.synced_quality_profile);
|
||||||
|
|
||||||
if (s.media_type != 'photo' && parseInt(s.bandwidth)) {
|
if (s.media_type !== 'photo' && parseInt(s.bandwidth)) {
|
||||||
var bw = parseInt(s.bandwidth);
|
var bw = parseInt(s.bandwidth);
|
||||||
if (bw != "Unknown") {
|
if (bw !== "Unknown") {
|
||||||
if (bw > 1000) {
|
if (bw > 1000) {
|
||||||
bw = (bw / 1000).toFixed(1) + ' Mbps';
|
bw = (bw / 1000).toFixed(1) + ' Mbps';
|
||||||
} else {
|
} else {
|
||||||
@@ -492,17 +489,19 @@
|
|||||||
|
|
||||||
// Update the stream progress times
|
// Update the stream progress times
|
||||||
$('#stream-eta-' + key).html(moment().add(parseInt(s.duration) - parseInt(s.view_offset), 'milliseconds').format(time_format));
|
$('#stream-eta-' + key).html(moment().add(parseInt(s.duration) - parseInt(s.view_offset), 'milliseconds').format(time_format));
|
||||||
$('#stream-view-offset-' + key).data('state', s.state);
|
var stream_view_offset = $('#stream-view-offset-' + key);
|
||||||
if ($('#stream-view-offset-' + key).data('last_view_offset') != s.view_offset) {
|
stream_view_offset.data('state', s.state);
|
||||||
$('#stream-view-offset-' + key).data('last_view_offset', s.view_offset).data('view_offset', s.view_offset);
|
if (stream_view_offset.data('last_view_offset') !== s.view_offset) {
|
||||||
|
stream_view_offset.data('last_view_offset', s.view_offset).data('view_offset', s.view_offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update the progress bars, percent - 3 because of 3px padding-right
|
// Update the progress bars, percent - 3 because of 3px padding-right
|
||||||
$('#buffer-bar-' + key).width(parseInt(s.transcode_progress) - 3 + '%').html(s.transcode_progress + '%')
|
$('#buffer-bar-' + key).width(parseInt(s.transcode_progress) - 3 + '%').html(s.transcode_progress + '%')
|
||||||
.attr('data-original-title', 'Transcoder Progress ' + s.transcode_progress + '%');
|
.attr('data-original-title', 'Transcoder Progress ' + s.transcode_progress + '%');
|
||||||
$('#progress-bar-' + key).data('state', s.state);
|
var progress_bar = $('#progress-bar-' + key);
|
||||||
if ($('#progress-bar-' + key).data('last_view_offset') != s.view_offset) {
|
progress_bar.data('state', s.state);
|
||||||
$('#progress-bar-' + key).data('last_view_offset', s.view_offset).data('view_offset', s.view_offset);
|
if (progress_bar.data('last_view_offset') !== s.view_offset) {
|
||||||
|
progress_bar.data('last_view_offset', s.view_offset).data('view_offset', s.view_offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add temporary class so we know which instances are still active
|
// Add temporary class so we know which instances are still active
|
||||||
@@ -771,13 +770,13 @@
|
|||||||
leftTotal = Math.max(Math.min(leftTotal + scrollAmount, 0), leftMax);
|
leftTotal = Math.max(Math.min(leftTotal + scrollAmount, 0), leftMax);
|
||||||
scroller.animate({ left: leftTotal }, 250);
|
scroller.animate({ left: leftTotal }, 250);
|
||||||
|
|
||||||
if (leftTotal == 0) {
|
if (leftTotal === 0) {
|
||||||
$("#recently-added-page-left").addClass("disabled").blur();
|
$("#recently-added-page-left").addClass("disabled").blur();
|
||||||
} else {
|
} else {
|
||||||
$("#recently-added-page-left").removeClass("disabled");
|
$("#recently-added-page-left").removeClass("disabled");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (leftTotal == leftMax) {
|
if (leftTotal === leftMax) {
|
||||||
$("#recently-added-page-right").addClass("disabled").blur();
|
$("#recently-added-page-right").addClass("disabled").blur();
|
||||||
} else {
|
} else {
|
||||||
$("#recently-added-page-right").removeClass("disabled");
|
$("#recently-added-page-right").removeClass("disabled");
|
||||||
|
@@ -38,20 +38,21 @@ DOCUMENTATION :: END
|
|||||||
<%!
|
<%!
|
||||||
import re
|
import re
|
||||||
|
|
||||||
from plexpy import common, notifiers
|
from plexpy import notifiers
|
||||||
|
from plexpy.common import MEDIA_TYPE_HEADERS, MEDIA_FLAGS_AUDIO, MEDIA_FLAGS_VIDEO
|
||||||
|
|
||||||
# Get audio codec file
|
# Get audio codec file
|
||||||
def af(codec):
|
def af(codec):
|
||||||
for pattern, file in common.MEDIA_FLAGS_AUDIO.iteritems():
|
for pattern, file_type in MEDIA_FLAGS_AUDIO.iteritems():
|
||||||
if re.match(pattern, codec):
|
if re.match(pattern, codec):
|
||||||
return file
|
return file_type
|
||||||
return codec
|
return codec
|
||||||
|
|
||||||
# Get audio codec file
|
# Get audio codec file
|
||||||
def vf(codec):
|
def vf(codec):
|
||||||
for pattern, file in common.MEDIA_FLAGS_VIDEO.iteritems():
|
for pattern, file_type in MEDIA_FLAGS_VIDEO.iteritems():
|
||||||
if re.match(pattern, codec):
|
if re.match(pattern, codec):
|
||||||
return file
|
return file_type
|
||||||
return codec
|
return codec
|
||||||
|
|
||||||
def br(text):
|
def br(text):
|
||||||
@@ -356,7 +357,7 @@ DOCUMENTATION :: END
|
|||||||
<div class="col-md-12">
|
<div class="col-md-12">
|
||||||
<div class="table-card-header">
|
<div class="table-card-header">
|
||||||
<div class="header-bar">
|
<div class="header-bar">
|
||||||
<span>Movies in <strong>${data['title']}</strong> collection</span>
|
<span>${MEDIA_TYPE_HEADERS[data['sub_media_type']]} in <strong>${data['title']}</strong> collection</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="table-card-back">
|
<div class="table-card-back">
|
||||||
|
@@ -28,22 +28,15 @@ DOCUMENTATION :: END
|
|||||||
|
|
||||||
% if data != None:
|
% if data != None:
|
||||||
<%
|
<%
|
||||||
|
from plexpy.common import MEDIA_TYPE_HEADERS
|
||||||
types = ('movie', 'show', 'artist', 'album')
|
types = ('movie', 'show', 'artist', 'album')
|
||||||
headers = {'movie': 'Movies',
|
|
||||||
'show': 'TV Shows',
|
|
||||||
'season': 'Seasons',
|
|
||||||
'episode': 'Episodes',
|
|
||||||
'artist': 'Artists',
|
|
||||||
'album': 'Albums',
|
|
||||||
'track': 'Tracks',
|
|
||||||
}
|
|
||||||
%>
|
%>
|
||||||
% for media_type in types:
|
% for media_type in types:
|
||||||
% if data['results_list'][media_type]:
|
% if data['results_list'][media_type]:
|
||||||
<div class="col-md-12">
|
<div class="col-md-12">
|
||||||
<div class="table-card-header">
|
<div class="table-card-header">
|
||||||
<div class="header-bar">
|
<div class="header-bar">
|
||||||
<span>${headers[media_type]} in <strong>${title}</strong> collection</span>
|
<span>${MEDIA_TYPE_HEADERS[media_type]} in <strong>${title}</strong> collection</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="table-card-back">
|
<div class="table-card-back">
|
||||||
|
@@ -28,9 +28,7 @@ libraries_list_table_options = {
|
|||||||
$(td).html('<div class="edit-library-toggles">' +
|
$(td).html('<div class="edit-library-toggles">' +
|
||||||
'<button class="btn btn-xs btn-warning delete-library" data-id="' + rowData['section_id'] + '" data-toggle="button"><i class="fa fa-trash-o fa-fw"></i> Delete</button> ' +
|
'<button class="btn btn-xs btn-warning delete-library" data-id="' + rowData['section_id'] + '" data-toggle="button"><i class="fa fa-trash-o fa-fw"></i> Delete</button> ' +
|
||||||
'<button class="btn btn-xs btn-warning purge-library" data-id="' + rowData['section_id'] + '" data-toggle="button"><i class="fa fa-eraser fa-fw"></i> Purge</button>   ' +
|
'<button class="btn btn-xs btn-warning purge-library" data-id="' + rowData['section_id'] + '" data-toggle="button"><i class="fa fa-eraser fa-fw"></i> Purge</button>   ' +
|
||||||
'<input type="checkbox" id="do_notify-' + rowData['section_id'] + '" name="do_notify" value="1" ' + rowData['do_notify'] + '><label class="edit-tooltip" for="do_notify-' + rowData['section_id'] + '" data-toggle="tooltip" title="Toggle Notifications"><i class="fa fa-bell fa-lg fa-fw"></i></label> ' +
|
|
||||||
'<input type="checkbox" id="keep_history-' + rowData['section_id'] + '" name="keep_history" value="1" ' + rowData['keep_history'] + '><label class="edit-tooltip" for="keep_history-' + rowData['section_id'] + '" data-toggle="tooltip" title="Toggle History"><i class="fa fa-history fa-lg fa-fw"></i></label> ' +
|
'<input type="checkbox" id="keep_history-' + rowData['section_id'] + '" name="keep_history" value="1" ' + rowData['keep_history'] + '><label class="edit-tooltip" for="keep_history-' + rowData['section_id'] + '" data-toggle="tooltip" title="Toggle History"><i class="fa fa-history fa-lg fa-fw"></i></label> ' +
|
||||||
'<input type="checkbox" id="do_notify_created-' + rowData['section_id'] + '" name="do_notify_created" value="1" ' + rowData['do_notify_created'] + '><label class="edit-tooltip" for="do_notify_created-' + rowData['section_id'] + '" data-toggle="tooltip" title="Toggle Recently Added"><i class="fa fa-download fa-lg fa-fw"></i></label> ' +
|
|
||||||
'</div>');
|
'</div>');
|
||||||
},
|
},
|
||||||
"width": "7%",
|
"width": "7%",
|
||||||
@@ -258,15 +256,7 @@ $('#libraries_list_table').on('change', 'td.edit-control > .edit-library-toggles
|
|||||||
var row = libraries_list_table.row(tr);
|
var row = libraries_list_table.row(tr);
|
||||||
var rowData = row.data();
|
var rowData = row.data();
|
||||||
|
|
||||||
var do_notify = 0;
|
|
||||||
var do_notify_created = 0;
|
|
||||||
var keep_history = 0;
|
var keep_history = 0;
|
||||||
if ($('#do_notify-' + rowData['section_id']).is(':checked')) {
|
|
||||||
do_notify = 1;
|
|
||||||
}
|
|
||||||
if ($('#do_notify_created-' + rowData['section_id']).is(':checked')) {
|
|
||||||
do_notify_created = 1;
|
|
||||||
}
|
|
||||||
if ($('#keep_history-' + rowData['section_id']).is(':checked')) {
|
if ($('#keep_history-' + rowData['section_id']).is(':checked')) {
|
||||||
keep_history = 1;
|
keep_history = 1;
|
||||||
}
|
}
|
||||||
@@ -280,8 +270,6 @@ $('#libraries_list_table').on('change', 'td.edit-control > .edit-library-toggles
|
|||||||
url: 'edit_library',
|
url: 'edit_library',
|
||||||
data: {
|
data: {
|
||||||
section_id: rowData['section_id'],
|
section_id: rowData['section_id'],
|
||||||
do_notify: do_notify,
|
|
||||||
do_notify_created: do_notify_created,
|
|
||||||
keep_history: keep_history,
|
keep_history: keep_history,
|
||||||
custom_thumb: custom_thumb
|
custom_thumb: custom_thumb
|
||||||
},
|
},
|
||||||
|
@@ -45,7 +45,6 @@ users_list_table_options = {
|
|||||||
$(td).html('<div class="edit-user-toggles">' +
|
$(td).html('<div class="edit-user-toggles">' +
|
||||||
'<button class="btn btn-xs btn-warning delete-user" data-id="' + rowData['user_id'] + '" data-toggle="button"><i class="fa fa-trash-o fa-fw"></i> Delete</button> ' +
|
'<button class="btn btn-xs btn-warning delete-user" data-id="' + rowData['user_id'] + '" data-toggle="button"><i class="fa fa-trash-o fa-fw"></i> Delete</button> ' +
|
||||||
'<button class="btn btn-xs btn-warning purge-user" data-id="' + rowData['user_id'] + '" data-toggle="button"><i class="fa fa-eraser fa-fw"></i> Purge</button>   ' +
|
'<button class="btn btn-xs btn-warning purge-user" data-id="' + rowData['user_id'] + '" data-toggle="button"><i class="fa fa-eraser fa-fw"></i> Purge</button>   ' +
|
||||||
'<input type="checkbox" id="do_notify-' + rowData['user_id'] + '" name="do_notify" value="1" ' + rowData['do_notify'] + '><label class="edit-tooltip" for="do_notify-' + rowData['user_id'] + '" data-toggle="tooltip" title="Toggle Notifications"><i class="fa fa-bell fa-lg fa-fw"></i></label> ' +
|
|
||||||
'<input type="checkbox" id="keep_history-' + rowData['user_id'] + '" name="keep_history" value="1" ' + rowData['keep_history'] + '><label class="edit-tooltip" for="keep_history-' + rowData['user_id'] + '" data-toggle="tooltip" title="Toggle History"><i class="fa fa-history fa-lg fa-fw"></i></label> ' +
|
'<input type="checkbox" id="keep_history-' + rowData['user_id'] + '" name="keep_history" value="1" ' + rowData['keep_history'] + '><label class="edit-tooltip" for="keep_history-' + rowData['user_id'] + '" data-toggle="tooltip" title="Toggle History"><i class="fa fa-history fa-lg fa-fw"></i></label> ' +
|
||||||
'<input type="checkbox" id="allow_guest-' + rowData['user_id'] + '" name="allow_guest" value="1" ' + rowData['allow_guest'] + '><label class="edit-tooltip" for="allow_guest-' + rowData['user_id'] + '" data-toggle="tooltip" title="Toggle Guest Access"><i class="fa fa-unlock-alt fa-lg fa-fw"></i></label> ' +
|
'<input type="checkbox" id="allow_guest-' + rowData['user_id'] + '" name="allow_guest" value="1" ' + rowData['allow_guest'] + '><label class="edit-tooltip" for="allow_guest-' + rowData['user_id'] + '" data-toggle="tooltip" title="Toggle Guest Access"><i class="fa fa-unlock-alt fa-lg fa-fw"></i></label> ' +
|
||||||
'</div>');
|
'</div>');
|
||||||
@@ -284,12 +283,8 @@ $('#users_list_table').on('change', 'td.edit-control > .edit-user-toggles > inpu
|
|||||||
var row = users_list_table.row(tr);
|
var row = users_list_table.row(tr);
|
||||||
var rowData = row.data();
|
var rowData = row.data();
|
||||||
|
|
||||||
var do_notify = 0;
|
|
||||||
var keep_history = 0;
|
var keep_history = 0;
|
||||||
var allow_guest = 0;
|
var allow_guest = 0;
|
||||||
if ($('#do_notify-' + rowData['user_id']).is(':checked')) {
|
|
||||||
do_notify = 1;
|
|
||||||
}
|
|
||||||
if ($('#keep_history-' + rowData['user_id']).is(':checked')) {
|
if ($('#keep_history-' + rowData['user_id']).is(':checked')) {
|
||||||
keep_history = 1;
|
keep_history = 1;
|
||||||
}
|
}
|
||||||
@@ -304,7 +299,6 @@ $('#users_list_table').on('change', 'td.edit-control > .edit-user-toggles > inpu
|
|||||||
data: {
|
data: {
|
||||||
user_id: rowData['user_id'],
|
user_id: rowData['user_id'],
|
||||||
friendly_name: friendly_name,
|
friendly_name: friendly_name,
|
||||||
do_notify: do_notify,
|
|
||||||
keep_history: keep_history,
|
keep_history: keep_history,
|
||||||
allow_guest: allow_guest,
|
allow_guest: allow_guest,
|
||||||
thumb: rowData['user_thumb']
|
thumb: rowData['user_thumb']
|
||||||
|
@@ -63,7 +63,7 @@ DOCUMENTATION :: END
|
|||||||
<h3 class="text-muted"> </h3>
|
<h3 class="text-muted"> </h3>
|
||||||
</div>
|
</div>
|
||||||
% elif item['media_type'] == 'show':
|
% elif item['media_type'] == 'show':
|
||||||
<a href="info?rating_key=${item['rating_key']}" title="${item['parent_title']}">
|
<a href="info?rating_key=${item['rating_key']}" title="${item['title']}">
|
||||||
<div class="dashboard-recent-media-poster">
|
<div class="dashboard-recent-media-poster">
|
||||||
<div class="dashboard-recent-media-poster-face" style="background-image: url(pms_image_proxy?img=${item['thumb']}&width=300&height=450&fallback=poster);">
|
<div class="dashboard-recent-media-poster-face" style="background-image: url(pms_image_proxy?img=${item['thumb']}&width=300&height=450&fallback=poster);">
|
||||||
<div class="dashboard-recent-media-overlay">
|
<div class="dashboard-recent-media-overlay">
|
||||||
|
@@ -918,7 +918,7 @@
|
|||||||
|
|
||||||
<div class="checkbox">
|
<div class="checkbox">
|
||||||
<label>
|
<label>
|
||||||
<input type="checkbox" id="get_file_sizes" name="get_file_sizes" value="1" ${config['get_file_sizes']}> Calculate Total File Sizes <span style="color: #eb8600; padding-left: 10px;">[experimental]</span>
|
<input type="checkbox" id="get_file_sizes" name="get_file_sizes" value="1" ${config['get_file_sizes']}> Calculate Total File Sizes
|
||||||
</label>
|
</label>
|
||||||
<p class="help-block">Enable if you want Tautulli to calculate the total file size for TV Shows/Seasons and Artists/Albums on the media info tables.</p>
|
<p class="help-block">Enable if you want Tautulli to calculate the total file size for TV Shows/Seasons and Artists/Albums on the media info tables.</p>
|
||||||
</div>
|
</div>
|
||||||
|
@@ -1189,6 +1189,27 @@ def dbcheck():
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
# Upgrade session_history_media_info table from earlier versions
|
||||||
|
try:
|
||||||
|
result = c_db.execute('SELECT stream_container FROM session_history_media_info '
|
||||||
|
'WHERE stream_container IS NULL').fetchall()
|
||||||
|
if len(result) > 0:
|
||||||
|
logger.debug(u"Altering database. Removing NULL values from session_history_media_info table.")
|
||||||
|
c_db.execute(
|
||||||
|
'UPDATE session_history_media_info SET stream_container = "" WHERE stream_container IS NULL '
|
||||||
|
)
|
||||||
|
c_db.execute(
|
||||||
|
'UPDATE session_history_media_info SET stream_video_codec = "" WHERE stream_video_codec IS NULL '
|
||||||
|
)
|
||||||
|
c_db.execute(
|
||||||
|
'UPDATE session_history_media_info SET stream_audio_codec = "" WHERE stream_audio_codec IS NULL '
|
||||||
|
)
|
||||||
|
c_db.execute(
|
||||||
|
'UPDATE session_history_media_info SET stream_subtitle_codec = "" WHERE stream_subtitle_codec IS NULL '
|
||||||
|
)
|
||||||
|
except sqlite3.OperationalError:
|
||||||
|
logger.warn(u"Unable to remove NULL values from session_history_media_info table.")
|
||||||
|
|
||||||
# Upgrade users table from earlier versions
|
# Upgrade users table from earlier versions
|
||||||
try:
|
try:
|
||||||
c_db.execute('SELECT do_notify FROM users')
|
c_db.execute('SELECT do_notify FROM users')
|
||||||
@@ -1370,8 +1391,8 @@ def dbcheck():
|
|||||||
|
|
||||||
# Upgrade library_sections table from earlier versions (remove duplicated libraries)
|
# Upgrade library_sections table from earlier versions (remove duplicated libraries)
|
||||||
try:
|
try:
|
||||||
result = c_db.execute('SELECT * FROM library_sections WHERE server_id = ""')
|
result = c_db.execute('SELECT * FROM library_sections WHERE server_id = ""').fetchall()
|
||||||
if result.rowcount > 0:
|
if len(result) > 0:
|
||||||
logger.debug(u"Altering database. Removing duplicate libraries from library_sections table.")
|
logger.debug(u"Altering database. Removing duplicate libraries from library_sections table.")
|
||||||
c_db.execute(
|
c_db.execute(
|
||||||
'DELETE FROM library_sections WHERE server_id = ""'
|
'DELETE FROM library_sections WHERE server_id = ""'
|
||||||
|
278
plexpy/common.py
278
plexpy/common.py
@@ -32,133 +32,176 @@ DEFAULT_POSTER_THUMB = "interfaces/default/images/poster.png"
|
|||||||
DEFAULT_COVER_THUMB = "interfaces/default/images/cover.png"
|
DEFAULT_COVER_THUMB = "interfaces/default/images/cover.png"
|
||||||
DEFAULT_ART = "interfaces/default/images/art.png"
|
DEFAULT_ART = "interfaces/default/images/art.png"
|
||||||
|
|
||||||
PLATFORM_NAME_OVERRIDES = {'Konvergo': 'Plex Media Player',
|
MEDIA_TYPE_HEADERS = {
|
||||||
'Mystery 3': 'Playstation 3',
|
'movie': 'Movies',
|
||||||
'Mystery 4': 'Playstation 4',
|
'show': 'TV Shows',
|
||||||
'Mystery 5': 'Xbox 360',
|
'season': 'Seasons',
|
||||||
'WebMAF': 'Playstation 4'
|
'episode': 'Episodes',
|
||||||
}
|
'artist': 'Artists',
|
||||||
|
'album': 'Albums',
|
||||||
|
'track': 'Tracks',
|
||||||
|
}
|
||||||
|
|
||||||
PMS_PLATFORM_NAME_OVERRIDES = {'MacOSX': 'Mac'
|
PLATFORM_NAME_OVERRIDES = {
|
||||||
}
|
'Konvergo': 'Plex Media Player',
|
||||||
|
'Mystery 3': 'Playstation 3',
|
||||||
|
'Mystery 4': 'Playstation 4',
|
||||||
|
'Mystery 5': 'Xbox 360',
|
||||||
|
'WebMAF': 'Playstation 4'
|
||||||
|
}
|
||||||
|
|
||||||
PLATFORM_NAMES = {'android': 'android',
|
PMS_PLATFORM_NAME_OVERRIDES = {
|
||||||
'apple tv': 'atv',
|
'MacOSX': 'Mac'
|
||||||
'chrome': 'chrome',
|
}
|
||||||
'chromecast': 'chromecast',
|
|
||||||
'dlna': 'dlna',
|
PLATFORM_NAMES = {
|
||||||
'firefox': 'firefox',
|
'android': 'android',
|
||||||
'internet explorer': 'ie',
|
'apple tv': 'atv',
|
||||||
'ios': 'ios',
|
'chrome': 'chrome',
|
||||||
'ipad': 'ios',
|
'chromecast': 'chromecast',
|
||||||
'iphone': 'ios',
|
'dlna': 'dlna',
|
||||||
'kodi': 'kodi',
|
'firefox': 'firefox',
|
||||||
'linux': 'linux',
|
'internet explorer': 'ie',
|
||||||
'nexus': 'android',
|
'ios': 'ios',
|
||||||
'macos': 'macos',
|
'ipad': 'ios',
|
||||||
'microsoft edge': 'msedge',
|
'iphone': 'ios',
|
||||||
'opera': 'opera',
|
'kodi': 'kodi',
|
||||||
'osx': 'macos',
|
'linux': 'linux',
|
||||||
'playstation': 'playstation',
|
'nexus': 'android',
|
||||||
'plex home theater': 'plex',
|
'macos': 'macos',
|
||||||
'plex media player': 'plex',
|
'microsoft edge': 'msedge',
|
||||||
'plexamp': 'plexamp',
|
'opera': 'opera',
|
||||||
'plextogether': 'synclounge',
|
'osx': 'macos',
|
||||||
'roku': 'roku',
|
'playstation': 'playstation',
|
||||||
'safari': 'safari',
|
'plex home theater': 'plex',
|
||||||
'samsung': 'samsung',
|
'plex media player': 'plex',
|
||||||
'synclounge': 'synclounge',
|
'plexamp': 'plexamp',
|
||||||
'tivo': 'tivo',
|
'plextogether': 'synclounge',
|
||||||
'tvos': 'atv',
|
'roku': 'roku',
|
||||||
'vizio': 'opera',
|
'safari': 'safari',
|
||||||
'wiiu': 'wiiu',
|
'samsung': 'samsung',
|
||||||
'windows': 'windows',
|
'synclounge': 'synclounge',
|
||||||
'windows phone': 'wp',
|
'tivo': 'tivo',
|
||||||
'xbmc': 'xbmc',
|
'tvos': 'atv',
|
||||||
'xbox': 'xbox'
|
'vizio': 'opera',
|
||||||
}
|
'wiiu': 'wiiu',
|
||||||
|
'windows': 'windows',
|
||||||
|
'windows phone': 'wp',
|
||||||
|
'xbmc': 'xbmc',
|
||||||
|
'xbox': 'xbox'
|
||||||
|
}
|
||||||
PLATFORM_NAMES = OrderedDict(sorted(PLATFORM_NAMES.items(), key=lambda k: k[0], reverse=True))
|
PLATFORM_NAMES = OrderedDict(sorted(PLATFORM_NAMES.items(), key=lambda k: k[0], reverse=True))
|
||||||
|
|
||||||
MEDIA_FLAGS_AUDIO = {'ac.?3': 'dolby_digital',
|
MEDIA_FLAGS_AUDIO = {
|
||||||
'truehd': 'dolby_truehd',
|
'ac.?3': 'dolby_digital',
|
||||||
'(dca|dta)': 'dts',
|
'truehd': 'dolby_truehd',
|
||||||
'dts(hd_|-hd|-)?ma': 'dca-ma',
|
'(dca|dta)': 'dts',
|
||||||
'vorbis': 'ogg'
|
'dts(hd_|-hd|-)?ma': 'dca-ma',
|
||||||
}
|
'vorbis': 'ogg'
|
||||||
MEDIA_FLAGS_VIDEO = {'avc1': 'h264',
|
}
|
||||||
'wmv(1|2)': 'wmv',
|
MEDIA_FLAGS_VIDEO = {
|
||||||
'wmv3': 'wmvhd'
|
'avc1': 'h264',
|
||||||
}
|
'wmv(1|2)': 'wmv',
|
||||||
|
'wmv3': 'wmvhd'
|
||||||
|
}
|
||||||
|
|
||||||
AUDIO_CODEC_OVERRIDES = {'truehd': 'TrueHD'}
|
AUDIO_CODEC_OVERRIDES = {
|
||||||
|
'truehd': 'TrueHD'
|
||||||
|
}
|
||||||
|
|
||||||
VIDEO_RESOLUTION_OVERRIDES = {'sd': 'SD',
|
VIDEO_RESOLUTION_OVERRIDES = {
|
||||||
'480': '480p',
|
'sd': 'SD',
|
||||||
'540': '540p',
|
'480': '480p',
|
||||||
'576': '576p',
|
'540': '540p',
|
||||||
'720': '720p',
|
'576': '576p',
|
||||||
'1080': '1080p',
|
'720': '720p',
|
||||||
'4k': '4k'
|
'1080': '1080p',
|
||||||
}
|
'4k': '4k'
|
||||||
|
}
|
||||||
|
|
||||||
AUDIO_CHANNELS = {'1': 'Mono',
|
AUDIO_CHANNELS = {
|
||||||
'2': 'Stereo',
|
'1': 'Mono',
|
||||||
'3': '2.1',
|
'2': 'Stereo',
|
||||||
'4': '3.1',
|
'3': '2.1',
|
||||||
'6': '5.1',
|
'4': '3.1',
|
||||||
'7': '6.1',
|
'6': '5.1',
|
||||||
'8': '7.1'
|
'7': '6.1',
|
||||||
}
|
'8': '7.1'
|
||||||
|
}
|
||||||
|
|
||||||
VIDEO_QUALITY_PROFILES = {20000: '20 Mbps 1080p',
|
VIDEO_QUALITY_PROFILES = {
|
||||||
12000: '12 Mbps 1080p',
|
20000: '20 Mbps 1080p',
|
||||||
10000: '10 Mbps 1080p',
|
12000: '12 Mbps 1080p',
|
||||||
8000: '8 Mbps 1080p',
|
10000: '10 Mbps 1080p',
|
||||||
4000: '4 Mbps 720p',
|
8000: '8 Mbps 1080p',
|
||||||
3000: '3 Mbps 720p',
|
4000: '4 Mbps 720p',
|
||||||
2000: '2 Mbps 720p',
|
3000: '3 Mbps 720p',
|
||||||
1500: '1.5 Mbps 480p',
|
2000: '2 Mbps 720p',
|
||||||
720: '0.7 Mbps 328p',
|
1500: '1.5 Mbps 480p',
|
||||||
320: '0.3 Mbps 240p',
|
720: '0.7 Mbps 328p',
|
||||||
208: '0.2 Mbps 160p',
|
320: '0.3 Mbps 240p',
|
||||||
96: '0.096 Mbps',
|
208: '0.2 Mbps 160p',
|
||||||
64: '0.064 Mbps'
|
96: '0.096 Mbps',
|
||||||
}
|
64: '0.064 Mbps'
|
||||||
|
}
|
||||||
VIDEO_QUALITY_PROFILES = OrderedDict(sorted(VIDEO_QUALITY_PROFILES.items(), key=lambda k: k[0], reverse=True))
|
VIDEO_QUALITY_PROFILES = OrderedDict(sorted(VIDEO_QUALITY_PROFILES.items(), key=lambda k: k[0], reverse=True))
|
||||||
|
|
||||||
AUDIO_QUALITY_PROFILES = {512: '512 kbps',
|
AUDIO_QUALITY_PROFILES = {
|
||||||
320: '320 kbps',
|
512: '512 kbps',
|
||||||
256: '256 kbps',
|
320: '320 kbps',
|
||||||
192: '192 kbps',
|
256: '256 kbps',
|
||||||
128: '128 kbps',
|
192: '192 kbps',
|
||||||
96: '96 kbps'
|
128: '128 kbps',
|
||||||
}
|
96: '96 kbps'
|
||||||
|
}
|
||||||
AUDIO_QUALITY_PROFILES = OrderedDict(sorted(AUDIO_QUALITY_PROFILES.items(), key=lambda k: k[0], reverse=True))
|
AUDIO_QUALITY_PROFILES = OrderedDict(sorted(AUDIO_QUALITY_PROFILES.items(), key=lambda k: k[0], reverse=True))
|
||||||
|
|
||||||
HW_DECODERS = ['dxva2', 'videotoolbox', 'mediacodecndk', 'vaapi']
|
HW_DECODERS = [
|
||||||
HW_ENCODERS = ['qsv', 'nvenc', 'mf', 'videotoolbox', 'mediacodecndk', 'vaapi', 'nvenc']
|
'dxva2',
|
||||||
|
'videotoolbox',
|
||||||
|
'mediacodecndk',
|
||||||
|
'vaapi'
|
||||||
|
]
|
||||||
|
HW_ENCODERS = [
|
||||||
|
'qsv',
|
||||||
|
'nvenc',
|
||||||
|
'mf',
|
||||||
|
'videotoolbox',
|
||||||
|
'mediacodecndk',
|
||||||
|
'vaapi',
|
||||||
|
'nvenc'
|
||||||
|
]
|
||||||
|
|
||||||
SCHEDULER_LIST = ['Check GitHub for updates',
|
SCHEDULER_LIST = [
|
||||||
'Check for active sessions',
|
'Check GitHub for updates',
|
||||||
'Check for recently added items',
|
'Check for active sessions',
|
||||||
'Check for Plex updates',
|
'Check for recently added items',
|
||||||
'Check for Plex remote access',
|
'Check for Plex updates',
|
||||||
'Check server response',
|
'Check for Plex remote access',
|
||||||
'Refresh users list',
|
'Check server response',
|
||||||
'Refresh libraries list',
|
'Refresh users list',
|
||||||
'Refresh Plex server URLs',
|
'Refresh libraries list',
|
||||||
'Backup Tautulli database',
|
'Refresh Plex server URLs',
|
||||||
'Backup Tautulli config'
|
'Backup Tautulli database',
|
||||||
]
|
'Backup Tautulli config'
|
||||||
|
]
|
||||||
|
|
||||||
DATE_TIME_FORMATS = [
|
DATE_TIME_FORMATS = [
|
||||||
{
|
{
|
||||||
'category': 'Year',
|
'category': 'Year',
|
||||||
|
'parameters': [
|
||||||
|
{'value': 'YYYY', 'description': 'Numeric, four digits', 'example': '1999, 2003'},
|
||||||
|
{'value': 'YY', 'description': 'Numeric, two digits', 'example': '99, 03'}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'category': 'Month',
|
||||||
'parameters': [
|
'parameters': [
|
||||||
{'value': 'MMMM', 'description': 'Textual, full', 'example': 'January-December'},
|
{'value': 'MMMM', 'description': 'Textual, full', 'example': 'January-December'},
|
||||||
{'value': 'MMM', 'description': 'Textual, three letters', 'example': 'Jan-Dec'},
|
{'value': 'MMM', 'description': 'Textual, three letters', 'example': 'Jan-Dec'},
|
||||||
{'value': 'MM', 'description': 'Numeric, with leading zeros', 'example': '42747'},
|
{'value': 'MM', 'description': 'Numeric, with leading zeros', 'example': '01-12'},
|
||||||
{'value': 'M', 'description': 'Numeric, without leading zeros', 'example': '42747'},
|
{'value': 'M', 'description': 'Numeric, without leading zeros', 'example': '1-12'},
|
||||||
|
{'value': 'Mo', 'description': 'Numeric, with suffix', 'example': '1st, 2nd ... 12th'},
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -166,14 +209,15 @@ DATE_TIME_FORMATS = [
|
|||||||
'parameters': [
|
'parameters': [
|
||||||
{'value': 'DDDD', 'description': 'Numeric, with leading zeros', 'example': '001-365'},
|
{'value': 'DDDD', 'description': 'Numeric, with leading zeros', 'example': '001-365'},
|
||||||
{'value': 'DDD', 'description': 'Numeric, without leading zeros', 'example': '1-365'},
|
{'value': 'DDD', 'description': 'Numeric, without leading zeros', 'example': '1-365'},
|
||||||
|
{'value': 'DDDo', 'description': 'Numeric, with suffix', 'example': '1st, 2nd, ... 365th'},
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
'category': 'Day of the Month',
|
'category': 'Day of the Month',
|
||||||
'parameters': [
|
'parameters': [
|
||||||
{'value': 'DD', 'description': 'Numeric, with leading zeros', 'example': '42766'},
|
{'value': 'DD', 'description': 'Numeric, with leading zeros', 'example': '01-31'},
|
||||||
{'value': 'D', 'description': 'Numeric, without leading zeros', 'example': '42766'},
|
{'value': 'D', 'description': 'Numeric, without leading zeros', 'example': '1-31'},
|
||||||
{'value': 'Do', 'description': 'Numeric, with suffix', 'example': 'E.g. 1st, 2nd ... 31st.'},
|
{'value': 'Do', 'description': 'Numeric, with suffix', 'example': '1st, 2nd ... 31st'},
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -181,7 +225,9 @@ DATE_TIME_FORMATS = [
|
|||||||
'parameters': [
|
'parameters': [
|
||||||
{'value': 'dddd', 'description': 'Textual, full', 'example': 'Sunday-Saturday'},
|
{'value': 'dddd', 'description': 'Textual, full', 'example': 'Sunday-Saturday'},
|
||||||
{'value': 'ddd', 'description': 'Textual, three letters', 'example': 'Sun-Sat'},
|
{'value': 'ddd', 'description': 'Textual, three letters', 'example': 'Sun-Sat'},
|
||||||
|
{'value': 'dd', 'description': 'Textual, two letters', 'example': 'Su-Sa'},
|
||||||
{'value': 'd', 'description': 'Numeric', 'example': '0-6'},
|
{'value': 'd', 'description': 'Numeric', 'example': '0-6'},
|
||||||
|
{'value': 'do', 'description': 'Numeric, with suffix', 'example': '0th, 1st ... 6th'},
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -189,8 +235,8 @@ DATE_TIME_FORMATS = [
|
|||||||
'parameters': [
|
'parameters': [
|
||||||
{'value': 'HH', 'description': '24-hour, with leading zeros', 'example': '00-23'},
|
{'value': 'HH', 'description': '24-hour, with leading zeros', 'example': '00-23'},
|
||||||
{'value': 'H', 'description': '24-hour, without leading zeros', 'example': '0-23'},
|
{'value': 'H', 'description': '24-hour, without leading zeros', 'example': '0-23'},
|
||||||
{'value': 'hh', 'description': '12-hour, with leading zeros', 'example': '42747'},
|
{'value': 'hh', 'description': '12-hour, with leading zeros', 'example': '01-12'},
|
||||||
{'value': 'h', 'description': '12-hour, without leading zeros', 'example': '42747'},
|
{'value': 'h', 'description': '12-hour, without leading zeros', 'example': '1-12'},
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -217,8 +263,8 @@ DATE_TIME_FORMATS = [
|
|||||||
{
|
{
|
||||||
'category': 'Timezone',
|
'category': 'Timezone',
|
||||||
'parameters': [
|
'parameters': [
|
||||||
{'value': 'ZZ', 'description': 'UTC offset', 'example': 'E.g. +0100, -0700'},
|
{'value': 'ZZ', 'description': 'UTC offset', 'example': '+0100, -0700'},
|
||||||
{'value': 'Z', 'description': 'UTC offset', 'example': 'E.g. +01:00, -07:00'},
|
{'value': 'Z', 'description': 'UTC offset', 'example': '+01:00, -07:00'},
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -227,7 +273,7 @@ DATE_TIME_FORMATS = [
|
|||||||
{'value': 'X', 'description': 'Unix timestamp', 'example': 'E.g. 1456887825'},
|
{'value': 'X', 'description': 'Unix timestamp', 'example': 'E.g. 1456887825'},
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
|
||||||
NOTIFICATION_PARAMETERS = [
|
NOTIFICATION_PARAMETERS = [
|
||||||
{
|
{
|
||||||
@@ -439,4 +485,4 @@ NOTIFICATION_PARAMETERS = [
|
|||||||
{'name': 'Plexpy Update Changelog', 'type': 'int', 'value': 'plexpy_update_changelog', 'description': 'The changelog for the available update.'},
|
{'name': 'Plexpy Update Changelog', 'type': 'int', 'value': 'plexpy_update_changelog', 'description': 'The changelog for the available update.'},
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
@@ -954,6 +954,7 @@ class DataFactory(object):
|
|||||||
'grandparent_title': item['grandparent_title']
|
'grandparent_title': item['grandparent_title']
|
||||||
}
|
}
|
||||||
|
|
||||||
|
stream_output = {k: v or '' for k, v in stream_output.iteritems()}
|
||||||
return stream_output
|
return stream_output
|
||||||
|
|
||||||
def get_metadata_details(self, rating_key):
|
def get_metadata_details(self, rating_key):
|
||||||
|
@@ -131,19 +131,19 @@ def notify_conditions(notify_action=None, stream_data=None, timeline_data=None):
|
|||||||
if stream_data:
|
if stream_data:
|
||||||
|
|
||||||
# Check if notifications enabled for user and library
|
# Check if notifications enabled for user and library
|
||||||
user_data = users.Users()
|
# user_data = users.Users()
|
||||||
user_details = user_data.get_details(user_id=stream_data['user_id'])
|
# user_details = user_data.get_details(user_id=stream_data['user_id'])
|
||||||
|
#
|
||||||
|
# library_data = libraries.Libraries()
|
||||||
|
# library_details = library_data.get_details(section_id=stream_data['section_id'])
|
||||||
|
|
||||||
library_data = libraries.Libraries()
|
# if not user_details['do_notify']:
|
||||||
library_details = library_data.get_details(section_id=stream_data['section_id'])
|
# logger.debug(u"Tautulli NotificationHandler :: Notifications for user '%s' are disabled." % user_details['username'])
|
||||||
|
# return False
|
||||||
if not user_details['do_notify']:
|
#
|
||||||
logger.debug(u"Tautulli NotificationHandler :: Notifications for user '%s' are disabled." % user_details['username'])
|
# elif not library_details['do_notify'] and notify_action not in ('on_concurrent', 'on_newdevice'):
|
||||||
return False
|
# logger.debug(u"Tautulli NotificationHandler :: Notifications for library '%s' are disabled." % library_details['section_name'])
|
||||||
|
# return False
|
||||||
elif not library_details['do_notify'] and notify_action not in ('on_concurrent', 'on_newdevice'):
|
|
||||||
logger.debug(u"Tautulli NotificationHandler :: Notifications for library '%s' are disabled." % library_details['section_name'])
|
|
||||||
return False
|
|
||||||
|
|
||||||
if notify_action == 'on_concurrent':
|
if notify_action == 'on_concurrent':
|
||||||
pms_connect = pmsconnect.PmsConnect()
|
pms_connect = pmsconnect.PmsConnect()
|
||||||
@@ -188,12 +188,12 @@ def notify_conditions(notify_action=None, stream_data=None, timeline_data=None):
|
|||||||
elif timeline_data:
|
elif timeline_data:
|
||||||
|
|
||||||
# Check if notifications enabled for library
|
# Check if notifications enabled for library
|
||||||
library_data = libraries.Libraries()
|
# library_data = libraries.Libraries()
|
||||||
library_details = library_data.get_details(section_id=timeline_data['section_id'])
|
# library_details = library_data.get_details(section_id=timeline_data['section_id'])
|
||||||
|
#
|
||||||
if not library_details['do_notify_created']:
|
# if not library_details['do_notify_created']:
|
||||||
# logger.debug(u"Tautulli NotificationHandler :: Notifications for library '%s' is disabled." % library_details['section_name'])
|
# # logger.debug(u"Tautulli NotificationHandler :: Notifications for library '%s' is disabled." % library_details['section_name'])
|
||||||
return False
|
# return False
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
@@ -451,7 +451,11 @@ def build_media_notify_params(notify_action=None, session=None, timeline=None, m
|
|||||||
|
|
||||||
notify_params = defaultdict(str)
|
notify_params = defaultdict(str)
|
||||||
if session:
|
if session:
|
||||||
|
# Reload json from raw stream info
|
||||||
|
if session.get('raw_stream_info'):
|
||||||
|
session.update(json.loads(session['raw_stream_info']))
|
||||||
notify_params.update(session)
|
notify_params.update(session)
|
||||||
|
|
||||||
if timeline:
|
if timeline:
|
||||||
notify_params.update(timeline)
|
notify_params.update(timeline)
|
||||||
|
|
||||||
|
@@ -1,2 +1,2 @@
|
|||||||
PLEXPY_BRANCH = "beta"
|
PLEXPY_BRANCH = "beta"
|
||||||
PLEXPY_RELEASE_VERSION = "v2.0.9-beta"
|
PLEXPY_RELEASE_VERSION = "v2.0.11-beta"
|
||||||
|
@@ -96,7 +96,8 @@ def check_credentials(username, password, admin_login='0'):
|
|||||||
if plexpy.CONFIG.HTTP_HASHED_PASSWORD and \
|
if plexpy.CONFIG.HTTP_HASHED_PASSWORD and \
|
||||||
username == plexpy.CONFIG.HTTP_USERNAME and check_hash(password, plexpy.CONFIG.HTTP_PASSWORD):
|
username == plexpy.CONFIG.HTTP_USERNAME and check_hash(password, plexpy.CONFIG.HTTP_PASSWORD):
|
||||||
return True, u'admin'
|
return True, u'admin'
|
||||||
elif username == plexpy.CONFIG.HTTP_USERNAME and password == plexpy.CONFIG.HTTP_PASSWORD:
|
elif not plexpy.CONFIG.HTTP_HASHED_PASSWORD and \
|
||||||
|
username == plexpy.CONFIG.HTTP_USERNAME and password == plexpy.CONFIG.HTTP_PASSWORD:
|
||||||
return True, u'admin'
|
return True, u'admin'
|
||||||
elif not admin_login == '1' and plexpy.CONFIG.ALLOW_GUEST_ACCESS and user_login(username, password):
|
elif not admin_login == '1' and plexpy.CONFIG.ALLOW_GUEST_ACCESS and user_login(username, password):
|
||||||
return True, u'guest'
|
return True, u'guest'
|
||||||
|
Reference in New Issue
Block a user