plexpy/data/interfaces/default/settings.html
2015-08-26 16:04:02 -07:00

1182 lines
No EOL
68 KiB
HTML

<%inherit file="base.html"/>
<%!
import plexpy
from plexpy import notifiers, common, versioncheck
available_notification_agents = notifiers.available_notification_agents()
%>
<%def name="headIncludes()">
</%def>
<%def name="headerIncludes()">
</%def>
<%def name="body()">
<div class="container">
<div class="row">
<div class="col-md-12">
<div class='card-back-full'>
<div class="header-bar">
<span><i class="fa fa-cog"></i> Settings</span>
</div>
<div class="button-bar">
% if config['check_github']:
<button id="menu_link_update_check" class="btn btn-dark"><i class="fa fa-arrow-circle-up"></i> Check for Updates</button>
% endif
<button id="menu_link_restart" class="btn btn-dark"><i class="fa fa-refresh"></i> Restart</button>
<button id="menu_link_shutdown" class="btn btn-dark"><i class="fa fa-power-off"></i> Shut Down</button>
</div>
</div>
</div>
</div>
<div class="row">
<!-- Nav tabs -->
<div class="col-md-4">
<ul class="nav-settings list-unstyled" role="tablist">
<li role="presentation" class="active"><a href="#tabs-1" aria-controls="tabs-1" role="tab" data-toggle="tab">General</a></li>
<li role="presentation"><a href="#tabs-2" aria-controls="tabs-2" role="tab" data-toggle="tab">Web Interface</a></li>
<li role="presentation"><a href="#tabs-3" aria-controls="tabs-3" role="tab" data-toggle="tab">Access Control</a></li>
<li role="presentation"><a href="#tabs-4" aria-controls="tabs-4" role="tab" data-toggle="tab">Plex Media Server</a></li>
<li role="presentation"><a href="#tabs-5" aria-controls="tabs-5" role="tab" data-toggle="tab">Plex.tv Account</a></li>
<li role="presentation"><a href="#tabs-6" aria-controls="tabs-6" role="tab" data-toggle="tab">Extra Settings</a></li>
<li role="presentation"><a href="#tabs-7" aria-controls="tabs-7" role="tab" data-toggle="tab">Monitoring</a></li>
<li role="presentation"><a href="#tabs-8" aria-controls="tabs-8" role="tab" data-toggle="tab">Notifications</a></li>
<li role="presentation"><a href="#tabs-9" aria-controls="tabs-9" role="tab" data-toggle="tab">Notification Agents</a></li>
</ul>
</div>
<div class="col-md-8">
<form action="configUpdate" method="post" class="form" id="configUpdate" data-parsley-validate>
<div class="tab-content">
<div role="tabpanel" class="tab-pane active" id="tabs-1">
% if common.VERSION_NUMBER:
<div class="padded-header">
<h3>Version ${common.VERSION_NUMBER} <small><a href="#changelog-modal" data-toggle="modal"><i class="fa fa-info-circle"></i> Changelog</a></small></h3>
</div>
% endif
<div class="checkbox">
<label>
<input type="checkbox" id="check_github" name="check_github" value="1" ${config['check_github']}> Enable Updates
</label>
<p class="help-block">If you have Git installed, allow periodic checks for updates.</p>
</div>
% if plexpy.CURRENT_VERSION:
<p class="help-block">Git hash: ${plexpy.CURRENT_VERSION}</p>
% endif
<div class="padded-header">
<h3>Display Settings</h3>
</div>
<div class="form-group">
<label for="date_format">Date Format</label>
<div class="row">
<div class="col-md-4">
<input type="text" class="form-control" id="date_format" name="date_format" value="${config['date_format']}" data-parsley-trigger="change" required>
</div>
</div>
<p class="help-block">Set your preferred date format. <a href="javascript:void(0)" data-target="#dateTimeOptionsModal" data-toggle="modal">Click here</a> to see the parameter list.</p>
</div>
<div class="form-group">
<label for="date_format">Time Format</label>
<div class="row">
<div class="col-md-2">
<input type="text" class="form-control" id="time_format" name="time_format" value="${config['time_format']}" data-parsley-trigger="change" required>
</div>
</div>
<p class="help-block">Set your preferred time format. <a href="javascript:void(0)" data-target="#dateTimeOptionsModal" data-toggle="modal">Click here</a> to see the parameter list.</p>
</div>
<div class="padded-header">
<h3>Homepage Statistics</h3>
</div>
<div class="form-group">
<label for="home_stats_length">Time Frame</label>
<div class="row">
<div class="col-md-2">
<input type="text" class="form-control" data-parsley-type="integer" id="home_stats_length" name="home_stats_length" value="${config['home_stats_length']}" size="3" data-parsley-min="0" data-parsley-trigger="change" data-parsley-errors-container="#home_stats_length_error" required>
</div>
<div id="home_stats_length_error" class="alert alert-danger settings-alert" role="alert"></div>
</div>
<p class="help-block">Specify the number of days for the statistics on the home page. Default is 30 days.</p>
</div>
<div class="form-group">
<label for="home_stats_count">Top Lists</label>
<div class="row">
<div class="col-md-2">
<input type="text" class="form-control" data-parsley-type="integer" id="home_stats_count" name="home_stats_count" value="${config['home_stats_count']}" size="3" data-parsley-range="[0,10]" data-parsley-trigger="change" data-parsley-errors-container="#home_stats_count_error" required>
</div>
<div id="home_stats_count_error" class="alert alert-danger settings-alert" role="alert"></div>
</div>
<p class="help-block">Specify the number of items to show in the top lists for the statistics on the home page. Max is 10 items, default is 5 items, 0 to disable.</p>
</div>
<div class="checkbox">
<label>
<input type="checkbox" id="home_stats_type" name="home_stats_type" value="1" ${config['home_stats_type']}> Use play duration
</label>
<p class="help-block">Use play duration instead of play count to generate statistics.</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-2">
<div class="padded-header">
<h3>Web Interface</h3>
</div>
<p class="help-block">Web interface changes require a restart.</p>
<div class="form-group">
<label for="http_host">HTTP Host</label>
<div class="row">
<div class="col-md-6">
<input type="text" class="form-control" id="http_host" name="http_host" value="${config['http_host']}" data-parsley-trigger="change" required>
</div>
</div>
<p class="help-block">e.g. localhost or an IP, such as 0.0.0.0</p>
</div>
<div class="form-group">
<label for="http_port">HTTP Port</label>
<div class="row">
<div class="col-md-2">
<input type="text" class="form-control" data-parsley-type="integer" id="http_port" name="http_port" value="${config['http_port']}" data-parsley-trigger="change" data-parsley-errors-container="#http_port_error" required>
</div>
<div id="http_port_error" class="alert alert-danger settings-alert" role="alert"></div>
</div>
<p class="help-block">Port to bind web server to. Note that ports below 1024 may require root.</p>
</div>
<div class="checkbox">
<label>
<input type="checkbox" name="launch_browser" value="1" ${config['launch_browser']}> Launch Browser on Startup
</label>
<p class="help-block">Launch browser pointed to PlexPy, on startup.</p>
</div>
<div class="checkbox">
<label>
<input type="checkbox" name="enable_https" id="enable_https" value="1" ${config['enable_https']} /> Enable HTTPS
</label>
<p class="help-block">Enable HTTPS for web server for encrypted communication.</p>
</div>
<div id="https_options">
<div class="form-group">
<label for="https_cert">HTTPS Cert</label>
<input type="text" class="form-control" id="https_cert" name="https_cert" value="${config['https_cert']}">
</div>
<div class="form-group">
<label for="https_key">HTTPS Key</label>
<input type="text" class="form-control" id="https_key" name="https_key" value="${config['https_key']}">
</div>
</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-3">
<div class="padded-header">
<h3>Authentication</h3>
</div>
<p class="help-block">Authentication changes require a restart.</p>
<div class="form-group">
<label for="http_username">HTTP Username</label>
<div class="row">
<div class="col-md-4">
<input type="text" class="form-control" id="http_username" name="http_username" value="${config['http_username']}" size="30">
</div>
</div>
<p class="help-block">Username for web server authentication. Leave empty to disable.</p>
</div>
<div class="form-group">
<label for="http_password">HTTP Password</label>
<div class="row">
<div class="col-md-4">
<input type="password" class="form-control" id="http_password" name="http_password" value="${config['http_password']}" size="30">
</div>
</div>
<p class="help-block">Password for web server authentication. Leave empty to disable.</p>
</div>
<div class="padded-header">
<h3>API</h3>
</div>
<div class="checkbox">
<label>
<input type="checkbox" id="api_enabled" name="api_enabled" value="1" ${config['api_enabled']}> Enable API
</label>
<p class="help-block">Allow remote applications to interface with PlexPy.</p>
</div>
<div id="apioptions" class="form-group">
<label for="api_key">API key</label>
<div class="row">
<div class="col-md-6">
<div class="input-group">
<input class="form-control" type="text" name="api_key" id="api_key" value="${config['api_key']}" size="20">
<span class="input-group-btn">
<button class="btn btn-form" type="button" id="generate_api">Generate</button>
</span>
</div>
</div>
</div>
<p class="help-block">Current API key: <strong><br/>${config['api_key']}</strong></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-4">
<div class="padded-header">
<h3>Plex Media Server</h3>
</div>
<div class="form-group has-feedback" id="pms-ip-group">
<label for="pms_ip">Plex IP or Hostname</label>
<div class="row">
<div class="col-md-6">
<input type="text" class="pms-settings form-control" id="pms_ip" name="pms_ip" value="${config['pms_ip']}" size="30" data-parsley-trigger="change" aria-describedby="server-verified" required>
<span class="form-control-feedback" id="pms-verify" aria-hidden="true" style="display: none;"></span>
</div>
</div>
<p class="help-block">IP Address or hostname for Plex Media Server.</p>
</div>
<div class="form-group">
<label for="pms_port">Plex Port</label>
<div class="row">
<div class="col-md-2">
<input data-parsley-type="integer" class="pms-settings form-control" type="text" id="pms_port" name="pms_port" value="${config['pms_port']}" size="30" data-parsley-trigger="change" data-parsley-errors-container="#pms_port_error" required>
</div>
<div id="pms_port_error" class="alert alert-danger settings-alert" role="alert"></div>
</div>
<p class="help-block">Port that Plex Media Server is listening on.</p>
</div>
<div class="checkbox">
<label>
<input type="checkbox" id="pms_is_remote" name="pms_is_remote" value="1" ${config['pms_is_remote']}> Remote Server
</label>
<p class="help-block">Check this is your Plex Server is not on the same local network as PlexPy.</p>
</div>
<div class="checkbox">
<label>
<input type="checkbox" id="pms_ssl" name="pms_ssl" value="1" ${config['pms_ssl']}> Force SSL
</label>
<p class="help-block">Force PlexPy to connect to your Plex Server via SSL. Your server needs to have remote access enabled.</p>
</div>
<div class="padded-header">
<h3>Plex Logs</h3>
</div>
<div class="form-group">
<label for="pms_logs_folder">Logs Folder</label>
<div class="row">
<div class="col-md-6">
<input type="text" class="form-control" id="pms_logs_folder" name="pms_logs_folder" value="${config['pms_logs_folder']}" size="30" data-parsley-trigger="change">
</div>
</div>
<p class="help-block">Set the folder where your Plex Server logs are. This is required if you enable IP logging.<br /><a href="https://support.plex.tv/hc/en-us/articles/200250417-Plex-Media-Server-Log-Files" target="_blank">Click here</a> for help.</p>
</div>
<input type="hidden" id="pms_identifier" name="pms_identifier" value="${config['pms_identifier']}">
<input type="button" class="btn btn-bright save-button" value="Save" data-success="Changes saved successfully">
</div>
<div role="tabpanel" class="tab-pane" id="tabs-5">
<div class="padded-header">
<h3>Plex.tv Authentication</h3>
</div>
<div class="form-group">
<label for="pms_token">PMS Token</label>
<div class="row">
<div class="col-md-6">
<div class="input-group">
<input type="text" class="form-control" id="pms_token" name="pms_token" value="${config['pms_token']}" data-parsley-trigger="change" required>
<span class="input-group-btn">
<button class="btn btn-form" type="button" data-toggle="modal" data-target="#pms-auth-modal">Fetch Token</button>
</span>
</div>
</div>
</div>
<p class="help-block">Token for Plex.tv authentication.</p>
</div>
<div class="padded-header">
<h3>Friends List</h3>
</div>
<div class="form-group">
<label for="refresh_users_interval">User list Refresh Interval</label>
<div class="row">
<div class="col-md-2">
<input type="text" class="form-control" data-parsley-type="integer" id="refresh_users_interval" name="refresh_users_interval" value="${config['refresh_users_interval']}" size="5" data-parsley-range="[1,24]" data-parsley-trigger="change" data-parsley-errors-container="#refresh_users_interval_error" required>
</div>
<div id="refresh_users_interval_error" class="alert alert-danger settings-alert" role="alert"></div>
</div>
<p class="help-block">The interval (in hours) PlexPy will request an updated friends list from Plex.tv. 1 minimum, 24 maximum.</p>
</div>
<div class="checkbox">
<label>
<input type="checkbox" id="refresh_users_on_startup" name="refresh_users_on_startup" value="1" ${config['refresh_users_on_startup']}> Refresh user list on startup
</label>
<p class="help-block">Refresh the user list when PlexPy starts.</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-6">
<div class="padded-header">
<h3>Extra Settings</h3>
</div>
<div class="checkbox">
<label>
<input type="checkbox" id="pms_use_bif" name="pms_use_bif" value="1" ${config['pms_use_bif']}> Use BIF thumbs
</label>
<p class="help-block">If you have media indexing enabled on your server, use these on the activity pane.</p>
</div>
<div class="padded-header">
<h3>PlexWatch Import Tool</h3>
</div>
<p class="help-block"><a href="javascript:void(0)" id="toggle-plexwatch-import-modal" data-target="#plexwatch-import-modal" data-toggle="modal">Click here to Import an existing Plexwatch database.</a></p>
<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-7">
<div class="padded-header">
<h3>Monitoring Settings</h3>
</div>
<div class="form-group">
<label for="monitoring_interval">Monitoring Interval</label>
<div class="row">
<div class="col-md-2">
<input type="text" class="form-control" data-parsley-type="integer" id="monitoring_interval" name="monitoring_interval" value="${config['monitoring_interval']}" size="5" data-parsley-min="30" data-parsley-trigger="change" data-parsley-errors-container="#monitoring_interval_error" required>
</div>
<div id="monitoring_interval_error" class="alert alert-danger settings-alert" role="alert"></div>
</div>
<p class="help-block">The interval (in seconds) PlexPy will ping your Plex Server. Min 30 seconds, recommended 60 seconds.</p>
</div>
<div class="padded-header">
<h3>History Logging</h3>
</div>
<div class="checkbox">
<label>
<input type="checkbox" id="video_logging_enable" name="video_logging_enable" value="1" ${config['video_logging_enable']}> Log Movies and TV
</label>
<p class="help-block">Keep records of all video items played from your Plex Media Server.</p>
</div>
<div class="form-group">
<label for="logging_ignore_interval">Ignore Interval</label>
<div class="row">
<div class="col-md-2">
<input type="text" class="form-control" data-parsley-type="integer" id="logging_ignore_interval" name="logging_ignore_interval" value="${config['logging_ignore_interval']}" size="5" data-parsley-min="0" data-parsley-trigger="change" data-parsley-errors-container="#logging_ignore_interval_error" required>
</div>
<div id="logging_ignore_interval_error" class="alert alert-danger settings-alert" role="alert"></div>
</div>
<p class="help-block">The interval (in seconds) PlexPy will wait for a video item to be active before logging it. 0 to disable.</p>
</div>
<div class="checkbox">
<label>
<input type="checkbox" id="music_logging_enable" name="music_logging_enable" value="1" ${config['music_logging_enable']}> Log Music
</label>
<p class="help-block">Keep records of all audio items played from your Plex Media Server. VERY experimental.</p>
</div>
<div class="padded-header">
<h3>IP Logging</h3>
</div>
<div class="checkbox">
<label>
<input type="checkbox" id="ip_logging_enable" name="ip_logging_enable" value="1" ${config['ip_logging_enable']}> Enable IP Logging
</label>
<span id="debugLogCheck" style="color: #eb8600; padding-left: 10px;"></span>
<p class="help-block">
Enable this to attempt to log the IP address of the user.
</p>
</div>
<div class="padded-header">
<h3>Buffer Warnings</h3>
</div>
<p class="help-block">Note: Buffer warnings only work on certain Plex clients. Android and PlexWeb do not report buffer events accurately or at all.</p>
<div class="form-group">
<label for="buffer_threshold">Buffer Threshold</label>
<div class="row">
<div class="col-md-2">
<input type="text" class="form-control" data-parsley-type="integer" id="buffer_threshold" name="buffer_threshold" value="${config['buffer_threshold']}" data-parsley-range="[0,50]" data-parsley-trigger="change" data-parsley-errors-container="#buffer_threshold_error" required>
</div>
<div id="buffer_threshold_error" class="alert alert-danger settings-alert" role="alert"></div>
</div>
<p class="help-block">How many buffer events should we wait before triggering the first warning. Buffer events increment on each monitor ping if play state is buffering. 0 to disable buffer warnings.</p>
</div>
<div class="form-group">
<label for="buffer_wait">Buffer Wait</label>
<div class="row">
<div class="col-md-2">
<input type="text" class="form-control" data-parsley-type="integer" id="buffer_wait" name="buffer_wait" value="${config['buffer_wait']}" data-parsley-min="0" data-parsley-trigger="change" data-parsley-errors-container="#buffer_wait_error" required>
</div>
<div id="buffer_wait_error" class="alert alert-danger settings-alert" role="alert"></div>
</div>
<p class="help-block">The value (in seconds) PlexPy should wait before triggering the next buffer warning. 0 to always trigger.</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-8">
<div class="padded-header">
<h3>Global Notification Toggles</h3>
</div>
<div class="checkbox">
<label>
<input type="checkbox" name="movie_notify_enable" id="movie_notify_enable" value="1" ${config['movie_notify_enable']}> Enable Movie and TV Notifications
</label>
</div>
<div class="checkbox">
<label>
<input type="checkbox" name="music_notify_enable" id="music_notify_enable" value="1" ${config['music_notify_enable']}> Enable Music Notifications
</label>
</div>
<div class="padded-header">
<h3>Notification Tuning</h3>
</div>
<div class="form-group">
<label for="notify_watched_percent">Watched Percent</label>
<div class="row">
<div class="col-md-2">
<input type="text" class="form-control" data-parsley-type="integer" id="notify_watched_percent" name="notify_watched_percent" value="${config['notify_watched_percent']}" size="5" data-parsley-range="[50,95]" data-parsley-trigger="change" data-parsley-errors-container="#notify_watched_percent_error" required>
</div>
<div id="notify_watched_percent_error" class="alert alert-danger settings-alert" role="alert"></div>
</div>
<p class="help-block">Set the progress percentage of when a watched notification should be triggered. Minimum 50, Maximum 95.</p>
</div>
<div class="padded-header">
<h3>Custom Notification Messages</h3>
</div>
<p class="help-block">
You can set custom formatted text for each type of notification.
Click <a href="#notify-text-sub-modal" data-toggle="modal">here</a> for a list of available parameters which can be used.
</p>
<p class="help-block">
You can also add tags to exclude certain text depending on the media type. Click
<a href="#notify-text-tags-modal" data-toggle="modal">here</a> to view usage information.
</p>
<br/>
<ul id="accordion" class="accordion list-unstyled">
<li>
<div class="link"><i class="fa fa-play"></i>Playback Start<i class="fa fa-chevron-down"></i></div>
<ul class="submenu">
<li>
<div class="form-group">
<label for="notify_on_start_subject_text">Subject Line</label>
<input class="form-control" type="text" id="notify_on_start_subject_text" name="notify_on_start_subject_text" value="${config['notify_on_start_subject_text']}" data-parsley-trigger="change" required>
<p class="help-block">Set a custom subject line.</p>
</div>
<div class="form-group">
<label for="notify_on_start_body_text">Message Body</label>
<input class="form-control" type="text" id="notify_on_start_body_text" name="notify_on_start_body_text" value="${config['notify_on_start_body_text']}" data-parsley-trigger="change" required>
<p class="help-block">Set a custom body.</p>
</div>
</li>
</ul>
</li>
<li>
<div class="link"><i class="fa fa-stop"></i>Playback Stop<i class="fa fa-chevron-down"></i></div>
<ul class="submenu">
<li>
<div class="form-group">
<label for="notify_on_stop_subject_text">Subject Line</label>
<input class="form-control" type="text" id="notify_on_stop_subject_text" name="notify_on_stop_subject_text" value="${config['notify_on_stop_subject_text']}" data-parsley-trigger="change" required>
<p class="help-block">Set a custom subject line.</p>
</div>
<div class="form-group">
<label for="notify_on_stop_body_text">Message Body</label>
<input class="form-control" type="text" id="notify_on_stop_body_text" name="notify_on_stop_body_text" value="${config['notify_on_stop_body_text']}" data-parsley-trigger="change" required>
<p class="help-block">Set a custom body.</p>
</div>
</li>
</ul>
</li>
<li>
<div class="link"><i class="fa fa-pause"></i>Playback Pause<i class="fa fa-chevron-down"></i></div>
<ul class="submenu">
<li>
<div class="form-group">
<label for="notify_on_pause_subject_text">Subject Line</label>
<input class="form-control" type="text" id="notify_on_pause_subject_text" name="notify_on_pause_subject_text" value="${config['notify_on_pause_subject_text']}" data-parsley-trigger="change" required>
<p class="help-block">Set a custom subject line.</p>
</div>
<div class="form-group">
<label for="notify_on_pause_body_text">Message Body</label>
<input class="form-control" type="text" id="notify_on_pause_body_text" name="notify_on_pause_body_text" value="${config['notify_on_pause_body_text']}" data-parsley-trigger="change" required>
<p class="help-block">Set a custom body.</p>
</div>
</li>
</ul>
</li>
<li>
<div class="link"><i class="fa fa-play"></i>Playback Resume<i class="fa fa-chevron-down"></i></div>
<ul class="submenu">
<li>
<div class="form-group">
<label for="notify_on_resume_subject_text">Subject Line</label>
<input class="form-control" type="text" id="notify_on_resume_subject_text" name="notify_on_resume_subject_text" value="${config['notify_on_resume_subject_text']}" data-parsley-trigger="change" required>
<p class="help-block">Set a custom subject line.</p>
</div>
<div class="form-group">
<label for="notify_on_resume_body_text">Message Body</label>
<input class="form-control" type="text" id="notify_on_resume_body_text" name="notify_on_resume_body_text" value="${config['notify_on_resume_body_text']}" data-parsley-trigger="change" required>
<p class="help-block">Set a custom body.</p>
</div>
</li>
</ul>
</li>
<li>
<div class="link"><i class="fa fa-eye"></i>Watched<i class="fa fa-chevron-down"></i></div>
<ul class="submenu">
<li>
<div class="form-group">
<label for="notify_on_watched_subject_text">Subject Line</label>
<input class="form-control" type="text" id="notify_on_watched_subject_text" name="notify_on_watched_subject_text" value="${config['notify_on_watched_subject_text']}" data-parsley-trigger="change" required>
<p class="help-block">Set a custom subject line.</p>
</div>
<div class="form-group">
<label for="notify_on_watched_body_text">Message Body</label>
<input class="form-control" type="text" id="notify_on_watched_body_text" name="notify_on_watched_body_text" value="${config['notify_on_watched_body_text']}" data-parsley-trigger="change" required>
<p class="help-block">Set a custom body.</p>
</div>
</li>
</ul>
</li>
<li>
<div class="link"><i class="fa fa-spinner"></i>Buffer Warnings<i class="fa fa-chevron-down"></i></div>
<ul class="submenu">
<li>
<div class="form-group">
<label for="notify_on_buffer_subject_text">Subject Line</label>
<input class="form-control" type="text" id="notify_on_buffer_subject_text" name="notify_on_buffer_subject_text" value="${config['notify_on_buffer_subject_text']}" data-parsley-trigger="change" required>
<p class="help-block">Set a custom subject line.</p>
</div>
<div class="form-group">
<label for="notify_on_buffer_body_text">Message Body</label>
<input class="form-control" type="text" id="notify_on_buffer_body_text" name="notify_on_buffer_body_text" value="${config['notify_on_buffer_body_text']}" data-parsley-trigger="change" required>
<p class="help-block">Set a custom body.</p>
</div>
</li>
</ul>
</li>
</ul>
<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-9">
<div class="padded-header">
<h3>Notification Agents</h3>
</div>
<p class="help-block">
Toggle the desired notification options by clicking the bell icon and configure it by clicking the settings icon to the right.
</p>
<br/>
<ul class="stacked-configs list-unstyled">
% for agent in available_notification_agents:
<li>
<span>
% if agent['on_play'] or agent['on_stop'] or agent['on_pause'] or agent['on_resume'] or agent['on_buffer'] or agent['on_watched']:
<a href="javascript:void(0)" data-target="#notification-triggers-modal" data-id="${agent['id']}" class="toggle-notification-triggers-modal toggle-left active" data-toggle="modal"><i class="fa fa-lg fa-bell"></i></a>
% else:
<a href="javascript:void(0)" data-target="#notification-triggers-modal" data-id="${agent['id']}" class="toggle-notification-triggers-modal toggle-left" data-toggle="modal"><i class="fa fa-lg fa-bell"></i></a>
% endif
${agent['name']}
% if agent['has_config']:
<a href="javascript:void(0)" rel="tooltip" data-target="#notification-config-modal" data-placement="top" title data-title="Open configuration" data-id="${agent['id']}" class="toggle-notification-config-modal toggle-right" data-toggle="modal"><i class="fa fa-lg fa-cog"></i></a>
% endif
</span>
</li>
% endfor
</ul>
</div>
</div>
</form>
</div>
</div>
<div id="dateTimeOptionsModal" class="modal fade" tabindex="-1" role="dialog" aria-labelledby="dateTimeOptionsModal">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">
<i class="fa fa-remove"></i>
</button>
<h4 class="modal-title">Date &amp; Time Format Options</h4>
</div>
<div class="modal-body">
<table>
<tbody>
<tr>
<td align="center" colspan="3"><h5>Day</h5></td>
</tr>
<tr>
<td width="100"><strong>DD</strong></td>
<td width="300">Numeric, with leading zeros</td>
<td>01 to 31</td>
</tr>
<tr>
<td><strong>D</strong></td>
<td>Numeric, without leading zeros</td>
<td>1 to 31</td>
</tr>
<tr>
<td><strong>Do</strong></td>
<td>The English suffix for the day of the month</td>
<td>st, nd or th in the 1st, 2nd or 15th.</td>
</tr>
<tr>
<td align="center" colspan="3"><h5>Month</h5></td>
</tr>
<tr>
<td><strong>MM</strong></td>
<td>Numeric, with leading zeros</td>
<td>01 to 31</td>
</tr>
<tr>
<td><strong>M</strong></td>
<td>Numeric, without leading zeros</td>
<td>1 to 31</td>
</tr>
<tr>
<td><strong>MMMM</strong></td>
<td>Textual full</td>
<td>January to December</td>
</tr>
<tr>
<td><strong>MMM</strong></td>
<td>Textual three letters</td>
<td>Jan to Dec</td>
</tr>
<tr>
<td align="center" colspan="3"><h5>Year</h5></td>
</tr>
<tr>
<td><strong>YYYY</strong></td>
<td>Numeric, 4 digits</td>
<td>Eg., 1999, 2003</td>
</tr>
<tr>
<td><strong>YY</strong></td>
<td>Numeric, 2 digits</td>
<td>Eg., 99, 03</td>
</tr>
<tr>
<td align="center" colspan="3"><h5>Time</h5></td>
</tr>
<tr>
<td><strong>a</strong></td>
<td width="300">am/pm Lowercase</td>
<td>am, pm</td>
</tr>
<tr>
<td><strong>A</strong></td>
<td>AM/PM Uppercase</td>
<td>AM, PM</td>
</tr>
<tr>
<td><strong>h</strong></td>
<td>Hour, 12-hour, without leading zeros</td>
<td>1-12</td>
</tr>
<tr>
<td><strong>hh</strong></td>
<td>Hour, 12-hour, with leading zeros</td>
<td>01-12</td>
</tr>
<tr>
<td><strong>H</strong></td>
<td>Hour, 24-hour, without leading zeros</td>
<td>0-23</td>
</tr>
<tr>
<td><strong>HH</strong></td>
<td>Hour, 24-hour, with leading zeros</td>
<td>00-23</td>
</tr>
<tr>
<td><strong>mm</strong></td>
<td>Minutes, with leading zeros</td>
<td>00-59</td>
</tr>
<tr>
<td><strong>ss</strong></td>
<td>Seconds, with leading zeros</td>
<td>00-59</td>
</tr>
<tr>
<td><strong>zz</strong></td>
<td>Timezone abbreviation</td>
<td>Eg., EST, MDT ...</td>
</tr>
</tbody>
</table>
</div>
<div class="modal-footer"></div>
</div>
</div>
</div>
<div id="pms-auth-modal" class="modal fade" tabindex="-1" role="dialog"
aria-labelledby="ip-info-modal">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true"><i
class="fa fa-remove"></i></button>
<h4 class="modal-title">Fetch Plex.tv Token</h4>
</div>
<div class="modal-body" id="modal-text">
<div>
<p class="help-block">
This will attempt to fetch your token for you. This will not work on Internet Explorer 9 or lower.
PlexPy does not store your username and password.
</p>
<div class="form-group">
<label for="pms_username">PMS Username</label>
<div class="row">
<div class="col-md-6">
<input type="text" class="form-control" id="pms_username" name="pms_username" size="30">
</div>
</div>
<p class="help-block">Username for Plex.tv authentication.</p>
</div>
<div class="form-group">
<label for="pms_password">PMS Password</label>
<div class="row">
<div class="col-md-6">
<input type="password" class="form-control" id="pms_password" name="pms_password" size="30">
</div>
</div>
<p class="help-block">Password for Plex.tv authentication.</p>
</div>
</div>
</div>
<div class="modal-footer">
<div style="float: left;">
<strong><span id="pms-token-status"></span></strong>
</div>
<input type="button" id="get-pms-auth-token" class="btn btn-bright" value="Fetch Token">
</div>
</div>
</div>
</div>
<div id="plexwatch-import-modal" class="modal fade" tabindex="-1" role="dialog" aria-labelledby="plexwatch-import-modal"></div>
<div id="notification-config-modal" class="modal fade" tabindex="-1" role="dialog" aria-labelledby="notification-config-modal"></div>
<div id="notification-triggers-modal" class="modal fade" tabindex="-1" role="dialog" aria-labelledby="notification-triggers-modal"></div>
<div id="notify-text-sub-modal" class="modal fade" tabindex="-1" role="dialog" aria-labelledby="notify-text-sub-modal">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true"><i
class="fa fa-remove"></i></button>
<h4 class="modal-title">Notification string substitutions</h4>
</div>
<div class="modal-body">
<div>
<p class="help-block">
If a value for a selected parameter cannot be provided nothing will be outputted for it.
</p>
<table>
<tbody>
<tr>
<td width="150"><strong>{user}</strong></td>
<td>The username of the person streaming.</td>
</tr>
<tr>
<td width="150"><strong>{server_name}</strong></td>
<td>The name of your Plex Server.</td>
</tr>
<tr>
<td width="150"><strong>{player}</strong></td>
<td>The name of the device being used for playback.</td>
</tr>
<tr>
<td width="150"><strong>{platform}</strong></td>
<td>The type of client being used for playback.</td>
</tr>
<tr>
<td width="150"><strong>{title}</strong></td>
<td>The title of the item being played back.</td>
</tr>
<tr>
<td width="150"><strong>{show_name}</strong></td>
<td>The title of the TV series being played back.</td>
</tr>
<tr>
<td width="150"><strong>{episode_name}</strong></td>
<td>The title of the episode being played back.</td>
</tr>
<tr>
<td width="150"><strong>{album_name}</strong></td>
<td>The title of the album being played back if item is track.</td>
</tr>
<tr>
<td width="150"><strong>{transcode_decision}</strong></td>
<td>The transcode decisions for the media item.</td>
</tr>
<tr>
<td width="150"><strong>{year}</strong></td>
<td>The release year for the media item.</td>
</tr>
<tr>
<td width="150"><strong>{studio}</strong></td>
<td>The studio for the media item.</td>
</tr>
<tr>
<td width="150"><strong>{content_rating}</strong></td>
<td>The content rating for the media item. E.g. TV-MA, TV-PG, etc.</td>
</tr>
<tr>
<td width="150"><strong>{summary}</strong></td>
<td>A short plot summary for the media item.</td>
</tr>
<tr>
<td width="150"><strong>{season_num}</strong></td>
<td>The season number for the media item if item is episode.</td>
</tr>
<tr>
<td width="150"><strong>{season_num00}</strong></td>
<td>The two digit season number.</td>
</tr>
<tr>
<td width="150"><strong>{episode_num}</strong></td>
<td>The episode number for the media item if item is episode.</td>
</tr>
<tr>
<td width="150"><strong>{episode_num00}</strong></td>
<td>The two digit episode number.</td>
</tr>
<tr>
<td width="150"><strong>{rating}</strong></td>
<td>The rating (out of 10) for the item.</td>
</tr>
<tr>
<td width="150"><strong>{duration}</strong></td>
<td>The duration (in minutes) for the item.</td>
</tr>
<tr>
<td width="150"><strong>{stream_duration}</strong></td>
<td>The stream duration (in minutes) for the item.</td>
</tr>
<tr>
<td width="150"><strong>{progress}</strong></td>
<td>The last reported offset (in minutes) for the item.</td>
</tr>
<tr>
<td width="150"><strong>{progress_percent}</strong></td>
<td>The last reported progress percent for the item.</td>
</tr>
</tbody>
</table>
</div>
</div>
<div class="modal-footer"></div>
</div>
</div>
</div>
<div id="notify-text-tags-modal" class="modal fade" tabindex="-1" role="dialog" aria-labelledby="notify-text-tags-modal">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true"><i class="fa fa-remove"></i></button>
<h4 class="modal-title">Notification exclusion tags</h4>
</div>
<div class="modal-body">
<div>
<div class="wellheader">
<h4>Movie Tag <strong>&lt;movie&gt;&lt;/movie&gt;</strong></h4>
</div>
<div>
<p class="help-block">All text inside a <strong>movie</strong> tag will only be sent when the media item being played back is a movie.</p>
<pre>Example: {user} has started playing {title} &lt;movie&gt;({year})&lt;/movie&gt;</pre>
</div>
<div class="wellheader">
<h4>TV Tag <strong>&lt;tv&gt;&lt;/tv&gt;</strong></h4>
</div>
<div>
<p class="help-block">All text inside a <strong>tv</strong> tag will only be sent when the media item being played back is an episode.</p>
<pre>Example: {user} has started playing {title} &lt;tv&gt;(S{season_num}E{episode_num})&lt;/tv&gt;</pre>
</div>
<div class="wellheader">
<h4>Music Tag <strong>&lt;music&gt;&lt;/music&gt;</strong></h4>
</div>
<div>
<p class="help-block">All text inside a <strong>music</strong> tag will only be sent when the media item being played back is a music track.</p>
<pre>Example: {user} has started playing {title} &lt;music&gt;(Track {episode_num})&lt;/music&gt;</pre>
</div>
</div>
</div>
<div class="modal-footer">
</div>
</div>
</div>
</div>
<div id="changelog-modal" class="modal fade" tabindex="-1" role="dialog" aria-labelledby="changelog-modal">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true"><i class="fa fa-remove"></i></button>
<h4 class="modal-title">Changelog</h4>
</div>
<div class="modal-body">
${versioncheck.read_changelog()}
</div>
<div class="modal-footer">
</div>
</div>
</div>
</div>
</div>
</%def>
<%def name="javascriptIncludes()">
<script src="interfaces/default/js/parsley.min.js"></script>
<script>
$(document).ready(function() {
// Javascript to enable link to tab
var hash = document.location.hash;
var prefix = "tab_";
if (hash) {
$('.nav-settings a[href='+hash.replace(prefix,"")+']').tab('show');
}
// Change hash for page-reload
$('.nav-settings a').on('shown.bs.tab', function (e) {
window.location.hash = e.target.hash.replace("#", "#" + prefix);
});
var configForm = $("#configUpdate");
$('.save-button').click(function() {
if ($("#pms_identifier").val() == "") {
showMsg('<i class="fa fa-exclamation-circle"></i>&nbspPlease verify your server.',false,true,2000,true)
} else {
if (configForm.parsley().validate()) {
doAjaxCall('configUpdate',$(this),'tabs',true);
return false;
} else {
showMsg('<i class="fa fa-exclamation-circle"></i>&nbspPlease verify your settings.',false,true,2000,true)
}
}
});
$("#menu_link_shutdown").click(function() {
var r = confirm("Are you sure you want to shutdown PlexPy?");
if (r == true) {
window.location.href = "shutdown";
}
});
$("#menu_link_restart").click(function() {
window.location.href = "restart";
});
$("#menu_link_update_check").click(function() {
// Allow the update bar to show again if previously dismissed.
setCookie('updateDismiss', 'true', 0);
$(this).html('<i class="fa fa-spin fa-refresh"></i> Checking</button>');
$(this).prop('disabled', true);
window.location.href = "checkGithub";
});
if ($("#api_enabled").is(":checked")) {
$("#apioptions").show();
} else {
$("#apioptions").hide();
}
$("#api_enabled").click(function(){
if ($("#api_enabled").is(":checked")) {
$("#apioptions").slideDown();
} else {
$("#apioptions").slideUp();
}
});
$('#api_key').click(function(){ $('#api_key').select() });
$("#generate_api").click(function() {
$.get('generateAPI',
function(data){
if (data.error != undefined) {
alert(data.error);
return;
}
$('#api_key').val(data);
});
});
if ($("#enable_https").is(":checked")) {
$("#https_options").show();
} else {
$("#https_options").hide();
}
$("#enable_https").click(function(){
if ($("#enable_https").is(":checked")) {
$("#https_options").slideDown();
} else {
$("#https_options").slideUp();
}
});
$( ".pms-settings" ).change(function() {
$("#pms_identifier").val("");
$("#pms-verify-status").html("");
verifyServer();
});
function verifyServer() {
var pms_ip = $("#pms_ip").val()
var pms_port = $("#pms_port").val()
if (($("#pms_ip").val() !== '') || ($("#pms_port").val() !== '')) {
$("#pms-verify").html('<i class="fa fa-refresh fa-spin"></i>');
$('#pms-verify').fadeIn('fast');
$.ajax({
url: 'get_server_id',
data : { hostname: pms_ip, port: pms_port },
cache: true,
async: true,
timeout: 5000,
error: function(jqXHR, textStatus, errorThrown) {
$("#pms-verify").html('<i class="fa fa-close"></i>');
$('#pms-verify').fadeIn('fast');
$("#pms-ip-group").addClass("has-error");
},
success: function (xml) {
if ($(xml).find('MediaContainer').attr('machineIdentifier')) {
$("#pms_identifier").val($(xml).find('MediaContainer').attr('machineIdentifier'));
$("#pms-verify").html('<i class="fa fa-check"></i>');
$('#pms-verify').fadeIn('fast');
$("#pms-ip-group").removeClass("has-error");
} else {
$("#pms-verify").html('<i class="fa fa-close"></i>');
$('#pms-verify').fadeIn('fast');
$("#pms-ip-group").addClass("has-error");
}
}
});
} else {
$("#pms-verify").html('<i class="fa fa-close"></i>');
$('#pms-verify').fadeIn('fast');
$("#pms-ip-group").addClass("has-error");
}
}
// Plex.tv auth token fetch
$("#get-pms-auth-token").click(function() {
$("#pms-token-status").html('<i class="fa fa-refresh fa-spin"></i> Fetching token...');
if (($("#pms_username").val() !== '') || ($("#pms_password").val() !== '')) {
$.ajax({
type: "post",
url: "https://plex.tv/users/sign_in.xml",
dataType: 'xml',
async: true,
headers: {'Content-Type': 'application/xml; charset=utf-8',
'X-Plex-Device-Name': 'PlexPy',
'X-Plex-Product': 'PlexPy',
'X-Plex-Version': '${common.VERSION_NUMBER}',
'X-Plex-Platform': '${common.PLATFORM}',
'X-Plex-Platform-Version': '${common.PLATFORM_VERSION}',
'X-Plex-Client-Identifier': '${config['pms_uuid']}',
'Authorization': 'Basic ' + btoa($("#pms_username").val() + ':' + $("#pms_password").val())
},
error: function(jqXHR, textStatus, errorThrown) {
$("#pms-token-status").html('<i class="fa fa-exclamation-circle"></i> Authentation failed!');
},
success: function (xml) {
var authToken = $(xml).find('user').attr('authenticationToken');
$("#pms-token-status").html('<i class="fa fa-check"></i> Authentation successful!');
$("#pms_token").val(authToken);
$('#pms-auth-modal').modal('hide');
}
});
} else {
$("#pms-token-status").html("You must enter both fields.");
}
});
// Load PlexWatch import modal
$("#toggle-plexwatch-import-modal").click(function() {
$.ajax({
url: 'plexwatch_import',
cache: false,
async: true,
complete: function(xhr, status) {
$("#plexwatch-import-modal").html(xhr.responseText);
}
});
});
// Load notification agent config modal
$(".toggle-notification-config-modal").click(function() {
var configId = $(this).data('id');
$.ajax({
url: 'get_notification_agent_config',
data: { config_id: configId },
cache: false,
async: true,
complete: function(xhr, status) {
$("#notification-config-modal").html(xhr.responseText);
}
});
});
// Load notification triggers config modal
$(".toggle-notification-triggers-modal").click(function() {
var configId = $(this).data('id');
$.ajax({
url: 'get_notification_agent_triggers',
data: { config_id: configId },
cache: false,
async: true,
complete: function(xhr, status) {
$("#notification-triggers-modal").html(xhr.responseText);
}
});
});
$('#osxnotifyregister').click(function () {
var osx_notify_app = $("#osx_notify_reg").val();
$.get("/osxnotifyregister", {'app': osx_notify_app}, function (data) { $('#ajaxMsg').html("<div class='msg'><span class='ui-icon ui-icon-check'></span>"+data+"</div>"); });
$('#ajaxMsg').addClass('success').fadeIn().delay(3000).fadeOut()
})
$.ajax({
url: 'get_server_pref',
data: { pref: 'logDebug' },
async: true,
success: function(data) {
if (data !== 'true') {
$("#debugLogCheck").html("Debug logging must be enabled on your Plex Server. <a target='_blank' href='https://support.plex.tv/hc/en-us/articles/201643703-Reporting-issues-with-Plex-Media-Server'> More..</a>");
$("#ip_logging_enable").attr("disabled", true);
}
}
});
// Check to see if our logs folder is set before allowing IP logging to be enabled.
checkLogsPath();
$("#pms_logs_folder").change(function() {
checkLogsPath();
});
function checkLogsPath() {
if ($("#pms_logs_folder").val() == '') {
$("#debugLogCheck").html("You must first define your Plex Server Logs folder path under the Extra Settings tab.");
$("#ip_logging_enable").attr("disabled", true);
} else {
$("#ip_logging_enable").attr("disabled", false);
$("#debugLogCheck").html("");
}
}
var accordion = new Accordion($('#accordion'), false);
});
</script>
</%def>