Compare commits

...

53 Commits

Author SHA1 Message Date
JonnyWong16
1a2e205c1f v1.4.13 2016-10-08 23:42:18 -07:00
JonnyWong16
5dd04cb8ab Temporarily set stopped time when connection is lost 2016-10-08 22:56:43 -07:00
JonnyWong16
62d05e5e08 Add supplementary URL option to Pushover 2016-10-08 22:45:16 -07:00
JonnyWong16
1c087ec856 Add backup days option 2016-10-08 22:29:30 -07:00
JonnyWong16
010c12da67 Use human file size in table 2016-10-03 21:36:02 -07:00
JonnyWong16
9bdac38561 Merge pull request #859 from logaritmisk/human-file-size
Human file size for media info table
2016-10-03 21:30:26 -07:00
logaritmisk
790ca9c90a Human file size for media info table. 2016-10-03 22:27:21 +02:00
JonnyWong16
58f72d2d9c Merge pull request #856 from Hellowlol/imgfix
fix for image proxy for api.
2016-10-02 12:09:33 -07:00
Hellowlol
285e6513ed fix for image proxy for api. 2016-10-02 20:38:51 +02:00
JonnyWong16
412bc8cf2d Move watched percent to General settings 2016-09-30 19:38:20 -07:00
JonnyWong16
45cd8b8a00 Cleanup kill script 2016-09-30 00:35:31 -07:00
JonnyWong16
ae2227959e Fix 0b10e68 2016-09-29 23:35:33 -07:00
JonnyWong16
b50c92f919 Rename get_log 2016-09-29 23:31:33 -07:00
JonnyWong16
93a1d9c164 Run script in a new thread with timeout
* Also fixes script output not sent to logger
2016-09-29 23:31:15 -07:00
JonnyWong16
0b10e68c60 Force refresh Plex.tv token in settings
* Removes the old PlexPy device and fetches a new token
2016-09-29 21:21:07 -07:00
JonnyWong16
73ac4076ac Disable manual changing of API key 2016-09-29 18:51:35 -07:00
JonnyWong16
5968b82a0b Add pms_image_proxy to api 2016-09-27 22:20:10 -07:00
JonnyWong16
ce1d2a0fd9 Fix success message show incorrectly when sending test notification
* Due to saving the settings before sending the notification
2016-09-27 21:48:09 -07:00
JonnyWong16
de3f813b46 Add flush temporary sessions button in settings 2016-09-27 21:47:12 -07:00
JonnyWong16
4797b1a3b7 Add new librarys to homepage automatically 2016-09-26 22:20:44 -07:00
JonnyWong16
3e996d284d Disable posters by default for all notification agents 2016-09-25 22:05:02 -07:00
JonnyWong16
420c5a0836 Fix Browser config section 2016-09-25 22:04:25 -07:00
JonnyWong16
c6b953055a Fix admin username not shown in login logs 2016-09-24 19:37:09 -07:00
JonnyWong16
1cd0c112a6 Fix PlexPy log level filter 2016-09-24 19:29:26 -07:00
JonnyWong16
492d28ea37 Update pytz library 2016-09-19 21:48:14 -07:00
JonnyWong16
4eb7e03b67 Update Readme 2016-09-19 19:08:26 -07:00
JonnyWong16
e029f329eb Merge branch 'dev' 2016-09-18 22:11:29 -07:00
JonnyWong16
47de9a752c v1.4.12 2016-09-18 22:11:12 -07:00
JonnyWong16
51c9aa2887 Update FreeBSD service script 2016-09-18 21:58:44 -07:00
JonnyWong16
82499a53d4 Merge pull request #844 from spolyack/pid-fix
Attempt to verify the PID in an existing PID file before giving up.
2016-09-18 21:33:11 -07:00
JonnyWong16
df15302f2c Merge pull request #842 from XusBadia/patch-2
Fix card width on the homepage for iPhone 6/7 Plus
2016-09-18 21:11:24 -07:00
JonnyWong16
039b51262d Update readme 2016-09-18 21:06:44 -07:00
spolyack
465add46d4 Attempt to verify the PID in an existing PID file before giving up.
If the PID doesn't map to a running process, then we can simply ignore the presence of the PID file and overwrite it with the current (new) PID later.
2016-09-18 11:36:09 -04:00
Xus Badia
bce965b402 Fix for iPhone 6/7 Plus
Changed the max-device-width from 400px to 450px so it adjusts to the iPhone 6/7 Plus screen and doesn't leave a gap on the right of the screen.
2016-09-18 07:41:58 +02:00
JonnyWong16
95ce293169 Add FAQ link to dropdown 2016-09-17 15:15:33 -07:00
JonnyWong16
5d604c2cad Make sure all endpoints have kwargs 2016-09-17 14:45:58 -07:00
JonnyWong16
ed2d3ca277 Update git user 2016-09-17 14:40:31 -07:00
JonnyWong16
0478f40d02 Square cover for music home stats 2016-09-17 14:39:58 -07:00
JonnyWong16
a4be73da3b Remove divider 2016-09-17 14:39:38 -07:00
JonnyWong16
762192518f Override MacOSX pms platform 2016-09-03 13:57:17 -07:00
JonnyWong16
fa51df192d Cleanup settings modal text 2016-09-02 13:18:06 -07:00
JonnyWong16
1a5cc02097 Update with support links 2016-09-02 13:01:12 -07:00
JonnyWong16
a07f54ca33 Merge branch 'dev' 2016-09-02 11:51:51 -07:00
JonnyWong16
6a8cbe92a9 v1.4.11 2016-09-02 11:51:26 -07:00
JonnyWong16
16d9376ec9 Add /r/Plex Discord to Readme 2016-09-02 11:48:36 -07:00
JonnyWong16
4356f5c72a Remove unnecessary argument 2016-09-02 10:54:20 -07:00
JonnyWong16
076dc94292 A bit of script notifier cleanup 2016-08-26 19:16:48 -07:00
JonnyWong16
fbc527010a Fix notifications not sending for Local user
Fixes #807
2016-08-26 18:48:09 -07:00
JonnyWong16
5b4a22276d Fix args in the correct order for datatables queries
Fixes #813
2016-08-26 18:14:26 -07:00
JonnyWong16
b55a563fce Fix PlexWatch and Plexivity import 2016-08-26 17:43:10 -07:00
JonnyWong16
2a701a6dfe Merge branch 'dev' 2016-08-15 08:40:16 -07:00
JonnyWong16
8931fb4758 v1.4.10 2016-08-15 08:39:29 -07:00
JonnyWong16
2124165319 Add missing ipaddress module 2016-08-15 08:39:18 -07:00
169 changed files with 3552 additions and 709 deletions

22
API.md
View File

@@ -772,7 +772,7 @@ Get the metadata for a media item.
```
Required parameters:
rating_key (str): Rating key of the item
media_info (bool): True or False wheter to get media info
media_info (bool): True or False whether to get media info
Optional parameters:
None
@@ -1793,6 +1793,26 @@ Returns:
```
### pms_image_proxy
Gets an image from the PMS and saves it to the image cache directory.
```
Required parameters:
img (str): /library/metadata/153037/thumb/1462175060
or
rating_key (str): 54321
Optional parameters:
width (str): 150
height (str): 255
fallback (str): "poster", "cover", "art"
refresh (bool): True or False whether to refresh the image cache
Returns:
None
```
### refresh_libraries_list
Refresh the PlexPy libraries list.

View File

