Compare commits

...

44 Commits

Author SHA1 Message Date
JonnyWong16
a7a9ed8628 v2.1.41 2019-12-30 14:33:10 -08:00
JonnyWong16
6af96332fa Use tar.extractall instead of tar.extract 2019-12-30 14:29:19 -08:00
JonnyWong16
e334a0fc8b Change GeoLite2 tar extraction 2019-12-30 14:19:12 -08:00
JonnyWong16
54bbbb36a6 Fix Geolite2 db extraction on Windows 2019-12-30 13:58:56 -08:00
JonnyWong16
b8ef56574a v2.1.40 2019-12-30 10:24:46 -08:00
JonnyWong16
bc491628d4 Add links to 3rd Party APIs guide 2019-12-29 15:03:22 -08:00
JonnyWong16
629800c239 Change metadata to links for lookup help text 2019-12-29 11:05:21 -08:00
JonnyWong16
8bf876f88c Add note to save the MaxMind license key 2019-12-28 11:09:52 -08:00
JonnyWong16
a81ad6d73e Set maximum GeoLite2 database update interval to 30 days 2019-12-28 11:06:04 -08:00
JonnyWong16
02220209e3 Add default activity refresh interval to setting help text 2019-12-27 09:48:38 -08:00
JonnyWong16
9450a1434d Remove line break from Python version in startup logs 2019-12-25 14:10:35 -08:00
JonnyWong16
c358693fb2 Fix GeoLite2 update scheduler 2019-12-25 14:10:16 -08:00
JonnyWong16
e7b3d768ce Prevent installing GeoLite2 database without license key 2019-12-25 14:07:59 -08:00
JonnyWong16
ee91da2ff1 Force reinstall of GeoLite2 database 2019-12-25 13:43:12 -08:00
JonnyWong16
0428df8e3f Fix GeoLite2 update button for previous installs 2019-12-25 13:31:46 -08:00
JonnyWong16
d4fee1d701 Fix GeoLite2 last updated time for previous installs 2019-12-25 13:23:33 -08:00
JonnyWong16
3b44a3afd2 Add setting for GeoLite2 database update interval 2019-12-25 12:51:59 -08:00
JonnyWong16
7ee1c51810 Go to correct setting for installing GeoLite2 database 2019-12-25 12:40:58 -08:00
JonnyWong16
f958de2de6 Move 3rd Party API settings to new tab 2019-12-25 11:41:53 -08:00
JonnyWong16
b83eb2e763 Add auto-updating of GeoLite2 database 2019-12-25 11:17:45 -08:00
JonnyWong16
41c9369b43 Change GeoIP database install using license key 2019-12-23 23:58:36 -08:00
JonnyWong16
554be92c39 Update go to setting links 2019-12-23 22:30:49 -08:00
JonnyWong16
7486a50c33 Calculate months for graphs using datetime 2019-12-12 09:12:29 -08:00
JonnyWong16
1e777b1a1b Add logging for notify_action (trigger) 2019-12-11 11:35:30 -08:00
JonnyWong16
b7bb159630 Fix regex IP match in hostname resolution 2019-12-10 10:07:34 -08:00
JonnyWong16
6e0a0d51b5 v2.1.39 2019-12-08 12:12:24 -08:00
JonnyWong16
55aad4e6ee Fix integrity check before database backup 2019-11-29 23:14:33 -08:00
JonnyWong16
d1e401cb0c Remove default subject and body for notify API command 2019-11-24 22:35:58 -08:00
JonnyWong16
018479fae9 Fix favicons in setup wizard 2019-11-24 15:03:36 -08:00
JonnyWong16
1c18e72539 Enable allow Plex admin by default 2019-11-20 21:51:52 -08:00
JonnyWong16
779e710045 Fix setup wizard height 2019-11-20 21:51:36 -08:00
JonnyWong16
089a981f6e Check for database corruption when making backup 2019-11-20 19:03:44 -08:00
JonnyWong16
3b24bbee5f Add web server HTTP username and password to setup wizard 2019-11-20 18:50:17 -08:00
JonnyWong16
f9a597bed9 Use bit.ly link for PayPal in FUNDING file 2019-11-17 21:54:47 -08:00
JonnyWong16
a637b3bb24 v2.1.38 2019-11-17 21:45:43 -08:00
JonnyWong16
3e520820d8 Update pytz to 2019.3 2019-11-17 21:13:21 -08:00
JonnyWong16
3a71929821 Remove issues template 2019-11-13 19:44:33 -08:00
JonnyWong16
a08629c503 Add GitHub sponsor 2019-11-13 19:40:26 -08:00
JonnyWong16
cfc30c1234 Add optional headers parameter for webhooks in notify API command 2019-11-11 15:41:11 -08:00
JonnyWong16
ddbd486500 Add custom headers to Webhook notification agent 2019-11-11 15:17:49 -08:00
JonnyWong16
f5794a5bae Improve resolving hostnames 2019-11-02 10:38:14 -07:00
JonnyWong16
bb1bf87fe2 Fix homepage recently watched not showing grouped history 2019-10-27 16:06:19 -07:00
JonnyWong16
acc59523e0 Prevent dismissing the changelog modal 2019-10-11 22:55:23 -07:00
JonnyWong16
38d7ea16b4 Fix typo in changelogs 2019-10-11 20:37:26 -07:00
502 changed files with 1675 additions and 1294 deletions

