Compare commits
120 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
5417747473 | ||
![]() |
cf6847d777 | ||
![]() |
464fa1f8a3 | ||
![]() |
665a6435ef | ||
![]() |
2d64ba4a0e | ||
![]() |
006c778dca | ||
![]() |
bd636b756b | ||
![]() |
d21b74f231 | ||
![]() |
4354f72578 | ||
![]() |
f5ca522e6c | ||
![]() |
8a556a50ab | ||
![]() |
532ff59dfe | ||
![]() |
ec685407bb | ||
![]() |
be9a1dcf06 | ||
![]() |
1f7e8b4d9a | ||
![]() |
b3da08ce74 | ||
![]() |
50753db4ff | ||
![]() |
b3fe6145e2 | ||
![]() |
af77e51307 | ||
![]() |
b4e8689e92 | ||
![]() |
8ec30a77ff | ||
![]() |
29c7853380 | ||
![]() |
cd417aaf44 | ||
![]() |
428a5cc0ff | ||
![]() |
d128d7c8e6 | ||
![]() |
8027199bd5 | ||
![]() |
099a887cc7 | ||
![]() |
ea41d06023 | ||
![]() |
5147baab05 | ||
![]() |
1c50e615cf | ||
![]() |
ed2d34e979 | ||
![]() |
c404016700 | ||
![]() |
14b0353ba4 | ||
![]() |
fbe136a350 | ||
![]() |
4fcfea943e | ||
![]() |
279d27d081 | ||
![]() |
651125ef2c | ||
![]() |
a5eb0e7faa | ||
![]() |
e85cdd5609 | ||
![]() |
83f80b9288 | ||
![]() |
76fe771d8c | ||
![]() |
c6ad09fe8f | ||
![]() |
a3014638c8 | ||
![]() |
8b15c63b0d | ||
![]() |
589adf4df9 | ||
![]() |
b07d85f233 | ||
![]() |
f0e5855a8e | ||
![]() |
5997aa5cd9 | ||
![]() |
cb2a38addc | ||
![]() |
873f857c82 | ||
![]() |
b9a22461c1 | ||
![]() |
85a02771a7 | ||
![]() |
6a0b0327c3 | ||
![]() |
3742f33d08 | ||
![]() |
82ac33dd75 | ||
![]() |
8c7c0101cd | ||
![]() |
4d6179dfdd | ||
![]() |
ef85fba2e5 | ||
![]() |
960b601384 | ||
![]() |
21d9091b43 | ||
![]() |
e881c32797 | ||
![]() |
57f1af05f5 | ||
![]() |
254f41a2cc | ||
![]() |
59ce3404c9 | ||
![]() |
11c7342299 | ||
![]() |
8b0959aa69 | ||
![]() |
9cd8ed12b9 | ||
![]() |
78b10d7ab5 | ||
![]() |
a322ec2b23 | ||
![]() |
1f23654735 | ||
![]() |
e1112b95c7 | ||
![]() |
4e043109bf | ||
![]() |
58e670443d | ||
![]() |
86a9230da8 | ||
![]() |
86f84766c1 | ||
![]() |
fdc7078e5c | ||
![]() |
c649ebfcc0 | ||
![]() |
6aa0d4cd0b | ||
![]() |
1a2e205c1f | ||
![]() |
5dd04cb8ab | ||
![]() |
62d05e5e08 | ||
![]() |
1c087ec856 | ||
![]() |
010c12da67 | ||
![]() |
9bdac38561 | ||
![]() |
790ca9c90a | ||
![]() |
58f72d2d9c | ||
![]() |
285e6513ed | ||
![]() |
412bc8cf2d | ||
![]() |
45cd8b8a00 | ||
![]() |
ae2227959e | ||
![]() |
b50c92f919 | ||
![]() |
93a1d9c164 | ||
![]() |
0b10e68c60 | ||
![]() |
73ac4076ac | ||
![]() |
5968b82a0b | ||
![]() |
ce1d2a0fd9 | ||
![]() |
de3f813b46 | ||
![]() |
4797b1a3b7 | ||
![]() |
3e996d284d | ||
![]() |
420c5a0836 | ||
![]() |
c6b953055a | ||
![]() |
1cd0c112a6 | ||
![]() |
492d28ea37 | ||
![]() |
4eb7e03b67 | ||
![]() |
e029f329eb | ||
![]() |
47de9a752c | ||
![]() |
51c9aa2887 | ||
![]() |
82499a53d4 | ||
![]() |
df15302f2c | ||
![]() |
039b51262d | ||
![]() |
465add46d4 | ||
![]() |
bce965b402 | ||
![]() |
95ce293169 | ||
![]() |
5d604c2cad | ||
![]() |
ed2d3ca277 | ||
![]() |
0478f40d02 | ||
![]() |
a4be73da3b | ||
![]() |
762192518f | ||
![]() |
fa51df192d | ||
![]() |
1a5cc02097 |
50
API.md
@@ -37,11 +37,11 @@ Get to the chopper!
|
||||
|
||||
|
||||
### backup_config
|
||||
Create a manual backup of the `config.ini` file.
|
||||
Create a manual backup of the `config.ini` file.
|
||||
|
||||
|
||||
### backup_db
|
||||
Create a manual backup of the `plexpy.db` file.
|
||||
Create a manual backup of the `plexpy.db` file.
|
||||
|
||||
|
||||
### delete_all_library_history
|
||||
@@ -142,6 +142,10 @@ Returns:
|
||||
```
|
||||
|
||||
|
||||
### delete_temp_sessions
|
||||
Flush out all of the temporary sessions in the database.
|
||||
|
||||
|
||||
### delete_user
|
||||
Delete a user from PlexPy. Also erases all history for the user.
|
||||
|
||||
@@ -158,11 +162,11 @@ Returns:
|
||||
|
||||
|
||||
### docs
|
||||
Return the api docs as a dict where commands are keys, docstring are value.
|
||||
Return the api docs as a dict where commands are keys, docstring are value.
|
||||
|
||||
|
||||
### docs_md
|
||||
Return the api docs formatted with markdown.
|
||||
Return the api docs formatted with markdown.
|
||||
|
||||
|
||||
### download_log
|
||||
@@ -755,11 +759,11 @@ Optional parameters:
|
||||
|
||||
Returns:
|
||||
json:
|
||||
[{"loglevel": "DEBUG",
|
||||
"msg": "Latest version is 2d10b0748c7fa2ee4cf59960c3d3fffc6aa9512b",
|
||||
"thread": "MainThread",
|
||||
[{"loglevel": "DEBUG",
|
||||
"msg": "Latest version is 2d10b0748c7fa2ee4cf59960c3d3fffc6aa9512b",
|
||||
"thread": "MainThread",
|
||||
"time": "2016-05-08 09:36:51 "
|
||||
},
|
||||
},
|
||||
{...},
|
||||
{...}
|
||||
]
|
||||
@@ -772,7 +776,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,16 +1797,36 @@ 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.
|
||||
Refresh the PlexPy libraries list.
|
||||
|
||||
|
||||
### refresh_users_list
|
||||
Refresh the PlexPy users list.
|
||||
Refresh the PlexPy users list.
|
||||
|
||||
|
||||
### restart
|
||||
Restart PlexPy.
|
||||
Restart PlexPy.
|
||||
|
||||
|
||||
### search
|
||||
@@ -1885,7 +1909,7 @@ Uninstalls the GeoLite2 database
|
||||
|
||||
|
||||
### update
|
||||
Check for PlexPy updates on Github.
|
||||
Check for PlexPy updates on Github.
|
||||
|
||||
|
||||
### update_metadata_details
|
||||
|
118
CHANGELOG.md
@@ -1,5 +1,123 @@
|
||||
# Changelog
|
||||
|
||||
## v1.4.24 (2017-10-01)
|
||||
|
||||
* Fix: New Plex Web urls. (Thanks @Joshua1337)
|
||||
* Fix: Fallback to the product name if the player title is blank.
|
||||
* New: Added no forking option to startup arguments. (Thanks @Vashypooh)
|
||||
|
||||
|
||||
## v1.4.23 (2017-09-30)
|
||||
|
||||
* Fix: Playstation 4 platform name.
|
||||
* Fix: PlexWatch and Plexivity import.
|
||||
* Fix: Pushbullet authorization header.
|
||||
|
||||
|
||||
## v1.4.22 (2017-08-19)
|
||||
|
||||
* Fix: Cleaning up of old config backups.
|
||||
* Fix: Temporary fix for incorrect source media info.
|
||||
|
||||
|
||||
## v1.4.21 (2017-07-01)
|
||||
|
||||
* New: Updated donation methods.
|
||||
|
||||
|
||||
## v1.4.20 (2017-06-24)
|
||||
|
||||
* New: Added platform image for the PlexTogether player.
|
||||
* Fix: Corrected math used to calculate human duration. (Thanks @senepa)
|
||||
* Fix: Sorting of 4k in media info tables.
|
||||
* Fix: Update file sizes when refreshing media info tables.
|
||||
* Fix: Support a custom port for Mattermost (Slack) notifications.
|
||||
|
||||
|
||||
## v1.4.19 (2017-05-31)
|
||||
|
||||
* Fix: Video resolution not showing up for transcoded streams on PMS 1.7.x.
|
||||
|
||||
|
||||
## v1.4.18 (2017-04-22)
|
||||
|
||||
* New: Added some new Arnold quotes. (Thanks @senepa)
|
||||
* Fix: Text wrapping in datatable footers.
|
||||
* Fix: API command get_apikey. (Thanks @Hellowlol)
|
||||
|
||||
|
||||
## v1.4.17 (2017-03-04)
|
||||
|
||||
* New: Configurable month range for the Plays by month graph. (Thanks @Pbaboe)
|
||||
* New: Option to chanage the week to start on Monday for the the Plays by day of week graph. (Thanks @Pbaboe)
|
||||
* Fix: Invalid iOS icon file paths. (Thanks @demonbane)
|
||||
* Fix: Plex Web 3.0 URLs on info pages and notifications.
|
||||
* Fix: Update bitcoin donation link to Coinbase.
|
||||
* Fix: Update init scripts. (Thanks @ampsonic)
|
||||
|
||||
|
||||
## v1.4.16 (2016-11-25)
|
||||
|
||||
* Fix: Websocket for new json response on PMS 1.3.0.
|
||||
* Fix: Update stream and transcoder tooltip percent.
|
||||
* Fix: Typo in the edit user modal.
|
||||
|
||||
|
||||
## v1.4.15 (2016-11-11)
|
||||
|
||||
* New: Add stream and transcoder progress percent to the current activity tooltip.
|
||||
* Fix: Refreshing of images in the cache when authentication is disabled.
|
||||
* Fix: Plex.tv authentication with special characters in the username or password.
|
||||
* Fix: Line breaks in the info page summaries.
|
||||
* Fix: Redirect to the proper http root when restarting.
|
||||
* Fix: API result type and responses showing incorrectly. (Thanks @Hellowlol)
|
||||
* Change: Use https URL for app.plex.tv.
|
||||
* Change: Show API traceback errors in the browser with debugging enabled. (Thanks @Hellowlol)
|
||||
* Change: Increase table width on mobile devices and max width set to 1750px. (Thanks @XusBadia)
|
||||
|
||||
|
||||
## v1.4.14 (2016-10-12)
|
||||
|
||||
* Fix: History logging locking up if media is removed from Plex before PlexPy can save the session.
|
||||
* Fix: Unable to save API key in the settings.
|
||||
* Fix: Some typos in the settings. (Thanks @Leafar3456)
|
||||
* Change: Disable script timeout by setting timeout to 0 seconds.
|
||||
|
||||
|
||||
## 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.
|
||||
|
@@ -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.
|
||||
|
@@ -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.
|
||||
-->
|
||||
|
||||
|
25
PlexPy.py
@@ -92,7 +92,9 @@ def main():
|
||||
'--nolaunch', action='store_true', help='Prevent browser from launching on startup')
|
||||
parser.add_argument(
|
||||
'--pidfile', help='Create a pid file (only relevant when running as a daemon)')
|
||||
|
||||
parser.add_argument(
|
||||
'--nofork', action='store_true', help='Start PlexPy as a service, do not fork when restarting')
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
if args.verbose:
|
||||
@@ -116,14 +118,31 @@ def main():
|
||||
plexpy.DAEMON = True
|
||||
plexpy.QUIET = True
|
||||
|
||||
if args.nofork:
|
||||
plexpy.NOFORK = True
|
||||
logger.info("PlexPy is running as a service, it will not fork when restarted.")
|
||||
|
||||
if args.pidfile:
|
||||
plexpy.PIDFILE = str(args.pidfile)
|
||||
|
||||
# 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
|
||||
|
24
README.md
@@ -1,15 +1,13 @@
|
||||
# PlexPy
|
||||
|
||||
[](https://gitter.im/drzoidberg33/plexpy?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
||||
[](https://discord.gg/36ggawe)
|
||||
[](https://gitter.im/plexpy/general)
|
||||
[](https://forums.plex.tv/discussion/169591/plexpy-another-plex-monitoring-program)
|
||||
|
||||
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)
|
||||
* [/r/Plex Discord server](https://discord.gg/011TFFWSuNFI02EKr) | [PlexPy Discord server](https://discord.gg/36ggawe)
|
||||
|
||||
## Features
|
||||
|
||||
* Responsive web design viewable on desktop, tablet and mobile web browsers.
|
||||
@@ -35,8 +33,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 +46,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 +72,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.
|
||||
|
@@ -66,67 +66,67 @@
|
||||
|
||||
<!-- STARTUP IMAGES -->
|
||||
<!-- iPad retina portrait startup image -->
|
||||
<link href="${http_root}images/res/screen/ios/Default-Portrait@2x~ipad.png"
|
||||
<link href="${http_root}images/res/ios/Default-Portrait@2x~ipad.png"
|
||||
media="(device-width: 768px) and (device-height: 1024px)
|
||||
and (-webkit-device-pixel-ratio: 2)
|
||||
and (orientation: portrait)"
|
||||
rel="apple-touch-startup-image">
|
||||
|
||||
<!-- iPad retina landscape startup image -->
|
||||
<link href="${http_root}images/res/screen/ios/Default-Landscape@2x~ipad.png"
|
||||
<link href="${http_root}images/res/ios/Default-Landscape@2x~ipad.png"
|
||||
media="(device-width: 768px) and (device-height: 1024px)
|
||||
and (-webkit-device-pixel-ratio: 2)
|
||||
and (orientation: landscape)"
|
||||
rel="apple-touch-startup-image">
|
||||
|
||||
<!-- iPad non-retina portrait startup image -->
|
||||
<link href="${http_root}images/res/screen/ios/Default-Portrait~ipad.png"
|
||||
<link href="${http_root}images/res/ios/Default-Portrait~ipad.png"
|
||||
media="(device-width: 768px) and (device-height: 1024px)
|
||||
and (-webkit-device-pixel-ratio: 1)
|
||||
and (orientation: portrait)"
|
||||
rel="apple-touch-startup-image">
|
||||
|
||||
<!-- iPad non-retina landscape startup image -->
|
||||
<link href="${http_root}images/res/screen/ios/Default-Landscape~ipad.png"
|
||||
<link href="${http_root}images/res/ios/Default-Landscape~ipad.png"
|
||||
media="(device-width: 768px) and (device-height: 1024px)
|
||||
and (-webkit-device-pixel-ratio: 1)
|
||||
and (orientation: landscape)"
|
||||
rel="apple-touch-startup-image">
|
||||
|
||||
<!-- iPhone 6 Plus portrait startup image -->
|
||||
<link href="${http_root}images/res/screen/ios/Default-736h.png"
|
||||
<link href="${http_root}images/res/ios/Default-736h.png"
|
||||
media="(device-width: 414px) and (device-height: 736px)
|
||||
and (-webkit-device-pixel-ratio: 3)
|
||||
and (orientation: portrait)"
|
||||
rel="apple-touch-startup-image">
|
||||
|
||||
<!-- iPhone 6 Plus landscape startup image -->
|
||||
<link href="${http_root}images/res/screen/ios/Default-Landscape-736h.png"
|
||||
<link href="${http_root}images/res/ios/Default-Landscape-736h.png"
|
||||
media="(device-width: 414px) and (device-height: 736px)
|
||||
and (-webkit-device-pixel-ratio: 3)
|
||||
and (orientation: landscape)"
|
||||
rel="apple-touch-startup-image">
|
||||
|
||||
<!-- iPhone 6 startup image -->
|
||||
<link href="${http_root}images/res/screen/ios/Default-667h.png"
|
||||
<link href="${http_root}images/res/ios/Default-667h.png"
|
||||
media="(device-width: 375px) and (device-height: 667px)
|
||||
and (-webkit-device-pixel-ratio: 2)"
|
||||
rel="apple-touch-startup-image">
|
||||
|
||||
<!-- iPhone 5 startup image -->
|
||||
<link href="${http_root}images/res/screen/ios/Default-568h@2x~iphone5.jpg"
|
||||
<link href="${http_root}images/res/ios/Default-568h@2x~iphone5.jpg"
|
||||
media="(device-width: 320px) and (device-height: 568px)
|
||||
and (-webkit-device-pixel-ratio: 2)"
|
||||
rel="apple-touch-startup-image">
|
||||
|
||||
<!-- iPhone < 5 retina startup image -->
|
||||
<link href="${http_root}images/res/screen/ios/Default@2x~iphone.png"
|
||||
<link href="${http_root}images/res/ios/Default@2x~iphone.png"
|
||||
media="(device-width: 320px) and (device-height: 480px)
|
||||
and (-webkit-device-pixel-ratio: 2)"
|
||||
rel="apple-touch-startup-image">
|
||||
|
||||
<!-- iPhone < 5 non-retina startup image -->
|
||||
<link href="${http_root}images/res/screen/ios/Default~iphone.png"
|
||||
<link href="${http_root}images/res/ios/Default~iphone.png"
|
||||
media="(device-width: 320px) and (device-height: 480px)
|
||||
and (-webkit-device-pixel-ratio: 1)"
|
||||
rel="apple-touch-startup-image">
|
||||
@@ -220,9 +220,10 @@
|
||||
<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>
|
||||
<li><a href="#" data-target="#donate-modal" data-toggle="modal"><i class="fa fa-fw fa-heart"></i> Donate</a></li>
|
||||
<li role="separator" class="divider"></li>
|
||||
% if plexpy.CONFIG.CHECK_GITHUB:
|
||||
<li><a href="#" id="nav-update"><i class="fa fa-fw fa-arrow-circle-up"></i> Check for Updates</a></li>
|
||||
@@ -303,6 +304,64 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
% else:
|
||||
<div id="donate-modal" class="modal fade" tabindex="-1" role="dialog" aria-labelledby="crypto-donate-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">PlexPy Donation</h4>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="row">
|
||||
<div class="col-md-12" style="text-align: center;">
|
||||
<h4>
|
||||
<strong>Thank you for supporting PlexPy!</strong>
|
||||
</h4>
|
||||
<p>
|
||||
Please select a donation method.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<ul id="donation_type" class="nav nav-pills" role="tablist" style="display: flex; justify-content: center; margin: 10px 0;">
|
||||
<li class="active"><a href="#paypal-donation" role="tab" data-toggle="tab">PayPal</a></li>
|
||||
<li><a href="#flattr-donation" role="tab" data-toggle="tab">Flattr</a></li>
|
||||
<li><a href="#crypto-donation" role="tab" data-toggle="tab" class="crypto-donation" data-coin="bitcoin" data-name="Bitcoin" data-address="3FdfJAyNWU15Sf11U9FTgPHuP1hPz32eEN">Bitcoin</a></li>
|
||||
<li><a href="#crypto-donation" role="tab" data-toggle="tab" class="crypto-donation" data-coin="bitcoincash" data-name="Bitcoin Cash" data-address="1H2atabxAQGaFAWYQEiLkXKSnK9CZZvt2n">Bitcoin Cash</a></li>
|
||||
<li><a href="#crypto-donation" role="tab" data-toggle="tab" class="crypto-donation" data-coin="ethereum" data-name="Ethereum" data-address="0x77ae4c2b8de1a1ccfa93553db39971da58c873d3">Ethereum</a></li>
|
||||
<li><a href="#crypto-donation" role="tab" data-toggle="tab" class="crypto-donation" data-coin="litecoin" data-name="Litecoin" data-address="LWpPmUqQYHBhMV83XSCsHzPmKLhJt6r57J">Litecoin</a></li>
|
||||
</ul>
|
||||
<div class="tab-content">
|
||||
<div role="tabpanel" class="tab-pane active" id="paypal-donation" style="text-align: center">
|
||||
<p>
|
||||
Click the button below to continue to PayPal.
|
||||
</p>
|
||||
<a href="${anon_url('https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=6XPPKTDSX9QFL&lc=US&item_name=PlexPy¤cy_code=USD&bn=PP%2dDonationsBF%3abtn_donate_LG%2egif%3aNonHosted')}" target="_blank">
|
||||
<img src="images/gold-rect-paypal-34px.png" alt="PayPal">
|
||||
</a>
|
||||
</div>
|
||||
<div role="tabpanel" class="tab-pane" id="flattr-donation" style="text-align: center">
|
||||
<p>
|
||||
Click the button below to continue to Flattr.
|
||||
</p>
|
||||
<a href="${anon_url('https://flattr.com/submit/auto?user_id=JonnyWong16&url=https://github.com/JonnyWong16/plexpy&title=PlexPy&language=en_GB&tags=github&category=software')}" target="_blank">
|
||||
<img src="images/flattr-badge-large.png" alt="Flattr">
|
||||
</a>
|
||||
</div>
|
||||
<div role="tabpanel" class="tab-pane" id="crypto-donation">
|
||||
<label>QR Code</label>
|
||||
<pre id="crypto_qr_code" style="text-align: center"></pre>
|
||||
<label><span id="crypto_type_label"></span> Address</label>
|
||||
<pre id="crypto_address" style="text-align: center"></pre>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<input type="button" class="btn btn-bright" data-dismiss="modal" value="Close">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
% endif
|
||||
|
||||
${next.headerIncludes()}
|
||||
@@ -315,8 +374,10 @@ ${next.headerIncludes()}
|
||||
<script src="${http_root}js/bootstrap-hover-dropdown.min.js"></script>
|
||||
<script src="${http_root}js/pnotify.custom.min.js"></script>
|
||||
<script src="${http_root}js/script.js"></script>
|
||||
<script src="${http_root}js/jquery.qrcode.min.js"></script>
|
||||
% if _session['user_group'] == 'admin' and plexpy.CONFIG.BROWSER_ENABLED:
|
||||
<script src="${http_root}js/ajaxNotifications.js"></script>
|
||||
% else:
|
||||
% endif
|
||||
<script>
|
||||
% if _session['user_group'] == 'admin':
|
||||
@@ -352,6 +413,17 @@ ${next.headerIncludes()}
|
||||
$(this).html('<i class="fa fa-spin fa-refresh"></i> Checking');
|
||||
window.location.href = "checkGithub";
|
||||
});
|
||||
|
||||
$('#donation_type a.crypto-donation').on('shown.bs.tab', function () {
|
||||
var crypto_coin = $(this).data('coin');
|
||||
var crypto_name = $(this).data('name');
|
||||
var crypto_address = $(this).data('address')
|
||||
$('#crypto_qr_code').empty().qrcode({
|
||||
text: crypto_coin + ":" + crypto_address
|
||||
});
|
||||
$('#crypto_type_label').html(crypto_name);
|
||||
$('#crypto_address').html(crypto_address);
|
||||
});
|
||||
% endif
|
||||
|
||||
$('.dropdown-toggle').click(function (e) {
|
||||
|
@@ -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>
|
@@ -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;
|
||||
@@ -2219,7 +2251,8 @@ a .home-platforms-list-poster-face:hover
|
||||
margin-right: auto;
|
||||
margin-top: 20px;
|
||||
margin-bottom: 20px;
|
||||
width: 90%;
|
||||
width: 100%;
|
||||
max-width: 1750px;
|
||||
overflow: hidden;
|
||||
}
|
||||
.table-card-header {
|
||||
@@ -2231,7 +2264,8 @@ a .home-platforms-list-poster-face:hover
|
||||
margin-right: auto;
|
||||
margin-top: 20px;
|
||||
margin-bottom: -20px;
|
||||
width: 90%;
|
||||
width: 100%;
|
||||
max-width: 1750px;
|
||||
overflow: hidden;
|
||||
}
|
||||
.table-card-back td {
|
||||
@@ -2457,6 +2491,9 @@ a .home-platforms-list-poster-face:hover
|
||||
.dataTables_paginate li {
|
||||
margin: 0;
|
||||
}
|
||||
div.dataTables_info {
|
||||
white-space: normal !important;
|
||||
}
|
||||
.tooltip.top .tooltip-arrow {
|
||||
border-top-color: #fff;
|
||||
}
|
||||
@@ -2630,7 +2667,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);
|
||||
}
|
||||
@@ -2799,6 +2836,14 @@ div[id^='media_info_child'] div[id^='media_info_child'] div.dataTables_scrollHea
|
||||
width: 75px;
|
||||
height: 34px;
|
||||
}
|
||||
#months-selection label {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
#graph-months {
|
||||
margin: 0;
|
||||
width: 75px;
|
||||
height: 34px;
|
||||
}
|
||||
.card-sortable {
|
||||
height: 36px;
|
||||
padding: 0 20px 0 0;
|
||||
@@ -3023,3 +3068,13 @@ 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[readonly] {
|
||||
background-color: #555;
|
||||
}
|
||||
#api_key.form-control[readonly]:focus {
|
||||
background-color: #fff;
|
||||
}
|
||||
|
@@ -207,8 +207,8 @@ DOCUMENTATION :: END
|
||||
% endif
|
||||
<div class="dashboard-activity-progress">
|
||||
<div class="dashboard-activity-progress-bar">
|
||||
<div id="bufferbar-${data['session_key']}" class="bufferbar" style="width: ${data['transcode_progress']}%" data-toggle="tooltip" title="Transcoder Progress">${data['transcode_progress']}%</div>
|
||||
<div id="bar-${data['session_key']}" class="bar" style="width: ${data['progress_percent']}%" data-toggle="tooltip" title="Stream Progress">${data['progress_percent']}%</div>
|
||||
<div id="bufferbar-${data['session_key']}" class="bufferbar" style="width: ${data['transcode_progress']}%" data-toggle="tooltip" title="Transcoder Progress ${data['transcode_progress']}%">${data['transcode_progress']}%</div>
|
||||
<div id="bar-${data['session_key']}" class="bar" style="width: ${data['progress_percent']}%" data-toggle="tooltip" title="Stream Progress ${data['progress_percent']}%">${data['progress_percent']}%</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@@ -45,7 +45,7 @@ DOCUMENTATION :: END
|
||||
<input type="text" class="form-control" id="friendly_name" name="friendly_name" value="${data['friendly_name']}" size="30">
|
||||
</div>
|
||||
</div>
|
||||
<p class="help-block">Replace all occurances of the username with this name.</p>
|
||||
<p class="help-block">Replace all occurrences of the username with this name.</p>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="profile_url">Profile Picture URL</label>
|
||||
|
@@ -42,6 +42,11 @@
|
||||
<input type="number" name="graph-days" id="graph-days" value="${config['graph_days']}" min="1" /> days
|
||||
</label>
|
||||
</div>
|
||||
<div class="btn-group" id="months-selection">
|
||||
<label>
|
||||
<input type="number" name="graph-months" id="graph-months" value="${config['graph_months']}" min="1" /> months
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class='table-card-back'>
|
||||
@@ -226,7 +231,7 @@
|
||||
% endif
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<h4><i class="fa fa-calendar"></i> Plays by Month <small>Last 12 months</small></h4>
|
||||
<h4><i class="fa fa-calendar"></i> Plays by month <small>Last <span class="months">12</span> months</small></h4>
|
||||
<p class="help-block">
|
||||
The combined total of tv, movies, and music by month.
|
||||
</p>
|
||||
@@ -317,10 +322,12 @@
|
||||
|
||||
// Initial values for graph from config
|
||||
var yaxis = "${config['graph_type']}";
|
||||
var current_range = ${config['graph_days']};
|
||||
var current_day_range = ${config['graph_days']};
|
||||
var current_month_range = ${config['graph_months']};
|
||||
var current_tab = "${'#' + config['graph_tab']}";
|
||||
|
||||
$('.days').html(current_range);
|
||||
$('.days').html(current_day_range);
|
||||
$('.months').html(current_month_range);
|
||||
|
||||
// Load user ids and names (for the selector)
|
||||
$.ajax({
|
||||
@@ -352,6 +359,7 @@
|
||||
|
||||
function loadGraphsTab1(time_range, yaxis) {
|
||||
$('#days-selection').show();
|
||||
$('#months-selection').hide();
|
||||
|
||||
setGraphFormat(yaxis);
|
||||
|
||||
@@ -442,6 +450,7 @@
|
||||
|
||||
function loadGraphsTab2(time_range, yaxis) {
|
||||
$('#days-selection').show();
|
||||
$('#months-selection').hide();
|
||||
|
||||
setGraphFormat(yaxis);
|
||||
|
||||
@@ -525,15 +534,16 @@
|
||||
});
|
||||
}
|
||||
|
||||
function loadGraphsTab3(yaxis) {
|
||||
function loadGraphsTab3(time_range, yaxis) {
|
||||
$('#days-selection').hide();
|
||||
$('#months-selection').show();
|
||||
|
||||
setGraphFormat(yaxis);
|
||||
|
||||
$.ajax({
|
||||
url: "get_plays_per_month",
|
||||
type: 'get',
|
||||
data: { y_axis: yaxis, user_id: selected_user_id },
|
||||
data: { time_range: time_range, y_axis: yaxis, user_id: selected_user_id },
|
||||
dataType: "json",
|
||||
success: function(data) {
|
||||
if (yaxis === 'duration') { dataSecondsToHours(data); }
|
||||
@@ -547,15 +557,15 @@
|
||||
}
|
||||
|
||||
// Set initial state
|
||||
if (current_tab == '#tabs-1') { loadGraphsTab1(current_range, yaxis); }
|
||||
if (current_tab == '#tabs-2') { loadGraphsTab2(current_range, yaxis); }
|
||||
if (current_tab == '#tabs-3') { loadGraphsTab3(yaxis); }
|
||||
if (current_tab == '#tabs-1') { loadGraphsTab1(current_day_range, yaxis); }
|
||||
if (current_tab == '#tabs-2') { loadGraphsTab2(current_day_range, yaxis); }
|
||||
if (current_tab == '#tabs-3') { loadGraphsTab3(current_month_range, yaxis); }
|
||||
|
||||
// Tab1 opened
|
||||
$('#graph-tabs a[href="#tabs-1"]').on('shown.bs.tab', function (e) {
|
||||
e.preventDefault();
|
||||
current_tab = $(this).attr('href');
|
||||
loadGraphsTab1(current_range, yaxis);
|
||||
loadGraphsTab1(current_day_range, yaxis);
|
||||
$.ajax({
|
||||
url: 'set_graph_config',
|
||||
data: { graph_tab: current_tab.replace('#','') },
|
||||
@@ -567,7 +577,7 @@
|
||||
$('#graph-tabs a[href="#tabs-2"]').on('shown.bs.tab', function (e) {
|
||||
e.preventDefault();
|
||||
current_tab = $(this).attr('href');
|
||||
loadGraphsTab2(current_range, yaxis);
|
||||
loadGraphsTab2(current_day_range, yaxis);
|
||||
$.ajax({
|
||||
url: 'set_graph_config',
|
||||
data: { graph_tab: current_tab.replace('#','') },
|
||||
@@ -579,7 +589,7 @@
|
||||
$('#graph-tabs a[href="#tabs-3"]').on('shown.bs.tab', function (e) {
|
||||
e.preventDefault();
|
||||
current_tab = $(this).attr('href');
|
||||
loadGraphsTab3(yaxis);
|
||||
loadGraphsTab3(current_month_range, yaxis);
|
||||
$.ajax({
|
||||
url: 'set_graph_config',
|
||||
data: { graph_tab: current_tab.replace('#','') },
|
||||
@@ -589,17 +599,35 @@
|
||||
|
||||
// Date range changed
|
||||
$('#graph-days').on('change', function() {
|
||||
current_range = $(this).val();
|
||||
if (current_range < 1) {
|
||||
current_day_range = Math.round($(this).val());
|
||||
$(this).val(current_day_range);
|
||||
if (current_day_range < 1) {
|
||||
$(this).val(7);
|
||||
current_range = 7;
|
||||
current_day_range = 7;
|
||||
}
|
||||
if (current_tab == '#tabs-1') { loadGraphsTab1(current_range, yaxis); }
|
||||
if (current_tab == '#tabs-2') { loadGraphsTab2(current_range, yaxis); }
|
||||
$('.days').html(current_range);
|
||||
if (current_tab == '#tabs-1') { loadGraphsTab1(current_day_range, yaxis); }
|
||||
if (current_tab == '#tabs-2') { loadGraphsTab2(current_day_range, yaxis); }
|
||||
$('.days').html(current_day_range);
|
||||
$.ajax({
|
||||
url: 'set_graph_config',
|
||||
data: { graph_days: current_range},
|
||||
data: { graph_days: current_day_range},
|
||||
async: true
|
||||
});
|
||||
});
|
||||
|
||||
// Month range changed
|
||||
$('#graph-months').on('change', function() {
|
||||
current_month_range = Math.round($(this).val());
|
||||
$(this).val(current_month_range);
|
||||
if (current_month_range < 1) {
|
||||
$(this).val(12);
|
||||
current_month_range = 12;
|
||||
}
|
||||
if (current_tab == '#tabs-3') { loadGraphsTab3(current_month_range, yaxis); }
|
||||
$('.months').html(current_month_range);
|
||||
$.ajax({
|
||||
url: 'set_graph_config',
|
||||
data: { graph_months: current_month_range},
|
||||
async: true
|
||||
});
|
||||
});
|
||||
@@ -607,17 +635,17 @@
|
||||
// User changed
|
||||
$('#graph-user').on('change', function() {
|
||||
selected_user_id = $(this).val() || null;
|
||||
if (current_tab == '#tabs-1') { loadGraphsTab1(current_range, yaxis); }
|
||||
if (current_tab == '#tabs-2') { loadGraphsTab2(current_range, yaxis); }
|
||||
if (current_tab == '#tabs-3') { loadGraphsTab3(yaxis); }
|
||||
if (current_tab == '#tabs-1') { loadGraphsTab1(current_day_range, yaxis); }
|
||||
if (current_tab == '#tabs-2') { loadGraphsTab2(current_day_range, yaxis); }
|
||||
if (current_tab == '#tabs-3') { loadGraphsTab3(current_month_range, yaxis); }
|
||||
});
|
||||
|
||||
// Y-axis changed
|
||||
$('#yaxis-selection').on('change', function() {
|
||||
yaxis = $('input[name=yaxis-options]:checked', '#yaxis-selection').val();
|
||||
if (current_tab == '#tabs-1') { loadGraphsTab1(current_range, yaxis); }
|
||||
if (current_tab == '#tabs-2') { loadGraphsTab2(current_range, yaxis); }
|
||||
if (current_tab == '#tabs-3') { loadGraphsTab3(yaxis); }
|
||||
if (current_tab == '#tabs-1') { loadGraphsTab1(current_day_range, yaxis); }
|
||||
if (current_tab == '#tabs-2') { loadGraphsTab2(current_day_range, yaxis); }
|
||||
if (current_tab == '#tabs-3') { loadGraphsTab3(current_month_range, yaxis); }
|
||||
$.ajax({
|
||||
url: 'set_graph_config',
|
||||
data: { graph_type: yaxis},
|
||||
|
@@ -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">
|
||||
|
BIN
data/interfaces/default/images/flattr-badge-large.png
Normal file
After Width: | Height: | Size: 2.2 KiB |
BIN
data/interfaces/default/images/gold-rect-paypal-34px.png
Normal file
After Width: | Height: | Size: 2.7 KiB |
BIN
data/interfaces/default/images/platforms/plextogether.png
Normal file
After Width: | Height: | Size: 4.2 KiB |
Before Width: | Height: | Size: 137 KiB |
Before Width: | Height: | Size: 3.7 KiB After Width: | Height: | Size: 3.7 KiB |
Before Width: | Height: | Size: 8.1 KiB After Width: | Height: | Size: 8.1 KiB |
Before Width: | Height: | Size: 2.3 KiB After Width: | Height: | Size: 2.3 KiB |
Before Width: | Height: | Size: 5.2 KiB After Width: | Height: | Size: 5.2 KiB |
Before Width: | Height: | Size: 3.0 KiB After Width: | Height: | Size: 3.0 KiB |
Before Width: | Height: | Size: 6.5 KiB After Width: | Height: | Size: 6.5 KiB |
@@ -204,8 +204,11 @@
|
||||
|
||||
// update the progress bars
|
||||
// percent - 3 because of 3px padding-right
|
||||
$('#bufferbar-' + key).width(parseInt(s.transcode_progress) - 3 + '%').html(s.transcode_progress + '%');
|
||||
$('#bar-' + key).width(parseInt(s.progress_percent) - 3 + '%').html(s.progress_percent + '%');
|
||||
$('#bufferbar-' + key).width(parseInt(s.transcode_progress) - 3 + '%').html(s.transcode_progress + '%')
|
||||
.attr('data-original-title', 'Transcoder Progress ' + s.transcode_progress + '%');
|
||||
$('#bar-' + key).width(parseInt(s.progress_percent) - 3 + '%').html(s.progress_percent + '%')
|
||||
.attr('data-original-title', 'Stream Progress ' + s.progress_percent + '%');
|
||||
|
||||
|
||||
// add temporary class so we know which instances are still active
|
||||
instance.addClass('updated-temp');
|
||||
|
@@ -53,6 +53,9 @@ DOCUMENTATION :: END
|
||||
if re.match(pattern, codec):
|
||||
return file
|
||||
return codec
|
||||
|
||||
def br(text):
|
||||
return text.replace('\n', '<br /><br />')
|
||||
%>
|
||||
|
||||
<%inherit file="base.html"/>
|
||||
@@ -112,9 +115,9 @@ DOCUMENTATION :: END
|
||||
<div class="col-md-9">
|
||||
<div class="summary-content-poster hidden-xs hidden-sm">
|
||||
% if data['media_type'] == 'track':
|
||||
<a href="http://app.plex.tv/web/app#!/server/${config['pms_identifier']}/details/%2Flibrary%2Fmetadata%2F${data['parent_rating_key']}" target="_blank" title="View in Plex Web">
|
||||
<a href="https://app.plex.tv/desktop#!/server/${config['pms_identifier']}/details?key=%2Flibrary%2Fmetadata%2F${data['parent_rating_key']}" target="_blank" title="View in Plex Web">
|
||||
% else:
|
||||
<a href="http://app.plex.tv/web/app#!/server/${config['pms_identifier']}/details/%2Flibrary%2Fmetadata%2F${data['rating_key']}" target="_blank" title="View in Plex Web">
|
||||
<a href="https://app.plex.tv/desktop#!/server/${config['pms_identifier']}/details?key=%2Flibrary%2Fmetadata%2F${data['rating_key']}" target="_blank" title="View in Plex Web">
|
||||
% endif
|
||||
% if data['media_type'] == 'episode':
|
||||
<div class="summary-poster-face-episode" style="background-image: url(pms_image_proxy?img=${data['thumb']}&width=500&height=280&fallback=art);">
|
||||
@@ -250,7 +253,7 @@ DOCUMENTATION :: END
|
||||
</div>
|
||||
% endif
|
||||
<div class="summary-content-summary">
|
||||
<p> ${data['summary']} </p>
|
||||
<p> ${data['summary'] | br, n} </p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
28
data/interfaces/default/js/jquery.qrcode.min.js
vendored
Normal file
@@ -0,0 +1,28 @@
|
||||
(function(r){r.fn.qrcode=function(h){var s;function u(a){this.mode=s;this.data=a}function o(a,c){this.typeNumber=a;this.errorCorrectLevel=c;this.modules=null;this.moduleCount=0;this.dataCache=null;this.dataList=[]}function q(a,c){if(void 0==a.length)throw Error(a.length+"/"+c);for(var d=0;d<a.length&&0==a[d];)d++;this.num=Array(a.length-d+c);for(var b=0;b<a.length-d;b++)this.num[b]=a[b+d]}function p(a,c){this.totalCount=a;this.dataCount=c}function t(){this.buffer=[];this.length=0}u.prototype={getLength:function(){return this.data.length},
|
||||
write:function(a){for(var c=0;c<this.data.length;c++)a.put(this.data.charCodeAt(c),8)}};o.prototype={addData:function(a){this.dataList.push(new u(a));this.dataCache=null},isDark:function(a,c){if(0>a||this.moduleCount<=a||0>c||this.moduleCount<=c)throw Error(a+","+c);return this.modules[a][c]},getModuleCount:function(){return this.moduleCount},make:function(){if(1>this.typeNumber){for(var a=1,a=1;40>a;a++){for(var c=p.getRSBlocks(a,this.errorCorrectLevel),d=new t,b=0,e=0;e<c.length;e++)b+=c[e].dataCount;
|
||||
for(e=0;e<this.dataList.length;e++)c=this.dataList[e],d.put(c.mode,4),d.put(c.getLength(),j.getLengthInBits(c.mode,a)),c.write(d);if(d.getLengthInBits()<=8*b)break}this.typeNumber=a}this.makeImpl(!1,this.getBestMaskPattern())},makeImpl:function(a,c){this.moduleCount=4*this.typeNumber+17;this.modules=Array(this.moduleCount);for(var d=0;d<this.moduleCount;d++){this.modules[d]=Array(this.moduleCount);for(var b=0;b<this.moduleCount;b++)this.modules[d][b]=null}this.setupPositionProbePattern(0,0);this.setupPositionProbePattern(this.moduleCount-
|
||||
7,0);this.setupPositionProbePattern(0,this.moduleCount-7);this.setupPositionAdjustPattern();this.setupTimingPattern();this.setupTypeInfo(a,c);7<=this.typeNumber&&this.setupTypeNumber(a);null==this.dataCache&&(this.dataCache=o.createData(this.typeNumber,this.errorCorrectLevel,this.dataList));this.mapData(this.dataCache,c)},setupPositionProbePattern:function(a,c){for(var d=-1;7>=d;d++)if(!(-1>=a+d||this.moduleCount<=a+d))for(var b=-1;7>=b;b++)-1>=c+b||this.moduleCount<=c+b||(this.modules[a+d][c+b]=
|
||||
0<=d&&6>=d&&(0==b||6==b)||0<=b&&6>=b&&(0==d||6==d)||2<=d&&4>=d&&2<=b&&4>=b?!0:!1)},getBestMaskPattern:function(){for(var a=0,c=0,d=0;8>d;d++){this.makeImpl(!0,d);var b=j.getLostPoint(this);if(0==d||a>b)a=b,c=d}return c},createMovieClip:function(a,c,d){a=a.createEmptyMovieClip(c,d);this.make();for(c=0;c<this.modules.length;c++)for(var d=1*c,b=0;b<this.modules[c].length;b++){var e=1*b;this.modules[c][b]&&(a.beginFill(0,100),a.moveTo(e,d),a.lineTo(e+1,d),a.lineTo(e+1,d+1),a.lineTo(e,d+1),a.endFill())}return a},
|
||||
setupTimingPattern:function(){for(var a=8;a<this.moduleCount-8;a++)null==this.modules[a][6]&&(this.modules[a][6]=0==a%2);for(a=8;a<this.moduleCount-8;a++)null==this.modules[6][a]&&(this.modules[6][a]=0==a%2)},setupPositionAdjustPattern:function(){for(var a=j.getPatternPosition(this.typeNumber),c=0;c<a.length;c++)for(var d=0;d<a.length;d++){var b=a[c],e=a[d];if(null==this.modules[b][e])for(var f=-2;2>=f;f++)for(var i=-2;2>=i;i++)this.modules[b+f][e+i]=-2==f||2==f||-2==i||2==i||0==f&&0==i?!0:!1}},setupTypeNumber:function(a){for(var c=
|
||||
j.getBCHTypeNumber(this.typeNumber),d=0;18>d;d++){var b=!a&&1==(c>>d&1);this.modules[Math.floor(d/3)][d%3+this.moduleCount-8-3]=b}for(d=0;18>d;d++)b=!a&&1==(c>>d&1),this.modules[d%3+this.moduleCount-8-3][Math.floor(d/3)]=b},setupTypeInfo:function(a,c){for(var d=j.getBCHTypeInfo(this.errorCorrectLevel<<3|c),b=0;15>b;b++){var e=!a&&1==(d>>b&1);6>b?this.modules[b][8]=e:8>b?this.modules[b+1][8]=e:this.modules[this.moduleCount-15+b][8]=e}for(b=0;15>b;b++)e=!a&&1==(d>>b&1),8>b?this.modules[8][this.moduleCount-
|
||||
b-1]=e:9>b?this.modules[8][15-b-1+1]=e:this.modules[8][15-b-1]=e;this.modules[this.moduleCount-8][8]=!a},mapData:function(a,c){for(var d=-1,b=this.moduleCount-1,e=7,f=0,i=this.moduleCount-1;0<i;i-=2)for(6==i&&i--;;){for(var g=0;2>g;g++)if(null==this.modules[b][i-g]){var n=!1;f<a.length&&(n=1==(a[f]>>>e&1));j.getMask(c,b,i-g)&&(n=!n);this.modules[b][i-g]=n;e--; -1==e&&(f++,e=7)}b+=d;if(0>b||this.moduleCount<=b){b-=d;d=-d;break}}}};o.PAD0=236;o.PAD1=17;o.createData=function(a,c,d){for(var c=p.getRSBlocks(a,
|
||||
c),b=new t,e=0;e<d.length;e++){var f=d[e];b.put(f.mode,4);b.put(f.getLength(),j.getLengthInBits(f.mode,a));f.write(b)}for(e=a=0;e<c.length;e++)a+=c[e].dataCount;if(b.getLengthInBits()>8*a)throw Error("code length overflow. ("+b.getLengthInBits()+">"+8*a+")");for(b.getLengthInBits()+4<=8*a&&b.put(0,4);0!=b.getLengthInBits()%8;)b.putBit(!1);for(;!(b.getLengthInBits()>=8*a);){b.put(o.PAD0,8);if(b.getLengthInBits()>=8*a)break;b.put(o.PAD1,8)}return o.createBytes(b,c)};o.createBytes=function(a,c){for(var d=
|
||||
0,b=0,e=0,f=Array(c.length),i=Array(c.length),g=0;g<c.length;g++){var n=c[g].dataCount,h=c[g].totalCount-n,b=Math.max(b,n),e=Math.max(e,h);f[g]=Array(n);for(var k=0;k<f[g].length;k++)f[g][k]=255&a.buffer[k+d];d+=n;k=j.getErrorCorrectPolynomial(h);n=(new q(f[g],k.getLength()-1)).mod(k);i[g]=Array(k.getLength()-1);for(k=0;k<i[g].length;k++)h=k+n.getLength()-i[g].length,i[g][k]=0<=h?n.get(h):0}for(k=g=0;k<c.length;k++)g+=c[k].totalCount;d=Array(g);for(k=n=0;k<b;k++)for(g=0;g<c.length;g++)k<f[g].length&&
|
||||
(d[n++]=f[g][k]);for(k=0;k<e;k++)for(g=0;g<c.length;g++)k<i[g].length&&(d[n++]=i[g][k]);return d};s=4;for(var j={PATTERN_POSITION_TABLE:[[],[6,18],[6,22],[6,26],[6,30],[6,34],[6,22,38],[6,24,42],[6,26,46],[6,28,50],[6,30,54],[6,32,58],[6,34,62],[6,26,46,66],[6,26,48,70],[6,26,50,74],[6,30,54,78],[6,30,56,82],[6,30,58,86],[6,34,62,90],[6,28,50,72,94],[6,26,50,74,98],[6,30,54,78,102],[6,28,54,80,106],[6,32,58,84,110],[6,30,58,86,114],[6,34,62,90,118],[6,26,50,74,98,122],[6,30,54,78,102,126],[6,26,52,
|
||||
78,104,130],[6,30,56,82,108,134],[6,34,60,86,112,138],[6,30,58,86,114,142],[6,34,62,90,118,146],[6,30,54,78,102,126,150],[6,24,50,76,102,128,154],[6,28,54,80,106,132,158],[6,32,58,84,110,136,162],[6,26,54,82,110,138,166],[6,30,58,86,114,142,170]],G15:1335,G18:7973,G15_MASK:21522,getBCHTypeInfo:function(a){for(var c=a<<10;0<=j.getBCHDigit(c)-j.getBCHDigit(j.G15);)c^=j.G15<<j.getBCHDigit(c)-j.getBCHDigit(j.G15);return(a<<10|c)^j.G15_MASK},getBCHTypeNumber:function(a){for(var c=a<<12;0<=j.getBCHDigit(c)-
|
||||
j.getBCHDigit(j.G18);)c^=j.G18<<j.getBCHDigit(c)-j.getBCHDigit(j.G18);return a<<12|c},getBCHDigit:function(a){for(var c=0;0!=a;)c++,a>>>=1;return c},getPatternPosition:function(a){return j.PATTERN_POSITION_TABLE[a-1]},getMask:function(a,c,d){switch(a){case 0:return 0==(c+d)%2;case 1:return 0==c%2;case 2:return 0==d%3;case 3:return 0==(c+d)%3;case 4:return 0==(Math.floor(c/2)+Math.floor(d/3))%2;case 5:return 0==c*d%2+c*d%3;case 6:return 0==(c*d%2+c*d%3)%2;case 7:return 0==(c*d%3+(c+d)%2)%2;default:throw Error("bad maskPattern:"+
|
||||
a);}},getErrorCorrectPolynomial:function(a){for(var c=new q([1],0),d=0;d<a;d++)c=c.multiply(new q([1,l.gexp(d)],0));return c},getLengthInBits:function(a,c){if(1<=c&&10>c)switch(a){case 1:return 10;case 2:return 9;case s:return 8;case 8:return 8;default:throw Error("mode:"+a);}else if(27>c)switch(a){case 1:return 12;case 2:return 11;case s:return 16;case 8:return 10;default:throw Error("mode:"+a);}else if(41>c)switch(a){case 1:return 14;case 2:return 13;case s:return 16;case 8:return 12;default:throw Error("mode:"+
|
||||
a);}else throw Error("type:"+c);},getLostPoint:function(a){for(var c=a.getModuleCount(),d=0,b=0;b<c;b++)for(var e=0;e<c;e++){for(var f=0,i=a.isDark(b,e),g=-1;1>=g;g++)if(!(0>b+g||c<=b+g))for(var h=-1;1>=h;h++)0>e+h||c<=e+h||0==g&&0==h||i==a.isDark(b+g,e+h)&&f++;5<f&&(d+=3+f-5)}for(b=0;b<c-1;b++)for(e=0;e<c-1;e++)if(f=0,a.isDark(b,e)&&f++,a.isDark(b+1,e)&&f++,a.isDark(b,e+1)&&f++,a.isDark(b+1,e+1)&&f++,0==f||4==f)d+=3;for(b=0;b<c;b++)for(e=0;e<c-6;e++)a.isDark(b,e)&&!a.isDark(b,e+1)&&a.isDark(b,e+
|
||||
2)&&a.isDark(b,e+3)&&a.isDark(b,e+4)&&!a.isDark(b,e+5)&&a.isDark(b,e+6)&&(d+=40);for(e=0;e<c;e++)for(b=0;b<c-6;b++)a.isDark(b,e)&&!a.isDark(b+1,e)&&a.isDark(b+2,e)&&a.isDark(b+3,e)&&a.isDark(b+4,e)&&!a.isDark(b+5,e)&&a.isDark(b+6,e)&&(d+=40);for(e=f=0;e<c;e++)for(b=0;b<c;b++)a.isDark(b,e)&&f++;a=Math.abs(100*f/c/c-50)/5;return d+10*a}},l={glog:function(a){if(1>a)throw Error("glog("+a+")");return l.LOG_TABLE[a]},gexp:function(a){for(;0>a;)a+=255;for(;256<=a;)a-=255;return l.EXP_TABLE[a]},EXP_TABLE:Array(256),
|
||||
LOG_TABLE:Array(256)},m=0;8>m;m++)l.EXP_TABLE[m]=1<<m;for(m=8;256>m;m++)l.EXP_TABLE[m]=l.EXP_TABLE[m-4]^l.EXP_TABLE[m-5]^l.EXP_TABLE[m-6]^l.EXP_TABLE[m-8];for(m=0;255>m;m++)l.LOG_TABLE[l.EXP_TABLE[m]]=m;q.prototype={get:function(a){return this.num[a]},getLength:function(){return this.num.length},multiply:function(a){for(var c=Array(this.getLength()+a.getLength()-1),d=0;d<this.getLength();d++)for(var b=0;b<a.getLength();b++)c[d+b]^=l.gexp(l.glog(this.get(d))+l.glog(a.get(b)));return new q(c,0)},mod:function(a){if(0>
|
||||
this.getLength()-a.getLength())return this;for(var c=l.glog(this.get(0))-l.glog(a.get(0)),d=Array(this.getLength()),b=0;b<this.getLength();b++)d[b]=this.get(b);for(b=0;b<a.getLength();b++)d[b]^=l.gexp(l.glog(a.get(b))+c);return(new q(d,0)).mod(a)}};p.RS_BLOCK_TABLE=[[1,26,19],[1,26,16],[1,26,13],[1,26,9],[1,44,34],[1,44,28],[1,44,22],[1,44,16],[1,70,55],[1,70,44],[2,35,17],[2,35,13],[1,100,80],[2,50,32],[2,50,24],[4,25,9],[1,134,108],[2,67,43],[2,33,15,2,34,16],[2,33,11,2,34,12],[2,86,68],[4,43,27],
|
||||
[4,43,19],[4,43,15],[2,98,78],[4,49,31],[2,32,14,4,33,15],[4,39,13,1,40,14],[2,121,97],[2,60,38,2,61,39],[4,40,18,2,41,19],[4,40,14,2,41,15],[2,146,116],[3,58,36,2,59,37],[4,36,16,4,37,17],[4,36,12,4,37,13],[2,86,68,2,87,69],[4,69,43,1,70,44],[6,43,19,2,44,20],[6,43,15,2,44,16],[4,101,81],[1,80,50,4,81,51],[4,50,22,4,51,23],[3,36,12,8,37,13],[2,116,92,2,117,93],[6,58,36,2,59,37],[4,46,20,6,47,21],[7,42,14,4,43,15],[4,133,107],[8,59,37,1,60,38],[8,44,20,4,45,21],[12,33,11,4,34,12],[3,145,115,1,146,
|
||||
116],[4,64,40,5,65,41],[11,36,16,5,37,17],[11,36,12,5,37,13],[5,109,87,1,110,88],[5,65,41,5,66,42],[5,54,24,7,55,25],[11,36,12],[5,122,98,1,123,99],[7,73,45,3,74,46],[15,43,19,2,44,20],[3,45,15,13,46,16],[1,135,107,5,136,108],[10,74,46,1,75,47],[1,50,22,15,51,23],[2,42,14,17,43,15],[5,150,120,1,151,121],[9,69,43,4,70,44],[17,50,22,1,51,23],[2,42,14,19,43,15],[3,141,113,4,142,114],[3,70,44,11,71,45],[17,47,21,4,48,22],[9,39,13,16,40,14],[3,135,107,5,136,108],[3,67,41,13,68,42],[15,54,24,5,55,25],[15,
|
||||
43,15,10,44,16],[4,144,116,4,145,117],[17,68,42],[17,50,22,6,51,23],[19,46,16,6,47,17],[2,139,111,7,140,112],[17,74,46],[7,54,24,16,55,25],[34,37,13],[4,151,121,5,152,122],[4,75,47,14,76,48],[11,54,24,14,55,25],[16,45,15,14,46,16],[6,147,117,4,148,118],[6,73,45,14,74,46],[11,54,24,16,55,25],[30,46,16,2,47,17],[8,132,106,4,133,107],[8,75,47,13,76,48],[7,54,24,22,55,25],[22,45,15,13,46,16],[10,142,114,2,143,115],[19,74,46,4,75,47],[28,50,22,6,51,23],[33,46,16,4,47,17],[8,152,122,4,153,123],[22,73,45,
|
||||
3,74,46],[8,53,23,26,54,24],[12,45,15,28,46,16],[3,147,117,10,148,118],[3,73,45,23,74,46],[4,54,24,31,55,25],[11,45,15,31,46,16],[7,146,116,7,147,117],[21,73,45,7,74,46],[1,53,23,37,54,24],[19,45,15,26,46,16],[5,145,115,10,146,116],[19,75,47,10,76,48],[15,54,24,25,55,25],[23,45,15,25,46,16],[13,145,115,3,146,116],[2,74,46,29,75,47],[42,54,24,1,55,25],[23,45,15,28,46,16],[17,145,115],[10,74,46,23,75,47],[10,54,24,35,55,25],[19,45,15,35,46,16],[17,145,115,1,146,116],[14,74,46,21,75,47],[29,54,24,19,
|
||||
55,25],[11,45,15,46,46,16],[13,145,115,6,146,116],[14,74,46,23,75,47],[44,54,24,7,55,25],[59,46,16,1,47,17],[12,151,121,7,152,122],[12,75,47,26,76,48],[39,54,24,14,55,25],[22,45,15,41,46,16],[6,151,121,14,152,122],[6,75,47,34,76,48],[46,54,24,10,55,25],[2,45,15,64,46,16],[17,152,122,4,153,123],[29,74,46,14,75,47],[49,54,24,10,55,25],[24,45,15,46,46,16],[4,152,122,18,153,123],[13,74,46,32,75,47],[48,54,24,14,55,25],[42,45,15,32,46,16],[20,147,117,4,148,118],[40,75,47,7,76,48],[43,54,24,22,55,25],[10,
|
||||
45,15,67,46,16],[19,148,118,6,149,119],[18,75,47,31,76,48],[34,54,24,34,55,25],[20,45,15,61,46,16]];p.getRSBlocks=function(a,c){var d=p.getRsBlockTable(a,c);if(void 0==d)throw Error("bad rs block @ typeNumber:"+a+"/errorCorrectLevel:"+c);for(var b=d.length/3,e=[],f=0;f<b;f++)for(var h=d[3*f+0],g=d[3*f+1],j=d[3*f+2],l=0;l<h;l++)e.push(new p(g,j));return e};p.getRsBlockTable=function(a,c){switch(c){case 1:return p.RS_BLOCK_TABLE[4*(a-1)+0];case 0:return p.RS_BLOCK_TABLE[4*(a-1)+1];case 3:return p.RS_BLOCK_TABLE[4*
|
||||
(a-1)+2];case 2:return p.RS_BLOCK_TABLE[4*(a-1)+3]}};t.prototype={get:function(a){return 1==(this.buffer[Math.floor(a/8)]>>>7-a%8&1)},put:function(a,c){for(var d=0;d<c;d++)this.putBit(1==(a>>>c-d-1&1))},getLengthInBits:function(){return this.length},putBit:function(a){var c=Math.floor(this.length/8);this.buffer.length<=c&&this.buffer.push(0);a&&(this.buffer[c]|=128>>>this.length%8);this.length++}};"string"===typeof h&&(h={text:h});h=r.extend({},{render:"canvas",width:256,height:256,typeNumber:-1,
|
||||
correctLevel:2,background:"#ffffff",foreground:"#000000"},h);return this.each(function(){var a;if("canvas"==h.render){a=new o(h.typeNumber,h.correctLevel);a.addData(h.text);a.make();var c=document.createElement("canvas");c.width=h.width;c.height=h.height;for(var d=c.getContext("2d"),b=h.width/a.getModuleCount(),e=h.height/a.getModuleCount(),f=0;f<a.getModuleCount();f++)for(var i=0;i<a.getModuleCount();i++){d.fillStyle=a.isDark(f,i)?h.foreground:h.background;var g=Math.ceil((i+1)*b)-Math.floor(i*b),
|
||||
j=Math.ceil((f+1)*b)-Math.floor(f*b);d.fillRect(Math.round(i*b),Math.round(f*e),g,j)}}else{a=new o(h.typeNumber,h.correctLevel);a.addData(h.text);a.make();c=r("<table></table>").css("width",h.width+"px").css("height",h.height+"px").css("border","0px").css("border-collapse","collapse").css("background-color",h.background);d=h.width/a.getModuleCount();b=h.height/a.getModuleCount();for(e=0;e<a.getModuleCount();e++){f=r("<tr></tr>").css("height",b+"px").appendTo(c);for(i=0;i<a.getModuleCount();i++)r("<td></td>").css("width",
|
||||
d+"px").css("background-color",a.isDark(e,i)?h.foreground:h.background).appendTo(f)}}a=c;jQuery(a).appendTo(this)})}})(jQuery);
|
@@ -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;
|
||||
@@ -256,6 +256,10 @@ function getPlatformImagePath(platformName) {
|
||||
return 'images/platforms/wp.png';
|
||||
} else if (platformName.indexOf("Plex Media Player") > -1) {
|
||||
return 'images/platforms/pmp.png';
|
||||
} else if (platformName.indexOf("PlexTogether") > -1) {
|
||||
return 'images/platforms/plextogether.png';
|
||||
} else if (platformName.indexOf("Linux") > -1) {
|
||||
return 'images/platforms/linux.png';
|
||||
} else {
|
||||
return 'images/platforms/default.png';
|
||||
}
|
||||
@@ -448,4 +452,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) + ' ' + units[u];
|
||||
}
|
||||
|
@@ -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> Fetching 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>' +
|
||||
|
@@ -28,7 +28,7 @@
|
||||
<option disabled>────────────</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 {
|
||||
|
@@ -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;
|
||||
});
|
||||
|
||||
|
@@ -117,6 +117,12 @@
|
||||
</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="checkbox">
|
||||
<label>
|
||||
<input type="checkbox" id="week_start_monday" name="week_start_monday" value="1" ${config['week_start_monday']}> Week Starting on Monday
|
||||
</label>
|
||||
<p class="help-block">Change the "<em>Play by day of week</em>" graph to start on Monday. Default is start on Sunday.</p>
|
||||
</div>
|
||||
<div class="checkbox">
|
||||
<label>
|
||||
<input type="checkbox" id="group_history_tables" name="group_history_tables" value="1" ${config['group_history_tables']}> Group Table and Watch Statistics History
|
||||
@@ -129,6 +135,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 +159,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 +547,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" readonly>
|
||||
<span class="input-group-btn">
|
||||
<button class="btn btn-form" type="button" id="generate_api">Generate</button>
|
||||
</span>
|
||||
@@ -736,6 +765,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 history logging by flushing out all of the temporary sessions in the database.<br />
|
||||
Warning: This will reset all currently active sessions. For emergency 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 +930,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 +1297,7 @@
|
||||
<table class="notification-params time-options">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>
|
||||
<th colspan="3">
|
||||
Year
|
||||
</th>
|
||||
</tr>
|
||||
@@ -1285,7 +1318,7 @@
|
||||
<table class="notification-params time-options">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>
|
||||
<th colspan="3">
|
||||
Month
|
||||
</th>
|
||||
</tr>
|
||||
@@ -1316,7 +1349,7 @@
|
||||
<table class="notification-params time-options">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>
|
||||
<th colspan="3">
|
||||
Day of the Year
|
||||
</th>
|
||||
</tr>
|
||||
@@ -1337,7 +1370,7 @@
|
||||
<table class="notification-params time-options">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>
|
||||
<th colspan="3">
|
||||
Day of the Month
|
||||
</th>
|
||||
</tr>
|
||||
@@ -1363,7 +1396,7 @@
|
||||
<table class="notification-params time-options">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>
|
||||
<th colspan="3">
|
||||
Day of the Week
|
||||
</th>
|
||||
</tr>
|
||||
@@ -1389,7 +1422,7 @@
|
||||
<table class="notification-params time-options">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>
|
||||
<th colspan="3">
|
||||
Hour
|
||||
</th>
|
||||
</tr>
|
||||
@@ -1420,7 +1453,7 @@
|
||||
<table class="notification-params time-options">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>
|
||||
<th colspan="3">
|
||||
Minute
|
||||
</th>
|
||||
</tr>
|
||||
@@ -1441,7 +1474,7 @@
|
||||
<table class="notification-params time-options">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>
|
||||
<th colspan="3">
|
||||
Second
|
||||
</th>
|
||||
</tr>
|
||||
@@ -1462,7 +1495,7 @@
|
||||
<table class="notification-params time-options">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>
|
||||
<th colspan="3">
|
||||
AM / PM
|
||||
</th>
|
||||
</tr>
|
||||
@@ -1483,7 +1516,7 @@
|
||||
<table class="notification-params time-options">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>
|
||||
<th colspan="3">
|
||||
Timezone
|
||||
</th>
|
||||
</tr>
|
||||
@@ -1504,7 +1537,7 @@
|
||||
<table class="notification-params time-options">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>
|
||||
<th colspan="3">
|
||||
Timestamp
|
||||
</th>
|
||||
</tr>
|
||||
@@ -1533,11 +1566,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 +1579,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 +1607,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 +1617,7 @@
|
||||
<table class="notification-params">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>
|
||||
<th colspan="2">
|
||||
Global
|
||||
</th>
|
||||
</tr>
|
||||
@@ -1619,7 +1652,7 @@
|
||||
<table class="notification-params">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>
|
||||
<th colspan="2">
|
||||
Stream Details
|
||||
</th>
|
||||
</tr>
|
||||
@@ -1778,7 +1811,7 @@
|
||||
<table class="notification-params">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>
|
||||
<th colspan="2">
|
||||
Metadata Details
|
||||
</th>
|
||||
</tr>
|
||||
@@ -1915,12 +1948,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 +2005,7 @@
|
||||
<table class="notification-params">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>
|
||||
<th colspan="2">
|
||||
Plex Update Available
|
||||
</th>
|
||||
</tr>
|
||||
@@ -2039,27 +2072,27 @@
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div>
|
||||
<div class="wellheader">
|
||||
<h4>Movie Tag <strong><movie></movie></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"><movie></movie></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} <movie>({year})</movie></pre>
|
||||
</div>
|
||||
<div class="wellheader">
|
||||
<h4>TV Tag <strong><tv></tv></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"><tv></tv></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} <tv>(S{season_num}E{episode_num})</tv></pre>
|
||||
</div>
|
||||
<div class="wellheader">
|
||||
<h4>Music Tag <strong><music></music></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"><music></music></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} <music>(Track {track_num})</music></pre>
|
||||
</div>
|
||||
@@ -2101,26 +2134,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 +2154,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> ')
|
||||
$('#best-support-link span').tooltip({ container: 'body' });
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -2205,7 +2223,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 +2306,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 +2407,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();
|
||||
}
|
||||
|
@@ -47,7 +47,7 @@
|
||||
|
||||
// Redirect to home page after countdown.
|
||||
function reloadPage() {
|
||||
window.location.href = "index";
|
||||
window.location.href = "${new_http_root}index";
|
||||
}
|
||||
</script>
|
||||
</%def>
|
||||
|
@@ -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);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@@ -1,7 +1,7 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# PROVIDE: plexpy
|
||||
# REQUIRE: sabnzbd
|
||||
# REQUIRE: plexpy
|
||||
# KEYWORD: shutdown
|
||||
#
|
||||
# Add the following lines to /etc/rc.conf.local or /etc/rc.conf
|
||||
@@ -10,7 +10,7 @@
|
||||
# plexpy_enable (bool): Set to NO by default.
|
||||
# Set it to YES to enable it.
|
||||
# plexpy_user: The user account PlexPy daemon runs as what
|
||||
# you want it to be. It uses '_sabnzbd' user by
|
||||
# you want it to be. It uses 'plexpy' user by
|
||||
# default. Do not sets it as empty or it will run
|
||||
# as root.
|
||||
# plexpy_dir: Directory where PlexPy lives.
|
||||
@@ -28,7 +28,7 @@ rcvar=${name}_enable
|
||||
load_rc_config ${name}
|
||||
|
||||
: ${plexpy_enable:="NO"}
|
||||
: ${plexpy_user:="_sabnzbd"}
|
||||
: ${plexpy_user:="plexpy"}
|
||||
: ${plexpy_dir:="/usr/local/plexpy"}
|
||||
: ${plexpy_chdir:="${plexpy_dir}"}
|
||||
: ${plexpy_pid:="${plexpy_dir}/plexpy.pid"}
|
||||
|
@@ -1,66 +0,0 @@
|
||||
# PlexPy - Stats for Plex Media Server usage
|
||||
#
|
||||
# Service Unit file for systemd system manager
|
||||
#
|
||||
# INSTALLATION NOTES
|
||||
#
|
||||
# 1. Rename this file as you want, ensuring that it ends in .service
|
||||
# e.g. 'plexpy.service'
|
||||
#
|
||||
# 2. Adjust configuration settings as required. More details in the
|
||||
# "CONFIGURATION NOTES" section shown below.
|
||||
#
|
||||
# 3. Copy this file into your systemd service unit directory, which is
|
||||
# often '/lib/systemd/system'.
|
||||
#
|
||||
# 4. Create any files/directories that you specified back in step #2.
|
||||
# e.g. '/etc/plexpy/plexpy.ini'
|
||||
# '/home/sabnzbd/.plexpy'
|
||||
#
|
||||
# 5. Enable boot-time autostart with the following commands:
|
||||
# systemctl daemon-reload
|
||||
# systemctl enable plexpy.service
|
||||
#
|
||||
# 6. Start now with the following command:
|
||||
# systemctl start plexpy.service
|
||||
#
|
||||
# 7. If troubleshooting startup-errors, start by checking permissions
|
||||
# and ownership on the files/directories that you created in step #4.
|
||||
#
|
||||
#
|
||||
# CONFIGURATION NOTES
|
||||
#
|
||||
# - The example settings in this file assume that:
|
||||
# 1. You will run PlexPy as user/group: sabnzbd.sabnzbd
|
||||
# 2. You will either have PlexPy installed as a subdirectory
|
||||
# under '~sabnzbd', or that you will have a symlink under
|
||||
# '~/sabnzbd' pointing to your PlexPy install dir.
|
||||
# 3. Your PlexPy data directory and configuration file will be
|
||||
# in separate locations from your PlexPy install dir, to
|
||||
# simplify updates.
|
||||
#
|
||||
# - Option names (e.g. ExecStart=, Type=) appear to be case-sensitive)
|
||||
#
|
||||
# - Adjust ExecStart= to point to:
|
||||
# 1. Your PlexPy executable,
|
||||
# 2. Your config file (recommended is to put it somewhere in /etc)
|
||||
# 3. Your datadir (recommended is to NOT put it in your PlexPy exec dir)
|
||||
#
|
||||
# - Adjust User= and Group= to the user/group you want PlexPy to run as.
|
||||
#
|
||||
# - WantedBy= specifies which target (i.e. runlevel) to start PlexPy for.
|
||||
# multi-user.target equates to runlevel 3 (multi-user text mode)
|
||||
# graphical.target equates to runlevel 5 (multi-user X11 graphical mode)
|
||||
|
||||
[Unit]
|
||||
Description=PlexPy - Stats for Plex Media Server usage
|
||||
|
||||
[Service]
|
||||
ExecStart=/home/sabnzbd/plexpy/PlexPy.py --daemon --config /etc/plexpy/plexpy.ini --datadir /home/sabnzbd/.plexpy --nolaunch --quiet
|
||||
GuessMainPID=no
|
||||
Type=forking
|
||||
User=sabnzbd
|
||||
Group=sabnzbd
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
@@ -1,7 +1,7 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# PROVIDE: plexpy
|
||||
# REQUIRE: DAEMON sabnzbd
|
||||
# REQUIRE: DAEMON plexpy
|
||||
# KEYWORD: shutdown
|
||||
#
|
||||
# Add the following lines to /etc/rc.conf.local or /etc/rc.conf
|
||||
@@ -10,7 +10,7 @@
|
||||
# plexpy_enable (bool): Set to NO by default.
|
||||
# Set it to YES to enable it.
|
||||
# plexpy_user: The user account PlexPy daemon runs as what
|
||||
# you want it to be. It uses '_sabnzbd' user by
|
||||
# you want it to be. It uses 'plexpy' user by
|
||||
# default. Do not sets it as empty or it will run
|
||||
# as root.
|
||||
# plexpy_dir: Directory where PlexPy lives.
|
||||
@@ -29,7 +29,7 @@ rcvar=${name}_enable
|
||||
load_rc_config ${name}
|
||||
|
||||
: ${plexpy_enable:="NO"}
|
||||
: ${plexpy_user:="_sabnzbd"}
|
||||
: ${plexpy_user:="plexpy"}
|
||||
: ${plexpy_dir:="/usr/local/share/plexpy"}
|
||||
: ${plexpy_chdir:="${plexpy_dir}"}
|
||||
: ${plexpy_pid:="${plexpy_dir}/plexpy.pid"}
|
||||
@@ -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"
|
||||
|
@@ -1,7 +1,7 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# PROVIDE: plexpy
|
||||
# REQUIRE: DAEMON sabnzbd
|
||||
# REQUIRE: DAEMON plexpy
|
||||
# KEYWORD: shutdown
|
||||
#
|
||||
# Add the following lines to /etc/rc.conf.local or /etc/rc.conf
|
||||
@@ -10,7 +10,7 @@
|
||||
# plexpy_enable (bool): Set to NO by default.
|
||||
# Set it to YES to enable it.
|
||||
# plexpy_user: The user account PlexPy daemon runs as what
|
||||
# you want it to be. It uses '_sabnzbd' user by
|
||||
# you want it to be. It uses 'plexpy' user by
|
||||
# default. Do not sets it as empty or it will run
|
||||
# as root.
|
||||
# plexpy_dir: Directory where PlexPy lives.
|
||||
@@ -29,7 +29,7 @@ rcvar=${name}_enable
|
||||
load_rc_config ${name}
|
||||
|
||||
: ${plexpy_enable:="NO"}
|
||||
: ${plexpy_user:="_sabnzbd"}
|
||||
: ${plexpy_user:="plexpy"}
|
||||
: ${plexpy_dir:="/usr/local/share/plexpy"}
|
||||
: ${plexpy_chdir:="${plexpy_dir}"}
|
||||
: ${plexpy_pid:="${plexpy_dir}/plexpy.pid"}
|
||||
@@ -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
|
||||
|
@@ -1,67 +0,0 @@
|
||||
# PlexPy - Stats for Plex Media Server usage
|
||||
#
|
||||
# Service Unit file for systemd system manager
|
||||
#
|
||||
# INSTALLATION NOTES
|
||||
#
|
||||
# 1. Rename this file as you want, ensuring that it ends in .service
|
||||
# e.g. 'plexpy.service'
|
||||
#
|
||||
# 2. Adjust configuration settings as required. More details in the
|
||||
# "CONFIGURATION NOTES" section shown below.
|
||||
#
|
||||
# 3. Copy this file into your systemd service unit directory, which is
|
||||
# often '/lib/systemd/system'.
|
||||
#
|
||||
# 4. Create any files/directories that you specified back in step #2.
|
||||
# e.g. '/opt/plexpy.ini'
|
||||
# '/opt/plexpy'
|
||||
#
|
||||
# 5. Enable boot-time autostart with the following commands:
|
||||
# systemctl daemon-reload
|
||||
# systemctl enable plexpy.service
|
||||
#
|
||||
# 6. Start now with the following command:
|
||||
# systemctl start plexpy.service
|
||||
#
|
||||
# 7. If troubleshooting startup-errors, start by checking permissions
|
||||
# and ownership on the files/directories that you created in step #4.
|
||||
#
|
||||
#
|
||||
# CONFIGURATION NOTES
|
||||
#
|
||||
# - The example settings in this file assume that:
|
||||
# 1. You will run PlexPy as user/group: plex.users
|
||||
# 2. You will either have PlexPy installed as a subdirectory
|
||||
# under '/opt', or that you will have a symlink under
|
||||
# '/opt' pointing to your PlexPy install dir.
|
||||
# 3. Your PlexPy data directory and configuration file can be
|
||||
# in separate locations from your PlexPy install dir, to
|
||||
# simplify updates. However, in the example below they are in the
|
||||
# PlexPy install dir.
|
||||
#
|
||||
# - Option names (e.g. ExecStart=, Type=) appear to be case-sensitive)
|
||||
#
|
||||
# - Adjust ExecStart= to point to:
|
||||
# 1. Your PlexPy executable,
|
||||
# 2. Your config file (recommended is to put it somewhere in /etc)
|
||||
# 3. Your datadir (recommended is to NOT put it in your PlexPy exec dir)
|
||||
#
|
||||
# - Adjust User= and Group= to the user/group you want PlexPy to run as.
|
||||
#
|
||||
# - WantedBy= specifies which target (i.e. runlevel) to start PlexPy for.
|
||||
# multi-user.target equates to runlevel 3 (multi-user text mode)
|
||||
# graphical.target equates to runlevel 5 (multi-user X11 graphical mode)
|
||||
|
||||
[Unit]
|
||||
Description=PlexPy - Stats for Plex Media Server usage
|
||||
|
||||
[Service]
|
||||
ExecStart=/opt/plexpy/PlexPy.py --daemon --config /opt/plexpy/config.ini --datadir /opt/plexpy --nolaunch --quiet
|
||||
GuessMainPID=no
|
||||
Type=forking
|
||||
User=plex
|
||||
Group=users
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
@@ -19,7 +19,7 @@
|
||||
</dependency>
|
||||
|
||||
<method_context>
|
||||
<method_credential user="sabnzbd" group="sabnzbd"/>
|
||||
<method_credential user="plexpy" group="nogroup"/>
|
||||
</method_context>
|
||||
|
||||
<exec_method type="method" name="start" exec="python /opt/plexpy/PlexPy.py --daemon --quiet --nolaunch" timeout_seconds="60"/>
|
||||
|
@@ -13,32 +13,20 @@
|
||||
# 3. Copy this file into your systemd service unit directory, which is
|
||||
# often '/lib/systemd/system'.
|
||||
#
|
||||
# 4. Create any files/directories that you specified back in step #2.
|
||||
# e.g. '/etc/plexpy/plexpy.ini'
|
||||
# '/home/sabnzbd/.plexpy'
|
||||
#
|
||||
# 5. Enable boot-time autostart with the following commands:
|
||||
# 4. Enable boot-time autostart with the following commands:
|
||||
# systemctl daemon-reload
|
||||
# systemctl enable plexpy.service
|
||||
#
|
||||
# 6. Start now with the following command:
|
||||
# 5. Start now with the following command:
|
||||
# systemctl start plexpy.service
|
||||
#
|
||||
# 7. If troubleshooting startup-errors, start by checking permissions
|
||||
# and ownership on the files/directories that you created in step #4.
|
||||
#
|
||||
#
|
||||
# CONFIGURATION NOTES
|
||||
#
|
||||
# - The example settings in this file assume that:
|
||||
# 1. You will run PlexPy as user/group: sabnzbd.sabnzbd
|
||||
# 2. You will either have PlexPy installed as a subdirectory
|
||||
# under '~sabnzbd', or that you will have a symlink under
|
||||
# '~/sabnzbd' pointing to your PlexPy install dir.
|
||||
# 3. Your PlexPy data directory and configuration file will be
|
||||
# in separate locations from your PlexPy install dir, to
|
||||
# simplify updates.
|
||||
#
|
||||
# - The example settings in this file assume that you will run PlexPy as user: plexpy
|
||||
# - To create this user and give it ownership of the plexpy directory:
|
||||
# sudo adduser --system --no-create-home plexpy
|
||||
# sudo chown plexpy:nogroup -R /opt/plexpy
|
||||
#
|
||||
# - Option names (e.g. ExecStart=, Type=) appear to be case-sensitive)
|
||||
#
|
||||
# - Adjust ExecStart= to point to:
|
||||
@@ -63,4 +51,4 @@ User=plexpy
|
||||
Group=nogroup
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
WantedBy=multi-user.target
|
@@ -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',
|
||||
|
@@ -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,
|
||||
|