@@ -1,5 +1,51 @@
# Changelog
## v1.4.13 (2016-10-08)
* New: Option to set the number of days to keep PlexPy backups.
* New: Option to add a supplementary url to Pushover notifications.
* New: Option to set a timeout duration for script notifications.
* New: Added flush temporary sessions button to extra settings for emergency use.
* New: Added pms_image_proxy to the API.
* Fix: Insanely long play durations being recorded when connection to the Plex server is lost.
* Fix: Script notification output not being sent to the logger.
* Fix: New libraries not being added to homepage automatically.
* Fix: Success message shown incorrectly when sending a test notification.
* Fix: PlexPy log level filter not working.
* Fix: Admin username not shown in login logs.
* Fix: FeatHub link in readme document.
* Change: Posters disabled by default for all notification agents.
* Change: Disable manual changing of the PlexPy API key.
* Change: Force refresh the Plex.tv token when fetching a new token.
* Change: Script notifications run in a new thread with the timeout setting.
* Change: Watched percent moved to general settings.
* Change: Use human readable file sizes to the media info tables. (Thanks @logaritmisk)
* Change: Update pytz library.
## v1.4.12 (2016-09-18)
* Fix: PMS update check not working for MacOSX.
* Fix: Square covers for music stats on homepage.
* Fix: Card width on the homepage for iPhone 6/7 Plus. (Thanks @XusBadia)
* Fix: Check for running PID when starting PlexPy. (Thanks @spolyack)
* Fix: FreeBSD service script not stopping PlexPy properly.
* Fix: Some web UI cleanup.
* Change: GitHub repostitory moved.
## v1.4.11 (2016-09-02)
* Fix: PlexWatch and Plexivity import errors.
* Fix: Searching in history datatables.
* Fix: Notifications not sending for Local user.
## v1.4.10 (2016-08-15)
* Fix: Missing python ipaddress module preventing PlexPy from starting.
## v1.4.9 (2016-08-14)
* New: Option to include current activity in the history tables.

View File