3
.github/FUNDING.yml vendored Normal file
View File

@@ -0,0 +1,3 @@
github: JonnyWong16
patreon: Tautulli
custom: ["https://bit.ly/2InPp15"]

1
API.md
View File

@@ -2459,6 +2459,7 @@ Required parameters:
body (str): The body of the message
Optional parameters:
headers (str): The JSON headers for webhook notifications
script_args (str): The arguments for script notifications
Returns:

View File

@@ -1,10 +1,49 @@
# Changelog
## v2.1.41 (2019-12-30)
* Other:
* Fix: Failing to extract the GeoLite2 database on Windows.
## v2.1.40 (2019-12-30)
* UI:
* Change: Moved 3rd Party API settings to new tab in the settings.
* Graphs:
* Change: Improve calculating month ranges for Play Totals graphs.
* Other:
* Fix: Failing to verify a Plex Media Server using a hostname.
* Change: A license key is now required to install the MaxMind GeoLite2 database for IP geolocation. Please follow the guide in the wiki to reinstall the GeoLite2 database.
* Change: The GeoLite2 database will now automatically update periodically if installed.
## v2.1.39 (2019-12-08)
* UI:
* New: Added creating admin username and password to setup wizard.
* API:
* Change: Remove default notification subject and body for notify API command.
* Other:
* Change: Check for database corruption when making backup.
## v2.1.38 (2019-11-17)
* Notifications:
* New: Added custom JSON headers to the webhook notification agent.
* UI:
* Fix: Homepage recently watched card not showing grouped history.
* Other:
* New: Added GitHub sponsor donation option.
* Change: Improve resolving hostnames.
## v2.1.37 (2019-10-11)
* Notifications:
* Fix: Last.fm URLs linking to artist page instead of the album page.
* New: Added option for MusicBrainz lookup for music notifications. Option must be enabled under 3rd Part APIs in the settings.
* New: Added option for MusicBrainz lookup for music notifications. Option must be enabled under 3rd Party APIs in the settings.
* New: Added MusicBrainz ID and MusicBrainz URL notification parameters.
* Change: Automatically truncate Discord description summary to 2048 characters.

View File

