Compare commits
26 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
bc2f73d686 | ||
![]() |
645c2ecef6 | ||
![]() |
4d4a8ca3b2 | ||
![]() |
a98bc45c10 | ||
![]() |
b9d5e49a71 | ||
![]() |
e90390be67 | ||
![]() |
8ef671c9cb | ||
![]() |
8829516cae | ||
![]() |
d8e8dfbd45 | ||
![]() |
0b6d9a4890 | ||
![]() |
55ffd68023 | ||
![]() |
6380de3e6c | ||
![]() |
d6220a921a | ||
![]() |
10e421b9d4 | ||
![]() |
90056bcce2 | ||
![]() |
4740d0fbf3 | ||
![]() |
13374c9ded | ||
![]() |
2a03be1905 | ||
![]() |
c8f132a750 | ||
![]() |
4d0c4bf4f4 | ||
![]() |
e321c5b197 | ||
![]() |
badbfdc4c1 | ||
![]() |
7d71086a41 | ||
![]() |
0e1764755a | ||
![]() |
c31d3ffd6c | ||
![]() |
0cba3988aa |
27
CHANGELOG.md
27
CHANGELOG.md
@@ -1,5 +1,32 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
|
## v2.1.43 (2020-02-03)
|
||||||
|
|
||||||
|
* Monitoring:
|
||||||
|
* New: Added HDR indicator on activity card.
|
||||||
|
* New: Added dynamic range to history steam info modal.
|
||||||
|
* Notifications:
|
||||||
|
* Fix: Webhook notification body sent as incorrect data type when Content-Type header is overridden.
|
||||||
|
* Fix: Telegram notification character limit incorrect for unicode characters.
|
||||||
|
* New: Added color and dynamic range notification parameters.
|
||||||
|
* Newsletters:
|
||||||
|
* Fix: Episodes and Albums plural spelling on recently added newsletter section headers.
|
||||||
|
* UI:
|
||||||
|
* Fix: Windows and macOS platform capitalization.
|
||||||
|
* Fix: Season number 0 not shown for episodes on history tables.
|
||||||
|
* Other:
|
||||||
|
* Change: Mask email addresses in logs.
|
||||||
|
* Change: Update deprecated GitHub access token URL parameter to Authorization header.
|
||||||
|
|
||||||
|
|
||||||
|
## v2.1.42 (2020-01-04)
|
||||||
|
|
||||||
|
* Other:
|
||||||
|
* Fix: SSL certificate error when installing GeoLite2 database.
|
||||||
|
* Change: Verify MaxMind license key and GeoLite2 database path before installing.
|
||||||
|
* Change: Disable GeoLite2 database uninstall button when it is not installed.
|
||||||
|
|
||||||
|
|
||||||
## v2.1.41 (2019-12-30)
|
## v2.1.41 (2019-12-30)
|
||||||
|
|
||||||
* Other:
|
* Other:
|
||||||
|
@@ -106,8 +106,8 @@ def main():
|
|||||||
plexpy.QUIET = True
|
plexpy.QUIET = True
|
||||||
|
|
||||||
# Do an intial setup of the logger.
|
# Do an intial setup of the logger.
|
||||||
logger.initLogger(console=not plexpy.QUIET, log_dir=False,
|
# Require verbose for pre-initilization to see critical errors
|
||||||
verbose=plexpy.VERBOSE)
|
logger.initLogger(console=not plexpy.QUIET, log_dir=False, verbose=True)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
plexpy.SYS_TIMEZONE = tzlocal.get_localzone()
|
plexpy.SYS_TIMEZONE = tzlocal.get_localzone()
|
||||||
|
@@ -226,17 +226,24 @@ DOCUMENTATION :: END
|
|||||||
<li class="dashboard-activity-info-item">
|
<li class="dashboard-activity-info-item">
|
||||||
<div class="sub-heading">Video</div>
|
<div class="sub-heading">Video</div>
|
||||||
<div class="sub-value" id="video_decision-${sk}">
|
<div class="sub-value" id="video_decision-${sk}">
|
||||||
% if data['media_type'] in ('movie', 'episode', 'clip'):
|
% if data['media_type'] in ('movie', 'episode', 'clip') and data['stream_video_decision']:
|
||||||
|
<%
|
||||||
|
if data['video_dynamic_range'] == 'HDR':
|
||||||
|
video_dynamic_range = ' ' + data['video_dynamic_range']
|
||||||
|
stream_video_dynamic_range = ' ' + data['stream_video_dynamic_range']
|
||||||
|
else:
|
||||||
|
video_dynamic_range = stream_video_dynamic_range = ''
|
||||||
|
%>
|
||||||
% if data['stream_video_decision'] == 'transcode':
|
% if data['stream_video_decision'] == 'transcode':
|
||||||
<%
|
<%
|
||||||
hw_d = ' (HW)' if data['transcode_hw_decoding'] else ''
|
hw_d = ' (HW)' if data['transcode_hw_decoding'] else ''
|
||||||
hw_e = ' (HW)' if data['transcode_hw_encoding'] else ''
|
hw_e = ' (HW)' if data['transcode_hw_encoding'] else ''
|
||||||
%>
|
%>
|
||||||
Transcode (${data['video_codec'].upper()}${hw_d} ${data['video_full_resolution']} <i class="fa fa-long-arrow-right"></i> ${data['stream_video_codec'].upper()}${hw_e} ${data['stream_video_full_resolution']})
|
Transcode (${data['video_codec'].upper()}${hw_d} ${data['video_full_resolution']}${video_dynamic_range} <i class="fa fa-long-arrow-right"></i> ${data['stream_video_codec'].upper()}${hw_e} ${data['stream_video_full_resolution']}${stream_video_dynamic_range})
|
||||||
% elif data['stream_video_decision'] == 'copy':
|
% elif data['stream_video_decision'] == 'copy':
|
||||||
Direct Stream (${data['stream_video_codec'].upper()} ${data['stream_video_full_resolution']})
|
Direct Stream (${data['stream_video_codec'].upper()} ${data['stream_video_full_resolution']}${stream_video_dynamic_range})
|
||||||
% else:
|
% else:
|
||||||
Direct Play (${data['stream_video_codec'].upper()} ${data['stream_video_full_resolution']})
|
Direct Play (${data['stream_video_codec'].upper()} ${data['stream_video_full_resolution']}${stream_video_dynamic_range})
|
||||||
% endif
|
% endif
|
||||||
% elif data['media_type'] == 'photo':
|
% elif data['media_type'] == 'photo':
|
||||||
Direct Play (${data['width']}x${data['height']})
|
Direct Play (${data['width']}x${data['height']})
|
||||||
@@ -248,12 +255,14 @@ DOCUMENTATION :: END
|
|||||||
<li class="dashboard-activity-info-item">
|
<li class="dashboard-activity-info-item">
|
||||||
<div class="sub-heading">Audio</div>
|
<div class="sub-heading">Audio</div>
|
||||||
<div class="sub-value" id="audio_decision-${sk}">
|
<div class="sub-value" id="audio_decision-${sk}">
|
||||||
% if data['stream_audio_decision'] == 'transcode':
|
% if data['stream_audio_decision']:
|
||||||
Transcode (${AUDIO_CODEC_OVERRIDES.get(data['audio_codec'], data['audio_codec'].upper())} ${data['audio_channel_layout'].split('(')[0].capitalize()} <i class="fa fa-long-arrow-right"></i> ${AUDIO_CODEC_OVERRIDES.get(data['stream_audio_codec'], data['stream_audio_codec'].upper())} ${data['stream_audio_channel_layout'].split('(')[0].capitalize()})
|
% if data['stream_audio_decision'] == 'transcode':
|
||||||
% elif data['stream_audio_decision'] == 'copy':
|
Transcode (${AUDIO_CODEC_OVERRIDES.get(data['audio_codec'], data['audio_codec'].upper())} ${data['audio_channel_layout'].split('(')[0].capitalize()} <i class="fa fa-long-arrow-right"></i> ${AUDIO_CODEC_OVERRIDES.get(data['stream_audio_codec'], data['stream_audio_codec'].upper())} ${data['stream_audio_channel_layout'].split('(')[0].capitalize()})
|
||||||
Direct Stream (${AUDIO_CODEC_OVERRIDES.get(data['stream_audio_codec'], data['stream_audio_codec'].upper())} ${data['stream_audio_channel_layout'].split('(')[0].capitalize()})
|
% elif data['stream_audio_decision'] == 'copy':
|
||||||
% else:
|
Direct Stream (${AUDIO_CODEC_OVERRIDES.get(data['stream_audio_codec'], data['stream_audio_codec'].upper())} ${data['stream_audio_channel_layout'].split('(')[0].capitalize()})
|
||||||
Direct Play (${AUDIO_CODEC_OVERRIDES.get(data['stream_audio_codec'], data['stream_audio_codec'].upper())} ${data['stream_audio_channel_layout'].split('(')[0].capitalize()})
|
% else:
|
||||||
|
Direct Play (${AUDIO_CODEC_OVERRIDES.get(data['stream_audio_codec'], data['stream_audio_codec'].upper())} ${data['stream_audio_channel_layout'].split('(')[0].capitalize()})
|
||||||
|
% endif
|
||||||
% endif
|
% endif
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
|
@@ -437,6 +437,8 @@
|
|||||||
|
|
||||||
var video_decision = '';
|
var video_decision = '';
|
||||||
if (['movie', 'episode', 'clip'].indexOf(s.media_type) > -1 && s.stream_video_decision) {
|
if (['movie', 'episode', 'clip'].indexOf(s.media_type) > -1 && s.stream_video_decision) {
|
||||||
|
var v_bd = (s.video_dynamic_range === 'HDR') ? ' ' + s.video_dynamic_range : '';
|
||||||
|
var sv_bd = (s.video_dynamic_range === 'HDR') ? ' ' + s.stream_video_dynamic_range : '';
|
||||||
var v_res= '';
|
var v_res= '';
|
||||||
switch (s.video_resolution.toLowerCase()) {
|
switch (s.video_resolution.toLowerCase()) {
|
||||||
case 'sd':
|
case 'sd':
|
||||||
@@ -462,11 +464,11 @@
|
|||||||
if (s.stream_video_decision === 'transcode') {
|
if (s.stream_video_decision === 'transcode') {
|
||||||
var hw_d = (s.transcode_hw_decoding === 1) ? ' (HW)' : '';
|
var hw_d = (s.transcode_hw_decoding === 1) ? ' (HW)' : '';
|
||||||
var hw_e = (s.transcode_hw_encoding === 1) ? ' (HW)' : '';
|
var hw_e = (s.transcode_hw_encoding === 1) ? ' (HW)' : '';
|
||||||
video_decision = 'Transcode (' + s.video_codec.toUpperCase() + hw_d + ' ' + v_res + ' <i class="fa fa-long-arrow-right"></i> ' + s.stream_video_codec.toUpperCase() + hw_e + ' ' + sv_res + ')';
|
video_decision = 'Transcode (' + s.video_codec.toUpperCase() + hw_d + ' ' + v_res + v_bd + ' <i class="fa fa-long-arrow-right"></i> ' + s.stream_video_codec.toUpperCase() + hw_e + ' ' + sv_res + sv_bd + ')';
|
||||||
} 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 + sv_bd + ')';
|
||||||
} else {
|
} else {
|
||||||
video_decision = 'Direct Play (' + s.stream_video_codec.toUpperCase() + ' ' + sv_res + ')';
|
video_decision = 'Direct Play (' + s.stream_video_codec.toUpperCase() + ' ' + sv_res + sv_bd + ')';
|
||||||
}
|
}
|
||||||
} else if (s.media_type === 'photo') {
|
} else if (s.media_type === 'photo') {
|
||||||
video_decision = 'Direct Play (' + s.width + 'x' + s.height + ')';
|
video_decision = 'Direct Play (' + s.width + 'x' + s.height + ')';
|
||||||
|
@@ -166,7 +166,7 @@ history_table_options = {
|
|||||||
thumb_popover = '<span class="thumb-tooltip" data-toggle="popover" data-img="pms_image_proxy?img=' + rowData['thumb'] + '&width=300&height=450&fallback=poster" data-height="120" data-width="80">' + cellData + parent_info + '</span>'
|
thumb_popover = '<span class="thumb-tooltip" data-toggle="popover" data-img="pms_image_proxy?img=' + rowData['thumb'] + '&width=300&height=450&fallback=poster" data-height="120" data-width="80">' + cellData + parent_info + '</span>'
|
||||||
$(td).html('<div class="history-title"><a href="info?' + source + 'rating_key=' + rowData['rating_key'] + '"><div style="float: left;">' + media_type + ' ' + thumb_popover + '</div></a></div>');
|
$(td).html('<div class="history-title"><a href="info?' + source + 'rating_key=' + rowData['rating_key'] + '"><div style="float: left;">' + media_type + ' ' + thumb_popover + '</div></a></div>');
|
||||||
} else if (rowData['media_type'] === 'episode') {
|
} else if (rowData['media_type'] === 'episode') {
|
||||||
if (rowData['parent_media_index'] && rowData['media_index']) { parent_info = ' (S' + rowData['parent_media_index'] + ' · E' + rowData['media_index'] + ')'; }
|
if (!isNaN(parseInt(rowData['parent_media_index'])) && !isNaN(parseInt(rowData['media_index']))) { parent_info = ' (S' + rowData['parent_media_index'] + ' · E' + rowData['media_index'] + ')'; }
|
||||||
media_type = '<span class="media-type-tooltip" data-toggle="tooltip" title="Episode"><i class="fa fa-television fa-fw"></i></span>';
|
media_type = '<span class="media-type-tooltip" data-toggle="tooltip" title="Episode"><i class="fa fa-television fa-fw"></i></span>';
|
||||||
thumb_popover = '<span class="thumb-tooltip" data-toggle="popover" data-img="pms_image_proxy?img=' + rowData['thumb'] + '&width=300&height=450&fallback=poster" data-height="120" data-width="80">' + cellData + parent_info + '</span>'
|
thumb_popover = '<span class="thumb-tooltip" data-toggle="popover" data-img="pms_image_proxy?img=' + rowData['thumb'] + '&width=300&height=450&fallback=poster" data-height="120" data-width="80">' + cellData + parent_info + '</span>'
|
||||||
$(td).html('<div class="history-title"><a href="info?' + source + 'rating_key=' + rowData['rating_key'] + '"><div style="float: left;" >' + media_type + ' ' + thumb_popover + '</div></a></div>');
|
$(td).html('<div class="history-title"><a href="info?' + source + 'rating_key=' + rowData['rating_key'] + '"><div style="float: left;" >' + media_type + ' ' + thumb_popover + '</div></a></div>');
|
||||||
|
@@ -107,7 +107,7 @@ history_table_modal_options = {
|
|||||||
thumb_popover = '<span class="thumb-tooltip" data-toggle="popover" data-img="pms_image_proxy?img=' + rowData['thumb'] + '&width=300&height=450&fallback=poster" data-height="120" data-width="80">' + cellData + parent_info + '</span>'
|
thumb_popover = '<span class="thumb-tooltip" data-toggle="popover" data-img="pms_image_proxy?img=' + rowData['thumb'] + '&width=300&height=450&fallback=poster" data-height="120" data-width="80">' + cellData + parent_info + '</span>'
|
||||||
$(td).html('<div class="history-title"><a href="info?source=history&rating_key=' + rowData['rating_key'] + '"><div style="float: left;">' + media_type + ' ' + thumb_popover + '</div></a></div>');
|
$(td).html('<div class="history-title"><a href="info?source=history&rating_key=' + rowData['rating_key'] + '"><div style="float: left;">' + media_type + ' ' + thumb_popover + '</div></a></div>');
|
||||||
} else if (rowData['media_type'] === 'episode') {
|
} else if (rowData['media_type'] === 'episode') {
|
||||||
if (rowData['parent_media_index'] && rowData['media_index']) { parent_info = ' (S' + rowData['parent_media_index'] + ' · E' + rowData['media_index'] + ')'; }
|
if (!isNaN(parseInt(rowData['parent_media_index'])) && !isNaN(parseInt(rowData['media_index']))) { parent_info = ' (S' + rowData['parent_media_index'] + ' · E' + rowData['media_index'] + ')'; }
|
||||||
media_type = '<span class="media-type-tooltip" data-toggle="tooltip" title="Episode"><i class="fa fa-television fa-fw"></i></span>';
|
media_type = '<span class="media-type-tooltip" data-toggle="tooltip" title="Episode"><i class="fa fa-television fa-fw"></i></span>';
|
||||||
thumb_popover = '<span class="thumb-tooltip" data-toggle="popover" data-img="pms_image_proxy?img=' + rowData['thumb'] + '&width=300&height=450&fallback=poster" data-height="120" data-width="80">' + cellData + parent_info + '</span>'
|
thumb_popover = '<span class="thumb-tooltip" data-toggle="popover" data-img="pms_image_proxy?img=' + rowData['thumb'] + '&width=300&height=450&fallback=poster" data-height="120" data-width="80">' + cellData + parent_info + '</span>'
|
||||||
$(td).html('<div class="history-title"><a href="info?source=history&rating_key=' + rowData['rating_key'] + '"><div style="float: left;" >' + media_type + ' ' + thumb_popover + '</div></a></div>');
|
$(td).html('<div class="history-title"><a href="info?source=history&rating_key=' + rowData['rating_key'] + '"><div style="float: left;" >' + media_type + ' ' + thumb_popover + '</div></a></div>');
|
||||||
|
@@ -153,7 +153,7 @@ libraries_list_table_options = {
|
|||||||
} else if (rowData['media_type'] === 'episode') {
|
} else if (rowData['media_type'] === 'episode') {
|
||||||
media_type = '<span class="media-type-tooltip" data-toggle="tooltip" title="Episode"><i class="fa fa-television fa-fw"></i></span>';
|
media_type = '<span class="media-type-tooltip" data-toggle="tooltip" title="Episode"><i class="fa fa-television fa-fw"></i></span>';
|
||||||
if (rowData['rating_key']) {
|
if (rowData['rating_key']) {
|
||||||
if (rowData['parent_media_index'] && rowData['media_index']) { parent_info = ' (S' + rowData['parent_media_index'] + ' · E' + rowData['media_index'] + ')'; }
|
if (!isNaN(parseInt(rowData['parent_media_index'])) && !isNaN(parseInt(rowData['media_index']))) { parent_info = ' (S' + rowData['parent_media_index'] + ' · E' + rowData['media_index'] + ')'; }
|
||||||
thumb_popover = '<span class="thumb-tooltip" data-toggle="popover" data-img="pms_image_proxy?img=' + rowData['thumb'] + '&width=300&height=450&fallback=poster" data-height="120" data-width="80">' + cellData + parent_info + '</span>'
|
thumb_popover = '<span class="thumb-tooltip" data-toggle="popover" data-img="pms_image_proxy?img=' + rowData['thumb'] + '&width=300&height=450&fallback=poster" data-height="120" data-width="80">' + cellData + parent_info + '</span>'
|
||||||
$(td).html('<div class="history-title"><a href="info?source=history&rating_key=' + rowData['rating_key'] + '"><div style="float: left;" >' + media_type + ' ' + thumb_popover + '</div></a></div>');
|
$(td).html('<div class="history-title"><a href="info?source=history&rating_key=' + rowData['rating_key'] + '"><div style="float: left;" >' + media_type + ' ' + thumb_popover + '</div></a></div>');
|
||||||
} else {
|
} else {
|
||||||
|
@@ -91,7 +91,7 @@ user_ip_table_options = {
|
|||||||
thumb_popover = '<span class="thumb-tooltip" data-toggle="popover" data-img="pms_image_proxy?img=' + rowData['thumb'] + '&width=300&height=450&fallback=poster" data-height="120" data-width="80">' + cellData + parent_info + '</span>'
|
thumb_popover = '<span class="thumb-tooltip" data-toggle="popover" data-img="pms_image_proxy?img=' + rowData['thumb'] + '&width=300&height=450&fallback=poster" data-height="120" data-width="80">' + cellData + parent_info + '</span>'
|
||||||
$(td).html('<div class="history-title"><a href="info?source=history&rating_key=' + rowData['rating_key'] + '"><div style="float: left;">' + media_type + ' ' + thumb_popover + '</div></a></div>');
|
$(td).html('<div class="history-title"><a href="info?source=history&rating_key=' + rowData['rating_key'] + '"><div style="float: left;">' + media_type + ' ' + thumb_popover + '</div></a></div>');
|
||||||
} else if (rowData['media_type'] === 'episode') {
|
} else if (rowData['media_type'] === 'episode') {
|
||||||
if (rowData['parent_media_index'] && rowData['media_index']) { parent_info = ' (S' + rowData['parent_media_index'] + ' · E' + rowData['media_index'] + ')'; }
|
if (!isNaN(parseInt(rowData['parent_media_index'])) && !isNaN(parseInt(rowData['media_index']))) { parent_info = ' (S' + rowData['parent_media_index'] + ' · E' + rowData['media_index'] + ')'; }
|
||||||
media_type = '<span class="media-type-tooltip" data-toggle="tooltip" title="Episode"><i class="fa fa-television fa-fw"></i></span>';
|
media_type = '<span class="media-type-tooltip" data-toggle="tooltip" title="Episode"><i class="fa fa-television fa-fw"></i></span>';
|
||||||
thumb_popover = '<span class="thumb-tooltip" data-toggle="popover" data-img="pms_image_proxy?img=' + rowData['thumb'] + '&width=300&height=450&fallback=poster" data-height="120" data-width="80">' + cellData + parent_info + '</span>'
|
thumb_popover = '<span class="thumb-tooltip" data-toggle="popover" data-img="pms_image_proxy?img=' + rowData['thumb'] + '&width=300&height=450&fallback=poster" data-height="120" data-width="80">' + cellData + parent_info + '</span>'
|
||||||
$(td).html('<div class="history-title"><a href="info?source=history&rating_key=' + rowData['rating_key'] + '"><div style="float: left;" >' + media_type + ' ' + thumb_popover + '</div></a></div>');
|
$(td).html('<div class="history-title"><a href="info?source=history&rating_key=' + rowData['rating_key'] + '"><div style="float: left;" >' + media_type + ' ' + thumb_popover + '</div></a></div>');
|
||||||
|
@@ -166,7 +166,7 @@ users_list_table_options = {
|
|||||||
thumb_popover = '<span class="thumb-tooltip" data-toggle="popover" data-img="pms_image_proxy?img=' + rowData['thumb'] + '&width=300&height=450&fallback=poster" data-height="120" data-width="80">' + cellData + parent_info + '</span>'
|
thumb_popover = '<span class="thumb-tooltip" data-toggle="popover" data-img="pms_image_proxy?img=' + rowData['thumb'] + '&width=300&height=450&fallback=poster" data-height="120" data-width="80">' + cellData + parent_info + '</span>'
|
||||||
$(td).html('<div class="history-title"><a href="info?source=history&rating_key=' + rowData['rating_key'] + '"><div style="float: left;">' + media_type + ' ' + thumb_popover + '</div></a></div>');
|
$(td).html('<div class="history-title"><a href="info?source=history&rating_key=' + rowData['rating_key'] + '"><div style="float: left;">' + media_type + ' ' + thumb_popover + '</div></a></div>');
|
||||||
} else if (rowData['media_type'] === 'episode') {
|
} else if (rowData['media_type'] === 'episode') {
|
||||||
if (rowData['parent_media_index'] && rowData['media_index']) { parent_info = ' (S' + rowData['parent_media_index'] + ' · E' + rowData['media_index'] + ')'; }
|
if (!isNaN(parseInt(rowData['parent_media_index'])) && !isNaN(parseInt(rowData['media_index']))) { parent_info = ' (S' + rowData['parent_media_index'] + ' · E' + rowData['media_index'] + ')'; }
|
||||||
media_type = '<span class="media-type-tooltip" data-toggle="tooltip" title="Episode"><i class="fa fa-television fa-fw"></i></span>';
|
media_type = '<span class="media-type-tooltip" data-toggle="tooltip" title="Episode"><i class="fa fa-television fa-fw"></i></span>';
|
||||||
thumb_popover = '<span class="thumb-tooltip" data-toggle="popover" data-img="pms_image_proxy?img=' + rowData['thumb'] + '&width=300&height=450&fallback=poster" data-height="120" data-width="80">' + cellData + parent_info + '</span>'
|
thumb_popover = '<span class="thumb-tooltip" data-toggle="popover" data-img="pms_image_proxy?img=' + rowData['thumb'] + '&width=300&height=450&fallback=poster" data-height="120" data-width="80">' + cellData + parent_info + '</span>'
|
||||||
$(td).html('<div class="history-title"><a href="info?source=history&rating_key=' + rowData['rating_key'] + '"><div style="float: left;" >' + media_type + ' ' + thumb_popover + '</div></a></div>');
|
$(td).html('<div class="history-title"><a href="info?source=history&rating_key=' + rowData['rating_key'] + '"><div style="float: left;" >' + media_type + ' ' + thumb_popover + '</div></a></div>');
|
||||||
|
@@ -1242,7 +1242,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<p class="help-block">
|
<p class="help-block">
|
||||||
Enter and save your MaxMind License Key to install the GeoLite2 database.
|
Enter your MaxMind License Key to install the GeoLite2 database.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
@@ -1250,16 +1250,17 @@
|
|||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-md-9">
|
<div class="col-md-9">
|
||||||
<div class="input-group">
|
<div class="input-group">
|
||||||
<input type="text" class="form-control" id="geoip_db" name="geoip_db" value="${config['geoip_db']}" ${docker_setting}>
|
<input type="text" class="form-control" id="geoip_db" name="geoip_db" value="${config['geoip_db']}" ${docker_setting} data-parsley-trigger="change" data-parsley-pattern=".+\.mmdb$" data-parsley-errors-container="#geoip_db_error" data-parsley-error-message="Must end with '.mmdb'">
|
||||||
<span class="input-group-btn">
|
<span class="input-group-btn">
|
||||||
<button class="btn btn-form" type="button" id="install_geoip_db" disabled>${'Update' if config["geoip_db_installed"] else 'Install'}</button>
|
<button class="btn btn-form" type="button" id="install_geoip_db">${'Update' if config["geoip_db_installed"] else 'Install'}</button>
|
||||||
<button class="btn btn-form" type="button" id="uninstall_geoip_db">Uninstall</button>
|
<button class="btn btn-form" type="button" id="uninstall_geoip_db" ${'disabled' if not config['geoip_db_installed'] else ''}>Uninstall</button>
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div id="geoip_db_error" class="alert alert-danger settings-alert" role="alert"></div>
|
||||||
</div>
|
</div>
|
||||||
<p class="help-block">
|
<p class="help-block">
|
||||||
GeoLite2 Database last updated <strong><span id="geoip_db_updated">never</span></strong>.
|
Leave blank to install in the default location. GeoLite2 database last updated <strong><span id="geoip_db_updated">never</span></strong>.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group advanced-setting">
|
<div class="form-group advanced-setting">
|
||||||
@@ -1979,12 +1980,10 @@ $(document).ready(function() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function preSaveChecks(_callback) {
|
function preSaveChecks(_callback) {
|
||||||
if (serverChanged) {
|
|
||||||
verifyServer();
|
|
||||||
}
|
|
||||||
verifyPMSWebURL();
|
verifyPMSWebURL();
|
||||||
|
if (serverChanged) {
|
||||||
if (_callback) {
|
verifyServer(_callback);
|
||||||
|
} else if (typeof _callback === "function") {
|
||||||
_callback();
|
_callback();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2001,7 +2000,6 @@ $(document).ready(function() {
|
|||||||
getNewslettersTable();
|
getNewslettersTable();
|
||||||
getMobileDevicesTable();
|
getMobileDevicesTable();
|
||||||
loadUpdateDistros();
|
loadUpdateDistros();
|
||||||
enableGeoLiteInstallButton();
|
|
||||||
settingsChanged = false;
|
settingsChanged = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2010,12 +2008,13 @@ $(document).ready(function() {
|
|||||||
settingsChanged = true;
|
settingsChanged = true;
|
||||||
});
|
});
|
||||||
|
|
||||||
function saveSettings() {
|
function saveSettings(showMsg, _callback) {
|
||||||
if (configForm.parsley().validate()) {
|
if (configForm.parsley().validate()) {
|
||||||
doAjaxCall('configUpdate', $(this), 'tabs', true, true, postSaveChecks);
|
doAjaxCall('configUpdate', $(this), 'tabs', true, showMsg, _callback);
|
||||||
return false;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
showMsg('<i class="fa fa-exclamation-circle"></i> Please verify your settings.', false, true, 5000, true)
|
showMsg('<i class="fa fa-exclamation-circle"></i> Please verify your settings.', false, true, 5000, true);
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2029,7 +2028,7 @@ $(document).ready(function() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
$('.save-button').click(function() {
|
$('.save-button').click(function() {
|
||||||
preSaveChecks(function () { saveSettings() });
|
preSaveChecks(function () { saveSettings(true, postSaveChecks) });
|
||||||
});
|
});
|
||||||
|
|
||||||
initConfigCheckbox('#api_enabled');
|
initConfigCheckbox('#api_enabled');
|
||||||
@@ -2338,6 +2337,7 @@ $(document).ready(function() {
|
|||||||
|
|
||||||
if (($("#pms_ip").val() !== '') || ($("#pms_port").val() !== '')) {
|
if (($("#pms_ip").val() !== '') || ($("#pms_port").val() !== '')) {
|
||||||
$("#pms_verify").html('<i class="fa fa-refresh fa-spin"></i>').fadeIn('fast');
|
$("#pms_verify").html('<i class="fa fa-refresh fa-spin"></i>').fadeIn('fast');
|
||||||
|
showMsg('Verifying Plex server...', true, true, 10000, false);
|
||||||
$.ajax({
|
$.ajax({
|
||||||
url: 'get_server_id',
|
url: 'get_server_id',
|
||||||
data: {
|
data: {
|
||||||
@@ -2375,10 +2375,11 @@ $(document).ready(function() {
|
|||||||
} else {
|
} else {
|
||||||
$("#pms_verify").html('<i class="fa fa-check"></i>').fadeIn('fast');
|
$("#pms_verify").html('<i class="fa fa-check"></i>').fadeIn('fast');
|
||||||
$("#pms_ip_group").removeClass("has-error");
|
$("#pms_ip_group").removeClass("has-error");
|
||||||
|
showMsg('<i class="fa fa-check"></i> Server verified.', false, true, 5000);
|
||||||
serverChanged = false;
|
serverChanged = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_callback) {
|
if (typeof _callback === "function") {
|
||||||
_callback();
|
_callback();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -2862,20 +2863,24 @@ $(document).ready(function() {
|
|||||||
gotoSetting('3rd_party_apis', 'geoip_db')
|
gotoSetting('3rd_party_apis', 'geoip_db')
|
||||||
}
|
}
|
||||||
|
|
||||||
function enableGeoLiteInstallButton() {
|
|
||||||
$('#install_geoip_db').prop('disabled', !(Boolean($("#maxmind_license_key").val())));
|
|
||||||
}
|
|
||||||
enableGeoLiteInstallButton();
|
|
||||||
|
|
||||||
if ("${config['geoip_db_installed']}" > "0") {
|
if ("${config['geoip_db_installed']}" > "0") {
|
||||||
$("#geoip_db_updated").text(moment("${config['geoip_db_installed']}", "X").fromNow());
|
$("#geoip_db_updated").text(moment("${config['geoip_db_installed']}", "X").fromNow());
|
||||||
}
|
}
|
||||||
|
|
||||||
$("#install_geoip_db").click(function () {
|
$("#install_geoip_db").click(function () {
|
||||||
|
var maxmind_license_key = $("#maxmind_license_key");
|
||||||
|
maxmind_license_key.val($.trim(maxmind_license_key.val()));
|
||||||
|
if (maxmind_license_key.val() === "") {
|
||||||
|
maxmind_license_key.focus();
|
||||||
|
showMsg('<i class="fa fa-exclamation-circle"></i> Maxmind License Key is required.', false, true, 5000, true);
|
||||||
|
return false;
|
||||||
|
} else if (!(saveSettings())) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
var msg = 'Are you sure you want to install the GeoLite2 database?<br /><br />' +
|
var msg = 'Are you sure you want to install the GeoLite2 database?<br /><br />' +
|
||||||
'The database is used to lookup IP address geolocation info.<br />' +
|
'The database is used to lookup IP address geolocation info.<br />' +
|
||||||
'The database will be downloaded from <a href="${anon_url("https://dev.maxmind.com/geoip/geoip2/geolite2/")}" target="_blank">MaxMind</a>, <br />' +
|
'The database will be downloaded from <a href="${anon_url("https://dev.maxmind.com/geoip/geoip2/geolite2/")}" target="_blank">MaxMind</a>, <br />' +
|
||||||
'and requires <strong>100MB</strong> of free space to install in your Tautulli directory.<br />';
|
'and requires <strong>100MB</strong> of free space to install.<br />';
|
||||||
var url = 'install_geoip_db';
|
var url = 'install_geoip_db';
|
||||||
if ($(this).text() === 'Update') {
|
if ($(this).text() === 'Update') {
|
||||||
url += '?update=true';
|
url += '?update=true';
|
||||||
@@ -2883,6 +2888,7 @@ $(document).ready(function() {
|
|||||||
confirmAjaxCall(url, msg, null, 'Installing GeoLite2 database.', function (result) {
|
confirmAjaxCall(url, msg, null, 'Installing GeoLite2 database.', function (result) {
|
||||||
if (result.result === "success") {
|
if (result.result === "success") {
|
||||||
$('#install_geoip_db').text('Update');
|
$('#install_geoip_db').text('Update');
|
||||||
|
$('#uninstall_geoip_db').prop('disabled', false);
|
||||||
$('#geoip_db_updated').text(moment(result.updated, "X").fromNow());
|
$('#geoip_db_updated').text(moment(result.updated, "X").fromNow());
|
||||||
}
|
}
|
||||||
getSchedulerTable();
|
getSchedulerTable();
|
||||||
@@ -2896,6 +2902,7 @@ $(document).ready(function() {
|
|||||||
confirmAjaxCall(url, msg, null, 'Uninstalling GeoLite2 database.', function (result) {
|
confirmAjaxCall(url, msg, null, 'Uninstalling GeoLite2 database.', function (result) {
|
||||||
if (result.result === "success") {
|
if (result.result === "success") {
|
||||||
$('#install_geoip_db').text('Install');
|
$('#install_geoip_db').text('Install');
|
||||||
|
$('#uninstall_geoip_db').prop('disabled', true);
|
||||||
$('#geoip_db_updated').text('never');
|
$('#geoip_db_updated').text('never');
|
||||||
}
|
}
|
||||||
getSchedulerTable();
|
getSchedulerTable();
|
||||||
|
@@ -178,6 +178,11 @@ DOCUMENTATION :: END
|
|||||||
<td>${data['stream_video_framerate']}</td>
|
<td>${data['stream_video_framerate']}</td>
|
||||||
<td>${data['video_framerate']}</td>
|
<td>${data['video_framerate']}</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Dynamic Range</td>
|
||||||
|
<td>${data['stream_video_dynamic_range']}</td>
|
||||||
|
<td>${data['video_dynamic_range']}</td>
|
||||||
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>Aspect Ratio</td>
|
<td>Aspect Ratio</td>
|
||||||
<td>-</td>
|
<td>-</td>
|
||||||
|
@@ -694,7 +694,7 @@
|
|||||||
<div class="sub-header-count" style="margin-left: auto;margin-right: auto;font-size: 30px;text-align: center;">
|
<div class="sub-header-count" style="margin-left: auto;margin-right: auto;font-size: 30px;text-align: center;">
|
||||||
<span class="count" style="color: #E5A00D;">${len(recently_added['show'])}</span> <span class="count-units" style="color: #aaaaaa;font-size: 20px;text-transform: uppercase;">show${'s' if len(recently_added['show']) > 1 else ''}</span> /
|
<span class="count" style="color: #E5A00D;">${len(recently_added['show'])}</span> <span class="count-units" style="color: #aaaaaa;font-size: 20px;text-transform: uppercase;">show${'s' if len(recently_added['show']) > 1 else ''}</span> /
|
||||||
<% total_episodes = sum(season['episode_count'] for show in recently_added['show'] for season in show['season']) %>
|
<% total_episodes = sum(season['episode_count'] for show in recently_added['show'] for season in show['season']) %>
|
||||||
<span class="count" style="color: #E5A00D;">${total_episodes}</span> <span class="count-units" style="color: #aaaaaa;font-size: 20px;text-transform: uppercase;">episode${'s' if total > 1 else ''}</span>
|
<span class="count" style="color: #E5A00D;">${total_episodes}</span> <span class="count-units" style="color: #aaaaaa;font-size: 20px;text-transform: uppercase;">episode${'s' if total_episodes > 1 else ''}</span>
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
@@ -847,7 +847,7 @@
|
|||||||
<div class="sub-header-count" style="margin-left: auto;margin-right: auto;font-size: 30px;text-align: center;">
|
<div class="sub-header-count" style="margin-left: auto;margin-right: auto;font-size: 30px;text-align: center;">
|
||||||
<span class="count" style="color: #E5A00D;">${len(recently_added['artist'])}</span> <span class="count-units" style="color: #aaaaaa;font-size: 20px;text-transform: uppercase;">artist${'s' if len(recently_added['artist']) > 1 else ''}</span> /
|
<span class="count" style="color: #E5A00D;">${len(recently_added['artist'])}</span> <span class="count-units" style="color: #aaaaaa;font-size: 20px;text-transform: uppercase;">artist${'s' if len(recently_added['artist']) > 1 else ''}</span> /
|
||||||
<% total_albums = sum(artist['album_count'] for artist in recently_added['artist']) %>
|
<% total_albums = sum(artist['album_count'] for artist in recently_added['artist']) %>
|
||||||
<span class="count" style="color: #E5A00D;">${total_albums}</span> <span class="count-units" style="color: #aaaaaa;font-size: 20px;text-transform: uppercase;">album${'s' if total > 1 else ''}</span>
|
<span class="count" style="color: #E5A00D;">${total_albums}</span> <span class="count-units" style="color: #aaaaaa;font-size: 20px;text-transform: uppercase;">album${'s' if total_albums > 1 else ''}</span>
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
@@ -694,7 +694,7 @@
|
|||||||
<div class="sub-header-count">
|
<div class="sub-header-count">
|
||||||
<span class="count">${len(recently_added['show'])}</span> <span class="count-units">show${'s' if len(recently_added['show']) > 1 else ''}</span> /
|
<span class="count">${len(recently_added['show'])}</span> <span class="count-units">show${'s' if len(recently_added['show']) > 1 else ''}</span> /
|
||||||
<% total_episodes = sum(season['episode_count'] for show in recently_added['show'] for season in show['season']) %>
|
<% total_episodes = sum(season['episode_count'] for show in recently_added['show'] for season in show['season']) %>
|
||||||
<span class="count">${total_episodes}</span> <span class="count-units">episode${'s' if total > 1 else ''}</span>
|
<span class="count">${total_episodes}</span> <span class="count-units">episode${'s' if total_episodes > 1 else ''}</span>
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
@@ -847,7 +847,7 @@
|
|||||||
<div class="sub-header-count">
|
<div class="sub-header-count">
|
||||||
<span class="count">${len(recently_added['artist'])}</span> <span class="count-units">artist${'s' if len(recently_added['artist']) > 1 else ''}</span> /
|
<span class="count">${len(recently_added['artist'])}</span> <span class="count-units">artist${'s' if len(recently_added['artist']) > 1 else ''}</span> /
|
||||||
<% total_albums = sum(artist['album_count'] for artist in recently_added['artist']) %>
|
<% total_albums = sum(artist['album_count'] for artist in recently_added['artist']) %>
|
||||||
<span class="count">${total_albums}</span> <span class="count-units">album${'s' if total > 1 else ''}</span>
|
<span class="count">${total_albums}</span> <span class="count-units">album${'s' if total_albums > 1 else ''}</span>
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
@@ -1,3 +1,3 @@
|
|||||||
from .core import where
|
from .core import where
|
||||||
|
|
||||||
__version__ = "2019.03.09"
|
__version__ = "2019.11.28"
|
||||||
|
@@ -771,36 +771,6 @@ vEsXCS+0yx5DaMkHJ8HSXPfqIbloEpw8nL+e/IBcm2PN7EeqJSdnoDfzAIJ9VNep
|
|||||||
+OkuE6N36B9K
|
+OkuE6N36B9K
|
||||||
-----END CERTIFICATE-----
|
-----END CERTIFICATE-----
|
||||||
|
|
||||||
# Issuer: CN=Class 2 Primary CA O=Certplus
|
|
||||||
# Subject: CN=Class 2 Primary CA O=Certplus
|
|
||||||
# Label: "Certplus Class 2 Primary CA"
|
|
||||||
# Serial: 177770208045934040241468760488327595043
|
|
||||||
# MD5 Fingerprint: 88:2c:8c:52:b8:a2:3c:f3:f7:bb:03:ea:ae:ac:42:0b
|
|
||||||
# SHA1 Fingerprint: 74:20:74:41:72:9c:dd:92:ec:79:31:d8:23:10:8d:c2:81:92:e2:bb
|
|
||||||
# SHA256 Fingerprint: 0f:99:3c:8a:ef:97:ba:af:56:87:14:0e:d5:9a:d1:82:1b:b4:af:ac:f0:aa:9a:58:b5:d5:7a:33:8a:3a:fb:cb
|
|
||||||
-----BEGIN CERTIFICATE-----
|
|
||||||
MIIDkjCCAnqgAwIBAgIRAIW9S/PY2uNp9pTXX8OlRCMwDQYJKoZIhvcNAQEFBQAw
|
|
||||||
PTELMAkGA1UEBhMCRlIxETAPBgNVBAoTCENlcnRwbHVzMRswGQYDVQQDExJDbGFz
|
|
||||||
cyAyIFByaW1hcnkgQ0EwHhcNOTkwNzA3MTcwNTAwWhcNMTkwNzA2MjM1OTU5WjA9
|
|
||||||
MQswCQYDVQQGEwJGUjERMA8GA1UEChMIQ2VydHBsdXMxGzAZBgNVBAMTEkNsYXNz
|
|
||||||
IDIgUHJpbWFyeSBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANxQ
|
|
||||||
ltAS+DXSCHh6tlJw/W/uz7kRy1134ezpfgSN1sxvc0NXYKwzCkTsA18cgCSR5aiR
|
|
||||||
VhKC9+Ar9NuuYS6JEI1rbLqzAr3VNsVINyPi8Fo3UjMXEuLRYE2+L0ER4/YXJQyL
|
|
||||||
kcAbmXuZVg2v7tK8R1fjeUl7NIknJITesezpWE7+Tt9avkGtrAjFGA7v0lPubNCd
|
|
||||||
EgETjdyAYveVqUSISnFOYFWe2yMZeVYHDD9jC1yw4r5+FfyUM1hBOHTE4Y+L3yas
|
|
||||||
H7WLO7dDWWuwJKZtkIvEcupdM5i3y95ee++U8Rs+yskhwcWYAqqi9lt3m/V+llU0
|
|
||||||
HGdpwPFC40es/CgcZlUCAwEAAaOBjDCBiTAPBgNVHRMECDAGAQH/AgEKMAsGA1Ud
|
|
||||||
DwQEAwIBBjAdBgNVHQ4EFgQU43Mt38sOKAze3bOkynm4jrvoMIkwEQYJYIZIAYb4
|
|
||||||
QgEBBAQDAgEGMDcGA1UdHwQwMC4wLKAqoCiGJmh0dHA6Ly93d3cuY2VydHBsdXMu
|
|
||||||
Y29tL0NSTC9jbGFzczIuY3JsMA0GCSqGSIb3DQEBBQUAA4IBAQCnVM+IRBnL39R/
|
|
||||||
AN9WM2K191EBkOvDP9GIROkkXe/nFL0gt5o8AP5tn9uQ3Nf0YtaLcF3n5QRIqWh8
|
|
||||||
yfFC82x/xXp8HVGIutIKPidd3i1RTtMTZGnkLuPT55sJmabglZvOGtd/vjzOUrMR
|
|
||||||
FcEPF80Du5wlFbqidon8BvEY0JNLDnyCt6X09l/+7UCmnYR0ObncHoUW2ikbhiMA
|
|
||||||
ybuJfm6AiB4vFLQDJKgybwOaRywwvlbGp0ICcBvqQNi6BQNwB6SW//1IMwrh3KWB
|
|
||||||
kJtN3X3n57LNXMhqlfil9o3EXXgIvnsG1knPGTZQIy4I5p4FTUcY1Rbpsda2ENW7
|
|
||||||
l7+ijrRU
|
|
||||||
-----END CERTIFICATE-----
|
|
||||||
|
|
||||||
# Issuer: CN=DST Root CA X3 O=Digital Signature Trust Co.
|
# Issuer: CN=DST Root CA X3 O=Digital Signature Trust Co.
|
||||||
# Subject: CN=DST Root CA X3 O=Digital Signature Trust Co.
|
# Subject: CN=DST Root CA X3 O=Digital Signature Trust Co.
|
||||||
# Label: "DST Root CA X3"
|
# Label: "DST Root CA X3"
|
||||||
@@ -1219,36 +1189,6 @@ t0QmwCbAr1UwnjvVNioZBPRcHv/PLLf/0P2HQBHVESO7SMAhqaQoLf0V+LBOK/Qw
|
|||||||
WyH8EZE0vkHve52Xdf+XlcCWWC/qu0bXu+TZLg==
|
WyH8EZE0vkHve52Xdf+XlcCWWC/qu0bXu+TZLg==
|
||||||
-----END CERTIFICATE-----
|
-----END CERTIFICATE-----
|
||||||
|
|
||||||
# Issuer: CN=Deutsche Telekom Root CA 2 O=Deutsche Telekom AG OU=T-TeleSec Trust Center
|
|
||||||
# Subject: CN=Deutsche Telekom Root CA 2 O=Deutsche Telekom AG OU=T-TeleSec Trust Center
|
|
||||||
# Label: "Deutsche Telekom Root CA 2"
|
|
||||||
# Serial: 38
|
|
||||||
# MD5 Fingerprint: 74:01:4a:91:b1:08:c4:58:ce:47:cd:f0:dd:11:53:08
|
|
||||||
# SHA1 Fingerprint: 85:a4:08:c0:9c:19:3e:5d:51:58:7d:cd:d6:13:30:fd:8c:de:37:bf
|
|
||||||
# SHA256 Fingerprint: b6:19:1a:50:d0:c3:97:7f:7d:a9:9b:cd:aa:c8:6a:22:7d:ae:b9:67:9e:c7:0b:a3:b0:c9:d9:22:71:c1:70:d3
|
|
||||||
-----BEGIN CERTIFICATE-----
|
|
||||||
MIIDnzCCAoegAwIBAgIBJjANBgkqhkiG9w0BAQUFADBxMQswCQYDVQQGEwJERTEc
|
|
||||||
MBoGA1UEChMTRGV1dHNjaGUgVGVsZWtvbSBBRzEfMB0GA1UECxMWVC1UZWxlU2Vj
|
|
||||||
IFRydXN0IENlbnRlcjEjMCEGA1UEAxMaRGV1dHNjaGUgVGVsZWtvbSBSb290IENB
|
|
||||||
IDIwHhcNOTkwNzA5MTIxMTAwWhcNMTkwNzA5MjM1OTAwWjBxMQswCQYDVQQGEwJE
|
|
||||||
RTEcMBoGA1UEChMTRGV1dHNjaGUgVGVsZWtvbSBBRzEfMB0GA1UECxMWVC1UZWxl
|
|
||||||
U2VjIFRydXN0IENlbnRlcjEjMCEGA1UEAxMaRGV1dHNjaGUgVGVsZWtvbSBSb290
|
|
||||||
IENBIDIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCrC6M14IspFLEU
|
|
||||||
ha88EOQ5bzVdSq7d6mGNlUn0b2SjGmBmpKlAIoTZ1KXleJMOaAGtuU1cOs7TuKhC
|
|
||||||
QN/Po7qCWWqSG6wcmtoIKyUn+WkjR/Hg6yx6m/UTAtB+NHzCnjwAWav12gz1Mjwr
|
|
||||||
rFDa1sPeg5TKqAyZMg4ISFZbavva4VhYAUlfckE8FQYBjl2tqriTtM2e66foai1S
|
|
||||||
NNs671x1Udrb8zH57nGYMsRUFUQM+ZtV7a3fGAigo4aKSe5TBY8ZTNXeWHmb0moc
|
|
||||||
QqvF1afPaA+W5OFhmHZhyJF81j4A4pFQh+GdCuatl9Idxjp9y7zaAzTVjlsB9WoH
|
|
||||||
txa2bkp/AgMBAAGjQjBAMB0GA1UdDgQWBBQxw3kbuvVT1xfgiXotF2wKsyudMzAP
|
|
||||||
BgNVHRMECDAGAQH/AgEFMA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQUFAAOC
|
|
||||||
AQEAlGRZrTlk5ynrE/5aw4sTV8gEJPB0d8Bg42f76Ymmg7+Wgnxu1MM9756Abrsp
|
|
||||||
tJh6sTtU6zkXR34ajgv8HzFZMQSyzhfzLMdiNlXiItiJVbSYSKpk+tYcNthEeFpa
|
|
||||||
IzpXl/V6ME+un2pMSyuOoAPjPuCp1NJ70rOo4nI8rZ7/gFnkm0W09juwzTkZmDLl
|
|
||||||
6iFhkOQxIY40sfcvNUqFENrnijchvllj4PKFiDFT1FQUhXB59C4Gdyd1Lx+4ivn+
|
|
||||||
xbrYNuSD7Odlt79jWvNGr4GUN9RBjNYj1h7P9WgbRGOiWrqnNVmh5XAFmw4jV5mU
|
|
||||||
Cm26OWMohpLzGITY+9HPBVZkVw==
|
|
||||||
-----END CERTIFICATE-----
|
|
||||||
|
|
||||||
# Issuer: CN=Cybertrust Global Root O=Cybertrust, Inc
|
# Issuer: CN=Cybertrust Global Root O=Cybertrust, Inc
|
||||||
# Subject: CN=Cybertrust Global Root O=Cybertrust, Inc
|
# Subject: CN=Cybertrust Global Root O=Cybertrust, Inc
|
||||||
# Label: "Cybertrust Global Root"
|
# Label: "Cybertrust Global Root"
|
||||||
@@ -3453,46 +3393,6 @@ AAoACxGV2lZFA4gKn2fQ1XmxqI1AbQ3CekD6819kR5LLU7m7Wc5P/dAVUwHY3+vZ
|
|||||||
5nbv0CO7O6l5s9UCKc2Jo5YPSjXnTkLAdc0Hz+Ys63su
|
5nbv0CO7O6l5s9UCKc2Jo5YPSjXnTkLAdc0Hz+Ys63su
|
||||||
-----END CERTIFICATE-----
|
-----END CERTIFICATE-----
|
||||||
|
|
||||||
# Issuer: CN=Certinomis - Root CA O=Certinomis OU=0002 433998903
|
|
||||||
# Subject: CN=Certinomis - Root CA O=Certinomis OU=0002 433998903
|
|
||||||
# Label: "Certinomis - Root CA"
|
|
||||||
# Serial: 1
|
|
||||||
# MD5 Fingerprint: 14:0a:fd:8d:a8:28:b5:38:69:db:56:7e:61:22:03:3f
|
|
||||||
# SHA1 Fingerprint: 9d:70:bb:01:a5:a4:a0:18:11:2e:f7:1c:01:b9:32:c5:34:e7:88:a8
|
|
||||||
# SHA256 Fingerprint: 2a:99:f5:bc:11:74:b7:3c:bb:1d:62:08:84:e0:1c:34:e5:1c:cb:39:78:da:12:5f:0e:33:26:88:83:bf:41:58
|
|
||||||
-----BEGIN CERTIFICATE-----
|
|
||||||
MIIFkjCCA3qgAwIBAgIBATANBgkqhkiG9w0BAQsFADBaMQswCQYDVQQGEwJGUjET
|
|
||||||
MBEGA1UEChMKQ2VydGlub21pczEXMBUGA1UECxMOMDAwMiA0MzM5OTg5MDMxHTAb
|
|
||||||
BgNVBAMTFENlcnRpbm9taXMgLSBSb290IENBMB4XDTEzMTAyMTA5MTcxOFoXDTMz
|
|
||||||
MTAyMTA5MTcxOFowWjELMAkGA1UEBhMCRlIxEzARBgNVBAoTCkNlcnRpbm9taXMx
|
|
||||||
FzAVBgNVBAsTDjAwMDIgNDMzOTk4OTAzMR0wGwYDVQQDExRDZXJ0aW5vbWlzIC0g
|
|
||||||
Um9vdCBDQTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBANTMCQosP5L2
|
|
||||||
fxSeC5yaah1AMGT9qt8OHgZbn1CF6s2Nq0Nn3rD6foCWnoR4kkjW4znuzuRZWJfl
|
|
||||||
LieY6pOod5tK8O90gC3rMB+12ceAnGInkYjwSond3IjmFPnVAy//ldu9n+ws+hQV
|
|
||||||
WZUKxkd8aRi5pwP5ynapz8dvtF4F/u7BUrJ1Mofs7SlmO/NKFoL21prbcpjp3vDF
|
|
||||||
TKWrteoB4owuZH9kb/2jJZOLyKIOSY008B/sWEUuNKqEUL3nskoTuLAPrjhdsKkb
|
|
||||||
5nPJWqHZZkCqqU2mNAKthH6yI8H7KsZn9DS2sJVqM09xRLWtwHkziOC/7aOgFLSc
|
|
||||||
CbAK42C++PhmiM1b8XcF4LVzbsF9Ri6OSyemzTUK/eVNfaoqoynHWmgE6OXWk6Ri
|
|
||||||
wsXm9E/G+Z8ajYJJGYrKWUM66A0ywfRMEwNvbqY/kXPLynNvEiCL7sCCeN5LLsJJ
|
|
||||||
wx3tFvYk9CcbXFcx3FXuqB5vbKziRcxXV4p1VxngtViZSTYxPDMBbRZKzbgqg4SG
|
|
||||||
m/lg0h9tkQPTYKbVPZrdd5A9NaSfD171UkRpucC63M9933zZxKyGIjK8e2uR73r4
|
|
||||||
F2iw4lNVYC2vPsKD2NkJK/DAZNuHi5HMkesE/Xa0lZrmFAYb1TQdvtj/dBxThZng
|
|
||||||
WVJKYe2InmtJiUZ+IFrZ50rlau7SZRFDAgMBAAGjYzBhMA4GA1UdDwEB/wQEAwIB
|
|
||||||
BjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBTvkUz1pcMw6C8I6tNxIqSSaHh0
|
|
||||||
2TAfBgNVHSMEGDAWgBTvkUz1pcMw6C8I6tNxIqSSaHh02TANBgkqhkiG9w0BAQsF
|
|
||||||
AAOCAgEAfj1U2iJdGlg+O1QnurrMyOMaauo++RLrVl89UM7g6kgmJs95Vn6RHJk/
|
|
||||||
0KGRHCwPT5iVWVO90CLYiF2cN/z7ZMF4jIuaYAnq1fohX9B0ZedQxb8uuQsLrbWw
|
|
||||||
F6YSjNRieOpWauwK0kDDPAUwPk2Ut59KA9N9J0u2/kTO+hkzGm2kQtHdzMjI1xZS
|
|
||||||
g081lLMSVX3l4kLr5JyTCcBMWwerx20RoFAXlCOotQqSD7J6wWAsOMwaplv/8gzj
|
|
||||||
qh8c3LigkyfeY+N/IZ865Z764BNqdeuWXGKRlI5nU7aJ+BIJy29SWwNyhlCVCNSN
|
|
||||||
h4YVH5Uk2KRvms6knZtt0rJ2BobGVgjF6wnaNsIbW0G+YSrjcOa4pvi2WsS9Iff/
|
|
||||||
ql+hbHY5ZtbqTFXhADObE5hjyW/QASAJN1LnDE8+zbz1X5YnpyACleAu6AdBBR8V
|
|
||||||
btaw5BngDwKTACdyxYvRVB9dSsNAl35VpnzBMwQUAR1JIGkLGZOdblgi90AMRgwj
|
|
||||||
Y/M50n92Uaf0yKHxDHYiI0ZSKS3io0EHVmmY0gUJvGnHWmHNj4FgFU2A3ZDifcRQ
|
|
||||||
8ow7bkrHxuaAKzyBvBGAFhAn1/DNP3nMcyrDflOR1m749fPH0FFNjkulW+YZFzvW
|
|
||||||
gQncItzujrnEj1PhZ7szuIgVRs/taTX/dQ1G885x4cVrhkIGuUE=
|
|
||||||
-----END CERTIFICATE-----
|
|
||||||
|
|
||||||
# Issuer: CN=OISTE WISeKey Global Root GB CA O=WISeKey OU=OISTE Foundation Endorsed
|
# Issuer: CN=OISTE WISeKey Global Root GB CA O=WISeKey OU=OISTE Foundation Endorsed
|
||||||
# Subject: CN=OISTE WISeKey Global Root GB CA O=WISeKey OU=OISTE Foundation Endorsed
|
# Subject: CN=OISTE WISeKey Global Root GB CA O=WISeKey OU=OISTE Foundation Endorsed
|
||||||
# Label: "OISTE WISeKey Global Root GB CA"
|
# Label: "OISTE WISeKey Global Root GB CA"
|
||||||
@@ -4656,3 +4556,47 @@ L5/ndtFhKvshuzHQqp9HpLIiyhY6UFfEW0NnxWViA0kB60PZ2Pierc+xYw5F9KBa
|
|||||||
LJstxabArahH9CdMOA0uG0k7UvToiIMrVCjU8jVStDKDYmlkDJGcn5fqdBb9HxEG
|
LJstxabArahH9CdMOA0uG0k7UvToiIMrVCjU8jVStDKDYmlkDJGcn5fqdBb9HxEG
|
||||||
mpv0
|
mpv0
|
||||||
-----END CERTIFICATE-----
|
-----END CERTIFICATE-----
|
||||||
|
|
||||||
|
# Issuer: CN=Entrust Root Certification Authority - G4 O=Entrust, Inc. OU=See www.entrust.net/legal-terms/(c) 2015 Entrust, Inc. - for authorized use only
|
||||||
|
# Subject: CN=Entrust Root Certification Authority - G4 O=Entrust, Inc. OU=See www.entrust.net/legal-terms/(c) 2015 Entrust, Inc. - for authorized use only
|
||||||
|
# Label: "Entrust Root Certification Authority - G4"
|
||||||
|
# Serial: 289383649854506086828220374796556676440
|
||||||
|
# MD5 Fingerprint: 89:53:f1:83:23:b7:7c:8e:05:f1:8c:71:38:4e:1f:88
|
||||||
|
# SHA1 Fingerprint: 14:88:4e:86:26:37:b0:26:af:59:62:5c:40:77:ec:35:29:ba:96:01
|
||||||
|
# SHA256 Fingerprint: db:35:17:d1:f6:73:2a:2d:5a:b9:7c:53:3e:c7:07:79:ee:32:70:a6:2f:b4:ac:42:38:37:24:60:e6:f0:1e:88
|
||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
MIIGSzCCBDOgAwIBAgIRANm1Q3+vqTkPAAAAAFVlrVgwDQYJKoZIhvcNAQELBQAw
|
||||||
|
gb4xCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1FbnRydXN0LCBJbmMuMSgwJgYDVQQL
|
||||||
|
Ex9TZWUgd3d3LmVudHJ1c3QubmV0L2xlZ2FsLXRlcm1zMTkwNwYDVQQLEzAoYykg
|
||||||
|
MjAxNSBFbnRydXN0LCBJbmMuIC0gZm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxMjAw
|
||||||
|
BgNVBAMTKUVudHJ1c3QgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEc0
|
||||||
|
MB4XDTE1MDUyNzExMTExNloXDTM3MTIyNzExNDExNlowgb4xCzAJBgNVBAYTAlVT
|
||||||
|
MRYwFAYDVQQKEw1FbnRydXN0LCBJbmMuMSgwJgYDVQQLEx9TZWUgd3d3LmVudHJ1
|
||||||
|
c3QubmV0L2xlZ2FsLXRlcm1zMTkwNwYDVQQLEzAoYykgMjAxNSBFbnRydXN0LCBJ
|
||||||
|
bmMuIC0gZm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxMjAwBgNVBAMTKUVudHJ1c3Qg
|
||||||
|
Um9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEc0MIICIjANBgkqhkiG9w0B
|
||||||
|
AQEFAAOCAg8AMIICCgKCAgEAsewsQu7i0TD/pZJH4i3DumSXbcr3DbVZwbPLqGgZ
|
||||||
|
2K+EbTBwXX7zLtJTmeH+H17ZSK9dE43b/2MzTdMAArzE+NEGCJR5WIoV3imz/f3E
|
||||||
|
T+iq4qA7ec2/a0My3dl0ELn39GjUu9CH1apLiipvKgS1sqbHoHrmSKvS0VnM1n4j
|
||||||
|
5pds8ELl3FFLFUHtSUrJ3hCX1nbB76W1NhSXNdh4IjVS70O92yfbYVaCNNzLiGAM
|
||||||
|
C1rlLAHGVK/XqsEQe9IFWrhAnoanw5CGAlZSCXqc0ieCU0plUmr1POeo8pyvi73T
|
||||||
|
DtTUXm6Hnmo9RR3RXRv06QqsYJn7ibT/mCzPfB3pAqoEmh643IhuJbNsZvc8kPNX
|
||||||
|
wbMv9W3y+8qh+CmdRouzavbmZwe+LGcKKh9asj5XxNMhIWNlUpEbsZmOeX7m640A
|
||||||
|
2Vqq6nPopIICR5b+W45UYaPrL0swsIsjdXJ8ITzI9vF01Bx7owVV7rtNOzK+mndm
|
||||||
|
nqxpkCIHH2E6lr7lmk/MBTwoWdPBDFSoWWG9yHJM6Nyfh3+9nEg2XpWjDrk4JFX8
|
||||||
|
dWbrAuMINClKxuMrLzOg2qOGpRKX/YAr2hRC45K9PvJdXmd0LhyIRyk0X+IyqJwl
|
||||||
|
N4y6mACXi0mWHv0liqzc2thddG5msP9E36EYxr5ILzeUePiVSj9/E15dWf10hkNj
|
||||||
|
c0kCAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYD
|
||||||
|
VR0OBBYEFJ84xFYjwznooHFs6FRM5Og6sb9nMA0GCSqGSIb3DQEBCwUAA4ICAQAS
|
||||||
|
5UKme4sPDORGpbZgQIeMJX6tuGguW8ZAdjwD+MlZ9POrYs4QjbRaZIxowLByQzTS
|
||||||
|
Gwv2LFPSypBLhmb8qoMi9IsabyZIrHZ3CL/FmFz0Jomee8O5ZDIBf9PD3Vht7LGr
|
||||||
|
hFV0d4QEJ1JrhkzO3bll/9bGXp+aEJlLdWr+aumXIOTkdnrG0CSqkM0gkLpHZPt/
|
||||||
|
B7NTeLUKYvJzQ85BK4FqLoUWlFPUa19yIqtRLULVAJyZv967lDtX/Zr1hstWO1uI
|
||||||
|
AeV8KEsD+UmDfLJ/fOPtjqF/YFOOVZ1QNBIPt5d7bIdKROf1beyAN/BYGW5KaHbw
|
||||||
|
H5Lk6rWS02FREAutp9lfx1/cH6NcjKF+m7ee01ZvZl4HliDtC3T7Zk6LERXpgUl+
|
||||||
|
b7DUUH8i119lAg2m9IUe2K4GS0qn0jFmwvjO5QimpAKWRGhXxNUzzxkvFMSUHHuk
|
||||||
|
2fCfDrGA4tGeEWSpiBE6doLlYsKA2KSD7ZPvfC+QsDJMlhVoSFLUmQjAJOgc47Ol
|
||||||
|
IQ6SwJAfzyBfyjs4x7dtOvPmRLgOMWuIjnDrnBdSqEGULoe256YSxXXfW8AKbnuk
|
||||||
|
5F6G+TaU33fD6Q3AOfF5u0aOq0NZJ7cguyPpVkAh7DE9ZapD8j3fcEThuk0mEDuY
|
||||||
|
n/PIjhs4ViFqUZPTkcpG2om3PVODLAgfi49T3f+sHw==
|
||||||
|
-----END CERTIFICATE-----
|
||||||
|
@@ -65,7 +65,7 @@ SYS_LANGUAGE = None
|
|||||||
SYS_ENCODING = None
|
SYS_ENCODING = None
|
||||||
|
|
||||||
QUIET = False
|
QUIET = False
|
||||||
VERBOSE = True
|
VERBOSE = False
|
||||||
DAEMON = False
|
DAEMON = False
|
||||||
CREATEPID = False
|
CREATEPID = False
|
||||||
PIDFILE = None
|
PIDFILE = None
|
||||||
@@ -122,6 +122,7 @@ def initialize(config_file):
|
|||||||
|
|
||||||
global CONFIG
|
global CONFIG
|
||||||
global CONFIG_FILE
|
global CONFIG_FILE
|
||||||
|
global VERBOSE
|
||||||
global _INITIALIZED
|
global _INITIALIZED
|
||||||
global CURRENT_VERSION
|
global CURRENT_VERSION
|
||||||
global LATEST_VERSION
|
global LATEST_VERSION
|
||||||
@@ -152,6 +153,8 @@ def initialize(config_file):
|
|||||||
if not log_writable and not QUIET:
|
if not log_writable and not QUIET:
|
||||||
sys.stderr.write("Unable to create the log directory. Logging to screen only.\n")
|
sys.stderr.write("Unable to create the log directory. Logging to screen only.\n")
|
||||||
|
|
||||||
|
VERBOSE = VERBOSE or bool(CONFIG.VERBOSE_LOGS)
|
||||||
|
|
||||||
# Start the logger, disable console if needed
|
# Start the logger, disable console if needed
|
||||||
logger.initLogger(console=not QUIET, log_dir=CONFIG.LOG_DIR if log_writable else None,
|
logger.initLogger(console=not QUIET, log_dir=CONFIG.LOG_DIR if log_writable else None,
|
||||||
verbose=VERBOSE)
|
verbose=VERBOSE)
|
||||||
@@ -585,12 +588,14 @@ def dbcheck():
|
|||||||
'view_offset INTEGER DEFAULT 0, duration INTEGER, video_decision TEXT, audio_decision TEXT, '
|
'view_offset INTEGER DEFAULT 0, duration INTEGER, video_decision TEXT, audio_decision TEXT, '
|
||||||
'transcode_decision TEXT, container TEXT, bitrate INTEGER, width INTEGER, height INTEGER, '
|
'transcode_decision TEXT, container TEXT, bitrate INTEGER, width INTEGER, height INTEGER, '
|
||||||
'video_codec TEXT, video_bitrate INTEGER, video_resolution TEXT, video_width INTEGER, video_height INTEGER, '
|
'video_codec TEXT, video_bitrate INTEGER, video_resolution TEXT, video_width INTEGER, video_height INTEGER, '
|
||||||
'video_framerate TEXT, video_scan_type TEXT, video_full_resolution TEXT, aspect_ratio TEXT, '
|
'video_framerate TEXT, video_scan_type TEXT, video_full_resolution TEXT, '
|
||||||
|
'video_dynamic_range TEXT, aspect_ratio TEXT, '
|
||||||
'audio_codec TEXT, audio_bitrate INTEGER, audio_channels INTEGER, subtitle_codec TEXT, '
|
'audio_codec TEXT, audio_bitrate INTEGER, audio_channels INTEGER, subtitle_codec TEXT, '
|
||||||
'stream_bitrate INTEGER, stream_video_resolution TEXT, quality_profile TEXT, '
|
'stream_bitrate INTEGER, stream_video_resolution TEXT, quality_profile TEXT, '
|
||||||
'stream_container_decision TEXT, stream_container TEXT, '
|
'stream_container_decision TEXT, stream_container TEXT, '
|
||||||
'stream_video_decision TEXT, stream_video_codec TEXT, stream_video_bitrate INTEGER, stream_video_width INTEGER, '
|
'stream_video_decision TEXT, stream_video_codec TEXT, stream_video_bitrate INTEGER, stream_video_width INTEGER, '
|
||||||
'stream_video_height INTEGER, stream_video_framerate TEXT, stream_video_scan_type TEXT, stream_video_full_resolution TEXT, '
|
'stream_video_height INTEGER, stream_video_framerate TEXT, stream_video_scan_type TEXT, stream_video_full_resolution TEXT, '
|
||||||
|
'stream_video_dynamic_range TEXT, '
|
||||||
'stream_audio_decision TEXT, stream_audio_codec TEXT, stream_audio_bitrate INTEGER, stream_audio_channels INTEGER, '
|
'stream_audio_decision TEXT, stream_audio_codec TEXT, stream_audio_bitrate INTEGER, stream_audio_channels INTEGER, '
|
||||||
'subtitles INTEGER, stream_subtitle_decision TEXT, stream_subtitle_codec TEXT, '
|
'subtitles INTEGER, stream_subtitle_decision TEXT, stream_subtitle_codec TEXT, '
|
||||||
'transcode_protocol TEXT, transcode_container TEXT, '
|
'transcode_protocol TEXT, transcode_container TEXT, '
|
||||||
@@ -620,7 +625,7 @@ def dbcheck():
|
|||||||
'video_decision TEXT, audio_decision TEXT, transcode_decision TEXT, duration INTEGER DEFAULT 0, '
|
'video_decision TEXT, audio_decision TEXT, transcode_decision TEXT, duration INTEGER DEFAULT 0, '
|
||||||
'container TEXT, bitrate INTEGER, width INTEGER, height INTEGER, video_bitrate INTEGER, video_bit_depth INTEGER, '
|
'container TEXT, bitrate INTEGER, width INTEGER, height INTEGER, video_bitrate INTEGER, video_bit_depth INTEGER, '
|
||||||
'video_codec TEXT, video_codec_level TEXT, video_width INTEGER, video_height INTEGER, video_resolution TEXT, '
|
'video_codec TEXT, video_codec_level TEXT, video_width INTEGER, video_height INTEGER, video_resolution TEXT, '
|
||||||
'video_framerate TEXT, video_scan_type TEXT, video_full_resolution TEXT, aspect_ratio TEXT, '
|
'video_framerate TEXT, video_scan_type TEXT, video_full_resolution TEXT, video_dynamic_range TEXT, aspect_ratio TEXT, '
|
||||||
'audio_bitrate INTEGER, audio_codec TEXT, audio_channels INTEGER, transcode_protocol TEXT, '
|
'audio_bitrate INTEGER, audio_codec TEXT, audio_channels INTEGER, transcode_protocol TEXT, '
|
||||||
'transcode_container TEXT, transcode_video_codec TEXT, transcode_audio_codec TEXT, '
|
'transcode_container TEXT, transcode_video_codec TEXT, transcode_audio_codec TEXT, '
|
||||||
'transcode_audio_channels INTEGER, transcode_width INTEGER, transcode_height INTEGER, '
|
'transcode_audio_channels INTEGER, transcode_width INTEGER, transcode_height INTEGER, '
|
||||||
@@ -630,7 +635,7 @@ def dbcheck():
|
|||||||
'stream_container TEXT, stream_container_decision TEXT, stream_bitrate INTEGER, '
|
'stream_container TEXT, stream_container_decision TEXT, stream_bitrate INTEGER, '
|
||||||
'stream_video_decision TEXT, stream_video_bitrate INTEGER, stream_video_codec TEXT, stream_video_codec_level TEXT, '
|
'stream_video_decision TEXT, stream_video_bitrate INTEGER, stream_video_codec TEXT, stream_video_codec_level TEXT, '
|
||||||
'stream_video_bit_depth INTEGER, stream_video_height INTEGER, stream_video_width INTEGER, stream_video_resolution TEXT, '
|
'stream_video_bit_depth INTEGER, stream_video_height INTEGER, stream_video_width INTEGER, stream_video_resolution TEXT, '
|
||||||
'stream_video_framerate TEXT, stream_video_scan_type TEXT, stream_video_full_resolution TEXT, '
|
'stream_video_framerate TEXT, stream_video_scan_type TEXT, stream_video_full_resolution TEXT, stream_video_dynamic_range TEXT, '
|
||||||
'stream_audio_decision TEXT, stream_audio_codec TEXT, stream_audio_bitrate INTEGER, stream_audio_channels INTEGER, '
|
'stream_audio_decision TEXT, stream_audio_codec TEXT, stream_audio_bitrate INTEGER, stream_audio_channels INTEGER, '
|
||||||
'stream_subtitle_decision TEXT, stream_subtitle_codec TEXT, stream_subtitle_container TEXT, stream_subtitle_forced INTEGER, '
|
'stream_subtitle_decision TEXT, stream_subtitle_codec TEXT, stream_subtitle_container TEXT, stream_subtitle_forced INTEGER, '
|
||||||
'subtitles INTEGER, subtitle_codec TEXT, synced_version INTEGER, synced_version_profile TEXT, '
|
'subtitles INTEGER, subtitle_codec TEXT, synced_version INTEGER, synced_version_profile TEXT, '
|
||||||
@@ -1203,6 +1208,18 @@ def dbcheck():
|
|||||||
'ALTER TABLE sessions ADD COLUMN stream_video_full_resolution TEXT'
|
'ALTER TABLE sessions ADD COLUMN stream_video_full_resolution TEXT'
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# Upgrade sessions table from earlier versions
|
||||||
|
try:
|
||||||
|
c_db.execute('SELECT video_dynamic_range FROM sessions')
|
||||||
|
except sqlite3.OperationalError:
|
||||||
|
logger.debug(u"Altering database. Updating database table sessions.")
|
||||||
|
c_db.execute(
|
||||||
|
'ALTER TABLE sessions ADD COLUMN video_dynamic_range TEXT'
|
||||||
|
)
|
||||||
|
c_db.execute(
|
||||||
|
'ALTER TABLE sessions ADD COLUMN stream_video_dynamic_range TEXT'
|
||||||
|
)
|
||||||
|
|
||||||
# Upgrade session_history table from earlier versions
|
# Upgrade session_history table from earlier versions
|
||||||
try:
|
try:
|
||||||
c_db.execute('SELECT reference_id FROM session_history')
|
c_db.execute('SELECT reference_id FROM session_history')
|
||||||
@@ -1541,6 +1558,17 @@ def dbcheck():
|
|||||||
'ELSE stream_video_resolution || "p" END)'
|
'ELSE stream_video_resolution || "p" END)'
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# Upgrade session_history_media_info table from earlier versions
|
||||||
|
try:
|
||||||
|
c_db.execute('SELECT video_dynamic_range FROM session_history_media_info')
|
||||||
|
except sqlite3.OperationalError:
|
||||||
|
logger.debug(u"Altering database. Updating database table session_history_media_info.")
|
||||||
|
c_db.execute(
|
||||||
|
'ALTER TABLE session_history_media_info ADD COLUMN video_dynamic_range TEXT '
|
||||||
|
)
|
||||||
|
c_db.execute(
|
||||||
|
'ALTER TABLE session_history_media_info ADD COLUMN stream_video_dynamic_range TEXT '
|
||||||
|
)
|
||||||
# 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')
|
||||||
|
@@ -78,6 +78,7 @@ class ActivityProcessor(object):
|
|||||||
'video_framerate': session.get('video_framerate', ''),
|
'video_framerate': session.get('video_framerate', ''),
|
||||||
'video_scan_type': session.get('video_scan_type', ''),
|
'video_scan_type': session.get('video_scan_type', ''),
|
||||||
'video_full_resolution': session.get('video_full_resolution', ''),
|
'video_full_resolution': session.get('video_full_resolution', ''),
|
||||||
|
'video_dynamic_range': session.get('video_dynamic_range', ''),
|
||||||
'aspect_ratio': session.get('aspect_ratio', ''),
|
'aspect_ratio': session.get('aspect_ratio', ''),
|
||||||
'audio_codec': session.get('audio_codec', ''),
|
'audio_codec': session.get('audio_codec', ''),
|
||||||
'audio_bitrate': session.get('audio_bitrate', ''),
|
'audio_bitrate': session.get('audio_bitrate', ''),
|
||||||
@@ -110,6 +111,7 @@ class ActivityProcessor(object):
|
|||||||
'stream_video_framerate': session.get('stream_video_framerate', ''),
|
'stream_video_framerate': session.get('stream_video_framerate', ''),
|
||||||
'stream_video_scan_type': session.get('stream_video_scan_type', ''),
|
'stream_video_scan_type': session.get('stream_video_scan_type', ''),
|
||||||
'stream_video_full_resolution': session.get('stream_video_full_resolution', ''),
|
'stream_video_full_resolution': session.get('stream_video_full_resolution', ''),
|
||||||
|
'stream_video_dynamic_range': session.get('stream_video_dynamic_range', ''),
|
||||||
'stream_audio_decision': session.get('stream_audio_decision', ''),
|
'stream_audio_decision': session.get('stream_audio_decision', ''),
|
||||||
'stream_audio_codec': session.get('stream_audio_codec', ''),
|
'stream_audio_codec': session.get('stream_audio_codec', ''),
|
||||||
'stream_audio_bitrate': session.get('stream_audio_bitrate', ''),
|
'stream_audio_bitrate': session.get('stream_audio_bitrate', ''),
|
||||||
@@ -353,6 +355,7 @@ class ActivityProcessor(object):
|
|||||||
'video_framerate': session['video_framerate'],
|
'video_framerate': session['video_framerate'],
|
||||||
'video_scan_type': session['video_scan_type'],
|
'video_scan_type': session['video_scan_type'],
|
||||||
'video_full_resolution': session['video_full_resolution'],
|
'video_full_resolution': session['video_full_resolution'],
|
||||||
|
'video_dynamic_range': session['video_dynamic_range'],
|
||||||
'aspect_ratio': session['aspect_ratio'],
|
'aspect_ratio': session['aspect_ratio'],
|
||||||
'audio_codec': session['audio_codec'],
|
'audio_codec': session['audio_codec'],
|
||||||
'audio_bitrate': session['audio_bitrate'],
|
'audio_bitrate': session['audio_bitrate'],
|
||||||
@@ -387,6 +390,7 @@ class ActivityProcessor(object):
|
|||||||
'stream_video_framerate': session['stream_video_framerate'],
|
'stream_video_framerate': session['stream_video_framerate'],
|
||||||
'stream_video_scan_type': session['stream_video_scan_type'],
|
'stream_video_scan_type': session['stream_video_scan_type'],
|
||||||
'stream_video_full_resolution': session['stream_video_full_resolution'],
|
'stream_video_full_resolution': session['stream_video_full_resolution'],
|
||||||
|
'stream_video_dynamic_range': session['stream_video_dynamic_range'],
|
||||||
'stream_audio_decision': session['stream_audio_decision'],
|
'stream_audio_decision': session['stream_audio_decision'],
|
||||||
'stream_audio_codec': session['stream_audio_codec'],
|
'stream_audio_codec': session['stream_audio_codec'],
|
||||||
'stream_audio_bitrate': session['stream_audio_bitrate'],
|
'stream_audio_bitrate': session['stream_audio_bitrate'],
|
||||||
|
@@ -54,7 +54,9 @@ PLATFORM_NAME_OVERRIDES = {
|
|||||||
'Mystery 3': 'Playstation 3',
|
'Mystery 3': 'Playstation 3',
|
||||||
'Mystery 4': 'Playstation 4',
|
'Mystery 4': 'Playstation 4',
|
||||||
'Mystery 5': 'Xbox 360',
|
'Mystery 5': 'Xbox 360',
|
||||||
'WebMAF': 'Playstation 4'
|
'WebMAF': 'Playstation 4',
|
||||||
|
'windows': 'Windows',
|
||||||
|
'osx': 'macOS'
|
||||||
}
|
}
|
||||||
|
|
||||||
PMS_PLATFORM_NAME_OVERRIDES = {
|
PMS_PLATFORM_NAME_OVERRIDES = {
|
||||||
@@ -361,6 +363,12 @@ NOTIFICATION_PARAMETERS = [
|
|||||||
{'name': 'Stream Video Codec Level', 'type': 'int', 'value': 'stream_video_codec_level', 'description': 'The video codec level of the stream.'},
|
{'name': 'Stream Video Codec Level', 'type': 'int', 'value': 'stream_video_codec_level', 'description': 'The video codec level of the stream.'},
|
||||||
{'name': 'Stream Video Bitrate', 'type': 'int', 'value': 'stream_video_bitrate', 'description': 'The video bitrate (in kbps) of the stream.'},
|
{'name': 'Stream Video Bitrate', 'type': 'int', 'value': 'stream_video_bitrate', 'description': 'The video bitrate (in kbps) of the stream.'},
|
||||||
{'name': 'Stream Video Bit Depth', 'type': 'int', 'value': 'stream_video_bit_depth', 'description': 'The video bit depth of the stream.'},
|
{'name': 'Stream Video Bit Depth', 'type': 'int', 'value': 'stream_video_bit_depth', 'description': 'The video bit depth of the stream.'},
|
||||||
|
{'name': 'Stream Video Chroma Subsampling', 'type': 'str', 'value': 'stream_video_chroma_subsampling', 'description': 'The video chroma subsampling of the stream.'},
|
||||||
|
{'name': 'Stream Video Color Primaries', 'type': 'srt', 'value': 'stream_video_color_primaries', 'description': 'The video color primaries of the stream.'},
|
||||||
|
{'name': 'Stream Video Color Range', 'type': 'srt', 'value': 'stream_video_color_range', 'description': 'The video color range of the stream.'},
|
||||||
|
{'name': 'Stream Video Color Space', 'type': 'str', 'value': 'stream_video_color_space', 'description': 'The video color space of the stream.'},
|
||||||
|
{'name': 'Stream Video Color Transfer Function', 'type': 'str', 'value': 'stream_video_color_trc', 'description': 'The video transfer function of the stream.'},
|
||||||
|
{'name': 'Stream Video Dynamic Range', 'type': 'str', 'value': 'stream_video_dynamic_range', 'description': 'The video dynamic range of the stream.', 'example': 'HDR or SDR'},
|
||||||
{'name': 'Stream Video Framerate', 'type': 'str', 'value': 'stream_video_framerate', 'description': 'The video framerate of the stream.'},
|
{'name': 'Stream Video Framerate', 'type': 'str', 'value': 'stream_video_framerate', 'description': 'The video framerate of the stream.'},
|
||||||
{'name': 'Stream Video Full Resolution', 'type': 'str', 'value': 'stream_video_full_resolution', 'description': 'The video resolution of the stream with scan type.'},
|
{'name': 'Stream Video Full Resolution', 'type': 'str', 'value': 'stream_video_full_resolution', 'description': 'The video resolution of the stream with scan type.'},
|
||||||
{'name': 'Stream Video Ref Frames', 'type': 'int', 'value': 'stream_video_ref_frames', 'description': 'The video reference frames of the stream.'},
|
{'name': 'Stream Video Ref Frames', 'type': 'int', 'value': 'stream_video_ref_frames', 'description': 'The video reference frames of the stream.'},
|
||||||
@@ -468,6 +476,12 @@ NOTIFICATION_PARAMETERS = [
|
|||||||
{'name': 'Video Codec Level', 'type': 'int', 'value': 'video_codec_level', 'description': 'The video codec level of the original media.'},
|
{'name': 'Video Codec Level', 'type': 'int', 'value': 'video_codec_level', 'description': 'The video codec level of the original media.'},
|
||||||
{'name': 'Video Bitrate', 'type': 'int', 'value': 'video_bitrate', 'description': 'The video bitrate of the original media.'},
|
{'name': 'Video Bitrate', 'type': 'int', 'value': 'video_bitrate', 'description': 'The video bitrate of the original media.'},
|
||||||
{'name': 'Video Bit Depth', 'type': 'int', 'value': 'video_bit_depth', 'description': 'The video bit depth of the original media.'},
|
{'name': 'Video Bit Depth', 'type': 'int', 'value': 'video_bit_depth', 'description': 'The video bit depth of the original media.'},
|
||||||
|
{'name': 'Video Chroma Subsampling', 'type': 'str', 'value': 'video_chroma_subsampling', 'description': 'The video chroma subsampling of the original media.'},
|
||||||
|
{'name': 'Video Color Primaries', 'type': 'srt', 'value': 'video_color_primaries', 'description': 'The video color primaries of the original media.'},
|
||||||
|
{'name': 'Video Color Range', 'type': 'srt', 'value': 'video_color_range', 'description': 'The video color range of the original media.'},
|
||||||
|
{'name': 'Video Color Space', 'type': 'str', 'value': 'video_color_space', 'description': 'The video color space of the original media.'},
|
||||||
|
{'name': 'Video Color Transfer Function', 'type': 'str', 'value': 'video_color_trc', 'description': 'The video transfer function of the original media.'},
|
||||||
|
{'name': 'Video Dynamic Range', 'type': 'str', 'value': 'video_dynamic_range', 'description': 'The video dynamic range of the original media.', 'example': 'HDR or SDR'},
|
||||||
{'name': 'Video Framerate', 'type': 'str', 'value': 'video_framerate', 'description': 'The video framerate of the original media.'},
|
{'name': 'Video Framerate', 'type': 'str', 'value': 'video_framerate', 'description': 'The video framerate of the original media.'},
|
||||||
{'name': 'Video Full Resolution', 'type': 'str', 'value': 'video_full_resolution', 'description': 'The video resolution of the original media with scan type.'},
|
{'name': 'Video Full Resolution', 'type': 'str', 'value': 'video_full_resolution', 'description': 'The video resolution of the original media with scan type.'},
|
||||||
{'name': 'Video Ref Frames', 'type': 'int', 'value': 'video_ref_frames', 'description': 'The video reference frames of the original media.'},
|
{'name': 'Video Ref Frames', 'type': 'int', 'value': 'video_ref_frames', 'description': 'The video reference frames of the original media.'},
|
||||||
|
@@ -603,6 +603,7 @@ _CONFIG_DEFINITIONS = {
|
|||||||
'UPDATE_LABELS': (int, 'General', 1),
|
'UPDATE_LABELS': (int, 'General', 1),
|
||||||
'UPDATE_LIBRARIES_DB_NOTIFY': (int, 'General', 1),
|
'UPDATE_LIBRARIES_DB_NOTIFY': (int, 'General', 1),
|
||||||
'UPDATE_NOTIFIERS_DB': (int, 'General', 1),
|
'UPDATE_NOTIFIERS_DB': (int, 'General', 1),
|
||||||
|
'VERBOSE_LOGS': (int, 'Advanced', 1),
|
||||||
'VERIFY_SSL_CERT': (bool_int, 'Advanced', 1),
|
'VERIFY_SSL_CERT': (bool_int, 'Advanced', 1),
|
||||||
'VIDEO_LOGGING_ENABLE': (int, 'Monitoring', 1),
|
'VIDEO_LOGGING_ENABLE': (int, 'Monitoring', 1),
|
||||||
'WEBSOCKET_MONITOR_PING_PONG': (int, 'Advanced', 0),
|
'WEBSOCKET_MONITOR_PING_PONG': (int, 'Advanced', 0),
|
||||||
|
@@ -878,11 +878,12 @@ class DataFactory(object):
|
|||||||
query = 'SELECT bitrate, video_full_resolution, ' \
|
query = 'SELECT bitrate, video_full_resolution, ' \
|
||||||
'optimized_version, optimized_version_profile, optimized_version_title, ' \
|
'optimized_version, optimized_version_profile, optimized_version_title, ' \
|
||||||
'synced_version, synced_version_profile, ' \
|
'synced_version, synced_version_profile, ' \
|
||||||
'container, video_codec, video_bitrate, video_width, video_height, video_framerate, aspect_ratio, ' \
|
'container, video_codec, video_bitrate, video_width, video_height, video_framerate, ' \
|
||||||
|
'video_dynamic_range, aspect_ratio, ' \
|
||||||
'audio_codec, audio_bitrate, audio_channels, subtitle_codec, ' \
|
'audio_codec, audio_bitrate, audio_channels, subtitle_codec, ' \
|
||||||
'stream_bitrate, stream_video_full_resolution, quality_profile, stream_container_decision, stream_container, ' \
|
'stream_bitrate, stream_video_full_resolution, quality_profile, stream_container_decision, stream_container, ' \
|
||||||
'stream_video_decision, stream_video_codec, stream_video_bitrate, stream_video_width, stream_video_height, ' \
|
'stream_video_decision, stream_video_codec, stream_video_bitrate, stream_video_width, stream_video_height, ' \
|
||||||
'stream_video_framerate, ' \
|
'stream_video_framerate, stream_video_dynamic_range, ' \
|
||||||
'stream_audio_decision, stream_audio_codec, stream_audio_bitrate, stream_audio_channels, ' \
|
'stream_audio_decision, stream_audio_codec, stream_audio_bitrate, stream_audio_channels, ' \
|
||||||
'subtitles, stream_subtitle_decision, stream_subtitle_codec, ' \
|
'subtitles, stream_subtitle_decision, stream_subtitle_codec, ' \
|
||||||
'transcode_hw_decoding, transcode_hw_encoding, ' \
|
'transcode_hw_decoding, transcode_hw_encoding, ' \
|
||||||
@@ -899,11 +900,12 @@ class DataFactory(object):
|
|||||||
query = 'SELECT bitrate, video_full_resolution, ' \
|
query = 'SELECT bitrate, video_full_resolution, ' \
|
||||||
'optimized_version, optimized_version_profile, optimized_version_title, ' \
|
'optimized_version, optimized_version_profile, optimized_version_title, ' \
|
||||||
'synced_version, synced_version_profile, ' \
|
'synced_version, synced_version_profile, ' \
|
||||||
'container, video_codec, video_bitrate, video_width, video_height, video_framerate, aspect_ratio, ' \
|
'container, video_codec, video_bitrate, video_width, video_height, video_framerate, ' \
|
||||||
|
'video_dynamic_range, aspect_ratio, ' \
|
||||||
'audio_codec, audio_bitrate, audio_channels, subtitle_codec, ' \
|
'audio_codec, audio_bitrate, audio_channels, subtitle_codec, ' \
|
||||||
'stream_bitrate, stream_video_full_resolution, quality_profile, stream_container_decision, stream_container, ' \
|
'stream_bitrate, stream_video_full_resolution, quality_profile, stream_container_decision, stream_container, ' \
|
||||||
'stream_video_decision, stream_video_codec, stream_video_bitrate, stream_video_width, stream_video_height, ' \
|
'stream_video_decision, stream_video_codec, stream_video_bitrate, stream_video_width, stream_video_height, ' \
|
||||||
'stream_video_framerate, ' \
|
'stream_video_framerate, stream_video_dynamic_range, ' \
|
||||||
'stream_audio_decision, stream_audio_codec, stream_audio_bitrate, stream_audio_channels, ' \
|
'stream_audio_decision, stream_audio_codec, stream_audio_bitrate, stream_audio_channels, ' \
|
||||||
'subtitles, stream_subtitle_decision, stream_subtitle_codec, ' \
|
'subtitles, stream_subtitle_decision, stream_subtitle_codec, ' \
|
||||||
'transcode_hw_decoding, transcode_hw_encoding, ' \
|
'transcode_hw_decoding, transcode_hw_encoding, ' \
|
||||||
@@ -950,6 +952,7 @@ class DataFactory(object):
|
|||||||
'video_width': item['video_width'],
|
'video_width': item['video_width'],
|
||||||
'video_height': item['video_height'],
|
'video_height': item['video_height'],
|
||||||
'video_framerate': item['video_framerate'],
|
'video_framerate': item['video_framerate'],
|
||||||
|
'video_dynamic_range': item['video_dynamic_range'],
|
||||||
'aspect_ratio': item['aspect_ratio'],
|
'aspect_ratio': item['aspect_ratio'],
|
||||||
'audio_codec': item['audio_codec'],
|
'audio_codec': item['audio_codec'],
|
||||||
'audio_bitrate': item['audio_bitrate'],
|
'audio_bitrate': item['audio_bitrate'],
|
||||||
@@ -966,6 +969,7 @@ class DataFactory(object):
|
|||||||
'stream_video_width': item['stream_video_width'],
|
'stream_video_width': item['stream_video_width'],
|
||||||
'stream_video_height': item['stream_video_height'],
|
'stream_video_height': item['stream_video_height'],
|
||||||
'stream_video_framerate': item['stream_video_framerate'],
|
'stream_video_framerate': item['stream_video_framerate'],
|
||||||
|
'stream_video_dynamic_range': item['stream_video_dynamic_range'],
|
||||||
'stream_audio_decision': item['stream_audio_decision'],
|
'stream_audio_decision': item['stream_audio_decision'],
|
||||||
'stream_audio_codec': item['stream_audio_codec'],
|
'stream_audio_codec': item['stream_audio_codec'],
|
||||||
'stream_audio_bitrate': item['stream_audio_bitrate'],
|
'stream_audio_bitrate': item['stream_audio_bitrate'],
|
||||||
|
@@ -14,6 +14,7 @@
|
|||||||
# along with Tautulli. If not, see <http://www.gnu.org/licenses/>.
|
# along with Tautulli. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
import base64
|
import base64
|
||||||
|
import certifi
|
||||||
import cloudinary
|
import cloudinary
|
||||||
from cloudinary.api import delete_resources_by_tag
|
from cloudinary.api import delete_resources_by_tag
|
||||||
from cloudinary.uploader import upload
|
from cloudinary.uploader import upload
|
||||||
@@ -21,7 +22,6 @@ from cloudinary.utils import cloudinary_url
|
|||||||
import datetime
|
import datetime
|
||||||
from functools import wraps
|
from functools import wraps
|
||||||
import geoip2.database, geoip2.errors
|
import geoip2.database, geoip2.errors
|
||||||
import gzip
|
|
||||||
import hashlib
|
import hashlib
|
||||||
import imghdr
|
import imghdr
|
||||||
from itertools import izip_longest
|
from itertools import izip_longest
|
||||||
@@ -34,12 +34,13 @@ from operator import itemgetter
|
|||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
import shlex
|
import shlex
|
||||||
|
import shutil
|
||||||
import socket
|
import socket
|
||||||
import sys
|
import sys
|
||||||
import tarfile
|
import tarfile
|
||||||
import time
|
import time
|
||||||
import unicodedata
|
import unicodedata
|
||||||
import urllib, urllib2
|
import urllib3
|
||||||
from xml.dom import minidom
|
from xml.dom import minidom
|
||||||
import xmltodict
|
import xmltodict
|
||||||
|
|
||||||
@@ -590,7 +591,8 @@ def update_geoip_db():
|
|||||||
now = int(time.time())
|
now = int(time.time())
|
||||||
if now - plexpy.CONFIG.GEOIP_DB_INSTALLED >= plexpy.CONFIG.GEOIP_DB_UPDATE_DAYS * 24 * 60 * 60:
|
if now - plexpy.CONFIG.GEOIP_DB_INSTALLED >= plexpy.CONFIG.GEOIP_DB_UPDATE_DAYS * 24 * 60 * 60:
|
||||||
return install_geoip_db(update=True)
|
return install_geoip_db(update=True)
|
||||||
logger.info(u"Tautulli Helpers :: GeoLite2 database already updated within the last 30 days.")
|
logger.info(u"Tautulli Helpers :: GeoLite2 database already updated within the last %s days."
|
||||||
|
% plexpy.CONFIG.GEOIP_DB_UPDATE_DAYS)
|
||||||
|
|
||||||
|
|
||||||
def install_geoip_db(update=False):
|
def install_geoip_db(update=False):
|
||||||
@@ -608,15 +610,21 @@ def install_geoip_db(update=False):
|
|||||||
geolite2_db = maxmind_db + '.mmdb'
|
geolite2_db = maxmind_db + '.mmdb'
|
||||||
geolite2_db_path = plexpy.CONFIG.GEOIP_DB or os.path.join(plexpy.DATA_DIR, geolite2_db)
|
geolite2_db_path = plexpy.CONFIG.GEOIP_DB or os.path.join(plexpy.DATA_DIR, geolite2_db)
|
||||||
|
|
||||||
|
# Check path ends with .mmdb
|
||||||
|
if os.path.splitext(geolite2_db_path)[1] != os.path.splitext(geolite2_db)[1]:
|
||||||
|
geolite2_db_path = os.path.join(geolite2_db_path, geolite2_db)
|
||||||
|
|
||||||
temp_gz = os.path.join(plexpy.CONFIG.CACHE_DIR, geolite2_gz)
|
temp_gz = os.path.join(plexpy.CONFIG.CACHE_DIR, geolite2_gz)
|
||||||
temp_md5 = os.path.join(plexpy.CONFIG.CACHE_DIR, geolite2_md5)
|
temp_md5 = os.path.join(plexpy.CONFIG.CACHE_DIR, geolite2_md5)
|
||||||
|
|
||||||
# Retrieve the GeoLite2 gzip file
|
# Retrieve the GeoLite2 gzip file
|
||||||
logger.debug(u"Tautulli Helpers :: Downloading GeoLite2 gzip file from MaxMind...")
|
logger.debug(u"Tautulli Helpers :: Downloading GeoLite2 gzip file from MaxMind...")
|
||||||
try:
|
try:
|
||||||
maxmind = urllib.URLopener()
|
maxmind = urllib3.PoolManager(cert_reqs='CERT_REQUIRED', ca_certs=certifi.where())
|
||||||
maxmind.retrieve(geolite2_db_url, temp_gz)
|
with maxmind.request('GET', geolite2_db_url, preload_content=False) as r_db, open(temp_gz, 'wb') as f_db:
|
||||||
maxmind.retrieve(geolite2_md5_url, temp_md5)
|
shutil.copyfileobj(r_db, f_db)
|
||||||
|
with maxmind.request('GET', geolite2_md5_url, preload_content=False) as r_md5, open(temp_md5, 'wb') as f_md5:
|
||||||
|
shutil.copyfileobj(r_md5, f_md5)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(u"Tautulli Helpers :: Failed to download GeoLite2 gzip file from MaxMind: %s" % e)
|
logger.error(u"Tautulli Helpers :: Failed to download GeoLite2 gzip file from MaxMind: %s" % e)
|
||||||
return False
|
return False
|
||||||
|
@@ -80,7 +80,7 @@ class BlacklistFilter(logging.Filter):
|
|||||||
Log filter for blacklisted tokens and passwords
|
Log filter for blacklisted tokens and passwords
|
||||||
"""
|
"""
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
pass
|
super(BlacklistFilter, self).__init__()
|
||||||
|
|
||||||
def filter(self, record):
|
def filter(self, record):
|
||||||
if not plexpy.CONFIG.LOG_BLACKLIST:
|
if not plexpy.CONFIG.LOG_BLACKLIST:
|
||||||
@@ -98,30 +98,29 @@ class BlacklistFilter(logging.Filter):
|
|||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
class PublicIPFilter(logging.Filter):
|
class RegexFilter(logging.Filter):
|
||||||
"""
|
"""
|
||||||
Log filter for public IP addresses
|
Base class for regex log filter
|
||||||
"""
|
"""
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
pass
|
super(RegexFilter, self).__init__()
|
||||||
|
|
||||||
|
self.regex = re.compile(r'')
|
||||||
|
|
||||||
def filter(self, record):
|
def filter(self, record):
|
||||||
if not plexpy.CONFIG.LOG_BLACKLIST:
|
if not plexpy.CONFIG.LOG_BLACKLIST:
|
||||||
return True
|
return True
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# Currently only checking for ipv4 addresses
|
matches = self.regex.findall(record.msg)
|
||||||
ipv4 = re.findall(r'[0-9]+(?:\.[0-9]+){3}(?!\d*-[a-z0-9]{6})', record.msg)
|
for match in matches:
|
||||||
for ip in ipv4:
|
record.msg = self.replace(record.msg, match)
|
||||||
if helpers.is_public_ip(ip):
|
|
||||||
record.msg = record.msg.replace(ip, ip.partition('.')[0] + '.***.***.***')
|
|
||||||
|
|
||||||
args = []
|
args = []
|
||||||
for arg in record.args:
|
for arg in record.args:
|
||||||
ipv4 = re.findall(r'[0-9]+(?:\.[0-9]+){3}(?!\d*-[a-z0-9]{6})', arg) if isinstance(arg, basestring) else []
|
matches = self.regex.findall(arg) if isinstance(arg, basestring) else []
|
||||||
for ip in ipv4:
|
for match in matches:
|
||||||
if helpers.is_public_ip(ip):
|
arg = self.replace(arg, match)
|
||||||
arg = arg.replace(ip, ip.partition('.')[0] + '.***.***.***')
|
|
||||||
args.append(arg)
|
args.append(arg)
|
||||||
record.args = tuple(args)
|
record.args = tuple(args)
|
||||||
except:
|
except:
|
||||||
@@ -129,31 +128,53 @@ class PublicIPFilter(logging.Filter):
|
|||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
def replace(self, text, match):
|
||||||
|
return text
|
||||||
|
|
||||||
class PlexTokenFilter(logging.Filter):
|
|
||||||
|
class PublicIPFilter(RegexFilter):
|
||||||
|
"""
|
||||||
|
Log filter for public IP addresses
|
||||||
|
"""
|
||||||
|
def __init__(self):
|
||||||
|
super(PublicIPFilter, self).__init__()
|
||||||
|
|
||||||
|
# Currently only checking for ipv4 addresses
|
||||||
|
self.regex = re.compile(r'[0-9]+(?:\.[0-9]+){3}(?!\d*-[a-z0-9]{6})')
|
||||||
|
|
||||||
|
def replace(self, text, ip):
|
||||||
|
if helpers.is_public_ip(ip):
|
||||||
|
return text.replace(ip, ip.partition('.')[0] + '.***.***.***')
|
||||||
|
return text
|
||||||
|
|
||||||
|
|
||||||
|
class EmailFilter(RegexFilter):
|
||||||
|
"""
|
||||||
|
Log filter for email addresses
|
||||||
|
"""
|
||||||
|
def __init__(self):
|
||||||
|
super(EmailFilter, self).__init__()
|
||||||
|
|
||||||
|
self.regex = re.compile(r'([a-z0-9!#$%&\'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&\'*+/=?^_`{|}~-]+)*@'
|
||||||
|
r'(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?)',
|
||||||
|
re.IGNORECASE)
|
||||||
|
|
||||||
|
def replace(self, text, email):
|
||||||
|
email_parts = email.partition('@')
|
||||||
|
return text.replace(email, email_parts[0][:2] + 8 * '*' + email_parts[1] + 8 * '*')
|
||||||
|
|
||||||
|
|
||||||
|
class PlexTokenFilter(RegexFilter):
|
||||||
"""
|
"""
|
||||||
Log filter for X-Plex-Token
|
Log filter for X-Plex-Token
|
||||||
"""
|
"""
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
pass
|
super(PlexTokenFilter, self).__init__()
|
||||||
|
|
||||||
def filter(self, record):
|
self.regex = re.compile(r'X-Plex-Token(?:=|%3D)([a-zA-Z0-9]+)')
|
||||||
try:
|
|
||||||
tokens = re.findall(r'X-Plex-Token(?:=|%3D)([a-zA-Z0-9]+)', record.msg)
|
|
||||||
for token in tokens:
|
|
||||||
record.msg = record.msg.replace(token, 8 * '*' + token[-2:])
|
|
||||||
|
|
||||||
args = []
|
def replace(self, text, token):
|
||||||
for arg in record.args:
|
return text.replace(token, 8 * '*' + token[-2:])
|
||||||
tokens = re.findall(r'X-Plex-Token(?:=|%3D)([a-zA-Z0-9]+)', arg) if isinstance(arg, basestring) else []
|
|
||||||
for token in tokens:
|
|
||||||
arg = arg.replace(token, 8 * '*' + token[-2:])
|
|
||||||
args.append(arg)
|
|
||||||
record.args = tuple(args)
|
|
||||||
except:
|
|
||||||
pass
|
|
||||||
|
|
||||||
return True
|
|
||||||
|
|
||||||
|
|
||||||
@contextlib.contextmanager
|
@contextlib.contextmanager
|
||||||
@@ -294,6 +315,7 @@ def initLogger(console=False, log_dir=False, verbose=False):
|
|||||||
for handler in logger.handlers + logger_api.handlers + logger_plex_websocket.handlers:
|
for handler in logger.handlers + logger_api.handlers + logger_plex_websocket.handlers:
|
||||||
handler.addFilter(BlacklistFilter())
|
handler.addFilter(BlacklistFilter())
|
||||||
handler.addFilter(PublicIPFilter())
|
handler.addFilter(PublicIPFilter())
|
||||||
|
handler.addFilter(EmailFilter())
|
||||||
handler.addFilter(PlexTokenFilter())
|
handler.addFilter(PlexTokenFilter())
|
||||||
|
|
||||||
# Install exception hooks
|
# Install exception hooks
|
||||||
|
@@ -830,6 +830,12 @@ def build_media_notify_params(notify_action=None, session=None, timeline=None, m
|
|||||||
'stream_video_codec_level': notify_params['stream_video_codec_level'],
|
'stream_video_codec_level': notify_params['stream_video_codec_level'],
|
||||||
'stream_video_bitrate': notify_params['stream_video_bitrate'],
|
'stream_video_bitrate': notify_params['stream_video_bitrate'],
|
||||||
'stream_video_bit_depth': notify_params['stream_video_bit_depth'],
|
'stream_video_bit_depth': notify_params['stream_video_bit_depth'],
|
||||||
|
'stream_video_chroma_subsampling': notify_params['stream_video_chroma_subsampling'],
|
||||||
|
'stream_video_color_primaries': notify_params['stream_video_color_primaries'],
|
||||||
|
'stream_video_color_range': notify_params['stream_video_color_range'],
|
||||||
|
'stream_video_color_space': notify_params['stream_video_color_space'],
|
||||||
|
'stream_video_color_trc': notify_params['stream_video_color_trc'],
|
||||||
|
'stream_video_dynamic_range': notify_params['stream_video_dynamic_range'],
|
||||||
'stream_video_framerate': notify_params['stream_video_framerate'],
|
'stream_video_framerate': notify_params['stream_video_framerate'],
|
||||||
'stream_video_full_resolution': notify_params['stream_video_full_resolution'],
|
'stream_video_full_resolution': notify_params['stream_video_full_resolution'],
|
||||||
'stream_video_ref_frames': notify_params['stream_video_ref_frames'],
|
'stream_video_ref_frames': notify_params['stream_video_ref_frames'],
|
||||||
@@ -940,6 +946,12 @@ def build_media_notify_params(notify_action=None, session=None, timeline=None, m
|
|||||||
'video_codec_level': notify_params['video_codec_level'],
|
'video_codec_level': notify_params['video_codec_level'],
|
||||||
'video_bitrate': notify_params['video_bitrate'],
|
'video_bitrate': notify_params['video_bitrate'],
|
||||||
'video_bit_depth': notify_params['video_bit_depth'],
|
'video_bit_depth': notify_params['video_bit_depth'],
|
||||||
|
'video_chroma_subsampling': notify_params['video_chroma_subsampling'],
|
||||||
|
'video_color_primaries': notify_params['video_color_primaries'],
|
||||||
|
'video_color_range': notify_params['video_color_range'],
|
||||||
|
'video_color_space': notify_params['video_color_space'],
|
||||||
|
'video_color_trc': notify_params['video_color_trc'],
|
||||||
|
'video_dynamic_range': notify_params['video_dynamic_range'],
|
||||||
'video_framerate': notify_params['video_framerate'],
|
'video_framerate': notify_params['video_framerate'],
|
||||||
'video_full_resolution': notify_params['video_full_resolution'],
|
'video_full_resolution': notify_params['video_full_resolution'],
|
||||||
'video_ref_frames': notify_params['video_ref_frames'],
|
'video_ref_frames': notify_params['video_ref_frames'],
|
||||||
|
@@ -3416,9 +3416,9 @@ class TELEGRAM(Notifier):
|
|||||||
data = {'chat_id': self.config['chat_id']}
|
data = {'chat_id': self.config['chat_id']}
|
||||||
|
|
||||||
if self.config['incl_subject']:
|
if self.config['incl_subject']:
|
||||||
text = subject.encode('utf-8') + '\r\n' + body.encode('utf-8')
|
text = subject + '\r\n' + body
|
||||||
else:
|
else:
|
||||||
text = body.encode('utf-8')
|
text = body
|
||||||
|
|
||||||
if self.config['html_support']:
|
if self.config['html_support']:
|
||||||
data['parse_mode'] = 'HTML'
|
data['parse_mode'] = 'HTML'
|
||||||
@@ -3442,7 +3442,7 @@ class TELEGRAM(Notifier):
|
|||||||
if len(text) > 1024:
|
if len(text) > 1024:
|
||||||
data['disable_notification'] = True
|
data['disable_notification'] = True
|
||||||
else:
|
else:
|
||||||
data['caption'] = text
|
data['caption'] = text.encode('utf-8')
|
||||||
|
|
||||||
r = self.make_request('https://api.telegram.org/bot{}/sendPhoto'.format(self.config['bot_token']),
|
r = self.make_request('https://api.telegram.org/bot{}/sendPhoto'.format(self.config['bot_token']),
|
||||||
data=data, files=files)
|
data=data, files=files)
|
||||||
@@ -3450,7 +3450,7 @@ class TELEGRAM(Notifier):
|
|||||||
if not data.pop('disable_notification', None):
|
if not data.pop('disable_notification', None):
|
||||||
return r
|
return r
|
||||||
|
|
||||||
data['text'] = text
|
data['text'] = (text[:4093] + (text[4093:] and '...')).encode('utf-8')
|
||||||
|
|
||||||
if self.config['disable_web_preview']:
|
if self.config['disable_web_preview']:
|
||||||
data['disable_web_page_preview'] = True
|
data['disable_web_page_preview'] = True
|
||||||
@@ -3636,7 +3636,12 @@ class WEBHOOK(Notifier):
|
|||||||
if webhook_headers:
|
if webhook_headers:
|
||||||
headers.update(webhook_headers)
|
headers.update(webhook_headers)
|
||||||
|
|
||||||
return self.make_request(self.config['hook'], method=self.config['method'], headers=headers, json=webhook_body)
|
if headers['Content-Type'] == 'application/json':
|
||||||
|
data = {'json': webhook_body}
|
||||||
|
else:
|
||||||
|
data = {'data': webhook_body}
|
||||||
|
|
||||||
|
return self.make_request(self.config['hook'], method=self.config['method'], headers=headers, **data)
|
||||||
|
|
||||||
def _return_config_options(self):
|
def _return_config_options(self):
|
||||||
config_option = [{'label': 'Webhook URL',
|
config_option = [{'label': 'Webhook URL',
|
||||||
|
@@ -1262,6 +1262,11 @@ class PmsConnect(object):
|
|||||||
'video_codec_level': helpers.get_xml_attr(stream, 'level'),
|
'video_codec_level': helpers.get_xml_attr(stream, 'level'),
|
||||||
'video_bitrate': helpers.get_xml_attr(stream, 'bitrate'),
|
'video_bitrate': helpers.get_xml_attr(stream, 'bitrate'),
|
||||||
'video_bit_depth': helpers.get_xml_attr(stream, 'bitDepth'),
|
'video_bit_depth': helpers.get_xml_attr(stream, 'bitDepth'),
|
||||||
|
'video_chroma_subsampling': helpers.get_xml_attr(stream, 'chromaSubsampling'),
|
||||||
|
'video_color_primaries': helpers.get_xml_attr(stream, 'colorPrimaries'),
|
||||||
|
'video_color_range': helpers.get_xml_attr(stream, 'colorRange'),
|
||||||
|
'video_color_space': helpers.get_xml_attr(stream, 'colorSpace'),
|
||||||
|
'video_color_trc': helpers.get_xml_attr(stream, 'colorTrc'),
|
||||||
'video_frame_rate': helpers.get_xml_attr(stream, 'frameRate'),
|
'video_frame_rate': helpers.get_xml_attr(stream, 'frameRate'),
|
||||||
'video_ref_frames': helpers.get_xml_attr(stream, 'refFrames'),
|
'video_ref_frames': helpers.get_xml_attr(stream, 'refFrames'),
|
||||||
'video_height': helpers.get_xml_attr(stream, 'height'),
|
'video_height': helpers.get_xml_attr(stream, 'height'),
|
||||||
@@ -1698,6 +1703,11 @@ class PmsConnect(object):
|
|||||||
video_id = helpers.get_xml_attr(video_stream_info, 'id')
|
video_id = helpers.get_xml_attr(video_stream_info, 'id')
|
||||||
video_details = {'stream_video_bitrate': helpers.get_xml_attr(video_stream_info, 'bitrate'),
|
video_details = {'stream_video_bitrate': helpers.get_xml_attr(video_stream_info, 'bitrate'),
|
||||||
'stream_video_bit_depth': helpers.get_xml_attr(video_stream_info, 'bitDepth'),
|
'stream_video_bit_depth': helpers.get_xml_attr(video_stream_info, 'bitDepth'),
|
||||||
|
'stream_video_chroma_subsampling': helpers.get_xml_attr(video_stream_info, 'chromaSubsampling'),
|
||||||
|
'stream_video_color_primaries': helpers.get_xml_attr(video_stream_info, 'colorPrimaries'),
|
||||||
|
'stream_video_color_range': helpers.get_xml_attr(video_stream_info, 'colorRange'),
|
||||||
|
'stream_video_color_space': helpers.get_xml_attr(video_stream_info, 'colorSpace'),
|
||||||
|
'stream_video_color_trc': helpers.get_xml_attr(video_stream_info, 'colorTrc'),
|
||||||
'stream_video_codec_level': helpers.get_xml_attr(video_stream_info, 'level'),
|
'stream_video_codec_level': helpers.get_xml_attr(video_stream_info, 'level'),
|
||||||
'stream_video_ref_frames': helpers.get_xml_attr(video_stream_info, 'refFrames'),
|
'stream_video_ref_frames': helpers.get_xml_attr(video_stream_info, 'refFrames'),
|
||||||
'stream_video_language': helpers.get_xml_attr(video_stream_info, 'language'),
|
'stream_video_language': helpers.get_xml_attr(video_stream_info, 'language'),
|
||||||
@@ -1708,6 +1718,11 @@ class PmsConnect(object):
|
|||||||
else:
|
else:
|
||||||
video_details = {'stream_video_bitrate': '',
|
video_details = {'stream_video_bitrate': '',
|
||||||
'stream_video_bit_depth': '',
|
'stream_video_bit_depth': '',
|
||||||
|
'stream_video_chroma_subsampling': '',
|
||||||
|
'stream_video_color_primaries': '',
|
||||||
|
'stream_video_color_range': '',
|
||||||
|
'stream_video_color_space': '',
|
||||||
|
'stream_video_color_trc': '',
|
||||||
'stream_video_codec_level': '',
|
'stream_video_codec_level': '',
|
||||||
'stream_video_ref_frames': '',
|
'stream_video_ref_frames': '',
|
||||||
'stream_video_language': '',
|
'stream_video_language': '',
|
||||||
@@ -1886,6 +1901,11 @@ class PmsConnect(object):
|
|||||||
'video_codec_level': '',
|
'video_codec_level': '',
|
||||||
'video_bitrate': '',
|
'video_bitrate': '',
|
||||||
'video_bit_depth': '',
|
'video_bit_depth': '',
|
||||||
|
'video_chroma_subsampling': '',
|
||||||
|
'video_color_primaries': '',
|
||||||
|
'video_color_range': '',
|
||||||
|
'video_color_space': '',
|
||||||
|
'video_color_trc': '',
|
||||||
'video_frame_rate': '',
|
'video_frame_rate': '',
|
||||||
'video_ref_frames': '',
|
'video_ref_frames': '',
|
||||||
'video_height': '',
|
'video_height': '',
|
||||||
@@ -1969,6 +1989,22 @@ class PmsConnect(object):
|
|||||||
stream_details['stream_video_resolution'],
|
stream_details['stream_video_resolution'],
|
||||||
stream_details['stream_video_resolution'] + (video_details['stream_video_scan_type'][:1] or 'p'))
|
stream_details['stream_video_resolution'] + (video_details['stream_video_scan_type'][:1] or 'p'))
|
||||||
|
|
||||||
|
if helpers.cast_to_int(source_video_details['video_bit_depth']) > 8 \
|
||||||
|
and source_video_details['video_color_space'] == 'bt2020nc':
|
||||||
|
stream_details['video_dynamic_range'] = 'HDR'
|
||||||
|
else:
|
||||||
|
stream_details['video_dynamic_range'] = 'SDR'
|
||||||
|
|
||||||
|
if video_details['stream_video_decision'] != 'transcode' \
|
||||||
|
or helpers.cast_to_int(video_details['stream_video_bit_depth']) > 8 \
|
||||||
|
and video_details['stream_video_color_space'] == 'bt2020nc':
|
||||||
|
stream_details['stream_video_dynamic_range'] = 'HDR'
|
||||||
|
else:
|
||||||
|
stream_details['stream_video_dynamic_range'] = 'SDR'
|
||||||
|
else:
|
||||||
|
stream_details['video_dynamic_range'] = ''
|
||||||
|
stream_details['stream_video_dynamic_range'] = ''
|
||||||
|
|
||||||
# Get the quality profile
|
# Get the quality profile
|
||||||
if media_type in ('movie', 'episode', 'clip') and 'stream_bitrate' in stream_details:
|
if media_type in ('movie', 'episode', 'clip') and 'stream_bitrate' in stream_details:
|
||||||
if sync_id:
|
if sync_id:
|
||||||
|
@@ -1,2 +1,2 @@
|
|||||||
PLEXPY_BRANCH = "master"
|
PLEXPY_BRANCH = "master"
|
||||||
PLEXPY_RELEASE_VERSION = "v2.1.41"
|
PLEXPY_RELEASE_VERSION = "v2.1.43"
|
||||||
|
@@ -158,13 +158,17 @@ def check_update(auto_update=False, notify=False):
|
|||||||
def check_github(auto_update=False, notify=False):
|
def check_github(auto_update=False, notify=False):
|
||||||
plexpy.COMMITS_BEHIND = 0
|
plexpy.COMMITS_BEHIND = 0
|
||||||
|
|
||||||
|
if plexpy.CONFIG.GIT_TOKEN:
|
||||||
|
headers = {'Authorization': 'token {}'.format(plexpy.CONFIG.GIT_TOKEN)}
|
||||||
|
else:
|
||||||
|
headers = {}
|
||||||
|
|
||||||
# Get the latest version available from github
|
# Get the latest version available from github
|
||||||
logger.info('Retrieving latest version information from GitHub')
|
logger.info('Retrieving latest version information from GitHub')
|
||||||
url = 'https://api.github.com/repos/%s/%s/commits/%s' % (plexpy.CONFIG.GIT_USER,
|
url = 'https://api.github.com/repos/%s/%s/commits/%s' % (plexpy.CONFIG.GIT_USER,
|
||||||
plexpy.CONFIG.GIT_REPO,
|
plexpy.CONFIG.GIT_REPO,
|
||||||
plexpy.CONFIG.GIT_BRANCH)
|
plexpy.CONFIG.GIT_BRANCH)
|
||||||
if plexpy.CONFIG.GIT_TOKEN: url = url + '?access_token=%s' % plexpy.CONFIG.GIT_TOKEN
|
version = request.request_json(url, headers=headers, timeout=20, validator=lambda x: type(x) == dict)
|
||||||
version = request.request_json(url, timeout=20, validator=lambda x: type(x) == dict)
|
|
||||||
|
|
||||||
if version is None:
|
if version is None:
|
||||||
logger.warn('Could not get the latest version from GitHub. Are you running a local development version?')
|
logger.warn('Could not get the latest version from GitHub. Are you running a local development version?')
|
||||||
@@ -187,8 +191,8 @@ def check_github(auto_update=False, notify=False):
|
|||||||
plexpy.CONFIG.GIT_REPO,
|
plexpy.CONFIG.GIT_REPO,
|
||||||
plexpy.LATEST_VERSION,
|
plexpy.LATEST_VERSION,
|
||||||
plexpy.CURRENT_VERSION)
|
plexpy.CURRENT_VERSION)
|
||||||
if plexpy.CONFIG.GIT_TOKEN: url = url + '?access_token=%s' % plexpy.CONFIG.GIT_TOKEN
|
commits = request.request_json(url, headers=headers, timeout=20, whitelist_status_code=404,
|
||||||
commits = request.request_json(url, timeout=20, whitelist_status_code=404, validator=lambda x: type(x) == dict)
|
validator=lambda x: type(x) == dict)
|
||||||
|
|
||||||
if commits is None:
|
if commits is None:
|
||||||
logger.warn('Could not get commits behind from GitHub.')
|
logger.warn('Could not get commits behind from GitHub.')
|
||||||
|
@@ -2667,8 +2667,11 @@ class WebInterface(object):
|
|||||||
@requireAuth(member_of("admin"))
|
@requireAuth(member_of("admin"))
|
||||||
def toggleVerbose(self, **kwargs):
|
def toggleVerbose(self, **kwargs):
|
||||||
plexpy.VERBOSE = not plexpy.VERBOSE
|
plexpy.VERBOSE = not plexpy.VERBOSE
|
||||||
logger.initLogger(console=not plexpy.QUIET,
|
|
||||||
log_dir=plexpy.CONFIG.LOG_DIR, verbose=plexpy.VERBOSE)
|
plexpy.CONFIG.__setattr__('VERBOSE_LOGS', plexpy.VERBOSE)
|
||||||
|
plexpy.CONFIG.write()
|
||||||
|
|
||||||
|
logger.initLogger(console=not plexpy.QUIET, log_dir=plexpy.CONFIG.LOG_DIR, verbose=plexpy.VERBOSE)
|
||||||
logger.info(u"Verbose toggled, set to %s", plexpy.VERBOSE)
|
logger.info(u"Verbose toggled, set to %s", plexpy.VERBOSE)
|
||||||
logger.debug(u"If you read this message, debug logging is available")
|
logger.debug(u"If you read this message, debug logging is available")
|
||||||
raise cherrypy.HTTPRedirect(plexpy.HTTP_ROOT + "logs")
|
raise cherrypy.HTTPRedirect(plexpy.HTTP_ROOT + "logs")
|
||||||
|
Reference in New Issue
Block a user