Compare commits
12 Commits
v2.2.3-bet
...
v2.2.4
Author | SHA1 | Date | |
---|---|---|---|
![]() |
7f178e0913 | ||
![]() |
dcad3017d3 | ||
![]() |
71551d3f6d | ||
![]() |
6ef9d187ba | ||
![]() |
d4b46a5721 | ||
![]() |
9d2be4b939 | ||
![]() |
bfabbe3cdb | ||
![]() |
5499e89058 | ||
![]() |
35a0242037 | ||
![]() |
e2e7063a29 | ||
![]() |
03035d0eac | ||
![]() |
7ce9283421 |
46
CHANGELOG.md
46
CHANGELOG.md
@@ -1,36 +1,41 @@
|
||||
# Changelog
|
||||
|
||||
## v2.2.3-beta (2020-04-27)
|
||||
## v2.2.4 (2020-05-16)
|
||||
|
||||
* Monitoring:
|
||||
* Fix: Show "None" as the subtitle source on the activity card for user selected subtitles.
|
||||
* UI:
|
||||
* Fix: Deleted libraries were showing up on the homepage library cards.
|
||||
* Fix: Libraries could get stuck as inactive in the database in some instances.
|
||||
* API:
|
||||
* Fix: Incorrect title was being returned for the get_history API command.
|
||||
* Other:
|
||||
* Fix: Plex remote access check was not being rescheduled after changing the settings.
|
||||
|
||||
|
||||
## v2.2.3 (2020-05-01)
|
||||
|
||||
* Notifications:
|
||||
* Fix: Notification grouping by season/album and show/artist not enabled by default.
|
||||
* Fix: The rating key notification parameter was being overwritten when 3rd party lookup was enabled.
|
||||
* Fix: Missing artist value for Musicbrainz lookup in certain situations.
|
||||
* New: Added notification trigger for Tautulli database corruption.
|
||||
* New: Added TAUTULLI_PYTHON_VERSION to script notification environment variables.
|
||||
* New: Added Plex Android / iOS App notification agent.
|
||||
* New: Added bandwidth notification parameters.
|
||||
* New: Added user thumb to notification parameters.
|
||||
* New: Added initial stream notification parameter and threshold setting to determine if a stream is the first stream of a continuous streaming session.
|
||||
* New: Added Plex remote access notification parameters.
|
||||
* Fix: The rating key notification parameter was being overwritten when 3rd party lookup was enabled.
|
||||
* Fix: Missing artist value for Musicbrainz lookup in certain situations.
|
||||
* UI:
|
||||
* Fix: History table was not being refreshed after deleting entries.
|
||||
* Other:
|
||||
* Fix: Auto-updater was not scheduled when enabling the setting unless Tautulli was restarted.
|
||||
* Change: Remove the unnecessary optional Plex logs volume from the Docker image.
|
||||
* Change: Use Plex.tv for GeoIP lookup instead of requiring the MaxMind GeoLite2 database.
|
||||
|
||||
|
||||
## v2.2.2-beta (2020-04-12)
|
||||
|
||||
* Notifications:
|
||||
* New: Added notification trigger for Tautulli database corruption.
|
||||
* New: Added TAUTULLI_PYTHON_VERSION to script notification environment variables.
|
||||
* Fix: Notification grouping by season/album and show/artist not enabled by default.
|
||||
* Change: The file size notification parameter is now reported in SI units. (Thanks @aaronldunlap)
|
||||
* UI:
|
||||
* Fix: Delete lookup info from the media info page failing.
|
||||
* Fix: XBMC platform icon not being redirected to the Kodi platform icon.
|
||||
* Fix: History table was not being refreshed after deleting entries.
|
||||
* New: Added icon on the users table to indicate if the user is not on the Plex server.
|
||||
* New: Added icon on the libraries table to indicate if the library is not on the Plex server.
|
||||
* Fix: XBMC platform icon not being redirected to the Kodi platform icon.
|
||||
* Change: Improved deleting libraries so libraries with the same section ID are not also deleted.
|
||||
* Mobile App:
|
||||
* Fix: Temporary device token was not being invalidated after cancelling device registration.
|
||||
* API:
|
||||
* Fix: Returning XML from the API failing due to unicode characters.
|
||||
* Fix: Grouping parameter for various API commands not falling back to default setting.
|
||||
@@ -38,12 +43,13 @@
|
||||
* New: Added an "is_active" return value to the get_user, get_users, get_library, and get_libraries API commands which indicates if the user or library is on the Plex server.
|
||||
* New: Added delete_history API command.
|
||||
* Change: Added optional parameter for row_ids for delete_library, delete_user, delete_all_library_history, and delete_all_user_history API commands.
|
||||
* Mobile App:
|
||||
* Fix: Temporary device token was not being invalidated after cancelling device registration.
|
||||
* Other:
|
||||
* Fix: Update failing on CentOS due to an older git version.
|
||||
* Fix: Manifest file for creating a web app had incorrect info.
|
||||
* Fix: Auto-updater was not scheduled when enabling the setting unless Tautulli was restarted.
|
||||
* New: Docker images updated to support ARM platforms.
|
||||
* Change: Remove the unnecessary optional Plex logs volume from the Docker image.
|
||||
* Change: Use Plex.tv for GeoIP lookup instead of requiring the MaxMind GeoLite2 database.
|
||||
|
||||
|
||||
## v2.2.1 (2020-03-28)
|
||||
|
@@ -276,14 +276,17 @@ DOCUMENTATION :: END
|
||||
<div class="sub-heading">Subtitle</div>
|
||||
<div class="sub-value" id="subtitle_decision-${sk}">
|
||||
% if data['subtitles'] == 1:
|
||||
<%
|
||||
subtitle_codec = 'None' if data['stream_subtitle_codec'] and data['stream_subtitle_transient'] else data['subtitle_codec'].upper()
|
||||
%>
|
||||
% if data['stream_subtitle_decision'] == 'transcode':
|
||||
Transcode (${data['subtitle_codec'].upper()} <i class="fa fa-long-arrow-right"></i> ${data['stream_subtitle_codec'].upper()})
|
||||
Transcode (${subtitle_codec} <i class="fa fa-long-arrow-right"></i> ${data['stream_subtitle_codec'].upper()})
|
||||
% elif data['stream_subtitle_decision'] == 'copy':
|
||||
Direct Stream (${data['subtitle_codec'].upper()})
|
||||
Direct Stream (${subtitle_codec})
|
||||
% elif data['stream_subtitle_decision'] == 'burn':
|
||||
Burn (${data['subtitle_codec'].upper()})
|
||||
Burn (${subtitle_codec})
|
||||
% else:
|
||||
Direct Play (${data['subtitle_codec'].upper() if data['synced_version'] else data['stream_subtitle_codec'].upper()})
|
||||
Direct Play (${subtitle_codec if data['synced_version'] else data['stream_subtitle_codec'].upper()})
|
||||
% endif
|
||||
% else:
|
||||
None
|
||||
|
@@ -493,14 +493,15 @@
|
||||
|
||||
var subtitle_decision = 'None';
|
||||
if (['movie', 'episode', 'clip'].indexOf(s.media_type) > -1 && s.subtitles === 1) {
|
||||
var subtitle_codec = (s.stream_subtitle_codec && s.stream_subtitle_transient) ? 'None' : s.subtitle_codec.toUpperCase();
|
||||
if (s.stream_subtitle_decision === 'transcode') {
|
||||
subtitle_decision = 'Transcode (' + s.subtitle_codec.toUpperCase() + ' <i class="fa fa-long-arrow-right"></i> ' + s.stream_subtitle_codec.toUpperCase() + ')';
|
||||
subtitle_decision = 'Transcode (' + subtitle_codec + ' <i class="fa fa-long-arrow-right"></i> ' + s.stream_subtitle_codec.toUpperCase() + ')';
|
||||
} else if (s.stream_subtitle_decision === 'copy') {
|
||||
subtitle_decision = 'Direct Stream (' + s.subtitle_codec.toUpperCase() + ')';
|
||||
subtitle_decision = 'Direct Stream (' + subtitle_codec + ')';
|
||||
} else if (s.stream_subtitle_decision === 'burn') {
|
||||
subtitle_decision = 'Burn (' + s.subtitle_codec.toUpperCase() + ')';
|
||||
subtitle_decision = 'Burn (' + subtitle_codec + ')';
|
||||
} else {
|
||||
subtitle_decision = 'Direct Play (' + ((s.synced_version === '1') ? s.subtitle_codec.toUpperCase() : s.stream_subtitle_codec.toUpperCase()) + ')';
|
||||
subtitle_decision = 'Direct Play (' + ((s.synced_version === '1') ? subtitle_codec : s.stream_subtitle_codec.toUpperCase()) + ')';
|
||||
}
|
||||
}
|
||||
$('#subtitle_decision-' + key).html(subtitle_decision);
|
||||
|
@@ -79,7 +79,7 @@
|
||||
$('#ip_error').html('<i class="fa fa-exclamation-circle"></i> Internal request failed.').show();
|
||||
},
|
||||
success: function (result) {
|
||||
if (result.results === 'error') {
|
||||
if (result.result === 'error') {
|
||||
$('#ip_error').html('<i class="fa fa-exclamation-circle"></i> ' + result.message).show();
|
||||
} else {
|
||||
var data = result.data;
|
||||
|
@@ -850,6 +850,28 @@
|
||||
<span id="remoteAccessCheck" class="settings-warning"></span>
|
||||
<p class="help-block">Enable to have Tautulli check if remote access to the Plex Media Server goes down.</p>
|
||||
</div>
|
||||
<div id="monitor_remote_access_options">
|
||||
<div class="form-group advanced-setting">
|
||||
<label for="remote_access_ping_interval">Remote Access Ping Interval</label>
|
||||
<div class="row">
|
||||
<div class="col-md-2">
|
||||
<input type="text" class="form-control" data-parsley-type="integer" id="remote_access_ping_interval" name="remote_access_ping_interval" value="${config['remote_access_ping_interval']}" size="5" data-parsley-min="60" data-parsley-trigger="change" data-parsley-errors-container="#remote_access_ping_interval_error" required>
|
||||
</div>
|
||||
<div id="remote_access_ping_interval_error" class="alert alert-danger settings-alert" role="alert"></div>
|
||||
</div>
|
||||
<p class="help-block">The interval (in seconds) Tautulli will ping the Plex Media Server for the remote access status. Minimum 60.</p>
|
||||
</div>
|
||||
<div class="form-group advanced-setting">
|
||||
<label for="remote_access_ping_threshold">Remote Access Ping Threshold</label>
|
||||
<div class="row">
|
||||
<div class="col-md-2">
|
||||
<input type="text" class="form-control" data-parsley-type="integer" id="remote_access_ping_threshold" name="remote_access_ping_threshold" value="${config['remote_access_ping_threshold']}" size="5" data-parsley-min="1" data-parsley-trigger="change" data-parsley-errors-container="#remote_access_ping_threshold_error" required>
|
||||
</div>
|
||||
<div id="remote_access_ping_threshold_error" class="alert alert-danger settings-alert" role="alert"></div>
|
||||
</div>
|
||||
<p class="help-block">The number of consecutive remote access status failures to consider remote access as down. Minimum 1.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group advanced-setting">
|
||||
<label for="refresh_users_interval">Users List Refresh Interval</label>
|
||||
@@ -2043,6 +2065,7 @@ $(document).ready(function() {
|
||||
initConfigCheckbox('#https_create_cert');
|
||||
initConfigCheckbox('#check_github');
|
||||
initConfigCheckbox('#monitor_pms_updates');
|
||||
initConfigCheckbox('#monitor_remote_access');
|
||||
initConfigCheckbox('#newsletter_self_hosted');
|
||||
|
||||
$('#menu_link_shutdown').click(function() {
|
||||
|
@@ -31,6 +31,7 @@ import web_socket
|
||||
|
||||
monitor_lock = threading.Lock()
|
||||
ext_ping_count = 0
|
||||
ext_ping_error = None
|
||||
int_ping_count = 0
|
||||
|
||||
|
||||
@@ -309,18 +310,25 @@ def check_server_access():
|
||||
server_response = pms_connect.get_server_response()
|
||||
|
||||
global ext_ping_count
|
||||
global ext_ping_error
|
||||
|
||||
# Check for remote access
|
||||
if server_response:
|
||||
log = (server_response['mapping_error'] != ext_ping_error)
|
||||
|
||||
if server_response['reason']:
|
||||
ext_ping_count += 1
|
||||
logger.warn(u"Tautulli Monitor :: Remote access failed: %s, ping attempt %s." \
|
||||
% (server_response['reason'], str(ext_ping_count)))
|
||||
ext_ping_error = server_response['mapping_error']
|
||||
if log:
|
||||
logger.warn(u"Tautulli Monitor :: Remote access failed: %s, ping attempt %s."
|
||||
% (server_response['reason'], str(ext_ping_count)))
|
||||
|
||||
# Waiting for port mapping
|
||||
elif server_response['mapping_state'] == 'waiting':
|
||||
logger.warn(u"Tautulli Monitor :: Remote access waiting for port mapping, ping attempt %s." \
|
||||
% str(ext_ping_count))
|
||||
ext_ping_error = server_response['mapping_error']
|
||||
if log:
|
||||
logger.warn(u"Tautulli Monitor :: Remote access waiting for port mapping, ping attempt %s."
|
||||
% str(ext_ping_count))
|
||||
|
||||
# Reset external ping counter
|
||||
else:
|
||||
@@ -330,8 +338,10 @@ def check_server_access():
|
||||
plexpy.NOTIFY_QUEUE.put({'notify_action': 'on_extup', 'remote_access_info': server_response})
|
||||
|
||||
ext_ping_count = 0
|
||||
ext_ping_error = None
|
||||
|
||||
if ext_ping_count == plexpy.CONFIG.REMOTE_ACCESS_PING_THRESHOLD:
|
||||
logger.info(u"Tautulli Monitor: Plex remote access is down.")
|
||||
plexpy.NOTIFY_QUEUE.put({'notify_action': 'on_extdown', 'remote_access_info': server_response})
|
||||
|
||||
|
||||
|
@@ -248,7 +248,7 @@ class DataFactory(object):
|
||||
'parent_rating_key': item['parent_rating_key'],
|
||||
'grandparent_rating_key': item['grandparent_rating_key'],
|
||||
'full_title': item['full_title'],
|
||||
'title': item['parent_title'],
|
||||
'title': item['title'],
|
||||
'parent_title': item['parent_title'],
|
||||
'grandparent_title': item['grandparent_title'],
|
||||
'original_title': item['original_title'],
|
||||
@@ -865,7 +865,7 @@ class DataFactory(object):
|
||||
'custom_thumb_url AS custom_thumb, art AS library_art, custom_art_url AS custom_art, ' \
|
||||
'count, parent_count, child_count ' \
|
||||
'FROM library_sections ' \
|
||||
'WHERE section_id IN (%s) ' \
|
||||
'WHERE section_id IN (%s) AND deleted_section = 0 ' \
|
||||
'ORDER BY section_type, count DESC, parent_count DESC, child_count DESC ' % ','.join(library_cards)
|
||||
result = monitor_db.select(query)
|
||||
except Exception as e:
|
||||
|
@@ -61,6 +61,7 @@ def refresh_libraries():
|
||||
'count': section['count'],
|
||||
'parent_count': section.get('parent_count', None),
|
||||
'child_count': section.get('child_count', None),
|
||||
'is_active': section['is_active']
|
||||
}
|
||||
|
||||
result = monitor_db.upsert('library_sections', key_dict=section_keys, value_dict=section_values)
|
||||
|
@@ -933,7 +933,7 @@ class PlexTV(object):
|
||||
return account_details
|
||||
|
||||
def get_geoip_lookup(self, ip_address=''):
|
||||
if not ip_address or not helpers.is_public_ip(ip_address):
|
||||
if not ip_address or not helpers.is_valid_ip(ip_address):
|
||||
return
|
||||
|
||||
geoip_data = self.get_plextv_geoip(ip_address=ip_address, output_format='xml')
|
||||
|
@@ -1568,7 +1568,11 @@ class PmsConnect(object):
|
||||
|
||||
# Get the user details
|
||||
user_info = session.getElementsByTagName('User')[0]
|
||||
user_details = users.Users().get_details(user=helpers.get_xml_attr(user_info, 'title'))
|
||||
user_id = helpers.get_xml_attr(user_info, 'id')
|
||||
if user_id == '1': # Admin user
|
||||
user_details = users.Users().get_details(user=helpers.get_xml_attr(user_info, 'title'))
|
||||
else:
|
||||
user_details = users.Users().get_details(user_id=user_id)
|
||||
|
||||
# Get the player details
|
||||
player_info = session.getElementsByTagName('Player')[0]
|
||||
@@ -1801,7 +1805,8 @@ class PmsConnect(object):
|
||||
'stream_subtitle_location': helpers.get_xml_attr(subtitle_stream_info, 'location'),
|
||||
'stream_subtitle_language': helpers.get_xml_attr(subtitle_stream_info, 'language'),
|
||||
'stream_subtitle_language_code': helpers.get_xml_attr(subtitle_stream_info, 'languageCode'),
|
||||
'stream_subtitle_decision': helpers.get_xml_attr(subtitle_stream_info, 'decision')
|
||||
'stream_subtitle_decision': helpers.get_xml_attr(subtitle_stream_info, 'decision'),
|
||||
'stream_subtitle_transient': int(helpers.get_xml_attr(subtitle_stream_info, 'transient') == '1')
|
||||
}
|
||||
else:
|
||||
subtitle_selected = None
|
||||
@@ -1812,7 +1817,8 @@ class PmsConnect(object):
|
||||
'stream_subtitle_location': '',
|
||||
'stream_subtitle_language': '',
|
||||
'stream_subtitle_language_code': '',
|
||||
'stream_subtitle_decision': ''
|
||||
'stream_subtitle_decision': '',
|
||||
'stream_subtitle_transient': 0
|
||||
}
|
||||
|
||||
# Get the bif thumbnail
|
||||
|
@@ -60,7 +60,7 @@ def refresh_users():
|
||||
else:
|
||||
item['custom_avatar_url'] = item['thumb']
|
||||
|
||||
monitor_db.upsert('users', item, keys_dict)
|
||||
monitor_db.upsert('users', key_dict=keys_dict, value_dict=item)
|
||||
|
||||
query = 'UPDATE users SET is_active = 0 WHERE user_id NOT IN ({})'.format(', '.join(['?'] * len(user_ids)))
|
||||
monitor_db.action(query=query, args=user_ids)
|
||||
|
@@ -1,2 +1,2 @@
|
||||
PLEXPY_BRANCH = "beta"
|
||||
PLEXPY_RELEASE_VERSION = "v2.2.3-beta"
|
||||
PLEXPY_BRANCH = "master"
|
||||
PLEXPY_RELEASE_VERSION = "v2.2.4"
|
||||
|
@@ -2897,6 +2897,8 @@ class WebInterface(object):
|
||||
"grouping_charts": checked(plexpy.CONFIG.GROUPING_CHARTS),
|
||||
"monitor_pms_updates": checked(plexpy.CONFIG.MONITOR_PMS_UPDATES),
|
||||
"monitor_remote_access": checked(plexpy.CONFIG.MONITOR_REMOTE_ACCESS),
|
||||
"remote_access_ping_interval": plexpy.CONFIG.REMOTE_ACCESS_PING_INTERVAL,
|
||||
"remote_access_ping_threshold": plexpy.CONFIG.REMOTE_ACCESS_PING_THRESHOLD,
|
||||
"refresh_libraries_interval": plexpy.CONFIG.REFRESH_LIBRARIES_INTERVAL,
|
||||
"refresh_libraries_on_startup": checked(plexpy.CONFIG.REFRESH_LIBRARIES_ON_STARTUP),
|
||||
"refresh_users_interval": plexpy.CONFIG.REFRESH_USERS_INTERVAL,
|
||||
@@ -3022,6 +3024,7 @@ class WebInterface(object):
|
||||
kwargs.get('pms_update_check_interval') != str(plexpy.CONFIG.PMS_UPDATE_CHECK_INTERVAL) or \
|
||||
kwargs.get('monitor_pms_updates') != plexpy.CONFIG.MONITOR_PMS_UPDATES or \
|
||||
kwargs.get('monitor_remote_access') != plexpy.CONFIG.MONITOR_REMOTE_ACCESS or \
|
||||
kwargs.get('remote_access_ping_interval') != str(plexpy.CONFIG.REMOTE_ACCESS_PING_INTERVAL) or \
|
||||
kwargs.get('pms_url_manual') != plexpy.CONFIG.PMS_URL_MANUAL:
|
||||
reschedule = True
|
||||
|
||||
@@ -5719,8 +5722,6 @@ class WebInterface(object):
|
||||
message = 'No IP address provided.'
|
||||
elif not helpers.is_valid_ip(ip_address):
|
||||
message = 'Invalid IP address provided: %s' % ip_address
|
||||
elif not helpers.is_public_ip(ip_address):
|
||||
message = 'Non-public IP address provided: %s' % ip_address
|
||||
|
||||
if message:
|
||||
return {'result': 'error', 'message': message}
|
||||
|
Reference in New Issue
Block a user