@@ -9,14 +9,14 @@ In case you read this because you are posting an issue, please take a minute and
- Turning your device off and on again.
- Analyzing your logs, you just might find the solution yourself!
- Using the **search** function to see if this issue has already been reported/solved.
- Checking the [Wiki](https://github.com/drzoidberg33/plexpy/wiki) for
[ [Installation] ](https://github.com/drzoidberg33/plexpy/wiki/Installation) and
[ [FAQs] ](https://github.com/drzoidberg33/plexpy/wiki/Frequently-Asked-Questions-(FAQ)).
- For basic questions try asking on [Gitter](https://gitter.im/drzoidberg33/plexpy) or the [Plex Forums](https://forums.plex.tv/discussion/169591/plexpy-another-plex-monitoring-program) first before opening an issue.
- Checking the [Wiki](https://github.com/JonnyWong16/plexpy/wiki) for
[ [Installation] ](https://github.com/JonnyWong16/plexpy/wiki/Installation) and
[ [FAQs] ](https://github.com/JonnyWong16/plexpy/wiki/Frequently-Asked-Questions-(FAQ)).
- For basic questions try asking on [Gitter](https://gitter.im/plexpy/general) or the [Plex Forums](https://forums.plex.tv/discussion/169591/plexpy-another-plex-monitoring-program) first before opening an issue.
##### If nothing has worked:
1. Open a new issue on the GitHub [issue tracker](http://github.com/drzoidberg33/plexpy/issues).
1. Open a new issue on the GitHub [issue tracker](http://github.com/JonnyWong16/plexpy/issues).
2. Provide a clear title to easily help identify your problem.
3. Use proper [markdown syntax](https://help.github.com/articles/github-flavored-markdown) to structure your post (i.e. code/log in code blocks).
4. Make sure you provide the following information:
@@ -35,7 +35,7 @@ In case you read this because you are posting an issue, please take a minute and
## Feature Requests
Feature requests are handled on [FeatHub](http://feathub.com/drzoidberg33/plexpy).
Feature requests are handled on [FeatHub](http://feathub.com/JonnyWong16/plexpy).
1. Search the existing requests to see if your suggestion has already been submitted.
2. If a similar request exists, give it a thumbs up (+1), or add additional comments to the request.

View File

@@ -8,7 +8,7 @@ Reporting Issues:
Please use [Gist](http://gist.github.com) or [Pastebin](http://pastebin.com/).
Feature Requests:
* Feature requests are handled on FeatHub: http://feathub.com/drzoidberg33/plexpy
* Feature requests are handled on FeatHub: http://feathub.com/JonnyWong16/plexpy
* Do not post them on the GitHub issues tracker.
-->

View File

@@ -122,8 +122,21 @@ def main():
# If the pidfile already exists, plexpy may still be running, so
# exit
if os.path.exists(plexpy.PIDFILE):
raise SystemExit("PID file '%s' already exists. Exiting." %
plexpy.PIDFILE)
try:
with open(plexpy.PIDFILE, 'r') as fp:
pid = int(fp.read())
os.kill(pid, 0)
except IOError as e:
raise SystemExit("Unable to read PID file: %s", e)
except OSError:
logger.warn("PID file '%s' already exists, but PID %d is " \
"not running. Ignoring PID file." %
(plexpy.PIDFILE, pid))
else:
# The pidfile exists and points to a live PID. plexpy may
# still be running, so exit.
raise SystemExit("PID file '%s' already exists. Exiting." %
plexpy.PIDFILE)
# The pidfile is only useful in daemon mode, make sure we can write the
# file properly

View File

@@ -1,14 +1,14 @@
# PlexPy
[![Join the chat at https://gitter.im/drzoidberg33/plexpy](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/drzoidberg33/plexpy?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
[![Join the chat at https://gitter.im/plexpy/general](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/plexpy/general?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
A python based web application for monitoring, analytics and notifications for [Plex Media Server](https://plex.tv).
This project is based on code from [Headphones](https://github.com/rembo10/headphones) and [PlexWatchWeb](https://github.com/ecleese/plexWatchWeb).
* [Plex forum thread](https://forums.plex.tv/discussion/169591/plexpy-another-plex-monitoring-program)
* [Gitter chat](https://gitter.im/drzoidberg33/plexpy)
* [Discord server](https://discord.gg/011TFFWSuNFI02EKr) | [PlexPy Discord server](https://discord.gg/36ggawe)
* [Gitter chat](https://gitter.im/plexpy/general)
* [/r/Plex Discord server](https://discord.gg/011TFFWSuNFI02EKr) | [PlexPy Discord server](https://discord.gg/36ggawe)
## Features
@@ -35,8 +35,8 @@ This project is based on code from [Headphones](https://github.com/rembo10/headp
## Installation and Support
* [Installation Guides](https://github.com/drzoidberg33/plexpy/wiki/Installation) shows you how to install PlexPy.
* [FAQs](https://github.com/drzoidberg33/plexpy/wiki/Frequently-Asked-Questions-(FAQ)) in the wiki can help you with common problems.
* [Installation Guides](https://github.com/JonnyWong16/plexpy/wiki/Installation) shows you how to install PlexPy.
* [FAQs](https://github.com/JonnyWong16/plexpy/wiki/Frequently-Asked-Questions-(FAQ)) in the wiki can help you with common problems.
**Support** the project by implementing new features, solving support tickets and provide bug fixes.
@@ -48,14 +48,14 @@ This project is based on code from [Headphones](https://github.com/rembo10/headp
- Turning your device off and on again.
- Analyzing your logs, you just might find the solution yourself!
- Using the **search** function to see if this issue has already been reported/solved.
- Checking the [Wiki](https://github.com/drzoidberg33/plexpy/wiki) for
[ [Installation] ](https://github.com/drzoidberg33/plexpy/wiki/Installation) and
[ [FAQs] ](https://github.com/drzoidberg33/plexpy/wiki/Frequently-Asked-Questions-(FAQ)).
- For basic questions try asking on [Gitter](https://gitter.im/drzoidberg33/plexpy) or the [Plex Forums](https://forums.plex.tv/discussion/169591/plexpy-another-plex-monitoring-program) first before opening an issue.
- Checking the [Wiki](https://github.com/JonnyWong16/plexpy/wiki) for
[ [Installation] ](https://github.com/JonnyWong16/plexpy/wiki/Installation) and
[ [FAQs] ](https://github.com/JonnyWong16/plexpy/wiki/Frequently-Asked-Questions-(FAQ)).
- For basic questions try asking on [Gitter](https://gitter.im/plexpy/general) or the [Plex Forums](https://forums.plex.tv/discussion/169591/plexpy-another-plex-monitoring-program) first before opening an issue.
##### If nothing has worked:
1. Open a new issue on the GitHub [issue tracker](http://github.com/drzoidberg33/plexpy/issues).
1. Open a new issue on the GitHub [issue tracker](http://github.com/JonnyWong16/plexpy/issues).
2. Provide a clear title to easily help identify your problem.
3. Use proper [markdown syntax](https://help.github.com/articles/github-flavored-markdown) to structure your post (i.e. code/log in code blocks).
4. Make sure you provide the following information:
@@ -74,7 +74,7 @@ This project is based on code from [Headphones](https://github.com/rembo10/headp
## Feature Requests
Feature requests are handled on [FeatHub](http://feathub.com/drzoidberg33/plexpy).
Feature requests are handled on [FeatHub](http://feathub.com/JonnyWong16/plexpy).
1. Search the existing requests to see if your suggestion has already been submitted.
2. If a similar request exists, give it a thumbs up (+1), or add additional comments to the request.

View File

@@ -220,6 +220,8 @@
<li><a href="settings"><i class="fa fa-fw fa-cogs"></i> Settings</a></li>
<li role="separator" class="divider"></li>
<li><a href="logs"><i class="fa fa-fw fa-list-alt"></i> View Logs</a></li>
<li><a href="${anon_url('https://github.com/%s/plexpy/wiki/Frequently-Asked-Questions-(FAQ)' % plexpy.CONFIG.GIT_USER)}" target="_blank"><i class="fa fa-fw fa-question-circle"></i> FAQ</a></li>
<li><a href="settings?support=true"><i class="fa fa-fw fa-comment"></i> Support</a></li>
<li role="separator" class="divider"></li>
<li><a href="${anon_url('https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=DG783BMSCU3V4')}" target="_blank"><i class="fa fa-fw fa-paypal"></i> Paypal</a></li>
<li><a href="${anon_url('http://swiftpanda16.tip.me/')}" target="_blank"><i class="fa fa-fw fa-btc"></i> Bitcoin</a></li>

View File

@@ -22,11 +22,11 @@ DOCUMENTATION :: END
% if plexpy.CURRENT_VERSION:
<tr>
<td>Git Branch:</td>
<td><a class="no-highlight" href="${anon_url('https://github.com/drzoidberg33/plexpy/tree/%s' % plexpy.CONFIG.GIT_BRANCH)}">${plexpy.CONFIG.GIT_BRANCH}</a></td>
<td><a class="no-highlight" href="${anon_url('https://github.com/%s/plexpy/tree/%s' % (plexpy.CONFIG.GIT_USER, plexpy.CONFIG.GIT_BRANCH))}">${plexpy.CONFIG.GIT_BRANCH}</a></td>
</tr>
<tr>
<td>Git Commit Hash:</td>
<td><a class="no-highlight" href="${anon_url('https://github.com/drzoidberg33/plexpy/commit/%s' % plexpy.CURRENT_VERSION)}">${plexpy.CURRENT_VERSION}</a></td>
<td><a class="no-highlight" href="${anon_url('https://github.com/%s/plexpy/commit/%s' % (plexpy.CONFIG.GIT_USER, plexpy.CONFIG.GIT_BRANCH))}">${plexpy.CURRENT_VERSION}</a></td>
</tr>
% endif
<tr>
@@ -72,32 +72,67 @@ DOCUMENTATION :: END
<td>${sys.version}</td>
</tr>
<tr>
<td class="top-line">Plex Forums:</td>
<td class="top-line"><a class="no-highlight" href="${anon_url('https://forums.plex.tv/discussion/169591/plexpy-another-plex-monitoring-program')}" target="_blank">https://forums.plex.tv/discussion/169591/plexpy-another-plex-monitoring-program</a></td>
<td class="top-line">Resources:</td>
<td class="top-line">
<a id="source-link" class="no-highlight" href="${anon_url('https://github.com/%s/plexpy' % plexpy.CONFIG.GIT_USER)}" target="_blank">GitHub Source</a> |
<a class="no-highlight guidelines-modal-link" href="${anon_url('https://github.com/%s/plexpy/issues' % plexpy.CONFIG.GIT_USER)}" data-id="issue">GitHub Issues</a> |
<a class="no-highlight guidelines-modal-link" href="${anon_url('http://feathub.com/%s/plexpy' % plexpy.CONFIG.GIT_USER)}" data-id="feature request">FeatHub Feature Requests</a> |
<a class="no-highlight" href="${anon_url('https://github.com/%s/plexpy/wiki' % plexpy.CONFIG.GIT_USER)}" target="_blank">PlexPy Wiki</a> |
<a id="faq-source-link" class="no-highlight" href="${anon_url('https://github.com/%s/plexpy/wiki/Frequently-Asked-Questions-(FAQ)' % plexpy.CONFIG.GIT_USER)}" target="_blank">PlexPy FAQ</a>
</td>
</tr>
<tr>
<td>Source:</td>
<td><a id="source-link" class="no-highlight" href="${anon_url('https://github.com/drzoidberg33/plexpy')}" target="_blank">https://github.com/drzoidberg33/plexpy</a></td>
</tr>
<tr>
<td>Wiki:</td>
<td><a class="no-highlight" href="${anon_url('https://github.com/drzoidberg33/plexpy/wiki')}" target="_blank">https://github.com/drzoidberg33/plexpy/wiki</a></td>
</tr>
<tr>
<td>Issues:</td>
<td><a class="no-highlight guidelines-modal-link" href="${anon_url('https://github.com/drzoidberg33/plexpy/issues')}" data-id="issue">https://github.com/drzoidberg33/plexpy/issues</a></td>
</tr>
<tr>
<td>Feature Requests:</td>
<td><a class="no-highlight guidelines-modal-link" href="${anon_url('http://feathub.com/drzoidberg33/plexpy')}" data-id="feature request">http://feathub.com/drzoidberg33/plexpy</a></td>
</tr>
<tr>
<td>Gitter Chat:</td>
<td><a class="no-highlight" href="${anon_url('https://gitter.im/drzoidberg33/plexpy')}" target="_blank">https://gitter.im/drzoidberg33/plexpy</a></td>
<td>Support:</td>
<td>
<a class="no-highlight support-modal-link" href="${anon_url('https://forums.plex.tv/discussion/169591/plexpy-another-plex-monitoring-program')}" target="_blank">Plex Forums</a> |
<a class="no-highlight support-modal-link" href="${anon_url('https://gitter.im/plexpy/general')}" target="_blank">PlexPy Gitter Chat</a> |
<a id="best-support-link" class="no-highlight support-modal-link" href="${anon_url('https://discord.gg/011TFFWSuNFI02EKr')}" target="_blank">/r/Plex Discord Server</a> |
<a class="no-highlight support-modal-link" href="${anon_url('https://discord.gg/36ggawe')}" target="_blank">PlexPy Discord Server</a>
</td>
</tr>
</tbody>
</table>
<div id="guidelines-modal" class="modal fade" tabindex="-1" role="dialog" aria-labelledby="guidelines-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">Guidelines</h4>
</div>
<div class="modal-body">
<div style="text-align: center; margin-top: 20px; margin-bottom: 20px;">
<strong>Please read the <a href="#" target="_blank" id="guidelines-link">guidelines</a> in the README document <br />before submitting a new <span id="guidelines-type"></span>!</strong>
<br /><br />
Your post may be removed for failure to follow the guidelines.
</div>
</div>
<div class="modal-footer">
<a href="#" target="_blank" id="guidelines-continue" class="btn btn-bright">Continue</a>
</div>
</div>
</div>
</div>
<div id="support-modal" class="modal fade" tabindex="-1" role="dialog" aria-labelledby="support-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">Support</h4>
</div>
<div class="modal-body">
<div style="text-align: center; margin-top: 20px; margin-bottom: 20px;">
<strong>Please read the <a href="#" target="_blank" id="faq-link">FAQ</a> before asking for help!</strong>
</div>
</div>
<div class="modal-footer">
<a href="#" target="_blank" id="support-continue" class="btn btn-bright">Continue</a>
</div>
</div>
</div>
</div>
<script>
$(document).ready(function () {
$("#install_geoip_db, #reinstall_geoip_db").click(function () {
@@ -125,5 +160,13 @@ DOCUMENTATION :: END
$('#guidelines-modal').modal('hide');
});
});
$('.support-modal-link').on('click', function (e) {
e.preventDefault();
$('#faq-link').attr('href', $('#faq-source-link').attr('href'));
$('#support-modal').modal();
$('#support-continue').attr('href', $(this).attr('href')).on('click', function () {
$('#support-modal').modal('hide');
});
});
});
</script>

View File

@@ -1929,6 +1929,12 @@ a .library-user-instance-box:hover {
position: absolute;
overflow: hidden;
}
.home-platforms-instance-cover {
margin-left: 0px;
position: absolute;
top: 20px;
overflow: hidden;
}
.home-platforms-instance-poster .home-platforms-poster-face {
background-position: center;
background-size: cover;
@@ -1938,6 +1944,15 @@ a .library-user-instance-box:hover {
-moz-box-shadow: 0 0 4px rgba(0,0,0,.3),inset 0 0 0 1px rgba(255,255,255,.1);
box-shadow: 0 0 4px rgba(0,0,0,.3),inset 0 0 0 1px rgba(255,255,255,.1);
}
.home-platforms-instance-cover .home-platforms-cover-face {
background-position: center;
background-size: cover;
height: 80px;
width: 80px;
-webkit-box-shadow: 0 0 4px rgba(0,0,0,.3),inset 0 0 0 1px rgba(255,255,255,.1);
-moz-box-shadow: 0 0 4px rgba(0,0,0,.3),inset 0 0 0 1px rgba(255,255,255,.1);
box-shadow: 0 0 4px rgba(0,0,0,.3),inset 0 0 0 1px rgba(255,255,255,.1);
}
.home-platforms-instance-poster .home-platforms-library-thumb {
background-position: center;
background-size: cover;
@@ -2087,6 +2102,12 @@ a .library-user-instance-box:hover {
left: 20px;
overflow: hidden;
}
.home-platforms-instance-list-cover {
position: absolute;
top: 10px;
left: 20px;
overflow: hidden;
}
.home-platforms-instance-list-poster .home-platforms-list-poster-face {
background-position: center;
background-size: cover;
@@ -2096,6 +2117,15 @@ a .library-user-instance-box:hover {
-moz-box-shadow: 0 0 4px rgba(0,0,0,.3),inset 0 0 0 1px rgba(255,255,255,.1);
box-shadow: 0 0 4px rgba(0,0,0,.3),inset 0 0 0 1px rgba(255,255,255,.1);
}
.home-platforms-instance-list-cover .home-platforms-list-cover-face {
background-position: center;
background-size: cover;
height: 40px;
width: 40px;
-webkit-box-shadow: 0 0 4px rgba(0,0,0,.3),inset 0 0 0 1px rgba(255,255,255,.1);
-moz-box-shadow: 0 0 4px rgba(0,0,0,.3),inset 0 0 0 1px rgba(255,255,255,.1);
box-shadow: 0 0 4px rgba(0,0,0,.3),inset 0 0 0 1px rgba(255,255,255,.1);
}
.home-platforms-instance-list-box {
background-position: center;
background-size: cover;
@@ -2154,7 +2184,9 @@ a .home-platforms-instance-oval:hover,
a .home-platforms-instance-list-box:hover,
a .home-platforms-instance-list-oval:hover,
a .home-platforms-poster-face:hover,
a .home-platforms-list-poster-face:hover
a .home-platforms-cover-face:hover,
a .home-platforms-list-poster-face:hover,
a .home-platforms-list-cover-face:hover
{
-webkit-box-shadow: inset 0 0 0 2px #e9a049;
-moz-box-shadow: inset 0 0 0 2px #e9a049;
@@ -2630,7 +2662,7 @@ a .home-platforms-list-poster-face:hover
@media only screen
and (min-device-width: 300px)
and (max-device-width: 400px) {
and (max-device-width: 450px) {
.home-platforms-instance {
width: calc(100% - 20px);
}
@@ -3023,3 +3055,10 @@ a:hover .overlay-refresh-image:hover {
padding-top: 10px;
padding-bottom: 10px;
}
#plexpy-log-levels label,
#plex-log-levels label {
margin-bottom: 0;
}
#api_key.form-control[disabled] {
background-color: #555;
}

View File

@@ -509,21 +509,21 @@ DOCUMENTATION :: END
% if top_stat['rows'][0]['rating_key']:
<a href="info?rating_key=${top_stat['rows'][0]['rating_key']}" title="${top_stat['rows'][0]['title']}">
% if top_stat['rows'][0]['grandparent_thumb']:
<div class="home-platforms-instance-poster">
<div class="home-platforms-poster-face" style="background-image: url(pms_image_proxy?img=${top_stat['rows'][0]['grandparent_thumb']}&width=300&height=300&fallback=poster);"></div>
<div class="home-platforms-instance-cover">
<div class="home-platforms-cover-face" style="background-image: url(pms_image_proxy?img=${top_stat['rows'][0]['grandparent_thumb']}&width=300&height=300&fallback=cover);"></div>
% if _session['user_group'] == 'admin':
<span class="overlay-refresh-image" title="Refresh image"><i class="fa fa-refresh refresh_pms_image"></i></span>
% endif
</div>
% else:
<div class="home-platforms-instance-poster">
<div class="home-platforms-poster-face" style="background-image: url(${http_root}images/poster.png);"></div>
<div class="home-platforms-instance-cover">
<div class="home-platforms-cover-face" style="background-image: url(${http_root}images/cover.png);"></div>
</div>
% endif
</a>
% else:
<div class="home-platforms-instance-poster">
<div class="home-platforms-poster-face" style="background-image: url(${http_root}images/poster.png);"></div>
<div class="home-platforms-instance-cover">
<div class="home-platforms-cover-face" style="background-image: url(${http_root}images/cover.png);"></div>
</div>
% endif
% if len(top_stat['rows']) > 1:
@@ -558,21 +558,21 @@ DOCUMENTATION :: END
% if top_stat['rows'][loop.index]['rating_key']:
<a href="info?rating_key=${top_stat['rows'][loop.index]['rating_key']}" title="${top_stat['rows'][loop.index]['title']}">
% if top_stat['rows'][loop.index]['grandparent_thumb']:
<div class="home-platforms-instance-list-poster">
<div class="home-platforms-list-poster-face" style="background-image: url(pms_image_proxy?img=${top_stat['rows'][loop.index]['grandparent_thumb']}&width=300&height=300&fallback=poster);"></div>
<div class="home-platforms-instance-list-cover">
<div class="home-platforms-list-cover-face" style="background-image: url(pms_image_proxy?img=${top_stat['rows'][loop.index]['grandparent_thumb']}&width=300&height=300&fallback=cover);"></div>
% if _session['user_group'] == 'admin':
<span class="overlay-refresh-image" title="Refresh image"><i class="fa fa-refresh refresh_pms_image"></i></span>
% endif
</div>
% else:
<div class="home-platforms-instance-list-poster">
<div class="home-platforms-list-poster-face" style="background-image: url(${http_root}images/poster.png);"></div>
<div class="home-platforms-instance-list-cover">
<div class="home-platforms-list-cover-face" style="background-image: url(${http_root}images/cover.png);"></div>
</div>
% endif
</a>
% else:
<div class="home-platforms-instance-list-poster">
<div class="home-platforms-list-poster-face" style="background-image: url(${http_root}images/poster.png);"></div>
<div class="home-platforms-instance-list-cover">
<div class="home-platforms-list-cover-face" style="background-image: url(${http_root}images/cover.png);"></div>
</div>
% endif
<div class="home-platforms-instance-list-number">
@@ -611,21 +611,21 @@ DOCUMENTATION :: END
% if top_stat['rows'][0]['rating_key']:
<a href="info?rating_key=${top_stat['rows'][0]['rating_key']}" title="${top_stat['rows'][0]['title']}">
% if top_stat['rows'][0]['grandparent_thumb'] != '':
<div class="home-platforms-instance-poster">
<div class="home-platforms-poster-face" style="background-image: url(pms_image_proxy?img=${top_stat['rows'][0]['grandparent_thumb']}&width=300&height=300&fallback=poster);"></div>
<div class="home-platforms-instance-cover">
<div class="home-platforms-cover-face" style="background-image: url(pms_image_proxy?img=${top_stat['rows'][0]['grandparent_thumb']}&width=300&height=300&fallback=cover);"></div>
% if _session['user_group'] == 'admin':
<span class="overlay-refresh-image" title="Refresh image"><i class="fa fa-refresh refresh_pms_image"></i></span>
% endif
</div>
% else:
<div class="home-platforms-instance-poster">
<div class="home-platforms-poster-face" style="background-image: url(${http_root}images/poster.png);"></div>
<div class="home-platforms-instance-cover">
<div class="home-platforms-cover-face" style="background-image: url(${http_root}images/cover.png);"></div>
</div>
% endif
</a>
% else:
<div class="home-platforms-instance-poster">
<div class="home-platforms-poster-face" style="background-image: url(${http_root}images/poster.png);"></div>
<div class="home-platforms-instance-cover">
<div class="home-platforms-cover-face" style="background-image: url(${http_root}images/cover.png);"></div>
</div>
% endif
% if len(top_stat['rows']) > 1:
@@ -656,21 +656,21 @@ DOCUMENTATION :: END
% if top_stat['rows'][loop.index]['rating_key']:
<a href="info?rating_key=${top_stat['rows'][loop.index]['rating_key']}" title="${top_stat['rows'][loop.index]['title']}">
% if top_stat['rows'][loop.index]['grandparent_thumb']:
<div class="home-platforms-instance-list-poster">
<div class="home-platforms-list-poster-face" style="background-image: url(pms_image_proxy?img=${top_stat['rows'][loop.index]['grandparent_thumb']}&width=300&height=300&fallback=poster);"></div>
<div class="home-platforms-instance-list-cover">
<div class="home-platforms-list-cover-face" style="background-image: url(pms_image_proxy?img=${top_stat['rows'][loop.index]['grandparent_thumb']}&width=300&height=300&fallback=cover);"></div>
% if _session['user_group'] == 'admin':
<span class="overlay-refresh-image" title="Refresh image"><i class="fa fa-refresh refresh_pms_image"></i></span>
% endif
</div>
% else:
<div class="home-platforms-instance-list-poster">
<div class="home-platforms-list-poster-face" style="background-image: url(${http_root}images/poster.png);"></div>
<div class="home-platforms-instance-list-cover">
<div class="home-platforms-list-cover-face" style="background-image: url(${http_root}images/cover.png);"></div>
</div>
% endif
</a>
% else:
<div class="home-platforms-instance-list-poster">
<div class="home-platforms-list-poster-face" style="background-image: url(${http_root}images/poster.png);"></div>
<div class="home-platforms-instance-list-cover">
<div class="home-platforms-list-cover-face" style="background-image: url(${http_root}images/cover.png);"></div>
</div>
% endif
<div class="home-platforms-instance-list-number">

View File

@@ -65,8 +65,8 @@ function confirmAjaxCall(url, msg, loader_msg, callback) {
url: url,
type: 'POST',
complete: function (xhr, status) {
result = $.parseJSON(xhr.responseText);
msg = result.message;
var result = $.parseJSON(xhr.responseText);
var msg = result.message;
if (result.result == 'success') {
showMsg('<i class="fa fa-check"></i> ' + msg, false, true, 5000)
} else {
@@ -80,9 +80,9 @@ function confirmAjaxCall(url, msg, loader_msg, callback) {
});
}
function doAjaxCall(url, elem, reload, form, callback) {
function doAjaxCall(url, elem, reload, form, showMsg, callback) {
// Set Message
feedback = $("#ajaxMsg");
feedback = (showMsg) ? $("#ajaxMsg") : $();
update = $("#updatebar");
if (update.is(":visible")) {
var height = update.height() + 35;
@@ -448,4 +448,21 @@ $('*').on('click', '.refresh_pms_image', function (e) {
background_div.css('background-image', 'url(' + pms_proxy_url + '&refresh=true)');
}
}
});
});
// Taken from http://stackoverflow.com/questions/10420352/converting-file-size-in-bytes-to-human-readable#answer-14919494
function humanFileSize(bytes, si) {
var thresh = si ? 1000 : 1024;
if (Math.abs(bytes) < thresh) {
return bytes + ' B';
}
var units = si
? ['kB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB']
: ['KiB', 'MiB', 'GiB', 'TiB', 'PiB', 'EiB', 'ZiB', 'YiB'];
var u = -1;
do {
bytes /= thresh;
++u;
} while (Math.abs(bytes) >= thresh && u < units.length - 1);
return bytes.toFixed(1) + '&nbsp;' + units[u];
}

View File

@@ -4,7 +4,7 @@ var time_format = 'hh:mm a';
$.ajax({
url: 'get_date_formats',
type: 'GET',
success: function(data) {
success: function (data) {
date_format = data.date_format;
time_format = data.time_format;
}
@@ -16,10 +16,10 @@ media_info_table_options = {
"destroy": true,
"language": {
"search": "Search: ",
"lengthMenu":"Show _MENU_ entries per page",
"info":"Showing _START_ to _END_ of _TOTAL_ library items",
"infoEmpty":"Showing 0 to 0 of 0 entries",
"infoFiltered":"<span class='hidden-md hidden-sm hidden-xs'>(filtered from _MAX_ total entries)</span>",
"lengthMenu": "Show _MENU_ entries per page",
"info": "Showing _START_ to _END_ of _TOTAL_ library items",
"infoEmpty": "Showing 0 to 0 of 0 entries",
"infoFiltered": "<span class='hidden-md hidden-sm hidden-xs'>(filtered from _MAX_ total entries)</span>",
"emptyTable": "No data in table",
"loadingRecords": '<i class="fa fa-refresh fa-spin"></i> Loading items...</div>'
},
@@ -28,7 +28,7 @@ media_info_table_options = {
"processing": false,
"serverSide": true,
"pageLength": 25,
"order": [ 1, 'asc'],
"order": [1, 'asc'],
"autoWidth": false,
"scrollX": true,
"columnDefs": [
@@ -110,7 +110,7 @@ media_info_table_options = {
},
"width": "20%",
"className": "no-wrap",
},
},
{
"targets": [2],
"data": "container",
@@ -194,7 +194,7 @@ media_info_table_options = {
"data": "file_size",
"createdCell": function (td, cellData, rowData, row, col) {
if (cellData !== null && cellData !== '') {
$(td).html(Math.round(cellData / Math.pow(1024, 2)).toString() + ' MiB');
$(td).html(humanFileSize(cellData));
} else {
if (rowData['section_type'] != 'photo' && get_file_sizes != null) {
get_file_sizes = true;
@@ -280,10 +280,10 @@ media_info_table_options = {
}
$("#media_info_table-SID-" + section_id + "_info").append('<span class="hidden-md hidden-sm hidden-xs"> with a total file size of ' +
Math.round(settings.json.filtered_file_size / Math.pow(1024, 3)).toString() + ' GiB' +
' (filtered from ' + Math.round(settings.json.total_file_size / Math.pow(1024, 3)).toString() + ' GiB)</span>');
humanFileSize(settings.json.filtered_file_size) +
' (filtered from ' + humanFileSize(settings.json.total_file_size) + ')</span>');
},
"preDrawCallback": function(settings) {
"preDrawCallback": function (settings) {
var msg = "<i class='fa fa-refresh fa-spin'></i>&nbspFetching rows...";
showMsg(msg, false, false, 0)
},
@@ -425,17 +425,17 @@ function childTableFormatMedia(rowData) {
'<table id="media_info_child-' + rowData['rating_key'] + '" data-id="' + rowData['rating_key'] + '" width="100%">' +
'<thead>' +
'<tr>' +
'<th align="left" id="added_at">Added At</th>' +
'<th align="left" id="title">Title</th>' +
'<th align="left" id="container">Container</th>' +
'<th align="left" id="bitrate">Bitrate</th>' +
'<th align="left" id="video_codec">Video Codec</th>' +
'<th align="left" id="video_resolution">Video Resolution</th>' +
'<th align="left" id="video_resolution">Video Framerate</th>' +
'<th align="left" id="audio_codec">Audio Codec</th>' +
'<th align="left" id="audio_channels">Audio Channels</th>' +
'<th align="left" id="file_size">File Size</th>' +
'<th align="left" id="last_played">Last Played</th>' +
'<th align="left" id="added_at">Added At</th>' +
'<th align="left" id="title">Title</th>' +
'<th align="left" id="container">Container</th>' +
'<th align="left" id="bitrate">Bitrate</th>' +
'<th align="left" id="video_codec">Video Codec</th>' +
'<th align="left" id="video_resolution">Video Resolution</th>' +
'<th align="left" id="video_resolution">Video Framerate</th>' +
'<th align="left" id="audio_codec">Audio Codec</th>' +
'<th align="left" id="audio_channels">Audio Channels</th>' +
'<th align="left" id="file_size">File Size</th>' +
'<th align="left" id="last_played">Last Played</th>' +
'<th align="left" id="total_plays">Total Plays</th>' +
'</tr>' +
'</thead>' +

View File

@@ -28,7 +28,7 @@
<option disabled>&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;</option>
<option value="DEBUG">Debug</option>
<option value="INFO">Info</option>
<option value="WARN">Warning</option>
<option value="WARNING">Warning</option>
<option value="ERROR">Error</option>
</select>
</label>
@@ -198,7 +198,7 @@
var selected_log_level = null;
function loadPlexPyLogs(selected_log_level) {
log_table_options.ajax = {
url: "getLog",
url: "get_log",
type: 'post',
data: function (d) {
return {

View File

@@ -148,7 +148,7 @@
$('#save-notification-item').click(function () {
// Reload modal to update certain fields
doAjaxCall('set_notification_config', $(this), 'tabs', true, reloadModal);
doAjaxCall('set_notification_config', $(this), 'tabs', true, true, reloadModal);
return false;
});
@@ -176,7 +176,7 @@
})
$('#test_notifier').click(function () {
doAjaxCall('set_notification_config', $(this), 'tabs', true, sendTestNotification);
doAjaxCall('set_notification_config', $(this), 'tabs', true, false, sendTestNotification);
});
function sendTestNotification() {
@@ -219,7 +219,7 @@
$('#pushbullet_apikey, #pushover_apitoken, #scripts_folder, #join_apikey').on('change', function () {
// Reload modal to update certain fields
doAjaxCall('set_notification_config', $(this), 'tabs', true, reloadModal);
doAjaxCall('set_notification_config', $(this), 'tabs', true, false, reloadModal);
return false;
});

View File

@@ -129,6 +129,16 @@
</label>
<p class="help-block">Include current activity in the history tables. Statistics will not be counted until the stream has ended.</p>
</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 percentage for a media item to be considered as watched. Minimum 50, Maximum 95.</p>
</div>
<div class="padded-header">
<h3>Backup</h3>
@@ -143,6 +153,19 @@
</div>
<p class="help-block">The interval (in hours) PlexPy will backup the database and configuration file. Minimum 1, maximum 24, default 6.</p>
</div>
<div class="form-group">
<label for="backup_interval">Backup Days</label>
<div class="row">
<div class="col-md-2">
<input type="text" class="form-control" data-parsley-type="integer" id="backup_days" name="backup_days" value="${config['backup_days']}" size="5" data-parsley-min="1" data-parsley-trigger="change" data-parsley-errors-container="#backup_days_error" required>
</div>
<div id="backup_days_error" class="alert alert-danger settings-alert" role="alert"></div>
</div>
<p class="help-block">
The number of days to keep scheduled backups. Minimum 1, default 3.<br />
Note: Manual backups are not removed automatically.
</p>
</div>
<div class="padded-header">
<h3>Directories</h3>
@@ -518,7 +541,7 @@
<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">
<input class="form-control" type="text" name="api_key" id="api_key" value="${config['api_key']}" size="20" disabled>
<span class="input-group-btn">
<button class="btn btn-form" type="button" id="generate_api">Generate</button>
</span>
@@ -736,6 +759,20 @@
</div>
<p class="help-block">Backlink protection via anonymizer service, must end in "?".</p>
</div>
<div class="form-group">
<label>Flush Temporary Sessions</label>
<p class="help-block">
Attempt to fix hisotry logging by flushing out all of the temporary sessions in the database.<br />
Warning: This will reset all currently active sessions. For emergeny use only when history logging is stuck!
</p>
<div class="row">
<div class="col-md-4">
<div class="btn-group">
<button class="btn btn-form" type="button" id="delete_temp_sessions">Flush</button>
</div>
</div>
</div>
</div>
<div class="padded-header">
<h3>Database Import Tool</h3>
@@ -887,16 +924,6 @@
<h3>Current Activity Notifications</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="checkbox">
<label>
<input type="checkbox" name="notify_consecutive" id="notify_consecutive" value="1" ${config['notify_consecutive']}> Allow Consecutive Notifications
@@ -1264,7 +1291,7 @@
<table class="notification-params time-options">
<thead>
<tr>
<th>
<th colspan="3">
Year
</th>
</tr>
@@ -1285,7 +1312,7 @@
<table class="notification-params time-options">
<thead>
<tr>
<th>
<th colspan="3">
Month
</th>
</tr>
@@ -1316,7 +1343,7 @@
<table class="notification-params time-options">
<thead>
<tr>
<th>
<th colspan="3">
Day of the Year
</th>
</tr>
@@ -1337,7 +1364,7 @@
<table class="notification-params time-options">
<thead>
<tr>
<th>
<th colspan="3">
Day of the Month
</th>
</tr>
@@ -1363,7 +1390,7 @@
<table class="notification-params time-options">
<thead>
<tr>
<th>
<th colspan="3">
Day of the Week
</th>
</tr>
@@ -1389,7 +1416,7 @@
<table class="notification-params time-options">
<thead>
<tr>
<th>
<th colspan="3">
Hour
</th>
</tr>
@@ -1420,7 +1447,7 @@
<table class="notification-params time-options">
<thead>
<tr>
<th>
<th colspan="3">
Minute
</th>
</tr>
@@ -1441,7 +1468,7 @@
<table class="notification-params time-options">
<thead>
<tr>
<th>
<th colspan="3">
Second
</th>
</tr>
@@ -1462,7 +1489,7 @@
<table class="notification-params time-options">
<thead>
<tr>
<th>
<th colspan="3">
AM / PM
</th>
</tr>
@@ -1483,7 +1510,7 @@
<table class="notification-params time-options">
<thead>
<tr>
<th>
<th colspan="3">
Timezone
</th>
</tr>
@@ -1504,7 +1531,7 @@
<table class="notification-params time-options">
<thead>
<tr>
<th>
<th colspan="3">
Timestamp
</th>
</tr>
@@ -1533,11 +1560,11 @@
<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.
This will attempt to fetch a new Plex.tv token for you. PlexPy does not store your username and password.
Note: This will not work on Internet Explorer 9 or lower.
</p>
<div class="form-group">
<label for="pms_username">PMS Username</label>
<label for="pms_username">Plex.tv Username</label>
<div class="row">
<div class="col-md-6">
<input type="text" class="form-control" id="pms_username" name="pms_username" size="30">
@@ -1546,7 +1573,7 @@
<p class="help-block">Username for Plex.tv authentication.</p>
</div>
<div class="form-group">
<label for="pms_password">PMS Password</label>
<label for="pms_password">Plex.tv Password</label>
<div class="row">
<div class="col-md-6">
<input type="password" class="form-control" id="pms_password" name="pms_password" size="30">
@@ -1574,7 +1601,7 @@
<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>
<h4 class="modal-title">Notification Parameters</h4>
</div>
<div class="modal-body">
<div>
@@ -1584,7 +1611,7 @@
<table class="notification-params">
<thead>
<tr>
<th>
<th colspan="2">
Global
</th>
</tr>
@@ -1619,7 +1646,7 @@
<table class="notification-params">
<thead>
<tr>
<th>
<th colspan="2">
Stream Details
</th>
</tr>
@@ -1778,7 +1805,7 @@
<table class="notification-params">
<thead>
<tr>
<th>
<th colspan="2">
Metadata Details
</th>
</tr>
@@ -1915,12 +1942,12 @@
<tr>
<td><strong>{imdb_id}</strong></td>
<td>The IMDB ID for the movie. <span class="small-muted">(e.g. tt2488496)</span>
<p class="small-muted">(PMS agent must be Freebase)</p></td>
<p class="small-muted">(PMS agent must be Plex Movie)</p></td>
</tr>
<tr>
<td><strong>{imdb_url}</strong></td>
<td>The IMDB URL for the movie.
<p class="small-muted">(PMS agent must be Freebase)</p></td>
<p class="small-muted">(PMS agent must be Plex Movie)</p></td>
</tr>
<tr>
<td><strong>{thetvdb_id}</strong></td>
@@ -1972,7 +1999,7 @@
<table class="notification-params">
<thead>
<tr>
<th>
<th colspan="2">
Plex Update Available
</th>
</tr>
@@ -2039,27 +2066,27 @@
</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>
<h4>Movie Tag</h4>
</div>
<div style="padding-bottom: 10px;">
<p class="help-block">All text inside <span class="inline-pre">&lt;movie&gt;&lt;/movie&gt;</span> tags will only be sent when the media item is a movie.</p>
<p><strong style="color: #fff;">Example:</strong></p>
<pre>{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>
<h4>TV Tag</h4>
</div>
<div style="padding-bottom: 10px;">
<p class="help-block">All text inside <span class="inline-pre">&lt;tv&gt;&lt;/tv&gt;</span> tags will only be sent when the media item is an episode.</p>
<p><strong style="color: #fff;">Example:</strong></p>
<pre>{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>
<h4>Music Tag</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>
<p class="help-block">All text inside <span class="inline-pre">&lt;music&gt;&lt;/music&gt;</span> tags will only be sent when the media item is a track.</p>
<p><strong style="color: #fff;">Example:</strong></p>
<pre>{user} has started playing {title} &lt;music&gt;(Track {track_num})&lt;/music&gt;</pre>
</div>
@@ -2101,26 +2128,6 @@
</div>
</div>
</div>
<div id="guidelines-modal" class="modal fade" tabindex="-1" role="dialog" aria-labelledby="guidelines-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">Guidelines</h4>
</div>
<div class="modal-body">
<div style="text-align: center; margin-top: 20px; margin-bottom: 20px;">
<strong>Please read the <a href="#" target="_blank" id="guidelines-link">guidelines</a> in the README document <br />before submitting a new <span id="guidelines-type"></span>!</strong>
<br /><br />
Your post may be removed for failure to follow the guidelines.
</div>
</div>
<div class="modal-footer">
<a href="#" target="_blank" id="guidelines-continue" class="btn btn-bright">Continue</a>
</div>
</div>
</div>
</div>
</div>
</%def>
@@ -2141,6 +2148,11 @@
} else if ("${kwargs.get('reinstall_geoip')}" == 'true') {
$('#reinstall_geoip_db').removeClass('no-highlight').css('color','#e9a049');
}
if ("${kwargs.get('support')}" == 'true') {
$('.support-modal-link').removeClass('no-highlight').css('color','#e9a049');
$('#best-support-link').prepend('<span data-toggle="tooltip" title="Most Active"><i class="fa fa-star"></i></span>&nbsp;')
$('#best-support-link span').tooltip({ container: 'body' });
}
}
});
}
@@ -2205,7 +2217,7 @@ $(document).ready(function() {
function saveSettings() {
if (configForm.parsley().validate()) {
doAjaxCall('configUpdate', $(this), 'tabs', true, postSaveChecks);
doAjaxCall('configUpdate', $(this), 'tabs', true, true, postSaveChecks);
return false;
} else {
showMsg('<i class="fa fa-exclamation-circle"></i> Please verify your settings.', false, true, 5000, true)
@@ -2288,6 +2300,12 @@ $(document).ready(function() {
confirmAjaxCall(url, msg);
});
$("#delete_temp_sessions").click(function () {
var msg = 'Are you sure you want to flush the temporary sessions?<br /><strong>This will reset all currently active sessions.</strong>';
var url = 'delete_temp_sessions';
confirmAjaxCall(url, msg);
});
$('#api_key').click(function(){ $('#api_key').select() });
$("#generate_api").click(function() {
$.get('generateAPI',
@@ -2383,21 +2401,24 @@ $(document).ready(function() {
if ((pms_username !== '') && (pms_password !== '')) {
$.ajax({
type: 'GET',
url: 'get_pms_token',
url: 'get_plexpy_pms_token',
data: {
username: pms_username,
password: pms_password
password: pms_password,
force: true
},
cache: false,
async: true,
complete: function(xhr, status) {
var authToken = $.parseJSON(xhr.responseText);
if (authToken) {
$("#pms-token-status").html('<i class="fa fa-check"></i> Authentication successful!');
var result = $.parseJSON(xhr.responseText);
var msg = result.message;
if (result.result == 'success') {
var authToken = result.token;
$("#pms-token-status").html('<i class="fa fa-check"></i> ' + msg);
$("#pms_token").val(authToken);
$('#pms-auth-modal').modal('hide');
} else {
$("#pms-token-status").html('<i class="fa fa-exclamation-circle"></i> Invalid username or password.');
$("#pms-token-status").html('<i class="fa fa-exclamation-circle"></i> ' + msg);
}
loadUpdateDistros();
}
@@ -2679,7 +2700,7 @@ $(document).ready(function() {
});
// Load PMS downloads
function loadUpdateDistros(distro_build) {
function loadUpdateDistros() {
var update_params_ajax = $.getJSON('get_server_update_params', function (data) { return data; });
$.when(update_params_ajax).done(function() {

View File

@@ -418,7 +418,7 @@
if ((pms_username !== '') && (pms_password !== '')) {
$.ajax({
type: 'GET',
url: 'get_pms_token',
url: 'get_plexpy_pms_token',
data: {
username: pms_username,
password: pms_password
@@ -426,15 +426,17 @@
cache: false,
async: true,
complete: function (xhr, status) {
var authToken = $.parseJSON(xhr.responseText);
if (authToken) {
$("#pms-token-status").html('<i class="fa fa-check"></i> Authentication successful!');
var result = $.parseJSON(xhr.responseText);
var msg = result.message;
if (result.result == 'success') {
var authToken = result.token;
$("#pms-token-status").html('<i class="fa fa-check"></i> ' + msg);
$('#pms-token-status').fadeIn('fast');
$("#pms_token").val(authToken);
authenticated = true;
getServerOptions(authToken)
} else {
$("#pms-token-status").html('<i class="fa fa-exclamation-circle"></i> Invalid username or password.');
$("#pms-token-status").html('<i class="fa fa-exclamation-circle"></i> ' + msg);
}
}
});

View File

@@ -49,23 +49,33 @@ fi
verify_plexpy_pid() {
# Make sure the pid corresponds to the PlexPy process.
pid=`cat ${plexpy_pid} 2>/dev/null`
ps -p ${pid} | grep -q "python ${plexpy_dir}/PlexPy.py"
return $?
if [ -f ${plexpy_pid} ]; then
pid=`cat ${plexpy_pid} 2>/dev/null`
ps -p ${pid} | grep -q "python2 ${plexpy_dir}/PlexPy.py"
return $?
else
return 0
fi
}
# Try to stop PlexPy cleanly by calling shutdown over http.
# Try to stop PlexPy cleanly by sending SIGTERM
plexpy_stop() {
echo "Stopping $name"
verify_plexpy_pid
if [ -n "${pid}" ]; then
kill ${pid}
wait_for_pids ${pid}
echo "Stopped"
echo "Stopped."
fi
}
plexpy_status() {
verify_plexpy_pid && echo "$name is running as ${pid}" || echo "$name is not running"
verify_plexpy_pid
if [ -n "${pid}" ]; then
echo "$name is running as ${pid}."
else
echo "$name is not running."
fi
}
run_rc_command "$1"

View File

@@ -58,7 +58,7 @@ verify_plexpy_pid() {
fi
}
# Try to stop PlexPy cleanly by calling shutdown over http.
# Try to stop PlexPy cleanly by sending SIGTERM
plexpy_stop() {
echo "Stopping $name."
verify_plexpy_pid

2417
lib/ipaddress.py Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -8,9 +8,9 @@ See the datetime section of the Python Library Reference for information
on how to use these modules.
'''
# The Olson database is updated several times a year.
OLSON_VERSION = '2014j'
VERSION = '2014.10' # Switching to pip compatible version numbering.
# The IANA (nee Olson) database is updated several times a year.
OLSON_VERSION = '2016f'
VERSION = '2016.6.1' # Switching to pip compatible version numbering.
__version__ = VERSION
OLSEN_VERSION = OLSON_VERSION # Old releases had this misspelling
@@ -25,11 +25,6 @@ __all__ = [
import sys, datetime, os.path, gettext
try:
from pkg_resources import resource_stream
except ImportError:
resource_stream = None
from pytz.exceptions import AmbiguousTimeError
from pytz.exceptions import InvalidTimeError
from pytz.exceptions import NonExistentTimeError
@@ -57,7 +52,7 @@ except NameError: # Python 3.x
...
UnicodeEncodeError: ...
"""
s.encode('US-ASCII') # Raise an exception if not ASCII
s.encode('ASCII') # Raise an exception if not ASCII
return s # But return the original string - not a byte string.
else: # Python 2.x
@@ -73,7 +68,7 @@ else: # Python 2.x
...
UnicodeEncodeError: ...
"""
return s.encode('US-ASCII')
return s.encode('ASCII')
def open_resource(name):
@@ -88,11 +83,17 @@ def open_resource(name):
raise ValueError('Bad path segment: %r' % part)
filename = os.path.join(os.path.dirname(__file__),
'zoneinfo', *name_parts)
if not os.path.exists(filename) and resource_stream is not None:
if not os.path.exists(filename):
# http://bugs.launchpad.net/bugs/383171 - we avoid using this
# unless absolutely necessary to help when a broken version of
# pkg_resources is installed.
return resource_stream(__name__, 'zoneinfo/' + name)
try:
from pkg_resources import resource_stream
except ImportError:
resource_stream = None
if resource_stream is not None:
return resource_stream(__name__, 'zoneinfo/' + name)
return open(filename, 'rb')
@@ -110,7 +111,7 @@ def resource_exists(name):
# module, as well as the Zope3 i18n package. Perhaps we should just provide
# the POT file and translations, and leave it up to callers to make use
# of them.
#
#
# t = gettext.translation(
# 'pytz', os.path.join(os.path.dirname(__file__), 'locales'),
# fallback=True
@@ -123,7 +124,7 @@ def resource_exists(name):
_tzinfo_cache = {}
def timezone(zone):
r''' Return a datetime.tzinfo implementation for the given timezone
r''' Return a datetime.tzinfo implementation for the given timezone
>>> from datetime import datetime, timedelta
>>> utc = timezone('UTC')
@@ -241,13 +242,13 @@ class UTC(datetime.tzinfo):
return "UTC"
UTC = utc = UTC() # UTC is a singleton
UTC = utc = UTC() # UTC is a singleton
def _UTC():
"""Factory function for utc unpickling.
Makes sure that unpickling a utc instance always returns the same
Makes sure that unpickling a utc instance always returns the same
module global.
These examples belong in the UTC class above, but it is obscured; or in
@@ -329,7 +330,7 @@ class _CountryTimezoneDict(LazyDict):
zone_tab = open_resource('zone.tab')
try:
for line in zone_tab:
line = line.decode('US-ASCII')
line = line.decode('UTF-8')
if line.startswith('#'):
continue
code, coordinates, zone = line.split(None, 4)[:3]
@@ -357,7 +358,7 @@ class _CountryNameDict(LazyDict):
zone_tab = open_resource('iso3166.tab')
try:
for line in zone_tab.readlines():
line = line.decode('US-ASCII')
line = line.decode('UTF-8')
if line.startswith('#'):
continue
code, name = line.split(None, 1)
@@ -404,9 +405,11 @@ class _FixedOffset(datetime.tzinfo):
def normalize(self, dt, is_dst=False):
'''Correct the timezone information on the given datetime'''
if dt.tzinfo is self:
return dt
if dt.tzinfo is None:
raise ValueError('Naive time - no tzinfo set')
return dt.replace(tzinfo=self)
return dt.astimezone(self)
def FixedOffset(offset, _tzinfos = {}):
@@ -599,6 +602,7 @@ all_timezones = \
'America/Eirunepe',
'America/El_Salvador',
'America/Ensenada',
'America/Fort_Nelson',
'America/Fort_Wayne',
'America/Fortaleza',
'America/Glace_Bay',
@@ -731,6 +735,7 @@ all_timezones = \
'Asia/Bahrain',
'Asia/Baku',
'Asia/Bangkok',
'Asia/Barnaul',
'Asia/Beirut',
'Asia/Bishkek',
'Asia/Brunei',
@@ -802,6 +807,7 @@ all_timezones = \
'Asia/Thimbu',
'Asia/Thimphu',
'Asia/Tokyo',
'Asia/Tomsk',
'Asia/Ujung_Pandang',
'Asia/Ulaanbaatar',
'Asia/Ulan_Bator',
@@ -907,6 +913,7 @@ all_timezones = \
'Etc/Zulu',
'Europe/Amsterdam',
'Europe/Andorra',
'Europe/Astrakhan',
'Europe/Athens',
'Europe/Belfast',
'Europe/Belgrade',
@@ -927,6 +934,7 @@ all_timezones = \
'Europe/Jersey',
'Europe/Kaliningrad',
'Europe/Kiev',
'Europe/Kirov',
'Europe/Lisbon',
'Europe/Ljubljana',
'Europe/London',
@@ -954,6 +962,7 @@ all_timezones = \
'Europe/Tallinn',
'Europe/Tirane',
'Europe/Tiraspol',
'Europe/Ulyanovsk',
'Europe/Uzhgorod',
'Europe/Vaduz',
'Europe/Vatican',
@@ -1177,6 +1186,7 @@ common_timezones = \
'America/Edmonton',
'America/Eirunepe',
'America/El_Salvador',
'America/Fort_Nelson',
'America/Fortaleza',
'America/Glace_Bay',
'America/Godthab',
@@ -1224,7 +1234,6 @@ common_timezones = \
'America/Moncton',
'America/Monterrey',
'America/Montevideo',
'America/Montreal',
'America/Montserrat',
'America/Nassau',
'America/New_York',
@@ -1249,7 +1258,6 @@ common_timezones = \
'America/Regina',
'America/Resolute',
'America/Rio_Branco',
'America/Santa_Isabel',
'America/Santarem',
'America/Santiago',
'America/Santo_Domingo',
@@ -1297,6 +1305,7 @@ common_timezones = \
'Asia/Bahrain',
'Asia/Baku',
'Asia/Bangkok',
'Asia/Barnaul',
'Asia/Beirut',
'Asia/Bishkek',
'Asia/Brunei',
@@ -1356,6 +1365,7 @@ common_timezones = \
'Asia/Tehran',
'Asia/Thimphu',
'Asia/Tokyo',
'Asia/Tomsk',
'Asia/Ulaanbaatar',
'Asia/Urumqi',
'Asia/Ust-Nera',
@@ -1394,6 +1404,7 @@ common_timezones = \
'Canada/Pacific',
'Europe/Amsterdam',
'Europe/Andorra',
'Europe/Astrakhan',
'Europe/Athens',
'Europe/Belgrade',
'Europe/Berlin',
@@ -1413,6 +1424,7 @@ common_timezones = \
'Europe/Jersey',
'Europe/Kaliningrad',
'Europe/Kiev',
'Europe/Kirov',
'Europe/Lisbon',
'Europe/Ljubljana',
'Europe/London',
@@ -1438,6 +1450,7 @@ common_timezones = \
'Europe/Stockholm',
'Europe/Tallinn',
'Europe/Tirane',
'Europe/Ulyanovsk',
'Europe/Uzhgorod',
'Europe/Vaduz',
'Europe/Vatican',

View File

@@ -15,13 +15,13 @@ from pytz.tzinfo import memorized_datetime, memorized_timedelta
def _byte_string(s):
"""Cast a string or byte string to an ASCII byte string."""
return s.encode('US-ASCII')
return s.encode('ASCII')
_NULL = _byte_string('\0')
def _std_string(s):
"""Cast a string or byte string to an ASCII string."""
return str(s.decode('US-ASCII'))
return str(s.decode('ASCII'))
def build_tzinfo(zone, fp):
head_fmt = '>4s c 15x 6l'
@@ -66,7 +66,7 @@ def build_tzinfo(zone, fp):
i += 3
# Now build the timezone object
if len(transitions) == 0:
if len(ttinfo) ==1 or len(transitions) == 0:
ttinfo[0][0], ttinfo[0][2]
cls = type(zone, (StaticTzInfo,), dict(
zone=zone,

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.

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