@@ -1,41 +0,0 @@
<!---
Reporting Issues:
* To ensure that a developer has enough information to work with please include all of the information below.
Please provide as much detail as possible. Screenshots can be very useful to see the problem.
* Use proper markdown syntax to structure your post (i.e. code/log in code blocks).
See: https://help.github.com/articles/basic-writing-and-formatting-syntax/
* Include a link to your **FULL** log file that has the error(not just a few lines!).
Please use [Gist](http://gist.github.com) or [Pastebin](http://pastebin.com/).
Feature Requests:
* Feature requests are handled on FeatHub: http://feathub.com/Tautulli/Tautulli
* Do not post them on the GitHub issues tracker.
-->
**Version:**
**Branch:**
**Commit hash:**
**Operating system:**
**Python version:**
**What you did?**
**What happened?**
**What you expected?**
**How can we reproduce your issue?**
<!-- Provide a detailed step-by-step. -->
**What are your (relevant) settings?**
**Link to logs:**
<!--
Close your issue when it's solved! If you found the solution yourself please comment so that others benefit from it.
-->

View File

@@ -234,31 +234,19 @@ def main():
plexpy.CONFIG.ENABLE_HTTPS = False
# Try to start the server. Will exit here is address is already in use.
web_config = {
'http_port': plexpy.HTTP_PORT,
'http_host': plexpy.CONFIG.HTTP_HOST,
'http_root': plexpy.CONFIG.HTTP_ROOT,
'http_environment': plexpy.CONFIG.HTTP_ENVIRONMENT,
'http_proxy': plexpy.CONFIG.HTTP_PROXY,
'enable_https': plexpy.CONFIG.ENABLE_HTTPS,
'https_cert': plexpy.CONFIG.HTTPS_CERT,
'https_cert_chain': plexpy.CONFIG.HTTPS_CERT_CHAIN,
'https_key': plexpy.CONFIG.HTTPS_KEY,
'http_username': plexpy.CONFIG.HTTP_USERNAME,
'http_password': plexpy.CONFIG.HTTP_PASSWORD,
'http_basic_auth': plexpy.CONFIG.HTTP_BASIC_AUTH
}
webstart.initialize(web_config)
webstart.start()
# Windows system tray icon
if os.name == 'nt' and plexpy.CONFIG.WIN_SYS_TRAY:
plexpy.win_system_tray()
logger.info("Tautulli is ready!")
# Open webbrowser
if plexpy.CONFIG.LAUNCH_BROWSER and not args.nolaunch and not plexpy.DEV:
plexpy.launch_browser(plexpy.CONFIG.HTTP_HOST, plexpy.HTTP_PORT,
plexpy.HTTP_ROOT)
# Windows system tray icon
if os.name == 'nt' and plexpy.CONFIG.WIN_SYS_TRAY:
plexpy.win_system_tray()
# Wait endlessy for a signal to happen
while True:
if not plexpy.SIGNAL:

View File

@@ -229,6 +229,7 @@ ${next.modalIncludes()}
</div>
<ul id="donation_type" class="nav nav-pills" role="tablist" style="display: flex; justify-content: center; margin: 10px 0;">
<li class="active"><a href="#patreon-donation" role="tab" data-toggle="tab">Patreon</a></li>
<li><a href="#github-donation" role="tab" data-toggle="tab">GitHub</a></li>
<li><a href="#paypal-donation" role="tab" data-toggle="tab">PayPal</a></li>
</ul>
<div class="tab-content">
@@ -240,6 +241,14 @@ ${next.modalIncludes()}
<img src="images/become_a_patron_button.png" alt="Become a Patron" height="40">
</a>
</div>
<div role="tabpanel" class="tab-pane" id="github-donation" style="text-align: center">
<p>
Click the button below to continue to GitHub.
</p>
<a href="${anon_url('https://github.com/sponsors/JonnyWong16')}" target="_blank" class="btn btn-sm btn-default" style="font-weight: 600;">
<i class="fa fa-heart fa-sm" style="color: #ea4aaa;"></i>&nbsp; Sponsor
</a>
</div>
<div role="tabpanel" class="tab-pane" id="paypal-donation" style="text-align: center">
<p>
Click the button below to continue to PayPal.

View File

@@ -53,14 +53,6 @@ DOCUMENTATION :: END
<td>Newsletter Directory:</td>
<td>${plexpy.CONFIG.NEWSLETTER_DIR}</td>
</tr>
<tr>
<td>GeoLite2 Database:</td>
% if plexpy.CONFIG.GEOIP_DB:
<td>${plexpy.CONFIG.GEOIP_DB} | <a class="no-highlight" href="#" id="reinstall_geoip_db">Reinstall / Update</a> | <a class="no-highlight" href="#" id="uninstall_geoip_db">Uninstall</a></td>
% else:
<td><a class="no-highlight" href="#" id="install_geoip_db">Click here to install the GeoLite2 database.</a></td>
% endif
</tr>
% if plexpy.ARGS:
<tr>
<td>Arguments:</td>
@@ -102,22 +94,6 @@ DOCUMENTATION :: END
<script>
$(document).ready(function () {
$("#install_geoip_db, #reinstall_geoip_db").click(function () {
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 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 />'
var url = 'install_geoip_db';
confirmAjaxCall(url, msg, null, 'Installing GeoLite2 database.', getConfigurationTable);
});
$("#uninstall_geoip_db").click(function () {
var msg = 'Are you sure you want to uninstall the GeoLite2 database?<br /><br />' +
'You will not be able to lookup IP address geolocation info.';
var url = 'uninstall_geoip_db';
confirmAjaxCall(url, msg, null, 'Uninstalling GeoLite2 database.', getConfigurationTable);
});
$('.guidelines-modal-link').on('click', function (e) {
e.preventDefault();
$('#guidelines-type').text($(this).data('id'))

View File

@@ -881,7 +881,10 @@
async: true,
complete: function (xhr, status) {
$("#changelog-modal .modal-body").html(xhr.responseText);
$('#changelog-modal').modal();
$('#changelog-modal').modal({
backdrop: 'static',
keyboard: false
});
}
});
</script>

View File

@@ -271,7 +271,7 @@
</div>
<p class="help-block">
Select an existing notification agent where the subject and body text will be sent.<br>
Note: Self-hosted newsletters must be enabled under <a data-tab-destination="tabs-notifications" data-dismiss="modal" data-target="#newsletter_self_hosted">Newsletters</a> to include a link to the newsletter.
Note: Self-hosted newsletters must be enabled under <a data-tab-destination="notifications" data-dismiss="modal" data-target="newsletter_self_hosted">Newsletters</a> to include a link to the newsletter.
</p>
</div>
<div id="newsletter-email-config">

View File

@@ -243,6 +243,11 @@
</div>
<ul class="submenu">
<li>
<div class="form-group">
<label for="${action['name']}_subject">JSON Headers</label>
<textarea class="form-control" id="${action['name']}_subject" name="${action['name']}_subject" data-parsley-trigger="change" data-autoresize required>${notifier['notify_text'][action['name']]['subject']}</textarea>
<p class="help-block">Set custom JSON headers.</p>
</div>
<div class="form-group">
<label for="${action['name']}_body">JSON Data</label>
<textarea class="form-control" id="${action['name']}_body" name="${action['name']}_body" data-parsley-trigger="change" data-autoresize required>${notifier['notify_text'][action['name']]['body']}</textarea>
@@ -326,6 +331,15 @@
<p class="help-block">Set custom arguments passed to the script.</p>
</div>
% elif notifier['agent_name'] == 'webhook':
<div class="form-group">
<label for="test_subject">JSON Headers</label>
<div class="row">
<div class="col-md-12">
<textarea class="form-control" id="test_subject" name="test_subject" data-autoresize></textarea>
</div>
</div>
<p class="help-block">Set custom JSON headers sent to the webhook.</p>
</div>
<div class="form-group">
<label for="test_body">JSON Data</label>
<div class="row">
@@ -471,7 +485,7 @@
'<div class="form-group">' +
'<label>Warning</label>' +
'<p class="help-block" style="color: #eb8600;">Facebook requires HTTPS for authorization. ' +
'Please enable HTTPS for Tautulli under <a data-tab-destination="tabs-web_interface" data-dismiss="modal" data-target="#enable_https">Web Interface</a>.</p>' +
'Please enable HTTPS for Tautulli under <a data-tab-destination="web_interface" data-dismiss="modal" data-target="enable_https">Web Interface</a>.</p>' +
'</div>'
);
$('#facebook_redirect_uri').val('HTTPS not enabled');

View File

@@ -56,6 +56,7 @@
<li role="presentation"><a href="#tabs-notifications" aria-controls="tabs-notifications" role="tab" data-toggle="tab">Notifications & Newsletters</a></li>
<li role="presentation"><a href="#tabs-notification_agents" aria-controls="tabs-notification_agents" role="tab" data-toggle="tab">Notification Agents</a></li>
<li role="presentation"><a href="#tabs-newsletter_agents" aria-controls="tabs-newsletter_agents" role="tab" data-toggle="tab">Newsletter Agents</a></li>
<li role="presentation"><a href="#tabs-3rd_party_apis" aria-controls="tabs-3rd_party_apis" role="tab" data-toggle="tab">3rd Party APIs</a></li>
<li role="presentation"><a href="#tabs-import_backups" aria-controls="tabs-import_backups" role="tab" data-toggle="tab">Import & Backups</a></li>
<li role="presentation"><a href="#tabs-android_app" aria-controls="tabs-android_app" role="tab" data-toggle="tab">Tautulli Remote Android App <sup><small>beta</small></sup></a></li>
</ul>
@@ -284,7 +285,7 @@
</div>
<div id="home_refresh_interval_error" class="alert alert-danger settings-alert" role="alert"></div>
</div>
<p class="help-block">Set the interval (in seconds) to refresh the current activity on the homepage. Minimum 2.</p>
<p class="help-block">Set the interval (in seconds) to refresh the current activity on the homepage. Minimum 2, default 10.</p>
</div>
<div class="padded-header">
@@ -1008,7 +1009,7 @@
<p class="help-block" id="self_host_newsletter_message">
Note: The <span class="inline-pre">${http_root}newsletter</span> endpoint on your domain must be publicly accessible from the internet.
</p>
<p class="help-block settings-warning base-url-warning">Warning: Public Tautulli domain not set under <a data-tab-destination="tabs-web_interface" data-target="#http_base_url">Web Interface</a>.</p>
<p class="help-block settings-warning base-url-warning">Warning: Public Tautulli domain not set under <a data-tab-destination="web_interface" data-target="http_base_url">Web Interface</a>.</p>
</div>
<div class="form-group">
<label for="newsletter_auth">Newsletter Authentication</label>
@@ -1022,7 +1023,7 @@
</div>
</div>
<p class="help-block">Select the authentication method to use for self-hosted newsletters.</p>
<p class="help-block settings-warning newsletter-guest-access-warning">Warning: Guest Access is not enabled under <a data-tab-destination="tabs-web_interface" data-target="#allow_guest_access">Web Interface</a>.</p>
<p class="help-block settings-warning newsletter-guest-access-warning">Warning: Guest Access is not enabled under <a data-tab-destination="web_interface" data-target="allow_guest_access">Web Interface</a>.</p>
</div>
<div class="form-group" id="newsletter_password_option">
<label for="newsletter_password">Newsletter Password</label>
@@ -1063,12 +1064,60 @@
<p class="help-block">Enter the full path to where newsletter files will be saved.</p>
</div>
<p><input type="button" class="btn btn-bright save-button" value="Save" data-success="Changes saved successfully"></p>
</div>
<div role="tabpanel" class="tab-pane" id="tabs-notification_agents">
<div class="padded-header">
<h3>3rd Party APIs</h3>
<h3>Notification Agents</h3>
</div>
<p class="help-block">
Add a new notification agent, or configure an existing notification agent by clicking the settings icon on the right.
</p>
<p class="help-block">
Please see the <a target='_blank' href='${anon_url('https://github.com/%s/%s-Wiki/wiki/Notification-Agents-Guide' % (plexpy.CONFIG.GIT_USER, plexpy.CONFIG.GIT_REPO))}'>Notification Agents Guide</a> for instructions on setting up each notification agent.
</p>
<br />
<div id="plexpy-notifiers-table">
<div class='text-muted'><i class="fa fa-refresh fa-spin"></i> Loading notification agents...</div>
<br>
</div>
</div>
<div role="tabpanel" class="tab-pane" id="tabs-newsletter_agents">
<div class="padded-header">
<h3>Newsletter Agents</h3>
</div>
<p class="help-block">
Add a new newsletter agent, or configure an existing newsletter agent by clicking the settings icon on the right.
</p>
<p class="help-block settings-warning" id="newsletter_upload_warning">
Warning: The <a data-tab-destination="3rd_party_apis" data-target="notify_upload_posters">Image Hosting</a> setting must be enabled for images to display on the newsletter.</span>
</p>
<br/>
<div id="plexpy-newsletters-table">
<div class='text-muted'><i class="fa fa-refresh fa-spin"></i> Loading newsletter agents...</div>
<br>
</div>
</div>
<div role="tabpanel" class="tab-pane" id="tabs-3rd_party_apis">
<div class="padded-header">
<h3>Image Hosting</h3>
</div>
<p class="help-block">Image hosting is used to provide posters and artwork for some notification agents and newsletters.</p>
<div class="form-group">
<label for="notify_upload_posters">Image Hosting</label>
<label for="notify_upload_posters">Image Host</label>
<div class="row">
<div class="col-md-6">
<div class="${'input-group' if config['notify_upload_posters'] in (1, 3) else ''}">
@@ -1090,8 +1139,8 @@
</div>
<div id="imgur_upload_options" style="overlfow: hidden; display: ${'none' if config['notify_upload_posters'] != 1 else 'block'}">
<div class="form-group">
<p class="help-block" id="imgur_upload_message">
You can register a new Imgur application <a href="${anon_url('https://api.imgur.com/oauth2/addclient')}" target="_blank">here</a>.<br>
<p class="help-block">
Please see the <a target='_blank' href='${anon_url('https://github.com/%s/%s-Wiki/wiki/3rd-Party-APIs-Guide' % (plexpy.CONFIG.GIT_USER, plexpy.CONFIG.GIT_REPO))}'>3rd Party APIs Guide</a> for instructions on setting up Imgur.<br>
Warning: Imgur uploads are rate-limited and newsletters may exceed the limit. Please use Cloudinary for newsletters instead.
</p>
</div>
@@ -1108,13 +1157,13 @@
<div id="self_host_image_options" style="overlfow: hidden; display: ${'none' if config['notify_upload_posters'] != 2 else 'block'}">
<div class="form-group">
<p class="help-block" id="self_host_image_message">Note: The <span class="inline-pre">${http_root}image</span> endpoint on your domain must be publicly accessible from the internet.</p>
<p class="help-block settings-warning base-url-warning">Warning: Public Tautulli domain not set under <a data-tab-destination="tabs-web_interface" data-target="#http_base_url">Web Interface</a>.</p>
<p class="help-block settings-warning base-url-warning">Warning: Public Tautulli domain not set under <a data-tab-destination="web_interface" data-target="http_base_url">Web Interface</a>.</p>
</div>
</div>
<div id="cloudinary_upload_options" style="overlfow: hidden; display: ${'none' if config['notify_upload_posters'] != 3 else 'block'}">
<div class="form-group">
<p class="help-block" id="imgur_upload_message">
You can sign up for Cloudinary <a href="${anon_url('https://cloudinary.com')}" target="_blank">here</a>.<br>
<p class="help-block">
Please see the <a target='_blank' href='${anon_url('https://github.com/%s/%s-Wiki/wiki/3rd-Party-APIs-Guide' % (plexpy.CONFIG.GIT_USER, plexpy.CONFIG.GIT_REPO))}'>3rd Party APIs Guide</a> for instructions on setting up Cloudinary.
</p>
</div>
<div class="form-group">
@@ -1151,6 +1200,13 @@
</p>
</div>
</div>
<div class="padded-header">
<h3>Metadata Lookups</h3>
</div>
<p class="help-block">Metadata lookups are used to provide additional links for notifications when available.</p>
<div class="checkbox">
<label>
<input type="checkbox" name="themoviedb_lookup" id="themoviedb_lookup" value="1" ${config['themoviedb_lookup']}> Lookup TheMovieDB Links
@@ -1170,50 +1226,57 @@
<p class="help-block">Enable to lookup links to MusicBrainz for music when available.</p>
</div>
<div class="padded-header">
<h3>Geolocation Database</h3>
</div>
<p class="help-block">The GeoLite2 database is used to geolocate IP addresses.</p>
<p class="help-block">
Please see the <a target='_blank' href='${anon_url('https://github.com/%s/%s-Wiki/wiki/3rd-Party-APIs-Guide' % (plexpy.CONFIG.GIT_USER, plexpy.CONFIG.GIT_REPO))}'>3rd Party APIs Guide</a> for instructions on setting up MaxMind.<br>
</p>
<div class="form-group">
<label for="maxmind_license_key">MaxMind License Key</label>
<div class="row">
<div class="col-md-6">
<input type="text" class="form-control" id="maxmind_license_key" name="maxmind_license_key" value="${config['maxmind_license_key']}" data-parsley-trigger="change">
</div>
</div>
<p class="help-block">
Enter and save your MaxMind License Key to install the GeoLite2 database.
</p>
</div>
<div class="form-group">
<label for="geoip_db">GeoLite2 Database File</label> ${docker_msg | n}
<div class="row">
<div class="col-md-9">
<div class="input-group">
<input type="text" class="form-control" id="geoip_db" name="geoip_db" value="${config['geoip_db']}" ${docker_setting}>
<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="uninstall_geoip_db">Uninstall</button>
</span>
</div>
</div>
</div>
<p class="help-block">
GeoLite2 Database last updated <strong><span id="geoip_db_updated">never</span></strong>.
</p>
</div>
<div class="form-group advanced-setting">
<label for="geoip_db_update_days">GeoLite2 Database Update Interval</label>
<div class="row">
<div class="col-md-2">
<input type="text" class="form-control" data-parsley-type="integer" id="geoip_db_update_days" name="geoip_db_update_days" value="${config['geoip_db_update_days']}" size="5" data-parsley-range="[7, 30]" data-parsley-trigger="change" data-parsley-errors-container="#geoip_db_update_days_error" required>
</div>
<div id="geoip_db_update_days_error" class="alert alert-danger settings-alert" role="alert"></div>
</div>
<p class="help-block">The interval (in days) Tautulli will automatically update the GeoLite2 database. Minimum 7, maximum 30, default 30.</p>
</div>
<p><input type="button" class="btn btn-bright save-button" value="Save" data-success="Changes saved successfully"></p>
</div>
<div role="tabpanel" class="tab-pane" id="tabs-notification_agents">
<div class="padded-header">
<h3>Notification Agents</h3>
</div>
<p class="help-block">
Add a new notification agent, or configure an existing notification agent by clicking the settings icon on the right.
</p>
<p class="help-block">
Please see the <a target='_blank' href='${anon_url('https://github.com/%s/%s-Wiki/wiki/Notification-Agents-Guide' % (plexpy.CONFIG.GIT_USER, plexpy.CONFIG.GIT_REPO))}'>Notification Agents Guide</a> for instructions on setting up each notification agent.
</p>
<br />
<div id="plexpy-notifiers-table">
<div class='text-muted'><i class="fa fa-refresh fa-spin"></i> Loading notification agents...</div>
<br>
</div>
</div>
<div role="tabpanel" class="tab-pane" id="tabs-newsletter_agents">
<div class="padded-header">
<h3>Newsletter Agents</h3>
</div>
<p class="help-block">
Add a new newsletter agent, or configure an existing newsletter agent by clicking the settings icon on the right.
</p>
<p class="help-block settings-warning" id="newsletter_upload_warning">
Warning: The <a data-tab-destination="tabs-notifications" data-target="#notify_upload_posters">Image Hosting</a> setting must be enabled for images to display on the newsletter.</span>
</p>
<br/>
<div id="plexpy-newsletters-table">
<div class='text-muted'><i class="fa fa-refresh fa-spin"></i> Loading newsletter agents...</div>
<br>
</div>
</div>
<div role="tabpanel" class="tab-pane" id="tabs-import_backups">
<div class="padded-header">
@@ -1316,7 +1379,7 @@
<div class="form-group">
<label>Registered Devices</label>
<p class="help-block">Register a new device using a QR code, or configure an existing device by clicking the settings icon on the right.</p>
<p id="app_api_msg" style="color: #eb8600;">The API must be enabled under <a data-tab-destination="tabs-web_interface" data-target="#api_enabled">Web Interface</a> to use the app.</p>
<p id="app_api_msg" style="color: #eb8600;">Warning: The API must be enabled under <a data-tab-destination="web_interface" data-target="api_enabled">Web Interface</a> to use the app.</p>
<div class="row">
<div id="plexpy-mobile-devices-table" class="col-md-12">
<div class='text-muted'><i class="fa fa-refresh fa-spin"></i> Loading registered devices...</div>
@@ -1796,11 +1859,6 @@ Rating: {rating}/10 --> Rating: /10
async: true,
complete: function(xhr, status) {
$("#plexpy-configuration-table").html(xhr.responseText);
if ("${kwargs.get('install_geoip')}" == 'true') {
$('#install_geoip_db').removeClass('no-highlight').css('color','#e9a049');
} else if ("${kwargs.get('reinstall_geoip')}" == 'true') {
$('#reinstall_geoip_db').removeClass('no-highlight').css('color','#e9a049');
}
}
});
}
@@ -1943,6 +2001,7 @@ $(document).ready(function() {
getNewslettersTable();
getMobileDevicesTable();
loadUpdateDistros();
enableGeoLiteInstallButton();
settingsChanged = false;
}
@@ -2773,25 +2832,75 @@ $(document).ready(function() {
$('#allow_guest_access').click(function () {
newsletterPasswordEnabled();
})
});
function gotoSetting(tab, setting){
$("a[href=#tabs-" + tab + "]").click();
if (setting) {
_setting = '#' + setting;
if ($(_setting).closest('.advanced-setting').length && !$('#menu_link_show_advanced_settings').hasClass('active')) {
$('#menu_link_show_advanced_settings').click()
}
var body_container = $('.body-container');
var scroll_pos = setting ? body_container.scrollTop() + $(_setting).offset().top - 100 : 0;
body_container.animate({scrollTop: scroll_pos});
$(_setting).closest('.form-group, .checkbox').delay(500).fadeOut().fadeIn('slow').fadeOut().fadeIn('slow');
}
}
$('body').on('click', 'a[data-tab-destination]', function () {
var tab = $(this).data('tab-destination');
$("a[href=#" + tab + "]").click();
var scroll_destination = $(this).data('target');
if (scroll_destination) {
if ($(scroll_destination).closest('.advanced-setting').length && !$('#menu_link_show_advanced_settings').hasClass('active')) {
$('#menu_link_show_advanced_settings').click()
}
var body_container = $('.body-container')
var scroll_pos = scroll_destination ? body_container.scrollTop() + $(scroll_destination).offset().top - 100 : 0;
body_container.animate({scrollTop: scroll_pos});
}
var setting = $(this).data('target');
gotoSetting(tab, setting)
});
$('#resources-xml').on('tripleclick', function () {
openPlexXML('/api/resources', true, {includeHttps: 1});
});
if ("${kwargs.get('install_geoip')}" === 'true') {
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") {
$("#geoip_db_updated").text(moment("${config['geoip_db_installed']}", "X").fromNow());
}
$("#install_geoip_db").click(function () {
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 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 />';
var url = 'install_geoip_db';
if ($(this).text() === 'Update') {
url += '?update=true';
}
confirmAjaxCall(url, msg, null, 'Installing GeoLite2 database.', function (result) {
if (result.result === "success") {
$('#install_geoip_db').text('Update');
$('#geoip_db_updated').text(moment(result.updated, "X").fromNow());
}
getSchedulerTable();
});
});
$("#uninstall_geoip_db").click(function () {
var msg = 'Are you sure you want to uninstall the GeoLite2 database?<br /><br />' +
'You will not be able to lookup IP address geolocation info.';
var url = 'uninstall_geoip_db';
confirmAjaxCall(url, msg, null, 'Uninstalling GeoLite2 database.', function (result) {
if (result.result === "success") {
$('#install_geoip_db').text('Install');
$('#geoip_db_updated').text('never');
}
getSchedulerTable();
});
});
});
</script>
</%def>

