Compare commits
18 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
bc2f73d686 | ||
![]() |
645c2ecef6 | ||
![]() |
4d4a8ca3b2 | ||
![]() |
a98bc45c10 | ||
![]() |
b9d5e49a71 | ||
![]() |
e90390be67 | ||
![]() |
8ef671c9cb | ||
![]() |
8829516cae | ||
![]() |
d8e8dfbd45 | ||
![]() |
0b6d9a4890 | ||
![]() |
55ffd68023 | ||
![]() |
6380de3e6c | ||
![]() |
d6220a921a | ||
![]() |
10e421b9d4 | ||
![]() |
90056bcce2 | ||
![]() |
4740d0fbf3 | ||
![]() |
13374c9ded | ||
![]() |
2a03be1905 |
21
CHANGELOG.md
21
CHANGELOG.md
@@ -1,11 +1,30 @@
|
||||
# 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.
|
||||
* Change: Disable GeoLite2 database uninstall button when it is not installed.
|
||||
|
||||
|
||||
## v2.1.41 (2019-12-30)
|
||||
|
@@ -106,8 +106,8 @@ def main():
|
||||
plexpy.QUIET = True
|
||||
|
||||
# Do an intial setup of the logger.
|
||||
logger.initLogger(console=not plexpy.QUIET, log_dir=False,
|
||||
verbose=plexpy.VERBOSE)
|
||||
# Require verbose for pre-initilization to see critical errors
|
||||
logger.initLogger(console=not plexpy.QUIET, log_dir=False, verbose=True)
|
||||
|
||||
try:
|
||||
plexpy.SYS_TIMEZONE = tzlocal.get_localzone()
|
||||
|
@@ -226,17 +226,24 @@ DOCUMENTATION :: END
|
||||
<li class="dashboard-activity-info-item">
|
||||
<div class="sub-heading">Video</div>
|
||||
<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':
|
||||
<%
|
||||
hw_d = ' (HW)' if data['transcode_hw_decoding'] 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':
|
||||
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:
|
||||
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
|
||||
% elif data['media_type'] == 'photo':
|
||||
Direct Play (${data['width']}x${data['height']})
|
||||
@@ -248,12 +255,14 @@ DOCUMENTATION :: END
|
||||
<li class="dashboard-activity-info-item">
|
||||
<div class="sub-heading">Audio</div>
|
||||
<div class="sub-value" id="audio_decision-${sk}">
|
||||
% if data['stream_audio_decision'] == 'transcode':
|
||||
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()})
|
||||
% elif data['stream_audio_decision'] == 'copy':
|
||||
Direct Stream (${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()})
|
||||
% if data['stream_audio_decision']:
|
||||
% if data['stream_audio_decision'] == 'transcode':
|
||||
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()})
|
||||
% elif data['stream_audio_decision'] == 'copy':
|
||||
Direct Stream (${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
|
||||
</div>
|
||||
</li>
|
||||
|
@@ -437,6 +437,8 @@
|
||||
|
||||
var 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= '';
|
||||
switch (s.video_resolution.toLowerCase()) {
|
||||
case 'sd':
|
||||
@@ -462,11 +464,11 @@
|
||||
if (s.stream_video_decision === 'transcode') {
|
||||
var hw_d = (s.transcode_hw_decoding === 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') {
|
||||
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 {
|
||||
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') {
|
||||
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>'
|
||||
$(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') {
|
||||
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>';
|
||||
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>');
|
||||
|
@@ -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>'
|
||||
$(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') {
|
||||
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>';
|
||||
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>');
|
||||
|
@@ -153,7 +153,7 @@ libraries_list_table_options = {
|
||||
} 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>';
|
||||
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>'
|
||||
$(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 {
|
||||
|
@@ -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>'
|
||||
$(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') {
|
||||
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>';
|
||||
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>');
|
||||
|
@@ -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>'
|
||||
$(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') {
|
||||
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>';
|
||||
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>');
|
||||
|
@@ -2868,11 +2868,13 @@ $(document).ready(function() {
|
||||
}
|
||||
|
||||
$("#install_geoip_db").click(function () {
|
||||
if ($.trim($("#maxmind_license_key").val()) === "") {
|
||||
$("#maxmind_license_key").focus();
|
||||
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())){
|
||||
} else if (!(saveSettings())) {
|
||||
return false;
|
||||
}
|
||||
var msg = 'Are you sure you want to install the GeoLite2 database?<br /><br />' +
|
||||
|
@@ -178,6 +178,11 @@ DOCUMENTATION :: END
|
||||
<td>${data['stream_video_framerate']}</td>
|
||||
<td>${data['video_framerate']}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Dynamic Range</td>
|
||||
<td>${data['stream_video_dynamic_range']}</td>
|
||||
<td>${data['video_dynamic_range']}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Aspect Ratio</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;">
|
||||
<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']) %>
|
||||
<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>
|
||||
</td>
|
||||
</tr>
|
||||
@@ -847,7 +847,7 @@
|
||||
<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> /
|
||||
<% 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>
|
||||
</td>
|
||||
</tr>
|
||||
|
@@ -694,7 +694,7 @@
|
||||
<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> /
|
||||
<% 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>
|
||||
</td>
|
||||
</tr>
|
||||
@@ -847,7 +847,7 @@
|
||||
<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> /
|
||||
<% 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>
|
||||
</td>
|
||||
</tr>
|
||||
|
@@ -65,7 +65,7 @@ SYS_LANGUAGE = None
|
||||
SYS_ENCODING = None
|
||||
|
||||
QUIET = False
|
||||
VERBOSE = True
|
||||
VERBOSE = False
|
||||
DAEMON = False
|
||||
CREATEPID = False
|
||||
PIDFILE = None
|
||||
@@ -122,6 +122,7 @@ def initialize(config_file):
|
||||
|
||||
global CONFIG
|
||||
global CONFIG_FILE
|
||||
global VERBOSE
|
||||
global _INITIALIZED
|
||||
global CURRENT_VERSION
|
||||
global LATEST_VERSION
|
||||
@@ -152,6 +153,8 @@ def initialize(config_file):
|
||||
if not log_writable and not QUIET:
|
||||
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
|
||||
logger.initLogger(console=not QUIET, log_dir=CONFIG.LOG_DIR if log_writable else None,
|
||||
verbose=VERBOSE)
|
||||
@@ -585,12 +588,14 @@ def dbcheck():
|
||||
'view_offset INTEGER DEFAULT 0, duration INTEGER, video_decision TEXT, audio_decision TEXT, '
|
||||
'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_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, '
|
||||
'stream_bitrate INTEGER, stream_video_resolution TEXT, quality_profile 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_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, '
|
||||
'subtitles INTEGER, stream_subtitle_decision TEXT, stream_subtitle_codec 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, '
|
||||
'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_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, '
|
||||
'transcode_container TEXT, transcode_video_codec TEXT, transcode_audio_codec TEXT, '
|
||||
'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_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_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_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, '
|
||||
@@ -1203,6 +1208,18 @@ def dbcheck():
|
||||
'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
|
||||
try:
|
||||
c_db.execute('SELECT reference_id FROM session_history')
|
||||
@@ -1541,6 +1558,17 @@ def dbcheck():
|
||||
'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
|
||||
try:
|
||||
c_db.execute('SELECT do_notify FROM users')
|
||||
|
@@ -78,6 +78,7 @@ class ActivityProcessor(object):
|
||||
'video_framerate': session.get('video_framerate', ''),
|
||||
'video_scan_type': session.get('video_scan_type', ''),
|
||||
'video_full_resolution': session.get('video_full_resolution', ''),
|
||||
'video_dynamic_range': session.get('video_dynamic_range', ''),
|
||||
'aspect_ratio': session.get('aspect_ratio', ''),
|
||||
'audio_codec': session.get('audio_codec', ''),
|
||||
'audio_bitrate': session.get('audio_bitrate', ''),
|
||||
@@ -110,6 +111,7 @@ class ActivityProcessor(object):
|
||||
'stream_video_framerate': session.get('stream_video_framerate', ''),
|
||||
'stream_video_scan_type': session.get('stream_video_scan_type', ''),
|
||||
'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_codec': session.get('stream_audio_codec', ''),
|
||||
'stream_audio_bitrate': session.get('stream_audio_bitrate', ''),
|
||||
@@ -353,6 +355,7 @@ class ActivityProcessor(object):
|
||||
'video_framerate': session['video_framerate'],
|
||||
'video_scan_type': session['video_scan_type'],
|
||||
'video_full_resolution': session['video_full_resolution'],
|
||||
'video_dynamic_range': session['video_dynamic_range'],
|
||||
'aspect_ratio': session['aspect_ratio'],
|
||||
'audio_codec': session['audio_codec'],
|
||||
'audio_bitrate': session['audio_bitrate'],
|
||||
@@ -387,6 +390,7 @@ class ActivityProcessor(object):
|
||||
'stream_video_framerate': session['stream_video_framerate'],
|
||||
'stream_video_scan_type': session['stream_video_scan_type'],
|
||||
'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_codec': session['stream_audio_codec'],
|
||||
'stream_audio_bitrate': session['stream_audio_bitrate'],
|
||||
|
@@ -54,7 +54,9 @@ PLATFORM_NAME_OVERRIDES = {
|
||||
'Mystery 3': 'Playstation 3',
|
||||
'Mystery 4': 'Playstation 4',
|
||||
'Mystery 5': 'Xbox 360',
|
||||
'WebMAF': 'Playstation 4'
|
||||
'WebMAF': 'Playstation 4',
|
||||
'windows': 'Windows',
|
||||
'osx': 'macOS'
|
||||
}
|
||||
|
||||
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 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 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 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.'},
|
||||
@@ -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 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 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 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.'},
|
||||
|
@@ -603,6 +603,7 @@ _CONFIG_DEFINITIONS = {
|
||||
'UPDATE_LABELS': (int, 'General', 1),
|
||||
'UPDATE_LIBRARIES_DB_NOTIFY': (int, 'General', 1),
|
||||
'UPDATE_NOTIFIERS_DB': (int, 'General', 1),
|
||||
'VERBOSE_LOGS': (int, 'Advanced', 1),
|
||||
'VERIFY_SSL_CERT': (bool_int, 'Advanced', 1),
|
||||
'VIDEO_LOGGING_ENABLE': (int, 'Monitoring', 1),
|
||||
'WEBSOCKET_MONITOR_PING_PONG': (int, 'Advanced', 0),
|
||||
|
@@ -878,11 +878,12 @@ class DataFactory(object):
|
||||
query = 'SELECT bitrate, video_full_resolution, ' \
|
||||
'optimized_version, optimized_version_profile, optimized_version_title, ' \
|
||||
'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, ' \
|
||||
'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_framerate, ' \
|
||||
'stream_video_framerate, stream_video_dynamic_range, ' \
|
||||
'stream_audio_decision, stream_audio_codec, stream_audio_bitrate, stream_audio_channels, ' \
|
||||
'subtitles, stream_subtitle_decision, stream_subtitle_codec, ' \
|
||||
'transcode_hw_decoding, transcode_hw_encoding, ' \
|
||||
@@ -899,11 +900,12 @@ class DataFactory(object):
|
||||
query = 'SELECT bitrate, video_full_resolution, ' \
|
||||
'optimized_version, optimized_version_profile, optimized_version_title, ' \
|
||||
'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, ' \
|
||||
'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_framerate, ' \
|
||||
'stream_video_framerate, stream_video_dynamic_range, ' \
|
||||
'stream_audio_decision, stream_audio_codec, stream_audio_bitrate, stream_audio_channels, ' \
|
||||
'subtitles, stream_subtitle_decision, stream_subtitle_codec, ' \
|
||||
'transcode_hw_decoding, transcode_hw_encoding, ' \
|
||||
@@ -950,6 +952,7 @@ class DataFactory(object):
|
||||
'video_width': item['video_width'],
|
||||
'video_height': item['video_height'],
|
||||
'video_framerate': item['video_framerate'],
|
||||
'video_dynamic_range': item['video_dynamic_range'],
|
||||
'aspect_ratio': item['aspect_ratio'],
|
||||
'audio_codec': item['audio_codec'],
|
||||
'audio_bitrate': item['audio_bitrate'],
|
||||
@@ -966,6 +969,7 @@ class DataFactory(object):
|
||||
'stream_video_width': item['stream_video_width'],
|
||||
'stream_video_height': item['stream_video_height'],
|
||||
'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_codec': item['stream_audio_codec'],
|
||||
'stream_audio_bitrate': item['stream_audio_bitrate'],
|
||||
|
@@ -80,7 +80,7 @@ class BlacklistFilter(logging.Filter):
|
||||
Log filter for blacklisted tokens and passwords
|
||||
"""
|
||||
def __init__(self):
|
||||
pass
|
||||
super(BlacklistFilter, self).__init__()
|
||||
|
||||
def filter(self, record):
|
||||
if not plexpy.CONFIG.LOG_BLACKLIST:
|
||||
@@ -98,30 +98,29 @@ class BlacklistFilter(logging.Filter):
|
||||
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):
|
||||
pass
|
||||
super(RegexFilter, self).__init__()
|
||||
|
||||
self.regex = re.compile(r'')
|
||||
|
||||
def filter(self, record):
|
||||
if not plexpy.CONFIG.LOG_BLACKLIST:
|
||||
return True
|
||||
|
||||
try:
|
||||
# Currently only checking for ipv4 addresses
|
||||
ipv4 = re.findall(r'[0-9]+(?:\.[0-9]+){3}(?!\d*-[a-z0-9]{6})', record.msg)
|
||||
for ip in ipv4:
|
||||
if helpers.is_public_ip(ip):
|
||||
record.msg = record.msg.replace(ip, ip.partition('.')[0] + '.***.***.***')
|
||||
matches = self.regex.findall(record.msg)
|
||||
for match in matches:
|
||||
record.msg = self.replace(record.msg, match)
|
||||
|
||||
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 []
|
||||
for ip in ipv4:
|
||||
if helpers.is_public_ip(ip):
|
||||
arg = arg.replace(ip, ip.partition('.')[0] + '.***.***.***')
|
||||
matches = self.regex.findall(arg) if isinstance(arg, basestring) else []
|
||||
for match in matches:
|
||||
arg = self.replace(arg, match)
|
||||
args.append(arg)
|
||||
record.args = tuple(args)
|
||||
except:
|
||||
@@ -129,31 +128,53 @@ class PublicIPFilter(logging.Filter):
|
||||
|
||||
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
|
||||
"""
|
||||
def __init__(self):
|
||||
pass
|
||||
super(PlexTokenFilter, self).__init__()
|
||||
|
||||
def filter(self, record):
|
||||
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:])
|
||||
self.regex = re.compile(r'X-Plex-Token(?:=|%3D)([a-zA-Z0-9]+)')
|
||||
|
||||
args = []
|
||||
for arg in record.args:
|
||||
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
|
||||
def replace(self, text, token):
|
||||
return text.replace(token, 8 * '*' + token[-2:])
|
||||
|
||||
|
||||
@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:
|
||||
handler.addFilter(BlacklistFilter())
|
||||
handler.addFilter(PublicIPFilter())
|
||||
handler.addFilter(EmailFilter())
|
||||
handler.addFilter(PlexTokenFilter())
|
||||
|
||||
# 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_bitrate': notify_params['stream_video_bitrate'],
|
||||
'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_full_resolution': notify_params['stream_video_full_resolution'],
|
||||
'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_bitrate': notify_params['video_bitrate'],
|
||||
'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_full_resolution': notify_params['video_full_resolution'],
|
||||
'video_ref_frames': notify_params['video_ref_frames'],
|
||||
|
@@ -3416,9 +3416,9 @@ class TELEGRAM(Notifier):
|
||||
data = {'chat_id': self.config['chat_id']}
|
||||
|
||||
if self.config['incl_subject']:
|
||||
text = subject.encode('utf-8') + '\r\n' + body.encode('utf-8')
|
||||
text = subject + '\r\n' + body
|
||||
else:
|
||||
text = body.encode('utf-8')
|
||||
text = body
|
||||
|
||||
if self.config['html_support']:
|
||||
data['parse_mode'] = 'HTML'
|
||||
@@ -3442,7 +3442,7 @@ class TELEGRAM(Notifier):
|
||||
if len(text) > 1024:
|
||||
data['disable_notification'] = True
|
||||
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']),
|
||||
data=data, files=files)
|
||||
@@ -3450,7 +3450,7 @@ class TELEGRAM(Notifier):
|
||||
if not data.pop('disable_notification', None):
|
||||
return r
|
||||
|
||||
data['text'] = text
|
||||
data['text'] = (text[:4093] + (text[4093:] and '...')).encode('utf-8')
|
||||
|
||||
if self.config['disable_web_preview']:
|
||||
data['disable_web_page_preview'] = True
|
||||
@@ -3636,7 +3636,12 @@ class WEBHOOK(Notifier):
|
||||
if 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):
|
||||
config_option = [{'label': 'Webhook URL',
|
||||
|
@@ -1262,6 +1262,11 @@ class PmsConnect(object):
|
||||
'video_codec_level': helpers.get_xml_attr(stream, 'level'),
|
||||
'video_bitrate': helpers.get_xml_attr(stream, 'bitrate'),
|
||||
'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_ref_frames': helpers.get_xml_attr(stream, 'refFrames'),
|
||||
'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_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_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_ref_frames': helpers.get_xml_attr(video_stream_info, 'refFrames'),
|
||||
'stream_video_language': helpers.get_xml_attr(video_stream_info, 'language'),
|
||||
@@ -1708,6 +1718,11 @@ class PmsConnect(object):
|
||||
else:
|
||||
video_details = {'stream_video_bitrate': '',
|
||||
'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_ref_frames': '',
|
||||
'stream_video_language': '',
|
||||
@@ -1886,6 +1901,11 @@ class PmsConnect(object):
|
||||
'video_codec_level': '',
|
||||
'video_bitrate': '',
|
||||
'video_bit_depth': '',
|
||||
'video_chroma_subsampling': '',
|
||||
'video_color_primaries': '',
|
||||
'video_color_range': '',
|
||||
'video_color_space': '',
|
||||
'video_color_trc': '',
|
||||
'video_frame_rate': '',
|
||||
'video_ref_frames': '',
|
||||
'video_height': '',
|
||||
@@ -1969,6 +1989,22 @@ class PmsConnect(object):
|
||||
stream_details['stream_video_resolution'],
|
||||
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
|
||||
if media_type in ('movie', 'episode', 'clip') and 'stream_bitrate' in stream_details:
|
||||
if sync_id:
|
||||
|
@@ -1,2 +1,2 @@
|
||||
PLEXPY_BRANCH = "master"
|
||||
PLEXPY_RELEASE_VERSION = "v2.1.42"
|
||||
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):
|
||||
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
|
||||
logger.info('Retrieving latest version information from GitHub')
|
||||
url = 'https://api.github.com/repos/%s/%s/commits/%s' % (plexpy.CONFIG.GIT_USER,
|
||||
plexpy.CONFIG.GIT_REPO,
|
||||
plexpy.CONFIG.GIT_BRANCH)
|
||||
if plexpy.CONFIG.GIT_TOKEN: url = url + '?access_token=%s' % plexpy.CONFIG.GIT_TOKEN
|
||||
version = request.request_json(url, timeout=20, validator=lambda x: type(x) == dict)
|
||||
version = request.request_json(url, headers=headers, timeout=20, validator=lambda x: type(x) == dict)
|
||||
|
||||
if version is None:
|
||||
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.LATEST_VERSION,
|
||||
plexpy.CURRENT_VERSION)
|
||||
if plexpy.CONFIG.GIT_TOKEN: url = url + '?access_token=%s' % plexpy.CONFIG.GIT_TOKEN
|
||||
commits = request.request_json(url, timeout=20, whitelist_status_code=404, validator=lambda x: type(x) == dict)
|
||||
commits = request.request_json(url, headers=headers, timeout=20, whitelist_status_code=404,
|
||||
validator=lambda x: type(x) == dict)
|
||||
|
||||
if commits is None:
|
||||
logger.warn('Could not get commits behind from GitHub.')
|
||||
|
@@ -2667,8 +2667,11 @@ class WebInterface(object):
|
||||
@requireAuth(member_of("admin"))
|
||||
def toggleVerbose(self, **kwargs):
|
||||
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.debug(u"If you read this message, debug logging is available")
|
||||
raise cherrypy.HTTPRedirect(plexpy.HTTP_ROOT + "logs")
|
||||
|
Reference in New Issue
Block a user