View File

@@ -21,28 +21,21 @@
<link href="${http_root}css/font-awesome.v4-shims.min.css" rel="stylesheet">
<!-- Favicons -->
<link rel="icon" type="image/png" sizes="32x32" href="${http_root}images/favicon/favicon-32x32.png?v=2.0.0">
<link rel="icon" type="image/png" sizes="16x16" href="${http_root}images/favicon/favicon-16x16.png?v=2.0.0">
<link rel="shortcut icon" href="${http_root}images/favicon/favicon.ico?v=2.0.0">
<link rel="icon" type="image/png" sizes="32x32" href="${http_root}images/favicon/favicon-32x32.png?v=2.0.5">
<link rel="icon" type="image/png" sizes="16x16" href="${http_root}images/favicon/favicon-16x16.png?v=2.0.5">
<link rel="shortcut icon" href="${http_root}images/favicon/favicon.ico?v=2.0.5">
<!-- ICONS -->
<!-- Android >M39 icon -->
<link rel="icon" type="image/png" sizes="192x192" href="${http_root}images/favicon/android-chrome-192x192.png?v=2.0.0">
<link rel="manifest" href="${http_root}json/Android-manifest.json?v=2.0.0">
<meta name="theme-color" content="#1f1f1f">
<!-- Android -->
<link rel="manifest" href="${http_root}images/favicon/manifest.json?v=2.0.5">
<meta name="theme-color" content="#282a2d">
<!-- Apple -->
<link rel="apple-touch-icon" sizes="180x180" href="${http_root}images/favicon/apple-touch-icon.png?v=2.0.0">
<link rel="mask-icon" href="${http_root}images/favicon/safari-pinned-tab.svg?v=2.0.0" color="#1f1f1f">
<link rel="apple-touch-icon" sizes="180x180" href="${http_root}images/favicon/apple-touch-icon.png?v=2.0.5">
<link rel="mask-icon" href="${http_root}images/favicon/safari-pinned-tab.svg?v=2.0.5" color="#282a2d">
<meta name="apple-mobile-web-app-title" content="Tautulli">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black">
<meta name="viewport" content="initial-scale=1">
<meta name="format-detection" content="telephone=no">
<!-- IE10 icon -->
<!-- Microsoft -->
<meta name="application-name" content="Tautulli">
<meta name="msapplication-TileColor" content="#1f1f1f">
<meta name="msapplication-TileImage" content="${http_root}images/favicon/mstile-144x144.png?v=2.0.0">
<meta name="msapplication-config" content="${http_root}xml/IEconfig.xml?v=2.0.0" />
<meta name="msapplication-config" content="${http_root}images/favicon/browserconfig.xml?v=2.0.5">
</head>
<body>
@@ -67,8 +60,38 @@
</p>
</div>
</div>
<div class="wizard-card" data-cardname="card2">
<h3>Plex Authentication</h3>
<h3>Authentication</h3>
<div class="wizard-input-section">
<p class="help-block">
Please setup an admin username and password for Tautulli.
</p>
</div>
<div class="wizard-input-section">
<label for="http_username">HTTP Username</label>
<div class="row">
<div class="col-xs-8">
<input type="text" class="form-control auth-settings" id="http_username" name="http_username" value="" size="30">
</div>
</div>
</div>
<div class="wizard-input-section">
<label for="http_password">HTTP Password</label>
<div class="row">
<div class="col-xs-8">
<input type="password" class="form-control auth-settings" id="http_password" name="http_password" value="" size="30" autocomplete="new-password">
</div>
</div>
</div>
<input type="hidden" class="form-control" name="http_hash_password" id="http_hash_password" value="1">
<input type="hidden" class="form-control" name="http_plex_admin" id="http_plex_admin" value="1">
<input type="hidden" id="authentication_valid" data-validate="validateAuthentication" value="">
<span style="display: none;" id="authentication-status"></span>
</div>
<div class="wizard-card" data-cardname="card3">
<h3>Plex Account</h3>
<div class="wizard-input-section">
<p class="help-block">
Tautulli requires a Plex.tv account. Click the button below to sign in on Plex.tv. You may need to allow popups in your browser.
@@ -78,7 +101,8 @@
<a class="btn btn-dark" id="sign-in-plex" href="#" role="button">Sign In with Plex</a>
<span style="margin-left: 10px; display: none;" id="pms-token-status"></span>
</div>
<div class="wizard-card" data-cardname="card3">
<div class="wizard-card" data-cardname="card4">
<h3>Plex Media Server</h3>
<div class="wizard-input-section">
<p class="help-block">
@@ -137,7 +161,7 @@
<span style="margin-left: 10px; display: none;" id="pms-verify-status"></span>
</div>
<div class="wizard-card" data-cardname="card4">
<div class="wizard-card" data-cardname="card5">
<h3>Activity Logging</h3>
<div class="wizard-input-section">
<p class="help-block">
@@ -162,7 +186,7 @@
</div>
</div>
<div class="wizard-card" data-cardname="card4">
<div class="wizard-card" data-cardname="card6">
<h3>Notifications</h3>
<div class="wizard-input-section">
<p class="help-block">
@@ -175,7 +199,7 @@
</div>
</div>
<div class="wizard-card" data-cardname="card5">
<div class="wizard-card" data-cardname="card7">
<h3>Database Import</h3>
<div class="wizard-input-section">
<p class="help-block">
@@ -227,11 +251,29 @@
<script src="${http_root}js/script.js${cache_param}"></script>
<script src="${http_root}js/bootstrap-wizard.min.js"></script>
<script>
function validateAuthentication(el) {
var http_username = $("#http_username").val();
var http_password = $("#http_password").val();
var valid_authentication = el.val();
var retValue = {};
if (http_username === "" || http_password === "") {
retValue.status = false;
retValue.msg = "Please enter a username and password.";
$("#authentication-status").html('<i class="fa fa-exclamation-circle"></i> Please enter a username and password.');
$('#authentication-status').fadeIn('fast').delay(2000).fadeOut('fast');
} else {
retValue.status = true;
}
return retValue;
}
function validatePMSip(el) {
var valid_pms_ip = el.val();
var retValue = {};
if (valid_pms_ip == "") {
if (valid_pms_ip === "") {
retValue.status = false;
retValue.msg = "Please verify your server.";
$("#pms-verify-status").html('<i class="fa fa-exclamation-circle"></i> Please verify your server.');
@@ -247,7 +289,7 @@
var valid_pms_token = el.val();
var retValue = {};
if (valid_pms_token == "") {
if (valid_pms_token === "") {
retValue.status = false;
retValue.msg = "Please authenticate.";
$("#pms-token-status").html('<i class="fa fa-exclamation-circle"></i> Please authenticate.');
@@ -284,7 +326,7 @@ $(document).ready(function() {
$.fn.wizard.logging = false;
var options = {
keyboard : false,
contentHeight : 400,
contentHeight : 450,
contentWidth : 700,
backdrop: 'static',
buttons: {submitText: 'Finish'},

View File

@@ -22,8 +22,8 @@ from pytz.tzfile import build_tzinfo
# The IANA (nee Olson) database is updated several times a year.
OLSON_VERSION = '2019a'
VERSION = '2019.1' # pip compatible version number.
OLSON_VERSION = '2019c'
VERSION = '2019.3' # pip compatible version number.
__version__ = VERSION
OLSEN_VERSION = OLSON_VERSION # Old releases had this misspelling
@@ -188,8 +188,14 @@ def _unmunge_zone(zone):
return zone.replace('_plus_', '+').replace('_minus_', '-')
_all_timezones_lower_to_standard = None
def _case_insensitive_zone_lookup(zone):
"""case-insensitively matching timezone, else return zone unchanged"""
global _all_timezones_lower_to_standard
if _all_timezones_lower_to_standard is None:
_all_timezones_lower_to_standard = dict((tz.lower(), tz) for tz in all_timezones) # noqa
return _all_timezones_lower_to_standard.get(zone.lower()) or zone # noqa
@@ -1098,7 +1104,6 @@ all_timezones = LazyList(
tz for tz in all_timezones if resource_exists(tz))
all_timezones_set = LazySet(all_timezones)
_all_timezones_lower_to_standard = dict((tz.lower(), tz) for tz in all_timezones)
common_timezones = \
['Africa/Abidjan',
'Africa/Accra',

View File

@@ -27,8 +27,8 @@ from pytz.tzinfo import DstTzInfo, StaticTzInfo # noqa
# I test for expected version to ensure the correct version of pytz is
# actually being tested.
EXPECTED_VERSION = '2019.1'
EXPECTED_OLSON_VERSION = '2019a'
EXPECTED_VERSION = '2019.3'
EXPECTED_OLSON_VERSION = '2019c'
fmt = '%Y-%m-%d %H:%M:%S %Z%z'
@@ -183,8 +183,14 @@ class PicklingTest(unittest.TestCase):
# Python 3 introduced a new pickle protocol where numbers are stored in
# hexadecimal representation. Here we extract the pickle
# representation of the number for the current Python version.
old_pickle_pattern = pickle.dumps(tz._utcoffset.seconds)[3:-1]
new_pickle_pattern = pickle.dumps(new_utcoffset)[3:-1]
#
# Test protocol 3 on Python 3 and protocol 0 on Python 2.
if sys.version_info >= (3,):
protocol = 3
else:
protocol = 0
old_pickle_pattern = pickle.dumps(tz._utcoffset.seconds, protocol)[3:-1]
new_pickle_pattern = pickle.dumps(new_utcoffset, protocol)[3:-1]
hacked_p = p.replace(old_pickle_pattern, new_pickle_pattern)
self.assertNotEqual(p, hacked_p)

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Some files were not shown because too many files have changed in this diff Show More